gfs2-utils: master - fsck.gfs2: delete all duplicates from unrecoverable damaged dinodes

Bob Peterson rpeterso at fedoraproject.org
Mon May 20 16:19:07 UTC 2013


Gitweb:        http://git.fedorahosted.org/git/?p=gfs2-utils.git;a=commitdiff;h=982979702a7f23b069e31f171cc38fc4c87a018a
Commit:        982979702a7f23b069e31f171cc38fc4c87a018a
Parent:        e8d58780c43e0befeacab299c6d099e196bc83b9
Author:        Bob Peterson <rpeterso at redhat.com>
AuthorDate:    Tue May 14 09:51:28 2013 -0500
Committer:     Bob Peterson <rpeterso at redhat.com>
CommitterDate: Mon May 20 11:12:47 2013 -0500

fsck.gfs2: delete all duplicates from unrecoverable damaged dinodes

When pass1 encounters a dinode with unrecoverable damage, it tries
to "undo" the metadata and data block designations it marked in the
blockmap prior to finding the damage. That's all fine, but if the
damaged dinode has a duplicate reference, we also need to delete that
from the duplicate reference list. Otherwise pass1b may try to
resolve the duplicate reference and reinstate the damaged dinode.
---
 gfs2/fsck/metawalk.c |    5 ++++
 gfs2/fsck/pass1b.c   |   60 --------------------------------------------------
 gfs2/fsck/util.c     |   59 +++++++++++++++++++++++++++++++++++++++++++++++++
 gfs2/fsck/util.h     |    1 +
 4 files changed, 65 insertions(+), 60 deletions(-)

diff --git a/gfs2/fsck/metawalk.c b/gfs2/fsck/metawalk.c
index 44b5c66..22f3334 100644
--- a/gfs2/fsck/metawalk.c
+++ b/gfs2/fsck/metawalk.c
@@ -1530,6 +1530,11 @@ undo_metalist:
 				brelse(bh);
 		}
 	}
+	/* There may be leftover duplicate records, so we need to delete them.
+	   For example, if a metadata block was found to be a duplicate, we
+	   may not have added it to the metalist, which means it's not there
+	   to undo. */
+	delete_all_dups(ip);
 	/* Set the dinode as "bad" so it gets deleted */
 	fsck_blockmap_set(ip, ip->i_di.di_num.no_addr,
 			  _("corrupt"), gfs2_block_free);
diff --git a/gfs2/fsck/pass1b.c b/gfs2/fsck/pass1b.c
index 9a23197..0dcb306 100644
--- a/gfs2/fsck/pass1b.c
+++ b/gfs2/fsck/pass1b.c
@@ -52,66 +52,6 @@ static void log_inode_reference(struct duptree *dt, osi_list_t *tmp, int inval)
 }
 
 /* delete_all_dups - delete all duplicate records for a given inode */
-static void delete_all_dups(struct gfs2_inode *ip)
-{
-	struct osi_node *n, *next;
-	struct duptree *dt;
-	osi_list_t *tmp, *x;
-	struct inode_with_dups *id;
-	int found;
-
-	for (n = osi_first(&dup_blocks); n; n = next) {
-		next = osi_next(n);
-		dt = (struct duptree *)n;
-
-		found = 0;
-		id = NULL;
-
-		osi_list_foreach_safe(tmp, &dt->ref_invinode_list, x) {
-			id = osi_list_entry(tmp, struct inode_with_dups, list);
-			if (id->block_no == ip->i_di.di_num.no_addr) {
-				dup_listent_delete(dt, id);
-				found = 1;
-			}
-		}
-		osi_list_foreach_safe(tmp, &dt->ref_inode_list, x) {
-			id = osi_list_entry(tmp, struct inode_with_dups, list);
-			if (id->block_no == ip->i_di.di_num.no_addr) {
-				dup_listent_delete(dt, id);
-				found = 1;
-			}
-		}
-		if (!found)
-			continue;
-
-		if (dt->refs == 0) {
-			log_debug(_("This was the last reference: 0x%llx is "
-				    "no longer a duplicate.\n"),
-				  (unsigned long long)dt->block);
-			dup_delete(dt); /* not duplicate now */
-		} else {
-			log_debug(_("%d references remain to 0x%llx\n"),
-				  dt->refs, (unsigned long long)dt->block);
-			if (dt->refs > 1)
-				continue;
-
-			id = NULL;
-			osi_list_foreach(tmp, &dt->ref_invinode_list)
-				id = osi_list_entry(tmp,
-						    struct inode_with_dups,
-						    list);
-			osi_list_foreach(tmp, &dt->ref_inode_list)
-				id = osi_list_entry(tmp,
-						    struct inode_with_dups,
-						    list);
-			if (id)
-				log_debug("Last reference is from inode "
-					  "0x%llx\n",
-					  (unsigned long long)id->block_no);
-		}
-	}
-}
-
 /*
  * resolve_dup_references - resolve all but the last dinode that has a
  *                          duplicate reference to a given block.
diff --git a/gfs2/fsck/util.c b/gfs2/fsck/util.c
index 9d6f163..fd1b292 100644
--- a/gfs2/fsck/util.c
+++ b/gfs2/fsck/util.c
@@ -725,3 +725,62 @@ uint64_t *get_dir_hash(struct gfs2_inode *ip)
 	return tbl;
 }
 
+void delete_all_dups(struct gfs2_inode *ip)
+{
+	struct osi_node *n, *next;
+	struct duptree *dt;
+	osi_list_t *tmp, *x;
+	struct inode_with_dups *id;
+	int found;
+
+	for (n = osi_first(&dup_blocks); n; n = next) {
+		next = osi_next(n);
+		dt = (struct duptree *)n;
+
+		found = 0;
+		id = NULL;
+
+		osi_list_foreach_safe(tmp, &dt->ref_invinode_list, x) {
+			id = osi_list_entry(tmp, struct inode_with_dups, list);
+			if (id->block_no == ip->i_di.di_num.no_addr) {
+				dup_listent_delete(dt, id);
+				found = 1;
+			}
+		}
+		osi_list_foreach_safe(tmp, &dt->ref_inode_list, x) {
+			id = osi_list_entry(tmp, struct inode_with_dups, list);
+			if (id->block_no == ip->i_di.di_num.no_addr) {
+				dup_listent_delete(dt, id);
+				found = 1;
+			}
+		}
+		if (!found)
+			continue;
+
+		if (dt->refs == 0) {
+			log_debug(_("This was the last reference: 0x%llx is "
+				    "no longer a duplicate.\n"),
+				  (unsigned long long)dt->block);
+			dup_delete(dt); /* not duplicate now */
+		} else {
+			log_debug(_("%d references remain to 0x%llx\n"),
+				  dt->refs, (unsigned long long)dt->block);
+			if (dt->refs > 1)
+				continue;
+
+			id = NULL;
+			osi_list_foreach(tmp, &dt->ref_invinode_list)
+				id = osi_list_entry(tmp,
+						    struct inode_with_dups,
+						    list);
+			osi_list_foreach(tmp, &dt->ref_inode_list)
+				id = osi_list_entry(tmp,
+						    struct inode_with_dups,
+						    list);
+			if (id)
+				log_debug("Last reference is from inode "
+					  "0x%llx\n",
+					  (unsigned long long)id->block_no);
+		}
+	}
+}
diff --git a/gfs2/fsck/util.h b/gfs2/fsck/util.h
index 361b1a2..580acd8 100644
--- a/gfs2/fsck/util.h
+++ b/gfs2/fsck/util.h
@@ -187,6 +187,7 @@ extern char generic_interrupt(const char *caller, const char *where,
 extern char gfs2_getch(void);
 extern uint64_t find_free_blk(struct gfs2_sbd *sdp);
 extern uint64_t *get_dir_hash(struct gfs2_inode *ip);
+extern void delete_all_dups(struct gfs2_inode *ip);
 
 #define stack log_debug("<backtrace> - %s()\n", __func__)
 


More information about the cluster-commits mailing list