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