[RFC] [PATCH 1/4]Multiple block allocation for ext3

2005-07-17 Thread Mingming Cao
Here is the patch support multiple block allocation for ext3. Current
ext3 allocates one block at a time, not efficient for large sequential
write IO.

This patch implements a simply multiple block allocation with current
ext3.  The basic idea is allocating the 1st block in the existing way,
and attempting to allocate the next adjacent blocks on a  best effort
basis. If contiguous allocation is blocked by an already allocated
block, the current number of free blocks are allocated and no futhur
search is tried.

This implementation makes uses of block reservation. With the knowledge
of how many blocks to allocate, the reservation window size is being
enlargedaccordin before block allocation to increase the chance to get
contiguous blocks.

Previous post of this patch with more description could be found here:
http://marc.theaimsgroup.com/?l=ext2-devel=111471578328685=2 




---

 linux-2.6.12-ming/fs/ext3/balloc.c|  121 +++--
 linux-2.6.12-ming/fs/ext3/inode.c |  380 --
 linux-2.6.12-ming/fs/ext3/xattr.c |3 
 linux-2.6.12-ming/include/linux/ext3_fs.h |2 
 4 files changed, 458 insertions(+), 48 deletions(-)

diff -puN fs/ext3/balloc.c~ext3-get-blocks fs/ext3/balloc.c
--- linux-2.6.12/fs/ext3/balloc.c~ext3-get-blocks   2005-07-14 
21:55:55.110385896 -0700
+++ linux-2.6.12-ming/fs/ext3/balloc.c  2005-07-14 22:40:32.265396472 -0700
@@ -20,6 +20,7 @@
 #include 
 #include 
 
+#defineNBS_DEBUG   0
 /*
  * balloc.c contains the blocks allocation and deallocation routines
  */
@@ -652,9 +653,11 @@ claim_block(spinlock_t *lock, int block,
  */
 static int
 ext3_try_to_allocate(struct super_block *sb, handle_t *handle, int group,
-   struct buffer_head *bitmap_bh, int goal, struct ext3_reserve_window 
*my_rsv)
+   struct buffer_head *bitmap_bh, int goal, unsigned long *count,
+   struct ext3_reserve_window *my_rsv)
 {
int group_first_block, start, end;
+   unsigned long num = 0;
 
/* we do allocation within the reservation window if we have a window */
if (my_rsv) {
@@ -712,8 +715,22 @@ repeat:
goto fail_access;
goto repeat;
}
-   return goal;
+   num++;
+   goal++;
+   if (NBS_DEBUG)
+   printk("ext3_new_block: first block allocated:block %d,num 
%d\n", goal, num);
+   while (num < *count && goal < end
+   && ext3_test_allocatable(goal, bitmap_bh)
+   && claim_block(sb_bgl_lock(EXT3_SB(sb), group), goal, 
bitmap_bh)) {
+   num++;
+   goal++;
+   }
+   *count = num;
+   if (NBS_DEBUG)
+   printk("ext3_new_block: additional block allocated:block %d,num 
%d,goal-num %d\n", goal, num, goal-num);
+   return goal - num;
 fail_access:
+   *count = num;
return -1;
 }
 
@@ -998,6 +1015,28 @@ retry:
goto retry;
 }
 
+static void try_to_extend_reservation(struct ext3_reserve_window_node *my_rsv,
+   struct super_block *sb, int size)
+{
+   struct ext3_reserve_window_node *next_rsv;
+   struct rb_node *next;
+   spinlock_t *rsv_lock = _SB(sb)->s_rsv_window_lock;
+
+   spin_lock(rsv_lock);
+   next = rb_next(_rsv->rsv_node);
+
+   if (!next)
+   my_rsv->rsv_end += size;
+   else {
+   next_rsv = list_entry(next, struct ext3_reserve_window_node, 
rsv_node);
+
+   if ((next_rsv->rsv_start - my_rsv->rsv_end) > size)
+   my_rsv->rsv_end += size;
+   else
+   my_rsv->rsv_end = next_rsv->rsv_start -1 ;
+   }
+   spin_unlock(rsv_lock);
+}
 /*
  * This is the main function used to allocate a new block and its reservation
  * window.
@@ -1023,11 +1062,12 @@ static int
 ext3_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle,
unsigned int group, struct buffer_head *bitmap_bh,
int goal, struct ext3_reserve_window_node * my_rsv,
-   int *errp)
+   unsigned long *count, int *errp)
 {
unsigned long group_first_block;
int ret = 0;
int fatal;
+   unsigned long num = *count;
 
*errp = 0;
 
@@ -1050,7 +1090,8 @@ ext3_try_to_allocate_with_rsv(struct sup
 * or last attempt to allocate a block with reservation turned on failed
 */
if (my_rsv == NULL ) {
-   ret = ext3_try_to_allocate(sb, handle, group, bitmap_bh, goal, 
NULL);
+   ret = ext3_try_to_allocate(sb, handle, group, bitmap_bh, goal,
+   count, NULL);
goto out;
}
/*
@@ -1080,6 +1121,10 @@ ext3_try_to_allocate_with_rsv(struct sup
while (1) {
if (rsv_is_empty(_rsv->rsv_window) || (ret < 0) ||
!goal_in_my_reservation(_rsv->rsv_window, goal, 

[RFC] [PATCH 1/4]Multiple block allocation for ext3

2005-07-17 Thread Mingming Cao
Here is the patch support multiple block allocation for ext3. Current
ext3 allocates one block at a time, not efficient for large sequential
write IO.

This patch implements a simply multiple block allocation with current
ext3.  The basic idea is allocating the 1st block in the existing way,
and attempting to allocate the next adjacent blocks on a  best effort
basis. If contiguous allocation is blocked by an already allocated
block, the current number of free blocks are allocated and no futhur
search is tried.

This implementation makes uses of block reservation. With the knowledge
of how many blocks to allocate, the reservation window size is being
enlargedaccordin before block allocation to increase the chance to get
contiguous blocks.

Previous post of this patch with more description could be found here:
http://marc.theaimsgroup.com/?l=ext2-develm=111471578328685w=2 




---

 linux-2.6.12-ming/fs/ext3/balloc.c|  121 +++--
 linux-2.6.12-ming/fs/ext3/inode.c |  380 --
 linux-2.6.12-ming/fs/ext3/xattr.c |3 
 linux-2.6.12-ming/include/linux/ext3_fs.h |2 
 4 files changed, 458 insertions(+), 48 deletions(-)

diff -puN fs/ext3/balloc.c~ext3-get-blocks fs/ext3/balloc.c
--- linux-2.6.12/fs/ext3/balloc.c~ext3-get-blocks   2005-07-14 
21:55:55.110385896 -0700
+++ linux-2.6.12-ming/fs/ext3/balloc.c  2005-07-14 22:40:32.265396472 -0700
@@ -20,6 +20,7 @@
 #include linux/quotaops.h
 #include linux/buffer_head.h
 
+#defineNBS_DEBUG   0
 /*
  * balloc.c contains the blocks allocation and deallocation routines
  */
@@ -652,9 +653,11 @@ claim_block(spinlock_t *lock, int block,
  */
 static int
 ext3_try_to_allocate(struct super_block *sb, handle_t *handle, int group,
-   struct buffer_head *bitmap_bh, int goal, struct ext3_reserve_window 
*my_rsv)
+   struct buffer_head *bitmap_bh, int goal, unsigned long *count,
+   struct ext3_reserve_window *my_rsv)
 {
int group_first_block, start, end;
+   unsigned long num = 0;
 
/* we do allocation within the reservation window if we have a window */
if (my_rsv) {
@@ -712,8 +715,22 @@ repeat:
goto fail_access;
goto repeat;
}
-   return goal;
+   num++;
+   goal++;
+   if (NBS_DEBUG)
+   printk(ext3_new_block: first block allocated:block %d,num 
%d\n, goal, num);
+   while (num  *count  goal  end
+ext3_test_allocatable(goal, bitmap_bh)
+claim_block(sb_bgl_lock(EXT3_SB(sb), group), goal, 
bitmap_bh)) {
+   num++;
+   goal++;
+   }
+   *count = num;
+   if (NBS_DEBUG)
+   printk(ext3_new_block: additional block allocated:block %d,num 
%d,goal-num %d\n, goal, num, goal-num);
+   return goal - num;
 fail_access:
+   *count = num;
return -1;
 }
 
@@ -998,6 +1015,28 @@ retry:
goto retry;
 }
 
+static void try_to_extend_reservation(struct ext3_reserve_window_node *my_rsv,
+   struct super_block *sb, int size)
+{
+   struct ext3_reserve_window_node *next_rsv;
+   struct rb_node *next;
+   spinlock_t *rsv_lock = EXT3_SB(sb)-s_rsv_window_lock;
+
+   spin_lock(rsv_lock);
+   next = rb_next(my_rsv-rsv_node);
+
+   if (!next)
+   my_rsv-rsv_end += size;
+   else {
+   next_rsv = list_entry(next, struct ext3_reserve_window_node, 
rsv_node);
+
+   if ((next_rsv-rsv_start - my_rsv-rsv_end)  size)
+   my_rsv-rsv_end += size;
+   else
+   my_rsv-rsv_end = next_rsv-rsv_start -1 ;
+   }
+   spin_unlock(rsv_lock);
+}
 /*
  * This is the main function used to allocate a new block and its reservation
  * window.
@@ -1023,11 +1062,12 @@ static int
 ext3_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle,
unsigned int group, struct buffer_head *bitmap_bh,
int goal, struct ext3_reserve_window_node * my_rsv,
-   int *errp)
+   unsigned long *count, int *errp)
 {
unsigned long group_first_block;
int ret = 0;
int fatal;
+   unsigned long num = *count;
 
*errp = 0;
 
@@ -1050,7 +1090,8 @@ ext3_try_to_allocate_with_rsv(struct sup
 * or last attempt to allocate a block with reservation turned on failed
 */
if (my_rsv == NULL ) {
-   ret = ext3_try_to_allocate(sb, handle, group, bitmap_bh, goal, 
NULL);
+   ret = ext3_try_to_allocate(sb, handle, group, bitmap_bh, goal,
+   count, NULL);
goto out;
}
/*
@@ -1080,6 +1121,10 @@ ext3_try_to_allocate_with_rsv(struct sup
while (1) {
if (rsv_is_empty(my_rsv-rsv_window) || (ret  0) ||