[Ocfs2-tools-commits] zab commits r267 - in trunk/fsck.ocfs2: . include

svn-commits at oss.oracle.com svn-commits at oss.oracle.com
Mon Sep 27 18:42:33 CDT 2004


Author: zab
Date: 2004-09-27 18:42:30 -0500 (Mon, 27 Sep 2004)
New Revision: 267

Modified:
   trunk/fsck.ocfs2/icount.c
   trunk/fsck.ocfs2/include/icount.h
   trunk/fsck.ocfs2/pass1.c
Log:
Do more while iterating the blocks on an inode.
                                                                                
o Make icount_update failure fatal
o don't bother checking the inode signatures
o track icount for all inodes
o really check that the root dir is in fact a dir before claiming it isn't
o record the number of and furthest blocks while iterating
o check for zero lengh directories
o make sure i_size and i_clusters matches what we found iterating


Modified: trunk/fsck.ocfs2/icount.c
===================================================================
--- trunk/fsck.ocfs2/icount.c	2004-09-27 17:22:24 UTC (rev 266)
+++ trunk/fsck.ocfs2/icount.c	2004-09-27 23:42:30 UTC (rev 267)
@@ -34,6 +34,7 @@
 
 #include "fsck.h"
 #include "icount.h"
+#include "util.h"
 
 typedef struct _icount_node {
 	struct rb_node	in_node;
@@ -83,7 +84,7 @@
 	return NULL;
 }
 
-errcode_t o2fsck_icount_update(o2fsck_icount *icount, uint64_t blkno, 
+void o2fsck_icount_update(o2fsck_icount *icount, uint64_t blkno, 
 				uint16_t count)
 {
 	icount_node *in;
@@ -105,13 +106,13 @@
 	} else if (count > 2){
 		in = calloc(1, sizeof(*in));
 		if (in == NULL)
-			return OCFS2_ET_NO_MEMORY;
+			fatal_error(OCFS2_ET_NO_MEMORY, 
+				    "while allocating to track icount");
 
 		in->in_blkno = blkno;
 		in->in_icount = count;
 		icount_insert(icount, in);
 	}
-	return 0;
 }
 
 errcode_t o2fsck_icount_new(ocfs2_filesys *fs, o2fsck_icount **ret)

Modified: trunk/fsck.ocfs2/include/icount.h
===================================================================
--- trunk/fsck.ocfs2/include/icount.h	2004-09-27 17:22:24 UTC (rev 266)
+++ trunk/fsck.ocfs2/include/icount.h	2004-09-27 23:42:30 UTC (rev 267)
@@ -31,7 +31,7 @@
 	struct rb_root	ic_multiple_tree;
 } o2fsck_icount;
 
-errcode_t o2fsck_icount_update(o2fsck_icount *icount, uint64_t blkno, 
+void o2fsck_icount_update(o2fsck_icount *icount, uint64_t blkno, 
 				uint16_t count);
 errcode_t o2fsck_icount_new(ocfs2_filesys *fs, o2fsck_icount **ret);
 void o2fsck_icount_free(o2fsck_icount *icount);

Modified: trunk/fsck.ocfs2/pass1.c
===================================================================
--- trunk/fsck.ocfs2/pass1.c	2004-09-27 17:22:24 UTC (rev 266)
+++ trunk/fsck.ocfs2/pass1.c	2004-09-27 23:42:30 UTC (rev 267)
@@ -25,6 +25,7 @@
  */
 #include <string.h>
 #include <inttypes.h>
+#include <time.h>
 
 #include "ocfs2.h"
 
@@ -65,23 +66,26 @@
 
 	/* what's our deletion story?  i_links_count, dtime, etc.. */
 
-	/* XXX it seems these are expected sometimes? */
+#if 0 /* XXX we don't care about the signature on inodes? */
 	if (memcmp(di->i_signature, OCFS2_INODE_SIGNATURE,
 		   strlen(OCFS2_INODE_SIGNATURE))) {
 		goto bad;
 	}
-	if (!(di->i_flags & OCFS2_VALID_FL)) {
-		goto bad;
-	}
+#endif
 
+	if (di->i_links_count)
+		o2fsck_icount_update(ost->ost_icount_in_inodes, di->i_blkno,
+					di->i_links_count);
+
 	/* offer to clear a non-directory root inode so that 
 	 * pass3:check_root() can re-create it */
-	if ((di->i_blkno == fs->fs_root_blkno) &&
+	if ((di->i_blkno == fs->fs_root_blkno) && !S_ISDIR(di->i_mode) && 
 	    should_fix(ost, FIX_DEFYES, "Root inode isn't a directory.")) {
 		di->i_dtime = 0ULL;
 		di->i_links_count = 0ULL;
-		o2fsck_icount_update(ost->ost_icount_in_inodes, di->i_blkno,
-					di->i_links_count);
+		o2fsck_icount_update(ost->ost_icount_in_inodes, 
+					di->i_blkno, di->i_links_count);
+
 		o2fsck_write_inode(fs, blkno, di);
 	}
 
@@ -123,7 +127,10 @@
 
 struct verifying_blocks {
        unsigned		vb_mark_dir_blocks;	
-       uint64_t		vb_blocks;	
+       uint64_t		vb_num_blocks;	
+       uint64_t		vb_last_block;	
+       int		vb_clear;
+       int		vb_errors;
        o2fsck_state 	*vb_ost;
        ocfs2_dinode	*vb_di;
 };
@@ -135,48 +142,135 @@
 {
 	struct verifying_blocks *vb = priv_data;
 	ocfs2_dinode *di = vb->vb_di;
+	o2fsck_state *ost = vb->vb_ost;
 	int was_set;
+	
+	/* someday we may want to worry about holes in files here */
 
-	ocfs2_bitmap_set(vb->vb_ost->ost_found_blocks, blkno, &was_set);
+	if ((blkno < OCFS2_SUPER_BLOCK_BLKNO) || (blkno > fs->fs_blocks)) {
+		vb->vb_errors++;
+#if 0 /* ext2 does this by returning a value to libext2 which clears the 
+	 block from the inode's allocation */
+		if (should_fix(ost, FIX_DEFYES, 
+				"inode %"PRIu64" references bad physical block"
+			       	" %"PRIu64" at logical block %"PRIu64
+				", should it be cleared?",
+			di->i_blkno, bklno, bcount)) {
+		}
+#endif
+	}
+
+	/* XXX this logic should be more sophisticated.  It's not really clear
+	 * what ext2 is trying to do in theirs. */
+	if (vb->vb_errors == 12) {
+		if (should_fix(ost, FIX_DEFYES, 
+			"inode %"PRIu64" has seen many errors, should it "
+			"be cleared?", di->i_blkno)) {
+			vb->vb_clear = 1;
+			return OCFS2_BLOCK_ABORT;
+		}
+	}
+
+	ocfs2_bitmap_set(ost->ost_found_blocks, blkno, &was_set);
 	if (was_set) {
 		fprintf(stderr, "duplicate block %"PRIu64"?\n", blkno);
-		ocfs2_bitmap_set(vb->vb_ost->ost_dup_blocks, blkno, NULL);
+		ocfs2_bitmap_set(ost->ost_dup_blocks, blkno, NULL);
 	}
 
 	if (S_ISDIR(di->i_mode)) {
-		/* do we want libocfs2 to record directory blocks or should
-		 * we? */
+#if 0
+		o2fsck_add_dir_block(di, blkno, bcount);
+#endif
 	}
 
-	vb->vb_blocks++;
+	vb->vb_num_blocks++;
+	if (bcount > vb->vb_last_block)
+		vb->vb_last_block = bcount;
+
 	return 0;
 }
 
-static errcode_t o2fsck_verify_inode_data(ocfs2_filesys *fs, o2fsck_state *ost,
-					  uint64_t blkno, ocfs2_dinode *di)
+/* XXX maybe this should be a helper in libocfs2? */
+static uint64_t clusters_holding_blocks(ocfs2_filesys *fs, uint64_t num_blocks)
 {
+	int c_to_b_bits = OCFS2_RAW_SB(fs->fs_super)->s_clustersize_bits -
+		          OCFS2_RAW_SB(fs->fs_super)->s_blocksize_bits;
+
+	return (num_blocks + ((1 << c_to_b_bits) - 1)) >> c_to_b_bits;
+}
+
+static void o2fsck_check_blocks(ocfs2_filesys *fs, o2fsck_state *ost,
+				uint64_t blkno, ocfs2_dinode *di)
+{
 	struct verifying_blocks vb = {0, };
+	uint64_t expected = 0;
 	errcode_t ret;
 
 	vb.vb_ost = ost;
 	vb.vb_di = di;
 
+	/* XXX it isn't enough to just walk the blocks.  We want to mark
+	 * metadata blocks in the extents as used and otherwise validate them
+	 * while we're at it. */
+
 	ret = ocfs2_block_iterate(fs, blkno, 0, verify_block, &vb);
+	if (ret == OCFS2_ET_INODE_CANNOT_BE_ITERATED) {
+		/* XXX I don't understand this.   just check the inode
+		 * fields as though there were no blocks? */
+		ret = 0;
+	}
 	if (ret) {
-		com_err(whoami, ret, "walking data blocks");
-		goto out;
+		fatal_error(ret, "while iterating over the blocks for inode "
+			         "%"PRIu64, di->i_blkno);	
 	}
 
-#if 0 /* hmm. */
-	if (vb.vb_blocks != di->i_blocks) {
-		fprintf(stderr, "inode %llu claimed %llu blocks, found"
-				" %llu blocks.\n", di->i_ino, di->i_blocks,
-				vb.vb_blocks);
+	if (S_ISDIR(di->i_mode) && vb.vb_num_blocks == 0) {
+		if (should_fix(ost, FIX_DEFYES, 
+			"inode %"PRIu64" is a zero length directory, "
+			"clear it?", di->i_blkno)) {
+			vb.vb_clear = 1;
+		}
 	}
-#endif
 
-out:
-	return ret;
+	/*
+	 * XXX we should have a helper that clears an inode and backs it out of
+	 * any book-keeping that it might have been included in, as though it
+	 * was never seen.  the alternative is to restart pass1 which seems
+	 * goofy. 
+	 */
+	if (vb.vb_clear) {
+		di->i_links_count = 0;
+		o2fsck_icount_update(ost->ost_icount_in_inodes, 
+				          di->i_blkno, di->i_links_count);
+		di->i_dtime = time(0);
+		o2fsck_write_inode(fs, di->i_blkno, di);
+		/* XXX clear valid flag and stuff? */
+	}
+
+	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 &&
+	    should_fix(ost, FIX_DEFYES, "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(fs, blkno, di);
+	}
+
+	if (vb.vb_num_blocks > 0)
+		expected = clusters_holding_blocks(fs, vb.vb_last_block + 1);
+
+	if (di->i_clusters < expected &&
+	    should_fix(ost, FIX_DEFYES, "inode %"PRIu64" has %"PRIu64" "
+		       "clusters but its blocks fit in %"PRIu64" clusters. "
+		       " Correct the number of clusters?", di->i_blkno, 
+		       di->i_clusters, expected)) {
+		di->i_clusters = expected;
+		o2fsck_write_inode(fs, blkno, di);
+	}
 }
 
 errcode_t o2fsck_pass1(o2fsck_state *ost)
@@ -217,11 +311,16 @@
 		}
 		if (blkno == 0)
 			break;
+		/* scanners have to skip over uninitialized inodes */
+		if (!(di->i_flags & OCFS2_VALID_FL))
+			continue;
 
 		o2fsck_verify_inode_fields(fs, ost, blkno, di);
+
 		/* XXX be able to mark the blocks in the inode as 
 		 * bad if the inode was bad */
-		o2fsck_verify_inode_data(fs, ost, blkno, di);
+
+		o2fsck_check_blocks(fs, ost, blkno, di);
 	}
 
 out_close_scan:



More information about the Ocfs2-tools-commits mailing list