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