libext2fs: Add callback functions for _alloc_block() and _block_alloc_stats()

Add callback functions for ext2fs_alloc_block() and
ext2fs_block_alloc_stats().  This is needed so e2fsck can be informed
when the extent_set_bmap() function needs to allocate or deallocate
blocks.

Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
diff --git a/lib/ext2fs/alloc.c b/lib/ext2fs/alloc.c
index 65f3ea1..f8d8a5f 100644
--- a/lib/ext2fs/alloc.c
+++ b/lib/ext2fs/alloc.c
@@ -118,16 +118,25 @@
 	}
 	memset(block_buf, 0, fs->blocksize);
 
-	if (!fs->block_map) {
-		retval = ext2fs_read_block_bitmap(fs);
+	if (fs->get_alloc_block) {
+		blk64_t	new;
+
+		retval = (fs->get_alloc_block)(fs, (blk64_t) goal, &new);
+		if (retval)
+			goto fail;
+		block = (blk_t) new;
+	} else {
+		if (!fs->block_map) {
+			retval = ext2fs_read_block_bitmap(fs);
+			if (retval)
+				goto fail;
+		}
+
+		retval = ext2fs_new_block(fs, goal, 0, &block);
 		if (retval)
 			goto fail;
 	}
 
-	retval = ext2fs_new_block(fs, goal, 0, &block);
-	if (retval)
-		goto fail;
-
 	retval = io_channel_write_blk(fs->io, block, 1, block_buf);
 	if (retval)
 		goto fail;
@@ -170,3 +179,19 @@
 	return EXT2_ET_BLOCK_ALLOC_FAIL;
 }
 
+void ext2fs_set_alloc_block_callback(ext2_filsys fs, 
+				     errcode_t (*func)(ext2_filsys fs,
+						       blk64_t goal,
+						       blk64_t *ret),
+				     errcode_t (**old)(ext2_filsys fs,
+						       blk64_t goal,
+						       blk64_t *ret))
+{
+	if (!fs || fs->magic != EXT2_ET_MAGIC_EXT2FS_FILSYS)
+		return;
+
+	if (old)
+		*old = fs->get_alloc_block;
+
+	fs->get_alloc_block = func;
+}
diff --git a/lib/ext2fs/alloc_stats.c b/lib/ext2fs/alloc_stats.c
index 3956528..a8514cc 100644
--- a/lib/ext2fs/alloc_stats.c
+++ b/lib/ext2fs/alloc_stats.c
@@ -69,4 +69,22 @@
 	fs->super->s_free_blocks_count -= inuse;
 	ext2fs_mark_super_dirty(fs);
 	ext2fs_mark_bb_dirty(fs);
+	if (fs->block_alloc_stats)
+		(fs->block_alloc_stats)(fs, (blk64_t) blk, inuse);
+}
+
+void ext2fs_set_block_alloc_stats_callback(ext2_filsys fs, 
+					   void (*func)(ext2_filsys fs,
+							blk64_t blk,
+							int inuse),
+					   void (**old)(ext2_filsys fs,
+							blk64_t blk,
+							int inuse))
+{
+	if (!fs || fs->magic != EXT2_ET_MAGIC_EXT2FS_FILSYS)
+		return;
+	if (old)
+		*old = fs->block_alloc_stats;
+
+	fs->block_alloc_stats = func;
 }
diff --git a/lib/ext2fs/ext2fs.h b/lib/ext2fs/ext2fs.h
index 3ef3b0d..ebad54e 100644
--- a/lib/ext2fs/ext2fs.h
+++ b/lib/ext2fs/ext2fs.h
@@ -229,6 +229,13 @@
 	 */
 	struct ext2_inode_cache		*icache;
 	io_channel			image_io;
+
+	/*
+	 * More callback functions
+	 */
+	errcode_t (*get_alloc_block)(ext2_filsys fs, blk64_t goal,
+				     blk64_t *ret);
+	void (*block_alloc_stats)(ext2_filsys fs, blk64_t blk, int inuse);
 };
 
 #if EXT2_FLAT_INCLUDES
@@ -552,11 +559,25 @@
 					blk_t *ret);
 extern errcode_t ext2fs_alloc_block(ext2_filsys fs, blk_t goal,
 				    char *block_buf, blk_t *ret);
+extern void ext2fs_set_alloc_block_callback(ext2_filsys fs, 
+					    errcode_t (*func)(ext2_filsys fs,
+							      blk64_t goal,
+							      blk64_t *ret),
+					    errcode_t (**old)(ext2_filsys fs,
+							      blk64_t goal,
+							      blk64_t *ret));
 
 /* alloc_sb.c */
 extern int ext2fs_reserve_super_and_bgd(ext2_filsys fs, 
 					dgrp_t group,
 					ext2fs_block_bitmap bmap);
+extern void ext2fs_set_block_alloc_stats_callback(ext2_filsys fs, 
+						  void (*func)(ext2_filsys fs,
+							       blk64_t blk,
+							       int inuse),
+						  void (**old)(ext2_filsys fs,
+							       blk64_t blk,
+							       int inuse));
 
 /* alloc_stats.c */
 void ext2fs_inode_alloc_stats(ext2_filsys fs, ext2_ino_t ino, int inuse);