xref: /freebsd/sbin/growfs/growfs.c (revision 7660b554bc59a07be0431c17e0e33815818baa69)
1 /*
2  * Copyright (c) 2000 Christoph Herrmann, Thomas-Henning von Kamptz
3  * Copyright (c) 1980, 1989, 1993 The Regents of the University of California.
4  * All rights reserved.
5  *
6  * This code is derived from software contributed to Berkeley by
7  * Christoph Herrmann and Thomas-Henning von Kamptz, Munich and Frankfurt.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. All advertising materials mentioning features or use of this software
18  *    must display the following acknowledgment:
19  *      This product includes software developed by the University of
20  *      California, Berkeley and its contributors, as well as Christoph
21  *      Herrmann and Thomas-Henning von Kamptz.
22  * 4. Neither the name of the University nor the names of its contributors
23  *    may be used to endorse or promote products derived from this software
24  *    without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36  * SUCH DAMAGE.
37  *
38  * $TSHeader: src/sbin/growfs/growfs.c,v 1.5 2000/12/12 19:31:00 tomsoft Exp $
39  *
40  */
41 
42 #ifndef lint
43 static const char copyright[] =
44 "@(#) Copyright (c) 2000 Christoph Herrmann, Thomas-Henning von Kamptz\n\
45 Copyright (c) 1980, 1989, 1993 The Regents of the University of California.\n\
46 All rights reserved.\n";
47 #endif /* not lint */
48 
49 #ifndef lint
50 static const char rcsid[] =
51   "$FreeBSD$";
52 #endif /* not lint */
53 
54 /* ********************************************************** INCLUDES ***** */
55 #include <sys/param.h>
56 #include <sys/disklabel.h>
57 #include <sys/ioctl.h>
58 #include <sys/stat.h>
59 #include <sys/disk.h>
60 
61 #include <stdio.h>
62 #include <paths.h>
63 #include <ctype.h>
64 #include <err.h>
65 #include <fcntl.h>
66 #include <limits.h>
67 #include <stdlib.h>
68 #include <string.h>
69 #include <unistd.h>
70 #include <ufs/ufs/dinode.h>
71 #include <ufs/ffs/fs.h>
72 
73 #include "debug.h"
74 
75 /* *************************************************** GLOBALS & TYPES ***** */
76 #ifdef FS_DEBUG
77 int	_dbg_lvl_ = (DL_INFO);	/* DL_TRC */
78 #endif /* FS_DEBUG */
79 
80 static union {
81 	struct fs	fs;
82 	char	pad[SBLOCKSIZE];
83 } fsun1, fsun2;
84 #define	sblock	fsun1.fs	/* the new superblock */
85 #define	osblock	fsun2.fs	/* the old superblock */
86 
87 /*
88  * Possible superblock locations ordered from most to least likely.
89  */
90 static int sblock_try[] = SBLOCKSEARCH;
91 static ufs2_daddr_t sblockloc;
92 
93 static union {
94 	struct cg	cg;
95 	char	pad[MAXBSIZE];
96 } cgun1, cgun2;
97 #define	acg	cgun1.cg	/* a cylinder cgroup (new) */
98 #define	aocg	cgun2.cg	/* an old cylinder group */
99 
100 static char	ablk[MAXBSIZE];	/* a block */
101 
102 static struct csum	*fscs;	/* cylinder summary */
103 
104 union dinode {
105 	struct ufs1_dinode dp1;
106 	struct ufs2_dinode dp2;
107 };
108 #define	DIP(dp, field) \
109 	((sblock.fs_magic == FS_UFS1_MAGIC) ? \
110 	(dp)->dp1.field : (dp)->dp2.field)
111 static ufs2_daddr_t 	inoblk;			/* inode block address */
112 static char		inobuf[MAXBSIZE];	/* inode block */
113 static int		maxino;			/* last valid inode */
114 static int		unlabeled;     /* unlabeled partition, e.g. vinum volume etc. */
115 
116 /*
117  * An array of elements of type struct gfs_bpp describes all blocks to
118  * be relocated in order to free the space needed for the cylinder group
119  * summary for all cylinder groups located in the first cylinder group.
120  */
121 struct gfs_bpp {
122 	ufs2_daddr_t	old;		/* old block number */
123 	ufs2_daddr_t	new;		/* new block number */
124 #define GFS_FL_FIRST	1
125 #define GFS_FL_LAST	2
126 	unsigned int	flags;	/* special handling required */
127 	int	found;		/* how many references were updated */
128 };
129 
130 /* ******************************************************** PROTOTYPES ***** */
131 static void	growfs(int, int, unsigned int);
132 static void	rdfs(ufs2_daddr_t, size_t, void *, int);
133 static void	wtfs(ufs2_daddr_t, size_t, void *, int, unsigned int);
134 static ufs2_daddr_t alloc(void);
135 static int	charsperline(void);
136 static void	usage(void);
137 static int	isblock(struct fs *, unsigned char *, int);
138 static void	clrblock(struct fs *, unsigned char *, int);
139 static void	setblock(struct fs *, unsigned char *, int);
140 static void	initcg(int, time_t, int, unsigned int);
141 static void	updjcg(int, time_t, int, int, unsigned int);
142 static void	updcsloc(time_t, int, int, unsigned int);
143 static struct disklabel	*get_disklabel(int);
144 static void	return_disklabel(int, struct disklabel *, unsigned int);
145 static union dinode *ginode(ino_t, int, int);
146 static void	frag_adjust(ufs2_daddr_t, int);
147 static int	cond_bl_upd(ufs2_daddr_t *, struct gfs_bpp *, int, int,
148 		    unsigned int);
149 static void	updclst(int);
150 static void	updrefs(int, ino_t, struct gfs_bpp *, int, int, unsigned int);
151 static void	indirchk(ufs_lbn_t, ufs_lbn_t, ufs2_daddr_t, ufs_lbn_t,
152 		    struct gfs_bpp *, int, int, unsigned int);
153 static void	get_dev_size(int, int *);
154 
155 /* ************************************************************ growfs ***** */
156 /*
157  * Here we actually start growing the file system. We basically read the
158  * cylinder summary from the first cylinder group as we want to update
159  * this on the fly during our various operations. First we handle the
160  * changes in the former last cylinder group. Afterwards we create all new
161  * cylinder groups.  Now we handle the cylinder group containing the
162  * cylinder summary which might result in a relocation of the whole
163  * structure.  In the end we write back the updated cylinder summary, the
164  * new superblock, and slightly patched versions of the super block
165  * copies.
166  */
167 static void
168 growfs(int fsi, int fso, unsigned int Nflag)
169 {
170 	DBG_FUNC("growfs")
171 	int	i;
172 	int	cylno, j;
173 	time_t	utime;
174 	int	width;
175 	char	tmpbuf[100];
176 #ifdef FSIRAND
177 	static int	randinit=0;
178 
179 	DBG_ENTER;
180 
181 	if (!randinit) {
182 		randinit = 1;
183 		srandomdev();
184 	}
185 #else /* not FSIRAND */
186 
187 	DBG_ENTER;
188 
189 #endif /* FSIRAND */
190 	time(&utime);
191 
192 	/*
193 	 * Get the cylinder summary into the memory.
194 	 */
195 	fscs = (struct csum *)calloc((size_t)1, (size_t)sblock.fs_cssize);
196 	if(fscs == NULL) {
197 		errx(1, "calloc failed");
198 	}
199 	for (i = 0; i < osblock.fs_cssize; i += osblock.fs_bsize) {
200 		rdfs(fsbtodb(&osblock, osblock.fs_csaddr +
201 		    numfrags(&osblock, i)), (size_t)MIN(osblock.fs_cssize - i,
202 		    osblock.fs_bsize), (void *)(((char *)fscs)+i), fsi);
203 	}
204 
205 #ifdef FS_DEBUG
206 {
207 	struct csum	*dbg_csp;
208 	int	dbg_csc;
209 	char	dbg_line[80];
210 
211 	dbg_csp=fscs;
212 	for(dbg_csc=0; dbg_csc<osblock.fs_ncg; dbg_csc++) {
213 		snprintf(dbg_line, sizeof(dbg_line),
214 		    "%d. old csum in old location", dbg_csc);
215 		DBG_DUMP_CSUM(&osblock,
216 		    dbg_line,
217 		    dbg_csp++);
218 	}
219 }
220 #endif /* FS_DEBUG */
221 	DBG_PRINT0("fscs read\n");
222 
223 	/*
224 	 * Do all needed changes in the former last cylinder group.
225 	 */
226 	updjcg(osblock.fs_ncg-1, utime, fsi, fso, Nflag);
227 
228 	/*
229 	 * Dump out summary information about file system.
230 	 */
231 #	define B2MBFACTOR (1 / (1024.0 * 1024.0))
232 	printf("growfs: %.1fMB (%qd sectors) block size %d, fragment size %d\n",
233 	    (float)sblock.fs_size * sblock.fs_fsize * B2MBFACTOR,
234 	    fsbtodb(&sblock, sblock.fs_size), sblock.fs_bsize, sblock.fs_fsize);
235 	printf("\tusing %d cylinder groups of %.2fMB, %d blks, %d inodes.\n",
236 	    sblock.fs_ncg, (float)sblock.fs_fpg * sblock.fs_fsize * B2MBFACTOR,
237 	    sblock.fs_fpg / sblock.fs_frag, sblock.fs_ipg);
238 	if (sblock.fs_flags & FS_DOSOFTDEP)
239 		printf("\twith soft updates\n");
240 #	undef B2MBFACTOR
241 
242 	/*
243 	 * Now build the cylinders group blocks and
244 	 * then print out indices of cylinder groups.
245 	 */
246 	printf("super-block backups (for fsck -b #) at:\n");
247 	i = 0;
248 	width = charsperline();
249 
250 	/*
251 	 * Iterate for only the new cylinder groups.
252 	 */
253 	for (cylno = osblock.fs_ncg; cylno < sblock.fs_ncg; cylno++) {
254 		initcg(cylno, utime, fso, Nflag);
255 		j = sprintf(tmpbuf, " %d%s",
256 		    (int)fsbtodb(&sblock, cgsblock(&sblock, cylno)),
257 		    cylno < (sblock.fs_ncg-1) ? "," : "" );
258 		if (i + j >= width) {
259 			printf("\n");
260 			i = 0;
261 		}
262 		i += j;
263 		printf("%s", tmpbuf);
264 		fflush(stdout);
265 	}
266 	printf("\n");
267 
268 	/*
269 	 * Do all needed changes in the first cylinder group.
270 	 * allocate blocks in new location
271 	 */
272 	updcsloc(utime, fsi, fso, Nflag);
273 
274 	/*
275 	 * Now write the cylinder summary back to disk.
276 	 */
277 	for (i = 0; i < sblock.fs_cssize; i += sblock.fs_bsize) {
278 		wtfs(fsbtodb(&sblock, sblock.fs_csaddr + numfrags(&sblock, i)),
279 		    (size_t)MIN(sblock.fs_cssize - i, sblock.fs_bsize),
280 		    (void *)(((char *)fscs) + i), fso, Nflag);
281 	}
282 	DBG_PRINT0("fscs written\n");
283 
284 #ifdef FS_DEBUG
285 {
286 	struct csum	*dbg_csp;
287 	int	dbg_csc;
288 	char	dbg_line[80];
289 
290 	dbg_csp=fscs;
291 	for(dbg_csc=0; dbg_csc<sblock.fs_ncg; dbg_csc++) {
292 		snprintf(dbg_line, sizeof(dbg_line),
293 		    "%d. new csum in new location", dbg_csc);
294 		DBG_DUMP_CSUM(&sblock,
295 		    dbg_line,
296 		    dbg_csp++);
297 	}
298 }
299 #endif /* FS_DEBUG */
300 
301 	/*
302 	 * Now write the new superblock back to disk.
303 	 */
304 	sblock.fs_time = utime;
305 	wtfs(sblockloc, (size_t)SBLOCKSIZE, (void *)&sblock, fso, Nflag);
306 	DBG_PRINT0("sblock written\n");
307 	DBG_DUMP_FS(&sblock,
308 	    "new initial sblock");
309 
310 	/*
311 	 * Clean up the dynamic fields in our superblock copies.
312 	 */
313 	sblock.fs_fmod = 0;
314 	sblock.fs_clean = 1;
315 	sblock.fs_ronly = 0;
316 	sblock.fs_cgrotor = 0;
317 	sblock.fs_state = 0;
318 	memset((void *)&sblock.fs_fsmnt, 0, sizeof(sblock.fs_fsmnt));
319 	sblock.fs_flags &= FS_DOSOFTDEP;
320 
321 	/*
322 	 * XXX
323 	 * The following fields are currently distributed from the superblock
324 	 * to the copies:
325 	 *     fs_minfree
326 	 *     fs_rotdelay
327 	 *     fs_maxcontig
328 	 *     fs_maxbpg
329 	 *     fs_minfree,
330 	 *     fs_optim
331 	 *     fs_flags regarding SOFTPDATES
332 	 *
333 	 * We probably should rather change the summary for the cylinder group
334 	 * statistics here to the value of what would be in there, if the file
335 	 * system were created initially with the new size. Therefor we still
336 	 * need to find an easy way of calculating that.
337 	 * Possibly we can try to read the first superblock copy and apply the
338 	 * "diffed" stats between the old and new superblock by still copying
339 	 * certain parameters onto that.
340 	 */
341 
342 	/*
343 	 * Write out the duplicate super blocks.
344 	 */
345 	for (cylno = 0; cylno < sblock.fs_ncg; cylno++) {
346 		wtfs(fsbtodb(&sblock, cgsblock(&sblock, cylno)),
347 		    (size_t)SBLOCKSIZE, (void *)&sblock, fso, Nflag);
348 	}
349 	DBG_PRINT0("sblock copies written\n");
350 	DBG_DUMP_FS(&sblock,
351 	    "new other sblocks");
352 
353 	DBG_LEAVE;
354 	return;
355 }
356 
357 /* ************************************************************ initcg ***** */
358 /*
359  * This creates a new cylinder group structure, for more details please see
360  * the source of newfs(8), as this function is taken over almost unchanged.
361  * As this is never called for the first cylinder group, the special
362  * provisions for that case are removed here.
363  */
364 static void
365 initcg(int cylno, time_t utime, int fso, unsigned int Nflag)
366 {
367 	DBG_FUNC("initcg")
368 	static caddr_t iobuf;
369 	long i, j, d, dlower, dupper, blkno, start;
370 	ufs2_daddr_t cbase, dmax;
371 	struct ufs1_dinode *dp1;
372 	struct ufs2_dinode *dp2;
373 	struct csum *cs;
374 
375 	if (iobuf == NULL && (iobuf = malloc(sblock.fs_bsize)) == NULL) {
376 		errx(37, "panic: cannot allocate I/O buffer");
377 	}
378 	/*
379 	 * Determine block bounds for cylinder group.
380 	 * Allow space for super block summary information in first
381 	 * cylinder group.
382 	 */
383 	cbase = cgbase(&sblock, cylno);
384 	dmax = cbase + sblock.fs_fpg;
385 	if (dmax > sblock.fs_size)
386 		dmax = sblock.fs_size;
387 	dlower = cgsblock(&sblock, cylno) - cbase;
388 	dupper = cgdmin(&sblock, cylno) - cbase;
389 	if (cylno == 0)	/* XXX fscs may be relocated */
390 		dupper += howmany(sblock.fs_cssize, sblock.fs_fsize);
391 	cs = &fscs[cylno];
392 	memset(&acg, 0, sblock.fs_cgsize);
393 	acg.cg_time = utime;
394 	acg.cg_magic = CG_MAGIC;
395 	acg.cg_cgx = cylno;
396 	acg.cg_niblk = sblock.fs_ipg;
397 	acg.cg_initediblk = sblock.fs_ipg;
398 	acg.cg_ndblk = dmax - cbase;
399 	if (sblock.fs_contigsumsize > 0)
400 		acg.cg_nclusterblks = acg.cg_ndblk / sblock.fs_frag;
401 	start = &acg.cg_space[0] - (u_char *)(&acg.cg_firstfield);
402 	if (sblock.fs_magic == FS_UFS2_MAGIC) {
403 		acg.cg_iusedoff = start;
404 	} else {
405 		acg.cg_old_ncyl = sblock.fs_old_cpg;
406 		acg.cg_old_time = acg.cg_time;
407 		acg.cg_time = 0;
408 		acg.cg_old_niblk = acg.cg_niblk;
409 		acg.cg_niblk = 0;
410 		acg.cg_initediblk = 0;
411 		acg.cg_old_btotoff = start;
412 		acg.cg_old_boff = acg.cg_old_btotoff +
413 		    sblock.fs_old_cpg * sizeof(int32_t);
414 		acg.cg_iusedoff = acg.cg_old_boff +
415 		    sblock.fs_old_cpg * sizeof(u_int16_t);
416 	}
417 	acg.cg_freeoff = acg.cg_iusedoff + howmany(sblock.fs_ipg, CHAR_BIT);
418 	acg.cg_nextfreeoff = acg.cg_freeoff + howmany(sblock.fs_fpg, CHAR_BIT);
419 	if (sblock.fs_contigsumsize > 0) {
420 		acg.cg_clustersumoff =
421 		    roundup(acg.cg_nextfreeoff, sizeof(u_int32_t));
422 		acg.cg_clustersumoff -= sizeof(u_int32_t);
423 		acg.cg_clusteroff = acg.cg_clustersumoff +
424 		    (sblock.fs_contigsumsize + 1) * sizeof(u_int32_t);
425 		acg.cg_nextfreeoff = acg.cg_clusteroff +
426 		    howmany(fragstoblks(&sblock, sblock.fs_fpg), CHAR_BIT);
427 	}
428 	if (acg.cg_nextfreeoff > sblock.fs_cgsize) {
429 		/*
430 		 * This should never happen as we would have had that panic
431 		 * already on file system creation
432 		 */
433 		errx(37, "panic: cylinder group too big");
434 	}
435 	acg.cg_cs.cs_nifree += sblock.fs_ipg;
436 	if (cylno == 0)
437 		for (i = 0; i < ROOTINO; i++) {
438 			setbit(cg_inosused(&acg), i);
439 			acg.cg_cs.cs_nifree--;
440 		}
441 	bzero(iobuf, sblock.fs_bsize);
442 	for (i = 0; i < sblock.fs_ipg / INOPF(&sblock); i += sblock.fs_frag) {
443 		dp1 = (struct ufs1_dinode *)iobuf;
444 		dp2 = (struct ufs2_dinode *)iobuf;
445 #ifdef FSIRAND
446 		for (j = 0; j < INOPB(&sblock); j++)
447 			if (sblock.fs_magic == FS_UFS1_MAGIC) {
448 				dp1->di_gen = random();
449 				dp1++;
450 			} else {
451 				dp2->di_gen = random();
452 				dp2++;
453 			}
454 #endif
455 		wtfs(fsbtodb(&sblock, cgimin(&sblock, cylno) + i),
456 		    sblock.fs_bsize, iobuf, fso, Nflag);
457 	}
458 	if (cylno > 0) {
459 		/*
460 		 * In cylno 0, beginning space is reserved
461 		 * for boot and super blocks.
462 		 */
463 		for (d = 0; d < dlower; d += sblock.fs_frag) {
464 			blkno = d / sblock.fs_frag;
465 			setblock(&sblock, cg_blksfree(&acg), blkno);
466 			if (sblock.fs_contigsumsize > 0)
467 				setbit(cg_clustersfree(&acg), blkno);
468 			acg.cg_cs.cs_nbfree++;
469 		}
470 		sblock.fs_dsize += dlower;
471 	}
472 	sblock.fs_dsize += acg.cg_ndblk - dupper;
473 	if ((i = dupper % sblock.fs_frag)) {
474 		acg.cg_frsum[sblock.fs_frag - i]++;
475 		for (d = dupper + sblock.fs_frag - i; dupper < d; dupper++) {
476 			setbit(cg_blksfree(&acg), dupper);
477 			acg.cg_cs.cs_nffree++;
478 		}
479 	}
480 	for (d = dupper; d + sblock.fs_frag <= acg.cg_ndblk;
481 	     d += sblock.fs_frag) {
482 		blkno = d / sblock.fs_frag;
483 		setblock(&sblock, cg_blksfree(&acg), blkno);
484 		if (sblock.fs_contigsumsize > 0)
485 			setbit(cg_clustersfree(&acg), blkno);
486 		acg.cg_cs.cs_nbfree++;
487 	}
488 	if (d < acg.cg_ndblk) {
489 		acg.cg_frsum[acg.cg_ndblk - d]++;
490 		for (; d < acg.cg_ndblk; d++) {
491 			setbit(cg_blksfree(&acg), d);
492 			acg.cg_cs.cs_nffree++;
493 		}
494 	}
495 	if (sblock.fs_contigsumsize > 0) {
496 		int32_t *sump = cg_clustersum(&acg);
497 		u_char *mapp = cg_clustersfree(&acg);
498 		int map = *mapp++;
499 		int bit = 1;
500 		int run = 0;
501 
502 		for (i = 0; i < acg.cg_nclusterblks; i++) {
503 			if ((map & bit) != 0)
504 				run++;
505 			else if (run != 0) {
506 				if (run > sblock.fs_contigsumsize)
507 					run = sblock.fs_contigsumsize;
508 				sump[run]++;
509 				run = 0;
510 			}
511 			if ((i & (CHAR_BIT - 1)) != CHAR_BIT - 1)
512 				bit <<= 1;
513 			else {
514 				map = *mapp++;
515 				bit = 1;
516 			}
517 		}
518 		if (run != 0) {
519 			if (run > sblock.fs_contigsumsize)
520 				run = sblock.fs_contigsumsize;
521 			sump[run]++;
522 		}
523 	}
524 	sblock.fs_cstotal.cs_ndir += acg.cg_cs.cs_ndir;
525 	sblock.fs_cstotal.cs_nffree += acg.cg_cs.cs_nffree;
526 	sblock.fs_cstotal.cs_nbfree += acg.cg_cs.cs_nbfree;
527 	sblock.fs_cstotal.cs_nifree += acg.cg_cs.cs_nifree;
528 	*cs = acg.cg_cs;
529 	wtfs(fsbtodb(&sblock, cgtod(&sblock, cylno)),
530 		sblock.fs_bsize, (char *)&acg, fso, Nflag);
531 	DBG_DUMP_CG(&sblock,
532 	    "new cg",
533 	    &acg);
534 
535 	DBG_LEAVE;
536 	return;
537 }
538 
539 /* ******************************************************* frag_adjust ***** */
540 /*
541  * Here we add or subtract (sign +1/-1) the available fragments in a given
542  * block to or from the fragment statistics. By subtracting before and adding
543  * after an operation on the free frag map we can easy update the fragment
544  * statistic, which seems to be otherwise a rather complex operation.
545  */
546 static void
547 frag_adjust(ufs2_daddr_t frag, int sign)
548 {
549 	DBG_FUNC("frag_adjust")
550 	int fragsize;
551 	int f;
552 
553 	DBG_ENTER;
554 
555 	fragsize=0;
556 	/*
557 	 * Here frag only needs to point to any fragment in the block we want
558 	 * to examine.
559 	 */
560 	for(f=rounddown(frag, sblock.fs_frag);
561 	    f<roundup(frag+1, sblock.fs_frag);
562 	    f++) {
563 		/*
564 		 * Count contiguous free fragments.
565 		 */
566 		if(isset(cg_blksfree(&acg), f)) {
567 			fragsize++;
568 		} else {
569 			if(fragsize && fragsize<sblock.fs_frag) {
570 				/*
571 				 * We found something in between.
572 				 */
573 				acg.cg_frsum[fragsize]+=sign;
574 				DBG_PRINT2("frag_adjust [%d]+=%d\n",
575 				    fragsize,
576 				    sign);
577 			}
578 			fragsize=0;
579 		}
580 	}
581 	if(fragsize && fragsize<sblock.fs_frag) {
582 		/*
583 		 * We found something.
584 		 */
585 		acg.cg_frsum[fragsize]+=sign;
586 		DBG_PRINT2("frag_adjust [%d]+=%d\n",
587 		    fragsize,
588 		    sign);
589 	}
590 	DBG_PRINT2("frag_adjust [[%d]]+=%d\n",
591 	    fragsize,
592 	    sign);
593 
594 	DBG_LEAVE;
595 	return;
596 }
597 
598 /* ******************************************************* cond_bl_upd ***** */
599 /*
600  * Here we conditionally update a pointer to a fragment. We check for all
601  * relocated blocks if any of its fragments is referenced by the current
602  * field, and update the pointer to the respective fragment in our new
603  * block.  If we find a reference we write back the block immediately,
604  * as there is no easy way for our general block reading engine to figure
605  * out if a write back operation is needed.
606  */
607 static int
608 cond_bl_upd(ufs2_daddr_t *block, struct gfs_bpp *field, int fsi, int fso,
609     unsigned int Nflag)
610 {
611 	DBG_FUNC("cond_bl_upd")
612 	struct gfs_bpp *f;
613 	ufs2_daddr_t src, dst;
614 	int fragnum;
615 	void *ibuf;
616 
617 	DBG_ENTER;
618 
619 	f = field;
620 	for (f = field; f->old != 0; f++) {
621 		src = *block;
622 		if (fragstoblks(&sblock, src) != f->old)
623 			continue;
624 		/*
625 		 * The fragment is part of the block, so update.
626 		 */
627 		dst = blkstofrags(&sblock, f->new);
628 		fragnum = fragnum(&sblock, src);
629 		*block = dst + fragnum;
630 		f->found++;
631 		DBG_PRINT3("scg (%d->%d)[%d] reference updated\n",
632 		    f->old,
633 		    f->new,
634 		    fragnum);
635 
636 		/*
637 		 * Copy the block back immediately.
638 		 *
639 		 * XXX	If src is is from an indirect block we have
640 		 *	to implement copy on write here in case of
641 		 *	active snapshots.
642 		 */
643 		ibuf = malloc(sblock.fs_bsize);
644 		if (!ibuf)
645 			errx(1, "malloc failed");
646 		src -= fragnum;
647 		rdfs(fsbtodb(&sblock, src), (size_t)sblock.fs_bsize, ibuf, fsi);
648 		wtfs(dst, (size_t)sblock.fs_bsize, ibuf, fso, Nflag);
649 		free(ibuf);
650 		/*
651 		 * The same block can't be found again in this loop.
652 		 */
653 		return (1);
654 	}
655 
656 	DBG_LEAVE;
657 	return (0);
658 }
659 
660 /* ************************************************************ updjcg ***** */
661 /*
662  * Here we do all needed work for the former last cylinder group. It has to be
663  * changed in any case, even if the file system ended exactly on the end of
664  * this group, as there is some slightly inconsistent handling of the number
665  * of cylinders in the cylinder group. We start again by reading the cylinder
666  * group from disk. If the last block was not fully available, we first handle
667  * the missing fragments, then we handle all new full blocks in that file
668  * system and finally we handle the new last fragmented block in the file
669  * system.  We again have to handle the fragment statistics rotational layout
670  * tables and cluster summary during all those operations.
671  */
672 static void
673 updjcg(int cylno, time_t utime, int fsi, int fso, unsigned int Nflag)
674 {
675 	DBG_FUNC("updjcg")
676 	ufs2_daddr_t	cbase, dmax, dupper;
677 	struct csum	*cs;
678 	int	i,k;
679 	int	j=0;
680 
681 	DBG_ENTER;
682 
683 	/*
684 	 * Read the former last (joining) cylinder group from disk, and make
685 	 * a copy.
686 	 */
687 	rdfs(fsbtodb(&osblock, cgtod(&osblock, cylno)),
688 	    (size_t)osblock.fs_cgsize, (void *)&aocg, fsi);
689 	DBG_PRINT0("jcg read\n");
690 	DBG_DUMP_CG(&sblock,
691 	    "old joining cg",
692 	    &aocg);
693 
694 	memcpy((void *)&cgun1, (void *)&cgun2, sizeof(cgun2));
695 
696 	/*
697 	 * If the cylinder group had already its new final size almost
698 	 * nothing is to be done ... except:
699 	 * For some reason the value of cg_ncyl in the last cylinder group has
700 	 * to be zero instead of fs_cpg. As this is now no longer the last
701 	 * cylinder group we have to change that value now to fs_cpg.
702 	 */
703 
704 	if(cgbase(&osblock, cylno+1) == osblock.fs_size) {
705 		if (sblock.fs_magic == FS_UFS1_MAGIC)
706 			acg.cg_old_ncyl=sblock.fs_old_cpg;
707 
708 		wtfs(fsbtodb(&sblock, cgtod(&sblock, cylno)),
709 		    (size_t)sblock.fs_cgsize, (void *)&acg, fso, Nflag);
710 		DBG_PRINT0("jcg written\n");
711 		DBG_DUMP_CG(&sblock,
712 		    "new joining cg",
713 		    &acg);
714 
715 		DBG_LEAVE;
716 		return;
717 	}
718 
719 	/*
720 	 * Set up some variables needed later.
721 	 */
722 	cbase = cgbase(&sblock, cylno);
723 	dmax = cbase + sblock.fs_fpg;
724 	if (dmax > sblock.fs_size)
725 		dmax = sblock.fs_size;
726 	dupper = cgdmin(&sblock, cylno) - cbase;
727 	if (cylno == 0) { /* XXX fscs may be relocated */
728 		dupper += howmany(sblock.fs_cssize, sblock.fs_fsize);
729 	}
730 
731 	/*
732 	 * Set pointer to the cylinder summary for our cylinder group.
733 	 */
734 	cs = fscs + cylno;
735 
736 	/*
737 	 * Touch the cylinder group, update all fields in the cylinder group as
738 	 * needed, update the free space in the superblock.
739 	 */
740 	acg.cg_time = utime;
741 	if (cylno == sblock.fs_ncg - 1) {
742 		/*
743 		 * This is still the last cylinder group.
744 		 */
745 		if (sblock.fs_magic == FS_UFS1_MAGIC)
746 			acg.cg_old_ncyl =
747 			    sblock.fs_old_ncyl % sblock.fs_old_cpg;
748 	} else {
749 		acg.cg_old_ncyl = sblock.fs_old_cpg;
750 	}
751 	DBG_PRINT2("jcg dbg: %d %u",
752 	    cylno,
753 	    sblock.fs_ncg);
754 	if (sblock.fs_magic == FS_UFS1_MAGIC)
755 		DBG_PRINT2("%d %u",
756 		    acg.cg_old_ncyl,
757 		    sblock.fs_old_cpg);
758 	DBG_PRINT0("\n");
759 	acg.cg_ndblk = dmax - cbase;
760 	sblock.fs_dsize += acg.cg_ndblk-aocg.cg_ndblk;
761 	if (sblock.fs_contigsumsize > 0) {
762 		acg.cg_nclusterblks = acg.cg_ndblk / sblock.fs_frag;
763 	}
764 
765 	/*
766 	 * Now we have to update the free fragment bitmap for our new free
767 	 * space.  There again we have to handle the fragmentation and also
768 	 * the rotational layout tables and the cluster summary.  This is
769 	 * also done per fragment for the first new block if the old file
770 	 * system end was not on a block boundary, per fragment for the new
771 	 * last block if the new file system end is not on a block boundary,
772 	 * and per block for all space in between.
773 	 *
774 	 * Handle the first new block here if it was partially available
775 	 * before.
776 	 */
777 	if(osblock.fs_size % sblock.fs_frag) {
778 		if(roundup(osblock.fs_size, sblock.fs_frag)<=sblock.fs_size) {
779 			/*
780 			 * The new space is enough to fill at least this
781 			 * block
782 			 */
783 			j=0;
784 			for(i=roundup(osblock.fs_size-cbase, sblock.fs_frag)-1;
785 			    i>=osblock.fs_size-cbase;
786 			    i--) {
787 				setbit(cg_blksfree(&acg), i);
788 				acg.cg_cs.cs_nffree++;
789 				j++;
790 			}
791 
792 			/*
793 			 * Check if the fragment just created could join an
794 			 * already existing fragment at the former end of the
795 			 * file system.
796 			 */
797 			if(isblock(&sblock, cg_blksfree(&acg),
798 			    ((osblock.fs_size - cgbase(&sblock, cylno))/
799 			    sblock.fs_frag))) {
800 				/*
801 				 * The block is now completely available.
802 				 */
803 				DBG_PRINT0("block was\n");
804 				acg.cg_frsum[osblock.fs_size%sblock.fs_frag]--;
805 				acg.cg_cs.cs_nbfree++;
806 				acg.cg_cs.cs_nffree-=sblock.fs_frag;
807 				k=rounddown(osblock.fs_size-cbase,
808 				    sblock.fs_frag);
809 				updclst((osblock.fs_size-cbase)/sblock.fs_frag);
810 			} else {
811 				/*
812 				 * Lets rejoin a possible partially growed
813 				 * fragment.
814 				 */
815 				k=0;
816 				while(isset(cg_blksfree(&acg), i) &&
817 				    (i>=rounddown(osblock.fs_size-cbase,
818 				    sblock.fs_frag))) {
819 					i--;
820 					k++;
821 				}
822 				if(k) {
823 					acg.cg_frsum[k]--;
824 				}
825 				acg.cg_frsum[k+j]++;
826 			}
827 		} else {
828 			/*
829 			 * We only grow by some fragments within this last
830 			 * block.
831 			 */
832 			for(i=sblock.fs_size-cbase-1;
833 				i>=osblock.fs_size-cbase;
834 				i--) {
835 				setbit(cg_blksfree(&acg), i);
836 				acg.cg_cs.cs_nffree++;
837 				j++;
838 			}
839 			/*
840 			 * Lets rejoin a possible partially growed fragment.
841 			 */
842 			k=0;
843 			while(isset(cg_blksfree(&acg), i) &&
844 			    (i>=rounddown(osblock.fs_size-cbase,
845 			    sblock.fs_frag))) {
846 				i--;
847 				k++;
848 			}
849 			if(k) {
850 				acg.cg_frsum[k]--;
851 			}
852 			acg.cg_frsum[k+j]++;
853 		}
854 	}
855 
856 	/*
857 	 * Handle all new complete blocks here.
858 	 */
859 	for(i=roundup(osblock.fs_size-cbase, sblock.fs_frag);
860 	    i+sblock.fs_frag<=dmax-cbase;	/* XXX <= or only < ? */
861 	    i+=sblock.fs_frag) {
862 		j = i / sblock.fs_frag;
863 		setblock(&sblock, cg_blksfree(&acg), j);
864 		updclst(j);
865 		acg.cg_cs.cs_nbfree++;
866 	}
867 
868 	/*
869 	 * Handle the last new block if there are stll some new fragments left.
870 	 * Here we don't have to bother about the cluster summary or the even
871 	 * the rotational layout table.
872 	 */
873 	if (i < (dmax - cbase)) {
874 		acg.cg_frsum[dmax - cbase - i]++;
875 		for (; i < dmax - cbase; i++) {
876 			setbit(cg_blksfree(&acg), i);
877 			acg.cg_cs.cs_nffree++;
878 		}
879 	}
880 
881 	sblock.fs_cstotal.cs_nffree +=
882 	    (acg.cg_cs.cs_nffree - aocg.cg_cs.cs_nffree);
883 	sblock.fs_cstotal.cs_nbfree +=
884 	    (acg.cg_cs.cs_nbfree - aocg.cg_cs.cs_nbfree);
885 	/*
886 	 * The following statistics are not changed here:
887 	 *     sblock.fs_cstotal.cs_ndir
888 	 *     sblock.fs_cstotal.cs_nifree
889 	 * As the statistics for this cylinder group are ready, copy it to
890 	 * the summary information array.
891 	 */
892 	*cs = acg.cg_cs;
893 
894 	/*
895 	 * Write the updated "joining" cylinder group back to disk.
896 	 */
897 	wtfs(fsbtodb(&sblock, cgtod(&sblock, cylno)), (size_t)sblock.fs_cgsize,
898 	    (void *)&acg, fso, Nflag);
899 	DBG_PRINT0("jcg written\n");
900 	DBG_DUMP_CG(&sblock,
901 	    "new joining cg",
902 	    &acg);
903 
904 	DBG_LEAVE;
905 	return;
906 }
907 
908 /* ********************************************************** updcsloc ***** */
909 /*
910  * Here we update the location of the cylinder summary. We have two possible
911  * ways of growing the cylinder summary.
912  * (1)	We can try to grow the summary in the current location, and relocate
913  *	possibly used blocks within the current cylinder group.
914  * (2)	Alternatively we can relocate the whole cylinder summary to the first
915  *	new completely empty cylinder group. Once the cylinder summary is no
916  *	longer in the beginning of the first cylinder group you should never
917  *	use a version of fsck which is not aware of the possibility to have
918  *	this structure in a non standard place.
919  * Option (1) is considered to be less intrusive to the structure of the file-
920  * system. So we try to stick to that whenever possible. If there is not enough
921  * space in the cylinder group containing the cylinder summary we have to use
922  * method (2). In case of active snapshots in the file system we probably can
923  * completely avoid implementing copy on write if we stick to method (2) only.
924  */
925 static void
926 updcsloc(time_t utime, int fsi, int fso, unsigned int Nflag)
927 {
928 	DBG_FUNC("updcsloc")
929 	struct csum	*cs;
930 	int	ocscg, ncscg;
931 	int	blocks;
932 	ufs2_daddr_t	cbase, dupper, odupper, d, f, g;
933 	int	ind;
934 	int	cylno, inc;
935 	struct gfs_bpp	*bp;
936 	int	i, l;
937 	int	lcs=0;
938 	int	block;
939 
940 	DBG_ENTER;
941 
942 	if(howmany(sblock.fs_cssize, sblock.fs_fsize) ==
943 	    howmany(osblock.fs_cssize, osblock.fs_fsize)) {
944 		/*
945 		 * No new fragment needed.
946 		 */
947 		DBG_LEAVE;
948 		return;
949 	}
950 	ocscg=dtog(&osblock, osblock.fs_csaddr);
951 	cs=fscs+ocscg;
952 	blocks = 1+howmany(sblock.fs_cssize, sblock.fs_bsize)-
953 	    howmany(osblock.fs_cssize, osblock.fs_bsize);
954 
955 	/*
956 	 * Read original cylinder group from disk, and make a copy.
957 	 * XXX	If Nflag is set in some very rare cases we now miss
958 	 *	some changes done in updjcg by reading the unmodified
959 	 *	block from disk.
960 	 */
961 	rdfs(fsbtodb(&osblock, cgtod(&osblock, ocscg)),
962 	    (size_t)osblock.fs_cgsize, (void *)&aocg, fsi);
963 	DBG_PRINT0("oscg read\n");
964 	DBG_DUMP_CG(&sblock,
965 	    "old summary cg",
966 	    &aocg);
967 
968 	memcpy((void *)&cgun1, (void *)&cgun2, sizeof(cgun2));
969 
970 	/*
971 	 * Touch the cylinder group, set up local variables needed later
972 	 * and update the superblock.
973 	 */
974 	acg.cg_time = utime;
975 
976 	/*
977 	 * XXX	In the case of having active snapshots we may need much more
978 	 *	blocks for the copy on write. We need each block twice, and
979 	 *	also up to 8*3 blocks for indirect blocks for all possible
980 	 *	references.
981 	 */
982 	if(/*((int)sblock.fs_time&0x3)>0||*/ cs->cs_nbfree < blocks) {
983 		/*
984 		 * There is not enough space in the old cylinder group to
985 		 * relocate all blocks as needed, so we relocate the whole
986 		 * cylinder group summary to a new group. We try to use the
987 		 * first complete new cylinder group just created. Within the
988 		 * cylinder group we align the area immediately after the
989 		 * cylinder group information location in order to be as
990 		 * close as possible to the original implementation of ffs.
991 		 *
992 		 * First we have to make sure we'll find enough space in the
993 		 * new cylinder group. If not, then we currently give up.
994 		 * We start with freeing everything which was used by the
995 		 * fragments of the old cylinder summary in the current group.
996 		 * Now we write back the group meta data, read in the needed
997 		 * meta data from the new cylinder group, and start allocating
998 		 * within that group. Here we can assume, the group to be
999 		 * completely empty. Which makes the handling of fragments and
1000 		 * clusters a lot easier.
1001 		 */
1002 		DBG_TRC;
1003 		if(sblock.fs_ncg-osblock.fs_ncg < 2) {
1004 			errx(2, "panic: not enough space");
1005 		}
1006 
1007 		/*
1008 		 * Point "d" to the first fragment not used by the cylinder
1009 		 * summary.
1010 		 */
1011 		d=osblock.fs_csaddr+(osblock.fs_cssize/osblock.fs_fsize);
1012 
1013 		/*
1014 		 * Set up last cluster size ("lcs") already here. Calculate
1015 		 * the size for the trailing cluster just behind where "d"
1016 		 * points to.
1017 		 */
1018 		if(sblock.fs_contigsumsize > 0) {
1019 			for(block=howmany(d%sblock.fs_fpg, sblock.fs_frag),
1020 			    lcs=0; lcs<sblock.fs_contigsumsize;
1021 			    block++, lcs++) {
1022 				if(isclr(cg_clustersfree(&acg), block)){
1023 					break;
1024 				}
1025 			}
1026 		}
1027 
1028 		/*
1029 		 * Point "d" to the last frag used by the cylinder summary.
1030 		 */
1031 		d--;
1032 
1033 		DBG_PRINT1("d=%d\n",
1034 		    d);
1035 		if((d+1)%sblock.fs_frag) {
1036 			/*
1037 			 * The end of the cylinder summary is not a complete
1038 			 * block.
1039 			 */
1040 			DBG_TRC;
1041 			frag_adjust(d%sblock.fs_fpg, -1);
1042 			for(; (d+1)%sblock.fs_frag; d--) {
1043 				DBG_PRINT1("d=%d\n",
1044 				    d);
1045 				setbit(cg_blksfree(&acg), d%sblock.fs_fpg);
1046 				acg.cg_cs.cs_nffree++;
1047 				sblock.fs_cstotal.cs_nffree++;
1048 			}
1049 			/*
1050 			 * Point "d" to the last fragment of the last
1051 			 * (incomplete) block of the cylinder summary.
1052 			 */
1053 			d++;
1054 			frag_adjust(d%sblock.fs_fpg, 1);
1055 
1056 			if(isblock(&sblock, cg_blksfree(&acg),
1057 			    (d%sblock.fs_fpg)/sblock.fs_frag)) {
1058 				DBG_PRINT1("d=%d\n", d);
1059 				acg.cg_cs.cs_nffree-=sblock.fs_frag;
1060 				acg.cg_cs.cs_nbfree++;
1061 				sblock.fs_cstotal.cs_nffree-=sblock.fs_frag;
1062 				sblock.fs_cstotal.cs_nbfree++;
1063 				if(sblock.fs_contigsumsize > 0) {
1064 					setbit(cg_clustersfree(&acg),
1065 					    (d%sblock.fs_fpg)/sblock.fs_frag);
1066 					if(lcs < sblock.fs_contigsumsize) {
1067 						if(lcs) {
1068 							cg_clustersum(&acg)
1069 							    [lcs]--;
1070 						}
1071 						lcs++;
1072 						cg_clustersum(&acg)[lcs]++;
1073 					}
1074 				}
1075 			}
1076 			/*
1077 			 * Point "d" to the first fragment of the block before
1078 			 * the last incomplete block.
1079 			 */
1080 			d--;
1081 		}
1082 
1083 		DBG_PRINT1("d=%d\n", d);
1084 		for(d=rounddown(d, sblock.fs_frag); d >= osblock.fs_csaddr;
1085 		    d-=sblock.fs_frag) {
1086 			DBG_TRC;
1087 			DBG_PRINT1("d=%d\n", d);
1088 			setblock(&sblock, cg_blksfree(&acg),
1089 			    (d%sblock.fs_fpg)/sblock.fs_frag);
1090 			acg.cg_cs.cs_nbfree++;
1091 			sblock.fs_cstotal.cs_nbfree++;
1092 			if(sblock.fs_contigsumsize > 0) {
1093 				setbit(cg_clustersfree(&acg),
1094 				    (d%sblock.fs_fpg)/sblock.fs_frag);
1095 				/*
1096 				 * The last cluster size is already set up.
1097 				 */
1098 				if(lcs < sblock.fs_contigsumsize) {
1099 					if(lcs) {
1100 						cg_clustersum(&acg)[lcs]--;
1101 					}
1102 					lcs++;
1103 					cg_clustersum(&acg)[lcs]++;
1104 				}
1105 			}
1106 		}
1107 		*cs = acg.cg_cs;
1108 
1109 		/*
1110 		 * Now write the former cylinder group containing the cylinder
1111 		 * summary back to disk.
1112 		 */
1113 		wtfs(fsbtodb(&sblock, cgtod(&sblock, ocscg)),
1114 		    (size_t)sblock.fs_cgsize, (void *)&acg, fso, Nflag);
1115 		DBG_PRINT0("oscg written\n");
1116 		DBG_DUMP_CG(&sblock,
1117 		    "old summary cg",
1118 		    &acg);
1119 
1120 		/*
1121 		 * Find the beginning of the new cylinder group containing the
1122 		 * cylinder summary.
1123 		 */
1124 		sblock.fs_csaddr=cgdmin(&sblock, osblock.fs_ncg);
1125 		ncscg=dtog(&sblock, sblock.fs_csaddr);
1126 		cs=fscs+ncscg;
1127 
1128 
1129 		/*
1130 		 * If Nflag is specified, we would now read random data instead
1131 		 * of an empty cg structure from disk. So we can't simulate that
1132 		 * part for now.
1133 		 */
1134 		if(Nflag) {
1135 			DBG_PRINT0("nscg update skipped\n");
1136 			DBG_LEAVE;
1137 			return;
1138 		}
1139 
1140 		/*
1141 		 * Read the future cylinder group containing the cylinder
1142 		 * summary from disk, and make a copy.
1143 		 */
1144 		rdfs(fsbtodb(&sblock, cgtod(&sblock, ncscg)),
1145 		    (size_t)sblock.fs_cgsize, (void *)&aocg, fsi);
1146 		DBG_PRINT0("nscg read\n");
1147 		DBG_DUMP_CG(&sblock,
1148 		    "new summary cg",
1149 		    &aocg);
1150 
1151 		memcpy((void *)&cgun1, (void *)&cgun2, sizeof(cgun2));
1152 
1153 		/*
1154 		 * Allocate all complete blocks used by the new cylinder
1155 		 * summary.
1156 		 */
1157 		for(d=sblock.fs_csaddr; d+sblock.fs_frag <=
1158 		    sblock.fs_csaddr+(sblock.fs_cssize/sblock.fs_fsize);
1159 		    d+=sblock.fs_frag) {
1160 			clrblock(&sblock, cg_blksfree(&acg),
1161 			    (d%sblock.fs_fpg)/sblock.fs_frag);
1162 			acg.cg_cs.cs_nbfree--;
1163 			sblock.fs_cstotal.cs_nbfree--;
1164 			if(sblock.fs_contigsumsize > 0) {
1165 				clrbit(cg_clustersfree(&acg),
1166 				    (d%sblock.fs_fpg)/sblock.fs_frag);
1167 			}
1168 		}
1169 
1170 		/*
1171 		 * Allocate all fragments used by the cylinder summary in the
1172 		 * last block.
1173 		 */
1174 		if(d<sblock.fs_csaddr+(sblock.fs_cssize/sblock.fs_fsize)) {
1175 			for(; d-sblock.fs_csaddr<
1176 			    sblock.fs_cssize/sblock.fs_fsize;
1177 			    d++) {
1178 				clrbit(cg_blksfree(&acg), d%sblock.fs_fpg);
1179 				acg.cg_cs.cs_nffree--;
1180 				sblock.fs_cstotal.cs_nffree--;
1181 			}
1182 			acg.cg_cs.cs_nbfree--;
1183 			acg.cg_cs.cs_nffree+=sblock.fs_frag;
1184 			sblock.fs_cstotal.cs_nbfree--;
1185 			sblock.fs_cstotal.cs_nffree+=sblock.fs_frag;
1186 			if(sblock.fs_contigsumsize > 0) {
1187 				clrbit(cg_clustersfree(&acg),
1188 				    (d%sblock.fs_fpg)/sblock.fs_frag);
1189 			}
1190 
1191 			frag_adjust(d%sblock.fs_fpg, +1);
1192 		}
1193 		/*
1194 		 * XXX	Handle the cluster statistics here in the case this
1195 		 *	cylinder group is now almost full, and the remaining
1196 		 *	space is less then the maximum cluster size. This is
1197 		 *	probably not needed, as you would hardly find a file
1198 		 *	system which has only MAXCSBUFS+FS_MAXCONTIG of free
1199 		 *	space right behind the cylinder group information in
1200 		 *	any new cylinder group.
1201 		 */
1202 
1203 		/*
1204 		 * Update our statistics in the cylinder summary.
1205 		 */
1206 		*cs = acg.cg_cs;
1207 
1208 		/*
1209 		 * Write the new cylinder group containing the cylinder summary
1210 		 * back to disk.
1211 		 */
1212 		wtfs(fsbtodb(&sblock, cgtod(&sblock, ncscg)),
1213 		    (size_t)sblock.fs_cgsize, (void *)&acg, fso, Nflag);
1214 		DBG_PRINT0("nscg written\n");
1215 		DBG_DUMP_CG(&sblock,
1216 		    "new summary cg",
1217 		    &acg);
1218 
1219 		DBG_LEAVE;
1220 		return;
1221 	}
1222 	/*
1223 	 * We have got enough of space in the current cylinder group, so we
1224 	 * can relocate just a few blocks, and let the summary information
1225 	 * grow in place where it is right now.
1226 	 */
1227 	DBG_TRC;
1228 
1229 	cbase = cgbase(&osblock, ocscg);	/* old and new are equal */
1230 	dupper = sblock.fs_csaddr - cbase +
1231 	    howmany(sblock.fs_cssize, sblock.fs_fsize);
1232 	odupper = osblock.fs_csaddr - cbase +
1233 	    howmany(osblock.fs_cssize, osblock.fs_fsize);
1234 
1235 	sblock.fs_dsize -= dupper-odupper;
1236 
1237 	/*
1238 	 * Allocate the space for the array of blocks to be relocated.
1239 	 */
1240  	bp=(struct gfs_bpp *)malloc(((dupper-odupper)/sblock.fs_frag+2)*
1241 	    sizeof(struct gfs_bpp));
1242 	if(bp == NULL) {
1243 		errx(1, "malloc failed");
1244 	}
1245 	memset((char *)bp, 0, ((dupper-odupper)/sblock.fs_frag+2)*
1246 	    sizeof(struct gfs_bpp));
1247 
1248 	/*
1249 	 * Lock all new frags needed for the cylinder group summary. This is
1250 	 * done per fragment in the first and last block of the new required
1251 	 * area, and per block for all other blocks.
1252 	 *
1253 	 * Handle the first new block here (but only if some fragments where
1254 	 * already used for the cylinder summary).
1255 	 */
1256 	ind=0;
1257 	frag_adjust(odupper, -1);
1258 	for(d=odupper; ((d<dupper)&&(d%sblock.fs_frag)); d++) {
1259 		DBG_PRINT1("scg first frag check loop d=%d\n",
1260 		    d);
1261 		if(isclr(cg_blksfree(&acg), d)) {
1262 			if (!ind) {
1263 				bp[ind].old=d/sblock.fs_frag;
1264 				bp[ind].flags|=GFS_FL_FIRST;
1265 				if(roundup(d, sblock.fs_frag) >= dupper) {
1266 					bp[ind].flags|=GFS_FL_LAST;
1267 				}
1268 				ind++;
1269 			}
1270 		} else {
1271 			clrbit(cg_blksfree(&acg), d);
1272 			acg.cg_cs.cs_nffree--;
1273 			sblock.fs_cstotal.cs_nffree--;
1274 		}
1275 		/*
1276 		 * No cluster handling is needed here, as there was at least
1277 		 * one fragment in use by the cylinder summary in the old
1278 		 * file system.
1279 		 * No block-free counter handling here as this block was not
1280 		 * a free block.
1281 		 */
1282 	}
1283 	frag_adjust(odupper, 1);
1284 
1285 	/*
1286 	 * Handle all needed complete blocks here.
1287 	 */
1288 	for(; d+sblock.fs_frag<=dupper; d+=sblock.fs_frag) {
1289 		DBG_PRINT1("scg block check loop d=%d\n",
1290 		    d);
1291 		if(!isblock(&sblock, cg_blksfree(&acg), d/sblock.fs_frag)) {
1292 			for(f=d; f<d+sblock.fs_frag; f++) {
1293 				if(isset(cg_blksfree(&aocg), f)) {
1294 					acg.cg_cs.cs_nffree--;
1295 					sblock.fs_cstotal.cs_nffree--;
1296 				}
1297 			}
1298 			clrblock(&sblock, cg_blksfree(&acg), d/sblock.fs_frag);
1299 			bp[ind].old=d/sblock.fs_frag;
1300 			ind++;
1301 		} else {
1302 			clrblock(&sblock, cg_blksfree(&acg), d/sblock.fs_frag);
1303 			acg.cg_cs.cs_nbfree--;
1304 			sblock.fs_cstotal.cs_nbfree--;
1305 			if(sblock.fs_contigsumsize > 0) {
1306 				clrbit(cg_clustersfree(&acg), d/sblock.fs_frag);
1307 				for(lcs=0, l=(d/sblock.fs_frag)+1;
1308 				    lcs<sblock.fs_contigsumsize;
1309 				    l++, lcs++ ) {
1310 					if(isclr(cg_clustersfree(&acg),l)){
1311 						break;
1312 					}
1313 				}
1314 				if(lcs < sblock.fs_contigsumsize) {
1315 					cg_clustersum(&acg)[lcs+1]--;
1316 					if(lcs) {
1317 						cg_clustersum(&acg)[lcs]++;
1318 					}
1319 				}
1320 			}
1321 		}
1322 		/*
1323 		 * No fragment counter handling is needed here, as this finally
1324 		 * doesn't change after the relocation.
1325 		 */
1326 	}
1327 
1328 	/*
1329 	 * Handle all fragments needed in the last new affected block.
1330 	 */
1331 	if(d<dupper) {
1332 		frag_adjust(dupper-1, -1);
1333 
1334 		if(isblock(&sblock, cg_blksfree(&acg), d/sblock.fs_frag)) {
1335 			acg.cg_cs.cs_nbfree--;
1336 			sblock.fs_cstotal.cs_nbfree--;
1337 			acg.cg_cs.cs_nffree+=sblock.fs_frag;
1338 			sblock.fs_cstotal.cs_nffree+=sblock.fs_frag;
1339 			if(sblock.fs_contigsumsize > 0) {
1340 				clrbit(cg_clustersfree(&acg), d/sblock.fs_frag);
1341 				for(lcs=0, l=(d/sblock.fs_frag)+1;
1342 				    lcs<sblock.fs_contigsumsize;
1343 				    l++, lcs++ ) {
1344 					if(isclr(cg_clustersfree(&acg),l)){
1345 						break;
1346 					}
1347 				}
1348 				if(lcs < sblock.fs_contigsumsize) {
1349 					cg_clustersum(&acg)[lcs+1]--;
1350 					if(lcs) {
1351 						cg_clustersum(&acg)[lcs]++;
1352 					}
1353 				}
1354 			}
1355 		}
1356 
1357 		for(; d<dupper; d++) {
1358 			DBG_PRINT1("scg second frag check loop d=%d\n",
1359 			    d);
1360 			if(isclr(cg_blksfree(&acg), d)) {
1361 				bp[ind].old=d/sblock.fs_frag;
1362 				bp[ind].flags|=GFS_FL_LAST;
1363 			} else {
1364 				clrbit(cg_blksfree(&acg), d);
1365 				acg.cg_cs.cs_nffree--;
1366 				sblock.fs_cstotal.cs_nffree--;
1367 			}
1368 		}
1369 		if(bp[ind].flags & GFS_FL_LAST) { /* we have to advance here */
1370 			ind++;
1371 		}
1372 		frag_adjust(dupper-1, 1);
1373 	}
1374 
1375 	/*
1376 	 * If we found a block to relocate just do so.
1377 	 */
1378 	if(ind) {
1379 		for(i=0; i<ind; i++) {
1380 			if(!bp[i].old) { /* no more blocks listed */
1381 				/*
1382 				 * XXX	A relative blocknumber should not be
1383 				 *	zero, which is not explicitly
1384 				 *	guaranteed by our code.
1385 				 */
1386 				break;
1387 			}
1388 			/*
1389 			 * Allocate a complete block in the same (current)
1390 			 * cylinder group.
1391 			 */
1392 			bp[i].new=alloc()/sblock.fs_frag;
1393 
1394 			/*
1395 			 * There is no frag_adjust() needed for the new block
1396 			 * as it will have no fragments yet :-).
1397 			 */
1398 			for(f=bp[i].old*sblock.fs_frag,
1399 			    g=bp[i].new*sblock.fs_frag;
1400 			    f<(bp[i].old+1)*sblock.fs_frag;
1401 			    f++, g++) {
1402 				if(isset(cg_blksfree(&aocg), f)) {
1403 					setbit(cg_blksfree(&acg), g);
1404 					acg.cg_cs.cs_nffree++;
1405 					sblock.fs_cstotal.cs_nffree++;
1406 				}
1407 			}
1408 
1409 			/*
1410 			 * Special handling is required if this was the first
1411 			 * block. We have to consider the fragments which were
1412 			 * used by the cylinder summary in the original block
1413 			 * which re to be free in the copy of our block.  We
1414 			 * have to be careful if this first block happens to
1415 			 * be also the last block to be relocated.
1416 			 */
1417 			if(bp[i].flags & GFS_FL_FIRST) {
1418 				for(f=bp[i].old*sblock.fs_frag,
1419 				    g=bp[i].new*sblock.fs_frag;
1420 				    f<odupper;
1421 				    f++, g++) {
1422 					setbit(cg_blksfree(&acg), g);
1423 					acg.cg_cs.cs_nffree++;
1424 					sblock.fs_cstotal.cs_nffree++;
1425 				}
1426 				if(!(bp[i].flags & GFS_FL_LAST)) {
1427 					frag_adjust(bp[i].new*sblock.fs_frag,1);
1428 				}
1429 			}
1430 
1431 			/*
1432 			 * Special handling is required if this is the last
1433 			 * block to be relocated.
1434 			 */
1435 			if(bp[i].flags & GFS_FL_LAST) {
1436 				frag_adjust(bp[i].new*sblock.fs_frag, 1);
1437 				frag_adjust(bp[i].old*sblock.fs_frag, -1);
1438 				for(f=dupper;
1439 				    f<roundup(dupper, sblock.fs_frag);
1440 				    f++) {
1441 					if(isclr(cg_blksfree(&acg), f)) {
1442 						setbit(cg_blksfree(&acg), f);
1443 						acg.cg_cs.cs_nffree++;
1444 						sblock.fs_cstotal.cs_nffree++;
1445 					}
1446 				}
1447 				frag_adjust(bp[i].old*sblock.fs_frag, 1);
1448 			}
1449 
1450 			/*
1451 			 * !!! Attach the cylindergroup offset here.
1452 			 */
1453 			bp[i].old+=cbase/sblock.fs_frag;
1454 			bp[i].new+=cbase/sblock.fs_frag;
1455 
1456 			/*
1457 			 * Copy the content of the block.
1458 			 */
1459 			/*
1460 			 * XXX	Here we will have to implement a copy on write
1461 			 *	in the case we have any active snapshots.
1462 			 */
1463 			rdfs(fsbtodb(&sblock, bp[i].old*sblock.fs_frag),
1464 			    (size_t)sblock.fs_bsize, (void *)&ablk, fsi);
1465 			wtfs(fsbtodb(&sblock, bp[i].new*sblock.fs_frag),
1466 			    (size_t)sblock.fs_bsize, (void *)&ablk, fso, Nflag);
1467 			DBG_DUMP_HEX(&sblock,
1468 			    "copied full block",
1469 			    (unsigned char *)&ablk);
1470 
1471 			DBG_PRINT2("scg (%d->%d) block relocated\n",
1472 			    bp[i].old,
1473 			    bp[i].new);
1474 		}
1475 
1476 		/*
1477 		 * Now we have to update all references to any fragment which
1478 		 * belongs to any block relocated. We iterate now over all
1479 		 * cylinder groups, within those over all non zero length
1480 		 * inodes.
1481 		 */
1482 		for(cylno=0; cylno<osblock.fs_ncg; cylno++) {
1483 			DBG_PRINT1("scg doing cg (%d)\n",
1484 			    cylno);
1485 			for(inc=osblock.fs_ipg-1 ; inc>=0 ; inc--) {
1486 				updrefs(cylno, (ino_t)inc, bp, fsi, fso, Nflag);
1487 			}
1488 		}
1489 
1490 		/*
1491 		 * All inodes are checked, now make sure the number of
1492 		 * references found make sense.
1493 		 */
1494 		for(i=0; i<ind; i++) {
1495 			if(!bp[i].found || (bp[i].found>sblock.fs_frag)) {
1496 				warnx("error: %d refs found for block %d.",
1497 				    bp[i].found, bp[i].old);
1498 			}
1499 
1500 		}
1501 	}
1502 	/*
1503 	 * The following statistics are not changed here:
1504 	 *     sblock.fs_cstotal.cs_ndir
1505 	 *     sblock.fs_cstotal.cs_nifree
1506 	 * The following statistics were already updated on the fly:
1507 	 *     sblock.fs_cstotal.cs_nffree
1508 	 *     sblock.fs_cstotal.cs_nbfree
1509 	 * As the statistics for this cylinder group are ready, copy it to
1510 	 * the summary information array.
1511 	 */
1512 
1513 	*cs = acg.cg_cs;
1514 
1515 	/*
1516 	 * Write summary cylinder group back to disk.
1517 	 */
1518 	wtfs(fsbtodb(&sblock, cgtod(&sblock, ocscg)), (size_t)sblock.fs_cgsize,
1519 	    (void *)&acg, fso, Nflag);
1520 	DBG_PRINT0("scg written\n");
1521 	DBG_DUMP_CG(&sblock,
1522 	    "new summary cg",
1523 	    &acg);
1524 
1525 	DBG_LEAVE;
1526 	return;
1527 }
1528 
1529 /* ************************************************************** rdfs ***** */
1530 /*
1531  * Here we read some block(s) from disk.
1532  */
1533 static void
1534 rdfs(ufs2_daddr_t bno, size_t size, void *bf, int fsi)
1535 {
1536 	DBG_FUNC("rdfs")
1537 	ssize_t	n;
1538 
1539 	DBG_ENTER;
1540 
1541 	if (lseek(fsi, (off_t)bno * DEV_BSIZE, 0) < 0) {
1542 		err(33, "rdfs: seek error: %ld", (long)bno);
1543 	}
1544 	n = read(fsi, bf, size);
1545 	if (n != (ssize_t)size) {
1546 		err(34, "rdfs: read error: %ld", (long)bno);
1547 	}
1548 
1549 	DBG_LEAVE;
1550 	return;
1551 }
1552 
1553 /* ************************************************************** wtfs ***** */
1554 /*
1555  * Here we write some block(s) to disk.
1556  */
1557 static void
1558 wtfs(ufs2_daddr_t bno, size_t size, void *bf, int fso, unsigned int Nflag)
1559 {
1560 	DBG_FUNC("wtfs")
1561 	ssize_t	n;
1562 
1563 	DBG_ENTER;
1564 
1565 	if (Nflag) {
1566 		DBG_LEAVE;
1567 		return;
1568 	}
1569 	if (lseek(fso, (off_t)bno * DEV_BSIZE, SEEK_SET) < 0) {
1570 		err(35, "wtfs: seek error: %ld", (long)bno);
1571 	}
1572 	n = write(fso, bf, size);
1573 	if (n != (ssize_t)size) {
1574 		err(36, "wtfs: write error: %ld", (long)bno);
1575 	}
1576 
1577 	DBG_LEAVE;
1578 	return;
1579 }
1580 
1581 /* ************************************************************* alloc ***** */
1582 /*
1583  * Here we allocate a free block in the current cylinder group. It is assumed,
1584  * that acg contains the current cylinder group. As we may take a block from
1585  * somewhere in the file system we have to handle cluster summary here.
1586  */
1587 static ufs2_daddr_t
1588 alloc(void)
1589 {
1590 	DBG_FUNC("alloc")
1591 	ufs2_daddr_t	d, blkno;
1592 	int	lcs1, lcs2;
1593 	int	l;
1594 	int	csmin, csmax;
1595 	int	dlower, dupper, dmax;
1596 
1597 	DBG_ENTER;
1598 
1599 	if (acg.cg_magic != CG_MAGIC) {
1600 		warnx("acg: bad magic number");
1601 		DBG_LEAVE;
1602 		return (0);
1603 	}
1604 	if (acg.cg_cs.cs_nbfree == 0) {
1605 		warnx("error: cylinder group ran out of space");
1606 		DBG_LEAVE;
1607 		return (0);
1608 	}
1609 	/*
1610 	 * We start seeking for free blocks only from the space available after
1611 	 * the end of the new grown cylinder summary. Otherwise we allocate a
1612 	 * block here which we have to relocate a couple of seconds later again
1613 	 * again, and we are not prepared to to this anyway.
1614 	 */
1615 	blkno=-1;
1616 	dlower=cgsblock(&sblock, acg.cg_cgx)-cgbase(&sblock, acg.cg_cgx);
1617 	dupper=cgdmin(&sblock, acg.cg_cgx)-cgbase(&sblock, acg.cg_cgx);
1618 	dmax=cgbase(&sblock, acg.cg_cgx)+sblock.fs_fpg;
1619 	if (dmax > sblock.fs_size) {
1620 		dmax = sblock.fs_size;
1621 	}
1622 	dmax-=cgbase(&sblock, acg.cg_cgx); /* retransform into cg */
1623 	csmin=sblock.fs_csaddr-cgbase(&sblock, acg.cg_cgx);
1624 	csmax=csmin+howmany(sblock.fs_cssize, sblock.fs_fsize);
1625 	DBG_PRINT3("seek range: dl=%d, du=%d, dm=%d\n",
1626 	    dlower,
1627 	    dupper,
1628 	    dmax);
1629 	DBG_PRINT2("range cont: csmin=%d, csmax=%d\n",
1630 	    csmin,
1631 	    csmax);
1632 
1633 	for(d=0; (d<dlower && blkno==-1); d+=sblock.fs_frag) {
1634 		if(d>=csmin && d<=csmax) {
1635 			continue;
1636 		}
1637 		if(isblock(&sblock, cg_blksfree(&acg), fragstoblks(&sblock,
1638 		    d))) {
1639 			blkno = fragstoblks(&sblock, d);/* Yeah found a block */
1640 			break;
1641 		}
1642 	}
1643 	for(d=dupper; (d<dmax && blkno==-1); d+=sblock.fs_frag) {
1644 		if(d>=csmin && d<=csmax) {
1645 			continue;
1646 		}
1647 		if(isblock(&sblock, cg_blksfree(&acg), fragstoblks(&sblock,
1648 		    d))) {
1649 			blkno = fragstoblks(&sblock, d);/* Yeah found a block */
1650 			break;
1651 		}
1652 	}
1653 	if(blkno==-1) {
1654 		warnx("internal error: couldn't find promised block in cg");
1655 		DBG_LEAVE;
1656 		return (0);
1657 	}
1658 
1659 	/*
1660 	 * This is needed if the block was found already in the first loop.
1661 	 */
1662 	d=blkstofrags(&sblock, blkno);
1663 
1664 	clrblock(&sblock, cg_blksfree(&acg), blkno);
1665 	if (sblock.fs_contigsumsize > 0) {
1666 		/*
1667 		 * Handle the cluster allocation bitmap.
1668 		 */
1669 		clrbit(cg_clustersfree(&acg), blkno);
1670 		/*
1671 		 * We possibly have split a cluster here, so we have to do
1672 		 * recalculate the sizes of the remaining cluster halves now,
1673 		 * and use them for updating the cluster summary information.
1674 		 *
1675 		 * Lets start with the blocks before our allocated block ...
1676 		 */
1677 		for(lcs1=0, l=blkno-1; lcs1<sblock.fs_contigsumsize;
1678 		    l--, lcs1++ ) {
1679 			if(isclr(cg_clustersfree(&acg),l)){
1680 				break;
1681 			}
1682 		}
1683 		/*
1684 		 * ... and continue with the blocks right after our allocated
1685 		 * block.
1686 		 */
1687 		for(lcs2=0, l=blkno+1; lcs2<sblock.fs_contigsumsize;
1688 		    l++, lcs2++ ) {
1689 			if(isclr(cg_clustersfree(&acg),l)){
1690 				break;
1691 			}
1692 		}
1693 
1694 		/*
1695 		 * Now update all counters.
1696 		 */
1697 		cg_clustersum(&acg)[MIN(lcs1+lcs2+1,sblock.fs_contigsumsize)]--;
1698 		if(lcs1) {
1699 			cg_clustersum(&acg)[lcs1]++;
1700 		}
1701 		if(lcs2) {
1702 			cg_clustersum(&acg)[lcs2]++;
1703 		}
1704 	}
1705 	/*
1706 	 * Update all statistics based on blocks.
1707 	 */
1708 	acg.cg_cs.cs_nbfree--;
1709 	sblock.fs_cstotal.cs_nbfree--;
1710 
1711 	DBG_LEAVE;
1712 	return (d);
1713 }
1714 
1715 /* *********************************************************** isblock ***** */
1716 /*
1717  * Here we check if all frags of a block are free. For more details again
1718  * please see the source of newfs(8), as this function is taken over almost
1719  * unchanged.
1720  */
1721 static int
1722 isblock(struct fs *fs, unsigned char *cp, int h)
1723 {
1724 	DBG_FUNC("isblock")
1725 	unsigned char	mask;
1726 
1727 	DBG_ENTER;
1728 
1729 	switch (fs->fs_frag) {
1730 	case 8:
1731 		DBG_LEAVE;
1732 		return (cp[h] == 0xff);
1733 	case 4:
1734 		mask = 0x0f << ((h & 0x1) << 2);
1735 		DBG_LEAVE;
1736 		return ((cp[h >> 1] & mask) == mask);
1737 	case 2:
1738 		mask = 0x03 << ((h & 0x3) << 1);
1739 		DBG_LEAVE;
1740 		return ((cp[h >> 2] & mask) == mask);
1741 	case 1:
1742 		mask = 0x01 << (h & 0x7);
1743 		DBG_LEAVE;
1744 		return ((cp[h >> 3] & mask) == mask);
1745 	default:
1746 		fprintf(stderr, "isblock bad fs_frag %d\n", fs->fs_frag);
1747 		DBG_LEAVE;
1748 		return (0);
1749 	}
1750 }
1751 
1752 /* ********************************************************** clrblock ***** */
1753 /*
1754  * Here we allocate a complete block in the block map. For more details again
1755  * please see the source of newfs(8), as this function is taken over almost
1756  * unchanged.
1757  */
1758 static void
1759 clrblock(struct fs *fs, unsigned char *cp, int h)
1760 {
1761 	DBG_FUNC("clrblock")
1762 
1763 	DBG_ENTER;
1764 
1765 	switch ((fs)->fs_frag) {
1766 	case 8:
1767 		cp[h] = 0;
1768 		break;
1769 	case 4:
1770 		cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2));
1771 		break;
1772 	case 2:
1773 		cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1));
1774 		break;
1775 	case 1:
1776 		cp[h >> 3] &= ~(0x01 << (h & 0x7));
1777 		break;
1778 	default:
1779 		warnx("clrblock bad fs_frag %d", fs->fs_frag);
1780 		break;
1781 	}
1782 
1783 	DBG_LEAVE;
1784 	return;
1785 }
1786 
1787 /* ********************************************************** setblock ***** */
1788 /*
1789  * Here we free a complete block in the free block map. For more details again
1790  * please see the source of newfs(8), as this function is taken over almost
1791  * unchanged.
1792  */
1793 static void
1794 setblock(struct fs *fs, unsigned char *cp, int h)
1795 {
1796 	DBG_FUNC("setblock")
1797 
1798 	DBG_ENTER;
1799 
1800 	switch (fs->fs_frag) {
1801 	case 8:
1802 		cp[h] = 0xff;
1803 		break;
1804 	case 4:
1805 		cp[h >> 1] |= (0x0f << ((h & 0x1) << 2));
1806 		break;
1807 	case 2:
1808 		cp[h >> 2] |= (0x03 << ((h & 0x3) << 1));
1809 		break;
1810 	case 1:
1811 		cp[h >> 3] |= (0x01 << (h & 0x7));
1812 		break;
1813 	default:
1814 		warnx("setblock bad fs_frag %d", fs->fs_frag);
1815 		break;
1816 	}
1817 
1818 	DBG_LEAVE;
1819 	return;
1820 }
1821 
1822 /* ************************************************************ ginode ***** */
1823 /*
1824  * This function provides access to an individual inode. We find out in which
1825  * block the requested inode is located, read it from disk if needed, and
1826  * return the pointer into that block. We maintain a cache of one block to
1827  * not read the same block again and again if we iterate linearly over all
1828  * inodes.
1829  */
1830 static union dinode *
1831 ginode(ino_t inumber, int fsi, int cg)
1832 {
1833 	DBG_FUNC("ginode")
1834 	static ino_t	startinum = 0;	/* first inode in cached block */
1835 
1836 	DBG_ENTER;
1837 
1838 	inumber += (cg * sblock.fs_ipg);
1839 	if (inumber < ROOTINO || inumber > maxino)
1840 		errx(8, "bad inode number %d to ginode", inumber);
1841 	if (startinum == 0 ||
1842 	    inumber < startinum || inumber >= startinum + INOPB(&sblock)) {
1843 		inoblk = fsbtodb(&sblock, ino_to_fsba(&sblock, inumber));
1844 		rdfs(inoblk, (size_t)sblock.fs_bsize, inobuf, fsi);
1845 		startinum = (inumber / INOPB(&sblock)) * INOPB(&sblock);
1846 	}
1847 	DBG_LEAVE;
1848 	if (sblock.fs_magic == FS_UFS1_MAGIC)
1849 		return ((union dinode *)
1850 		    &((struct ufs1_dinode *)inobuf)[inumber % INOPB(&sblock)]);
1851 	return ((union dinode *)
1852 	    &((struct ufs2_dinode *)inobuf)[inumber % INOPB(&sblock)]);
1853 }
1854 
1855 /* ****************************************************** charsperline ***** */
1856 /*
1857  * Figure out how many lines our current terminal has. For more details again
1858  * please see the source of newfs(8), as this function is taken over almost
1859  * unchanged.
1860  */
1861 static int
1862 charsperline(void)
1863 {
1864 	DBG_FUNC("charsperline")
1865 	int	columns;
1866 	char	*cp;
1867 	struct winsize	ws;
1868 
1869 	DBG_ENTER;
1870 
1871 	columns = 0;
1872 	if (ioctl(0, TIOCGWINSZ, &ws) != -1) {
1873 		columns = ws.ws_col;
1874 	}
1875 	if (columns == 0 && (cp = getenv("COLUMNS"))) {
1876 		columns = atoi(cp);
1877 	}
1878 	if (columns == 0) {
1879 		columns = 80;	/* last resort */
1880 	}
1881 
1882 	DBG_LEAVE;
1883 	return columns;
1884 }
1885 
1886 /* ****************************************************** get_dev_size ***** */
1887 /*
1888  * Get the size of the partition if we can't figure it out from the disklabel,
1889  * e.g. from vinum volumes.
1890  */
1891 static void
1892 get_dev_size(int fd, int *size)
1893 {
1894    int sectorsize;
1895    off_t mediasize;
1896 
1897    if (ioctl(fd, DIOCGSECTORSIZE, &sectorsize) == -1)
1898         err(1,"DIOCGSECTORSIZE");
1899    if (ioctl(fd, DIOCGMEDIASIZE, &mediasize) == -1)
1900         err(1,"DIOCGMEDIASIZE");
1901 
1902    if (sectorsize <= 0)
1903        errx(1, "bogus sectorsize: %d", sectorsize);
1904 
1905    *size = mediasize / sectorsize;
1906 }
1907 
1908 /* ************************************************************** main ***** */
1909 /*
1910  * growfs(8)  is a utility which allows to increase the size of an existing
1911  * ufs file system. Currently this can only be done on unmounted file system.
1912  * It recognizes some command line options to specify the new desired size,
1913  * and it does some basic checkings. The old file system size is determined
1914  * and after some more checks like we can really access the new last block
1915  * on the disk etc. we calculate the new parameters for the superblock. After
1916  * having done this we just call growfs() which will do the work.  Before
1917  * we finish the only thing left is to update the disklabel.
1918  * We still have to provide support for snapshots. Therefore we first have to
1919  * understand what data structures are always replicated in the snapshot on
1920  * creation, for all other blocks we touch during our procedure, we have to
1921  * keep the old blocks unchanged somewhere available for the snapshots. If we
1922  * are lucky, then we only have to handle our blocks to be relocated in that
1923  * way.
1924  * Also we have to consider in what order we actually update the critical
1925  * data structures of the file system to make sure, that in case of a disaster
1926  * fsck(8) is still able to restore any lost data.
1927  * The foreseen last step then will be to provide for growing even mounted
1928  * file systems. There we have to extend the mount() system call to provide
1929  * userland access to the file system locking facility.
1930  */
1931 int
1932 main(int argc, char **argv)
1933 {
1934 	DBG_FUNC("main")
1935 	char	*device, *special, *cp;
1936 	char	ch;
1937 	unsigned int	size=0;
1938 	size_t	len;
1939 	unsigned int	Nflag=0;
1940 	int	ExpertFlag=0;
1941 	struct stat	st;
1942 	struct disklabel	*lp;
1943 	struct partition	*pp;
1944 	int	i,fsi,fso;
1945     u_int32_t p_size;
1946 	char	reply[5];
1947 #ifdef FSMAXSNAP
1948 	int	j;
1949 #endif /* FSMAXSNAP */
1950 
1951 	DBG_ENTER;
1952 
1953 	while((ch=getopt(argc, argv, "Ns:vy")) != -1) {
1954 		switch(ch) {
1955 		case 'N':
1956 			Nflag=1;
1957 			break;
1958 		case 's':
1959 			size=(size_t)atol(optarg);
1960 			if(size<1) {
1961 				usage();
1962 			}
1963 			break;
1964 		case 'v': /* for compatibility to newfs */
1965 			break;
1966 		case 'y':
1967 			ExpertFlag=1;
1968 			break;
1969 		case '?':
1970 			/* FALLTHROUGH */
1971 		default:
1972 			usage();
1973 		}
1974 	}
1975 	argc -= optind;
1976 	argv += optind;
1977 
1978 	if(argc != 1) {
1979 		usage();
1980 	}
1981 	device=*argv;
1982 
1983 	/*
1984 	 * Now try to guess the (raw)device name.
1985 	 */
1986 	if (0 == strrchr(device, '/')) {
1987 		/*
1988 		 * No path prefix was given, so try in that order:
1989 		 *     /dev/r%s
1990 		 *     /dev/%s
1991 		 *     /dev/vinum/r%s
1992 		 *     /dev/vinum/%s.
1993 		 *
1994 		 * FreeBSD now doesn't distinguish between raw and block
1995 		 * devices any longer, but it should still work this way.
1996 		 */
1997 		len=strlen(device)+strlen(_PATH_DEV)+2+strlen("vinum/");
1998 		special=(char *)malloc(len);
1999 		if(special == NULL) {
2000 			errx(1, "malloc failed");
2001 		}
2002 		snprintf(special, len, "%sr%s", _PATH_DEV, device);
2003 		if (stat(special, &st) == -1) {
2004 			snprintf(special, len, "%s%s", _PATH_DEV, device);
2005 			if (stat(special, &st) == -1) {
2006 				snprintf(special, len, "%svinum/r%s",
2007 				    _PATH_DEV, device);
2008 				if (stat(special, &st) == -1) {
2009 					/* For now this is the 'last resort' */
2010 					snprintf(special, len, "%svinum/%s",
2011 					    _PATH_DEV, device);
2012 				}
2013 			}
2014 		}
2015 		device = special;
2016 	}
2017 
2018 	/*
2019 	 * Try to access our devices for writing ...
2020 	 */
2021 	if (Nflag) {
2022 		fso = -1;
2023 	} else {
2024 		fso = open(device, O_WRONLY);
2025 		if (fso < 0) {
2026 			err(1, "%s", device);
2027 		}
2028 	}
2029 
2030 	/*
2031 	 * ... and reading.
2032 	 */
2033 	fsi = open(device, O_RDONLY);
2034 	if (fsi < 0) {
2035 		err(1, "%s", device);
2036 	}
2037 
2038 	/*
2039 	 * Try to read a label and guess the slice if not specified. This
2040 	 * code should guess the right thing and avoid to bother the user
2041 	 * with the task of specifying the option -v on vinum volumes.
2042 	 */
2043 	cp=device+strlen(device)-1;
2044 	lp = get_disklabel(fsi);
2045     if (lp != NULL) {
2046         if (isdigit(*cp)) {
2047             pp = &lp->d_partitions[2];
2048         } else if (*cp>='a' && *cp<='h') {
2049             pp = &lp->d_partitions[*cp - 'a'];
2050         } else {
2051             errx(1, "unknown device");
2052         }
2053         p_size = pp->p_size;
2054     } else {
2055         get_dev_size(fsi, &p_size);
2056     }
2057 
2058 	/*
2059 	 * Check if that partition is suitable for growing a file system.
2060 	 */
2061 	if (p_size < 1) {
2062 		errx(1, "partition is unavailable");
2063 	}
2064 
2065 	/*
2066 	 * Read the current superblock, and take a backup.
2067 	 */
2068 	for (i = 0; sblock_try[i] != -1; i++) {
2069 		sblockloc = sblock_try[i] / DEV_BSIZE;
2070 		rdfs(sblockloc, (size_t)SBLOCKSIZE, (void *)&(osblock), fsi);
2071 		if ((osblock.fs_magic == FS_UFS1_MAGIC ||
2072 		     (osblock.fs_magic == FS_UFS2_MAGIC &&
2073 		      osblock.fs_sblockloc == sblock_try[i])) &&
2074 		    osblock.fs_bsize <= MAXBSIZE &&
2075 		    osblock.fs_bsize >= sizeof(struct fs))
2076 			break;
2077 	}
2078 	if (sblock_try[i] == -1) {
2079 		errx(1, "superblock not recognized");
2080 	}
2081 	memcpy((void *)&fsun1, (void *)&fsun2, sizeof(fsun2));
2082 	maxino = sblock.fs_ncg * sblock.fs_ipg;
2083 
2084 	DBG_OPEN("/tmp/growfs.debug"); /* already here we need a superblock */
2085 	DBG_DUMP_FS(&sblock,
2086 	    "old sblock");
2087 
2088 	/*
2089 	 * Determine size to grow to. Default to the full size specified in
2090 	 * the disk label.
2091 	 */
2092 	sblock.fs_size = dbtofsb(&osblock, p_size);
2093 	if (size != 0) {
2094 		if (size > p_size){
2095 			errx(1, "There is not enough space (%d < %d)",
2096 			    p_size, size);
2097 		}
2098 		sblock.fs_size = dbtofsb(&osblock, size);
2099 	}
2100 
2101 	/*
2102 	 * Are we really growing ?
2103 	 */
2104 	if(osblock.fs_size >= sblock.fs_size) {
2105 		errx(1, "we are not growing (%d->%d)", osblock.fs_size,
2106 		    sblock.fs_size);
2107 	}
2108 
2109 
2110 #ifdef FSMAXSNAP
2111 	/*
2112 	 * Check if we find an active snapshot.
2113 	 */
2114 	if(ExpertFlag == 0) {
2115 		for(j=0; j<FSMAXSNAP; j++) {
2116 			if(sblock.fs_snapinum[j]) {
2117 				errx(1, "active snapshot found in file system\n"
2118 				    "	please remove all snapshots before "
2119 				    "using growfs\n");
2120 			}
2121 			if(!sblock.fs_snapinum[j]) { /* list is dense */
2122 				break;
2123 			}
2124 		}
2125 	}
2126 #endif
2127 
2128 	if (ExpertFlag == 0 && Nflag == 0) {
2129 		printf("We strongly recommend you to make a backup "
2130 		    "before growing the Filesystem\n\n"
2131 		    " Did you backup your data (Yes/No) ? ");
2132 		fgets(reply, (int)sizeof(reply), stdin);
2133 		if (strcmp(reply, "Yes\n")){
2134 			printf("\n Nothing done \n");
2135 			exit (0);
2136 		}
2137 	}
2138 
2139 	printf("new file systemsize is: %d frags\n", sblock.fs_size);
2140 
2141 	/*
2142 	 * Try to access our new last block in the file system. Even if we
2143 	 * later on realize we have to abort our operation, on that block
2144 	 * there should be no data, so we can't destroy something yet.
2145 	 */
2146 	wtfs((ufs2_daddr_t)p_size-1, (size_t)DEV_BSIZE, (void *)&sblock,
2147 	    fso, Nflag);
2148 
2149 	/*
2150 	 * Now calculate new superblock values and check for reasonable
2151 	 * bound for new file system size:
2152 	 *     fs_size:    is derived from label or user input
2153 	 *     fs_dsize:   should get updated in the routines creating or
2154 	 *                 updating the cylinder groups on the fly
2155 	 *     fs_cstotal: should get updated in the routines creating or
2156 	 *                 updating the cylinder groups
2157 	 */
2158 
2159 	/*
2160 	 * Update the number of cylinders and cylinder groups in the file system.
2161 	 */
2162 	if (sblock.fs_magic == FS_UFS1_MAGIC) {
2163 		sblock.fs_old_ncyl =
2164 		    sblock.fs_size * sblock.fs_old_nspf / sblock.fs_old_spc;
2165 		if (sblock.fs_size * sblock.fs_old_nspf >
2166 		    sblock.fs_old_ncyl * sblock.fs_old_spc)
2167 			sblock.fs_old_ncyl++;
2168 	}
2169 	sblock.fs_ncg = howmany(sblock.fs_size, sblock.fs_fpg);
2170 	maxino = sblock.fs_ncg * sblock.fs_ipg;
2171 
2172 	if (sblock.fs_size % sblock.fs_fpg != 0 &&
2173 	    sblock.fs_size % sblock.fs_fpg < cgdmin(&sblock, sblock.fs_ncg)) {
2174 		/*
2175 		 * The space in the new last cylinder group is too small,
2176 		 * so revert back.
2177 		 */
2178 		sblock.fs_ncg--;
2179 		if (sblock.fs_magic == FS_UFS1_MAGIC)
2180 			sblock.fs_old_ncyl = sblock.fs_ncg * sblock.fs_old_cpg;
2181 		printf("Warning: %d sector(s) cannot be allocated.\n",
2182 		    fsbtodb(&sblock, sblock.fs_size % sblock.fs_fpg));
2183 		sblock.fs_size = sblock.fs_ncg * sblock.fs_fpg;
2184 	}
2185 
2186 	/*
2187 	 * Update the space for the cylinder group summary information in the
2188 	 * respective cylinder group data area.
2189 	 */
2190 	sblock.fs_cssize =
2191 	    fragroundup(&sblock, sblock.fs_ncg * sizeof(struct csum));
2192 
2193 	if(osblock.fs_size >= sblock.fs_size) {
2194 		errx(1, "not enough new space");
2195 	}
2196 
2197 	DBG_PRINT0("sblock calculated\n");
2198 
2199 	/*
2200 	 * Ok, everything prepared, so now let's do the tricks.
2201 	 */
2202 	growfs(fsi, fso, Nflag);
2203 
2204 	/*
2205 	 * Update the disk label.
2206 	 */
2207     if (!unlabeled) {
2208         pp->p_fsize = sblock.fs_fsize;
2209         pp->p_frag = sblock.fs_frag;
2210         pp->p_cpg = sblock.fs_fpg;
2211 
2212         return_disklabel(fso, lp, Nflag);
2213         DBG_PRINT0("label rewritten\n");
2214     }
2215 
2216 	close(fsi);
2217 	if(fso>-1) close(fso);
2218 
2219 	DBG_CLOSE;
2220 
2221 	DBG_LEAVE;
2222 	return 0;
2223 }
2224 
2225 /* ************************************************** return_disklabel ***** */
2226 /*
2227  * Write the updated disklabel back to disk.
2228  */
2229 static void
2230 return_disklabel(int fd, struct disklabel *lp, unsigned int Nflag)
2231 {
2232 	DBG_FUNC("return_disklabel")
2233 	u_short	sum;
2234 	u_short	*ptr;
2235 
2236 	DBG_ENTER;
2237 
2238 	if(!lp) {
2239 		DBG_LEAVE;
2240 		return;
2241 	}
2242 	if(!Nflag) {
2243 		lp->d_checksum=0;
2244 		sum = 0;
2245 		ptr=(u_short *)lp;
2246 
2247 		/*
2248 		 * recalculate checksum
2249 		 */
2250 		while(ptr < (u_short *)&lp->d_partitions[lp->d_npartitions]) {
2251 			sum ^= *ptr++;
2252 		}
2253 		lp->d_checksum=sum;
2254 
2255 		if (ioctl(fd, DIOCWDINFO, (char *)lp) < 0) {
2256 			errx(1, "DIOCWDINFO failed");
2257 		}
2258 	}
2259 	free(lp);
2260 
2261 	DBG_LEAVE;
2262 	return ;
2263 }
2264 
2265 /* ***************************************************** get_disklabel ***** */
2266 /*
2267  * Read the disklabel from disk.
2268  */
2269 static struct disklabel *
2270 get_disklabel(int fd)
2271 {
2272 	DBG_FUNC("get_disklabel")
2273 	static struct	disklabel *lab;
2274 
2275 	DBG_ENTER;
2276 
2277 	lab=(struct disklabel *)malloc(sizeof(struct disklabel));
2278 	if (!lab)
2279 		errx(1, "malloc failed");
2280 
2281     if (!ioctl(fd, DIOCGDINFO, (char *)lab))
2282         return (lab);
2283 
2284     unlabeled++;
2285 
2286 	DBG_LEAVE;
2287 	return (NULL);
2288 }
2289 
2290 
2291 /* ************************************************************* usage ***** */
2292 /*
2293  * Dump a line of usage.
2294  */
2295 static void
2296 usage(void)
2297 {
2298 	DBG_FUNC("usage")
2299 
2300 	DBG_ENTER;
2301 
2302 	fprintf(stderr, "usage: growfs [-Ny] [-s size] special\n");
2303 
2304 	DBG_LEAVE;
2305 	exit(1);
2306 }
2307 
2308 /* *********************************************************** updclst ***** */
2309 /*
2310  * This updates most parameters and the bitmap related to cluster. We have to
2311  * assume that sblock, osblock, acg are set up.
2312  */
2313 static void
2314 updclst(int block)
2315 {
2316 	DBG_FUNC("updclst")
2317 	static int	lcs=0;
2318 
2319 	DBG_ENTER;
2320 
2321 	if(sblock.fs_contigsumsize < 1) { /* no clustering */
2322 		return;
2323 	}
2324 	/*
2325 	 * update cluster allocation map
2326 	 */
2327 	setbit(cg_clustersfree(&acg), block);
2328 
2329 	/*
2330 	 * update cluster summary table
2331 	 */
2332 	if(!lcs) {
2333 		/*
2334 		 * calculate size for the trailing cluster
2335 		 */
2336 		for(block--; lcs<sblock.fs_contigsumsize; block--, lcs++ ) {
2337 			if(isclr(cg_clustersfree(&acg), block)){
2338 				break;
2339 			}
2340 		}
2341 	}
2342 	if(lcs < sblock.fs_contigsumsize) {
2343 		if(lcs) {
2344 			cg_clustersum(&acg)[lcs]--;
2345 		}
2346 		lcs++;
2347 		cg_clustersum(&acg)[lcs]++;
2348 	}
2349 
2350 	DBG_LEAVE;
2351 	return;
2352 }
2353 
2354 /* *********************************************************** updrefs ***** */
2355 /*
2356  * This updates all references to relocated blocks for the given inode.  The
2357  * inode is given as number within the cylinder group, and the number of the
2358  * cylinder group.
2359  */
2360 static void
2361 updrefs(int cg, ino_t in, struct gfs_bpp *bp, int fsi, int fso, unsigned int
2362     Nflag)
2363 {
2364 	DBG_FUNC("updrefs")
2365 	ufs_lbn_t	len, lbn, numblks;
2366 	ufs2_daddr_t	iptr, blksperindir;
2367 	union dinode	*ino;
2368 	int		i, mode, remaining_blocks, inodeupdated;
2369 
2370 	DBG_ENTER;
2371 
2372 	/*
2373 	 * XXX We should skip unused inodes even from being read from disk
2374 	 *     here by using the bitmap.
2375 	 */
2376 	ino = ginode(in, fsi, cg);
2377 	mode = DIP(ino, di_mode) & IFMT;
2378 	if (mode != IFDIR && mode != IFREG && mode != IFLNK) {
2379 		DBG_LEAVE;
2380 		return; /* only check DIR, FILE, LINK */
2381 	}
2382 	if (mode == IFLNK && DIP(ino, di_size) < sblock.fs_maxsymlinklen) {
2383 		DBG_LEAVE;
2384 		return;	/* skip short symlinks */
2385 	}
2386 	numblks = howmany(DIP(ino, di_size), sblock.fs_bsize);
2387 	if (numblks == 0) {
2388 		DBG_LEAVE;
2389 		return;	/* skip empty file */
2390 	}
2391 	if (DIP(ino, di_blocks) == 0) {
2392 		DBG_LEAVE;
2393 		return;	/* skip empty swiss cheesy file or old fastlink */
2394 	}
2395 	DBG_PRINT2("scg checking inode (%d in %d)\n",
2396 	    in,
2397 	    cg);
2398 
2399 	/*
2400 	 * Check all the blocks.
2401 	 */
2402 	inodeupdated = 0;
2403 	len = numblks < NDADDR ? numblks : NDADDR;
2404 	for (i = 0; i < len; i++) {
2405 		iptr = DIP(ino, di_db[i]);
2406 		if (iptr == 0)
2407 			continue;
2408 		if (cond_bl_upd(&iptr, bp, fsi, fso, Nflag)) {
2409 			DIP(ino, di_db[i]) = iptr;
2410 			inodeupdated++;
2411 		}
2412 	}
2413 	DBG_PRINT0("~~scg direct blocks checked\n");
2414 
2415 	blksperindir = 1;
2416 	len = numblks - NDADDR;
2417 	lbn = NDADDR;
2418 	for (i = 0; len > 0 && i < NIADDR; i++) {
2419 		iptr = DIP(ino, di_ib[i]);
2420 		if (iptr == 0)
2421 			continue;
2422 		if (cond_bl_upd(&iptr, bp, fsi, fso, Nflag)) {
2423 			DIP(ino, di_ib[i]) = iptr;
2424 			inodeupdated++;
2425 		}
2426 		indirchk(blksperindir, lbn, iptr, numblks, bp, fsi, fso, Nflag);
2427 		blksperindir *= NINDIR(&sblock);
2428 		lbn += blksperindir;
2429 		len -= blksperindir;
2430 		DBG_PRINT1("scg indirect_%d blocks checked\n", i + 1);
2431 	}
2432 	if (inodeupdated)
2433 		wtfs(inoblk, sblock.fs_bsize, inobuf, fso, Nflag);
2434 
2435 	DBG_LEAVE;
2436 	return;
2437 }
2438 
2439 /*
2440  * Recursively check all the indirect blocks.
2441  */
2442 static void
2443 indirchk(ufs_lbn_t blksperindir, ufs_lbn_t lbn, ufs2_daddr_t blkno,
2444     ufs_lbn_t lastlbn, struct gfs_bpp *bp, int fsi, int fso, unsigned int Nflag)
2445 {
2446 	DBG_FUNC("indirchk")
2447 	void *ibuf;
2448 	off_t offset;
2449 	int i, last;
2450 	ufs2_daddr_t iptr;
2451 
2452 	DBG_ENTER;
2453 
2454 	/* read in the indirect block. */
2455 	ibuf = malloc(sblock.fs_bsize);
2456 	if (!ibuf)
2457 		errx(1, "malloc failed");
2458 	rdfs(fsbtodb(&sblock, blkno), (size_t)sblock.fs_bsize, ibuf, fsi);
2459 	last = howmany(lastlbn - lbn, blksperindir) < NINDIR(&sblock) ?
2460 	    howmany(lastlbn - lbn, blksperindir) : NINDIR(&sblock);
2461 	for (i = 0; i < last; i++) {
2462 		if (sblock.fs_magic == FS_UFS1_MAGIC)
2463 			iptr = ((ufs1_daddr_t *)ibuf)[i];
2464 		else
2465 			iptr = ((ufs2_daddr_t *)ibuf)[i];
2466 		if (iptr == 0)
2467 			continue;
2468 		if (cond_bl_upd(&iptr, bp, fsi, fso, Nflag)) {
2469 			if (sblock.fs_magic == FS_UFS1_MAGIC)
2470 				((ufs1_daddr_t *)ibuf)[i] = iptr;
2471 			else
2472 				((ufs2_daddr_t *)ibuf)[i] = iptr;
2473 		}
2474 		if (blksperindir == 1)
2475 			continue;
2476 		indirchk(blksperindir / NINDIR(&sblock), lbn + blksperindir * i,
2477 		    iptr, lastlbn, bp, fsi, fso, Nflag);
2478 	}
2479 	free(ibuf);
2480 
2481 	DBG_LEAVE;
2482 	return;
2483 }
2484