Gitweb:
http://git.fedorahosted.org/git/?p=gfs2-utils.git;a=commitdiff;h=74f4384b...
Commit: 74f4384b361eb05b40c463d40067a3f9a1b1b7da
Parent: 31710448d37825078494fb63c4af1f9dd83bcb24
Author: Andrew Price <anprice(a)redhat.com>
AuthorDate: Thu Oct 25 22:08:14 2012 +0100
Committer: Andrew Price <anprice(a)redhat.com>
CommitterDate: Thu Oct 25 22:29:21 2012 +0100
libgfs2: gfs2_get_bitmap performance enhancements
This patch takes the bit lookup strategy from the kernel code (an
amalgamation of gfs2_rbm_from_block and gfs2_testbit) to speed up
gfs2_get_bitmap, which is renamed lgfs2_get_bitmap.
Timings obtained running fsck.gfs2 on a 5% full, 10G local fs with 512
byte blocks (to maximize the number of leaf blocks) and many large
directories:
HEAD~2 HEAD
------- -------
2:15.70 2:10.03
2:14.32 2:09.89
2:14.32 2:09.83
2:14.66 2:09.84
2:14.30 2:09.89
2:14.62 2:10.23
2:14.58 2:09.64
2:14.50 2:09.68
2:14.99 2:09.49
2:14.79 2:09.97
For sanity the output of the new lgfs2_get_bitmap was checked against
the output of the old gfs2_get_bitmap over 1 million block state
lookups.
Signed-off-by: Andrew Price <anprice(a)redhat.com>
---
gfs2/edit/hexedit.c | 8 ++++----
gfs2/fsck/fsck.h | 2 +-
gfs2/fsck/metawalk.c | 2 +-
gfs2/libgfs2/fs_bits.c | 44 ++++++++++++++++++++++++--------------------
gfs2/libgfs2/lang.c | 2 +-
gfs2/libgfs2/libgfs2.h | 4 ++--
gfs2/libgfs2/rgrp.c | 17 ++++++-----------
gfs2/libgfs2/super.c | 2 ++
8 files changed, 41 insertions(+), 40 deletions(-)
diff --git a/gfs2/edit/hexedit.c b/gfs2/edit/hexedit.c
index ff0dca9..6f5f5af 100644
--- a/gfs2/edit/hexedit.c
+++ b/gfs2/edit/hexedit.c
@@ -698,7 +698,7 @@ int display_block_type(int from_restore)
(be32_to_cpu(mh->mh_type) == GFS2_METATYPE_RB))
type = 4;
else {
- type = gfs2_get_bitmap(&sbd, block, rgd);
+ type = lgfs2_get_bitmap(&sbd, block, rgd);
}
} else
type = 4;
@@ -726,7 +726,7 @@ int display_block_type(int from_restore)
print_gfs2(" blk ");
for (b = blknum; b < blknum + 4; b++) {
- btype = gfs2_get_bitmap(&sbd, b, rgd);
+ btype = lgfs2_get_bitmap(&sbd, b, rgd);
if (btype >= 0) {
print_gfs2("0x%x-%s ", b,
allocdesc[sbd.gfs1][btype]);
@@ -760,7 +760,7 @@ int display_block_type(int from_restore)
blknum += rgd->ri.ri_data0;
print_gfs2(" blk ");
for (b = blknum; b < blknum + 4; b++) {
- btype = gfs2_get_bitmap(&sbd, b, rgd);
+ btype = lgfs2_get_bitmap(&sbd, b, rgd);
if (btype >= 0) {
print_gfs2("0x%x-%s ", b,
allocdesc[sbd.gfs1][btype]);
@@ -2053,7 +2053,7 @@ static void find_change_block_alloc(int *newval)
else
printf("%d\n", *newval);
} else {
- type = gfs2_get_bitmap(&sbd, ablock, rgd);
+ type = lgfs2_get_bitmap(&sbd, ablock, rgd);
if (type < 0) {
printf("-1 (block invalid or part of "
"an rgrp).\n");
diff --git a/gfs2/fsck/fsck.h b/gfs2/fsck/fsck.h
index dd49280..ecd37ad 100644
--- a/gfs2/fsck/fsck.h
+++ b/gfs2/fsck/fsck.h
@@ -151,7 +151,7 @@ extern struct gfs_sb *sbd1;
static inline int valid_block(struct gfs2_sbd *sdp, uint64_t blkno)
{
return !((blkno > sdp->fssize) || (blkno <= sdp->sb_addr) ||
- (gfs2_get_bitmap(sdp, blkno, NULL) < 0));
+ (lgfs2_get_bitmap(sdp, blkno, NULL) < 0));
}
#endif /* _FSCK_H */
diff --git a/gfs2/fsck/metawalk.c b/gfs2/fsck/metawalk.c
index 24de901..f19c0f7 100644
--- a/gfs2/fsck/metawalk.c
+++ b/gfs2/fsck/metawalk.c
@@ -34,7 +34,7 @@ int check_n_fix_bitmap(struct gfs2_sbd *sdp, uint64_t blk,
rgd = gfs2_blk2rgrpd(sdp, blk);
- old_bitmap_state = gfs2_get_bitmap(sdp, blk, rgd);
+ old_bitmap_state = lgfs2_get_bitmap(sdp, blk, rgd);
if (old_bitmap_state < 0) {
log_err( _("Block %llu (0x%llx) is not represented in the "
"system bitmap; part of an rgrp or superblock.\n"),
diff --git a/gfs2/libgfs2/fs_bits.c b/gfs2/libgfs2/fs_bits.c
index fdc3bb3..94a612b 100644
--- a/gfs2/libgfs2/fs_bits.c
+++ b/gfs2/libgfs2/fs_bits.c
@@ -4,6 +4,7 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <limits.h>
#include "libgfs2.h"
@@ -175,14 +176,12 @@ int gfs2_set_bitmap(struct gfs2_sbd *sdp, uint64_t blkno, int
state)
*
* Returns: state on success, -1 on error
*/
-int gfs2_get_bitmap(struct gfs2_sbd *sdp, uint64_t blkno,
- struct rgrp_tree *rgd)
+int lgfs2_get_bitmap(struct gfs2_sbd *sdp, uint64_t blkno, struct rgrp_tree *rgd)
{
- int i, val;
- uint32_t rgrp_block;
- struct gfs2_bitmap *bits = NULL;
- unsigned int bit;
- unsigned char *byte;
+ uint64_t offset;
+ uint32_t i = 0;
+ char *byte;
+ unsigned int bit;
if (rgd == NULL) {
rgd = gfs2_blk2rgrpd(sdp, blkno);
@@ -190,23 +189,28 @@ int gfs2_get_bitmap(struct gfs2_sbd *sdp, uint64_t blkno,
return -1;
}
- rgrp_block = (uint32_t)(blkno - rgd->ri.ri_data0);
+ offset = blkno - rgd->ri.ri_data0;
+ if (offset > UINT_MAX) {
+ errno = EINVAL;
+ return -1;
+ }
+ if (offset >= rgd->ri.ri_data0 + rgd->ri.ri_data) {
+ errno = E2BIG;
+ return -1;
+ }
- for (i = 0; i < rgd->ri.ri_length; i++) {
- bits = &(rgd->bits[i]);
- if(rgrp_block < ((bits->bi_start + bits->bi_len)*GFS2_NBBY))
- break;
+ if (offset >= (rgd->bits->bi_start + rgd->bits->bi_len) * GFS2_NBBY) {
+ offset += (sizeof(struct gfs2_rgrp) - sizeof(struct gfs2_meta_header))
+ * GFS2_NBBY;
+ i = offset / sdp->sd_blocks_per_bitmap;
+ offset -= i * sdp->sd_blocks_per_bitmap;
}
- if (i >= rgd->ri.ri_length)
- return -1;
if (!rgd->bh || !rgd->bh[i])
- return 0;
- byte = (unsigned char *)(rgd->bh[i]->b_data + bits->bi_offset) +
- (rgrp_block/GFS2_NBBY - bits->bi_start);
- bit = (rgrp_block % GFS2_NBBY) * GFS2_BIT_SIZE;
+ return GFS2_BLKST_FREE;
- val = ((*byte >> bit) & GFS2_BIT_MASK);
+ byte = (rgd->bh[i]->b_data + rgd->bits[i].bi_offset) + (offset/GFS2_NBBY);
+ bit = (offset % GFS2_NBBY) * GFS2_BIT_SIZE;
- return val;
+ return (*byte >> bit) & GFS2_BIT_MASK;
}
diff --git a/gfs2/libgfs2/lang.c b/gfs2/libgfs2/lang.c
index 12ca7bd..ad9382f 100644
--- a/gfs2/libgfs2/lang.c
+++ b/gfs2/libgfs2/lang.c
@@ -329,7 +329,7 @@ static int ast_get_bitstate(uint64_t bn, struct gfs2_sbd *sbd)
return -1;
}
- state = gfs2_get_bitmap(sbd, bn, rgd);
+ state = lgfs2_get_bitmap(sbd, bn, rgd);
if (state == -1) {
fprintf(stderr, "Failed to acquire bitmap state for block
%"PRIu64"\n", bn);
return -1;
diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h
index bf65922..2b109fb 100644
--- a/gfs2/libgfs2/libgfs2.h
+++ b/gfs2/libgfs2/libgfs2.h
@@ -276,6 +276,7 @@ struct gfs2_sbd {
uint32_t sd_hash_bsize;
uint32_t sd_hash_bsize_shift;
uint32_t sd_hash_ptrs;
+ uint32_t sd_blocks_per_bitmap;
uint32_t sd_max_dirres;
uint32_t sd_max_height;
uint64_t sd_heightsize[GFS2_MAX_META_HEIGHT];
@@ -408,8 +409,7 @@ extern uint32_t gfs2_blkalloc_internal(struct rgrp_tree *rgd, uint32_t
goal,
extern int gfs2_check_range(struct gfs2_sbd *sdp, uint64_t blkno);
/* functions with blk #'s that are file system relative */
-extern int gfs2_get_bitmap(struct gfs2_sbd *sdp, uint64_t blkno,
- struct rgrp_tree *rgd);
+extern int lgfs2_get_bitmap(struct gfs2_sbd *sdp, uint64_t blkno, struct rgrp_tree
*rgd);
extern int gfs2_set_bitmap(struct gfs2_sbd *sdp, uint64_t blkno, int state);
/* fs_geometry.c */
diff --git a/gfs2/libgfs2/rgrp.c b/gfs2/libgfs2/rgrp.c
index c0f72fd..cbab2a3 100644
--- a/gfs2/libgfs2/rgrp.c
+++ b/gfs2/libgfs2/rgrp.c
@@ -98,17 +98,12 @@ int gfs2_compute_bitstructs(struct gfs2_sbd *sdp, struct rgrp_tree
*rgd)
*/
struct rgrp_tree *gfs2_blk2rgrpd(struct gfs2_sbd *sdp, uint64_t blk)
{
- struct osi_node *node = sdp->rgtree.osi_node;
- struct gfs2_rindex *ri;
-
- while (node) {
- struct rgrp_tree *rgd = (struct rgrp_tree *)node;
- ri = &rgd->ri;
-
- if (blk < ri->ri_addr)
- node = node->osi_left;
- else if (blk >= ri->ri_data0 + ri->ri_data)
- node = node->osi_right;
+ struct rgrp_tree *rgd = (struct rgrp_tree *)sdp->rgtree.osi_node;
+ while (rgd) {
+ if (blk < rgd->ri.ri_addr)
+ rgd = (struct rgrp_tree *)rgd->node.osi_left;
+ else if (blk >= rgd->ri.ri_data0 + rgd->ri.ri_data)
+ rgd = (struct rgrp_tree *)rgd->node.osi_right;
else
return rgd;
}
diff --git a/gfs2/libgfs2/super.c b/gfs2/libgfs2/super.c
index fdf0e60..8317862 100644
--- a/gfs2/libgfs2/super.c
+++ b/gfs2/libgfs2/super.c
@@ -116,6 +116,8 @@ int read_sb(struct gfs2_sbd *sdp)
}
sdp->fssize = lseek(sdp->device_fd, 0, SEEK_END) / sdp->sd_sb.sb_bsize;
sdp->sb_addr = GFS2_SB_ADDR * GFS2_BASIC_BLOCK / sdp->bsize;
+ sdp->sd_blocks_per_bitmap = (sdp->sd_sb.sb_bsize - sizeof(struct
gfs2_meta_header))
+ * GFS2_NBBY;
return 0;
}