From: Andrew Price <anprice@redhat.com>
To: cluster-devel.redhat.com
Subject: [Cluster-devel] [fsck.gfs2 PATCH] fsck.gfs2: Change block_map to match bitmap
Date: Mon, 26 Jan 2015 10:56:41 +0000 [thread overview]
Message-ID: <54C61D69.4060306@redhat.com> (raw)
In-Reply-To: <651499900.13792931.1421959269755.JavaMail.zimbra@redhat.com>
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 <rpeterso@redhat.com>
> ---
> 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,
>
next prev parent reply other threads:[~2015-01-26 10:56 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <1442399810.13789822.1421959172642.JavaMail.zimbra@redhat.com>
2015-01-22 20:41 ` [Cluster-devel] [fsck.gfs2 PATCH] fsck.gfs2: Change block_map to match bitmap Bob Peterson
2015-01-26 10:56 ` Andrew Price [this message]
2015-01-26 13:59 ` Bob Peterson
2015-02-12 18:18 ` Bob Peterson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=54C61D69.4060306@redhat.com \
--to=anprice@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).