commit 1c9c96f17d03c51fd875eea94f14f517f2c2c446 Author: Bob Peterson <rpeterso@redhat.com> Date: Thu Aug 4 14:40:32 2011 -0500 fsck.gfs can not check file system with 500,000 files This patch allows fsck.gfs2 to properly process "continuation leaf blocks" in directories. This enables gfs_fsck to process directories properly when they get very big. rhbz#704328 diff --git a/gfs/gfs_fsck/metawalk.c b/gfs/gfs_fsck/metawalk.c index e28a1cc..e14d4dc 100644 --- a/gfs/gfs_fsck/metawalk.c +++ b/gfs/gfs_fsck/metawalk.c @@ -251,35 +251,39 @@ static int check_leaf_blks(struct fsck_inode *ip, int *update, ref_count++; continue; } - if(check_range(sbp, old_leaf) == 0 && ref_count != exp_count){ - log_err("Dir #%"PRIu64" has an incorrect number " - "of pointers to leaf #%"PRIu64"\n" - "\tFound: %u, Expected: %u\n", - ip->i_num.no_addr, old_leaf, ref_count, - exp_count); - errors_found++; - if (query(ip->i_sbd, "Attempt to fix it? (y/n) ")) { - int factor = 0, divisor = ref_count; - - errors_corrected++; - get_and_read_buf(sbp, old_leaf, &lbh); - while (divisor > 1) { - factor++; - divisor /= 2; + do { + if(check_range(sbp, old_leaf) == 0 && + ref_count != exp_count){ + log_err("Dir #%"PRIu64" has an incorrect " + "number of pointers to leaf #%"PRIu64 + "\n\tFound: %u, Expected: %u\n", + ip->i_num.no_addr, old_leaf, ref_count, + exp_count); + errors_found++; + if (query(ip->i_sbd, "Attempt to fix it? " + "(y/n) ")) { + int factor = 0, divisor = ref_count; + + errors_corrected++; + get_and_read_buf(sbp, old_leaf, &lbh); + while (divisor > 1) { + factor++; + divisor /= 2; + } + gfs_leaf_in(&oldleaf, BH_DATA(lbh)); + oldleaf.lf_depth = ip->i_di.di_depth - + factor; + gfs_leaf_out(&oldleaf, BH_DATA(lbh)); + write_buf(sbp, lbh, 0); + relse_buf(sbp, lbh); } - gfs_leaf_in(&oldleaf, BH_DATA(lbh)); - oldleaf.lf_depth = ip->i_di.di_depth - factor; - gfs_leaf_out(&oldleaf, BH_DATA(lbh)); - write_buf(sbp, lbh, 0); - relse_buf(sbp, lbh); + else + return 1; } - else - return 1; - } - ref_count = 1; + ref_count = 1; + + count = 0; - count = 0; - do { if (fsck_abort) break; /* Make sure the block number is in range. */ @@ -376,19 +380,16 @@ static int check_leaf_blks(struct fsck_inode *ip, int *update, } relse_buf(sbp, lbh); } - /* FIXME: Need to get entry count and - * compare it against leaf->lf_entries */ - break; /* not a chain; go back to outer loop */ - } else { + } else relse_buf(sbp, lbh); - if(!leaf.lf_next) - break; - leaf_no = leaf.lf_next; - log_debug("Leaf chain detected.\n"); - } + old_leaf = leaf_no; + memcpy(&oldleaf, &leaf, sizeof(oldleaf)); + if (!leaf.lf_next) + break; + leaf_no = leaf.lf_next; + log_debug("Leaf chain 0x%llx detected.\n", + (unsigned long long)leaf_no); } while(1); /* while we have chained leaf blocks */ - old_leaf = leaf_no; - memcpy(&oldleaf, &leaf, sizeof(oldleaf)); } /* for every leaf block */ return 0; }