[Ocfs2-tools-commits] zab commits r314 - trunk/fsck.ocfs2

svn-commits at oss.oracle.com svn-commits at oss.oracle.com
Tue Oct 5 19:44:49 CDT 2004


Author: zab
Date: 2004-10-05 19:44:46 -0500 (Tue, 05 Oct 2004)
New Revision: 314

Modified:
   trunk/fsck.ocfs2/pass2.c
Log:
o notice zero-length directories
o more carefully check dirent's inodes (finds bogus orphan dir "..")


Modified: trunk/fsck.ocfs2/pass2.c
===================================================================
--- trunk/fsck.ocfs2/pass2.c	2004-10-05 23:57:13 UTC (rev 313)
+++ trunk/fsck.ocfs2/pass2.c	2004-10-06 00:44:46 UTC (rev 314)
@@ -199,7 +199,15 @@
 	char *chr = dirent->name;
 	int len = dirent->name_len, fix = 0, ret_flags = 0;
 
-	for(; len-- && (*chr == '/' || *chr == '\0'); chr++) {
+	if (len == 0) {
+		if (should_fix(ost, FIX_DEFYES, "Directory entry has a "
+				"zero-length name, clear it?")) {
+			dirent->inode = 0;
+			ret_flags = OCFS2_DIRENT_CHANGED;
+		}
+	}
+
+	for(; len-- > 0 && (*chr == '/' || *chr == '\0'); chr++) {
 		/* XXX in %s parent name */
 		if (!fix) {
 			fix = should_fix(ost, FIX_DEFYES, "Entry '%.*s' "
@@ -216,6 +224,44 @@
 	return ret_flags;
 }
 
+/* XXX might go somewhere else*/
+static int inode_out_of_range(ocfs2_filesys *fs, uint64_t blkno)
+{
+	if ((blkno < OCFS2_SUPER_BLOCK_BLKNO) ||
+	    (blkno > fs->fs_blocks))
+		return 1;
+	return 0;
+}
+
+static int fix_dirent_inode(o2fsck_state *ost, o2fsck_dirblock_entry *dbe,
+				struct ocfs2_dir_entry *dirent, int offset)
+{
+	int was_set;
+
+	if (inode_out_of_range(ost->ost_fs, dirent->inode)) {
+		if (should_fix(ost, FIX_DEFYES, "Entry '%.*s' refers to inode "
+				"number %"PRIu64" which is out of range, "
+				"clear it?", dirent->name_len, dirent->name, 
+				dirent->inode)) {
+			dirent->inode = 0;
+			return OCFS2_DIRENT_CHANGED;
+		}
+	}
+
+	/* XXX Do I care about possible bitmap_test errors here? */
+	ocfs2_bitmap_test(ost->ost_used_inodes, dirent->inode, &was_set);
+	if (!was_set) {
+		if (should_fix(ost, FIX_DEFYES, "Entry '%.*s' refers to inode "
+				"number %"PRIu64" which is unused, clear it?", 
+				dirent->name_len, dirent->name, 
+				dirent->inode)) {
+			dirent->inode = 0;
+			return OCFS2_DIRENT_CHANGED;
+		}
+	}
+	return 0;
+}
+
 #define type_entry(type) [type] = #type
 static char *file_types[] = {
 	type_entry(OCFS2_FT_UNKNOWN),
@@ -371,6 +417,8 @@
 	return 0;
 }
 
+
+
 /* this could certainly be more clever to issue reads in groups */
 static unsigned pass2_dir_block_iterate(o2fsck_dirblock_entry *dbe, 
 					void *priv_data) 
@@ -413,31 +461,50 @@
 		/* XXX I wonder if we should be checking that the padding
 		 * is 0 */
 
-		/* XXX hmm, this isn't quite right.  sometimes when we
-		 * change we re-examine the current entry, other times
-		 * we move on past it. */
 
+		/* first verify that we can trust the dirent's lengths
+		 * to navigate to the next in the block.  doing so can
+		 * modify the one we're checking in place */
 		this_flags = fix_dirent_lengths(dd->ost, dbe, dirent, offset, 
 						 dd->fs->fs_blocksize - offset,
 						 prev);
-
 		ret_flags |= this_flags;
-
-		/* dirtying might have swapped in a new dirent in place
-		 * of the one we just checked. */
 		if (this_flags & OCFS2_DIRENT_CHANGED)
 			continue;
 
+		/* 
+		 * In general, these calls mark ->inode as 0 when they want it
+		 * to be seen as deleted; ignored by fsck and reclaimed by the
+		 * kernel.  The dots are a special case, of course.  This
+		 * pass makes sure that they are the first two entries in
+		 * the directory and pass3 fixes ".."'s ->inode.
+		 *
+		 * XXX should verify that ocfs2 reclaims entries like that.
+		 */
 		ret_flags |= fix_dirent_dots(dd->ost, dbe, dirent, offset, 
 					     dd->fs->fs_blocksize - offset);
+		if (dirent->inode == 0)
+			goto next;
+
 		ret_flags |= fix_dirent_name(dd->ost, dbe, dirent, offset);
-		/* XXX we need to check dirent->inode before calling into here
-		 * as it'll try and read it and assert if that fails */
+		if (dirent->inode == 0)
+			goto next;
+
+		ret_flags |= fix_dirent_inode(dd->ost, dbe, dirent, offset);
+		if (dirent->inode == 0)
+			goto next;
+
 		ret_flags |= fix_dirent_filetype(dd->ost, dbe, dirent, offset);
+		if (dirent->inode == 0)
+			goto next;
+
 		ret_flags |= fix_dirent_linkage(dd->ost, dbe, dirent, offset);
+		if (dirent->inode == 0)
+			goto next;
+
 		ret_flags |= fix_dirent_dups(dd->ost, dbe, dirent, &strings,
 					     &dups_in_block);
-
+next:
 		offset += dirent->rec_len;
 		prev = dirent;
 	}



More information about the Ocfs2-tools-commits mailing list