--- /dev/null
+--- linux-2.6.9-full/include/linux/ext3_fs.h 2007-03-23 15:57:00.000000000 +0300
++++ linux-2.6.9-full/include/linux/ext3_fs.h 2007-02-16 17:16:23.000000000 +0300
+@@ -850,7 +850,7 @@ extern struct inode_operations ext3_fast
+
+ /* extents.c */
+ extern int ext3_ext_writepage_trans_blocks(struct inode *, int);
+-extern int ext3_ext_get_block(handle_t *, struct inode *, long,
++extern int ext3_ext_get_block(handle_t *, struct inode *, long, int,
+ struct buffer_head *, int, int);
+ extern void ext3_ext_truncate(struct inode *, struct page *);
+ extern void ext3_ext_init(struct super_block *);
+
+--- linux-2.6.9-full/fs/ext3/extents.c 2007-03-23 15:57:00.000000000 +0300
++++ linux-2.6.9-full/fs/ext3/extents.c 2007-02-22 17:45:05.000000000 +0300
+@@ -2031,7 +2168,8 @@ void ext3_init_tree_desc(struct ext3_ext
+ }
+
+ int ext3_ext_get_block(handle_t *handle, struct inode *inode,
+- long iblock, struct buffer_head *bh_result,
++ long iblock, int max_blocks,
++ struct buffer_head *bh_result,
+ int create, int extend_disksize)
+ {
+ struct ext3_ext_path *path = NULL;
+@@ -2039,6 +2177,11 @@ int ext3_ext_get_block(handle_t *handle,
+ struct ext3_extent *ex;
+ int goal, newblock, err = 0, depth;
+ struct ext3_extents_tree tree;
++ unsigned long next;
++ int allocated = 0;
++
++ /* until we have multiblock allocation */
++ max_blocks = 1;
+
+ clear_buffer_new(bh_result);
+ ext3_init_tree_desc(&tree, inode);
+@@ -2058,6 +2201,9 @@ int ext3_ext_get_block(handle_t *handle,
+ } else if (goal == EXT3_EXT_CACHE_EXTENT) {
+ /* block is already allocated */
+ newblock = iblock - newex.ee_block + newex.ee_start;
++ /* number of remaining blocks in the extent */
++ EXT_ASSERT(iblock >= newex.ee_block);
++ allocated = newex.ee_len - (iblock - newex.ee_block);
+ goto out;
+ } else {
+ EXT_ASSERT(0);
+@@ -2085,6 +2231,8 @@ int ext3_ext_get_block(handle_t *handle,
+ /* if found exent covers block, simple return it */
+ if (iblock >= ex->ee_block && iblock < ex->ee_block + ex->ee_len) {
+ newblock = iblock - ex->ee_block + ex->ee_start;
++ /* number of remaining blocks in the extent */
++ allocated = ex->ee_len - (iblock - ex->ee_block);
+ ext_debug(&tree, "%d fit into %d:%d -> %d\n",
+ (int) iblock, ex->ee_block, ex->ee_len,
+ newblock);
+@@ -2105,6 +2253,15 @@ int ext3_ext_get_block(handle_t *handle,
+ goto out2;
+ }
+
++ /* find next allocated block so that we know how many
++ * blocks we can allocate without ovelapping next extent */
++ EXT_ASSERT(iblock >= ex->ee_block + ex->ee_len);
++ next = ext3_ext_next_allocated_block(path);
++ EXT_ASSERT(next > iblock);
++ allocated = next - iblock;
++ if (allocated > max_blocks)
++ allocated = max_blocks;
++
+ /* allocate new block */
+ goal = ext3_ext_find_goal(inode, path, iblock);
+ newblock = ext3_new_block(handle, inode, goal, &err);
+@@ -2119,8 +2276,11 @@ int ext3_ext_get_block(handle_t *handle,
+ newex.ee_start_hi = 0;
+ newex.ee_len = 1;
+ err = ext3_ext_insert_extent(handle, &tree, path, &newex);
+- if (err)
++ if (err) {
++ /* free data blocks we just allocated */
++ ext3_free_blocks(handle, inode, newex.ee_start, newex.ee_len);
+ goto out2;
++ }
+
+ if (extend_disksize && inode->i_size > EXT3_I(inode)->i_disksize)
+ EXT3_I(inode)->i_disksize = inode->i_size;
+@@ -2132,8 +2292,11 @@ int ext3_ext_get_block(handle_t *handle,
+ ext3_ext_put_in_cache(&tree, newex.ee_block, newex.ee_len,
+ newex.ee_start, EXT3_EXT_CACHE_EXTENT);
+ out:
++ if (allocated > max_blocks)
++ allocated = max_blocks;
+ ext3_ext_show_leaf(&tree, path);
+ map_bh(bh_result, inode->i_sb, newblock);
++ bh_result->b_size = (allocated << inode->i_blkbits);
+ out2:
+ if (path) {
+ ext3_ext_drop_refs(path);
+--- linux-2.6.9-full/fs/ext3/inode.c 2007-03-23 15:57:00.000000000 +0300
++++ linux-2.6.9-full/fs/ext3/inode.c 2007-02-16 17:17:03.000000000 +0300
+@@ -798,13 +798,17 @@ changed:
+
+ static inline int
+ ext3_get_block_wrap(handle_t *handle, struct inode *inode, long block,
+- struct buffer_head *bh, int create, int extend_disksize)
++ int max_blocks, struct buffer_head *bh, int create,
++ int extend_disksize)
+ {
++ int ret;
+ if (EXT3_I(inode)->i_flags & EXT3_EXTENTS_FL)
+- return ext3_ext_get_block(handle, inode, block, bh, create,
+- extend_disksize);
+- return ext3_get_block_handle(handle, inode, block, bh, create,
++ return ext3_ext_get_block(handle, inode, block, max_blocks,
++ bh, create, extend_disksize);
++ ret = ext3_get_block_handle(handle, inode, block, bh, create,
+ extend_disksize);
++ bh->b_size = (1 << inode->i_blkbits);
++ return ret;
+ }
+
+ static int ext3_get_block(struct inode *inode, sector_t iblock,
+@@ -817,7 +821,7 @@ static int ext3_get_block(struct inode *
+ handle = ext3_journal_current_handle();
+ J_ASSERT(handle != 0);
+ }
+- ret = ext3_get_block_wrap(handle, inode, iblock,
++ ret = ext3_get_block_wrap(handle, inode, iblock, 1,
+ bh_result, create, 1);
+ return ret;
+ }
+@@ -862,9 +866,8 @@ ext3_direct_io_get_blocks(struct inode *
+
+ get_block:
+ if (ret == 0)
+- ret = ext3_get_block_wrap(handle, inode, iblock,
++ ret = ext3_get_block_wrap(handle, inode, iblock, max_blocks,
+ bh_result, create, 0);
+- bh_result->b_size = (1 << inode->i_blkbits);
+ return ret;
+ }
+
+@@ -882,7 +885,7 @@ struct buffer_head *ext3_getblk(handle_t
+ dummy.b_state = 0;
+ dummy.b_blocknr = -1000;
+ buffer_trace_init(&dummy.b_history);
+- *errp = ext3_get_block_wrap(handle, inode, block, &dummy, create, 1);
++ *errp = ext3_get_block_wrap(handle, inode, block, 1, &dummy, create, 1);
+ if (!*errp && buffer_mapped(&dummy)) {
+ struct buffer_head *bh;
+ bh = sb_getblk(inode->i_sb, dummy.b_blocknr);