From mboxrd@z Thu Jan 1 00:00:00 1970 From: Andrew Price Date: Mon, 26 Jan 2015 10:56:41 +0000 Subject: [Cluster-devel] [fsck.gfs2 PATCH] fsck.gfs2: Change block_map to match bitmap In-Reply-To: <651499900.13792931.1421959269755.JavaMail.zimbra@redhat.com> References: <651499900.13792931.1421959269755.JavaMail.zimbra@redhat.com> Message-ID: <54C61D69.4060306@redhat.com> List-Id: To: cluster-devel.redhat.com MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Hi Bob, On 22/01/15 20:41, Bob Peterson wrote: > Hi, > > This patch changes the old block_map structure for fsck.gfs2 to the > simpler bitmap structure so that we have a 1:1 correspondence. This > was done to reduce memory requirements of fsck.gfs2. I'm curious as to whether we're losing any useful information here. I see an extra bread() for BLKST_USED blocks in check_data, is that the main performance compromise, and how severe is it? Cheers, Andy > > Regards, > > Bob Peterson > Red Hat File Systems > > Signed-off-by: Bob Peterson > --- > gfs2/fsck/lost_n_found.c | 4 +- > gfs2/fsck/metawalk.c | 69 ++++++++------- > gfs2/fsck/metawalk.h | 6 +- > gfs2/fsck/pass1.c | 218 ++++++++++++++++++++++++++--------------------- > gfs2/fsck/pass1b.c | 39 ++++----- > gfs2/fsck/pass1c.c | 20 +++-- > gfs2/fsck/pass2.c | 143 ++++++++++++------------------- > gfs2/fsck/pass3.c | 27 +++--- > gfs2/fsck/pass4.c | 15 ++-- > gfs2/fsck/pass5.c | 2 +- > gfs2/fsck/util.c | 59 +++++-------- > gfs2/fsck/util.h | 113 +++--------------------- > 12 files changed, 300 insertions(+), 415 deletions(-) > > diff --git a/gfs2/fsck/lost_n_found.c b/gfs2/fsck/lost_n_found.c > index b2e35e2..ba3ae1d 100644 > --- a/gfs2/fsck/lost_n_found.c > +++ b/gfs2/fsck/lost_n_found.c > @@ -132,7 +132,7 @@ void make_sure_lf_exists(struct gfs2_inode *ip) > set_di_nlink(sdp->md.rooti); > > q = block_type(lf_dip->i_di.di_num.no_addr); > - if (q != gfs2_inode_dir) { > + if (q != GFS2_BLKST_DINODE) { > lf_was_created = 1; > /* This is a new lost+found directory, so set its block type > and increment link counts for the directories */ > @@ -140,7 +140,7 @@ void make_sure_lf_exists(struct gfs2_inode *ip) > whether it created a new directory or just found an old one, > and we used that instead of the block_type to run this */ > fsck_blockmap_set(ip, lf_dip->i_di.di_num.no_addr, > - _("lost+found dinode"), gfs2_inode_dir); > + _("lost+found dinode"), GFS2_BLKST_DINODE); > dirtree_insert(lf_dip->i_di.di_num); > /* root inode links to lost+found */ > incr_link_count(sdp->md.rooti->i_di.di_num, lf_dip, _("root")); > diff --git a/gfs2/fsck/metawalk.c b/gfs2/fsck/metawalk.c > index b771b9e..90127d3 100644 > --- a/gfs2/fsck/metawalk.c > +++ b/gfs2/fsck/metawalk.c > @@ -29,9 +29,9 @@ > 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, > - enum gfs2_mark_block new_blockmap_state) > + int new_blockmap_state) > { > - int old_bitmap_state, new_bitmap_state; > + int old_bitmap_state; > struct rgrp_tree *rgd; > > rgd = gfs2_blk2rgrpd(sdp, blk); > @@ -43,19 +43,18 @@ int check_n_fix_bitmap(struct gfs2_sbd *sdp, uint64_t blk, int error_on_dinode, > (unsigned long long)blk, (unsigned long long)blk); > return -1; > } > - new_bitmap_state = blockmap_to_bitmap(new_blockmap_state, sdp->gfs1); > - if (old_bitmap_state != new_bitmap_state) { > + if (old_bitmap_state != new_blockmap_state) { > const char *allocdesc[2][5] = { /* gfs2 descriptions */ > {"free", "data", "unlinked", "inode", "reserved"}, > /* gfs1 descriptions: */ > {"free", "data", "free meta", "metadata", "reserved"}}; > > if (error_on_dinode && old_bitmap_state == GFS2_BLKST_DINODE && > - new_bitmap_state != GFS2_BLKST_FREE) { > + new_blockmap_state != GFS2_BLKST_FREE) { > log_debug(_("Reference as '%s' to block %llu (0x%llx) " > "which was marked as dinode. Needs " > "further investigation.\n"), > - allocdesc[sdp->gfs1][new_bitmap_state], > + allocdesc[sdp->gfs1][new_blockmap_state], > (unsigned long long)blk, > (unsigned long long)blk); > return 1; > @@ -65,7 +64,7 @@ int check_n_fix_bitmap(struct gfs2_sbd *sdp, uint64_t blk, int error_on_dinode, > log_err( _("Block %llu (0x%llx) was '%s', should be %s.\n"), > (unsigned long long)blk, (unsigned long long)blk, > allocdesc[sdp->gfs1][old_bitmap_state], > - allocdesc[sdp->gfs1][new_bitmap_state]); > + allocdesc[sdp->gfs1][new_blockmap_state]); > if (query( _("Fix the bitmap? (y/n)"))) { > /* If the new bitmap state is free (and therefore the > old state was not) we have to add to the free > @@ -74,11 +73,12 @@ int check_n_fix_bitmap(struct gfs2_sbd *sdp, uint64_t blk, int error_on_dinode, > subtract to the free space. If the type changed > from dinode to data or data to dinode, no change in > free space. */ > - gfs2_set_bitmap(rgd, blk, new_bitmap_state); > - if (new_bitmap_state == GFS2_BLKST_FREE) { > + gfs2_set_bitmap(rgd, blk, new_blockmap_state); > + if (new_blockmap_state == GFS2_BLKST_FREE) { > /* If we're freeing a dinode, get rid of > the hash table entries for it. */ > - if (old_bitmap_state == GFS2_BLKST_DINODE) { > + if (old_bitmap_state == GFS2_BLKST_DINODE || > + old_bitmap_state == GFS2_BLKST_UNLINKED) { > struct dir_info *dt; > struct inode_info *ii; > > @@ -114,18 +114,18 @@ int check_n_fix_bitmap(struct gfs2_sbd *sdp, uint64_t blk, int error_on_dinode, > * bitmap, and adjust free space accordingly. > */ > int _fsck_blockmap_set(struct gfs2_inode *ip, uint64_t bblock, > - const char *btype, enum gfs2_mark_block mark, > - int error_on_dinode, > - const char *caller, int fline) > + const char *btype, int mark, > + int error_on_dinode, const char *caller, int fline) > { > int error; > static int prev_ino_addr = 0; > - static enum gfs2_mark_block prev_mark = 0; > + static int prev_mark = 0; > static int prevcount = 0; > + static const char *prev_caller = NULL; > > if (print_level >= MSG_DEBUG) { > if ((ip->i_di.di_num.no_addr == prev_ino_addr) && > - (mark == prev_mark)) { > + (mark == prev_mark) && caller == prev_caller) { > log_info("(0x%llx) ", (unsigned long long)bblock); > prevcount++; > if (prevcount > 10) { > @@ -145,7 +145,7 @@ int _fsck_blockmap_set(struct gfs2_inode *ip, uint64_t bblock, > (unsigned long long)ip->i_di.di_num.no_addr, > block_type_string(mark)); > > - } else if (mark == gfs2_bad_block || mark == gfs2_meta_inval) { > + } else if (mark == GFS2_BLKST_UNLINKED) { > if (prevcount) { > log_info("\n"); > prevcount = 0; > @@ -170,6 +170,7 @@ int _fsck_blockmap_set(struct gfs2_inode *ip, uint64_t bblock, > } > prev_ino_addr = ip->i_di.di_num.no_addr; > prev_mark = mark; > + prev_caller = caller; > } > > /* First, check the rgrp bitmap against what we think it should be. > @@ -909,8 +910,9 @@ static int check_eattr_entries(struct gfs2_inode *ip, > a single byte. */ > fsck_blockmap_set(ip, > ip->i_di.di_eattr, > - _("extended attribute"), > - gfs2_meta_eattr); > + _("extended attribute"), > + sdp->gfs1 ? GFS2_BLKST_DINODE : > + GFS2_BLKST_USED); > log_err( _("The EA was " > "fixed.\n")); > } else { > @@ -986,7 +988,7 @@ int delete_block(struct gfs2_inode *ip, uint64_t block, > void *private) > { > if (valid_block(ip->i_sbd, block)) { > - fsck_blockmap_set(ip, block, btype, gfs2_block_free); > + fsck_blockmap_set(ip, block, btype, GFS2_BLKST_FREE); > return 0; > } > return -1; > @@ -1041,7 +1043,7 @@ static int delete_block_if_notdup(struct gfs2_inode *ip, uint64_t block, > return meta_error; > > q = block_type(block); > - if (q == gfs2_block_free) { > + if (q == GFS2_BLKST_FREE) { > log_info( _("%s block %lld (0x%llx), part of inode " > "%lld (0x%llx), was already free.\n"), > btype, (unsigned long long)block, > @@ -1060,7 +1062,7 @@ 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 { > - fsck_blockmap_set(ip, block, btype, gfs2_block_free); > + fsck_blockmap_set(ip, block, btype, GFS2_BLKST_FREE); > } > return meta_is_good; > } > @@ -1672,7 +1674,7 @@ undo_metalist: > delete_all_dups(ip); > /* Set the dinode as "bad" so it gets deleted */ > fsck_blockmap_set(ip, ip->i_di.di_num.no_addr, > - _("corrupt"), gfs2_block_free); > + _("corrupt"), GFS2_BLKST_FREE); > log_err(_("The corrupt inode was invalidated.\n")); > out: > free_metalist(ip, &metalist[0]); > @@ -1763,8 +1765,8 @@ int remove_dentry_from_dir(struct gfs2_sbd *sdp, uint64_t dir, > remove_dentry_fxns.check_dentry = remove_dentry; > > q = block_type(dir); > - if (q != gfs2_inode_dir) { > - log_info( _("Parent block is not a directory...ignoring\n")); > + if (q != GFS2_BLKST_DINODE) { > + log_info( _("Parent block is not an inode...ignoring\n")); > return 1; > } > /* Need to run check_dir with a private var of dentryblock, > @@ -1807,7 +1809,7 @@ static int del_eattr_generic(struct gfs2_inode *ip, uint64_t block, > > if (valid_block(ip->i_sbd, block)) { > q = block_type(block); > - if (q == gfs2_block_free) > + if (q == GFS2_BLKST_FREE) > was_free = 1; > ret = delete_block_if_notdup(ip, block, NULL, eatype, > NULL, private); > @@ -1907,12 +1909,13 @@ static int alloc_metalist(struct gfs2_inode *ip, uint64_t block, > *was_duplicate = 0; > *bh = bread(ip->i_sbd, block); > q = block_type(block); > - if (blockmap_to_bitmap(q, ip->i_sbd->gfs1) == GFS2_BLKST_FREE) { > + if (q == GFS2_BLKST_FREE) { > log_debug(_("%s reference to new metadata block " > "%lld (0x%llx) is now marked as indirect.\n"), > desc, (unsigned long long)block, > (unsigned long long)block); > - gfs2_blockmap_set(bl, block, gfs2_indir_blk); > + gfs2_blockmap_set(bl, block, ip->i_sbd->gfs1 ? > + GFS2_BLKST_DINODE : GFS2_BLKST_USED); > } > return meta_is_good; > } > @@ -1927,12 +1930,12 @@ static int alloc_data(struct gfs2_inode *ip, uint64_t metablock, > /* We can't check the bitmap here because this function is called > after the bitmap has been set but before the blockmap has. */ > q = block_type(block); > - if (blockmap_to_bitmap(q, ip->i_sbd->gfs1) == GFS2_BLKST_FREE) { > + if (q == GFS2_BLKST_FREE) { > log_debug(_("%s reference to new data block " > "%lld (0x%llx) is now marked as data.\n"), > desc, (unsigned long long)block, > (unsigned long long)block); > - gfs2_blockmap_set(bl, block, gfs2_block_used); > + gfs2_blockmap_set(bl, block, GFS2_BLKST_USED); > } > return 0; > } > @@ -1945,9 +1948,10 @@ static int alloc_leaf(struct gfs2_inode *ip, uint64_t block, void *private) > /* We can't check the bitmap here because this function is called > after the bitmap has been set but before the blockmap has. */ > q = block_type(block); > - if (blockmap_to_bitmap(q, ip->i_sbd->gfs1) == GFS2_BLKST_FREE) > + if (q == GFS2_BLKST_FREE) > fsck_blockmap_set(ip, block, _("newly allocated leaf"), > - gfs2_leaf_blk); > + ip->i_sbd->gfs1 ? GFS2_BLKST_DINODE : > + GFS2_BLKST_USED); > return 0; > } > > @@ -2111,7 +2115,8 @@ int write_new_leaf(struct gfs2_inode *dip, int start_lindex, int num_copies, > free(padbuf); > return -1; > } > - fsck_blockmap_set(dip, *bn, _("directory leaf"), gfs2_leaf_blk); > + fsck_blockmap_set(dip, *bn, _("directory leaf"), dip->i_sbd->gfs1 ? > + GFS2_BLKST_DINODE : GFS2_BLKST_USED); > log_err(_("A new directory leaf was allocated at block %lld " > "(0x%llx) to fill the %d (0x%x) pointer gap %s the existing " > "pointer at index %d (0x%x).\n"), (unsigned long long)*bn, > diff --git a/gfs2/fsck/metawalk.h b/gfs2/fsck/metawalk.h > index 06345c3..057e698 100644 > --- a/gfs2/fsck/metawalk.h > +++ b/gfs2/fsck/metawalk.h > @@ -46,12 +46,10 @@ extern int delete_eattr_extentry(struct gfs2_inode *ip, uint64_t *ea_data_ptr, > void *private); > > extern int _fsck_blockmap_set(struct gfs2_inode *ip, uint64_t bblock, > - const char *btype, enum gfs2_mark_block mark, > - int error_on_dinode, > + 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, > - enum gfs2_mark_block new_blockmap_state); > + int error_on_dinode, int new_blockmap_state); > extern int check_i_goal(struct gfs2_inode *ip, uint64_t goal_blk, > void *private); > extern void reprocess_inode(struct gfs2_inode *ip, const char *desc); > diff --git a/gfs2/fsck/pass1.c b/gfs2/fsck/pass1.c > index 5342701..b516a21 100644 > --- a/gfs2/fsck/pass1.c > +++ b/gfs2/fsck/pass1.c > @@ -137,7 +137,7 @@ static int resuscitate_metalist(struct gfs2_inode *ip, uint64_t block, > *bh = NULL; > if (!valid_block(ip->i_sbd, block)){ /* blk outside of FS */ > fsck_blockmap_set(ip, ip->i_di.di_num.no_addr, > - _("itself"), gfs2_bad_block); > + _("itself"), GFS2_BLKST_UNLINKED); > log_err( _("Bad indirect block pointer (invalid or out of " > "range) found in system inode %lld (0x%llx).\n"), > (unsigned long long)ip->i_di.di_num.no_addr, > @@ -146,9 +146,12 @@ static int resuscitate_metalist(struct gfs2_inode *ip, uint64_t block, > return meta_is_good; > } > if (fsck_system_inode(ip->i_sbd, block)) > - fsck_blockmap_set(ip, block, _("system file"), gfs2_indir_blk); > + fsck_blockmap_set(ip, block, _("system file"), > + ip->i_sbd->gfs1 ? > + GFS2_BLKST_DINODE : GFS2_BLKST_USED); > else > - check_n_fix_bitmap(ip->i_sbd, block, 0, gfs2_indir_blk); > + check_n_fix_bitmap(ip->i_sbd, block, 0, ip->i_sbd->gfs1 ? > + GFS2_BLKST_DINODE : GFS2_BLKST_USED); > bc->indir_count++; > return meta_is_good; > } > @@ -168,7 +171,6 @@ static int resuscitate_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent, > struct gfs2_dirent dentry, *de; > char tmp_name[PATH_MAX]; > uint64_t block; > - enum gfs2_mark_block dinode_type; > > memset(&dentry, 0, sizeof(struct gfs2_dirent)); > gfs2_dirent_in(&dentry, (char *)dent); > @@ -188,21 +190,15 @@ static int resuscitate_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent, > (unsigned long long)ip->i_di.di_num.no_addr); > return 0; > } > - if (block == sdp->md.jiinode->i_di.di_num.no_addr) > - dinode_type = gfs2_inode_dir; > - else if (!sdp->gfs1 && (block == sdp->md.pinode->i_di.di_num.no_addr || > - block == sdp->master_dir->i_di.di_num.no_addr)) > - dinode_type = gfs2_inode_dir; > - else > - dinode_type = gfs2_inode_file; > /* If this is a system dinode, we'll handle it later in > check_system_inodes. If not, it'll be handled by pass1 but > since it's in a system directory we need to make sure it's > represented in the rgrp bitmap. */ > if (fsck_system_inode(sdp, block)) > - fsck_blockmap_set(ip, block, _("system file"), dinode_type); > + fsck_blockmap_set(ip, block, _("system file"), > + GFS2_BLKST_DINODE); > else > - check_n_fix_bitmap(sdp, block, 0, dinode_type); > + check_n_fix_bitmap(sdp, 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); > @@ -225,7 +221,7 @@ static int p1check_leaf(struct gfs2_inode *ip, uint64_t block, void *private) > So we know it's a leaf block. */ > bc->indir_count++; > q = block_type(block); > - if (q != gfs2_block_free) { > + if (q != GFS2_BLKST_FREE) { > log_err( _("Found duplicate block #%llu (0x%llx) referenced " > "as a directory leaf in dinode " > "%llu (0x%llx) - was marked %d (%s)\n"), > @@ -235,12 +231,15 @@ static int p1check_leaf(struct gfs2_inode *ip, uint64_t block, void *private) > (unsigned long long)ip->i_di.di_num.no_addr, q, > block_type_string(q)); > add_duplicate_ref(ip, block, ref_as_meta, 0, INODE_VALID); > - if (q == gfs2_leaf_blk) /* If the previous reference also saw > - this as a leaf, it was already > - checked, so don't check again. */ > + if (q == (ip->i_sbd->gfs1 ? GFS2_BLKST_DINODE : > + GFS2_BLKST_USED)) > + /* If the previous reference also saw this as a leaf, > + it was already checked, so don't check again. */ > return EEXIST; /* non-fatal */ > } > - fsck_blockmap_set(ip, block, _("directory leaf"), gfs2_leaf_blk); > + fsck_blockmap_set(ip, block, _("directory leaf"), > + ip->i_sbd->gfs1 ? GFS2_BLKST_DINODE : > + GFS2_BLKST_USED); > return 0; > } > > @@ -264,7 +263,7 @@ static int check_metalist(struct gfs2_inode *ip, uint64_t block, > set "free" and removed from the inodetree by > undo_check_metalist. */ > fsck_blockmap_set(ip, ip->i_di.di_num.no_addr, > - _("bad block referencing"), gfs2_bad_block); > + _("bad block referencing"), GFS2_BLKST_UNLINKED); > log_debug( _("Bad indirect block (invalid/out of range) " > "found in inode %lld (0x%llx).\n"), > (unsigned long long)ip->i_di.di_num.no_addr, > @@ -280,7 +279,7 @@ static int check_metalist(struct gfs2_inode *ip, uint64_t block, > blktypedesc = _("a journaled data block"); > } > q = block_type(block); > - if (q != gfs2_block_free) { > + if (q != GFS2_BLKST_FREE) { > log_err( _("Found duplicate block #%llu (0x%llx) referenced " > "as metadata in indirect block for dinode " > "%llu (0x%llx) - was marked %d (%s)\n"), > @@ -314,7 +313,8 @@ static int check_metalist(struct gfs2_inode *ip, uint64_t block, > brelse(nbh); > } else { > *bh = nbh; > - fsck_blockmap_set(ip, block, _("indirect"), gfs2_indir_blk); > + fsck_blockmap_set(ip, block, _("indirect"), ip->i_sbd->gfs1 ? > + GFS2_BLKST_DINODE : GFS2_BLKST_USED); > } > > if (*is_valid) > @@ -342,7 +342,7 @@ static int undo_reference(struct gfs2_inode *ip, uint64_t block, int meta, > > if (!valid_block(ip->i_sbd, block)) { /* blk outside of FS */ > fsck_blockmap_set(ip, ip->i_di.di_num.no_addr, > - _("bad block referencing"), gfs2_block_free); > + _("bad block referencing"), GFS2_BLKST_FREE); > return 1; > } > > @@ -380,7 +380,7 @@ static int undo_reference(struct gfs2_inode *ip, uint64_t block, int meta, > } > fsck_blockmap_set(ip, block, > meta ? _("bad indirect") : _("referenced data"), > - gfs2_block_free); > + GFS2_BLKST_FREE); > return 0; > } > > @@ -410,7 +410,7 @@ static int blockmap_set_as_data(struct gfs2_inode *ip, uint64_t block) > struct gfs2_buffer_head *bh; > struct gfs2_dinode *di; > > - error = fsck_blkmap_set_noino(ip, block, _("data"), gfs2_block_used); > + error = fsck_blkmap_set_noino(ip, block, _("data"), GFS2_BLKST_USED); > if (!error) > return 0; > > @@ -436,7 +436,7 @@ static int blockmap_set_as_data(struct gfs2_inode *ip, uint64_t block) > error = -1; > out: > if (!error) > - fsck_blockmap_set(ip, block, _("data"), gfs2_block_used); > + fsck_blockmap_set(ip, block, _("data"), GFS2_BLKST_USED); > brelse(bh); > return error; > } > @@ -464,12 +464,15 @@ static int check_data(struct gfs2_inode *ip, uint64_t metablock, > * blocks later */ > fsck_blockmap_set(ip, ip->i_di.di_num.no_addr, > _("bad (out of range) data"), > - gfs2_bad_block); > + GFS2_BLKST_UNLINKED); > return -1; > } > bc->data_count++; /* keep the count sane anyway */ > q = block_type(block); > - if (q != gfs2_block_free) { > + if (q != GFS2_BLKST_FREE) { > + struct gfs2_buffer_head *bh; > + struct gfs2_meta_header mh; > + > log_err( _("Found duplicate %s block %llu (0x%llx) " > "referenced as data by dinode %llu (0x%llx) "), > block_type_string(q), > @@ -483,11 +486,11 @@ static int check_data(struct gfs2_inode *ip, uint64_t metablock, > log_err(_("from metadata block %llu (0x%llx)\n"), > (unsigned long long)metablock, > (unsigned long long)metablock); > - > - if (q >= gfs2_indir_blk && q <= gfs2_jdata) { > - log_info(_("The block was processed earlier as valid " > - "metadata, so it can't possibly be " > - "data.\n")); > + > + switch (q) { > + case GFS2_BLKST_DINODE: > + log_info(_("The block was processed earlier as an " > + "inode, so it can't possibly be data.\n")); > /* We still need to add a duplicate record here because > when check_metatree tries to delete the inode, we > can't have the "undo" functions freeing the block > @@ -495,8 +498,27 @@ static int check_data(struct gfs2_inode *ip, uint64_t metablock, > add_duplicate_ref(ip, block, ref_as_data, 0, > INODE_VALID); > return 1; > - } > - if (q != gfs2_meta_inval) { > + case GFS2_BLKST_USED: /* tough decision: May be data or meta */ > + bh = bread(ip->i_sbd, block); > + gfs2_meta_header_in(&mh, bh); > + brelse(bh); > + if (mh.mh_magic == GFS2_MAGIC && > + mh.mh_type >= GFS2_METATYPE_RG && > + mh.mh_type <= GFS2_METATYPE_QC && > + mh.mh_type != GFS2_METATYPE_DI && > + mh.mh_format % 100 == 0) { > + log_info(_("The block was processed earlier " > + "as valid metadata, so it can't " > + "possibly be data.\n")); > + /* We still need to add a duplicate record here > + because when check_metatree tries to delete > + the inode, we can't have the "undo" > + functions freeing the block out from other > + the original referencing inode. */ > + add_duplicate_ref(ip, block, ref_as_data, 0, > + INODE_VALID); > + return 1; > + } > log_info( _("Seems to be a normal duplicate; I'll " > "sort it out in pass1b.\n")); > add_duplicate_ref(ip, block, ref_as_data, 0, > @@ -504,11 +526,12 @@ static int check_data(struct gfs2_inode *ip, uint64_t metablock, > /* This inode references the block as data. So if this > all is validated, we want to keep this count. */ > return 0; > + case GFS2_BLKST_UNLINKED: > + log_info( _("The block was invalid as metadata but might be " > + "okay as data. I'll sort it out in pass1b.\n")); > + add_duplicate_ref(ip, block, ref_as_data, 0, INODE_VALID); > + return 0; > } > - log_info( _("The block was invalid as metadata but might be " > - "okay as data. I'll sort it out in pass1b.\n")); > - add_duplicate_ref(ip, block, ref_as_data, 0, INODE_VALID); > - return 0; > } > /* In gfs1, rgrp indirect blocks are marked in the bitmap as "meta". > In gfs2, "meta" is only for dinodes. So here we dummy up the > @@ -517,13 +540,13 @@ static int check_data(struct gfs2_inode *ip, uint64_t metablock, > log_info(_("Block %lld (0x%llx) is a GFS1 rindex block\n"), > (unsigned long long)block, (unsigned long long)block); > gfs2_special_set(&gfs1_rindex_blks, block); > - fsck_blockmap_set(ip, block, _("rgrp"), gfs2_indir_blk); > + fsck_blockmap_set(ip, block, _("rgrp"), GFS2_BLKST_DINODE); > /*gfs2_meta_rgrp);*/ > } else if (ip->i_sbd->gfs1 && ip->i_di.di_flags & GFS2_DIF_JDATA) { > log_info(_("Block %lld (0x%llx) is a GFS1 journaled data " > "block\n"), > (unsigned long long)block, (unsigned long long)block); > - fsck_blockmap_set(ip, block, _("jdata"), gfs2_jdata); > + fsck_blockmap_set(ip, block, _("jdata"), GFS2_BLKST_DINODE); > } else > return blockmap_set_as_data(ip, block); > return 0; > @@ -618,7 +641,7 @@ static int check_eattr_indir(struct gfs2_inode *ip, uint64_t indirect, > count it as a duplicate. */ > *bh = bread(sdp, indirect); > if (gfs2_check_meta(*bh, GFS2_METATYPE_IN)) { > - if (q != gfs2_block_free) { /* Duplicate? */ > + if (q != GFS2_BLKST_FREE) { /* Duplicate? */ > add_duplicate_ref(ip, indirect, ref_as_ea, 0, > INODE_VALID); > if (!clear_eas(ip, bc, indirect, 1, > @@ -632,7 +655,7 @@ static int check_eattr_indir(struct gfs2_inode *ip, uint64_t indirect, > "type")); > return 1; > } > - if (q != gfs2_block_free) { /* Duplicate? */ > + if (q != GFS2_BLKST_FREE) { /* Duplicate? */ > log_err( _("Inode #%llu (0x%llx): Duplicate Extended " > "Attribute indirect block found at #%llu " > "(0x%llx).\n"), > @@ -645,8 +668,8 @@ static int check_eattr_indir(struct gfs2_inode *ip, uint64_t indirect, > ret = 1; > } else { > fsck_blockmap_set(ip, indirect, > - _("indirect Extended Attribute"), > - gfs2_indir_blk); > + _("indirect Extended Attribute"), sdp->gfs1 ? > + GFS2_BLKST_DINODE : GFS2_BLKST_USED); > bc->ea_count++; > } > return ret; > @@ -715,7 +738,7 @@ static int check_ealeaf_block(struct gfs2_inode *ip, uint64_t block, int btype, > If it isn't, clear it but don't count it as a duplicate. */ > leaf_bh = bread(sdp, block); > if (gfs2_check_meta(leaf_bh, btype)) { > - if (q != gfs2_block_free) { /* Duplicate? */ > + if (q != GFS2_BLKST_FREE) { /* Duplicate? */ > add_duplicate_ref(ip, block, ref_as_ea, 0, > INODE_VALID); > clear_eas(ip, bc, block, 1, > @@ -728,7 +751,7 @@ static int check_ealeaf_block(struct gfs2_inode *ip, uint64_t block, int btype, > brelse(leaf_bh); > return 1; > } > - if (q != gfs2_block_free) { /* Duplicate? */ > + if (q != GFS2_BLKST_FREE) { /* Duplicate? */ > log_debug( _("Duplicate block found at #%lld (0x%llx).\n"), > (unsigned long long)block, > (unsigned long long)block); > @@ -748,9 +771,10 @@ static int check_ealeaf_block(struct gfs2_inode *ip, uint64_t block, int btype, > return 1; > } > /* Point of confusion: We've got to set the ea block itself to > - gfs2_meta_eattr here. Elsewhere we mark the inode with > + GFS2_BLKST_USED here. Elsewhere we mark the inode with > gfs2_eattr_block meaning it contains an eattr for pass1c. */ > - fsck_blockmap_set(ip, block, _("Extended Attribute"), gfs2_meta_eattr); > + fsck_blockmap_set(ip, block, _("Extended Attribute"), > + sdp->gfs1 ? GFS2_BLKST_DINODE : GFS2_BLKST_USED); > bc->ea_count++; > *bh = leaf_bh; > return 0; > @@ -790,7 +814,7 @@ static int check_extended_leaf_eattr(struct gfs2_inode *ip, uint64_t *data_ptr, > (unsigned long long)el_blk); > fsck_blockmap_set(ip, ip->i_di.di_eattr, > _("bad (out of range) Extended Attribute "), > - gfs2_bad_block); > + GFS2_BLKST_UNLINKED); > return 1; > } > error = check_ealeaf_block(ip, el_blk, GFS2_METATYPE_ED, &bh, private); > @@ -831,7 +855,7 @@ static int check_eattr_leaf(struct gfs2_inode *ip, uint64_t block, > (unsigned long long)block, (unsigned long long)block); > fsck_blockmap_set(ip, ip->i_di.di_eattr, > _("bad (out of range) Extended " > - "Attribute leaf"), gfs2_bad_block); > + "Attribute leaf"), GFS2_BLKST_UNLINKED); > return 1; > } > return check_ealeaf_block(ip, block, GFS2_METATYPE_EA, bh, private); > @@ -910,7 +934,7 @@ static int mark_block_invalid(struct gfs2_inode *ip, uint64_t block, > } > > q = block_type(block); > - if (q != gfs2_block_free) { > + if (q != GFS2_BLKST_FREE) { > if (was_duplicate) > *was_duplicate = 1; > add_duplicate_ref(ip, block, reftype, 0, INODE_INVALID); > @@ -923,7 +947,7 @@ static int mark_block_invalid(struct gfs2_inode *ip, uint64_t block, > (unsigned long long)ip->i_di.di_num.no_addr); > return meta_is_good; > } > - fsck_blockmap_set(ip, block, btype, gfs2_meta_inval); > + fsck_blockmap_set(ip, block, btype, GFS2_BLKST_UNLINKED); > return meta_is_good; > } > > @@ -1008,7 +1032,7 @@ static int rangecheck_block(struct gfs2_inode *ip, uint64_t block, > } > /* See how many duplicate blocks it has */ > q = block_type(block); > - if (q != gfs2_block_free) { > + if (q != GFS2_BLKST_FREE) { > (*bad_pointers)++; > log_info( _("Duplicated %s block pointer (violation %ld, block" > " %lld (0x%llx)) found in inode %lld (0x%llx).\n"), > @@ -1100,7 +1124,7 @@ static int handle_ip(struct gfs2_sbd *sdp, struct gfs2_inode *ip) > (unsigned long long)ip->i_di.di_num.no_addr, > BAD_POINTER_TOLERANCE); > fsck_blockmap_set(ip, ip->i_di.di_num.no_addr, > - _("badly corrupt"), gfs2_block_free); > + _("badly corrupt"), GFS2_BLKST_FREE); > return 0; > } > > @@ -1113,7 +1137,7 @@ static int handle_ip(struct gfs2_sbd *sdp, struct gfs2_inode *ip) > metadata will be flagged as metadata or data blocks yet. > Therefore, we don't need to invalidate anything. */ > fsck_blockmap_set(ip, ip->i_di.di_num.no_addr, > - _("invalid mode"), gfs2_block_free); > + _("invalid mode"), GFS2_BLKST_FREE); > return 0; > } else if (error) > goto bad_dinode; > @@ -1241,8 +1265,7 @@ static int handle_di(struct gfs2_sbd *sdp, struct gfs2_buffer_head *bh, > static int check_system_inode(struct gfs2_sbd *sdp, > struct gfs2_inode **sysinode, > const char *filename, > - int builder(struct gfs2_sbd *sdp), > - enum gfs2_mark_block mark, > + int builder(struct gfs2_sbd *sdp), int isdir, > struct gfs2_inode *sysdir, int needs_sysbit) > { > uint64_t iblock = 0; > @@ -1263,8 +1286,8 @@ static int check_system_inode(struct gfs2_sbd *sdp, > "%llu (0x%llx)\n"), > (unsigned long long)iblock, > (unsigned long long)iblock); > - gfs2_blockmap_set(bl, iblock, gfs2_block_free); > - check_n_fix_bitmap(sdp, iblock, 0, gfs2_block_free); > + gfs2_blockmap_set(bl, iblock, GFS2_BLKST_FREE); > + check_n_fix_bitmap(sdp, iblock, 0, GFS2_BLKST_FREE); > inode_put(sysinode); > } > } > @@ -1274,14 +1297,14 @@ static int check_system_inode(struct gfs2_sbd *sdp, > be recovering from a corrupt bitmap. In that case, don't > rebuild the inode. Just reuse the inode and fix the > bitmap. */ > - if (ds.q == gfs2_block_free) { > + if (ds.q == GFS2_BLKST_FREE) { > log_info( _("The inode exists but the block is not " > "marked 'in use'; fixing it.\n")); > fsck_blockmap_set(*sysinode, > (*sysinode)->i_di.di_num.no_addr, > - filename, mark); > - ds.q = mark; > - if (mark == gfs2_inode_dir) > + filename, GFS2_BLKST_DINODE); > + ds.q = GFS2_BLKST_DINODE; > + if (isdir) > dirtree_insert((*sysinode)->i_di.di_num); > } > /* Make sure it's marked as a system file/directory */ > @@ -1297,7 +1320,7 @@ static int check_system_inode(struct gfs2_sbd *sdp, > /* Set the blockmap (but not bitmap) back to > 'free' so that it gets checked like any > normal dinode. */ > - gfs2_blockmap_set(bl, iblock, gfs2_block_free); > + gfs2_blockmap_set(bl, iblock, GFS2_BLKST_FREE); > log_err( _("Removed system inode \"%s\".\n"), > filename); > } > @@ -1309,11 +1332,11 @@ static int check_system_inode(struct gfs2_sbd *sdp, > inode and get it all setup - of course, everything will be in > lost+found then, but we *need* our system inodes before we can > do any of that. */ > - if (!(*sysinode) || ds.q != mark) { > - log_err( _("Invalid or missing %s system inode (should be " > - "'%s', is '%s').\n"), filename, > - block_type_string(mark), > - block_type_string(ds.q)); > + if (!(*sysinode) || ds.q != GFS2_BLKST_DINODE) { > + log_err(_("Invalid or missing %s system inode (is '%s', " > + "should be '%s').\n"), filename, > + block_type_string(ds.q), > + block_type_string(GFS2_BLKST_DINODE)); > if (query(_("Create new %s system inode? (y/n) "), filename)) { > log_err( _("Rebuilding system file \"%s\"\n"), > filename); > @@ -1328,9 +1351,9 @@ static int check_system_inode(struct gfs2_sbd *sdp, > ji_update(sdp); > fsck_blockmap_set(*sysinode, > (*sysinode)->i_di.di_num.no_addr, > - filename, mark); > - ds.q = mark; > - if (mark == gfs2_inode_dir) > + filename, GFS2_BLKST_DINODE); > + ds.q = GFS2_BLKST_DINODE; > + if (isdir) > dirtree_insert((*sysinode)->i_di.di_num); > } else { > log_err( _("Cannot continue without valid %s inode\n"), > @@ -1389,10 +1412,9 @@ static int check_system_inodes(struct gfs2_sbd *sdp) > if (!sdp->gfs1) { > fsck_blockmap_set(sdp->master_dir, > sdp->master_dir->i_di.di_num.no_addr, > - "master", gfs2_inode_dir); > + "master", GFS2_BLKST_DINODE); > if (check_system_inode(sdp, &sdp->master_dir, "master", > - build_master, gfs2_inode_dir, > - NULL, 1)) { > + build_master, 1, NULL, 1)) { > stack; > return -1; > } > @@ -1400,43 +1422,42 @@ static int check_system_inodes(struct gfs2_sbd *sdp) > /* Mark the root dinode as a "dinode" in the block map as we did > for master, since it has no parent. */ > fsck_blockmap_set(sdp->md.rooti, sdp->md.rooti->i_di.di_num.no_addr, > - "root", gfs2_inode_dir); > - if (check_system_inode(sdp, &sdp->md.rooti, "root", build_root, > - gfs2_inode_dir, NULL, 0)) { > + "root", GFS2_BLKST_DINODE); > + if (check_system_inode(sdp, &sdp->md.rooti, "root", build_root, 1, > + NULL, 0)) { > stack; > return -1; > } > if (!sdp->gfs1 && > - check_system_inode(sdp, &sdp->md.inum, "inum", build_inum, > - gfs2_inode_file, sdp->master_dir, 1)) { > + check_system_inode(sdp, &sdp->md.inum, "inum", build_inum, 0, > + sdp->master_dir, 1)) { > stack; > return -1; > } > - if (check_system_inode(sdp, &sdp->md.statfs, "statfs", build_statfs, > - gfs2_inode_file, sdp->master_dir, !sdp->gfs1)) { > + if (check_system_inode(sdp, &sdp->md.statfs, "statfs", build_statfs, 0, > + sdp->master_dir, !sdp->gfs1)) { > stack; > return -1; > } > if (check_system_inode(sdp, &sdp->md.jiinode, "jindex", build_jindex, > - (sdp->gfs1 ? gfs2_inode_file : gfs2_inode_dir), > - sdp->master_dir, !sdp->gfs1)) { > + (sdp->gfs1 ? 0 : 1), sdp->master_dir, > + !sdp->gfs1)) { > stack; > return -1; > } > if (check_system_inode(sdp, &sdp->md.riinode, "rindex", build_rindex, > - gfs2_inode_file, sdp->master_dir, !sdp->gfs1)) { > + 0, sdp->master_dir, !sdp->gfs1)) { > stack; > return -1; > } > if (check_system_inode(sdp, &sdp->md.qinode, "quota", build_quota, > - gfs2_inode_file, sdp->master_dir, !sdp->gfs1)) { > + 0, sdp->master_dir, !sdp->gfs1)) { > stack; > return -1; > } > if (!sdp->gfs1 && > check_system_inode(sdp, &sdp->md.pinode, "per_node", > - build_per_node, gfs2_inode_dir, > - sdp->master_dir, 1)) { > + build_per_node, 1, sdp->master_dir, 1)) { > stack; > return -1; > } > @@ -1464,8 +1485,8 @@ static int check_system_inodes(struct gfs2_sbd *sdp) > > sprintf(jname, "journal%d", sdp->md.journals); > if (check_system_inode(sdp, &sdp->md.journal[sdp->md.journals], > - jname, build_a_journal, > - gfs2_inode_file, sdp->md.jiinode, 1)) { > + jname, build_a_journal, 0, > + sdp->md.jiinode, 1)) { > stack; > return -1; > } > @@ -1529,7 +1550,7 @@ static int pass1_process_bitmap(struct gfs2_sbd *sdp, struct rgrp_tree *rgd, uin > (bh->b_data))->mh_magic; > > q = block_type(block); > - if (q != gfs2_block_free) { > + if (q != GFS2_BLKST_FREE) { > if (be32_to_cpu(check_magic) == GFS2_MAGIC && > sdp->gfs1 && !is_inode) { > log_debug(_("Block 0x%llx assumed to be " > @@ -1580,7 +1601,7 @@ 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_block_free); > + check_n_fix_bitmap(sdp, block, 0, GFS2_BLKST_FREE); > } else if (handle_di(sdp, bh, rgd) < 0) { > stack; > brelse(bh); > @@ -1615,6 +1636,8 @@ static int pass1_process_rgrp(struct gfs2_sbd *sdp, struct rgrp_tree *rgd) > return ret; > } > > + if (fsck_abort) > + return 0; > /* > For GFS1, we have to count the "free meta" blocks in the > resource group and mark them specially so we can count them > @@ -1624,8 +1647,11 @@ static int pass1_process_rgrp(struct gfs2_sbd *sdp, struct rgrp_tree *rgd) > continue; > > n = lgfs2_bm_scan(rgd, k, ibuf, GFS2_BLKST_UNLINKED); > - for (i = 0; i < n; i++) > - gfs2_blockmap_set(bl, ibuf[i], gfs2_freemeta); > + for (i = 0; i < n; i++) { > + gfs2_blockmap_set(bl, ibuf[i], GFS2_BLKST_UNLINKED); > + if (fsck_abort) > + return 0; > + } > } > > free(ibuf); > @@ -1674,6 +1700,8 @@ 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; > next = osi_next(n); > log_debug( _("Checking metadata in Resource Group #%llu\n"), > (unsigned long long)rg_count); > @@ -1683,7 +1711,7 @@ int pass1(struct gfs2_sbd *sdp) > "is now marked as 'rgrp data'\n"), > rgd->ri.ri_addr + i, rgd->ri.ri_addr + i); > if (gfs2_blockmap_set(bl, rgd->ri.ri_addr + i, > - gfs2_indir_blk)) { > + GFS2_BLKST_USED)) { > stack; > gfs2_special_free(&gfs1_rindex_blks); > return FSCK_ERROR; > diff --git a/gfs2/fsck/pass1b.c b/gfs2/fsck/pass1b.c > index f82f43b..a8f3d28 100644 > --- a/gfs2/fsck/pass1b.c > +++ b/gfs2/fsck/pass1b.c > @@ -52,7 +52,6 @@ static void log_inode_reference(struct duptree *dt, osi_list_t *tmp, int inval) > (unsigned long long)dt->block, reftypestring); > } > > -/* delete_all_dups - delete all duplicate records for a given inode */ > /* > * resolve_dup_references - resolve all but the last dinode that has a > * duplicate reference to a given block. > @@ -114,7 +113,7 @@ static void resolve_dup_references(struct gfs2_sbd *sdp, struct duptree *dt, > !found_good_ref) { /* We haven't found a good reference */ > /* If this is an invalid inode, but not on the invalid > list, it's better to delete it. */ > - if (q != gfs2_inode_invalid) { > + if (q == GFS2_BLKST_DINODE) { > found_good_ref = 1; > log_warn( _("Inode %s (%lld/0x%llx)'s " > "reference to block %llu (0x%llx) " > @@ -158,7 +157,7 @@ static void resolve_dup_references(struct gfs2_sbd *sdp, struct duptree *dt, > dup_listent_delete(dt, id); > continue; > } > - if (q == gfs2_block_free) > + if (q == GFS2_BLKST_FREE) > log_warn( _("Inode %lld (0x%llx) was previously " > "deleted.\n"), > (unsigned long long)id->block_no, > @@ -172,7 +171,7 @@ static void resolve_dup_references(struct gfs2_sbd *sdp, struct duptree *dt, > /* If we've already deleted this dinode, don't try to delete > it again. That could free blocks that used to be duplicate > references that are now resolved (and gone). */ > - if (q != gfs2_block_free) { > + if (q != GFS2_BLKST_FREE) { > /* Clear the EAs for the inode first */ > check_inode_eattr(ip, &pass1b_fxns_delete); > /* If the reference was as metadata or data, we've got > @@ -185,7 +184,7 @@ static void resolve_dup_references(struct gfs2_sbd *sdp, struct duptree *dt, > inodetree_delete(ii); > fsck_blockmap_set(ip, ip->i_di.di_num.no_addr, > _("duplicate referencing bad"), > - gfs2_inode_invalid); > + GFS2_BLKST_UNLINKED); > /* We delete the dup_handler inode count and > duplicate id BEFORE clearing the metadata, > because if this is the last reference to > @@ -391,7 +390,7 @@ static int handle_dup_blk(struct gfs2_sbd *sdp, struct duptree *dt) > ip = fsck_load_inode(sdp, id->block_no); > > q = block_type(id->block_no); > - if (q == gfs2_inode_invalid) { > + if (q == GFS2_BLKST_UNLINKED) { > log_debug( _("The remaining reference inode %lld " > "(0x%llx) is marked invalid: Marking " > "the block as free.\n"), > @@ -399,28 +398,32 @@ static int handle_dup_blk(struct gfs2_sbd *sdp, struct duptree *dt) > (unsigned long long)id->block_no); > fsck_blockmap_set(ip, dt->block, > _("reference-repaired leaf"), > - gfs2_block_free); > + GFS2_BLKST_FREE); > } else if (id->reftypecount[ref_is_inode]) { > set_ip_blockmap(ip, 0); /* 0=do not add to dirtree */ > } else if (id->reftypecount[ref_as_data]) { > fsck_blockmap_set(ip, dt->block, > _("reference-repaired data"), > - gfs2_block_used); > + GFS2_BLKST_USED); > } else if (id->reftypecount[ref_as_meta]) { > if (is_dir(&ip->i_di, sdp->gfs1)) > fsck_blockmap_set(ip, dt->block, > _("reference-repaired leaf"), > - gfs2_leaf_blk); > + sdp->gfs1 ? > + GFS2_BLKST_DINODE : > + GFS2_BLKST_USED); > else > fsck_blockmap_set(ip, dt->block, > _("reference-repaired " > - "indirect"), > - gfs2_indir_blk); > + "indirect"), sdp->gfs1 ? > + GFS2_BLKST_DINODE : > + GFS2_BLKST_USED); > } else > fsck_blockmap_set(ip, dt->block, > _("reference-repaired extended " > "attribute"), > - gfs2_meta_eattr); > + sdp->gfs1 ? GFS2_BLKST_DINODE : > + GFS2_BLKST_USED); > fsck_inode_put(&ip); /* out, brelse, free */ > log_debug(_("Done with duplicate reference to block 0x%llx\n"), > (unsigned long long)dt->block); > @@ -441,8 +444,8 @@ static int handle_dup_blk(struct gfs2_sbd *sdp, struct duptree *dt) > if (dh.dt) > dup_delete(dh.dt); > /* Now fix the block type of the block in question. */ > - gfs2_blockmap_set(bl, dup_blk, gfs2_block_free); > - check_n_fix_bitmap(sdp, dup_blk, 0, gfs2_block_free); > + gfs2_blockmap_set(bl, dup_blk, GFS2_BLKST_FREE); > + check_n_fix_bitmap(sdp, dup_blk, 0, GFS2_BLKST_FREE); > } > } > return 0; > @@ -599,13 +602,11 @@ int pass1b(struct gfs2_sbd *sdp) > } > q = block_type(i); > > - if (q < gfs2_inode_dir) > - continue; > - if (q > gfs2_inode_invalid) > + if (q == GFS2_BLKST_FREE || q == GFS2_BLKST_USED) > continue; > > - if (q == gfs2_inode_invalid) > - log_debug( _("Checking invalidated duplicate dinode " > + if (q == GFS2_BLKST_UNLINKED) > + log_debug( _("Checking invalidated duplicate block " > "%lld (0x%llx)\n"), > (unsigned long long)i, > (unsigned long long)i); > diff --git a/gfs2/fsck/pass1c.c b/gfs2/fsck/pass1c.c > index ce9ca96..aa905da 100644 > --- a/gfs2/fsck/pass1c.c > +++ b/gfs2/fsck/pass1c.c > @@ -97,7 +97,7 @@ static int check_eattr_indir(struct gfs2_inode *ip, uint64_t block, > return ask_remove_eattr(ip); > } > q = block_type(block); > - if (q != gfs2_indir_blk) { > + if (q != (sdp->gfs1 ? GFS2_BLKST_DINODE : GFS2_BLKST_USED)) { > log_err( _("Extended attributes indirect block #%llu" > " (0x%llx) for inode #%llu" > " (0x%llx) is invalid.\n"), > @@ -122,16 +122,18 @@ static int check_eattr_leaf(struct gfs2_inode *ip, uint64_t block, > uint8_t q; > > if (!valid_block(sdp, block)) { > - log_err( _("Extended attributes block for inode #%llu" > - " (0x%llx) is invalid.\n"), > - (unsigned long long)ip->i_di.di_num.no_addr, > - (unsigned long long)ip->i_di.di_num.no_addr); > + log_err( _("Extended attributes block %lld (0x%llx) for " > + "inode #%llu (0x%llx) is invalid.\n"), > + (unsigned long long)block, (unsigned long long)block, > + (unsigned long long)ip->i_di.di_num.no_addr, > + (unsigned long long)ip->i_di.di_num.no_addr); > return ask_remove_eattr(ip); > } > q = block_type(block); > - if (q != gfs2_meta_eattr) { > - log_err( _("Extended attributes block for inode #%llu" > - " (0x%llx) invalid.\n"), > + if (q != (sdp->gfs1 ? GFS2_BLKST_DINODE : GFS2_BLKST_USED)) { > + log_err( _("Extended attributes block %lld (0x%llx) for " > + "inode #%llu (0x%llx) invalid.\n"), > + (unsigned long long)block, (unsigned long long)block, > (unsigned long long)ip->i_di.di_num.no_addr, > (unsigned long long)ip->i_di.di_num.no_addr); > return ask_remove_eattr(ip); > @@ -218,7 +220,7 @@ static int check_eattr_extentry(struct gfs2_inode *ip, uint64_t *ea_ptr, > struct gfs2_sbd *sdp = ip->i_sbd; > > q = block_type(be64_to_cpu(*ea_ptr)); > - if (q != gfs2_meta_eattr) { > + if (q != (sdp->gfs1 ? GFS2_BLKST_DINODE : GFS2_BLKST_USED)) { > if (remove_eattr_entry(sdp, leaf_bh, ea_hdr, ea_hdr_prev)){ > stack; > return -1; > diff --git a/gfs2/fsck/pass2.c b/gfs2/fsck/pass2.c > index 74bcc26..1d32335 100644 > --- a/gfs2/fsck/pass2.c > +++ b/gfs2/fsck/pass2.c > @@ -135,40 +135,28 @@ static const char *de_type_string(uint8_t de_type) > return de_types[3]; /* invalid */ > } > > -static int check_file_type(uint8_t de_type, uint8_t blk_type, int gfs1) > +static int check_file_type(uint64_t block, uint8_t de_type, uint8_t q, > + int gfs1, int *isdir) > { > - switch(blk_type) { > - case gfs2_inode_dir: > - if (de_type != (gfs1 ? GFS_FILE_DIR : DT_DIR)) > - return 1; > - break; > - case gfs2_inode_file: > - if (de_type != (gfs1 ? GFS_FILE_REG : DT_REG)) > - return 1; > - break; > - case gfs2_inode_lnk: > - if (de_type != (gfs1 ? GFS_FILE_LNK : DT_LNK)) > - return 1; > - break; > - case gfs2_inode_device: > - if ((de_type != (gfs1 ? GFS_FILE_BLK : DT_BLK)) && > - (de_type != (gfs1 ? GFS_FILE_CHR : DT_CHR))) > - return 1; > - break; > - case gfs2_inode_fifo: > - if (de_type != (gfs1 ? GFS_FILE_FIFO : DT_FIFO)) > - return 1; > - break; > - case gfs2_inode_sock: > - if (de_type != (gfs1 ? GFS_FILE_SOCK : DT_SOCK)) > - return 1; > - break; > - default: > + struct dir_info *dt; > + > + *isdir = 0; > + if (q != GFS2_BLKST_DINODE) { > log_err( _("Invalid block type\n")); > return -1; > - break; > } > - return 0; > + if (de_type == (gfs1 ? GFS_FILE_DIR : DT_DIR)) > + *isdir = 1; > + /* Check if the dinode is in the dir tree */ > + dt = dirtree_find(block); > + /* This is a bit confusing, so let me explain: > + If the dirent says the inode supposed to be for a directory, > + it should be in the dir tree. If it is, no problem, return 0. > + If it's not, return 1 (wrong type). If it's not supposed to be > + a directory, it shouldn't be in the dir tree. */ > + if (dt) > + return !(*isdir); > + return *isdir; > } > > struct metawalk_fxns pass2_fxns_delete = { > @@ -209,7 +197,7 @@ static int bad_formal_ino(struct gfs2_inode *ip, struct gfs2_dirent *dent, > (unsigned long long)entry.no_formal_ino, > (unsigned long long)ii->di_num.no_formal_ino, > (unsigned long long)ii->di_num.no_formal_ino); > - if (q != gfs2_inode_dir || !strcmp("..", tmp_name)) { > + if (q != GFS2_BLKST_DINODE || !strcmp("..", tmp_name)) { > if (query( _("Remove the corrupt directory entry? (y/n) "))) > return 1; > log_err( _("Corrupt directory entry not removed.\n")); > @@ -388,7 +376,8 @@ static int wrong_leaf(struct gfs2_inode *ip, struct gfs2_inum *entry, > (unsigned long long)real_leaf, > (unsigned long long)ip->i_di.di_blocks); > fsck_blockmap_set(ip, real_leaf, _("split leaf"), > - gfs2_indir_blk); > + sdp->gfs1 ? GFS2_BLKST_DINODE : > + GFS2_BLKST_USED); > } > /* If the misplaced dirent was supposed to be earlier in the > hash table, we need to adjust our counts for the blocks > @@ -449,7 +438,7 @@ static int basic_dentry_checks(struct gfs2_inode *ip, struct gfs2_dirent *dent, > struct gfs2_inum *entry, const char *tmp_name, > uint32_t *count, struct gfs2_dirent *de, > struct dir_status *ds, uint8_t *q, > - struct gfs2_buffer_head *bh) > + struct gfs2_buffer_head *bh, int *isdir) > { > struct gfs2_sbd *sdp = ip->i_sbd; > uint32_t calculated_hash; > @@ -457,6 +446,7 @@ static int basic_dentry_checks(struct gfs2_inode *ip, struct gfs2_dirent *dent, > int error; > struct inode_info *ii; > > + *isdir = 0; > if (!valid_block(ip->i_sbd, entry->no_addr)) { > log_err( _("Block # referenced by directory entry %s in inode " > "%lld (0x%llx) is invalid\n"), > @@ -487,7 +477,7 @@ static int basic_dentry_checks(struct gfs2_inode *ip, struct gfs2_dirent *dent, > /* Don't be tempted to do this: > fsck_blockmap_set(ip, ip->i_di.di_num.no_addr, > _("corrupt directory entry"), > - gfs2_inode_invalid); > + GFS2_BLKST_FREE); > We can't free it because another dir may have a valid reference > to it. Just return 1 so we can delete the bad dirent. */ > log_err( _("Bad directory entry deleted.\n")); > @@ -530,41 +520,7 @@ static int basic_dentry_checks(struct gfs2_inode *ip, struct gfs2_dirent *dent, > * 2. Blocks marked "bad" need to have their entire > * metadata tree deleted. > */ > - if (*q == gfs2_inode_invalid || *q == gfs2_bad_block) { > - /* This entry's inode has bad blocks in it */ > - > - /* Handle bad blocks */ > - log_err( _("Found directory entry '%s' pointing to invalid " > - "block %lld (0x%llx)\n"), tmp_name, > - (unsigned long long)entry->no_addr, > - (unsigned long long)entry->no_addr); > - > - if (!query( _("Delete inode containing bad blocks? (y/n)"))) { > - log_warn( _("Entry to inode containing bad blocks remains\n")); > - return 0; > - } > - > - if (*q == gfs2_bad_block) { > - if (ip->i_di.di_num.no_addr == entry->no_addr) > - entry_ip = ip; > - else > - entry_ip = fsck_load_inode(sdp, entry->no_addr); > - if (ip->i_di.di_eattr) { > - check_inode_eattr(entry_ip, > - &pass2_fxns_delete); > - } > - check_metatree(entry_ip, &pass2_fxns_delete); > - if (entry_ip != ip) > - fsck_inode_put(&entry_ip); > - } > - fsck_blockmap_set(ip, entry->no_addr, > - _("bad directory entry"), gfs2_block_free); > - log_err( _("Inode %lld (0x%llx) was deleted.\n"), > - (unsigned long long)entry->no_addr, > - (unsigned long long)entry->no_addr); > - return 1; > - } > - if (*q < gfs2_inode_dir || *q > gfs2_inode_sock) { > + if (*q != GFS2_BLKST_DINODE) { > log_err( _("Directory entry '%s' referencing inode %llu " > "(0x%llx) in dir inode %llu (0x%llx) block type " > "%d: %s.\n"), tmp_name, > @@ -572,7 +528,7 @@ static int basic_dentry_checks(struct gfs2_inode *ip, struct gfs2_dirent *dent, > (unsigned long long)entry->no_addr, > (unsigned long long)ip->i_di.di_num.no_addr, > (unsigned long long)ip->i_di.di_num.no_addr, > - *q, *q == gfs2_inode_invalid ? > + *q, *q == GFS2_BLKST_FREE ? > _("was previously marked invalid") : > _("was deleted or is not an inode")); > > @@ -601,7 +557,8 @@ static int basic_dentry_checks(struct gfs2_inode *ip, struct gfs2_dirent *dent, > return 1; > } > > - error = check_file_type(de->de_type, *q, sdp->gfs1); > + error = check_file_type(entry->no_addr, de->de_type, *q, sdp->gfs1, > + isdir); > if (error < 0) { > log_err( _("Error: directory entry type is " > "incompatible with block type at block %lld " > @@ -674,6 +631,7 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent, > struct gfs2_dirent dentry, *de; > int hash_index; /* index into the hash table based on the hash */ > int lindex_max; /* largest acceptable hash table index for hash */ > + int isdir; > > memset(&dentry, 0, sizeof(struct gfs2_dirent)); > gfs2_dirent_in(&dentry, (char *)dent); > @@ -690,7 +648,7 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent, > strncpy(tmp_name, filename, MAX_FILENAME - 1); > > error = basic_dentry_checks(ip, dent, &entry, tmp_name, count, de, > - ds, &q, bh); > + ds, &q, bh, &isdir); > if (error) > goto nuke_dentry; > > @@ -781,8 +739,7 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent, > > goto nuke_dentry; > } > - > - if (q != gfs2_inode_dir) { > + if (!isdir) { > log_err( _("Found '..' entry in directory %llu (0x%llx) " > "pointing to something that's not a directory"), > (unsigned long long)ip->i_di.di_num.no_addr, > @@ -831,7 +788,7 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent, > } > > /* After this point we're only concerned with directories */ > - if (q != gfs2_inode_dir) { > + if (!isdir) { > log_debug( _("Found non-dir inode dentry pointing to %lld " > "(0x%llx)\n"), > (unsigned long long)entry.no_addr, > @@ -916,7 +873,8 @@ static void pad_with_leafblks(struct gfs2_inode *ip, uint64_t *tbl, > (unsigned long long)new_leaf_blk, > lindex, lindex, new_len); > fsck_blockmap_set(ip, new_leaf_blk, _("pad leaf"), > - gfs2_leaf_blk); > + ip->i_sbd->gfs1 ? > + GFS2_BLKST_DINODE : GFS2_BLKST_USED); > /* Fix the hash table in memory to have the new leaf */ > for (i = 0; i < new_len; i++) > tbl[lindex + i] = cpu_to_be64(new_leaf_blk); > @@ -941,6 +899,7 @@ static int lost_leaf(struct gfs2_inode *ip, uint64_t *tbl, uint64_t leafno, > char *bh_end = bh->b_data + ip->i_sbd->bsize; > struct gfs2_dirent de, *dent; > int error; > + int isdir = 0; > > log_err(_("Leaf block %llu (0x%llx) seems to be out of place and its " > "contents need to be moved to lost+found.\n"), > @@ -979,7 +938,7 @@ static int lost_leaf(struct gfs2_inode *ip, uint64_t *tbl, uint64_t leafno, > > error = basic_dentry_checks(ip, dent, &de.de_inum, > tmp_name, &count, &de, > - &ds, &q, bh); > + &ds, &q, bh, &isdir); > if (error) { > log_err(_("Not relocating corrupt entry " > "\"%s\".\n"), tmp_name); > @@ -999,7 +958,7 @@ static int lost_leaf(struct gfs2_inode *ip, uint64_t *tbl, uint64_t leafno, > _("from lost+found")); > /* If it's a directory, lost+found is > back-linked to it via .. */ > - if (q == gfs2_inode_dir) > + if (isdir) > incr_link_count(lf_dip->i_di.di_num, > NULL, > _("to lost+found")); > @@ -1017,7 +976,7 @@ static int lost_leaf(struct gfs2_inode *ip, uint64_t *tbl, uint64_t leafno, > log_err(_("Directory entries from misplaced leaf block were relocated " > "to lost+found.\n")); > /* Free the lost leaf. */ > - fsck_blockmap_set(ip, leafno, _("lost leaf"), gfs2_block_free); > + fsck_blockmap_set(ip, leafno, _("lost leaf"), GFS2_BLKST_FREE); > ip->i_di.di_blocks--; > bmodified(ip->i_bh); > /* Now we have to deal with the bad hash table entries pointing to the > @@ -1039,6 +998,7 @@ static int basic_check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent, > struct dir_status *ds = (struct dir_status *) priv; > struct gfs2_dirent dentry, *de; > int error; > + int isdir; > > memset(&dentry, 0, sizeof(struct gfs2_dirent)); > gfs2_dirent_in(&dentry, (char *)dent); > @@ -1055,7 +1015,7 @@ static int basic_check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent, > strncpy(tmp_name, filename, MAX_FILENAME - 1); > > error = basic_dentry_checks(ip, dent, &entry, tmp_name, count, de, > - ds, &q, bh); > + ds, &q, bh, &isdir); > if (error) { > dirent2_del(ip, bh, prev_de, dent); > log_err( _("Bad directory entry '%s' cleared.\n"), tmp_name); > @@ -1248,7 +1208,8 @@ static int fix_hashtable(struct gfs2_inode *ip, uint64_t *tbl, unsigned hsize, > (unsigned long long)new_leaf_blk, > (unsigned long long)new_leaf_blk, lindex, lindex); > fsck_blockmap_set(ip, new_leaf_blk, _("split leaf"), > - gfs2_leaf_blk); > + ip->i_sbd->gfs1 ? > + GFS2_BLKST_DINODE : GFS2_BLKST_USED); > log_err(_("Hash table repaired.\n")); > /* Fix up the hash table in memory to include the new leaf */ > for (i = 0; i < *proper_len; i++) > @@ -1712,7 +1673,7 @@ build_it: > log_err(_("Error rebuilding %s.\n"), fn); > return -1; > } > - fsck_blockmap_set(ip, ip->i_di.di_num.no_addr, fn, gfs2_inode_file); > + fsck_blockmap_set(ip, ip->i_di.di_num.no_addr, fn, GFS2_BLKST_DINODE); > reprocess_inode(ip, fn); > log_err(_("System file %s rebuilt.\n"), fn); > goto out_good; > @@ -1740,7 +1701,7 @@ static int check_system_dir(struct gfs2_inode *sysinode, const char *dirname, > ds.q = block_type(iblock); > > pass2_fxns.private = (void *) &ds; > - if (ds.q == gfs2_bad_block) { > + if (ds.q == GFS2_BLKST_UNLINKED) { > astate_save(sysinode, &as); > /* First check that the directory's metatree is valid */ > error = check_metatree(sysinode, &pass2_fxns); > @@ -1759,8 +1720,7 @@ static int check_system_dir(struct gfs2_inode *sysinode, const char *dirname, > return -1; > } > if (error > 0) > - fsck_blockmap_set(sysinode, iblock, dirname, > - gfs2_inode_invalid); > + fsck_blockmap_set(sysinode, iblock, dirname, GFS2_BLKST_FREE); > > if (check_inode_eattr(sysinode, &pass2_fxns)) { > stack; > @@ -1866,6 +1826,7 @@ int pass2(struct gfs2_sbd *sdp) > struct dir_status ds = {0}; > struct gfs2_inode *ip; > int error = 0; > + struct dir_info *dt; > > /* Check all the system directory inodes. */ > if (!sdp->gfs1 && > @@ -1908,7 +1869,11 @@ int pass2(struct gfs2_sbd *sdp) > > q = block_type(dirblk); > > - if (q != gfs2_inode_dir) > + if (q != GFS2_BLKST_DINODE) > + continue; > + > + dt = dirtree_find(dirblk); > + if (dt == NULL) > continue; > > /* If we created lost+found, its links should have been > @@ -1924,7 +1889,7 @@ int pass2(struct gfs2_sbd *sdp) > > memset(&ds, 0, sizeof(ds)); > pass2_fxns.private = (void *) &ds; > - if (ds.q == gfs2_bad_block) { > + if (ds.q == GFS2_BLKST_UNLINKED) { > /* First check that the directory's metatree > * is valid */ > ip = fsck_load_inode(sdp, dirblk); > @@ -1985,8 +1950,8 @@ int pass2(struct gfs2_sbd *sdp) > (unsigned long long)dirblk); > /* Can't use fsck_blockmap_set here because we don't > have an inode in memory. */ > - gfs2_blockmap_set(bl, dirblk, gfs2_inode_invalid); > - check_n_fix_bitmap(sdp, dirblk, 0, gfs2_inode_invalid); > + gfs2_blockmap_set(bl, dirblk, GFS2_BLKST_FREE); > + check_n_fix_bitmap(sdp, dirblk, 0, GFS2_BLKST_FREE); > } > ip = fsck_load_inode(sdp, dirblk); > if (!ds.dotdir) { > diff --git a/gfs2/fsck/pass3.c b/gfs2/fsck/pass3.c > index 3e183e5..054953f 100644 > --- a/gfs2/fsck/pass3.c > +++ b/gfs2/fsck/pass3.c > @@ -67,6 +67,7 @@ static struct dir_info *mark_and_return_parent(struct gfs2_sbd *sdp, > struct dir_info *pdi; > uint8_t q_dotdot, q_treewalk; > int error = 0; > + struct dir_info *dt_dotdot, *dt_treewalk; > > di->checked = 1; > > @@ -75,7 +76,7 @@ static struct dir_info *mark_and_return_parent(struct gfs2_sbd *sdp, > > if (di->dotdot_parent.no_addr == di->treewalk_parent) { > q_dotdot = block_type(di->dotdot_parent.no_addr); > - if (q_dotdot != gfs2_inode_dir) { > + if (q_dotdot != GFS2_BLKST_DINODE) { > log_err( _("Orphaned directory at block %llu (0x%llx) " > "moved to lost+found\n"), > (unsigned long long)di->dinode.no_addr, > @@ -95,7 +96,9 @@ static struct dir_info *mark_and_return_parent(struct gfs2_sbd *sdp, > (unsigned long long)di->treewalk_parent, > (unsigned long long)di->treewalk_parent); > q_dotdot = block_type(di->dotdot_parent.no_addr); > + dt_dotdot = dirtree_find(di->dotdot_parent.no_addr); > q_treewalk = block_type(di->treewalk_parent); > + dt_treewalk = dirtree_find(di->treewalk_parent); > /* if the dotdot entry isn't a directory, but the > * treewalk is, treewalk is correct - if the treewalk > * entry isn't a directory, but the dotdot is, dotdot > @@ -103,8 +106,8 @@ static struct dir_info *mark_and_return_parent(struct gfs2_sbd *sdp, > * choose? if neither are directories, we have a > * problem - need to move this directory into lost+found > */ > - if (q_dotdot != gfs2_inode_dir) { > - if (q_treewalk != gfs2_inode_dir) { > + if (q_dotdot != GFS2_BLKST_DINODE || dt_dotdot == NULL) { > + if (q_treewalk != GFS2_BLKST_DINODE) { > log_err( _("Orphaned directory, move to " > "lost+found\n")); > return NULL; > @@ -120,7 +123,7 @@ static struct dir_info *mark_and_return_parent(struct gfs2_sbd *sdp, > } > goto out; > } > - if (q_treewalk == gfs2_inode_dir) { > + if (dt_treewalk) { > log_err( _("Both .. and treewalk parents are directories, " > "going with treewalk...\n")); > attach_dotdot_to(sdp, di->treewalk_parent, > @@ -247,7 +250,7 @@ int pass3(struct gfs2_sbd *sdp) > continue; > } > q = block_type(di->dinode.no_addr); > - if (q == gfs2_bad_block) { > + if (q == GFS2_BLKST_UNLINKED) { > log_err( _("Found unlinked directory " > "containing bad block at block %llu" > " (0x%llx)\n"), > @@ -264,16 +267,14 @@ int pass3(struct gfs2_sbd *sdp) > /* Can't use fsck_blockmap_set > because we don't have ip */ > gfs2_blockmap_set(bl, di->dinode.no_addr, > - gfs2_block_free); > + GFS2_BLKST_FREE); > check_n_fix_bitmap(sdp, di->dinode.no_addr, > - 0, gfs2_block_free); > + 0, GFS2_BLKST_FREE); > break; > } else > log_err( _("Unlinked directory with bad block remains\n")); > } > - if (q != gfs2_inode_dir && q != gfs2_inode_file && > - q != gfs2_inode_lnk && q != gfs2_inode_device && > - q != gfs2_inode_fifo && q != gfs2_inode_sock) { > + if (q != GFS2_BLKST_DINODE) { > log_err( _("Unlinked block marked as an inode " > "is not an inode\n")); > if (!query(_("Clear the unlinked block?" > @@ -289,9 +290,9 @@ int pass3(struct gfs2_sbd *sdp) > /* Can't use fsck_blockmap_set > because we don't have ip */ > gfs2_blockmap_set(bl, di->dinode.no_addr, > - gfs2_block_free); > + GFS2_BLKST_FREE); > check_n_fix_bitmap(sdp, di->dinode.no_addr, 0, > - gfs2_block_free); > + GFS2_BLKST_FREE); > log_err( _("The block was cleared\n")); > break; > } > @@ -310,7 +311,7 @@ int pass3(struct gfs2_sbd *sdp) > fsck_blockmap_set(ip, > di->dinode.no_addr, > _("zero-sized unlinked inode"), > - gfs2_block_free); > + GFS2_BLKST_FREE); > fsck_inode_put(&ip); > break; > } else { > diff --git a/gfs2/fsck/pass4.c b/gfs2/fsck/pass4.c > index 324ea9f..f307782 100644 > --- a/gfs2/fsck/pass4.c > +++ b/gfs2/fsck/pass4.c > @@ -71,7 +71,7 @@ static int scan_inode_list(struct gfs2_sbd *sdp) { > (unsigned long long)ii->di_num.no_addr, > (unsigned long long)ii->di_num.no_addr); > q = block_type(ii->di_num.no_addr); > - if (q == gfs2_bad_block) { > + if (q == GFS2_BLKST_UNLINKED) { > log_err( _("Unlinked inode %llu (0x%llx) contains " > "bad blocks\n"), > (unsigned long long)ii->di_num.no_addr, > @@ -84,18 +84,13 @@ static int scan_inode_list(struct gfs2_sbd *sdp) { > check_metatree(ip, &pass4_fxns_delete); > fsck_blockmap_set(ip, ii->di_num.no_addr, > _("bad unlinked"), > - gfs2_block_free); > + GFS2_BLKST_FREE); > fsck_inode_put(&ip); > continue; > } else > log_err( _("Unlinked inode with bad blocks not cleared\n")); > } > - if (q != gfs2_inode_dir && > - q != gfs2_inode_file && > - q != gfs2_inode_lnk && > - q != gfs2_inode_device && > - q != gfs2_inode_fifo && > - q != gfs2_inode_sock) { > + if (q != GFS2_BLKST_DINODE) { > log_err( _("Unlinked block %lld (0x%llx) " > "marked as inode is " > "not an inode (%d)\n"), > @@ -108,7 +103,7 @@ static int scan_inode_list(struct gfs2_sbd *sdp) { > check_metatree(ip, &pass4_fxns_delete); > fsck_blockmap_set(ip, ii->di_num.no_addr, > _("invalid unlinked"), > - gfs2_block_free); > + GFS2_BLKST_FREE); > fsck_inode_put(&ip); > log_err( _("The inode was deleted\n")); > } else { > @@ -129,7 +124,7 @@ static int scan_inode_list(struct gfs2_sbd *sdp) { > "(y/n) "))) { > fsck_blockmap_set(ip, ii->di_num.no_addr, > _("unlinked zero-length"), > - gfs2_block_free); > + GFS2_BLKST_FREE); > fsck_inode_put(&ip); > continue; > } > diff --git a/gfs2/fsck/pass5.c b/gfs2/fsck/pass5.c > index 2b8536d..fab3e5c 100644 > --- a/gfs2/fsck/pass5.c > +++ b/gfs2/fsck/pass5.c > @@ -34,7 +34,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 = blockmap_to_bitmap(block_type(block), sdp->gfs1); > + q = block_type(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 > diff --git a/gfs2/fsck/util.c b/gfs2/fsck/util.c > index a0f6009..efdd132 100644 > --- a/gfs2/fsck/util.c > +++ b/gfs2/fsck/util.c > @@ -375,7 +375,7 @@ int add_duplicate_ref(struct gfs2_inode *ip, uint64_t block, > q = block_type(ip->i_di.di_num.no_addr); > /* If it's an invalid dinode, put it first on the invalid > inode reference list otherwise put it on the normal list. */ > - if (!inode_valid || q == gfs2_inode_invalid) > + if (!inode_valid || q == GFS2_BLKST_UNLINKED) > osi_list_add_prev(&id->list, &dt->ref_invinode_list); > else { > /* If this is a system dinode, we want the duplicate > @@ -526,7 +526,7 @@ static int gfs2_blockmap_create(struct gfs2_bmap *bmap, uint64_t size) > > /* Have to add 1 to BLOCKMAP_SIZE since it's 0-based and mallocs > * must be 1-based */ > - bmap->mapsize = BLOCKMAP_SIZE4(size) + 1; > + bmap->mapsize = BLOCKMAP_SIZE2(size) + 1; > > if (!(bmap->map = calloc(bmap->mapsize, sizeof(char)))) > return -ENOMEM; > @@ -560,8 +560,7 @@ struct gfs2_bmap *gfs2_bmap_create(struct gfs2_sbd *sdp, uint64_t size, > return il; > } > > -int gfs2_blockmap_set(struct gfs2_bmap *bmap, uint64_t bblock, > - enum gfs2_mark_block mark) > +int gfs2_blockmap_set(struct gfs2_bmap *bmap, uint64_t bblock, int mark) > { > static unsigned char *byte; > static uint64_t b; > @@ -571,10 +570,10 @@ int gfs2_blockmap_set(struct gfs2_bmap *bmap, uint64_t bblock, > if (bblock > bmap->size) > return -1; > > - byte = bmap->map + BLOCKMAP_SIZE4(bblock); > - b = BLOCKMAP_BYTE_OFFSET4(bblock); > - *byte &= ~(BLOCKMAP_MASK4 << b); > - *byte |= (mark & BLOCKMAP_MASK4) << b; > + byte = bmap->map + BLOCKMAP_SIZE2(bblock); > + b = BLOCKMAP_BYTE_OFFSET2(bblock); > + *byte &= ~(BLOCKMAP_MASK2 << b); > + *byte |= (mark & BLOCKMAP_MASK2) << b; > return 0; > } > > @@ -598,61 +597,45 @@ void *gfs2_bmap_destroy(struct gfs2_sbd *sdp, struct gfs2_bmap *il) > int set_ip_blockmap(struct gfs2_inode *ip, int instree) > { > uint64_t block = ip->i_bh->b_blocknr; > - struct gfs2_sbd *sdp = ip->i_sbd; > uint32_t mode; > + const char *ty; > > - if (sdp->gfs1) > + if (ip->i_sbd->gfs1) > mode = gfs_to_gfs2_mode(ip); > else > mode = ip->i_di.di_mode & S_IFMT; > > switch (mode) { > case S_IFDIR: > - if (fsck_blockmap_set(ip, block, _("directory"), > - gfs2_inode_dir)) > - goto bad_dinode; > - if (instree && !dirtree_insert(ip->i_di.di_num)) > - goto bad_dinode; > + ty = _("directory"); > break; > case S_IFREG: > - if (fsck_blockmap_set(ip, block, _("file"), gfs2_inode_file)) > - goto bad_dinode; > + ty = _("file"); > break; > case S_IFLNK: > - if (fsck_blockmap_set(ip, block, _("symlink"), > - gfs2_inode_lnk)) > - goto bad_dinode; > + ty = _("symlink"); > break; > case S_IFBLK: > - if (fsck_blockmap_set(ip, block, _("block device"), > - gfs2_inode_device)) > - goto bad_dinode; > + ty = _("block device"); > break; > case S_IFCHR: > - if (fsck_blockmap_set(ip, block, _("character device"), > - gfs2_inode_device)) > - goto bad_dinode; > + ty = _("character device"); > break; > case S_IFIFO: > - if (fsck_blockmap_set(ip, block, _("fifo"), > - gfs2_inode_fifo)) > - goto bad_dinode; > + ty = _("fifo"); > break; > case S_IFSOCK: > - if (fsck_blockmap_set(ip, block, _("socket"), > - gfs2_inode_sock)) > - goto bad_dinode; > + ty = _("socket"); > break; > default: > - fsck_blockmap_set(ip, block, _("invalid mode"), > - gfs2_inode_invalid); > return -EINVAL; > } > + if (fsck_blockmap_set(ip, block, ty, GFS2_BLKST_DINODE) || > + (mode == S_IFDIR && instree && !dirtree_insert(ip->i_di.di_num))) { > + stack; > + return -EPERM; > + } > return 0; > - > -bad_dinode: > - stack; > - return -EPERM; > } > > uint64_t find_free_blk(struct gfs2_sbd *sdp) > diff --git a/gfs2/fsck/util.h b/gfs2/fsck/util.h > index 66b9c7a..62f8ca6 100644 > --- a/gfs2/fsck/util.h > +++ b/gfs2/fsck/util.h > @@ -28,9 +28,9 @@ extern void dup_listent_delete(struct duptree *dt, struct inode_with_dups *id); > > extern const char *reftypes[ref_types + 1]; > > -#define BLOCKMAP_SIZE4(size) ((size) >> 1) > -#define BLOCKMAP_BYTE_OFFSET4(x) (((x) & 0x0000000000000001) << 2) > -#define BLOCKMAP_MASK4 (0xf) > +#define BLOCKMAP_SIZE2(size) ((size) >> 2) > +#define BLOCKMAP_BYTE_OFFSET2(x) ((x & 0x0000000000000003) << 1) > +#define BLOCKMAP_MASK2 (0x3) > > static inline void astate_save(struct gfs2_inode *ip, struct alloc_state *as) > { > @@ -53,110 +53,18 @@ static inline uint8_t block_type(uint64_t bblock) > static uint64_t b; > static uint8_t btype; > > - byte = bl->map + BLOCKMAP_SIZE4(bblock); > - b = BLOCKMAP_BYTE_OFFSET4(bblock); > - btype = (*byte & (BLOCKMAP_MASK4 << b )) >> b; > + byte = bl->map + BLOCKMAP_SIZE2(bblock); > + b = BLOCKMAP_BYTE_OFFSET2(bblock); > + btype = (*byte & (BLOCKMAP_MASK2 << b )) >> b; > return btype; > } > > -/* blockmap declarations and functions */ > -enum gfs2_mark_block { > - gfs2_block_free = (0x0), > - gfs2_block_used = (0x1), > - gfs2_indir_blk = (0x2), > - /* These are inode block types (only): */ > - gfs2_inode_dir = (0x3), > - gfs2_inode_file = (0x4), > - > - gfs2_inode_lnk = (0x5), > - gfs2_inode_device = (0x6), /* char or block device */ > - gfs2_inode_fifo = (0x7), > - gfs2_inode_sock = (0x8), > - gfs2_inode_invalid = (0x9), > - > - /* misc block types: */ > - gfs2_jdata = (0xa), /* gfs journaled data blocks */ > - gfs2_meta_inval = (0xb), > - gfs2_leaf_blk = (0xc), > - gfs2_freemeta = (0xd), /* was: gfs2_meta_rgrp */ > - gfs2_meta_eattr = (0xe), > - > - gfs2_bad_block = (0xf), /* Contains at least one bad block */ > -}; > - > static const inline char *block_type_string(uint8_t q) > { > - const char *blktyp[] = { > - "free", > - "data", > - "indirect meta", > - "directory", > - "file", > - > - "symlink", > - "device", > - "fifo", > - "socket", > - "invalid inode", > - > - "journaled data", > - "invalid meta", > - "dir leaf", > - "free metadata", > - "eattribute", > - > - "bad"}; > - if (q < 16) > + const char *blktyp[] = {"free", "data", "other", "inode", "invalid"}; > + if (q <= GFS2_BLKST_DINODE) > return (blktyp[q]); > - return blktyp[15]; > -} > - > -/* Must be kept in sync with gfs2_mark_block enum above. Blocks marked as > - invalid or bad are considered metadata until actually freed. */ > -static inline int blockmap_to_bitmap(enum gfs2_mark_block m, int gfs1) > -{ > - static int bitmap_states[2][16] = { > - /* ---------------------- gfs2 ------------------------------*/ > - {GFS2_BLKST_FREE, /* free */ > - GFS2_BLKST_USED, /* data */ > - GFS2_BLKST_USED, /* indirect data or rgrp meta */ > - GFS2_BLKST_DINODE, /* directory */ > - GFS2_BLKST_DINODE, /* file */ > - > - GFS2_BLKST_DINODE, /* symlink */ > - GFS2_BLKST_DINODE, /* block or char device */ > - GFS2_BLKST_DINODE, /* fifo */ > - GFS2_BLKST_DINODE, /* socket */ > - GFS2_BLKST_FREE, /* invalid inode */ > - > - GFS2_BLKST_USED, /* journaled data */ > - GFS2_BLKST_FREE, /* invalid meta */ > - GFS2_BLKST_USED, /* dir leaf */ > - GFS2_BLKST_UNLINKED, /* GFS unlinked metadata */ > - GFS2_BLKST_USED, /* eattribute */ > - > - GFS2_BLKST_DINODE}, /* bad */ > - /* ---------------------- gfs1 ----------------------------- */ > - {GFS2_BLKST_FREE, /* free */ > - GFS2_BLKST_USED, /* data */ > - GFS2_BLKST_DINODE, /* indirect data or rgrp meta*/ > - GFS2_BLKST_DINODE, /* directory */ > - GFS2_BLKST_DINODE, /* file */ > - > - GFS2_BLKST_DINODE, /* symlink */ > - GFS2_BLKST_DINODE, /* block or char device */ > - GFS2_BLKST_DINODE, /* fifo */ > - GFS2_BLKST_DINODE, /* socket */ > - GFS2_BLKST_FREE, /* invalid inode */ > - > - GFS2_BLKST_DINODE, /* journaled data */ > - GFS2_BLKST_FREE, /* invalid meta */ > - GFS2_BLKST_DINODE, /* dir leaf */ > - GFS2_BLKST_UNLINKED, /* GFS unlinked metadata */ > - GFS2_BLKST_DINODE, /* eattribute */ > - > - GFS2_BLKST_DINODE}}; /* bad */ > - return bitmap_states[gfs1][m]; > + return blktyp[4]; > } > > static inline int is_dir(struct gfs2_dinode *dinode, int gfs1) > @@ -202,8 +110,7 @@ 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, > - enum gfs2_mark_block mark); > +extern int gfs2_blockmap_set(struct gfs2_bmap *il, uint64_t block, int mark); > extern int set_ip_blockmap(struct gfs2_inode *ip, int instree); > extern char generic_interrupt(const char *caller, const char *where, > const char *progress, const char *question, >