Whamcloud - gitweb
- make HEAD from b_post_cmd3
[fs/lustre-release.git] / lustre / kernel_patches / patches / ext3-extents-multiblock-directio-2.6.9-rhel4.patch
diff --git a/lustre/kernel_patches/patches/ext3-extents-multiblock-directio-2.6.9-rhel4.patch b/lustre/kernel_patches/patches/ext3-extents-multiblock-directio-2.6.9-rhel4.patch
new file mode 100644 (file)
index 0000000..726a473
--- /dev/null
@@ -0,0 +1,149 @@
+--- 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);