Gitweb: http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=5df... Commit: 5df69b1d9f020df9e97629240196596c330567fa Parent: 611c213c35e1af8dc36f3b15fccc5ee5c352eaa3 Author: Bob Peterson bob@ganesha.peterson AuthorDate: Fri Jan 22 14:38:05 2010 -0600 Committer: Bob Peterson rpeterso@redhat.com CommitterDate: Tue Jan 26 14:39:31 2010 -0600
fsck.gfs2: separate check_data function in check_metatree
Function check_metatree had a loop for checking data blocks. I broke this loop into its own function. That serves two purposes: First, it makes check_metatree smaller and easier to read (it's already big an unruly). Second, it avoids looping unnecessarily when the caller has no check_data() function of its own. Net result is faster code.
rhbz#455300 --- gfs2/fsck/metawalk.c | 72 ++++++++++++++++++++++++++++++++++++++------------ 1 files changed, 55 insertions(+), 17 deletions(-)
diff --git a/gfs2/fsck/metawalk.c b/gfs2/fsck/metawalk.c index 13290e1..2ad47fe 100644 --- a/gfs2/fsck/metawalk.c +++ b/gfs2/fsck/metawalk.c @@ -1157,6 +1157,49 @@ fail: }
/** + * check_data - check all data pointers for a given buffer + * This does not include "data" blocks that are really + * hash table blocks for directories. + * + * @ip: + * + * returns: +ENOENT if there are too many bad pointers + * -1 if a more serious error occurred. + * 0 if no errors occurred + * 1 if errors were found and corrected + * 2 (ENOENT) is there were too many bad pointers + */ +static int check_data(struct gfs2_inode *ip, struct metawalk_fxns *pass, + uint64_t *ptr_start, char *ptr_end, + uint64_t *blks_checked) +{ + int error = 0, rc = 0; + uint64_t block, *ptr; + + /* If there isn't much pointer corruption check the pointers */ + for (ptr = ptr_start ; (char *)ptr < ptr_end && !fsck_abort; ptr++) { + if (!*ptr) + continue; + + if (skip_this_pass || fsck_abort) + return error; + block = be64_to_cpu(*ptr); + /* It's important that we don't call gfs2_check_range and + bypass calling check_data on invalid blocks because that + would defeat the rangecheck_block related functions in + pass1. Therefore the individual check_data functions + should do a range check. */ + rc = pass->check_data(ip, block, pass->private); + if (rc < 0) + return rc; + if (!error && rc) + error = rc; + (*blks_checked)++; + } + return error; +} + +/** * check_metatree * @ip: * @rgd: @@ -1167,11 +1210,10 @@ int check_metatree(struct gfs2_inode *ip, struct metawalk_fxns *pass) osi_list_t metalist[GFS2_MAX_META_HEIGHT]; osi_list_t *list; struct gfs2_buffer_head *bh; - uint64_t block, *ptr; uint32_t height = ip->i_di.di_height; int i, head_size; uint64_t blks_checked = 0; - int error; + int error, rc;
if (!height && !S_ISDIR(ip->i_di.di_mode)) return 0; @@ -1227,23 +1269,19 @@ int check_metatree(struct gfs2_inode *ip, struct metawalk_fxns *pass) } head_size = sizeof(struct gfs2_dinode); } - ptr = (uint64_t *)(bh->b_data + head_size);
- for ( ; (char *)ptr < (bh->b_data + ip->i_sbd->bsize); ptr++) { - if (!*ptr) - continue; - - block = be64_to_cpu(*ptr); + if (pass->check_data) + rc = check_data(ip, pass, (uint64_t *) + (bh->b_data + head_size), + (bh->b_data + ip->i_sbd->bsize), + &blks_checked); + else + rc = 0;
- if(pass->check_data && - (pass->check_data(ip, block, pass->private) < 0)) { - stack; - return -1; - } - blks_checked++; - if (ip->i_di.di_blocks > COMFORTABLE_BLKS) - big_file_comfort(ip, blks_checked); - } + if (rc && (!error || rc < 0)) + error = rc; + if (ip->i_di.di_blocks > COMFORTABLE_BLKS) + big_file_comfort(ip, blks_checked); if (bh == ip->i_bh) osi_list_del(&bh->b_altlist); else
cluster-commits@lists.stg.fedorahosted.org