cluster: RHEL6 - fsck.gfs2 only rebuilds one missing journal at a time

Bob Peterson rpeterso at fedoraproject.org
Thu Jun 16 19:26:55 UTC 2011


Gitweb:        http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=0b505a0b890dfe8898a612cd45667f0ba2086304
Commit:        0b505a0b890dfe8898a612cd45667f0ba2086304
Parent:        d02df4bcd1aee3ed287ee8f8c08c34c47db4cd1e
Author:        Bob Peterson <rpeterso at redhat.com>
AuthorDate:    Thu Jun 16 13:50:54 2011 -0500
Committer:     Bob Peterson <rpeterso at redhat.com>
CommitterDate: Thu Jun 16 13:50:54 2011 -0500

fsck.gfs2 only rebuilds one missing journal at a time

This patch allows fsck.gfs2 to rebuild multiple journals in a single run.
It figures out the correct number of journals based on the number of entries
in the per_node directory.  If per_node is missing, it reverts to its previous
behavior of rebuilding a single journal.

rhbz#683104
---
 gfs2/fsck/fs_recovery.c |   16 +++++++++---
 gfs2/fsck/initialize.c  |   62 ++++++++++++++++++++++++++++++++++++++++------
 2 files changed, 66 insertions(+), 12 deletions(-)

diff --git a/gfs2/fsck/fs_recovery.c b/gfs2/fsck/fs_recovery.c
index 07c1552..b9d856e 100644
--- a/gfs2/fsck/fs_recovery.c
+++ b/gfs2/fsck/fs_recovery.c
@@ -636,20 +636,28 @@ int ji_update(struct gfs2_sbd *sdp)
 		return -1;
 	}
 
-	if(!(sdp->md.journal = calloc(ip->i_di.di_entries - 2, sizeof(struct gfs2_inode *)))) {
+	/* The per_node directory will have 3 directory entries per node,
+	   plus two for "." and "..".  So we subtract the 2 and divide by 3.
+	   If per_node is missing or damaged, we have to trust jindex has
+	   the correct number of entries. */
+	if (sdp->md.pinode) /* if per_node was read in properly */
+		sdp->md.journals = (sdp->md.pinode->i_di.di_entries - 2) / 3;
+	else
+		sdp->md.journals = ip->i_di.di_entries - 2;
+
+	if(!(sdp->md.journal = calloc(sdp->md.journals,
+				      sizeof(struct gfs2_inode *)))) {
 		log_err("Unable to allocate journal index\n");
 		return -1;
 	}
-	sdp->md.journals = 0;
 	memset(journal_name, 0, sizeof(*journal_name));
-	for(i = 0; i < ip->i_di.di_entries - 2; i++) {
+	for (i = 0; i < sdp->md.journals; i++) {
 		/* FIXME check snprintf return code */
 		snprintf(journal_name, JOURNAL_NAME_SIZE, "journal%u", i);
 		gfs2_lookupi(sdp->md.jiinode, journal_name, strlen(journal_name),
 			     &jip);
 		sdp->md.journal[i] = jip;
 	}
-	sdp->md.journals = ip->i_di.di_entries - 2;
 	return 0;
 
 }
diff --git a/gfs2/fsck/initialize.c b/gfs2/fsck/initialize.c
index 469f022..5a6fc6e 100644
--- a/gfs2/fsck/initialize.c
+++ b/gfs2/fsck/initialize.c
@@ -391,6 +391,52 @@ static int rebuild_master(struct gfs2_sbd *sdp)
 }
 
 /**
+ * lookup_per_node - Make sure the per_node directory is read in
+ *
+ * This function is used to read in the per_node directory.  It is called
+ * twice.  The first call tries to read in the dinode early on.  That ensures
+ * that if any journals are missing, we can figure out the number of journals
+ * from per_node.  However, we unfortunately can't rebuild per_node at that
+ * point in time because our resource groups aren't read in yet.
+ * The second time it's called is much later when we can rebuild it.
+ *
+ * allow_rebuild: 0 if rebuilds are not allowed
+ *                1 if rebuilds are allowed
+ */
+static void lookup_per_node(struct gfs2_sbd *sdp, int allow_rebuild)
+{
+	if (sdp->md.pinode)
+		return;
+
+	gfs2_lookupi(sdp->master_dir, "per_node", 8, &sdp->md.pinode);
+	if (sdp->md.pinode)
+		return;
+	if (!allow_rebuild) {
+		log_err( _("The gfs2 system per_node directory "
+			   "inode is missing, so we might not be \nable to "
+			   "rebuild missing journals this run.\n"));
+		return;
+	}
+
+	if (query( _("The gfs2 system per_node directory "
+		     "inode is missing. Okay to rebuild it? (y/n) "))) {
+		int err;
+
+		err = build_per_node(sdp);
+		if (err) {
+			log_crit(_("Error rebuilding per_node directory: %s\n"),
+				 strerror(err));
+			exit(-1);
+		}
+	}
+	gfs2_lookupi(sdp->master_dir, "per_node", 8, &sdp->md.pinode);
+	if (!sdp->md.pinode) {
+		log_err( _("Unable to rebuild per_node; aborting.\n"));
+		exit(-1);
+	}
+}
+
+/**
  * init_system_inodes
  *
  * Returns: 0 on success, -1 on failure
@@ -520,14 +566,9 @@ static int init_system_inodes(struct gfs2_sbd *sdp)
 			build_quota(sdp);
 	}
 
-	gfs2_lookupi(sdp->master_dir, "per_node", 8, &sdp->md.pinode);
-	if (!sdp->md.pinode) {
-		if (query( _("The gfs2 system per_node directory inode is "
-			     "missing. Okay to rebuild it? (y/n) ")))
-			build_per_node(sdp);
-	}
-
-	/* FIXME fill in per_node structure */
+	/* Try to lookup the per_node inode.  If it was missing, it is now
+	   safe to rebuild it. */
+	lookup_per_node(sdp, 1);
 	/*******************************************************************
 	 *******  Now, set boundary fields in the super block  *************
 	 *******************************************************************/
@@ -1126,6 +1167,11 @@ int initialize(struct gfs2_sbd *sbp, int force_check, int preen,
 					     sbp->sd_sb.sb_master_dir.no_addr);
 	}
 
+	/* Look up the "per_node" inode.  If there are journals missing, we
+	   need to figure out what's missing from per_node. And we need all
+	   our journals to be there before we can replay them. */
+	lookup_per_node(sbp, 0);
+
 	/* verify various things */
 
 	if(replay_journals(sbp, preen, force_check, &clean_journals)) {


More information about the cluster-commits mailing list