All of lore.kernel.org
 help / color / mirror / Atom feed
* [Cluster-devel] [fsck.gfs2 PATCH] fsck.gfs2: Change block_map to match bitmap
       [not found] <1442399810.13789822.1421959172642.JavaMail.zimbra@redhat.com>
@ 2015-01-22 20:41 ` Bob Peterson
  2015-01-26 10:56   ` Andrew Price
  0 siblings, 1 reply; 4+ messages in thread
From: Bob Peterson @ 2015-01-22 20:41 UTC (permalink / raw)
  To: cluster-devel.redhat.com

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.

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@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,



^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [Cluster-devel] [fsck.gfs2 PATCH] fsck.gfs2: Change block_map to match bitmap
  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
  2015-01-26 13:59     ` Bob Peterson
  0 siblings, 1 reply; 4+ messages in thread
From: Andrew Price @ 2015-01-26 10:56 UTC (permalink / raw)
  To: cluster-devel.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,
>



^ permalink raw reply	[flat|nested] 4+ messages in thread

* [Cluster-devel] [fsck.gfs2 PATCH] fsck.gfs2: Change block_map to match bitmap
  2015-01-26 10:56   ` Andrew Price
@ 2015-01-26 13:59     ` Bob Peterson
  2015-02-12 18:18       ` Bob Peterson
  0 siblings, 1 reply; 4+ messages in thread
From: Bob Peterson @ 2015-01-26 13:59 UTC (permalink / raw)
  To: cluster-devel.redhat.com

----- Original Message -----
> 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

Hi,

That's exactly where things get a bit sticky. It used to keep track of
the various GFS2_METATYPE_* block types. For the most part, dinodes were
straightforward because we only needed to distinguish between directories
and non-directories. Free space is pretty straightforward too, with only
a few corner cases where things were marked a "bad" type. Unlinked also
wasn't a big problem. The problem comes with blocks marked "Data."

In GFS1, "data" blocks were data blocks. In GFS2, a data block could be
data or metadata. In some cases we don't care because the height will
tell us if it's real data. But things get sticky when we need to
distinguish between different types of non-dinode metadata in fsck.
For example, what if a dinode has "indirect blocks" that are not
really indirect blocks, but say, an extended attribute block? The old
fsck could distinguish between them pretty easily because of their
unique types. Going by just the bitmap alone is ambiguous, so sometimes
we need to know more details, especially in cases where we have a block
that's referenced multiple times: it's much more likely that one of the
references is for the wrong type, and in that case, we do the extra
read. This shouldn't impact performance, except for duplicate references
(which is rare) and needs to be done.

There are probably cases where fsck is now making assumptions about the
previously processed block type for indirect blocks, so in that
respect, the information is lost. However, I've tried to minimize the
risk, and rigorous testing has shown that it works in many very difficult
situations. You can tell my testing has been good, since I've posted
so many bug fix patches recently that I've uncovered. :)

In that respect, this new fsck is better than the previous.

Still, there may very well be cases where the lost information causes
an unforeseen problem. I'm not sure we can do anything about that but
test it thoroughly.

Maybe I'll try to dummy up some potential problems (like the one I gave
above with indirect versus extended attribute) to see how well it does.
I suppose I could try to dummy up every permutation. That is likely to
uncover even more problems, most of which already exist in today's fsck.

Regards,

Bob Peterson
Red Hat File Systems



^ permalink raw reply	[flat|nested] 4+ messages in thread

* [Cluster-devel] [fsck.gfs2 PATCH] fsck.gfs2: Change block_map to match bitmap
  2015-01-26 13:59     ` Bob Peterson
@ 2015-02-12 18:18       ` Bob Peterson
  0 siblings, 0 replies; 4+ messages in thread
From: Bob Peterson @ 2015-02-12 18:18 UTC (permalink / raw)
  To: cluster-devel.redhat.com

----- Original Message -----
> ----- Original Message -----
> > 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
> 
> Hi,
> 
> That's exactly where things get a bit sticky. It used to keep track of
> the various GFS2_METATYPE_* block types. For the most part, dinodes were
> straightforward because we only needed to distinguish between directories
> and non-directories. Free space is pretty straightforward too, with only
> a few corner cases where things were marked a "bad" type. Unlinked also
> wasn't a big problem. The problem comes with blocks marked "Data."
> 
> In GFS1, "data" blocks were data blocks. In GFS2, a data block could be
> data or metadata. In some cases we don't care because the height will
> tell us if it's real data. But things get sticky when we need to
> distinguish between different types of non-dinode metadata in fsck.
> For example, what if a dinode has "indirect blocks" that are not
> really indirect blocks, but say, an extended attribute block? The old
> fsck could distinguish between them pretty easily because of their
> unique types. Going by just the bitmap alone is ambiguous, so sometimes
> we need to know more details, especially in cases where we have a block
> that's referenced multiple times: it's much more likely that one of the
> references is for the wrong type, and in that case, we do the extra
> read. This shouldn't impact performance, except for duplicate references
> (which is rare) and needs to be done.
> 
> There are probably cases where fsck is now making assumptions about the
> previously processed block type for indirect blocks, so in that
> respect, the information is lost. However, I've tried to minimize the
> risk, and rigorous testing has shown that it works in many very difficult
> situations. You can tell my testing has been good, since I've posted
> so many bug fix patches recently that I've uncovered. :)
> 
> In that respect, this new fsck is better than the previous.
> 
> Still, there may very well be cases where the lost information causes
> an unforeseen problem. I'm not sure we can do anything about that but
> test it thoroughly.
> 
> Maybe I'll try to dummy up some potential problems (like the one I gave
> above with indirect versus extended attribute) to see how well it does.
> I suppose I could try to dummy up every permutation. That is likely to
> uncover even more problems, most of which already exist in today's fsck.
> 
> Regards,
> 
> Bob Peterson
> Red Hat File Systems

Hi,

As promised, I dummied up some file systems to intentionally have the wrong
metadata block types. I tried these scenarios:

1. File that had an extended attribute block that was really an indirect block.
2. File that had an indirect block that was really an extended attribute block.
3. Directory that had an extended attribute block that was really a leaf block.
4. Directory that had a leaf block that was really an extended attribute block.
5. File that had an extended attribute block that was really an "ED" block.
6. File whose indirect pointer points to a leaf block
7. Directory whose leaf block pointers all point to an indirect block

In all these scenarios, the fsck.gfs2 with my patch made the same decisions
and produced relatively the same output as the stock fsck.gfs2. So I think
it's safe to push this patch now, unless anyone has an objection or has
specific tests they'd like me to try.

Regards,

Bob Peterson
Red Hat File Systems



^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2015-02-12 18:18 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [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
2015-01-26 13:59     ` Bob Peterson
2015-02-12 18:18       ` Bob Peterson

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.