Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 23 Jun 2012 19:03:42 +0000 (UTC)
From:      Edward Tomasz Napierala <trasz@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org
Subject:   svn commit: r237499 - stable/9/sbin/growfs
Message-ID:  <201206231903.q5NJ3gxf058971@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: trasz
Date: Sat Jun 23 19:03:42 2012
New Revision: 237499
URL: http://svn.freebsd.org/changeset/base/237499

Log:
  MFC r234178:
  
  Remove block reallocation used to make room for the cylinder group
  summary structure.  From now on, when there is no room for it,
  we simply allocate new one in a newly added cylinder group.
  
  This patch removes a conditional in updcsloc(), reindents some code
  there, and removes unused routines.  I decided to do it this way instead
  of disabling reallocation when the filesystem is live and leaving it
  as it is otherwise, because this allows for removal of lots of complicated
  and hard to test code.  Also, conditionally disabling it would result
  in a different layout in filesystems resized online and offline, which
  would look somewhat weird.
  
  Reviewed by:            mckusick
  No objections from:     kib
  Sponsored by:           The FreeBSD Foundation

Modified:
  stable/9/sbin/growfs/growfs.c
Directory Properties:
  stable/9/sbin/growfs/   (props changed)

Modified: stable/9/sbin/growfs/growfs.c
==============================================================================
--- stable/9/sbin/growfs/growfs.c	Sat Jun 23 19:01:42 2012	(r237498)
+++ stable/9/sbin/growfs/growfs.c	Sat Jun 23 19:03:42 2012	(r237499)
@@ -94,45 +94,11 @@ static union {
 #define	acg	cgun1.cg	/* a cylinder cgroup (new) */
 #define	aocg	cgun2.cg	/* an old cylinder group */
 
-static char	ablk[MAXBSIZE];	/* a block */
-
 static struct csum	*fscs;	/* cylinder summary */
 
-union dinode {
-	struct ufs1_dinode dp1;
-	struct ufs2_dinode dp2;
-};
-#define	DIP(dp, field) \
-	((sblock.fs_magic == FS_UFS1_MAGIC) ? \
-	(uint32_t)(dp)->dp1.field : (dp)->dp2.field)
-#define	DIP_SET(dp, field, val) do { \
-	if (sblock.fs_magic == FS_UFS1_MAGIC) \
-		(dp)->dp1.field = (val); \
-	else \
-		(dp)->dp2.field = (val); \
-	} while (0)
-static ufs2_daddr_t 	inoblk;			/* inode block address */
-static char		inobuf[MAXBSIZE];	/* inode block */
-static ino_t		maxino;			/* last valid inode */
-
-/*
- * An array of elements of type struct gfs_bpp describes all blocks to
- * be relocated in order to free the space needed for the cylinder group
- * summary for all cylinder groups located in the first cylinder group.
- */
-struct gfs_bpp {
-	ufs2_daddr_t	old;		/* old block number */
-	ufs2_daddr_t	new;		/* new block number */
-#define GFS_FL_FIRST	1
-#define GFS_FL_LAST	2
-	unsigned int	flags;	/* special handling required */
-	int		found;	/* how many references were updated */
-};
-
 static void	growfs(int, int, unsigned int);
 static void	rdfs(ufs2_daddr_t, size_t, void *, int);
 static void	wtfs(ufs2_daddr_t, size_t, void *, int, unsigned int);
-static ufs2_daddr_t alloc(void);
 static int	charsperline(void);
 static void	usage(void);
 static int	isblock(struct fs *, unsigned char *, int);
@@ -141,14 +107,8 @@ static void	setblock(struct fs *, unsign
 static void	initcg(int, time_t, int, unsigned int);
 static void	updjcg(int, time_t, int, int, unsigned int);
 static void	updcsloc(time_t, int, int, unsigned int);
-static union dinode *ginode(ino_t, int, int);
 static void	frag_adjust(ufs2_daddr_t, int);
-static int	cond_bl_upd(ufs2_daddr_t *, struct gfs_bpp *, int, int,
-		    unsigned int);
 static void	updclst(int);
-static void	updrefs(int, ino_t, struct gfs_bpp *, int, int, unsigned int);
-static void	indirchk(ufs_lbn_t, ufs_lbn_t, ufs2_daddr_t, ufs_lbn_t,
-		    struct gfs_bpp *, int, int, unsigned int);
 static void	get_dev_size(int, int *);
 
 /*
@@ -587,64 +547,6 @@ frag_adjust(ufs2_daddr_t frag, int sign)
 }
 
 /*
- * Here we conditionally update a pointer to a fragment. We check for all
- * relocated blocks if any of its fragments is referenced by the current
- * field, and update the pointer to the respective fragment in our new
- * block.  If we find a reference we write back the block immediately,
- * as there is no easy way for our general block reading engine to figure
- * out if a write back operation is needed.
- */
-static int
-cond_bl_upd(ufs2_daddr_t *block, struct gfs_bpp *field, int fsi, int fso,
-    unsigned int Nflag)
-{
-	DBG_FUNC("cond_bl_upd")
-	struct gfs_bpp *f;
-	ufs2_daddr_t src, dst;
-	int fragnum;
-	void *ibuf;
-
-	DBG_ENTER;
-
-	for (f = field; f->old != 0; f++) {
-		src = *block;
-		if (fragstoblks(&sblock, src) != f->old)
-			continue;
-		/*
-		 * The fragment is part of the block, so update.
-		 */
-		dst = blkstofrags(&sblock, f->new);
-		fragnum = fragnum(&sblock, src);
-		*block = dst + fragnum;
-		f->found++;
-		DBG_PRINT3("scg (%jd->%jd)[%d] reference updated\n",
-		    (intmax_t)f->old, (intmax_t)f->new, fragnum);
-
-		/*
-		 * Copy the block back immediately.
-		 *
-		 * XXX	If src is from an indirect block we have
-		 *	to implement copy on write here in case of
-		 *	active snapshots.
-		 */
-		ibuf = malloc(sblock.fs_bsize);
-		if (!ibuf)
-			errx(1, "malloc failed");
-		src -= fragnum;
-		rdfs(fsbtodb(&sblock, src), (size_t)sblock.fs_bsize, ibuf, fsi);
-		wtfs(dst, (size_t)sblock.fs_bsize, ibuf, fso, Nflag);
-		free(ibuf);
-		/*
-		 * The same block can't be found again in this loop.
-		 */
-		return (1);
-	}
-
-	DBG_LEAVE;
-	return (0);
-}
-
-/*
  * Here we do all needed work for the former last cylinder group. It has to be
  * changed in any case, even if the file system ended exactly on the end of
  * this group, as there is some slightly inconsistent handling of the number
@@ -890,11 +792,8 @@ updjcg(int cylno, time_t modtime, int fs
  *	longer in the beginning of the first cylinder group you should never
  *	use a version of fsck which is not aware of the possibility to have
  *	this structure in a non standard place.
- * Option (1) is considered to be less intrusive to the structure of the file-
- * system. So we try to stick to that whenever possible. If there is not enough
- * space in the cylinder group containing the cylinder summary we have to use
- * method (2). In case of active snapshots in the file system we probably can
- * completely avoid implementing copy on write if we stick to method (2) only.
+ * Option (2) is considered to be less intrusive to the structure of the file-
+ * system, so that's the one being used.
  */
 static void
 updcsloc(time_t modtime, int fsi, int fso, unsigned int Nflag)
@@ -903,11 +802,7 @@ updcsloc(time_t modtime, int fsi, int fs
 	struct csum *cs;
 	int ocscg, ncscg;
 	int blocks;
-	ufs2_daddr_t cbase, dupper, odupper, d, f, g;
-	int ind, inc;
-	uint cylno;
-	struct gfs_bpp *bp;
-	int i, l;
+	ufs2_daddr_t d;
 	int lcs = 0;
 	int block;
 
@@ -951,117 +846,86 @@ updcsloc(time_t modtime, int fsi, int fs
 	 *	also up to 8*3 blocks for indirect blocks for all possible
 	 *	references.
 	 */
-	if (/*((int)sblock.fs_time&0x3)>0||*/ cs->cs_nbfree < blocks) {
-		/*
-		 * There is not enough space in the old cylinder group to
-		 * relocate all blocks as needed, so we relocate the whole
-		 * cylinder group summary to a new group. We try to use the
-		 * first complete new cylinder group just created. Within the
-		 * cylinder group we align the area immediately after the
-		 * cylinder group information location in order to be as
-		 * close as possible to the original implementation of ffs.
-		 *
-		 * First we have to make sure we'll find enough space in the
-		 * new cylinder group. If not, then we currently give up.
-		 * We start with freeing everything which was used by the
-		 * fragments of the old cylinder summary in the current group.
-		 * Now we write back the group meta data, read in the needed
-		 * meta data from the new cylinder group, and start allocating
-		 * within that group. Here we can assume, the group to be
-		 * completely empty. Which makes the handling of fragments and
-		 * clusters a lot easier.
-		 */
-		DBG_TRC;
-		if (sblock.fs_ncg - osblock.fs_ncg < 2)
-			errx(2, "panic: not enough space");
+	/*
+	 * There is not enough space in the old cylinder group to
+	 * relocate all blocks as needed, so we relocate the whole
+	 * cylinder group summary to a new group. We try to use the
+	 * first complete new cylinder group just created. Within the
+	 * cylinder group we align the area immediately after the
+	 * cylinder group information location in order to be as
+	 * close as possible to the original implementation of ffs.
+	 *
+	 * First we have to make sure we'll find enough space in the
+	 * new cylinder group. If not, then we currently give up.
+	 * We start with freeing everything which was used by the
+	 * fragments of the old cylinder summary in the current group.
+	 * Now we write back the group meta data, read in the needed
+	 * meta data from the new cylinder group, and start allocating
+	 * within that group. Here we can assume, the group to be
+	 * completely empty. Which makes the handling of fragments and
+	 * clusters a lot easier.
+	 */
+	DBG_TRC;
+	if (sblock.fs_ncg - osblock.fs_ncg < 2)
+		errx(2, "panic: not enough space");
 
-		/*
-		 * Point "d" to the first fragment not used by the cylinder
-		 * summary.
-		 */
-		d = osblock.fs_csaddr + (osblock.fs_cssize / osblock.fs_fsize);
+	/*
+	 * Point "d" to the first fragment not used by the cylinder
+	 * summary.
+	 */
+	d = osblock.fs_csaddr + (osblock.fs_cssize / osblock.fs_fsize);
 
-		/*
-		 * Set up last cluster size ("lcs") already here. Calculate
-		 * the size for the trailing cluster just behind where "d"
-		 * points to.
-		 */
-		if (sblock.fs_contigsumsize > 0) {
-			for (block = howmany(d % sblock.fs_fpg, sblock.fs_frag),
-			    lcs = 0; lcs < sblock.fs_contigsumsize;
-			    block++, lcs++) {
-				if (isclr(cg_clustersfree(&acg), block))
-					break;
-			}
+	/*
+	 * Set up last cluster size ("lcs") already here. Calculate
+	 * the size for the trailing cluster just behind where "d"
+	 * points to.
+	 */
+	if (sblock.fs_contigsumsize > 0) {
+		for (block = howmany(d % sblock.fs_fpg, sblock.fs_frag),
+		    lcs = 0; lcs < sblock.fs_contigsumsize;
+		    block++, lcs++) {
+			if (isclr(cg_clustersfree(&acg), block))
+				break;
 		}
+	}
 
+	/*
+	 * Point "d" to the last frag used by the cylinder summary.
+	 */
+	d--;
+
+	DBG_PRINT1("d=%jd\n", (intmax_t)d);
+	if ((d + 1) % sblock.fs_frag) {
 		/*
-		 * Point "d" to the last frag used by the cylinder summary.
+		 * The end of the cylinder summary is not a complete
+		 * block.
 		 */
-		d--;
-
-		DBG_PRINT1("d=%jd\n", (intmax_t)d);
-		if ((d + 1) % sblock.fs_frag) {
-			/*
-			 * The end of the cylinder summary is not a complete
-			 * block.
-			 */
-			DBG_TRC;
-			frag_adjust(d % sblock.fs_fpg, -1);
-			for (; (d + 1) % sblock.fs_frag; d--) {
-				DBG_PRINT1("d=%jd\n", (intmax_t)d);
-				setbit(cg_blksfree(&acg), d % sblock.fs_fpg);
-				acg.cg_cs.cs_nffree++;
-				sblock.fs_cstotal.cs_nffree++;
-			}
-			/*
-			 * Point "d" to the last fragment of the last
-			 * (incomplete) block of the cylinder summary.
-			 */
-			d++;
-			frag_adjust(d%sblock.fs_fpg, 1);
-
-			if (isblock(&sblock, cg_blksfree(&acg),
-			    (d % sblock.fs_fpg) / sblock.fs_frag)) {
-				DBG_PRINT1("d=%jd\n", (intmax_t)d);
-				acg.cg_cs.cs_nffree -= sblock.fs_frag;
-				acg.cg_cs.cs_nbfree++;
-				sblock.fs_cstotal.cs_nffree -= sblock.fs_frag;
-				sblock.fs_cstotal.cs_nbfree++;
-				if (sblock.fs_contigsumsize > 0) {
-					setbit(cg_clustersfree(&acg),
-					    (d % sblock.fs_fpg) /
-					    sblock.fs_frag);
-					if (lcs < sblock.fs_contigsumsize) {
-						if (lcs)
-							cg_clustersum(&acg)[lcs]--;
-						lcs++;
-						cg_clustersum(&acg)[lcs]++;
-					}
-				}
-			}
-			/*
-			 * Point "d" to the first fragment of the block before
-			 * the last incomplete block.
-			 */
-			d--;
+		DBG_TRC;
+		frag_adjust(d % sblock.fs_fpg, -1);
+		for (; (d + 1) % sblock.fs_frag; d--) {
+			DBG_PRINT1("d=%jd\n", (intmax_t)d);
+			setbit(cg_blksfree(&acg), d % sblock.fs_fpg);
+			acg.cg_cs.cs_nffree++;
+			sblock.fs_cstotal.cs_nffree++;
 		}
+		/*
+		 * Point "d" to the last fragment of the last
+		 * (incomplete) block of the cylinder summary.
+		 */
+		d++;
+		frag_adjust(d%sblock.fs_fpg, 1);
 
-		DBG_PRINT1("d=%jd\n", (intmax_t)d);
-		for (d = rounddown(d, sblock.fs_frag); d >= osblock.fs_csaddr;
-		    d -= sblock.fs_frag) {
-			DBG_TRC;
+		if (isblock(&sblock, cg_blksfree(&acg),
+		    (d % sblock.fs_fpg) / sblock.fs_frag)) {
 			DBG_PRINT1("d=%jd\n", (intmax_t)d);
-			setblock(&sblock, cg_blksfree(&acg),
-			    (d % sblock.fs_fpg) / sblock.fs_frag);
+			acg.cg_cs.cs_nffree -= sblock.fs_frag;
 			acg.cg_cs.cs_nbfree++;
+			sblock.fs_cstotal.cs_nffree -= sblock.fs_frag;
 			sblock.fs_cstotal.cs_nbfree++;
 			if (sblock.fs_contigsumsize > 0) {
 				setbit(cg_clustersfree(&acg),
-				    (d % sblock.fs_fpg) / sblock.fs_frag);
-				/*
-				 * The last cluster size is already set up.
-				 */
+				    (d % sblock.fs_fpg) /
+				    sblock.fs_frag);
 				if (lcs < sblock.fs_contigsumsize) {
 					if (lcs)
 						cg_clustersum(&acg)[lcs]--;
@@ -1070,392 +934,138 @@ updcsloc(time_t modtime, int fsi, int fs
 				}
 			}
 		}
-		*cs = acg.cg_cs;
-
 		/*
-		 * Now write the former cylinder group containing the cylinder
-		 * summary back to disk.
+		 * Point "d" to the first fragment of the block before
+		 * the last incomplete block.
 		 */
-		wtfs(fsbtodb(&sblock, cgtod(&sblock, ocscg)),
-		    (size_t)sblock.fs_cgsize, (void *)&acg, fso, Nflag);
-		DBG_PRINT0("oscg written\n");
-		DBG_DUMP_CG(&sblock, "old summary cg", &acg);
-
-		/*
-		 * Find the beginning of the new cylinder group containing the
-		 * cylinder summary.
-		 */
-		sblock.fs_csaddr = cgdmin(&sblock, osblock.fs_ncg);
-		ncscg = dtog(&sblock, sblock.fs_csaddr);
-		cs = fscs + ncscg;
-
-		/*
-		 * If Nflag is specified, we would now read random data instead
-		 * of an empty cg structure from disk. So we can't simulate that
-		 * part for now.
-		 */
-		if (Nflag) {
-			DBG_PRINT0("nscg update skipped\n");
-			DBG_LEAVE;
-			return;
-		}
-
-		/*
-		 * Read the future cylinder group containing the cylinder
-		 * summary from disk, and make a copy.
-		 */
-		rdfs(fsbtodb(&sblock, cgtod(&sblock, ncscg)),
-		    (size_t)sblock.fs_cgsize, (void *)&aocg, fsi);
-		DBG_PRINT0("nscg read\n");
-		DBG_DUMP_CG(&sblock, "new summary cg", &aocg);
-
-		memcpy((void *)&cgun1, (void *)&cgun2, sizeof(cgun2));
+		d--;
+	}
 
-		/*
-		 * Allocate all complete blocks used by the new cylinder
-		 * summary.
-		 */
-		for (d = sblock.fs_csaddr; d + sblock.fs_frag <=
-		    sblock.fs_csaddr + (sblock.fs_cssize / sblock.fs_fsize);
-		    d += sblock.fs_frag) {
-			clrblock(&sblock, cg_blksfree(&acg),
+	DBG_PRINT1("d=%jd\n", (intmax_t)d);
+	for (d = rounddown(d, sblock.fs_frag); d >= osblock.fs_csaddr;
+	    d -= sblock.fs_frag) {
+		DBG_TRC;
+		DBG_PRINT1("d=%jd\n", (intmax_t)d);
+		setblock(&sblock, cg_blksfree(&acg),
+		    (d % sblock.fs_fpg) / sblock.fs_frag);
+		acg.cg_cs.cs_nbfree++;
+		sblock.fs_cstotal.cs_nbfree++;
+		if (sblock.fs_contigsumsize > 0) {
+			setbit(cg_clustersfree(&acg),
 			    (d % sblock.fs_fpg) / sblock.fs_frag);
-			acg.cg_cs.cs_nbfree--;
-			sblock.fs_cstotal.cs_nbfree--;
-			if (sblock.fs_contigsumsize > 0) {
-				clrbit(cg_clustersfree(&acg),
-				    (d % sblock.fs_fpg) / sblock.fs_frag);
-			}
-		}
-
-		/*
-		 * Allocate all fragments used by the cylinder summary in the
-		 * last block.
-		 */
-		if (d <
-		    sblock.fs_csaddr + (sblock.fs_cssize / sblock.fs_fsize)) {
-			for (; d - sblock.fs_csaddr <
-			    sblock.fs_cssize/sblock.fs_fsize; d++) {
-				clrbit(cg_blksfree(&acg), d % sblock.fs_fpg);
-				acg.cg_cs.cs_nffree--;
-				sblock.fs_cstotal.cs_nffree--;
+			/*
+			 * The last cluster size is already set up.
+			 */
+			if (lcs < sblock.fs_contigsumsize) {
+				if (lcs)
+					cg_clustersum(&acg)[lcs]--;
+				lcs++;
+				cg_clustersum(&acg)[lcs]++;
 			}
-			acg.cg_cs.cs_nbfree--;
-			acg.cg_cs.cs_nffree += sblock.fs_frag;
-			sblock.fs_cstotal.cs_nbfree--;
-			sblock.fs_cstotal.cs_nffree += sblock.fs_frag;
-			if (sblock.fs_contigsumsize > 0)
-				clrbit(cg_clustersfree(&acg),
-				    (d % sblock.fs_fpg) / sblock.fs_frag);
-
-			frag_adjust(d % sblock.fs_fpg, 1);
 		}
-		/*
-		 * XXX	Handle the cluster statistics here in the case this
-		 *	cylinder group is now almost full, and the remaining
-		 *	space is less then the maximum cluster size. This is
-		 *	probably not needed, as you would hardly find a file
-		 *	system which has only MAXCSBUFS+FS_MAXCONTIG of free
-		 *	space right behind the cylinder group information in
-		 *	any new cylinder group.
-		 */
-
-		/*
-		 * Update our statistics in the cylinder summary.
-		 */
-		*cs = acg.cg_cs;
-
-		/*
-		 * Write the new cylinder group containing the cylinder summary
-		 * back to disk.
-		 */
-		wtfs(fsbtodb(&sblock, cgtod(&sblock, ncscg)),
-		    (size_t)sblock.fs_cgsize, (void *)&acg, fso, Nflag);
-		DBG_PRINT0("nscg written\n");
-		DBG_DUMP_CG(&sblock, "new summary cg", &acg);
-
-		DBG_LEAVE;
-		return;
 	}
-	/*
-	 * We have got enough of space in the current cylinder group, so we
-	 * can relocate just a few blocks, and let the summary information
-	 * grow in place where it is right now.
-	 */
-	DBG_TRC;
-
-	cbase = cgbase(&osblock, ocscg);	/* old and new are equal */
-	dupper = sblock.fs_csaddr - cbase +
-	    howmany(sblock.fs_cssize, sblock.fs_fsize);
-	odupper = osblock.fs_csaddr - cbase +
-	    howmany(osblock.fs_cssize, osblock.fs_fsize);
-
-	sblock.fs_dsize -= dupper - odupper;
+	*cs = acg.cg_cs;
 
 	/*
-	 * Allocate the space for the array of blocks to be relocated.
+	 * Now write the former cylinder group containing the cylinder
+	 * summary back to disk.
 	 */
-	bp = (struct gfs_bpp *)malloc(((dupper - odupper) /
-	    sblock.fs_frag + 2) * sizeof(struct gfs_bpp));
-	if (bp == NULL)
-		errx(1, "malloc failed");
-	memset((char *)bp, 0, ((dupper - odupper) / sblock.fs_frag + 2) *
-	    sizeof(struct gfs_bpp));
+	wtfs(fsbtodb(&sblock, cgtod(&sblock, ocscg)),
+	    (size_t)sblock.fs_cgsize, (void *)&acg, fso, Nflag);
+	DBG_PRINT0("oscg written\n");
+	DBG_DUMP_CG(&sblock, "old summary cg", &acg);
 
 	/*
-	 * Lock all new frags needed for the cylinder group summary. This is
-	 * done per fragment in the first and last block of the new required
-	 * area, and per block for all other blocks.
-	 *
-	 * Handle the first new block here (but only if some fragments where
-	 * already used for the cylinder summary).
+	 * Find the beginning of the new cylinder group containing the
+	 * cylinder summary.
 	 */
-	ind = 0;
-	frag_adjust(odupper, -1);
-	for (d = odupper; ((d < dupper) && (d % sblock.fs_frag)); d++) {
-		DBG_PRINT1("scg first frag check loop d=%jd\n", (intmax_t)d);
-		if (isclr(cg_blksfree(&acg), d)) {
-			if (!ind) {
-				bp[ind].old = d / sblock.fs_frag;
-				bp[ind].flags |= GFS_FL_FIRST;
-				if (roundup(d, sblock.fs_frag) >= dupper)
-					bp[ind].flags |= GFS_FL_LAST;
-				ind++;
-			}
-		} else {
-			clrbit(cg_blksfree(&acg), d);
-			acg.cg_cs.cs_nffree--;
-			sblock.fs_cstotal.cs_nffree--;
-		}
-		/*
-		 * No cluster handling is needed here, as there was at least
-		 * one fragment in use by the cylinder summary in the old
-		 * file system.
-		 * No block-free counter handling here as this block was not
-		 * a free block.
-		 */
-	}
-	frag_adjust(odupper, 1);
+	sblock.fs_csaddr = cgdmin(&sblock, osblock.fs_ncg);
+	ncscg = dtog(&sblock, sblock.fs_csaddr);
+	cs = fscs + ncscg;
 
 	/*
-	 * Handle all needed complete blocks here.
+	 * If Nflag is specified, we would now read random data instead
+	 * of an empty cg structure from disk. So we can't simulate that
+	 * part for now.
 	 */
-	for (; d + sblock.fs_frag <= dupper; d += sblock.fs_frag) {
-		DBG_PRINT1("scg block check loop d=%jd\n", (intmax_t)d);
-		if (!isblock(&sblock, cg_blksfree(&acg), d / sblock.fs_frag)) {
-			for (f = d; f < d + sblock.fs_frag; f++) {
-				if (isset(cg_blksfree(&aocg), f)) {
-					acg.cg_cs.cs_nffree--;
-					sblock.fs_cstotal.cs_nffree--;
-				}
-			}
-			clrblock(&sblock, cg_blksfree(&acg), d / sblock.fs_frag);
-			bp[ind].old = d / sblock.fs_frag;
-			ind++;
-		} else {
-			clrblock(&sblock, cg_blksfree(&acg), d / sblock.fs_frag);
-			acg.cg_cs.cs_nbfree--;
-			sblock.fs_cstotal.cs_nbfree--;
-			if (sblock.fs_contigsumsize > 0) {
-				clrbit(cg_clustersfree(&acg), d / sblock.fs_frag);
-				for (lcs = 0, l = (d / sblock.fs_frag) + 1;
-				    lcs < sblock.fs_contigsumsize; l++, lcs++ ) {
-					if (isclr(cg_clustersfree(&acg), l))
-						break;
-				}
-				if (lcs < sblock.fs_contigsumsize) {
-					cg_clustersum(&acg)[lcs + 1]--;
-					if (lcs)
-						cg_clustersum(&acg)[lcs]++;
-				}
-			}
-		}
-		/*
-		 * No fragment counter handling is needed here, as this finally
-		 * doesn't change after the relocation.
-		 */
+	if (Nflag) {
+		DBG_PRINT0("nscg update skipped\n");
+		DBG_LEAVE;
+		return;
 	}
 
 	/*
-	 * Handle all fragments needed in the last new affected block.
+	 * Read the future cylinder group containing the cylinder
+	 * summary from disk, and make a copy.
 	 */
-	if (d < dupper) {
-		frag_adjust(dupper - 1, -1);
+	rdfs(fsbtodb(&sblock, cgtod(&sblock, ncscg)),
+	    (size_t)sblock.fs_cgsize, (void *)&aocg, fsi);
+	DBG_PRINT0("nscg read\n");
+	DBG_DUMP_CG(&sblock, "new summary cg", &aocg);
 
-		if (isblock(&sblock, cg_blksfree(&acg), d / sblock.fs_frag)) {
-			acg.cg_cs.cs_nbfree--;
-			sblock.fs_cstotal.cs_nbfree--;
-			acg.cg_cs.cs_nffree += sblock.fs_frag;
-			sblock.fs_cstotal.cs_nffree += sblock.fs_frag;
-			if (sblock.fs_contigsumsize > 0) {
-				clrbit(cg_clustersfree(&acg), d / sblock.fs_frag);
-				for (lcs = 0, l =(d / sblock.fs_frag) + 1;
-				    lcs < sblock.fs_contigsumsize; l++, lcs++ ) {
-					if (isclr(cg_clustersfree(&acg),l))
-						break;
-				}
-				if (lcs < sblock.fs_contigsumsize) {
-					cg_clustersum(&acg)[lcs + 1]--;
-					if (lcs)
-						cg_clustersum(&acg)[lcs]++;
-				}
-			}
-		}
+	memcpy((void *)&cgun1, (void *)&cgun2, sizeof(cgun2));
 
-		for (; d < dupper; d++) {
-			DBG_PRINT1("scg second frag check loop d=%jd\n",
-			    (intmax_t)d);
-			if (isclr(cg_blksfree(&acg), d)) {
-				bp[ind].old = d / sblock.fs_frag;
-				bp[ind].flags |= GFS_FL_LAST;
-			} else {
-				clrbit(cg_blksfree(&acg), d);
-				acg.cg_cs.cs_nffree--;
-				sblock.fs_cstotal.cs_nffree--;
-			}
+	/*
+	 * Allocate all complete blocks used by the new cylinder
+	 * summary.
+	 */
+	for (d = sblock.fs_csaddr; d + sblock.fs_frag <=
+	    sblock.fs_csaddr + (sblock.fs_cssize / sblock.fs_fsize);
+	    d += sblock.fs_frag) {
+		clrblock(&sblock, cg_blksfree(&acg),
+		    (d % sblock.fs_fpg) / sblock.fs_frag);
+		acg.cg_cs.cs_nbfree--;
+		sblock.fs_cstotal.cs_nbfree--;
+		if (sblock.fs_contigsumsize > 0) {
+			clrbit(cg_clustersfree(&acg),
+			    (d % sblock.fs_fpg) / sblock.fs_frag);
 		}
-		if (bp[ind].flags & GFS_FL_LAST) /* we have to advance here */
-			ind++;
-		frag_adjust(dupper - 1, 1);
 	}
 
 	/*
-	 * If we found a block to relocate just do so.
+	 * Allocate all fragments used by the cylinder summary in the
+	 * last block.
 	 */
-	if (ind) {
-		for (i = 0; i < ind; i++) {
-			if (!bp[i].old) { /* no more blocks listed */
-				/*
-				 * XXX	A relative blocknumber should not be
-				 *	zero, which is not explicitly
-				 *	guaranteed by our code.
-				 */
-				break;
-			}
-			/*
-			 * Allocate a complete block in the same (current)
-			 * cylinder group.
-			 */
-			bp[i].new = alloc() / sblock.fs_frag;
-
-			/*
-			 * There is no frag_adjust() needed for the new block
-			 * as it will have no fragments yet :-).
-			 */
-			for (f = bp[i].old * sblock.fs_frag,
-			    g = bp[i].new * sblock.fs_frag;
-			    f < (bp[i].old + 1) * sblock.fs_frag;
-			    f++, g++) {
-				if (isset(cg_blksfree(&aocg), f)) {
-					setbit(cg_blksfree(&acg), g);
-					acg.cg_cs.cs_nffree++;
-					sblock.fs_cstotal.cs_nffree++;
-				}
-			}
-
-			/*
-			 * Special handling is required if this was the first
-			 * block. We have to consider the fragments which were
-			 * used by the cylinder summary in the original block
-			 * which re to be free in the copy of our block.  We
-			 * have to be careful if this first block happens to
-			 * be also the last block to be relocated.
-			 */
-			if (bp[i].flags & GFS_FL_FIRST) {
-				for (f = bp[i].old * sblock.fs_frag,
-				    g =bp[i].new * sblock.fs_frag;
-				    f < odupper; f++, g++) {
-					setbit(cg_blksfree(&acg), g);
-					acg.cg_cs.cs_nffree++;
-					sblock.fs_cstotal.cs_nffree++;
-				}
-				if (!(bp[i].flags & GFS_FL_LAST))
-					frag_adjust(bp[i].new * sblock.fs_frag, 1);
-			}
-
-			/*
-			 * Special handling is required if this is the last
-			 * block to be relocated.
-			 */
-			if (bp[i].flags & GFS_FL_LAST) {
-				frag_adjust(bp[i].new * sblock.fs_frag, 1);
-				frag_adjust(bp[i].old * sblock.fs_frag, -1);
-				for (f = dupper;
-				    f < roundup(dupper, sblock.fs_frag); f++) {
-					if (isclr(cg_blksfree(&acg), f)) {
-						setbit(cg_blksfree(&acg), f);
-						acg.cg_cs.cs_nffree++;
-						sblock.fs_cstotal.cs_nffree++;
-					}
-				}
-				frag_adjust(bp[i].old * sblock.fs_frag, 1);
-			}
-
-			/*
-			 * !!! Attach the cylindergroup offset here.
-			 */
-			bp[i].old += cbase / sblock.fs_frag;
-			bp[i].new += cbase / sblock.fs_frag;
-
-			/*
-			 * Copy the content of the block.
-			 */
-			/*
-			 * XXX	Here we will have to implement a copy on write
-			 *	in the case we have any active snapshots.
-			 */
-			rdfs(fsbtodb(&sblock, bp[i].old * sblock.fs_frag),
-			    (size_t)sblock.fs_bsize, (void *)&ablk, fsi);
-			wtfs(fsbtodb(&sblock, bp[i].new * sblock.fs_frag),
-			    (size_t)sblock.fs_bsize, (void *)&ablk, fso, Nflag);
-			DBG_DUMP_HEX(&sblock, "copied full block",
-			    (unsigned char *)&ablk);
-			DBG_PRINT2("scg (%jd->%jd) block relocated\n",
-			    (intmax_t)bp[i].old, (intmax_t)bp[i].new);
-		}
-
-		/*
-		 * Now we have to update all references to any fragment which
-		 * belongs to any block relocated. We iterate now over all
-		 * cylinder groups, within those over all non zero length
-		 * inodes.
-		 */
-		for (cylno = 0; cylno < osblock.fs_ncg; cylno++) {
-			DBG_PRINT1("scg doing cg (%d)\n", cylno);
-			for (inc = osblock.fs_ipg - 1 ; inc > 0 ; inc--)
-				updrefs(cylno, (ino_t)inc, bp, fsi, fso, Nflag);
+	if (d <
+	    sblock.fs_csaddr + (sblock.fs_cssize / sblock.fs_fsize)) {
+		for (; d - sblock.fs_csaddr <
+		    sblock.fs_cssize/sblock.fs_fsize; d++) {
+			clrbit(cg_blksfree(&acg), d % sblock.fs_fpg);
+			acg.cg_cs.cs_nffree--;
+			sblock.fs_cstotal.cs_nffree--;
 		}
+		acg.cg_cs.cs_nbfree--;
+		acg.cg_cs.cs_nffree += sblock.fs_frag;
+		sblock.fs_cstotal.cs_nbfree--;
+		sblock.fs_cstotal.cs_nffree += sblock.fs_frag;
+		if (sblock.fs_contigsumsize > 0)
+			clrbit(cg_clustersfree(&acg),
+			    (d % sblock.fs_fpg) / sblock.fs_frag);
 
-		/*
-		 * All inodes are checked, now make sure the number of
-		 * references found make sense.
-		 */
-		for (i = 0; i < ind; i++) {
-			if (!bp[i].found || (bp[i].found > sblock.fs_frag)) {
-				warnx("error: %jd refs found for block %jd.",
-				    (intmax_t)bp[i].found, (intmax_t)bp[i].old);
-			}
-		}
+		frag_adjust(d % sblock.fs_fpg, 1);
 	}
 	/*
-	 * The following statistics are not changed here:
-	 *     sblock.fs_cstotal.cs_ndir
-	 *     sblock.fs_cstotal.cs_nifree
-	 * The following statistics were already updated on the fly:
-	 *     sblock.fs_cstotal.cs_nffree
-	 *     sblock.fs_cstotal.cs_nbfree
-	 * As the statistics for this cylinder group are ready, copy it to
-	 * the summary information array.
+	 * XXX	Handle the cluster statistics here in the case this
+	 *	cylinder group is now almost full, and the remaining
+	 *	space is less then the maximum cluster size. This is
+	 *	probably not needed, as you would hardly find a file
+	 *	system which has only MAXCSBUFS+FS_MAXCONTIG of free
+	 *	space right behind the cylinder group information in
+	 *	any new cylinder group.
 	 */
 
+	/*
+	 * Update our statistics in the cylinder summary.
+	 */
 	*cs = acg.cg_cs;
 
 	/*
-	 * Write summary cylinder group back to disk.
+	 * Write the new cylinder group containing the cylinder summary
+	 * back to disk.
 	 */
-	wtfs(fsbtodb(&sblock, cgtod(&sblock, ocscg)), (size_t)sblock.fs_cgsize,
-	    (void *)&acg, fso, Nflag);
-	DBG_PRINT0("scg written\n");
+	wtfs(fsbtodb(&sblock, cgtod(&sblock, ncscg)),
+	    (size_t)sblock.fs_cgsize, (void *)&acg, fso, Nflag);
+	DBG_PRINT0("nscg written\n");
 	DBG_DUMP_CG(&sblock, "new summary cg", &acg);
 
 	DBG_LEAVE;
@@ -1511,126 +1121,6 @@ wtfs(ufs2_daddr_t bno, size_t size, void
 }
 
 /*
- * Here we allocate a free block in the current cylinder group. It is assumed,
- * that acg contains the current cylinder group. As we may take a block from
- * somewhere in the file system we have to handle cluster summary here.
- */
-static ufs2_daddr_t
-alloc(void)
-{
-	DBG_FUNC("alloc")
-	ufs2_daddr_t d, blkno;
-	int lcs1, lcs2;
-	int l;
-	int csmin, csmax;
-	int dlower, dupper, dmax;
-
-	DBG_ENTER;
-
-	if (acg.cg_magic != CG_MAGIC) {
-		warnx("acg: bad magic number");
-		DBG_LEAVE;
-		return (0);
-	}
-	if (acg.cg_cs.cs_nbfree == 0) {
-		warnx("error: cylinder group ran out of space");
-		DBG_LEAVE;
-		return (0);
-	}
-	/*
-	 * We start seeking for free blocks only from the space available after
-	 * the end of the new grown cylinder summary. Otherwise we allocate a
-	 * block here which we have to relocate a couple of seconds later again
-	 * again, and we are not prepared to to this anyway.
-	 */
-	blkno = -1;
-	dlower = cgsblock(&sblock, acg.cg_cgx) - cgbase(&sblock, acg.cg_cgx);
-	dupper = cgdmin(&sblock, acg.cg_cgx) - cgbase(&sblock, acg.cg_cgx);
-	dmax = cgbase(&sblock, acg.cg_cgx) + sblock.fs_fpg;
-	if (dmax > sblock.fs_size)
-		dmax = sblock.fs_size;
-	dmax -= cgbase(&sblock, acg.cg_cgx); /* retransform into cg */
-	csmin = sblock.fs_csaddr - cgbase(&sblock, acg.cg_cgx);
-	csmax = csmin + howmany(sblock.fs_cssize, sblock.fs_fsize);
-	DBG_PRINT3("seek range: dl=%d, du=%d, dm=%d\n", dlower, dupper, dmax);
-	DBG_PRINT2("range cont: csmin=%d, csmax=%d\n", csmin, csmax);
-
-	for (d = 0; (d < dlower && blkno == -1); d += sblock.fs_frag) {
-		if (d >= csmin && d <= csmax)
-			continue;
-		if (isblock(&sblock, cg_blksfree(&acg), fragstoblks(&sblock, d))) {
-			blkno = fragstoblks(&sblock, d);/* Yeah found a block */
-			break;
-		}
-	}
-	for (d = dupper; (d < dmax && blkno == -1); d += sblock.fs_frag) {
-		if (d >= csmin && d <= csmax) {
-			continue;
-		}
-		if (isblock(&sblock, cg_blksfree(&acg), fragstoblks(&sblock, d))) {
-			blkno = fragstoblks(&sblock, d);/* Yeah found a block */
-			break;
-		}
-	}
-	if (blkno == -1) {
-		warnx("internal error: couldn't find promised block in cg");
-		DBG_LEAVE;
-		return (0);
-	}
-
-	/*
-	 * This is needed if the block was found already in the first loop.
-	 */
-	d = blkstofrags(&sblock, blkno);
-
-	clrblock(&sblock, cg_blksfree(&acg), blkno);
-	if (sblock.fs_contigsumsize > 0) {
-		/*
-		 * Handle the cluster allocation bitmap.
-		 */
-		clrbit(cg_clustersfree(&acg), blkno);
-		/*
-		 * We possibly have split a cluster here, so we have to do
-		 * recalculate the sizes of the remaining cluster halves now,
-		 * and use them for updating the cluster summary information.
-		 *
-		 * Lets start with the blocks before our allocated block ...
-		 */
-		for (lcs1 = 0, l = blkno - 1; lcs1 < sblock.fs_contigsumsize;
-				l--, lcs1++ ) {
-			if (isclr(cg_clustersfree(&acg), l))
-				break;
-		}
-		/*
-		 * ... and continue with the blocks right after our allocated
-		 * block.
-		 */
-		for (lcs2 = 0, l = blkno + 1; lcs2 < sblock.fs_contigsumsize;
-		    l++, lcs2++ ) {
-			if (isclr(cg_clustersfree(&acg), l))
-				break;
-		}
-
-		/*
-		 * Now update all counters.
-		 */
-		cg_clustersum(&acg)[MIN(lcs1 + lcs2 + 1, sblock.fs_contigsumsize)]--;
-		if (lcs1)
-			cg_clustersum(&acg)[lcs1]++;
-		if (lcs2)
-			cg_clustersum(&acg)[lcs2]++;
-	}
-	/*
-	 * Update all statistics based on blocks.
-	 */
-	acg.cg_cs.cs_nbfree--;
-	sblock.fs_cstotal.cs_nbfree--;
-
-	DBG_LEAVE;
-	return (d);
-}
-
-/*
  * Here we check if all frags of a block are free. For more details again
  * please see the source of newfs(8), as this function is taken over almost
  * unchanged.
@@ -1735,54 +1225,6 @@ setblock(struct fs *fs, unsigned char *c
 }
 
 /*
- * This function provides access to an individual inode. We find out in which
- * block the requested inode is located, read it from disk if needed, and
- * return the pointer into that block. We maintain a cache of one block to
- * not read the same block again and again if we iterate linearly over all
- * inodes.
- */
-static union dinode *
-ginode(ino_t inumber, int fsi, int cg)
-{
-	DBG_FUNC("ginode")
-	static ino_t startinum = 0;	/* first inode in cached block */
-
-	DBG_ENTER;
-
-	/*
-	 * The inumber passed in is relative to the cg, so use it here to see
-	 * if the inode has been allocated yet.
-	 */
-	if (isclr(cg_inosused(&aocg), inumber)) {
-		DBG_LEAVE;
-		return NULL;
-	}
-	/*
-	 * Now make the inumber relative to the entire inode space so it can
-	 * be sanity checked.
-	 */
-	inumber += (cg * sblock.fs_ipg);
-	if (inumber < ROOTINO) {
-		DBG_LEAVE;
-		return NULL;
-	}
-	if (inumber > maxino)
-		errx(8, "bad inode number %d to ginode", inumber);
-	if (startinum == 0 ||
-	    inumber < startinum || inumber >= startinum + INOPB(&sblock)) {
-		inoblk = fsbtodb(&sblock, ino_to_fsba(&sblock, inumber));
-		rdfs(inoblk, (size_t)sblock.fs_bsize, inobuf, fsi);
-		startinum = (inumber / INOPB(&sblock)) * INOPB(&sblock);
-	}
-	DBG_LEAVE;
-	if (sblock.fs_magic == FS_UFS1_MAGIC)

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201206231903.q5NJ3gxf058971>