Gitweb:
http://git.fedorahosted.org/git/?p=gfs2-utils.git;a=commitdiff;h=a59b70e8...
Commit: a59b70e8d2b1467171ef3200350959079bef8561
Parent: 433d06c67ada88170ecf500d061383c7ca7a7957
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Wed Jun 1 09:42:27 2016 -0500
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Thu Jun 2 10:57:10 2016 -0500
fsck.gfs2: Speed up fsck.gfs2 with a new inode rgrp pointer
This patch tries to speed up fsck.gfs2 by adding a new field in the
in-core inode which points to the inode's rgrp. Most blocks will be
contained within the rgrp, so we save time looking up the rgrp by
first checking if the desired inode block falls within the inode's
rgrp.
Signed-off-by: Bob Peterson <rpeterso(a)redhat.com>
---
gfs2/fsck/afterpass1_common.c | 3 ++-
gfs2/fsck/fsck.h | 12 +++++++++++-
gfs2/fsck/initialize.c | 2 +-
gfs2/fsck/metawalk.c | 23 +++++++++++++++--------
gfs2/fsck/metawalk.h | 5 +++--
gfs2/fsck/pass1.c | 25 +++++++++++++++----------
gfs2/fsck/pass1b.c | 3 ++-
gfs2/fsck/pass2.c | 2 +-
gfs2/fsck/pass3.c | 6 ++++--
gfs2/libgfs2/libgfs2.h | 1 +
10 files changed, 55 insertions(+), 27 deletions(-)
diff --git a/gfs2/fsck/afterpass1_common.c b/gfs2/fsck/afterpass1_common.c
index 95fdbf8..0632695 100644
--- a/gfs2/fsck/afterpass1_common.c
+++ b/gfs2/fsck/afterpass1_common.c
@@ -108,7 +108,8 @@ static int delete_block_if_notdup(struct gfs2_inode *ip, uint64_t
block,
(unsigned long long)ip->i_di.di_num.no_addr,
(unsigned long long)block, (unsigned long long)block);
} else {
- check_n_fix_bitmap(ip->i_sbd, block, 0, GFS2_BLKST_FREE);
+ check_n_fix_bitmap(ip->i_sbd, ip->i_rgd, block, 0,
+ GFS2_BLKST_FREE);
}
return meta_is_good;
}
diff --git a/gfs2/fsck/fsck.h b/gfs2/fsck/fsck.h
index 09b96ed..c4e6e3b 100644
--- a/gfs2/fsck/fsck.h
+++ b/gfs2/fsck/fsck.h
@@ -108,7 +108,8 @@ enum rgindex_trust_level { /* how far can we trust our RG index? */
extern struct gfs2_inode *fsck_load_inode(struct gfs2_sbd *sdp, uint64_t block);
extern struct gfs2_inode *fsck_inode_get(struct gfs2_sbd *sdp,
- struct gfs2_buffer_head *bh);
+ struct rgrp_tree *rgd,
+ struct gfs2_buffer_head *bh);
extern void fsck_inode_put(struct gfs2_inode **ip);
extern int initialize(struct gfs2_sbd *sdp, int force_check, int preen,
@@ -163,4 +164,13 @@ static inline int valid_block(struct gfs2_sbd *sdp, uint64_t blkno)
(lgfs2_get_bitmap(sdp, blkno, NULL) < 0));
}
+static inline int rgrp_contains_block(struct rgrp_tree *rgd, uint64_t blk)
+{
+ if (blk < rgd->ri.ri_addr)
+ return 0;
+ if (blk >= rgd->ri.ri_data0 + rgd->ri.ri_data)
+ return 0;
+ return 1;
+}
+
#endif /* _FSCK_H */
diff --git a/gfs2/fsck/initialize.c b/gfs2/fsck/initialize.c
index 652eec3..75f050b 100644
--- a/gfs2/fsck/initialize.c
+++ b/gfs2/fsck/initialize.c
@@ -300,7 +300,7 @@ static void check_rgrp_integrity(struct gfs2_sbd *sdp, struct
rgrp_tree *rgd,
bh = bread(sdp, diblock);
if (!gfs2_check_meta(bh, GFS2_METATYPE_DI)) {
struct gfs2_inode *ip =
- fsck_inode_get(sdp, bh);
+ fsck_inode_get(sdp, rgd, bh);
if (ip->i_di.di_blocks > 1) {
blks_2free +=
ip->i_di.di_blocks - 1;
diff --git a/gfs2/fsck/metawalk.c b/gfs2/fsck/metawalk.c
index 0e279e5..7261422 100644
--- a/gfs2/fsck/metawalk.c
+++ b/gfs2/fsck/metawalk.c
@@ -29,11 +29,10 @@
is used to set the latter. The two must be kept in sync, otherwise
you'll get bitmap mismatches. This function checks the status of the
bitmap whenever the blockmap changes, and fixes it accordingly. */
-int check_n_fix_bitmap(struct gfs2_sbd *sdp, uint64_t blk, int error_on_dinode,
- int new_state)
+int check_n_fix_bitmap(struct gfs2_sbd *sdp, struct rgrp_tree *rgd,
+ uint64_t blk, int error_on_dinode, int new_state)
{
int old_state;
- struct rgrp_tree *rgd;
int treat_as_inode = 0;
int rewrite_rgrp = 0;
struct gfs_rgrp *gfs1rg;
@@ -42,7 +41,9 @@ int check_n_fix_bitmap(struct gfs2_sbd *sdp, uint64_t blk, int
error_on_dinode,
/* gfs1 descriptions: */
{"free", "data", "free meta", "metadata",
"reserved"}};
- rgd = gfs2_blk2rgrpd(sdp, blk);
+ if (rgd == NULL || !rgrp_contains_block(rgd, blk))
+ rgd = gfs2_blk2rgrpd(sdp, blk);
+
gfs1rg = (struct gfs_rgrp *)&rgd->rg;
old_state = lgfs2_get_bitmap(sdp, blk, rgd);
@@ -208,7 +209,8 @@ int _fsck_bitmap_set(struct gfs2_inode *ip, uint64_t bblock,
prev_mark = mark;
prev_caller = caller;
}
- error = check_n_fix_bitmap(ip->i_sbd, bblock, error_on_dinode, mark);
+ error = check_n_fix_bitmap(ip->i_sbd, ip->i_rgd, bblock,
+ error_on_dinode, mark);
if (error < 0)
log_err(_("This block is not represented in the bitmap.\n"));
return error;
@@ -273,18 +275,23 @@ struct gfs2_inode *fsck_load_inode(struct gfs2_sbd *sdp, uint64_t
block)
/* fsck_inode_get - same as inode_get() in libgfs2 but system inodes
get special treatment. */
-struct gfs2_inode *fsck_inode_get(struct gfs2_sbd *sdp,
+struct gfs2_inode *fsck_inode_get(struct gfs2_sbd *sdp, struct rgrp_tree *rgd,
struct gfs2_buffer_head *bh)
{
struct gfs2_inode *sysip;
+ struct gfs2_inode *ip;
sysip = fsck_system_inode(sdp, bh->b_blocknr);
if (sysip)
return sysip;
if (sdp->gfs1)
- return lgfs2_gfs_inode_get(sdp, bh);
- return lgfs2_inode_get(sdp, bh);
+ ip = lgfs2_gfs_inode_get(sdp, bh);
+ else
+ ip = lgfs2_inode_get(sdp, bh);
+ if (ip)
+ ip->i_rgd = rgd;
+ return ip;
}
/* fsck_inode_put - same as inode_put() in libgfs2 but system inodes
diff --git a/gfs2/fsck/metawalk.h b/gfs2/fsck/metawalk.h
index b16e57d..119efee 100644
--- a/gfs2/fsck/metawalk.h
+++ b/gfs2/fsck/metawalk.h
@@ -22,8 +22,9 @@ extern int check_leaf(struct gfs2_inode *ip, int lindex,
extern int _fsck_bitmap_set(struct gfs2_inode *ip, uint64_t bblock,
const char *btype, int mark, int error_on_dinode,
const char *caller, int line);
-extern int check_n_fix_bitmap(struct gfs2_sbd *sdp, uint64_t blk,
- int error_on_dinode, int new_state);
+extern int check_n_fix_bitmap(struct gfs2_sbd *sdp, struct rgrp_tree *rgd,
+ uint64_t blk, int error_on_dinode,
+ int new_state);
extern struct duptree *dupfind(uint64_t block);
extern struct gfs2_inode *fsck_system_inode(struct gfs2_sbd *sdp,
uint64_t block);
diff --git a/gfs2/fsck/pass1.c b/gfs2/fsck/pass1.c
index 6908ac7..3a1931d 100644
--- a/gfs2/fsck/pass1.c
+++ b/gfs2/fsck/pass1.c
@@ -248,8 +248,9 @@ static int resuscitate_metalist(struct gfs2_inode *ip, uint64_t
block,
ip->i_sbd->gfs1 ?
GFS2_BLKST_DINODE : GFS2_BLKST_USED);
else
- check_n_fix_bitmap(ip->i_sbd, block, 0, ip->i_sbd->gfs1 ?
- GFS2_BLKST_DINODE : GFS2_BLKST_USED);
+ check_n_fix_bitmap(ip->i_sbd, ip->i_rgd, block, 0,
+ ip->i_sbd->gfs1 ?
+ GFS2_BLKST_DINODE : GFS2_BLKST_USED);
bc->indir_count++;
return meta_is_good;
}
@@ -296,7 +297,8 @@ static int resuscitate_dentry(struct gfs2_inode *ip, struct
gfs2_dirent *dent,
fsck_blockmap_set(ip, block, _("system file"),
GFS2_BLKST_DINODE);
else
- check_n_fix_bitmap(sdp, block, 0, GFS2_BLKST_DINODE);
+ check_n_fix_bitmap(sdp, ip->i_rgd, block, 0,
+ GFS2_BLKST_DINODE);
/* Return the number of leaf entries so metawalk doesn't flag this
leaf as having none. */
*count = be16_to_cpu(((struct gfs2_leaf *)bh->b_data)->lf_entries);
@@ -1594,13 +1596,14 @@ static void check_i_goal(struct gfs2_sbd *sdp, struct gfs2_inode
*ip)
* handle_di - This is now a wrapper function that takes a gfs2_buffer_head
* and calls handle_ip, which takes an in-code dinode structure.
*/
-static int handle_di(struct gfs2_sbd *sdp, struct gfs2_buffer_head *bh)
+static int handle_di(struct gfs2_sbd *sdp, struct rgrp_tree *rgd,
+ struct gfs2_buffer_head *bh)
{
int error = 0;
uint64_t block = bh->b_blocknr;
struct gfs2_inode *ip;
- ip = fsck_inode_get(sdp, bh);
+ ip = fsck_inode_get(sdp, rgd, bh);
if (ip->i_di.di_num.no_addr != block) {
log_err( _("Inode #%llu (0x%llx): Bad inode address found: %llu "
@@ -1671,7 +1674,8 @@ static int check_system_inode(struct gfs2_sbd *sdp,
(unsigned long long)iblock,
(unsigned long long)iblock);
gfs2_blockmap_set(bl, iblock, GFS2_BLKST_FREE);
- check_n_fix_bitmap(sdp, iblock, 0, GFS2_BLKST_FREE);
+ check_n_fix_bitmap(sdp, (*sysinode)->i_rgd, iblock, 0,
+ GFS2_BLKST_FREE);
inode_put(sysinode);
}
}
@@ -1955,7 +1959,7 @@ static int pass1_process_bitmap(struct gfs2_sbd *sdp, struct
rgrp_tree *rgd, uin
(unsigned long long)block,
(unsigned long long)block,
block_type_string(q));
- ip = fsck_inode_get(sdp, bh);
+ ip = fsck_inode_get(sdp, rgd, bh);
if (is_inode && ip->i_di.di_num.no_addr == block)
add_duplicate_ref(ip, block, ref_is_inode, 0,
INODE_VALID);
@@ -1991,8 +1995,9 @@ static int pass1_process_bitmap(struct gfs2_sbd *sdp, struct
rgrp_tree *rgd, uin
"%llu (0x%llx)\n"),
(unsigned long long)block,
(unsigned long long)block);
- check_n_fix_bitmap(sdp, block, 0, GFS2_BLKST_FREE);
- } else if (handle_di(sdp, bh) < 0) {
+ check_n_fix_bitmap(sdp, rgd, block, 0,
+ GFS2_BLKST_FREE);
+ } else if (handle_di(sdp, rgd, bh) < 0) {
stack;
brelse(bh);
gfs2_special_free(&gfs1_rindex_blks);
@@ -2206,7 +2211,7 @@ int pass1(struct gfs2_sbd *sdp)
}
/* rgrps and bitmaps don't have bits to represent
their blocks, so don't do this:
- check_n_fix_bitmap(sdp, rgd->ri.ri_addr + i, 0,
+ check_n_fix_bitmap(sdp, rgd, rgd->ri.ri_addr + i, 0,
gfs2_meta_rgrp);*/
}
diff --git a/gfs2/fsck/pass1b.c b/gfs2/fsck/pass1b.c
index 6dec193..62686fe 100644
--- a/gfs2/fsck/pass1b.c
+++ b/gfs2/fsck/pass1b.c
@@ -775,7 +775,8 @@ static int handle_dup_blk(struct gfs2_sbd *sdp, struct duptree *dt)
(unsigned long long)dup_blk);
if (dh.dt)
dup_delete(dh.dt);
- check_n_fix_bitmap(sdp, dup_blk, 0, GFS2_BLKST_FREE);
+ check_n_fix_bitmap(sdp, NULL, dup_blk, 0,
+ GFS2_BLKST_FREE);
}
}
return 0;
diff --git a/gfs2/fsck/pass2.c b/gfs2/fsck/pass2.c
index ffd58dc..d072634 100644
--- a/gfs2/fsck/pass2.c
+++ b/gfs2/fsck/pass2.c
@@ -2036,7 +2036,7 @@ static int pass2_check_dir(struct gfs2_sbd *sdp, struct gfs2_inode
*ip)
log_debug(_("Directory block %lld (0x%llx) is now marked as
'invalid'\n"),
(unsigned long long)dirblk, (unsigned long long)dirblk);
- check_n_fix_bitmap(sdp, dirblk, 0, GFS2_BLKST_FREE);
+ check_n_fix_bitmap(sdp, ip->i_rgd, dirblk, 0, GFS2_BLKST_FREE);
}
if (!ds.dotdir) {
diff --git a/gfs2/fsck/pass3.c b/gfs2/fsck/pass3.c
index 85d7e36..4b9c54d 100644
--- a/gfs2/fsck/pass3.c
+++ b/gfs2/fsck/pass3.c
@@ -253,7 +253,8 @@ int pass3(struct gfs2_sbd *sdp)
di->dinode.no_addr,
(unsigned long long)
di->dinode.no_addr);
- check_n_fix_bitmap(sdp, di->dinode.no_addr,
+ check_n_fix_bitmap(sdp, ip->i_rgd,
+ di->dinode.no_addr,
0, GFS2_BLKST_FREE);
fsck_inode_put(&ip);
break;
@@ -274,7 +275,8 @@ int pass3(struct gfs2_sbd *sdp)
"marked as free\n"),
(unsigned long long)di->dinode.no_addr,
(unsigned long long)di->dinode.no_addr);
- check_n_fix_bitmap(sdp, di->dinode.no_addr, 0,
+ check_n_fix_bitmap(sdp, ip->i_rgd,
+ di->dinode.no_addr, 0,
GFS2_BLKST_FREE);
log_err( _("The block was cleared\n"));
fsck_inode_put(&ip);
diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h
index d6c54b3..5414a20 100644
--- a/gfs2/libgfs2/libgfs2.h
+++ b/gfs2/libgfs2/libgfs2.h
@@ -235,6 +235,7 @@ struct gfs2_inode {
struct gfs2_dinode i_di;
struct gfs2_buffer_head *i_bh;
struct gfs2_sbd *i_sbd;
+ struct rgrp_tree *i_rgd; /* performance hint */
};
struct master_dir