lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Message-ID: <20081003000237.GF28293@shell>
Date:	Thu, 2 Oct 2008 20:02:37 -0400
From:	Valerie Aurora Henson <vaurora@...hat.com>
To:	linux-ext4@...r.kernel.org
Cc:	Theodore Tso <tytso@....edu>, "Jose R. Santos" <jrs@...ibm.com>
Subject: [RFC,PATCH] 64-bit bitmaps for e2fsprogs

Hi all,

I've been working on 64-bit bitmaps for e2fsprogs, which will allow us
to create an ext4 file system with more than 2^32 blocks.  Below is a
snapshot of my development tree as-is (doesn't even compile); I'd
appreciate comments on the direction, especially from Ted and Jose.

Some background: Ted's goal is to preserve the ABI for programs
dynamically linked against libext2.  This is implemented by preserving
the existing 32-bit bitmap interfaces as-is and implementing a new set
of 64-bit interfaces which detect whether the application has been
recompiled since the new 64-bit support went in.  If so, it uses the
new functions, otherwise it passes the arguments back to the old
functions.

The diff includes three patches: implementation of 64-bit bmap ops,
warning squashing (so I can concentrate on my warnings), and a partial
port to the new 64-bit interfaces.  I can split them out if necessary.
Diff is against commit 6db77ec039ff241dab0f1e267fabcfa814fbaf4c in the
pu branch.

-VAL

diff --git a/debugfs/debugfs.c b/debugfs/debugfs.c
index 8b0965e..d1c6460 100644
--- a/debugfs/debugfs.c
+++ b/debugfs/debugfs.c
@@ -1850,7 +1850,7 @@ static int find_supp_feature(__u32 *supp, int feature_type, char *name)
 
 void do_supported_features(int argc, char *argv[])
 {
-        int	i, j, ret;
+        int	ret;
 	__u32	supp[3] = { EXT2_LIB_FEATURE_COMPAT_SUPP,
 			    EXT2_LIB_FEATURE_INCOMPAT_SUPP,
 			    EXT2_LIB_FEATURE_RO_COMPAT_SUPP };
diff --git a/debugfs/htree.c b/debugfs/htree.c
index 983dc9a..f9332ab 100644
--- a/debugfs/htree.c
+++ b/debugfs/htree.c
@@ -48,11 +48,11 @@ static void htree_dump_leaf_node(ext2_filsys fs, ext2_ino_t ino,
 		return;
 	}
 
-	printf("Reading directory block %lu, phys %lu\n", blk, pblk);
+	printf("Reading directory block %u, phys %u\n", blk, pblk);
 	errcode = ext2fs_read_dir_block2(current_fs, pblk, buf, 0);
 	if (errcode) {
 		com_err("htree_dump_leaf_node", errcode,
-			"while reading block %lu (%lu)\n", blk, pblk);
+			"while reading block %u (%u)\n", blk, pblk);
 		return;
 	}
 	hash_alg = rootnode->hash_version;
diff --git a/lib/blkid/probe.c b/lib/blkid/probe.c
index 10ac803..4bdc62a 100644
--- a/lib/blkid/probe.c
+++ b/lib/blkid/probe.c
@@ -1099,7 +1099,8 @@ static int probe_hfs(struct blkid_probe *probe __BLKID_ATTR((unused)),
 		sprintf(uuid_str, "%016llX", uuid);
 		blkid_set_tag(probe->dev, "UUID", uuid_str, 0);
 	}
-	blkid_set_tag(probe->dev, "LABEL", hfs->label, hfs->label_len);
+	blkid_set_tag(probe->dev, "LABEL", (char *) hfs->label,
+		      hfs->label_len);
 	return 0;
 }
 
@@ -1220,7 +1221,7 @@ static int probe_hfsplus(struct blkid_probe *probe,
 		return 0;
 
 	label_len = blkid_be16(key->unicode_len) * 2;
-	unicode_16be_to_utf8(label, sizeof(label), key->unicode, label_len);
+	unicode_16be_to_utf8((unsigned char *) label, sizeof(label), key->unicode, label_len);
 	blkid_set_tag(probe->dev, "LABEL", label, 0);
 	return 0;
 }
diff --git a/lib/e2p/e2p.h b/lib/e2p/e2p.h
index 98c97db..d5d10a5 100644
--- a/lib/e2p/e2p.h
+++ b/lib/e2p/e2p.h
@@ -38,6 +38,8 @@ int setversion (int fd, unsigned long version);
 
 const char *e2p_feature2string(int compat, unsigned int mask);
 int e2p_string2feature(char *string, int *compat, unsigned int *mask);
+const char *e2p_jrnl_feature2string(int compat, unsigned int mask);
+int e2p_jrnl_string2feature(char *string, int *compat_type, unsigned int *mask);
 int e2p_edit_feature(const char *str, __u32 *compat_array, __u32 *ok_array);
 int e2p_edit_feature2(const char *str, __u32 *compat_array, __u32 *ok_array,
 		      __u32 *clear_ok_array, int *type_err,
diff --git a/lib/ext2fs/alloc.c b/lib/ext2fs/alloc.c
index 696f27e..fe4fdb4 100644
--- a/lib/ext2fs/alloc.c
+++ b/lib/ext2fs/alloc.c
@@ -29,8 +29,8 @@
 /*
  * Check for uninit block bitmaps and deal with them appropriately
  */
-static check_block_uninit(ext2_filsys fs, ext2fs_block_bitmap map,
-			  dgrp_t group)
+static void check_block_uninit(ext2_filsys fs, ext2fs_block_bitmap map,
+			       dgrp_t group)
 {
 	int		i;
 	blk_t		blk, super_blk, old_desc_blk, new_desc_blk;
@@ -75,7 +75,7 @@ static check_block_uninit(ext2_filsys fs, ext2fs_block_bitmap map,
 /*
  * Check for uninit inode bitmaps and deal with them appropriately
  */
-static check_inode_uninit(ext2_filsys fs, ext2fs_inode_bitmap map,
+static void check_inode_uninit(ext2_filsys fs, ext2fs_inode_bitmap map,
 			  dgrp_t group)
 {
 	int		i;
diff --git a/lib/ext2fs/bitmaps.c b/lib/ext2fs/bitmaps.c
index ea08b3e..47cf9eb 100644
--- a/lib/ext2fs/bitmaps.c
+++ b/lib/ext2fs/bitmaps.c
@@ -26,108 +26,145 @@
 
 #include "ext2_fs.h"
 #include "ext2fs.h"
+#include "ext2fsP.h"
 
 void ext2fs_free_inode_bitmap(ext2fs_inode_bitmap bitmap)
 {
-	ext2fs_free_generic_bitmap(bitmap);
+	ext2fs_free_generic_bmap(bitmap);
 }
 
 void ext2fs_free_block_bitmap(ext2fs_block_bitmap bitmap)
 {
-	ext2fs_free_generic_bitmap(bitmap);
+	ext2fs_free_generic_bmap(bitmap);
 }
 
-errcode_t ext2fs_copy_bitmap(ext2fs_generic_bitmap src,
-			     ext2fs_generic_bitmap *dest)
+errcode_t ext2fs_copy_bitmap(ext2fs_generic_bitmap64 src,
+			     ext2fs_generic_bitmap64 *dest)
 {
-	return (ext2fs_copy_generic_bitmap(src, dest));
+	return (ext2fs_copy_generic_bmap((ext2fs_generic_bitmap64) src,
+					 (ext2fs_generic_bitmap64 *) dest));
 }
-
 void ext2fs_set_bitmap_padding(ext2fs_generic_bitmap map)
 {
-	ext2fs_set_generic_bitmap_padding(map);
+	ext2fs_set_generic_bmap_padding((ext2fs_generic_bitmap64) map);
+}
+
+void ext2fs_set_bmap_padding(ext2fs_generic_bitmap64 map)
+{
+	ext2fs_set_generic_bmap_padding(map);
 }
 
 errcode_t ext2fs_allocate_inode_bitmap(ext2_filsys fs,
 				       const char *descr,
 				       ext2fs_inode_bitmap *ret)
 {
-	__u32		start, end, real_end;
+	__u64		start, end, real_end;
 
 	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
 
 	fs->write_bitmaps = ext2fs_write_bitmaps;
 
 	start = 1;
-	end = fs->super->s_inodes_count;
+	end = ext2fs_blocks_count(fs->super)-1;
 	real_end = (EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count);
 
+	/* Are we permitted to use new-style bitmaps? */
+	if (fs->flags & EXT2_FLAG_NEW_BITMAPS)
+		return (ext2fs_alloc_generic_bmap(fs,
+				  EXT2_ET_MAGIC_INODE_BITMAP64,
+				  EXT2FS_BMAP64_BITARRAY,
+				  start, end, real_end, descr, ret));
+
+	/* Otherwise, check to see if the file system is small enough
+	 * to use old-style 32-bit bitmaps */
+	if ((end > ~0U) || (real_end > ~0U))
+		return EXT2_ET_FILE_TOO_BIG; /* XXX better error code */
+
 	return (ext2fs_make_generic_bitmap(EXT2_ET_MAGIC_INODE_BITMAP, fs,
 					   start, end, real_end,
-					   descr, 0, ret));
+					   descr, 0,
+					   (ext2fs_generic_bitmap *) ret));
 }
 
 errcode_t ext2fs_allocate_block_bitmap(ext2_filsys fs,
 				       const char *descr,
 				       ext2fs_block_bitmap *ret)
 {
-	__u32		start, end, real_end;
+	__u64		start, end, real_end;
 
 	EXT2_CHECK_MAGIC(fs, EXT2_ET_MAGIC_EXT2FS_FILSYS);
 
 	fs->write_bitmaps = ext2fs_write_bitmaps;
 
 	start = fs->super->s_first_data_block;
-	end = fs->super->s_blocks_count-1;
+	end = ext2fs_blocks_count(fs->super)-1;
 	real_end = (EXT2_BLOCKS_PER_GROUP(fs->super)
 		    * fs->group_desc_count)-1 + start;
 
+	if (fs->flags & EXT2_FLAG_NEW_BITMAPS)
+		return (ext2fs_alloc_generic_bmap(fs,
+				  EXT2_ET_MAGIC_BLOCK_BITMAP64,
+				  EXT2FS_BMAP64_BITARRAY,
+				  start, end, real_end, descr, ret));
+
+	if ((end > ~0U) || (real_end > ~0U))
+		return EXT2_ET_FILE_TOO_BIG; /* XXX better error code */
+
 	return (ext2fs_make_generic_bitmap(EXT2_ET_MAGIC_BLOCK_BITMAP, fs,
 					   start, end, real_end,
-					   descr, 0, ret));
+					   descr, 0,
+					   (ext2fs_generic_bitmap *) ret));
 }
 
 errcode_t ext2fs_fudge_inode_bitmap_end(ext2fs_inode_bitmap bitmap,
 					ext2_ino_t end, ext2_ino_t *oend)
 {
 
-	return (ext2fs_fudge_generic_bitmap_end(bitmap,
-						EXT2_ET_MAGIC_INODE_BITMAP,
-						EXT2_ET_FUDGE_INODE_BITMAP_END,
-						end, oend));
+	return (ext2fs_fudge_generic_bmap_end(bitmap,
+					      EXT2_ET_FUDGE_INODE_BITMAP_END,
+					      end, oend));
 }
 
 errcode_t ext2fs_fudge_block_bitmap_end(ext2fs_block_bitmap bitmap,
 					blk_t end, blk_t *oend)
 {
-	return (ext2fs_fudge_generic_bitmap_end(bitmap,
-						EXT2_ET_MAGIC_BLOCK_BITMAP,
-						EXT2_ET_FUDGE_BLOCK_BITMAP_END,
-						end, oend));
+	return (ext2fs_fudge_generic_bmap_end(bitmap,
+					      EXT2_ET_FUDGE_BLOCK_BITMAP_END,
+					      end, oend));
 }
 
 void ext2fs_clear_inode_bitmap(ext2fs_inode_bitmap bitmap)
 {
-	ext2fs_clear_generic_bitmap(bitmap);
+	ext2fs_clear_generic_bmap(bitmap);
 }
 
 void ext2fs_clear_block_bitmap(ext2fs_block_bitmap bitmap)
 {
-	ext2fs_clear_generic_bitmap(bitmap);
+	ext2fs_clear_generic_bmap(bitmap);
 }
 
 errcode_t ext2fs_resize_inode_bitmap(__u32 new_end, __u32 new_real_end,
 				     ext2fs_inode_bitmap bmap)
 {
-	return (ext2fs_resize_generic_bitmap(EXT2_ET_MAGIC_INODE_BITMAP,
-					     new_end, new_real_end, bmap));
+	return (ext2fs_resize_generic_bmap(new_end, new_real_end, bmap));
 }
 
 errcode_t ext2fs_resize_block_bitmap(__u32 new_end, __u32 new_real_end,
 				     ext2fs_block_bitmap bmap)
 {
-	return (ext2fs_resize_generic_bitmap(EXT2_ET_MAGIC_BLOCK_BITMAP,
-					     new_end, new_real_end, bmap));
+	return (ext2fs_resize_generic_bmap(new_end, new_real_end, bmap));
+}
+
+errcode_t ext2fs_resize_inode_bitmap2(__u64 new_end, __u64 new_real_end,
+				      ext2fs_inode_bitmap bmap)
+{
+	return (ext2fs_resize_generic_bmap(new_end, new_real_end, bmap));
+}
+
+errcode_t ext2fs_resize_block_bitmap2(__u64 new_end, __u64 new_real_end,
+				     ext2fs_block_bitmap bmap)
+{
+	return (ext2fs_resize_generic_bmap(new_end, new_real_end, bmap));
 }
 
 errcode_t ext2fs_compare_block_bitmap(ext2fs_block_bitmap bm1,
@@ -150,34 +187,26 @@ errcode_t ext2fs_set_inode_bitmap_range(ext2fs_inode_bitmap bmap,
 					ext2_ino_t start, unsigned int num,
 					void *in)
 {
-	return (ext2fs_set_generic_bitmap_range(bmap,
-						EXT2_ET_MAGIC_INODE_BITMAP,
-						start, num, in));
+	return (ext2fs_set_generic_bmap_range(bmap, start, num, in));
 }
 
 errcode_t ext2fs_get_inode_bitmap_range(ext2fs_inode_bitmap bmap,
 					ext2_ino_t start, unsigned int num,
 					void *out)
 {
-	return (ext2fs_get_generic_bitmap_range(bmap,
-						EXT2_ET_MAGIC_INODE_BITMAP,
-						start, num, out));
+	return (ext2fs_get_generic_bmap_range(bmap, start, num, out));
 }
 
 errcode_t ext2fs_set_block_bitmap_range(ext2fs_block_bitmap bmap,
 					blk_t start, unsigned int num,
 					void *in)
 {
-	return (ext2fs_set_generic_bitmap_range(bmap,
-						EXT2_ET_MAGIC_BLOCK_BITMAP,
-						start, num, in));
+	return (ext2fs_set_generic_bmap_range(bmap, start, num, in));
 }
 
 errcode_t ext2fs_get_block_bitmap_range(ext2fs_block_bitmap bmap,
 					blk_t start, unsigned int num,
 					void *out)
 {
-	return (ext2fs_get_generic_bitmap_range(bmap,
-						EXT2_ET_MAGIC_BLOCK_BITMAP,
-						start, num, out));
+	return (ext2fs_get_generic_bmap_range(bmap, start, num, out));
 }
diff --git a/lib/ext2fs/bitops.c b/lib/ext2fs/bitops.c
index 485e997..a1cc78f 100644
--- a/lib/ext2fs/bitops.c
+++ b/lib/ext2fs/bitops.c
@@ -76,3 +76,43 @@ void ext2fs_warn_bitmap(errcode_t errcode, unsigned long arg,
 		com_err(0, errcode, "#%lu", arg);
 #endif
 }
+
+/*
+ * C-only 64 bit ops.  These are compiled and partially tested for
+ * 32-bit binaries, but will not work for bit numbers > 32 bits.
+ */
+
+int ext2fs_set_bit64(__u64 nr, void * addr)
+{
+	int		mask, retval;
+	unsigned char	*ADDR = (unsigned char *) addr;
+
+	ADDR += nr >> 3;
+	mask = 1 << (nr & 0x07);
+	retval = mask & *ADDR;
+	*ADDR |= mask;
+	return retval;
+}
+
+int ext2fs_clear_bit64(__u64 nr, void * addr)
+{
+	int		mask, retval;
+	unsigned char	*ADDR = (unsigned char *) addr;
+
+	ADDR += nr >> 3;
+	mask = 1 << (nr & 0x07);
+	retval = mask & *ADDR;
+	*ADDR &= ~mask;
+	return retval;
+}
+
+int ext2fs_test_bit64(__u64 nr, const void * addr)
+{
+	int			mask;
+	const unsigned char	*ADDR = (const unsigned char *) addr;
+
+	ADDR += nr >> 3;
+	mask = 1 << (nr & 0x07);
+	return (mask & *ADDR);
+}
+
diff --git a/lib/ext2fs/bitops.h b/lib/ext2fs/bitops.h
index 82ca138..920ab92 100644
--- a/lib/ext2fs/bitops.h
+++ b/lib/ext2fs/bitops.h
@@ -19,6 +19,11 @@ extern int ext2fs_clear_bit(unsigned int nr, void * addr);
 extern int ext2fs_test_bit(unsigned int nr, const void * addr);
 extern void ext2fs_fast_set_bit(unsigned int nr,void * addr);
 extern void ext2fs_fast_clear_bit(unsigned int nr, void * addr);
+extern int ext2fs_set_bit64(__u64 nr,void * addr);
+extern int ext2fs_clear_bit64(__u64 nr, void * addr);
+extern int ext2fs_test_bit64(__u64 nr, const void * addr);
+extern void ext2fs_fast_set_bit64(__u64 nr,void * addr);
+extern void ext2fs_fast_clear_bit64(__u64 nr, void * addr);
 extern __u16 ext2fs_swab16(__u16 val);
 extern __u32 ext2fs_swab32(__u32 val);
 extern __u64 ext2fs_swab64(__u64 val);
@@ -62,22 +67,24 @@ extern void ext2fs_warn_bitmap(errcode_t errcode, unsigned long arg,
 extern void ext2fs_warn_bitmap2(ext2fs_generic_bitmap bitmap,
 				int code, unsigned long arg);
 
-extern int ext2fs_mark_block_bitmap(ext2fs_block_bitmap bitmap, blk_t block);
+extern int ext2fs_mark_block_bitmap(ext2fs_block_bitmap bitmap, blk64_t block);
 extern int ext2fs_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
-				       blk_t block);
-extern int ext2fs_test_block_bitmap(ext2fs_block_bitmap bitmap, blk_t block);
+				      blk64_t block);
+extern int ext2fs_test_block_bitmap(ext2fs_block_bitmap bitmap, blk64_t block);
 
-extern int ext2fs_mark_inode_bitmap(ext2fs_inode_bitmap bitmap, ext2_ino_t inode);
+extern int ext2fs_mark_inode_bitmap(ext2fs_inode_bitmap bitmap,
+				    ext2_ino_t inode);
 extern int ext2fs_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
-				       ext2_ino_t inode);
-extern int ext2fs_test_inode_bitmap(ext2fs_inode_bitmap bitmap, ext2_ino_t inode);
+				      ext2_ino_t inode);
+extern int ext2fs_test_inode_bitmap(ext2fs_inode_bitmap bitmap,
+				    ext2_ino_t inode);
 
 extern void ext2fs_fast_mark_block_bitmap(ext2fs_block_bitmap bitmap,
-					  blk_t block);
+					  blk64_t block);
 extern void ext2fs_fast_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
-					    blk_t block);
+					    blk64_t block);
 extern int ext2fs_fast_test_block_bitmap(ext2fs_block_bitmap bitmap,
-					 blk_t block);
+					 blk64_t block);
 
 extern void ext2fs_fast_mark_inode_bitmap(ext2fs_inode_bitmap bitmap,
 					  ext2_ino_t inode);
@@ -85,36 +92,37 @@ extern void ext2fs_fast_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
 					    ext2_ino_t inode);
 extern int ext2fs_fast_test_inode_bitmap(ext2fs_inode_bitmap bitmap,
 					 ext2_ino_t inode);
-extern blk_t ext2fs_get_block_bitmap_start(ext2fs_block_bitmap bitmap);
+extern blk64_t ext2fs_get_block_bitmap_start(ext2fs_block_bitmap bitmap);
 extern ext2_ino_t ext2fs_get_inode_bitmap_start(ext2fs_inode_bitmap bitmap);
-extern blk_t ext2fs_get_block_bitmap_end(ext2fs_block_bitmap bitmap);
+extern blk64_t ext2fs_get_block_bitmap_end(ext2fs_block_bitmap bitmap);
 extern ext2_ino_t ext2fs_get_inode_bitmap_end(ext2fs_inode_bitmap bitmap);
 
 extern void ext2fs_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
-					   blk_t block, int num);
+					   blk64_t block, int num);
 extern void ext2fs_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
-					     blk_t block, int num);
+					     blk64_t block, int num);
 extern int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
-					  blk_t block, int num);
+					  blk64_t block, int num);
 extern void ext2fs_fast_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
-						blk_t block, int num);
+						blk64_t block, int num);
 extern void ext2fs_fast_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
-						  blk_t block, int num);
+						  blk64_t block, int num);
 extern int ext2fs_fast_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
-					       blk_t block, int num);
+					       blk64_t block, int num);
 extern void ext2fs_set_bitmap_padding(ext2fs_generic_bitmap map);
-
-/* These routines moved to gen_bitmap.c */
-extern int ext2fs_mark_generic_bitmap(ext2fs_generic_bitmap bitmap,
-					 __u32 bitno);
-extern int ext2fs_unmark_generic_bitmap(ext2fs_generic_bitmap bitmap,
-					   blk_t bitno);
-extern int ext2fs_test_generic_bitmap(ext2fs_generic_bitmap bitmap,
-				      blk_t bitno);
+extern void ext2fs_set_bmap_padding(ext2fs_generic_bitmap64 map);
+
+/* These routines moved to gen_bitmap64.c */
+extern int ext2fs_mark_generic_bmap(ext2fs_generic_bitmap64 bitmap,
+				    __u64 bitno);
+extern int ext2fs_unmark_generic_bmap(ext2fs_generic_bitmap64 bitmap,
+				      blk64_t bitno);
+extern int ext2fs_test_generic_bmap(ext2fs_generic_bitmap64 bitmap,
+				    blk64_t bitno);
 extern int ext2fs_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
-					  blk_t block, int num);
-extern __u32 ext2fs_get_generic_bitmap_start(ext2fs_generic_bitmap bitmap);
-extern __u32 ext2fs_get_generic_bitmap_end(ext2fs_generic_bitmap bitmap);
+					  blk64_t block, int num);
+extern __u32 ext2fs_get_generic_bmap_start(ext2fs_generic_bitmap64 bitmap);
+extern __u32 ext2fs_get_generic_bmap_end(ext2fs_generic_bitmap64 bitmap);
 
 /*
  * The inline routines themselves...
@@ -165,6 +173,23 @@ _INLINE_ void ext2fs_fast_clear_bit(unsigned int nr, void * addr)
 }
 
 
+_INLINE_ void ext2fs_fast_set_bit64(__u64 nr, void * addr)
+{
+	unsigned char	*ADDR = (unsigned char *) addr;
+
+	ADDR += nr >> 3;
+	*ADDR |= (1 << (nr & 0x07));
+}
+
+_INLINE_ void ext2fs_fast_clear_bit64(__u64 nr, void * addr)
+{
+	unsigned char	*ADDR = (unsigned char *) addr;
+
+	ADDR += nr >> 3;
+	*ADDR &= ~(1 << (nr & 0x07));
+}
+
+
 #if ((defined __GNUC__) && !defined(_EXT2_USE_C_VERSIONS_) && \
      (defined(__i386__) || defined(__i486__) || defined(__i586__)))
 
@@ -408,119 +433,119 @@ _INLINE_ int ext2fs_find_next_bit_set (void * addr, int size, int offset)
 #endif
 
 _INLINE_ int ext2fs_mark_block_bitmap(ext2fs_block_bitmap bitmap,
-				       blk_t block)
+				      blk64_t block)
 {
-	return ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap) bitmap,
-					  block);
+	return ext2fs_mark_generic_bmap((ext2fs_generic_bitmap64) bitmap,
+					block);
 }
 
 _INLINE_ int ext2fs_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
-					 blk_t block)
+					blk64_t block)
 {
-	return ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap,
-					    block);
+	return ext2fs_unmark_generic_bmap((ext2fs_generic_bitmap64) bitmap,
+					  block);
 }
 
 _INLINE_ int ext2fs_test_block_bitmap(ext2fs_block_bitmap bitmap,
-				       blk_t block)
+				      blk64_t block)
 {
-	return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap,
-					  block);
+	return ext2fs_test_generic_bmap((ext2fs_generic_bitmap64) bitmap,
+					block);
 }
 
 _INLINE_ int ext2fs_mark_inode_bitmap(ext2fs_inode_bitmap bitmap,
-				       ext2_ino_t inode)
+				      ext2_ino_t inode)
 {
-	return ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap) bitmap,
-					  inode);
+	return ext2fs_mark_generic_bmap((ext2fs_generic_bitmap64) bitmap,
+					inode);
 }
 
 _INLINE_ int ext2fs_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
-					 ext2_ino_t inode)
+					ext2_ino_t inode)
 {
-	return ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap,
-				     inode);
+	return ext2fs_unmark_generic_bmap((ext2fs_generic_bitmap64) bitmap,
+					  inode);
 }
 
 _INLINE_ int ext2fs_test_inode_bitmap(ext2fs_inode_bitmap bitmap,
-				       ext2_ino_t inode)
+				      ext2_ino_t inode)
 {
-	return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap,
-					  inode);
+	return ext2fs_test_generic_bmap((ext2fs_generic_bitmap64) bitmap,
+					inode);
 }
 
 _INLINE_ void ext2fs_fast_mark_block_bitmap(ext2fs_block_bitmap bitmap,
-					    blk_t block)
+					    blk64_t block)
 {
-	ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap) bitmap, block);
+	ext2fs_mark_generic_bmap((ext2fs_generic_bitmap64) bitmap, block);
 }
 
 _INLINE_ void ext2fs_fast_unmark_block_bitmap(ext2fs_block_bitmap bitmap,
-					      blk_t block)
+					      blk64_t block)
 {
-	ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap, block);
+	ext2fs_unmark_generic_bmap((ext2fs_generic_bitmap64) bitmap, block);
 }
 
 _INLINE_ int ext2fs_fast_test_block_bitmap(ext2fs_block_bitmap bitmap,
-					    blk_t block)
+					   blk64_t block)
 {
-	return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap,
+	return ext2fs_test_generic_bmap((ext2fs_generic_bitmap64) bitmap,
 					  block);
 }
 
 _INLINE_ void ext2fs_fast_mark_inode_bitmap(ext2fs_inode_bitmap bitmap,
 					    ext2_ino_t inode)
 {
-	ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap) bitmap, inode);
+	ext2fs_mark_generic_bmap((ext2fs_generic_bitmap64) bitmap, inode);
 }
 
 _INLINE_ void ext2fs_fast_unmark_inode_bitmap(ext2fs_inode_bitmap bitmap,
 					      ext2_ino_t inode)
 {
-	ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap) bitmap, inode);
+	ext2fs_unmark_generic_bmap((ext2fs_generic_bitmap64) bitmap, inode);
 }
 
 _INLINE_ int ext2fs_fast_test_inode_bitmap(ext2fs_inode_bitmap bitmap,
 					   ext2_ino_t inode)
 {
-	return ext2fs_test_generic_bitmap((ext2fs_generic_bitmap) bitmap,
+	return ext2fs_test_generic_bmap((ext2fs_generic_bitmap64) bitmap,
 					  inode);
 }
 
-_INLINE_ blk_t ext2fs_get_block_bitmap_start(ext2fs_block_bitmap bitmap)
+_INLINE_ blk64_t ext2fs_get_block_bitmap_start(ext2fs_block_bitmap bitmap)
 {
-	return ext2fs_get_generic_bitmap_start((ext2fs_generic_bitmap) bitmap);
+	return ext2fs_get_generic_bmap_start((ext2fs_generic_bitmap64) bitmap);
 }
 
 _INLINE_ ext2_ino_t ext2fs_get_inode_bitmap_start(ext2fs_inode_bitmap bitmap)
 {
-	return ext2fs_get_generic_bitmap_start((ext2fs_generic_bitmap) bitmap);
+	return ext2fs_get_generic_bmap_start((ext2fs_generic_bitmap64) bitmap);
 }
 
-_INLINE_ blk_t ext2fs_get_block_bitmap_end(ext2fs_block_bitmap bitmap)
+_INLINE_ blk64_t ext2fs_get_block_bitmap_end(ext2fs_block_bitmap bitmap)
 {
-	return ext2fs_get_generic_bitmap_end((ext2fs_generic_bitmap) bitmap);
+	return ext2fs_get_generic_bmap_end((ext2fs_generic_bitmap64) bitmap);
 }
 
 _INLINE_ ext2_ino_t ext2fs_get_inode_bitmap_end(ext2fs_inode_bitmap bitmap)
 {
-	return ext2fs_get_generic_bitmap_end((ext2fs_generic_bitmap) bitmap);
+	return ext2fs_get_generic_bmap_end((ext2fs_generic_bitmap64) bitmap);
 }
 
 _INLINE_ int ext2fs_fast_test_block_bitmap_range(ext2fs_block_bitmap bitmap,
-						 blk_t block, int num)
+						 blk64_t block, int num)
 {
 	return ext2fs_test_block_bitmap_range(bitmap, block, num);
 }
 
 _INLINE_ void ext2fs_fast_mark_block_bitmap_range(ext2fs_block_bitmap bitmap,
-						  blk_t block, int num)
+						  blk64_t block, int num)
 {
 	ext2fs_mark_block_bitmap_range(bitmap, block, num);
 }
 
 _INLINE_ void ext2fs_fast_unmark_block_bitmap_range(ext2fs_block_bitmap bitmap,
-						    blk_t block, int num)
+						    blk64_t block, int num)
 {
 	ext2fs_unmark_block_bitmap_range(bitmap, block, num);
 }
diff --git a/lib/ext2fs/blkmap64_ba.c b/lib/ext2fs/blkmap64_ba.c
index 855a160..2e28a83 100644
--- a/lib/ext2fs/blkmap64_ba.c
+++ b/lib/ext2fs/blkmap64_ba.c
@@ -26,54 +26,203 @@
 #include "ext2_fs.h"
 #include "ext2fsP.h"
 
-static errcode_t ba_new_bmap(ext2_filsys fs, ext2fs_generic_bitmap64 *bmap)
+/*
+ * Private data for bit array implementation of bitmap ops.
+ * Currently, this is just a pointer to our big flat hunk of memory,
+ * exactly equivalent to the old-skool char * bitmap member.
+ */
+
+struct ext2fs_ba_private_struct {
+	char *bitarray;
+};
+
+typedef struct ext2fs_ba_private_struct *ext2fs_ba_private;
+
+static errcode_t ba_alloc_private_data (ext2fs_generic_bitmap64 bitmap)
 {
+	ext2fs_ba_private bp;
+	errcode_t	retval;
+	size_t		size;
+
+	/*
+	 * Since we only have the one pointer, we could just shove our
+	 * private data in the void *private field itself, but then
+	 * we'd have to do a fair bit of rewriting if we ever added a
+	 * field.  I'm agnostic.
+	 */
+	retval = ext2fs_get_mem(sizeof (ext2fs_ba_private), &bp);
+	if (retval)
+		return retval;
+
+	size = (size_t) (((bitmap->real_end - bitmap->start) / 8) + 1);
+
+	retval = ext2fs_get_mem(size, &bp->bitarray);
+	if (retval) {
+		ext2fs_free_mem(&bp);
+		bp = 0;
+		return retval;
+	}
+	bitmap->private = (void *) bp;
+	return 0;
+}
+
+static errcode_t ba_new_bmap(ext2_filsys fs, ext2fs_generic_bitmap64 bitmap)
+{
+	ext2fs_ba_private bp;
+	errcode_t	retval;
+	size_t		size;
+
+	retval = ba_alloc_private_data (bitmap);
+	if (retval)
+		return retval;
+
+	bp = (ext2fs_ba_private) bitmap->private;
+	size = (size_t) (((bitmap->real_end - bitmap->start) / 8) + 1);
+	memset(bp->bitarray, 0, size);
+
+	return 0;
 }
 
 static void ba_free_bmap(ext2fs_generic_bitmap64 bitmap)
 {
+	ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private;
+
+	if (!bp)
+		return;
+
+	if (bp->bitarray) {
+		ext2fs_free_mem (&bp->bitarray);
+		bp->bitarray = 0;
+	}
+	ext2fs_free_mem (&bp);
+	bp = 0;
 }
 
 static errcode_t ba_copy_bmap(ext2fs_generic_bitmap64 src,
-			      ext2fs_generic_bitmap64 *dest)
+			      ext2fs_generic_bitmap64 dest)
 {
+	ext2fs_ba_private src_bp = (ext2fs_ba_private) src->private;
+	ext2fs_ba_private dest_bp;
+	errcode_t retval;
+	size_t size;
+
+	retval = ba_alloc_private_data (dest);
+	if (retval)
+		return retval;
+
+	dest_bp = (ext2fs_ba_private) dest->private;
+
+	size = (size_t) (((src->real_end - src->start) / 8) + 1);
+	memcpy (dest_bp->bitarray, src_bp->bitarray, size);
+
+	return 0;
 }
 
-static errcode_t ba_resize_bmap(ext2fs_generic_bitmap64 bitmap,
+static errcode_t ba_resize_bmap(ext2fs_generic_bitmap64 bmap,
 				__u64 new_end, __u64 new_real_end)
 {
+	ext2fs_ba_private bp = (ext2fs_ba_private) bmap->private;
+	errcode_t	retval;
+	size_t		size, new_size;
+	__u32		bitno;
+
+	/*
+	 * If we're expanding the bitmap, make sure all of the new
+	 * parts of the bitmap are zero.
+	 */
+	if (new_end > bmap->end) {
+		bitno = bmap->real_end;
+		if (bitno > new_end)
+			bitno = new_end;
+		for (; bitno > bmap->end; bitno--)
+			ext2fs_clear_bit64(bitno - bmap->start, bp->bitarray);
+	}
+	if (new_real_end == bmap->real_end) {
+		bmap->end = new_end;
+		return 0;
+	}
+	
+	size = ((bmap->real_end - bmap->start) / 8) + 1;
+	new_size = ((new_real_end - bmap->start) / 8) + 1;
+
+	if (size != new_size) {
+		retval = ext2fs_resize_mem(size, new_size, &bp->bitarray);
+		if (retval)
+			return retval;
+	}
+	if (new_size > size)
+		memset(bp->bitarray + size, 0, new_size - size);
+
+	bmap->end = new_end;
+	bmap->real_end = new_real_end;
+	return 0;
+
 }
 
 static int ba_mark_bmap(ext2fs_generic_bitmap64 bitmap, __u64 arg)
 {
+	ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private;
+	blk64_t bitno = (blk64_t) arg;
+
+	return ext2fs_set_bit64(bitno - bitmap->start, bp->bitarray);
 }
 
 static int ba_unmark_bmap(ext2fs_generic_bitmap64 bitmap, __u64 arg)
 {
+	ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private;
+	blk64_t bitno = (blk64_t) arg;
+
+	return ext2fs_clear_bit64(bitno - bitmap->start, bp->bitarray);
 }
 
 static int ba_test_bmap(ext2fs_generic_bitmap64 bitmap, __u64 arg)
 {
+	ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private;
+	blk64_t bitno = (blk64_t) arg;
+
+	return ext2fs_test_bit64(bitno - bitmap->start, bp->bitarray);
 }
 
 static void ba_mark_bmap_extent(ext2fs_generic_bitmap64 bitmap, __u64 arg,
-				 int num)
+				size_t num)
 {
+	ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private;
+	blk64_t bitno = (blk64_t) arg;
+	size_t i;
+
+	for (i = 0; i < num; i++)
+		ext2fs_fast_set_bit64(bitno + i - bitmap->start, bp->bitarray);
 }
 
 static void ba_unmark_bmap_extent(ext2fs_generic_bitmap64 bitmap, __u64 arg,
-				  int num)
+				  size_t num)
 {
+	ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private;
+	blk64_t bitno = (blk64_t) arg;
+	size_t i;
+
+	for (i = 0; i < num; i++)
+		ext2fs_fast_clear_bit64(bitno + i - bitmap->start, bp->bitarray);
 }
 
 static errcode_t ba_set_bmap_range(ext2fs_generic_bitmap64 bitmap,
-				     __u64 start, unsigned int num, void *in)
+				     __u64 start, size_t num, void *in)
 {
+	ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private;
+
+	memcpy (bp->bitarray + (start >> 3), in, (num + 7) >> 3);
+
+	return 0;
 }
 
 static errcode_t ba_get_bmap_range(ext2fs_generic_bitmap64 bitmap,
-				     __u64 start, unsigned int num, void *out)
+				     __u64 start, size_t num, void *out)
 {
+	ext2fs_ba_private bp = (ext2fs_ba_private) bitmap->private;
+
+	memcpy (out, bp->bitarray + (start >> 3), (num + 7) >> 3);
+
+	return 0;
 }
 
 struct ext2_bitmap_ops ext2fs_blkmap64_bitarray = {
diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h
index ad21fd7..faa44be 100644
--- a/lib/ext2fs/ext2fs.h
+++ b/lib/ext2fs/ext2fs.h
@@ -99,9 +99,15 @@ typedef struct struct_ext2_filsys *ext2_filsys;
 #define EXT2FS_UNMARK_ERROR 	1
 #define EXT2FS_TEST_ERROR	2
 
+/*
+ * We keep around ext2fs_generic_bitmap for backwards compatability in
+ * the underlying generic bitmap ops, but otherwise everything else
+ * becomes an ext2fs_generic_bitmap64.
+ */
 typedef struct ext2fs_struct_generic_bitmap *ext2fs_generic_bitmap;
-typedef struct ext2fs_struct_generic_bitmap *ext2fs_inode_bitmap;
-typedef struct ext2fs_struct_generic_bitmap *ext2fs_block_bitmap;
+typedef struct ext2fs_struct_generic_bitmap64 *ext2fs_generic_bitmap64;
+typedef struct ext2fs_struct_generic_bitmap64 *ext2fs_inode_bitmap;
+typedef struct ext2fs_struct_generic_bitmap64 *ext2fs_block_bitmap;
 
 #define EXT2_FIRST_INODE(s)	EXT2_FIRST_INO(s)
 
@@ -653,8 +659,8 @@ extern errcode_t ext2fs_update_bb_inode(ext2_filsys fs,
 /* bitmaps.c */
 extern void ext2fs_free_block_bitmap(ext2fs_block_bitmap bitmap);
 extern void ext2fs_free_inode_bitmap(ext2fs_inode_bitmap bitmap);
-extern errcode_t ext2fs_copy_bitmap(ext2fs_generic_bitmap src,
-				    ext2fs_generic_bitmap *dest);
+extern errcode_t ext2fs_copy_bitmap(ext2fs_generic_bitmap64 src,
+				    ext2fs_generic_bitmap64 *dest);
 extern errcode_t ext2fs_write_inode_bitmap(ext2_filsys fs);
 extern errcode_t ext2fs_write_block_bitmap (ext2_filsys fs);
 extern errcode_t ext2fs_read_inode_bitmap (ext2_filsys fs);
@@ -949,7 +955,7 @@ extern void ext2fs_badblocks_list_free(ext2_badblocks_list bb);
 extern void ext2fs_u32_list_free(ext2_u32_list bb);
 
 /* gen_bitmap.c */
-extern void ext2fs_free_generic_bitmap(ext2fs_inode_bitmap bitmap);
+extern void ext2fs_free_generic_bitmap(ext2fs_generic_bitmap bitmap);
 extern errcode_t ext2fs_make_generic_bitmap(errcode_t magic, ext2_filsys fs,
 					    __u32 start, __u32 end,
 					    __u32 real_end,
@@ -963,11 +969,9 @@ extern errcode_t ext2fs_allocate_generic_bitmap(__u32 start,
 extern errcode_t ext2fs_copy_generic_bitmap(ext2fs_generic_bitmap src,
 					    ext2fs_generic_bitmap *dest);
 extern void ext2fs_clear_generic_bitmap(ext2fs_generic_bitmap bitmap);
-extern errcode_t ext2fs_fudge_generic_bitmap_end(ext2fs_inode_bitmap bitmap,
-						 errcode_t magic,
-						 errcode_t neq,
-						 ext2_ino_t end,
-						 ext2_ino_t *oend);
+errcode_t ext2fs_fudge_generic_bmap_end(ext2fs_generic_bitmap64 bmap,
+					errcode_t neq,
+					ext2_ino_t end, ext2_ino_t *oend);
 extern void ext2fs_set_generic_bitmap_padding(ext2fs_generic_bitmap map);
 extern errcode_t ext2fs_resize_generic_bitmap(errcode_t magic,
 					      __u32 new_end,
@@ -985,6 +989,24 @@ extern errcode_t ext2fs_set_generic_bitmap_range(ext2fs_generic_bitmap bmap,
 						 __u32 start, __u32 num,
 						 void *in);
 
+/* gen_bitmap64.c */
+void ext2fs_free_generic_bmap(ext2fs_generic_bitmap64 bmap);
+errcode_t ext2fs_alloc_generic_bmap(ext2_filsys fs, errcode_t magic,
+				    int type, __u64 start, __u64 end,
+				    __u64 real_end,
+				    const char *descr,
+				    ext2fs_generic_bitmap64 *ret);
+errcode_t ext2fs_copy_generic_bmap(ext2fs_generic_bitmap64 src,
+				   ext2fs_generic_bitmap64 *dest);
+errcode_t ext2fs_get_generic_bmap_range(ext2fs_generic_bitmap64 bmap,
+					__u64 start, unsigned int num,
+					void *out);
+errcode_t ext2fs_set_generic_bmap_range(ext2fs_generic_bitmap64 bmap,
+					__u64 start, unsigned int num,
+					void *in);
+void ext2fs_set_generic_bmap_padding(ext2fs_generic_bitmap64 map);
+
+
 /* getsize.c */
 extern errcode_t ext2fs_get_device_size(const char *file, int blocksize,
 					blk_t *retblocks);
diff --git a/lib/ext2fs/ext2fsP.h b/lib/ext2fs/ext2fsP.h
index 6f8a4e1..2e4ad74 100644
--- a/lib/ext2fs/ext2fsP.h
+++ b/lib/ext2fs/ext2fsP.h
@@ -113,15 +113,13 @@ struct ext2fs_struct_generic_bitmap64 {
 
 #define EXT2FS_BMAP64_BITARRAY	1
 
-typedef struct ext2fs_struct_generic_bitmap64 *ext2fs_generic_bitmap64;
-
 struct ext2_bitmap_ops {
 	int	type;
 	/* Generic bmap operators */
-	errcode_t (*new_bmap)(ext2_filsys fs, ext2fs_generic_bitmap64 *bmap);
+	errcode_t (*new_bmap)(ext2_filsys fs, ext2fs_generic_bitmap64 bmap);
 	void	(*free_bmap)(ext2fs_generic_bitmap64 bitmap);
 	errcode_t (*copy_bmap)(ext2fs_generic_bitmap64 src,
-			     ext2fs_generic_bitmap64 *dest);
+			     ext2fs_generic_bitmap64 dest);
 	errcode_t (*resize_bmap)(ext2fs_generic_bitmap64 bitmap,
 			       __u64 new_end,
 			       __u64 new_real_end);
@@ -130,13 +128,13 @@ struct ext2_bitmap_ops {
 	int	(*unmark_bmap)(ext2fs_generic_bitmap64 bitmap, __u64 arg);
 	int	(*test_bmap)(ext2fs_generic_bitmap64 bitmap, __u64 arg);
 	void	(*mark_bmap_extent)(ext2fs_generic_bitmap64 bitmap, __u64 arg,
-				  int num);
+				    size_t num);
 	void	(*unmark_bmap_extent)(ext2fs_generic_bitmap64 bitmap, __u64 arg,
-				    int num);
+				    size_t num);
 	errcode_t (*set_bmap_range)(ext2fs_generic_bitmap64 bitmap,
-				    __u64 start, unsigned int num, void *in);
+				    __u64 start, size_t num, void *in);
 	errcode_t (*get_bmap_range)(ext2fs_generic_bitmap64 bitmap,
-				    __u64 start, unsigned int num, void *out);
+				    __u64 start, size_t num, void *out);
 };
 
 extern struct ext2_bitmap_ops ext2fs_blkmap64_bitarray;
diff --git a/lib/ext2fs/gen_bitmap.c b/lib/ext2fs/gen_bitmap.c
index a1b1d8f..5aa6675 100644
--- a/lib/ext2fs/gen_bitmap.c
+++ b/lib/ext2fs/gen_bitmap.c
@@ -138,7 +138,7 @@ errcode_t ext2fs_copy_generic_bitmap(ext2fs_generic_bitmap src,
 					   dest));
 }
 
-void ext2fs_free_generic_bitmap(ext2fs_inode_bitmap bitmap)
+void ext2fs_free_generic_bitmap(ext2fs_generic_bitmap bitmap)
 {
 	if (check_magic(bitmap))
 		return;
@@ -204,7 +204,7 @@ void ext2fs_clear_generic_bitmap(ext2fs_generic_bitmap bitmap)
 	       (size_t) (((bitmap->real_end - bitmap->start) / 8) + 1));
 }
 
-errcode_t ext2fs_fudge_generic_bitmap_end(ext2fs_inode_bitmap bitmap,
+errcode_t ext2fs_fudge_generic_bitmap_end(ext2fs_generic_bitmap bitmap,
 					  errcode_t magic, errcode_t neq,
 					  ext2_ino_t end, ext2_ino_t *oend)
 {
diff --git a/lib/ext2fs/gen_bitmap64.c b/lib/ext2fs/gen_bitmap64.c
index 75af6de..df688b6 100644
--- a/lib/ext2fs/gen_bitmap64.c
+++ b/lib/ext2fs/gen_bitmap64.c
@@ -99,6 +99,7 @@ errcode_t ext2fs_alloc_generic_bmap(ext2_filsys fs, errcode_t magic,
 	if (retval)
 		return retval;
 
+	/* XXX factor out, repeated in copy_bmap */
 	bitmap->magic = magic;
 	bitmap->fs = fs;
 	bitmap->start = start;
@@ -125,7 +126,7 @@ errcode_t ext2fs_alloc_generic_bmap(ext2_filsys fs, errcode_t magic,
 	} else
 		bitmap->description = 0;
 
-	retval = bitmap->bitmap_ops->new_bmap(fs, &bitmap);
+	retval = bitmap->bitmap_ops->new_bmap(fs, bitmap);
 	if (retval) {
 		ext2fs_free_mem(&bitmap);
 		ext2fs_free_mem(&bitmap->description);
@@ -159,40 +160,58 @@ void ext2fs_free_generic_bmap(ext2fs_generic_bitmap64 bmap)
 }
 
 errcode_t ext2fs_copy_generic_bmap(ext2fs_generic_bitmap64 src,
-					  ext2fs_generic_bitmap64 *dest)
+				   ext2fs_generic_bitmap64 *dest)
 {
 	char *descr, *new_descr;
+	ext2fs_generic_bitmap64	new_bmap;
 	errcode_t retval;
 
 	if (!src)
-		return;
+		return EINVAL;
 
 	if (EXT2FS_IS_32_BITMAP(src)) {
 		ext2fs_copy_generic_bitmap((ext2fs_generic_bitmap) src,
 					   (ext2fs_generic_bitmap *) dest);
-		return;
+		return EINVAL;
 	}
 
 	if (!EXT2FS_IS_64_BITMAP(src))
-		return;
+		return EINVAL;
+
+	/* Allocate a new bitmap struct */
+	retval = ext2fs_get_mem(sizeof(struct ext2fs_struct_generic_bitmap64),
+				&new_bmap);
+	if (retval)
+		return retval;
+
+	/* Copy all the high-level parts over */
+	new_bmap->magic = src->magic;
+	new_bmap->fs = src->fs;
+	new_bmap->start = src->start;
+	new_bmap->end = src->end;
+	new_bmap->real_end = src->real_end;
+	new_bmap->bitmap_ops = src->bitmap_ops;
+	new_bmap->base_error_code = src->base_error_code;
 
 	descr = src->description;
 	if (descr) {
 		retval = ext2fs_get_mem(strlen(descr)+1, &new_descr);
 		if (retval) {
-			new_descr = 0;
+			ext2fs_free_mem(&new_bmap);
 			return retval;
 		}
 		strcpy(new_descr, descr);
+		new_bmap->description = new_descr;
 	}
 
-	retval = src->bitmap_ops->copy_bmap(src, dest);
+	retval = src->bitmap_ops->copy_bmap(src, new_bmap);
 	if (retval) {
-		ext2fs_free_mem(&new_descr);
+		ext2fs_free_mem(&new_bmap->description);
+		ext2fs_free_mem(&new_bmap);
 		return retval;
 	}
 
-	(*dest)->description = new_descr;
+	*dest = new_bmap;
 
 	return 0;
 }
@@ -201,24 +220,47 @@ errcode_t ext2fs_resize_generic_bmap(ext2fs_generic_bitmap64 bmap,
 				     __u64 new_end,
 				     __u64 new_real_end)
 {
-	errcode_t retval;
-
 	if (!bmap)
-		return;
+		return EINVAL;
 
 	if (EXT2FS_IS_32_BITMAP(bmap)) {
 		ext2fs_resize_generic_bitmap(bmap->magic,
 					     new_end, new_real_end,
 					     (ext2fs_generic_bitmap) bmap);
-		return;
+		return EINVAL;
 	}
 
 	if (!EXT2FS_IS_64_BITMAP(bmap))
-		return;
+		return EINVAL;
 
 	return bmap->bitmap_ops->resize_bmap(bmap, new_end, new_real_end);
 }
 
+errcode_t ext2fs_fudge_generic_bmap_end(ext2fs_generic_bitmap64 bmap,
+					errcode_t neq,
+					ext2_ino_t end, ext2_ino_t *oend)
+{
+	if (!bmap)
+		return EINVAL;
+
+	if (EXT2FS_IS_32_BITMAP(bmap)) {
+		ext2fs_resize_generic_bitmap((ext2fs_generic_bitmap) bmap,
+					     bmap->magic, neq,
+					     new_end, new_real_end);
+		return EINVAL;
+	}
+
+	if (!EXT2FS_IS_64_BITMAP(bmap))
+		return EINVAL;
+
+	if (end > bitmap->real_end)
+		return neq;
+	if (oend)
+		*oend = bitmap->end;
+	bitmap->end = end;
+	return 0;
+}
+
 int ext2fs_mark_generic_bmap(ext2fs_generic_bitmap64 bitmap,
 			     __u64 arg)
 {
@@ -303,9 +345,7 @@ int ext2fs_test_generic_bmap(ext2fs_generic_bitmap64 bitmap,
 void ext2fs_mark_generic_bmap_extent(ext2fs_generic_bitmap64 bmap,
 				     __u64 arg, int num)
 {
-	errcode_t retval;
-	__u32 i;
-	int c;
+	int i;
 
 	if (!bmap)
 		return;
@@ -316,9 +356,9 @@ void ext2fs_mark_generic_bmap_extent(ext2fs_generic_bitmap64 bmap,
 					    EXT2FS_MARK_ERROR, 0xffffffff);
 			return;
 		}
-		for (i = arg, c = num; c > 0; c--)
+		for (i = 0; i < num; i++)
 			ext2fs_mark_generic_bitmap((ext2fs_generic_bitmap)
-						   bmap, i);
+						   bmap, arg + i);
 		return;
 	}
 
@@ -331,9 +371,7 @@ void ext2fs_mark_generic_bmap_extent(ext2fs_generic_bitmap64 bmap,
 void ext2fs_unmark_generic_bmap_extent(ext2fs_generic_bitmap64 bmap,
 				      __u64 arg, int num)
 {
-	errcode_t retval;
 	__u32 i;
-	int c;
 
 	if (!bmap)
 		return;
@@ -344,9 +382,9 @@ void ext2fs_unmark_generic_bmap_extent(ext2fs_generic_bitmap64 bmap,
 					    EXT2FS_UNMARK_ERROR, 0xffffffff);
 			return;
 		}
-		for (i = arg, c = num; c > 0; c--)
+		for (i = 0; i < num; i++)
 			ext2fs_unmark_generic_bitmap((ext2fs_generic_bitmap)
-						     bmap, i);
+						     bmap, arg + i);
 		return;
 	}
 
@@ -356,14 +394,73 @@ void ext2fs_unmark_generic_bmap_extent(ext2fs_generic_bitmap64 bmap,
 	bmap->bitmap_ops->unmark_bmap_extent(bmap, arg, num);
 }
 
-errcode_t ext2fs_set_generic_bmap_range(ext2fs_generic_bitmap64 bitmap,
+errcode_t ext2fs_set_generic_bmap_range(ext2fs_generic_bitmap64 bmap,
 					__u64 start, unsigned int num,
 					void *in)
 {
+	if (!bmap)
+		return EINVAL;
+
+	if (EXT2FS_IS_32_BITMAP(bmap)) {
+		if ((start+num) & ~0xffffffff) {
+			ext2fs_warn_bitmap2((ext2fs_generic_bitmap) bmap,
+					    EXT2FS_UNMARK_ERROR, 0xffffffff);
+			return EINVAL;
+		}
+		return ext2fs_set_generic_bitmap_range((ext2fs_generic_bitmap) bmap,
+						       bmap->magic, start, num,
+						       in);
+	}
+
+	if (!EXT2FS_IS_64_BITMAP(bmap))
+		return EINVAL;
+
+	return bmap->bitmap_ops->set_bmap_range(bmap, start, num, in);
 }
 
-errcode_t ext2fs_get_generic_bmap_range(ext2fs_generic_bitmap64 bitmap,
+errcode_t ext2fs_get_generic_bmap_range(ext2fs_generic_bitmap64 bmap,
 					__u64 start, unsigned int num,
 					void *out)
 {
+	if (!bmap)
+		return EINVAL;
+
+	if (EXT2FS_IS_32_BITMAP(bmap)) {
+		if ((start+num) & ~0xffffffff) {
+			ext2fs_warn_bitmap2((ext2fs_generic_bitmap) bmap,
+					    EXT2FS_UNMARK_ERROR, 0xffffffff);
+			return EINVAL;
+		}
+		return ext2fs_get_generic_bitmap_range((ext2fs_generic_bitmap) bmap,
+						       bmap->magic, start, num,
+						       out);
+	}
+
+	if (!EXT2FS_IS_64_BITMAP(bmap))
+		return EINVAL;
+
+	return bmap->bitmap_ops->get_bmap_range(bmap, start, num, out);
+}
+
+void ext2fs_set_generic_bmap_padding(ext2fs_generic_bitmap64 map)
+{
+	__u64	i, j;
+
+	if (!bmap)
+		return EINVAL;
+
+	if (EXT2FS_IS_32_BITMAP(bmap)) {
+		ext2fs_set_generic_bitmap_padding((ext2fs_generic_bitmap) bmap);
+		return EINVAL;
+	}
+
+	if (!EXT2FS_IS_64_BITMAP(bmap))
+		return EINVAL;
+
+	/* Protect loop from wrap-around if map->real_end is maxed */
+	for (i=map->end+1, j = i - map->start; 
+	     i <= map->real_end && i > map->end; 
+	     i++, j++)
+		ext2fs_set_bit64(j, map->bitmap);
 }
+
diff --git a/lib/ext2fs/imager.c b/lib/ext2fs/imager.c
index 0154333..ba72e46 100644
--- a/lib/ext2fs/imager.c
+++ b/lib/ext2fs/imager.c
@@ -277,7 +277,7 @@ errout:
  */
 errcode_t ext2fs_image_bitmap_write(ext2_filsys fs, int fd, int flags)
 {
-	ext2fs_generic_bitmap	bmap;
+	ext2fs_generic_bitmap64	bmap;
 	errcode_t		err, retval;
 	ssize_t			actual;
 	__u32			itr, cnt, size;
@@ -314,8 +314,8 @@ errcode_t ext2fs_image_bitmap_write(ext2_filsys fs, int fd, int flags)
 		if (size > (cnt >> 3))
 			size = (cnt >> 3);
 
-		retval = ext2fs_get_generic_bitmap_range(bmap,
-				 err, itr, size << 3, buf);
+		retval = ext2fs_get_generic_bmap_range(bmap,
+				 itr, size << 3, buf);
 		if (retval)
 			return retval;
 
@@ -354,7 +354,7 @@ errcode_t ext2fs_image_bitmap_write(ext2_filsys fs, int fd, int flags)
  */
 errcode_t ext2fs_image_bitmap_read(ext2_filsys fs, int fd, int flags)
 {
-	ext2fs_generic_bitmap	bmap;
+	ext2fs_generic_bitmap64	bmap;
 	errcode_t		err, retval;
 	__u32			itr, cnt;
 	char			buf[1024];
@@ -396,8 +396,8 @@ errcode_t ext2fs_image_bitmap_read(ext2_filsys fs, int fd, int flags)
 		if (actual != (int) size)
 			return EXT2_ET_SHORT_READ;
 
-		retval = ext2fs_set_generic_bitmap_range(bmap,
-				 err, itr, size << 3, buf);
+		retval = ext2fs_set_generic_bmap_range(bmap,
+				 itr, size << 3, buf);
 		if (retval)
 			return retval;
 
diff --git a/lib/ext2fs/inode.c b/lib/ext2fs/inode.c
index b75cb77..667f3c6 100644
--- a/lib/ext2fs/inode.c
+++ b/lib/ext2fs/inode.c
@@ -11,6 +11,7 @@
 
 #include <stdio.h>
 #include <string.h>
+#include <time.h>
 #if HAVE_UNISTD_H
 #include <unistd.h>
 #endif
diff --git a/lib/ext2fs/tst_bitops.c b/lib/ext2fs/tst_bitops.c
index 6febe68..f05a54a 100644
--- a/lib/ext2fs/tst_bitops.c
+++ b/lib/ext2fs/tst_bitops.c
@@ -169,5 +169,127 @@ int main(int argc, char **argv)
 
 	printf("ext2fs_fast_set_bit big_test successful\n");
 
+	/* Repeat foregoing tests for 64-bit bitops */
+
+	/* Test test_bit */
+	for (i=0,j=0; i < size; i++) {
+		if (ext2fs_test_bit64(i, bitarray)) {
+			if (bits_list[j] == i) {
+				j++;
+			} else {
+				printf("64-bit: Bit %d set, not expected\n",
+				       i);
+				exit(1);
+			}
+		} else {
+			if (bits_list[j] == i) {
+				printf("64-bit: "
+				       "Expected bit %d to be clear.\n", i);
+				exit(1);
+			}
+		}
+	}
+	printf("64-bit: ext2fs_test_bit appears to be correct\n");
+
+	/* Test ext2fs_set_bit */
+	memset(testarray, 0, sizeof(testarray));
+	for (i=0; bits_list[i] > 0; i++) {
+		ext2fs_set_bit64(bits_list[i], testarray);
+	}
+	if (memcmp(testarray, bitarray, sizeof(testarray)) == 0) {
+		printf("64-bit: ext2fs_set_bit test succeeded.\n");
+	} else {
+		printf("64-bit: ext2fs_set_bit test failed.\n");
+		for (i=0; i < sizeof(testarray); i++) {
+			printf("%02x ", testarray[i]);
+		}
+		printf("\n");
+		exit(1);
+	}
+	for (i=0; bits_list[i] > 0; i++) {
+		ext2fs_clear_bit64(bits_list[i], testarray);
+	}
+	for (i=0; i < sizeof(testarray); i++) {
+		if (testarray[i]) {
+			printf("64-bit: ext2fs_clear_bit failed, "
+			       "testarray[%d] is %d\n", i, testarray[i]);
+			exit(1);
+		}
+	}
+	printf("64-bit: ext2fs_clear_bit test succeed.\n");
+		
+
+	/* Do bigarray test */
+	bigarray = malloc(1 << 29);
+	if (!bigarray) {
+		fprintf(stderr, "Failed to allocate scratch memory!\n");
+		exit(1);
+	}
+
+        bigarray[BIG_TEST_BIT >> 3] = 0;
+
+	ext2fs_set_bit64(BIG_TEST_BIT, bigarray);
+	printf("64-bit: big bit number (%u) test: %d, expected %d\n",
+	       BIG_TEST_BIT, bigarray[BIG_TEST_BIT >> 3],
+	       (1 << (BIG_TEST_BIT & 7)));
+	if (bigarray[BIG_TEST_BIT >> 3] != (1 << (BIG_TEST_BIT & 7)))
+		exit(1);
+
+	ext2fs_clear_bit64(BIG_TEST_BIT, bigarray);
+
+	printf("64-bit: big bit number (%u) test: %d, expected 0\n",
+	       BIG_TEST_BIT,
+	       bigarray[BIG_TEST_BIT >> 3]);
+	if (bigarray[BIG_TEST_BIT >> 3] != 0)
+		exit(1);
+
+	printf("64-bit: ext2fs_set_bit big_test successful\n");
+
+	/* Now test ext2fs_fast_set_bit */
+	memset(testarray, 0, sizeof(testarray));
+	for (i=0; bits_list[i] > 0; i++) {
+		ext2fs_fast_set_bit64(bits_list[i], testarray);
+	}
+	if (memcmp(testarray, bitarray, sizeof(testarray)) == 0) {
+		printf("64-bit: ext2fs_fast_set_bit test succeeded.\n");
+	} else {
+		printf("64-bit: ext2fs_fast_set_bit test failed.\n");
+		for (i=0; i < sizeof(testarray); i++) {
+			printf("%02x ", testarray[i]);
+		}
+		printf("\n");
+		exit(1);
+	}
+	for (i=0; bits_list[i] > 0; i++) {
+		ext2fs_clear_bit64(bits_list[i], testarray);
+	}
+	for (i=0; i < sizeof(testarray); i++) {
+		if (testarray[i]) {
+			printf("64-bit: ext2fs_clear_bit failed, "
+			       "testarray[%d] is %d\n", i, testarray[i]);
+			exit(1);
+		}
+	}
+	printf("64-bit: ext2fs_clear_bit test succeed.\n");
+		
+
+        bigarray[BIG_TEST_BIT >> 3] = 0;
+
+	ext2fs_fast_set_bit64(BIG_TEST_BIT, bigarray);
+	printf("64-bit: big bit number (%u) test: %d, expected %d\n",
+	       BIG_TEST_BIT, bigarray[BIG_TEST_BIT >> 3],
+	       (1 << (BIG_TEST_BIT & 7)));
+	if (bigarray[BIG_TEST_BIT >> 3] != (1 << (BIG_TEST_BIT & 7)))
+		exit(1);
+
+	ext2fs_fast_clear_bit64(BIG_TEST_BIT, bigarray);
+
+	printf("64-bit: big bit number (%u) test: %d, expected 0\n",
+	       BIG_TEST_BIT, bigarray[BIG_TEST_BIT >> 3]);
+	if (bigarray[BIG_TEST_BIT >> 3] != 0)
+		exit(1);
+
+	printf("64-bit: ext2fs_fast_set_bit big_test successful\n");
+
 	exit(0);
 }
diff --git a/lib/uuid/gen_uuid.c b/lib/uuid/gen_uuid.c
index a3052d4..76c989c 100644
--- a/lib/uuid/gen_uuid.c
+++ b/lib/uuid/gen_uuid.c
@@ -35,8 +35,10 @@
 /*
  * Force inclusion of SVID stuff since we need it if we're compiling in
  * gcc-wall wall mode
+ *
+ * XXX - below somehow hides ftruncate() definition and _creates_ warnings
  */
-#define _SVID_SOURCE
+/* #define _SVID_SOURCE */
 
 #ifdef _WIN32
 #define _WIN32_WINNT 0x0500
diff --git a/misc/blkid.c b/misc/blkid.c
index 4bbf9fb..e5c8088 100644
--- a/misc/blkid.c
+++ b/misc/blkid.c
@@ -170,7 +170,6 @@ static void pretty_print_dev(blkid_dev dev)
 	blkid_tag_iterate	iter;
 	const char		*type, *value, *devname;
 	const char		*uuid = "", *fs_type = "", *label = "";
-	char			*cp;
 	int			len, mount_flags;
 	char			mtpt[80];
 	errcode_t		retval;
diff --git a/misc/dumpe2fs.c b/misc/dumpe2fs.c
index 9ef5476..1c70c24 100644
--- a/misc/dumpe2fs.c
+++ b/misc/dumpe2fs.c
@@ -214,7 +214,7 @@ static void list_desc (ext2_filsys fs)
 		diff = fs->group_desc[i].bg_inode_table - first_block;
 		if (diff > 0)
 			printf(" (+%ld)", diff);
-		printf (_("\n  %u free blocks, %u free inodes, "
+		printf (_("\n  %d free blocks, %u free inodes, "
 			  "%u directories%s"),
 			fs->group_desc[i].bg_free_blocks_count,
 			fs->group_desc[i].bg_free_inodes_count,
diff --git a/misc/mke2fs.c b/misc/mke2fs.c
index 77f1bc0..be9f4e6 100644
--- a/misc/mke2fs.c
+++ b/misc/mke2fs.c
@@ -48,6 +48,7 @@ extern int optind;
 #include <sys/types.h>
 #include <libgen.h>
 #include <limits.h>
+#include <strings.h>
 
 #include "ext2fs/ext2_fs.h"
 #include "et/com_err.h"
@@ -380,7 +381,7 @@ static void write_inode_tables(ext2_filsys fs, int lazy_flag)
 		retval = ext2fs_zero_blocks2(fs, blk, num, &blk, &num);
 		if (retval) {
 			fprintf(stderr, _("\nCould not write %d "
-				  "blocks in inode table starting at %ull: %s\n"),
+				  "blocks in inode table starting at %llu: %s\n"),
 				num, blk, error_message(retval));
 			exit(1);
 		}
@@ -597,7 +598,7 @@ static void show_stats(ext2_filsys fs)
 	int			need, col_left;
 
 	if (ext2fs_blocks_count(&fs_param) != ext2fs_blocks_count(s))
-		fprintf(stderr, _("warning: %u blocks unused.\n\n"),
+		fprintf(stderr, _("warning: %llu blocks unused.\n\n"),
 		       ext2fs_blocks_count(&fs_param) - ext2fs_blocks_count(s));
 
 	memset(buf, 0, sizeof(buf));
@@ -1995,7 +1996,7 @@ int main (int argc, char *argv[])
 
 		if (retval) {
 			com_err(program_name, retval,
-				_("while zeroing block %u at end of filesystem"),
+				_("while zeroing block %llu at end of filesystem"),
 				ret_blk);
 		}
 		write_inode_tables(fs, lazy_itable_init);
diff --git a/misc/tune2fs.c b/misc/tune2fs.c
index a1fa57b..04e2b9f 100644
--- a/misc/tune2fs.c
+++ b/misc/tune2fs.c
@@ -1440,7 +1440,7 @@ retry_open:
 		 * file.
 		 */
 		if (new_inode_size == EXT2_INODE_SIZE(fs->super)) {
-			fprintf(stderr, _("The inode size is already %d\n"),
+			fprintf(stderr, _("The inode size is already %lu\n"),
 				new_inode_size);
 			exit(1);
 		}

--
To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ