[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[Cluster-devel] [gfs2-utils PATCH 47/47] 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 c7122ac..e4e3067 100644
--- a/gfs2/fsck/metawalk.c
+++ b/gfs2/fsck/metawalk.c
@@ -1537,6 +1537,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__)
 
-- 
1.7.11.7


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]