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