commit d6e3399a259167c1762651586ea062cf7d0c6c30 Author: Bob Peterson <bob@ganesha.peterson> Date: Wed Nov 25 14:34:08 2009 -0600 Simplify bitmap/block list structures This patch eliminates structures within structures to simplify the code and improve performance. rhbz#455300 diff --git a/gfs2/edit/savemeta.c b/gfs2/edit/savemeta.c index 8959442..50c9e2a 100644 --- a/gfs2/edit/savemeta.c +++ b/gfs2/edit/savemeta.c @@ -47,7 +47,7 @@ struct saved_metablock { struct saved_metablock *savedata; uint64_t last_fs_block, last_reported_block, blks_saved, total_out, pct; -struct gfs2_block_list *blocklist = NULL; +struct gfs2_bmap *blocklist = NULL; uint64_t journal_blocks[MAX_JOURNALS_SAVED]; uint64_t gfs1_journal_size = 0; /* in blocks */ int journals_found = 0; @@ -588,8 +588,8 @@ void savemeta(char *out_fn, int saveoption) fflush(stdout); } if (!slow) { - blocklist = gfs2_block_list_create(&sbd, last_fs_block + 1, - &memreq); + blocklist = gfs2_bmap_create(&sbd, last_fs_block + 1, + &memreq); if (!blocklist) slow = TRUE; } @@ -683,7 +683,7 @@ void savemeta(char *out_fn, int saveoption) } /* Clean up */ if (blocklist) - gfs2_block_list_destroy(&sbd, blocklist); + gfs2_bmap_destroy(&sbd, blocklist); /* There may be a gap between end of file system and end of device */ /* so we tell the user that we've processed everything. */ block = last_fs_block; diff --git a/gfs2/fsck/fsck.h b/gfs2/fsck/fsck.h index 57dd6b4..7cf0d8b 100644 --- a/gfs2/fsck/fsck.h +++ b/gfs2/fsck/fsck.h @@ -97,7 +97,7 @@ extern struct gfs2_options opts; extern struct gfs2_inode *lf_dip; /* Lost and found directory inode */ extern osi_list_t dir_hash[FSCK_HASH_SIZE]; extern osi_list_t inode_hash[FSCK_HASH_SIZE]; -extern struct gfs2_block_list *bl; +extern struct gfs2_bmap *bl; extern uint64_t last_fs_block, last_reported_block; extern int skip_this_pass, fsck_abort; extern int errors_found, errors_corrected; diff --git a/gfs2/fsck/initialize.c b/gfs2/fsck/initialize.c index 67fa1fb..5985919 100644 --- a/gfs2/fsck/initialize.c +++ b/gfs2/fsck/initialize.c @@ -115,7 +115,7 @@ static void empty_super_block(struct gfs2_sbd *sdp) } if (bl) - gfs2_block_list_destroy(sdp, bl); + gfs2_bmap_destroy(sdp, bl); } @@ -271,7 +271,7 @@ static int init_system_inodes(struct gfs2_sbd *sdp) goto fail; } - bl = gfs2_block_list_create(sdp, last_fs_block+1, &addl_mem_needed); + bl = gfs2_bmap_create(sdp, last_fs_block+1, &addl_mem_needed); if (!bl) { log_crit( _("This system doesn't have enough memory + swap space to fsck this file system.\n")); log_crit( _("Additional memory needed is approximately: %lluMB\n"), diff --git a/gfs2/fsck/main.c b/gfs2/fsck/main.c index 56ac943..9da8dd2 100644 --- a/gfs2/fsck/main.c +++ b/gfs2/fsck/main.c @@ -32,7 +32,7 @@ struct gfs2_options opts = {0}; struct gfs2_inode *lf_dip; /* Lost and found directory inode */ osi_list_t dir_hash[FSCK_HASH_SIZE]; osi_list_t inode_hash[FSCK_HASH_SIZE]; -struct gfs2_block_list *bl = NULL; +struct gfs2_bmap *bl = NULL; uint64_t last_fs_block, last_reported_block = -1; int skip_this_pass = FALSE, fsck_abort = FALSE; int errors_found = 0, errors_corrected = 0; diff --git a/gfs2/libgfs2/block_list.c b/gfs2/libgfs2/block_list.c index c67c5a4..19e91df 100644 --- a/gfs2/libgfs2/block_list.c +++ b/gfs2/libgfs2/block_list.c @@ -29,19 +29,150 @@ static int mark_to_gbmap[16] = { INVALID_META, INVALID_META }; -struct gfs2_block_list *gfs2_block_list_create(struct gfs2_sbd *sdp, - uint64_t size, - uint64_t *addl_mem_needed) +#define BITMAP_SIZE(size, cpb) (size / cpb) +#define BITMAP_SIZE1(size) (size >> 3) +#define BITMAP_SIZE4(size) (size >> 1) + +#define BITMAP_BYTE_OFFSET(x, map) ((x % map->chunks_per_byte) \ + * map->chunksize ) + +/* BITMAP_BYTE_OFFSET1 is for chunksize==1, which implies chunks_per_byte==8 */ +/* Reducing the math, we get: */ +/* #define BITMAP_BYTE_OFFSET1(x) ((x % 8) * 1) */ +/* #define BITMAP_BYTE_OFFSET1(x) (x % 8) */ +/* #define BITMAP_BYTE_OFFSET1(x) (x & 0x0000000000000007) */ +#define BITMAP_BYTE_OFFSET1(x) (x & 0x0000000000000007) + +/* BITMAP_BYTE_OFFSET4 is for chunksize==4, which implies chunks_per_byte==2 */ +/* Reducing the math, we get: */ +/* #define BITMAP_BYTE_OFFSET4(x) ((x % 2) * 4) */ +/* #define BITMAP_BYTE_OFFSET4(x) ((x & 0x0000000000000001) * 4) */ +/* #define BITMAP_BYTE_OFFSET4(x) ((x & 0x0000000000000001) << 2) */ +#define BITMAP_BYTE_OFFSET4(x) ((x & 0x0000000000000001) << 2) + +#define BITMAP_MASK(chunksize) ((2 << (chunksize - 1)) - 1) +/* BITMAP_MASK1 is for chunksize==1 */ +/* Reducing the math, we get: */ +/* #define BITMAP_MASK1(chunksize) ((2 << (1 - 1)) - 1) */ +/* #define BITMAP_MASK1(chunksize) ((2 << 0) - 1) */ +/* #define BITMAP_MASK1(chunksize) ((2) - 1) */ +#define BITMAP_MASK1(chunksize) (1) + +/* BITMAP_MASK4 is for chunksize==4 */ +/* #define BITMAP_MASK(chunksize) ((2 << (4 - 1)) - 1) */ +/* #define BITMAP_MASK(chunksize) ((2 << 3) - 1) */ +/* #define BITMAP_MASK(chunksize) (0x10 - 1) */ +#define BITMAP_MASK4(chunksize) (0xf) + +static int gfs2_bitmap_create(struct gfs2_bmap *bmap, uint64_t size, + uint8_t chunksize) { - struct gfs2_block_list *il; + if((((chunksize >> 1) << 1) != chunksize) && chunksize != 1) + return -1; + if(chunksize > 8) + return -1; + bmap->chunksize = chunksize; + bmap->chunks_per_byte = 8 / chunksize; + + bmap->size = size; + + /* Have to add 1 to BITMAP_SIZE since it's 0-based and mallocs + * must be 1-based */ + bmap->mapsize = BITMAP_SIZE(size, bmap->chunks_per_byte)+1; + + if(!(bmap->map = malloc(sizeof(char) * bmap->mapsize))) + return -ENOMEM; + if(!memset(bmap->map, 0, sizeof(char) * bmap->mapsize)) { + free(bmap->map); + bmap->map = NULL; + return -ENOMEM; + } + return 0; +} + +static int gfs2_bitmap_set(struct gfs2_bmap *bmap, uint64_t offset, uint8_t val) +{ + static char *byte; + static uint64_t b; + + if(offset < bmap->size) { + if (bmap->chunksize == 1) { + byte = bmap->map + BITMAP_SIZE1(offset); + b = BITMAP_BYTE_OFFSET1(offset); + *byte |= (val & BITMAP_MASK1(bmap->chunksize)); + } else { + byte = bmap->map + BITMAP_SIZE4(offset); + b = BITMAP_BYTE_OFFSET4(offset); + *byte |= (val & BITMAP_MASK4(bmap->chunksize)) << b; + } + return 0; + } + return -1; +} + +static int gfs2_bitmap_get(struct gfs2_bmap *bmap, uint64_t bit, uint8_t *val) +{ + static char *byte; + static uint64_t b; + + if(bit < bmap->size) { + if (bmap->chunksize == 1) { + byte = bmap->map + BITMAP_SIZE1(bit); + b = BITMAP_BYTE_OFFSET1(bit); + *val = (*byte & (BITMAP_MASK1(bmap->chunksize) << b )) >> b; + } else { + byte = bmap->map + BITMAP_SIZE4(bit); + b = BITMAP_BYTE_OFFSET4(bit); + *val = (*byte & (BITMAP_MASK4(bmap->chunksize) << b )) >> b; + } + return 0; + } + return -1; +} + +static int gfs2_bitmap_clear(struct gfs2_bmap *bmap, uint64_t offset) +{ + static char *byte; + static uint64_t b; + + if(offset < bmap->size) { + if (bmap->chunksize == 1) { + byte = bmap->map + BITMAP_SIZE1(offset); + b = BITMAP_BYTE_OFFSET1(offset); + *byte &= ~(BITMAP_MASK1(bmap->chunksize) << b); + } else { + byte = bmap->map + BITMAP_SIZE4(offset); + b = BITMAP_BYTE_OFFSET4(offset); + *byte &= ~(BITMAP_MASK4(bmap->chunksize) << b); + } + return 0; + } + return -1; + +} + +static void gfs2_bitmap_destroy(struct gfs2_bmap *bmap) +{ + if(bmap->map) + free(bmap->map); + bmap->size = 0; + bmap->mapsize = 0; + bmap->chunksize = 0; + bmap->chunks_per_byte = 0; +} + +struct gfs2_bmap *gfs2_bmap_create(struct gfs2_sbd *sdp, uint64_t size, + uint64_t *addl_mem_needed) +{ + struct gfs2_bmap *il; *addl_mem_needed = 0L; il = malloc(sizeof(*il)); if (!il || !memset(il, 0, sizeof(*il))) return NULL; - if(gfs2_bitmap_create(&il->list.gbmap, size, 4)) { - *addl_mem_needed = il->list.gbmap.mapsize; + if(gfs2_bitmap_create(il, size, 4)) { + *addl_mem_needed = il->mapsize; free(il); il = NULL; } @@ -156,7 +287,7 @@ static void gfs2_dup_clear(struct dup_blocks *blocklist, uint64_t block) } } -int gfs2_block_mark(struct gfs2_sbd *sdp, struct gfs2_block_list *il, +int gfs2_block_mark(struct gfs2_sbd *sdp, struct gfs2_bmap *il, uint64_t block, enum gfs2_mark_block mark) { int err = 0; @@ -166,13 +297,12 @@ int gfs2_block_mark(struct gfs2_sbd *sdp, struct gfs2_block_list *il, else if(mark == gfs2_eattr_block) gfs2_special_set(&sdp->eattr_blocks, block); else - err = gfs2_bitmap_set(&il->list.gbmap, block, - mark_to_gbmap[mark]); + err = gfs2_bitmap_set(il, block, mark_to_gbmap[mark]); return err; } /* gfs2_block_unmark clears ONE mark for the given block */ -int gfs2_block_unmark(struct gfs2_sbd *sdp, struct gfs2_block_list *il, +int gfs2_block_unmark(struct gfs2_sbd *sdp, struct gfs2_bmap *il, uint64_t block, enum gfs2_mark_block mark) { int err = 0; @@ -186,25 +316,25 @@ int gfs2_block_unmark(struct gfs2_sbd *sdp, struct gfs2_block_list *il, break; default: /* FIXME: check types */ - err = gfs2_bitmap_clear(&il->list.gbmap, block); + err = gfs2_bitmap_clear(il, block); break; } return err; } /* gfs2_block_clear clears all the marks for the given block */ -int gfs2_block_clear(struct gfs2_sbd *sdp, struct gfs2_block_list *il, +int gfs2_block_clear(struct gfs2_sbd *sdp, struct gfs2_bmap *il, uint64_t block) { int err = 0; gfs2_dup_clear(&sdp->dup_blocks, block); gfs2_special_clear(&sdp->eattr_blocks, block); - err = gfs2_bitmap_clear(&il->list.gbmap, block); + err = gfs2_bitmap_clear(il, block); return err; } -int gfs2_block_set(struct gfs2_sbd *sdp, struct gfs2_block_list *il, +int gfs2_block_set(struct gfs2_sbd *sdp, struct gfs2_bmap *il, uint64_t block, enum gfs2_mark_block mark) { int err; @@ -215,7 +345,7 @@ int gfs2_block_set(struct gfs2_sbd *sdp, struct gfs2_block_list *il, return err; } -int gfs2_block_check(struct gfs2_sbd *sdp, struct gfs2_block_list *il, +int gfs2_block_check(struct gfs2_sbd *sdp, struct gfs2_bmap *il, uint64_t block, struct gfs2_block_query *val) { int err = 0; @@ -226,15 +356,15 @@ int gfs2_block_check(struct gfs2_sbd *sdp, struct gfs2_block_list *il, val->dup_block = 1; if (blockfind(&sdp->eattr_blocks, block)) val->eattr_block = 1; - if((err = gfs2_bitmap_get(&il->list.gbmap, block, &val->block_type))) + if((err = gfs2_bitmap_get(il, block, &val->block_type))) return err; return 0; } -void *gfs2_block_list_destroy(struct gfs2_sbd *sdp, struct gfs2_block_list *il) +void *gfs2_bmap_destroy(struct gfs2_sbd *sdp, struct gfs2_bmap *il) { if(il) { - gfs2_bitmap_destroy(&il->list.gbmap); + gfs2_bitmap_destroy(il); free(il); il = NULL; } diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h index a9aeb2a..fc8af3f 100644 --- a/gfs2/libgfs2/libgfs2.h +++ b/gfs2/libgfs2/libgfs2.h @@ -301,11 +301,6 @@ struct gfs2_bmap { char *map; }; -int gfs2_bitmap_create(struct gfs2_bmap *bmap, uint64_t size, uint8_t bitsize); -int gfs2_bitmap_set(struct gfs2_bmap *bmap, uint64_t offset, uint8_t val); -int gfs2_bitmap_get(struct gfs2_bmap *bmap, uint64_t bit, uint8_t *val); -int gfs2_bitmap_clear(struct gfs2_bmap *bmap, uint64_t offset); -void gfs2_bitmap_destroy(struct gfs2_bmap *bmap); uint64_t gfs2_bitmap_size(struct gfs2_bmap *bmap); /* block_list.c */ @@ -354,35 +349,24 @@ struct gfs2_block_query { uint8_t eattr_block; }; -union gfs2_block_lists { - struct gfs2_bmap gbmap; -}; - -/* bitmap implementation */ -struct gfs2_block_list { - union gfs2_block_lists list; -}; - -struct gfs2_block_list *gfs2_block_list_create(struct gfs2_sbd *sdp, - uint64_t size, - uint64_t *addl_mem_needed); -struct special_blocks *blockfind(struct special_blocks *blist, uint64_t num); -void gfs2_special_set(struct special_blocks *blocklist, uint64_t block); -void gfs2_special_free(struct special_blocks *blist); -int gfs2_block_mark(struct gfs2_sbd *sdp, struct gfs2_block_list *il, - uint64_t block, enum gfs2_mark_block mark); -int gfs2_block_set(struct gfs2_sbd *sdp, struct gfs2_block_list *il, - uint64_t block, enum gfs2_mark_block mark); +extern struct gfs2_bmap *gfs2_bmap_create(struct gfs2_sbd *sdp, uint64_t size, + uint64_t *addl_mem_needed); +extern struct special_blocks *blockfind(struct special_blocks *blist, uint64_t num); +extern void gfs2_special_set(struct special_blocks *blocklist, uint64_t block); +extern void gfs2_special_free(struct special_blocks *blist); +extern int gfs2_block_mark(struct gfs2_sbd *sdp, struct gfs2_bmap *il, + uint64_t block, enum gfs2_mark_block mark); +extern int gfs2_block_set(struct gfs2_sbd *sdp, struct gfs2_bmap *il, + uint64_t block, enum gfs2_mark_block mark); /* gfs2_block_unmark clears ONE mark for the given block */ -int gfs2_block_unmark(struct gfs2_sbd *sdp, struct gfs2_block_list *il, - uint64_t block, enum gfs2_mark_block m); +extern int gfs2_block_unmark(struct gfs2_sbd *sdp, struct gfs2_bmap *il, + uint64_t block, enum gfs2_mark_block m); /* gfs2_block_clear clears all the marks for the given block */ -int gfs2_block_clear(struct gfs2_sbd *sdp, struct gfs2_block_list *il, - uint64_t block); -int gfs2_block_check(struct gfs2_sbd *sdp, struct gfs2_block_list *il, - uint64_t block, struct gfs2_block_query *val); -void *gfs2_block_list_destroy(struct gfs2_sbd *sdp, - struct gfs2_block_list *il); +extern int gfs2_block_clear(struct gfs2_sbd *sdp, struct gfs2_bmap *il, + uint64_t block); +extern int gfs2_block_check(struct gfs2_sbd *sdp, struct gfs2_bmap *il, + uint64_t block, struct gfs2_block_query *val); +extern void *gfs2_bmap_destroy(struct gfs2_sbd *sdp, struct gfs2_bmap *il); /* buf.c */ void init_buf_list(struct gfs2_sbd *sdp, struct buf_list *bl, uint32_t limit);