[Ocfs2-tools-commits] zab commits r1034 - in trunk: fsck.ocfs2 libocfs2

svn-commits at oss.oracle.com svn-commits at oss.oracle.com
Wed Aug 10 12:12:22 CDT 2005


Author: zab
Signed-off-by: mfasheh
Signed-off-by: jlbec
Date: 2005-08-10 12:12:19 -0500 (Wed, 10 Aug 2005)
New Revision: 1034

Modified:
   trunk/fsck.ocfs2/fsck.ocfs2.checks.8.in
   trunk/fsck.ocfs2/pass0.c
   trunk/fsck.ocfs2/pass1.c
   trunk/libocfs2/chainalloc.c
Log:
Check i_size in fsck.

o be sure to update i_size and i_clusters for chain allocator inodes as
  groups are added and removed, both in fsck and libocfs2.
o check chain allocator i_size/i_clusters in pass0 as we validate the
  allocators
o then only check i_size/i_clusters for inodes that have i_list in pass1

Signed-off-by: mfasheh
Signed-off-by: jlbec
  


Modified: trunk/fsck.ocfs2/fsck.ocfs2.checks.8.in
===================================================================
--- trunk/fsck.ocfs2/fsck.ocfs2.checks.8.in	2005-08-09 18:34:07 UTC (rev 1033)
+++ trunk/fsck.ocfs2/fsck.ocfs2.checks.8.in	2005-08-10 17:12:19 UTC (rev 1034)
@@ -183,6 +183,23 @@
 Answering yes will remove the unused chain and shift the remaining chains
 forward in the list.
 
+.SS "CHAIN_I_CLUSTERS"
+Chain allocator inodes have an i_clusters value that represents the number
+of clusters used by the allocator.  An inode was found whose i_clusters
+value doesn't match the number of clusters its chains cover.
+
+Answering yes updates i_clusters in the inode to reflect what was actually
+found by walking the chain.
+
+.SS "CHAIN_I_SIZE"
+Chain allocator inodes multiply the number of bytes per cluster
+by the their i_clusters value and store it in i_size.  An inode was found
+which didn't have the correct value in its i_size.
+
+Answering yes updates i_size to be the product of i_clusters and the cluster
+size.  Nothing else uses this value, and previous versions of tools didn't
+calculate it properly, so don't be too worried if this error appears.
+
 .SS "CHAIN_GROUP_BITS"
 The inode that contains an embedded chain list has fields which record the
 total number of bits covered by the chain as well as the amount free.  These 
@@ -423,6 +440,17 @@
 Answering yes to this question clears the directorie's inode and so
 deletes the directory.
 
+.SS "INODE_SIZE"
+Certain inodes record the size of the data they reference in an i_size field.
+This can be the number of bytes in a file, directory, or symlink target
+which are stored in data mapped by extents of clusters.  This error occurs
+when the extent lists are walked and the amount of data found does not match
+what is stored in i_size.
+
+Answering yes to this question updates the inode's i_size to match the amount
+of data referenced by the extent lists.  It is vitally important that i_size
+matches the extent lists and so answering yes is strongly encouraged.
+
 .SS "INODE_CLUSTERS"
 Inodes contain a record of how many clusters are allocated to them.  An inode
 was found whose recorded number of clusters doesn't match the number of blocks

Modified: trunk/fsck.ocfs2/pass0.c
===================================================================
--- trunk/fsck.ocfs2/pass0.c	2005-08-09 18:34:07 UTC (rev 1033)
+++ trunk/fsck.ocfs2/pass0.c	2005-08-10 17:12:19 UTC (rev 1034)
@@ -245,6 +245,8 @@
 	cr->c_total -= bg->bg_bits;
 	di->id1.bitmap1.i_used -= bg->bg_bits - bg->bg_free_bits_count;
 	di->id1.bitmap1.i_total -= bg->bg_bits;
+	di->i_clusters -= (bg->bg_bits / cl->cl_bpc);
+	di->i_size = (uint64_t)di->i_clusters * ost->ost_fs->fs_clustersize;
 
 	ret = ocfs2_write_inode(ost->ost_fs, di->i_blkno, (char *)di);
 	if (ret) {
@@ -451,6 +453,7 @@
 	uint32_t free = 0, total = 0;
 	int changed = 0, trust_next_free = 1;
 	errcode_t ret = 0;
+	uint64_t chain_bytes;
 
 	if (memcmp(di->i_signature, OCFS2_INODE_SIGNATURE,
 		   strlen(OCFS2_INODE_SIGNATURE))) {
@@ -543,6 +546,7 @@
 		};
 		ret = check_chain(ost, di, &cs, cr, buf1, buf2, &changed,
 				  allowed, forbidden);
+		/* XXX what?  not checking ret? */
 
 		if (cr->c_blkno != 0) {
 			free += cs.cs_free_bits;
@@ -597,6 +601,30 @@
 		}
 	}
 
+	total /= cl->cl_bpc;
+
+	if (di->i_clusters != total &&
+	    prompt(ost, PY, PR_CHAIN_I_CLUSTERS,
+		   "Allocator inode %"PRIu64" has %"PRIu32" clusters "
+		   "represtented in its allocator chains but has an "
+		   "i_clusters value of %"PRIu32". Fix this by updating "
+		   "i_clusters?", di->i_blkno, total, di->i_clusters)) {
+		di->i_clusters = total;
+		changed = 1;
+	}
+
+	chain_bytes = (uint64_t)total * ost->ost_fs->fs_clustersize;
+	if (di->i_size != chain_bytes &&
+	    prompt(ost, PY, PR_CHAIN_I_SIZE,
+		   "Allocator inode %"PRIu64" has %"PRIu32" clusters "
+		   "represtented in its allocator chain which accounts for "
+		   "%"PRIu64" total bytes, but its i_size is %"PRIu64". "
+		   "Fix this by updating i_size?", di->i_blkno,
+		   di->id1.bitmap1.i_total, chain_bytes, di->i_size)) {
+		di->i_size = chain_bytes;
+		changed = 1;
+	}
+
 	if (changed) {
 		ret = ocfs2_write_inode(ost->ost_fs, di->i_blkno, (char *)di);
 		if (ret) {
@@ -781,6 +809,9 @@
 
 		di->id1.bitmap1.i_used += bg->bg_bits - bg->bg_free_bits_count;
 		di->id1.bitmap1.i_total += bg->bg_bits;
+		di->i_clusters += (bg->bg_bits / di->id2.i_chain.cl_bpc);
+		di->i_size = (uint64_t)di->i_clusters *
+			     ost->ost_fs->fs_clustersize;
 
 		ret = ocfs2_write_inode(ost->ost_fs, di->i_blkno, (char *)di);
 		if (ret) {

Modified: trunk/fsck.ocfs2/pass1.c
===================================================================
--- trunk/fsck.ocfs2/pass1.c	2005-08-09 18:34:07 UTC (rev 1033)
+++ trunk/fsck.ocfs2/pass1.c	2005-08-10 17:12:19 UTC (rev 1034)
@@ -698,22 +698,10 @@
 	return 0;
 }
 
-/* XXX this is only really building up the vb data so that the caller can
- * verify the chain allocator inode's fields.  I wonder if we shouldn't have
- * already done that in pass 0. */
-static int check_gd_block(ocfs2_filesys *fs, uint64_t gd_blkno, int chain_num,
-			   void *priv_data)
-{
-	struct verifying_blocks *vb = priv_data;
-	verbosef("found gd block %"PRIu64"\n", gd_blkno);
-	/* XXX should arguably be verifying that pass 0 marked the group desc
-	 * blocks found */
-	/* don't have bcount */
-	vb_saw_block(vb, vb->vb_num_blocks);
-	return 0;
-}
-
-
+/*
+ * this verifies i_size and i_clusters for inodes that use i_list to
+ * reference extents of data.
+ */
 static errcode_t o2fsck_check_blocks(ocfs2_filesys *fs, o2fsck_state *ost,
 				     uint64_t blkno, ocfs2_dinode *di)
 {
@@ -724,28 +712,21 @@
 		.vb_di = di,
 	};
 
-	/*
-	 * ISLNK && clusters == 0 is the only sign of an inode that doesn't
-	 * have an extent list when i_flags would have us believe it did.  
-	 * We might be able to be very clever about discovering the 
-	 * difference between i_symlink and i_list, but we don't try yet.
-	 */
-	if (di->i_flags & OCFS2_LOCAL_ALLOC_FL ||
-	    di->i_flags & OCFS2_DEALLOC_FL)
-		ret = 0;
-	else if (di->i_flags & OCFS2_CHAIN_FL)
-		ret = ocfs2_chain_iterate(fs, blkno, check_gd_block, &vb);
-	else if (S_ISLNK(di->i_mode) && di->i_clusters == 0) 
-		ret = 0;
-	else {
-		ret = o2fsck_check_extents(ost, di);
-		if (ret == 0)
-			ret = ocfs2_block_iterate_inode(fs, di, 0,
-							verify_block, &vb);
-		if (vb.vb_ret)
-			ret = vb.vb_ret;
-	}
+	/* don't bother to verify for inodes that don't have i_list,
+	 * we have to trust i_mode/i_clusters to tell us that a symlink
+	 * has put target data in the union instead of i_list */
+	if ((di->i_flags & (OCFS2_SUPER_BLOCK_FL | OCFS2_LOCAL_ALLOC_FL |
+			    OCFS2_BITMAP_FL | OCFS2_CHAIN_FL |
+			    OCFS2_DEALLOC_FL)) ||
+	    (S_ISLNK(di->i_mode) && di->i_clusters == 0))
+		return 0;
 
+	ret = o2fsck_check_extents(ost, di);
+	if (ret == 0)
+		ret = ocfs2_block_iterate_inode(fs, di, 0, verify_block, &vb);
+	if (vb.vb_ret)
+		ret = vb.vb_ret;
+
 	if (ret) {
 		com_err(whoami, ret, "while iterating over the blocks for "
 			"inode %"PRIu64, di->i_blkno);	
@@ -778,19 +759,18 @@
 		/* XXX clear valid flag and stuff? */
 	}
 
-#if 0 /* boy, this is just broken */
 	if (vb.vb_num_blocks > 0)
 		expected = (vb.vb_last_block + 1) * fs->fs_blocksize;
 
 	/* i_size is checked for symlinks elsewhere */
 	if (!S_ISLNK(di->i_mode) && di->i_size > expected &&
-	    prompt(ost, PY, 0, "Inode %"PRIu64" has a size of %"PRIu64" but has "
-		    "%"PRIu64" bytes of actual data. Correct the file size?",
+	    prompt(ost, PY, PR_INODE_SIZE, "Inode %"PRIu64" has a size of "
+		   "%"PRIu64" but has %"PRIu64" bytes of actual data. "
+		   "Correct the file size?",
 		    di->i_blkno, di->i_size, expected)) {
 		di->i_size = expected;
 		o2fsck_write_inode(ost, blkno, di);
 	}
-#endif
 
 	if (vb.vb_num_blocks > 0)
 		expected = ocfs2_clusters_in_blocks(fs, vb.vb_last_block + 1);

Modified: trunk/libocfs2/chainalloc.c
===================================================================
--- trunk/libocfs2/chainalloc.c	2005-08-09 18:34:07 UTC (rev 1033)
+++ trunk/libocfs2/chainalloc.c	2005-08-10 17:12:19 UTC (rev 1034)
@@ -534,6 +534,8 @@
 	rec->c_blkno = blkno;
 
 	cinode->ci_inode->i_clusters += cinode->ci_inode->id2.i_chain.cl_cpg;
+	cinode->ci_inode->i_size = (uint64_t)cinode->ci_inode->i_clusters *
+				   fs->fs_clustersize;
 	cinode->ci_inode->id1.bitmap1.i_total += gd->bg_bits;
 	cinode->ci_inode->id1.bitmap1.i_used += gd->bg_bits -
 						gd->bg_free_bits_count;
@@ -564,6 +566,8 @@
 
 		cinode->ci_inode->i_clusters -= 
 			cinode->ci_inode->id2.i_chain.cl_cpg;
+		cinode->ci_inode->i_size = (uint64_t)cinode->ci_inode->i_clusters *
+					   fs->fs_clustersize;
 		cinode->ci_inode->id1.bitmap1.i_total -= gd->bg_bits;
 		cinode->ci_inode->id1.bitmap1.i_used -= gd->bg_bits -
 							gd->bg_free_bits_count;



More information about the Ocfs2-tools-commits mailing list