From mboxrd@z Thu Jan 1 00:00:00 1970 From: Bob Peterson Date: Fri, 6 May 2016 12:39:10 -0500 Subject: [Cluster-devel] [fsck.gfs2 v2 PATCH 17/40] fsck.gfs2: make blockmap global variable only to pass1 In-Reply-To: References: Message-ID: <7113d95d4ce66cd4e39b075ea690a1d0b78a66a3.1462556087.git.rpeterso@redhat.com> List-Id: To: cluster-devel.redhat.com MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit This patch changes the variable "bl" from being a global variable to being global only to pass1. This is another step toward allowing pass1 to free the blockmap when it's done. Signed-off-by: Bob Peterson --- gfs2/fsck/fsck.h | 3 +- gfs2/fsck/initialize.c | 11 ----- gfs2/fsck/main.c | 1 - gfs2/fsck/pass1.c | 120 +++++++++++++++++++++++++++++++++++++++++-------- gfs2/fsck/pass5.c | 17 +++---- gfs2/fsck/util.c | 66 --------------------------- gfs2/fsck/util.h | 6 +-- 7 files changed, 112 insertions(+), 112 deletions(-) diff --git a/gfs2/fsck/fsck.h b/gfs2/fsck/fsck.h index 4cf4ce1..d57ccfd 100644 --- a/gfs2/fsck/fsck.h +++ b/gfs2/fsck/fsck.h @@ -119,7 +119,7 @@ extern int pass1c(struct gfs2_sbd *sdp); extern int pass2(struct gfs2_sbd *sdp); extern int pass3(struct gfs2_sbd *sdp); extern int pass4(struct gfs2_sbd *sdp); -extern int pass5(struct gfs2_sbd *sdp); +extern int pass5(struct gfs2_sbd *sdp, struct gfs2_bmap *bl); extern int rg_repair(struct gfs2_sbd *sdp, int trust_lvl, int *rg_count, int *sane); extern int fsck_query(const char *format, ...) @@ -142,7 +142,6 @@ struct gfs2_options { extern struct gfs2_options opts; extern struct gfs2_inode *lf_dip; /* Lost and found directory inode */ extern int lf_was_created; -extern struct gfs2_bmap *bl; extern uint64_t last_fs_block, last_reported_block; extern int64_t last_reported_fblock; extern int skip_this_pass, fsck_abort; diff --git a/gfs2/fsck/initialize.c b/gfs2/fsck/initialize.c index 84d39cd..d54ab0d 100644 --- a/gfs2/fsck/initialize.c +++ b/gfs2/fsck/initialize.c @@ -115,8 +115,6 @@ static void empty_super_block(struct gfs2_sbd *sdp) log_info( _("Freeing buffers.\n")); gfs2_rgrp_free(&sdp->rgtree); - if (bl) - gfs2_bmap_destroy(sdp, bl); gfs2_inodetree_free(); gfs2_dirtree_free(); gfs2_dup_free(); @@ -674,7 +672,6 @@ static int init_system_inodes(struct gfs2_sbd *sdp) uint64_t inumbuf = 0; char *buf; struct gfs2_statfs_change sc; - uint64_t addl_mem_needed; int err; /******************************************************************* @@ -841,14 +838,6 @@ static int init_system_inodes(struct gfs2_sbd *sdp) goto fail; } - bl = gfs2_bmap_create(sdp, last_fs_block+1, &addl_mem_needed); - if (!bl) { - log_crit( _("This system doesn't have enough memory and swap space to fsck this file system.\n")); - log_crit( _("Additional memory needed is approximately: %lluMB\n"), - (unsigned long long)(addl_mem_needed / 1048576ULL)); - log_crit( _("Please increase your swap space by that amount and run gfs2_fsck again.\n")); - goto fail; - } return 0; fail: empty_super_block(sdp); diff --git a/gfs2/fsck/main.c b/gfs2/fsck/main.c index 2cedb30..91ebe28 100644 --- a/gfs2/fsck/main.c +++ b/gfs2/fsck/main.c @@ -27,7 +27,6 @@ struct gfs2_options opts = {0}; struct gfs2_inode *lf_dip = NULL; /* Lost and found directory inode */ int lf_was_created = 0; -struct gfs2_bmap *bl = NULL; uint64_t last_fs_block, last_reported_block = -1; int64_t last_reported_fblock = -1000000; int skip_this_pass = FALSE, fsck_abort = FALSE; diff --git a/gfs2/fsck/pass1.c b/gfs2/fsck/pass1.c index 876e565..49f6c6e 100644 --- a/gfs2/fsck/pass1.c +++ b/gfs2/fsck/pass1.c @@ -30,6 +30,7 @@ #include "fs_recovery.h" struct special_blocks gfs1_rindex_blks; +struct gfs2_bmap *bl = NULL; struct block_count { uint64_t indir_count; @@ -88,6 +89,24 @@ static int handle_ip(struct gfs2_sbd *sdp, struct gfs2_inode *ip); static int delete_block(struct gfs2_inode *ip, uint64_t block, struct gfs2_buffer_head **bh, const char *btype, void *private); + +static int gfs2_blockmap_set(struct gfs2_bmap *bmap, uint64_t bblock, int mark) +{ + static unsigned char *byte; + static uint64_t b; + + if (!bmap) + return 0; + if (bblock > bmap->size) + return -1; + + byte = bmap->map + BLOCKMAP_SIZE2(bblock); + b = BLOCKMAP_BYTE_OFFSET2(bblock); + *byte &= ~(BLOCKMAP_MASK2 << b); + *byte |= (mark & BLOCKMAP_MASK2) << b; + return 0; +} + /* * _fsck_blockmap_set - Mark a block in the 4-bit blockmap and the 2-bit * bitmap, and adjust free space accordingly. @@ -253,7 +272,7 @@ static int p1check_leaf(struct gfs2_inode *ip, uint64_t block, void *private) check in metawalk: gfs2_check_meta(lbh, GFS2_METATYPE_LF). So we know it's a leaf block. */ bc->indir_count++; - q = block_type(block); + q = block_type(bl, block); if (q != GFS2_BLKST_FREE) { log_err( _("Found duplicate block #%llu (0x%llx) referenced " "as a directory leaf in dinode " @@ -311,7 +330,7 @@ static int check_metalist(struct gfs2_inode *ip, uint64_t block, iblk_type = GFS2_METATYPE_IN; blktypedesc = _("a journaled data block"); } - q = block_type(block); + q = block_type(bl, block); if (q != GFS2_BLKST_FREE) { log_err( _("Found duplicate block #%llu (0x%llx) referenced " "as metadata in indirect block for dinode " @@ -502,7 +521,7 @@ static int check_data(struct gfs2_inode *ip, uint64_t metablock, return -1; } bc->data_count++; /* keep the count sane anyway */ - q = block_type(block); + q = block_type(bl, block); if (q != GFS2_BLKST_FREE) { struct gfs2_buffer_head *bh; struct gfs2_meta_header mh; @@ -623,7 +642,7 @@ static int undo_eattr_indir_or_leaf(struct gfs2_inode *ip, uint64_t block, /* Need to check block_type before undoing the reference, which can set it to free, which would cause the test below to fail. */ - q = block_type(block); + q = block_type(bl, block); error = undo_reference(ip, block, 0, private); if (error) @@ -672,7 +691,7 @@ static int check_eattr_indir(struct gfs2_inode *ip, uint64_t indirect, * in pass1c */ return 1; } - q = block_type(indirect); + q = block_type(bl, indirect); /* Special duplicate processing: If we have an EA block, check if it really is an EA. If it is, let duplicate @@ -756,7 +775,7 @@ static int check_ealeaf_block(struct gfs2_inode *ip, uint64_t block, int btype, int q; struct block_count *bc = (struct block_count *) private; - q = block_type(block); + q = block_type(bl, block); /* Special duplicate processing: If we have an EA block, check if it really is an EA. If it is, let duplicate handling sort it out. If it isn't, clear it but don't count it as a duplicate. */ @@ -1027,7 +1046,7 @@ static int mark_block_invalid(struct gfs2_inode *ip, uint64_t block, return meta_is_good; } - q = block_type(block); + q = block_type(bl, block); if (q != GFS2_BLKST_FREE) { if (was_duplicate) *was_duplicate = 1; @@ -1126,7 +1145,7 @@ static int rangecheck_block(struct gfs2_inode *ip, uint64_t block, return meta_error; /* Exits check_metatree quicker */ } /* See how many duplicate blocks it has */ - q = block_type(block); + q = block_type(bl, block); if (q != GFS2_BLKST_FREE) { (*bad_pointers)++; log_info( _("Duplicated %s block pointer (violation %ld, block" @@ -1595,7 +1614,7 @@ static int check_system_inode(struct gfs2_sbd *sdp, } } if (*sysinode) { - ds.q = block_type(iblock); + ds.q = block_type(bl, iblock); /* If the inode exists but the block is marked free, we might be recovering from a corrupt bitmap. In that case, don't rebuild the inode. Just reuse the inode and fix the @@ -1858,7 +1877,7 @@ static int pass1_process_bitmap(struct gfs2_sbd *sdp, struct rgrp_tree *rgd, uin check_magic = ((struct gfs2_meta_header *) (bh->b_data))->mh_magic; - q = block_type(block); + q = block_type(bl, block); if (q != GFS2_BLKST_FREE) { if (be32_to_cpu(check_magic) == GFS2_MAGIC && sdp->gfs1 && !is_inode) { @@ -1971,6 +1990,55 @@ out: return ret; } +static int gfs2_blockmap_create(struct gfs2_bmap *bmap, uint64_t size) +{ + bmap->size = size; + + /* Have to add 1 to BLOCKMAP_SIZE since it's 0-based and mallocs + * must be 1-based */ + bmap->mapsize = BLOCKMAP_SIZE2(size) + 1; + + if (!(bmap->map = calloc(bmap->mapsize, sizeof(char)))) + return -ENOMEM; + return 0; +} + +static 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 = calloc(1, sizeof(*il)); + if (!il) + return NULL; + + if (gfs2_blockmap_create(il, size)) { + *addl_mem_needed = il->mapsize; + free(il); + il = NULL; + } + return il; +} + +static void gfs2_blockmap_destroy(struct gfs2_bmap *bmap) +{ + if (bmap->map) + free(bmap->map); + bmap->size = 0; + bmap->mapsize = 0; +} + +static void *gfs2_bmap_destroy(struct gfs2_sbd *sdp, struct gfs2_bmap *il) +{ + if (il) { + gfs2_blockmap_destroy(il); + free(il); + il = NULL; + } + return il; +} + /** * pass1 - walk through inodes and check inode state * @@ -1990,9 +2058,18 @@ int pass1(struct gfs2_sbd *sdp) struct rgrp_tree *rgd; uint64_t i; uint64_t rg_count = 0; - int ret; struct timeval timer; - + int ret = FSCK_OK; + uint64_t 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 and swap space to fsck this file system.\n")); + log_crit( _("Additional memory needed is approximately: %lluMB\n"), + (unsigned long long)(addl_mem_needed / 1048576ULL)); + log_crit( _("Please increase your swap space by that amount and run gfs2_fsck again.\n")); + return FSCK_ERROR; + } osi_list_init(&gfs1_rindex_blks.list); /* FIXME: In the gfs fsck, we had to mark things like the @@ -2014,8 +2091,10 @@ int pass1(struct gfs2_sbd *sdp) * things - we can change the method later if necessary. */ for (n = osi_first(&sdp->rgtree); n; n = next, rg_count++) { - if (fsck_abort) - return FSCK_CANCELED; + if (fsck_abort) { + ret = FSCK_CANCELED; + goto out; + } next = osi_next(n); log_debug( _("Checking metadata in Resource Group #%llu\n"), (unsigned long long)rg_count); @@ -2028,7 +2107,8 @@ int pass1(struct gfs2_sbd *sdp) GFS2_BLKST_USED)) { stack; gfs2_special_free(&gfs1_rindex_blks); - return FSCK_ERROR; + ret = FSCK_ERROR; + goto out; } /* rgrps and bitmaps don't have bits to represent their blocks, so don't do this: @@ -2038,13 +2118,15 @@ int pass1(struct gfs2_sbd *sdp) ret = pass1_process_rgrp(sdp, rgd); if (ret) - return ret; - + goto out; } log_notice(_("Reconciling bitmaps.\n")); gettimeofday(&timer, NULL); - pass5(sdp); + pass5(sdp, bl); print_pass_duration("reconcile_bitmaps", &timer); +out: gfs2_special_free(&gfs1_rindex_blks); - return FSCK_OK; + if (bl) + gfs2_bmap_destroy(sdp, bl); + return ret; } diff --git a/gfs2/fsck/pass5.c b/gfs2/fsck/pass5.c index 99ff0a1..7d81bfa 100644 --- a/gfs2/fsck/pass5.c +++ b/gfs2/fsck/pass5.c @@ -12,9 +12,10 @@ #include "fsck.h" #include "util.h" -static int check_block_status(struct gfs2_sbd *sdp, char *buffer, - unsigned int buflen, uint64_t *rg_block, - uint64_t rg_data, uint32_t *count) +static int check_block_status(struct gfs2_sbd *sdp, struct gfs2_bmap *bl, + char *buffer, unsigned int buflen, + uint64_t *rg_block, uint64_t rg_data, + uint32_t *count) { unsigned char *byte, *end; unsigned int bit; @@ -34,7 +35,7 @@ static int check_block_status(struct gfs2_sbd *sdp, char *buffer, if (skip_this_pass || fsck_abort) /* if asked to skip the rest */ return 0; - q = block_type(block); + q = block_type(bl, block); /* GFS1 file systems will have to suffer from slower fsck run * times because in GFS, there's no 1:1 relationship between * bits and counts. If a bit is marked "dinode" in GFS1, it @@ -124,7 +125,7 @@ static int check_block_status(struct gfs2_sbd *sdp, char *buffer, } static void update_rgrp(struct gfs2_sbd *sdp, struct rgrp_tree *rgp, - uint32_t *count) + struct gfs2_bmap *bl, uint32_t *count) { uint32_t i; struct gfs2_bitmap *bits; @@ -136,7 +137,7 @@ static void update_rgrp(struct gfs2_sbd *sdp, struct rgrp_tree *rgp, bits = &rgp->bits[i]; /* update the bitmaps */ - if (check_block_status(sdp, bits->bi_bh->b_data + bits->bi_offset, + if (check_block_status(sdp, bl, bits->bi_bh->b_data + bits->bi_offset, bits->bi_len, &rg_block, rgp->ri.ri_data0, count)) return; if (skip_this_pass || fsck_abort) /* if asked to skip the rest */ @@ -209,7 +210,7 @@ static void update_rgrp(struct gfs2_sbd *sdp, struct rgrp_tree *rgp, * fix free block maps * fix used inode maps */ -int pass5(struct gfs2_sbd *sdp) +int pass5(struct gfs2_sbd *sdp, struct gfs2_bmap *bl) { struct osi_node *n, *next = NULL; struct rgrp_tree *rgp = NULL; @@ -227,7 +228,7 @@ int pass5(struct gfs2_sbd *sdp) rg_count++; /* Compare the bitmaps and report the differences */ - update_rgrp(sdp, rgp, count); + update_rgrp(sdp, rgp, bl, count); } /* Fix up superblock info based on this - don't think there's * anything to do here... */ diff --git a/gfs2/fsck/util.c b/gfs2/fsck/util.c index d6d664a..2e77000 100644 --- a/gfs2/fsck/util.c +++ b/gfs2/fsck/util.c @@ -525,72 +525,6 @@ void dirtree_delete(struct dir_info *b) free(b); } -static int gfs2_blockmap_create(struct gfs2_bmap *bmap, uint64_t size) -{ - bmap->size = size; - - /* Have to add 1 to BLOCKMAP_SIZE since it's 0-based and mallocs - * must be 1-based */ - bmap->mapsize = BLOCKMAP_SIZE2(size) + 1; - - if (!(bmap->map = calloc(bmap->mapsize, sizeof(char)))) - return -ENOMEM; - return 0; -} - -static void gfs2_blockmap_destroy(struct gfs2_bmap *bmap) -{ - if (bmap->map) - free(bmap->map); - bmap->size = 0; - bmap->mapsize = 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 = calloc(1, sizeof(*il)); - if (!il) - return NULL; - - if (gfs2_blockmap_create(il, size)) { - *addl_mem_needed = il->mapsize; - free(il); - il = NULL; - } - return il; -} - -int gfs2_blockmap_set(struct gfs2_bmap *bmap, uint64_t bblock, int mark) -{ - static unsigned char *byte; - static uint64_t b; - - if (!bmap) - return 0; - if (bblock > bmap->size) - return -1; - - byte = bmap->map + BLOCKMAP_SIZE2(bblock); - b = BLOCKMAP_BYTE_OFFSET2(bblock); - *byte &= ~(BLOCKMAP_MASK2 << b); - *byte |= (mark & BLOCKMAP_MASK2) << b; - return 0; -} - -void *gfs2_bmap_destroy(struct gfs2_sbd *sdp, struct gfs2_bmap *il) -{ - if (il) { - gfs2_blockmap_destroy(il); - free(il); - il = NULL; - } - return il; -} - uint64_t find_free_blk(struct gfs2_sbd *sdp) { struct osi_node *n, *next = NULL; diff --git a/gfs2/fsck/util.h b/gfs2/fsck/util.h index 50a3c8d..aa01552 100644 --- a/gfs2/fsck/util.h +++ b/gfs2/fsck/util.h @@ -32,7 +32,7 @@ struct fsck_pass { int (*f)(struct gfs2_sbd *sdp); }; -static inline int block_type(uint64_t bblock) +static inline int block_type(struct gfs2_bmap *bl, uint64_t bblock) { static unsigned char *byte; static uint64_t b; @@ -100,10 +100,6 @@ static inline uint32_t gfs_to_gfs2_mode(struct gfs2_inode *ip) } extern enum dup_ref_type get_ref_type(struct inode_with_dups *id); -extern struct gfs2_bmap *gfs2_bmap_create(struct gfs2_sbd *sdp, uint64_t size, - uint64_t *addl_mem_needed); -extern void *gfs2_bmap_destroy(struct gfs2_sbd *sdp, struct gfs2_bmap *il); -extern int gfs2_blockmap_set(struct gfs2_bmap *il, uint64_t block, int mark); extern char generic_interrupt(const char *caller, const char *where, const char *progress, const char *question, const char *answers); -- 2.5.5