[Ocfs2-tools-devel] [patch 7/9] Add group check mechanism in fsck.ocfs2 in case of bad slot remove, take 4

tao.ma at oracle.com tao.ma at oracle.com
Wed Jul 11 02:10:18 PDT 2007


In slot remove of tunefs.ocfs2, when we relink the group to the new chain
of a new file, we link it to the new chain first and delete it from the old file
secondly, so we may meet the situation that the group is in two different files,
and we must remove it from one of them.

Other two error types are also added here for other additional check

Index: new.ocfs2-tools/fsck.ocfs2/fsck.ocfs2.checks.8.in
===================================================================
--- new.ocfs2-tools.orig/fsck.ocfs2/fsck.ocfs2.checks.8.in	2007-07-10 16:35:20.000000000 -0400
+++ new.ocfs2-tools/fsck.ocfs2/fsck.ocfs2.checks.8.in	2007-07-10 16:36:36.000000000 -0400
@@ -150,6 +150,13 @@ inode that doesn't match the descriptor'
 Answering yes updates the group descriptor's parent pointer to match the inode
 it resides in.
 
+.SS "GROUP_DUPLICATE"
+Group descriptors contain a pointer to the allocator inode which contains
+the chain they belong to.  A group descriptor was found in two allocator
+inodes so it may be duplicated.
+
+Answering yes removes the group descriptor from current allocator inode.
+
 .SS "GROUP_BLKNO"
 Group descriptors have a field which records their block location on disk.  A
 group descriptor was found at a given location but is recorded as being
@@ -657,6 +664,21 @@ Answering yes will refresh the superbloc
 only disable the copying of the backup superblock and will not effect the
 remaining \fIfsck.ocfs2\fR processing.
 
+.SS "ORPHAN_DIR_MISSING"
+While files are being deleted they are placed in an internal directory, named
+orphan directory. If an orphan directory does't exist, an OCFS2 volume can't
+be mounted successfully. Fsck has found the orphan directory is missing and
+would like to create it for future use.
+
+Answering yes creates the orphan directory in the system directory.
+
+.SS "JOURNAL_FILE_INVALID"
+OCFS2 uses JDB for journalling and some journal files exist in the
+system directory. Fsck has found some journal file is whther empty or has
+bad journal superblock and would like to fix it for future use.
+
+Answering yes reformats the journal file in the system directory.
+
 .SH "SEE ALSO"
 .BR fsck.ocfs2(8)
 
Index: new.ocfs2-tools/fsck.ocfs2/pass0.c
===================================================================
--- new.ocfs2-tools.orig/fsck.ocfs2/pass0.c	2007-07-10 16:35:20.000000000 -0400
+++ new.ocfs2-tools/fsck.ocfs2/pass0.c	2007-07-10 16:36:36.000000000 -0400
@@ -91,11 +91,76 @@ static void find_max_free_bits(struct oc
 	}
 }
 
+/* check whether the group really exists in the specified chain of
+ * the specified allocator file.
+ */
+static errcode_t check_group_parent(ocfs2_filesys *fs, uint64_t group,
+				    uint64_t ino, uint16_t chain,int *exist)
+{
+	errcode_t ret;
+	uint64_t gd_blkno;
+	char *buf = NULL, *gd_buf = NULL;
+	struct ocfs2_dinode *di = NULL;
+	struct ocfs2_group_desc *gd = NULL;
+	struct ocfs2_chain_rec *cr = NULL;
+
+	ret = ocfs2_malloc_block(fs->fs_io, &buf);
+	if (ret)
+		goto out;
+
+	ret = ocfs2_read_inode(fs, ino, buf);
+	if (ret) {
+		goto out;
+	}
+
+	di = (struct ocfs2_dinode *)buf;
+
+	if (!(di->i_flags & OCFS2_VALID_FL) ||
+	    !(di->i_flags & OCFS2_BITMAP_FL) ||
+	    !(di->i_flags & OCFS2_CHAIN_FL))
+		goto out;
+
+	if (di->id1.bitmap1.i_total == 0)
+		goto out;
+
+	if (di->id2.i_chain.cl_next_free_rec <= chain)
+		goto out;
+
+	cr = &di->id2.i_chain.cl_recs[chain];
+
+	ret = ocfs2_malloc_block(fs->fs_io, &gd_buf);
+	if (ret)
+		goto out;
+
+	gd_blkno = cr->c_blkno;
+	while (gd_blkno) {
+		if (gd_blkno ==  group) {
+			*exist = 1;
+			break;
+		}
+
+		ret = ocfs2_read_group_desc(fs, gd_blkno, gd_buf);
+		if (ret)
+			goto out;
+		gd = (struct ocfs2_group_desc *)gd_buf;
+
+		gd_blkno = gd->bg_next_group;
+	}
+
+out:
+	if (gd_buf)
+		ocfs2_free(&gd_buf);
+	if (buf)
+		ocfs2_free(&buf);
+	return ret;
+}
+
 static errcode_t repair_group_desc(o2fsck_state *ost,
 				   struct ocfs2_dinode *di,
 				   struct chain_state *cs,
 				   struct ocfs2_group_desc *bg,
-				   uint64_t blkno)
+				   uint64_t blkno,
+				   int *clear_ref)
 {
 	errcode_t ret = 0;
 	int changed = 0;
@@ -121,14 +186,36 @@ static errcode_t repair_group_desc(o2fsc
 	/* XXX maybe for advanced pain we could check to see if these 
 	 * kinds of descs have valid generations for the inodes they
 	 * reference */
-	if ((bg->bg_parent_dinode != di->i_blkno) &&
-	    prompt(ost, PY, PR_GROUP_PARENT,
+	if ((bg->bg_parent_dinode != di->i_blkno)) {
+		int exist = 0;
+		ret = check_group_parent(ost->ost_fs, bg->bg_blkno,
+					 bg->bg_parent_dinode,
+					 bg->bg_chain, &exist);
+
+		/* If we finds that the group really exists in the specified
+		 * chain of the specified alloc inode, then this may be a
+		 * duplicated group and we may need to remove it from current
+		 * inode.
+		 */
+		if (!ret && exist && prompt(ost, PY, PR_GROUP_DUPLICATE,
+		   "Group descriptor at block %"PRIu64" is "
+		   "referenced by inode %"PRIu64" but thinks its parent inode "
+		   "is %"PRIu64" and we can also see it in that inode."
+		    " So it may be duplicated.  Remove it from this inode?",
+		    blkno, di->i_blkno, bg->bg_parent_dinode)) {
+			*clear_ref = 1;
+			goto out;
+		}
+
+		if (prompt(ost, PY, PR_GROUP_PARENT,
 		   "Group descriptor at block %"PRIu64" is "
 		   "referenced by inode %"PRIu64" but thinks its parent inode "
 		   "is %"PRIu64".  Fix the descriptor's parent inode?", blkno,
 		   di->i_blkno, bg->bg_parent_dinode)) {
-		bg->bg_parent_dinode = di->i_blkno;
-		changed = 1;
+			bg->bg_parent_dinode = di->i_blkno;
+			changed = 1;
+		}
+
 	}
 
 	if ((bg->bg_blkno != blkno) &&
@@ -179,7 +266,7 @@ static errcode_t repair_group_desc(o2fsc
 
 	cs->cs_total_bits += bg->bg_bits;
 	cs->cs_free_bits += bg->bg_free_bits_count;
-
+out:
 	return ret;
 }
 
@@ -474,10 +561,19 @@ static errcode_t check_chain(o2fsck_stat
 			break;
 		}
 
-		ret = repair_group_desc(ost, di, cs, bg2, blkno);
+		ret = repair_group_desc(ost, di, cs, bg2, blkno, &clear_ref);
 		if (ret)
 			goto out;
 
+		/* we found a duplicate chain, so we need to clear them from
+		 * current chain.
+		 *
+		 * Please note that all the groups below this group will also
+		 * be removed from this chain because this is the mechanism
+		 * of removing slots in tunefs.ocfs2.
+		 */
+		if (clear_ref)
+			break;
 
 		/* the loop will now start by reading bg1->next_group */
 		memcpy(buf1, buf2, ost->ost_fs->fs_blocksize);

-- 



More information about the Ocfs2-tools-devel mailing list