gfs2-utils: RHEL7 - fsck.gfs2: Change block_map to match bitmap

Andrew Price andyp at fedoraproject.org
Tue Apr 7 21:23:59 UTC 2015


Gitweb:        http://git.fedorahosted.org/git/?p=gfs2-utils.git;a=commitdiff;h=5c82136b8b26b063542af8850c494cacb5c97c87
Commit:        5c82136b8b26b063542af8850c494cacb5c97c87
Parent:        6abfaa91f56f771c2ebaa6bc77d76503ac9bd899
Author:        Bob Peterson <rpeterso at redhat.com>
AuthorDate:    Fri Oct 17 11:28:20 2014 -0500
Committer:     Andrew Price <anprice at redhat.com>
CommitterDate: Wed Apr 1 16:51:35 2015 +0100

fsck.gfs2: Change block_map to match bitmap

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.
---
 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 adc87a4..b679459 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;
 }
 
@@ -2119,7 +2123,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,


More information about the cluster-commits mailing list