Gitweb:
http://git.fedorahosted.org/git/gfs2-utils.git?p=gfs2-utils.git;a=commitd...
Commit: 96e3a7f031d04d792b1e24758849015942631593
Parent: 8331ddfd39725e0d206633488cf5582c252e9aa5
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Thu Jun 16 13:37:10 2011 -0500
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Thu Jun 16 13:37:10 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 | 68 +++++++++++++++++++++++++++++++++++++---------
2 files changed, 66 insertions(+), 18 deletions(-)
diff --git a/gfs2/fsck/fs_recovery.c b/gfs2/fsck/fs_recovery.c
index 21f6db1..da06598 100644
--- a/gfs2/fsck/fs_recovery.c
+++ b/gfs2/fsck/fs_recovery.c
@@ -638,20 +638,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 c5dc7ef..697671c 100644
--- a/gfs2/fsck/initialize.c
+++ b/gfs2/fsck/initialize.c
@@ -449,6 +449,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
@@ -607,20 +653,9 @@ static int init_system_inodes(struct gfs2_sbd *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) "))) {
- err = build_per_node(sdp);
- if (err) {
- log_crit(_("Error rebuilding per_node directory: %s\n"),
- strerror(err));
- exit(-1);
- }
- }
- }
-
- /* 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 *************
*******************************************************************/
@@ -1219,6 +1254,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)) {