Gitweb: http://git.fedorahosted.org/git/?p=cluster.git;a=commitdiff;h=bdce9f370fc437... Commit: bdce9f370fc437774585d6a4264afdfbeebabc4b Parent: fd8905389d16ff6f5fbaaf525b6fbcdf2d283733 Author: Bob Peterson rpeterso@redhat.com AuthorDate: Thu Jun 16 13:50:54 2011 -0500 Committer: Bob Peterson rpeterso@redhat.com CommitterDate: Fri Apr 5 06:24:18 2013 -0700
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#877150 --- 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 e0706e8..3498739 100644 --- a/gfs2/fsck/fs_recovery.c +++ b/gfs2/fsck/fs_recovery.c @@ -648,20 +648,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 a26ed84..f413250 100644 --- a/gfs2/fsck/initialize.c +++ b/gfs2/fsck/initialize.c @@ -406,6 +406,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 @@ -516,14 +562,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 ************* *******************************************************************/ @@ -1120,6 +1161,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)) {
cluster-commits@lists.fedorahosted.org