Merge branch 'maint' into next
diff --git a/misc/filefrag.c b/misc/filefrag.c
index 820821b..2ce1b9b 100644
--- a/misc/filefrag.c
+++ b/misc/filefrag.c
@@ -331,9 +331,10 @@
 			fm_ext.fe_physical = block * st->st_blksize;
 			fm_ext.fe_length = 0;
 			(*num_extents)++;
-		} else if (verbose && last_block && (block != last_block + 1)) {
-			printf("Discontinuity: Block %ld is at %lu (was %lu)\n",
-			       i, block, last_block + 1);
+		} else if (last_block && (block != last_block + 1)) {
+			if (verbose)
+				printf("Discontinuity: Block %ld is at %lu (was "
+				       "%lu)\n", i, block, last_block + 1);
 			(*num_extents)++;
 		}
 		fm_ext.fe_length += st->st_blksize;
@@ -350,6 +351,7 @@
 static int frag_report(const char *filename)
 {
 	static struct statfs fsinfo;
+	static unsigned int blksize;
 	ext2fs_struct_stat st;
 	int		blk_shift;
 	long		fd;
@@ -380,22 +382,22 @@
 #endif
 		rc = -errno;
 		perror("stat");
-		close(fd);
-		return rc;
+		goto out_close;
 	}
 
 	if (last_device != st.st_dev) {
 		if (fstatfs(fd, &fsinfo) < 0) {
 			rc = -errno;
 			perror("fstatfs");
-			close(fd);
-			return rc;
+			goto out_close;
 		}
+		if (ioctl(fd, FIGETBSZ, &blksize) < 0)
+			blksize = fsinfo.f_bsize;
 		if (verbose)
 			printf("Filesystem type is: %lx\n",
 			       (unsigned long)fsinfo.f_type);
 	}
-	st.st_blksize = fsinfo.f_bsize;
+	st.st_blksize = blksize;
 	if (ioctl(fd, EXT3_IOC_GETFLAGS, &flags) < 0)
 		flags = 0;
 	if (!(flags & EXT4_EXTENTS_FL) &&
@@ -404,13 +406,13 @@
 		is_ext2++;
 
 	if (is_ext2) {
-		long cylgroups = div_ceil(fsinfo.f_blocks, fsinfo.f_bsize * 8);
+		long cylgroups = div_ceil(fsinfo.f_blocks, blksize * 8);
 
 		if (verbose && last_device != st.st_dev)
 			printf("Filesystem cylinder groups approximately %ld\n",
 			       cylgroups);
 
-		data_blocks_per_cyl = fsinfo.f_bsize * 8 -
+		data_blocks_per_cyl = blksize * 8 -
 					(fsinfo.f_files / 8 / cylgroups) - 3;
 	}
 	last_device = st.st_dev;
@@ -419,11 +421,11 @@
 	if (width > physical_width)
 		physical_width = width;
 
-	numblocks = (st.st_size + fsinfo.f_bsize - 1) / fsinfo.f_bsize;
+	numblocks = (st.st_size + blksize - 1) / blksize;
 	if (blocksize != 0)
 		blk_shift = int_log2(blocksize);
 	else
-		blk_shift = int_log2(fsinfo.f_bsize);
+		blk_shift = int_log2(blksize);
 
 	width = int_log10(numblocks);
 	if (width > logical_width)
@@ -431,7 +433,7 @@
 	if (verbose)
 		printf("File size of %s is %llu (%llu block%s of %d bytes)\n",
 		       filename, (unsigned long long)st.st_size,
-		       numblocks * fsinfo.f_bsize >> blk_shift,
+		       numblocks * blksize >> blk_shift,
 		       numblocks == 1 ? "" : "s", 1 << blk_shift);
 
 	if (!force_bmap) {
@@ -439,7 +441,7 @@
 		expected = 0;
 	}
 
-	if (rc < 0) {
+	if (force_bmap || rc < 0) {
 		expected = filefrag_fibmap(fd, blk_shift, &num_extents,
 					   &st, numblocks, is_ext2);
 		if (expected < 0) {
diff --git a/tests/f_badcluster/expect b/tests/f_badcluster/expect
new file mode 100644
index 0000000..eb3bcf0
--- /dev/null
+++ b/tests/f_badcluster/expect
@@ -0,0 +1,198 @@
+Pass 1: Checking inodes, blocks, and sizes
+Inode 12 logical block 2 (physical block 1154) violates cluster allocation rules.
+Will fix in pass 1B.
+Inode 12, i_blocks is 32, should be 64.  Fix? yes
+
+Inode 16 logical block 5 (physical block 1173) violates cluster allocation rules.
+Will fix in pass 1B.
+Inode 16, i_size is 3072, should be 6144.  Fix? yes
+
+Inode 16, i_blocks is 32, should be 64.  Fix? yes
+
+Inode 17 logical block 0 (physical block 1186) violates cluster allocation rules.
+Will fix in pass 1B.
+Inode 17 logical block 2 (physical block 1184) violates cluster allocation rules.
+Will fix in pass 1B.
+Inode 17, i_blocks is 32, should be 64.  Fix? yes
+
+Inode 18 logical block 3 (physical block 1201) violates cluster allocation rules.
+Will fix in pass 1B.
+Inode 18, i_blocks is 32, should be 64.  Fix? yes
+
+
+Running additional passes to resolve blocks claimed by more than one inode...
+Pass 1B: Rescanning for multiply-claimed blocks
+Multiply-claimed block(s) in inode 12: 1154
+Multiply-claimed block(s) in inode 13: 1152--1154
+Multiply-claimed block(s) in inode 14: 1648--1650
+Multiply-claimed block(s) in inode 15: 1650
+Multiply-claimed block(s) in inode 16: 1173
+Multiply-claimed block(s) in inode 17: 1186 1185 1184
+Multiply-claimed block(s) in inode 18: 1201
+Pass 1C: Scanning directories for inodes with multiply-claimed blocks
+Pass 1D: Reconciling multiply-claimed blocks
+(There are 7 inodes containing multiply-claimed blocks.)
+
+File /a (inode #12, mod time Tue Jun 17 08:00:50 2014) 
+  has 1 multiply-claimed block(s), shared with 1 file(s):
+	/b (inode #13, mod time Tue Jun 17 08:00:50 2014)
+Clone multiply-claimed blocks? yes
+
+File /b (inode #13, mod time Tue Jun 17 08:00:50 2014) 
+  has 1 multiply-claimed block(s), shared with 1 file(s):
+	/a (inode #12, mod time Tue Jun 17 08:00:50 2014)
+Multiply-claimed blocks already reassigned or cloned.
+
+File /c (inode #14, mod time Tue Jun 17 08:00:50 2014) 
+  has 1 multiply-claimed block(s), shared with 1 file(s):
+	/d (inode #15, mod time Tue Jun 17 08:00:50 2014)
+Clone multiply-claimed blocks? yes
+
+File /d (inode #15, mod time Tue Jun 17 08:00:50 2014) 
+  has 1 multiply-claimed block(s), shared with 1 file(s):
+	/c (inode #14, mod time Tue Jun 17 08:00:50 2014)
+Multiply-claimed blocks already reassigned or cloned.
+
+File /e (inode #16, mod time Tue Jun 17 08:00:50 2014) 
+  has 1 multiply-claimed block(s), shared with 0 file(s):
+Clone multiply-claimed blocks? yes
+
+File /f (inode #17, mod time Tue Jun 17 08:00:50 2014) 
+  has 1 multiply-claimed block(s), shared with 0 file(s):
+Clone multiply-claimed blocks? yes
+
+File /g (inode #18, mod time Tue Jun 17 08:00:50 2014) 
+  has 1 multiply-claimed block(s), shared with 0 file(s):
+Clone multiply-claimed blocks? yes
+
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+Free blocks count wrong for group #0 (50, counted=47).
+Fix? yes
+
+Free blocks count wrong (800, counted=752).
+Fix? yes
+
+
+test_fs: ***** FILE SYSTEM WAS MODIFIED *****
+test_fs: 18/128 files (22.2% non-contiguous), 1296/2048 blocks
+Pass 1: Checking inodes, blocks, and sizes
+Inode 12, i_blocks is 64, should be 32.  Fix? yes
+
+Inode 16, i_blocks is 64, should be 32.  Fix? yes
+
+Inode 17, i_blocks is 64, should be 32.  Fix? yes
+
+Inode 18, i_blocks is 64, should be 32.  Fix? yes
+
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+Block bitmap differences:  -(1168--1200)
+Fix? yes
+
+Free blocks count wrong for group #0 (47, counted=50).
+Fix? yes
+
+Free blocks count wrong (752, counted=800).
+Fix? yes
+
+
+test_fs: ***** FILE SYSTEM WAS MODIFIED *****
+test_fs: 18/128 files (5.6% non-contiguous), 1248/2048 blocks
+Pass 1: Checking inodes, blocks, and sizes
+Pass 2: Checking directory structure
+Pass 3: Checking directory connectivity
+Pass 4: Checking reference counts
+Pass 5: Checking group summary information
+test_fs: 18/128 files (5.6% non-contiguous), 1248/2048 blocks
+debugfs:  stat /a
+Inode: 12   Type: regular    Mode:  0644   Flags: 0x80000
+Generation: 1117152157    Version: 0x00000001
+User:     0   Group:     0   Size: 3072
+File ACL: 0    Directory ACL: 0
+Links: 1   Blockcount: 32
+Fragment:  Address: 0    Number: 0    Size: 0
+ctime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014
+atime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014
+mtime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014
+EXTENTS:
+(0-1):1136-1137, (2):1138
+debugfs:  stat /b
+Inode: 13   Type: regular    Mode:  0644   Flags: 0x80000
+Generation: 1117152158    Version: 0x00000001
+User:     0   Group:     0   Size: 3072
+File ACL: 0    Directory ACL: 0
+Links: 1   Blockcount: 32
+Fragment:  Address: 0    Number: 0    Size: 0
+ctime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014
+atime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014
+mtime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014
+EXTENTS:
+(0-2):1152-1154
+debugfs:  stat /c
+Inode: 14   Type: regular    Mode:  0644   Flags: 0x80000
+Generation: 1117152159    Version: 0x00000001
+User:     0   Group:     0   Size: 3072
+File ACL: 0    Directory ACL: 0
+Links: 1   Blockcount: 32
+Fragment:  Address: 0    Number: 0    Size: 0
+ctime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014
+atime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014
+mtime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014
+EXTENTS:
+(0-1):1216-1217, (2):1218
+debugfs:  stat /d
+Inode: 15   Type: regular    Mode:  0644   Flags: 0x0
+Generation: 1117152160    Version: 0x00000001
+User:     0   Group:     0   Size: 3072
+File ACL: 0    Directory ACL: 0
+Links: 1   Blockcount: 32
+Fragment:  Address: 0    Number: 0    Size: 0
+ctime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014
+atime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014
+mtime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014
+BLOCKS:
+(TIND):1650
+TOTAL: 1
+
+debugfs:  stat /e
+Inode: 16   Type: regular    Mode:  0644   Flags: 0x80000
+Generation: 1117152161    Version: 0x00000001
+User:     0   Group:     0   Size: 6144
+File ACL: 0    Directory ACL: 0
+Links: 1   Blockcount: 32
+Fragment:  Address: 0    Number: 0    Size: 0
+ctime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014
+atime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014
+mtime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014
+EXTENTS:
+(0-2):1664-1666, (5):1669
+debugfs:  stat /f
+Inode: 17   Type: regular    Mode:  0644   Flags: 0x80000
+Generation: 1117152162    Version: 0x00000001
+User:     0   Group:     0   Size: 3072
+File ACL: 0    Directory ACL: 0
+Links: 1   Blockcount: 32
+Fragment:  Address: 0    Number: 0    Size: 0
+ctime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014
+atime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014
+mtime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014
+EXTENTS:
+(0):1232, (1):1233, (2):1234
+debugfs:  stat /g
+Inode: 18   Type: regular    Mode:  0644   Flags: 0x80000
+Generation: 1117152163    Version: 0x00000001
+User:     0   Group:     0   Size: 3072
+File ACL: 0    Directory ACL: 0
+Links: 1   Blockcount: 32
+Fragment:  Address: 0    Number: 0    Size: 0
+ctime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014
+atime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014
+mtime: 0x539ff5b2 -- Tue Jun 17 08:00:50 2014
+EXTENTS:
+(0-2):1680-1682, (3):1683
+debugfs:  
\ No newline at end of file
diff --git a/tests/f_badcluster/image.gz b/tests/f_badcluster/image.gz
new file mode 100644
index 0000000..3f21e98
--- /dev/null
+++ b/tests/f_badcluster/image.gz
Binary files differ
diff --git a/tests/f_badcluster/name b/tests/f_badcluster/name
new file mode 100644
index 0000000..266f81c
--- /dev/null
+++ b/tests/f_badcluster/name
@@ -0,0 +1,2 @@
+test alignment problems with bigalloc clusters
+
diff --git a/tests/f_badcluster/script b/tests/f_badcluster/script
new file mode 100644
index 0000000..74498a4
--- /dev/null
+++ b/tests/f_badcluster/script
@@ -0,0 +1,24 @@
+if test -x $DEBUGFS_EXE; then
+	IMAGE=$test_dir/../f_badcluster/image.gz
+	OUT=$test_name.log
+	EXP=$test_dir/expect
+	gzip -d < $IMAGE > $TMPFILE
+	$FSCK -fy $TMPFILE 2>&1 | sed -f $cmd_dir/filter.sed > $OUT
+	$FSCK -fy $TMPFILE 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT
+	$FSCK -fy $TMPFILE 2>&1 | sed -f $cmd_dir/filter.sed >> $OUT
+	for i in a b c d e f g; do echo "stat /$i"; done | $DEBUGFS_EXE $TMPFILE >> $OUT
+
+	cmp -s $OUT $EXP
+	status=$?
+
+	if [ "$status" = 0 ]; then
+		echo "$test_name: $test_description: ok"
+		touch $test_name.ok
+	else
+		echo "$test_name: $test_description: failed"
+		diff $DIFF_OPTS $EXP $OUT > $test_name.failed
+		rm -f $test_name.tmp
+	fi
+else
+	echo "$test_name: skipped"
+fi