Commit b54e41ec authored by Mingming Cao's avatar Mingming Cao Committed by Linus Torvalds

[PATCH] ext3_get_blocks: support multiple blocks allocation in ext3_new_block()

Change ext3_try_to_allocate() (called via ext3_new_blocks()) to try to
allocate the requested number of blocks on a best effort basis: After
allocated the first block, it will always attempt to allocate the next few(up
to the requested size and not beyond the reservation window) adjacent blocks
at the same time.
Signed-off-by: default avatarMingming Cao <cmm@us.ibm.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent b47b2478
...@@ -653,9 +653,11 @@ claim_block(spinlock_t *lock, int block, struct buffer_head *bh) ...@@ -653,9 +653,11 @@ claim_block(spinlock_t *lock, int block, struct buffer_head *bh)
*/ */
static int static int
ext3_try_to_allocate(struct super_block *sb, handle_t *handle, int group, 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; int group_first_block, start, end;
unsigned long num = 0;
/* we do allocation within the reservation window if we have a window */ /* we do allocation within the reservation window if we have a window */
if (my_rsv) { if (my_rsv) {
...@@ -713,8 +715,18 @@ repeat: ...@@ -713,8 +715,18 @@ repeat:
goto fail_access; goto fail_access;
goto repeat; goto repeat;
} }
return goal; num++;
goal++;
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;
return goal - num;
fail_access: fail_access:
*count = num;
return -1; return -1;
} }
...@@ -1024,11 +1036,12 @@ static int ...@@ -1024,11 +1036,12 @@ static int
ext3_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle, ext3_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle,
unsigned int group, struct buffer_head *bitmap_bh, unsigned int group, struct buffer_head *bitmap_bh,
int goal, struct ext3_reserve_window_node * my_rsv, int goal, struct ext3_reserve_window_node * my_rsv,
int *errp) unsigned long *count, int *errp)
{ {
unsigned long group_first_block; unsigned long group_first_block;
int ret = 0; int ret = 0;
int fatal; int fatal;
unsigned long num = *count;
*errp = 0; *errp = 0;
...@@ -1051,7 +1064,8 @@ ext3_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle, ...@@ -1051,7 +1064,8 @@ ext3_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle,
* or last attempt to allocate a block with reservation turned on failed * or last attempt to allocate a block with reservation turned on failed
*/ */
if (my_rsv == NULL ) { 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; goto out;
} }
/* /*
...@@ -1093,11 +1107,13 @@ ext3_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle, ...@@ -1093,11 +1107,13 @@ ext3_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle,
|| (my_rsv->rsv_end < group_first_block)) || (my_rsv->rsv_end < group_first_block))
BUG(); BUG();
ret = ext3_try_to_allocate(sb, handle, group, bitmap_bh, goal, ret = ext3_try_to_allocate(sb, handle, group, bitmap_bh, goal,
&my_rsv->rsv_window); &num, &my_rsv->rsv_window);
if (ret >= 0) { if (ret >= 0) {
my_rsv->rsv_alloc_hit++; my_rsv->rsv_alloc_hit += num;
*count = num;
break; /* succeed */ break; /* succeed */
} }
num = *count;
} }
out: out:
if (ret >= 0) { if (ret >= 0) {
...@@ -1154,8 +1170,8 @@ int ext3_should_retry_alloc(struct super_block *sb, int *retries) ...@@ -1154,8 +1170,8 @@ int ext3_should_retry_alloc(struct super_block *sb, int *retries)
* bitmap, and then for any free bit if that fails. * bitmap, and then for any free bit if that fails.
* This function also updates quota and i_blocks field. * This function also updates quota and i_blocks field.
*/ */
int ext3_new_block(handle_t *handle, struct inode *inode, int ext3_new_blocks(handle_t *handle, struct inode *inode,
unsigned long goal, int *errp) unsigned long goal, unsigned long *count, int *errp)
{ {
struct buffer_head *bitmap_bh = NULL; struct buffer_head *bitmap_bh = NULL;
struct buffer_head *gdp_bh; struct buffer_head *gdp_bh;
...@@ -1178,6 +1194,7 @@ int ext3_new_block(handle_t *handle, struct inode *inode, ...@@ -1178,6 +1194,7 @@ int ext3_new_block(handle_t *handle, struct inode *inode,
static int goal_hits, goal_attempts; static int goal_hits, goal_attempts;
#endif #endif
unsigned long ngroups; unsigned long ngroups;
unsigned long num = *count;
*errp = -ENOSPC; *errp = -ENOSPC;
sb = inode->i_sb; sb = inode->i_sb;
...@@ -1244,7 +1261,7 @@ retry: ...@@ -1244,7 +1261,7 @@ retry:
if (!bitmap_bh) if (!bitmap_bh)
goto io_error; goto io_error;
ret_block = ext3_try_to_allocate_with_rsv(sb, handle, group_no, ret_block = ext3_try_to_allocate_with_rsv(sb, handle, group_no,
bitmap_bh, ret_block, my_rsv, &fatal); bitmap_bh, ret_block, my_rsv, &num, &fatal);
if (fatal) if (fatal)
goto out; goto out;
if (ret_block >= 0) if (ret_block >= 0)
...@@ -1281,7 +1298,7 @@ retry: ...@@ -1281,7 +1298,7 @@ retry:
if (!bitmap_bh) if (!bitmap_bh)
goto io_error; goto io_error;
ret_block = ext3_try_to_allocate_with_rsv(sb, handle, group_no, ret_block = ext3_try_to_allocate_with_rsv(sb, handle, group_no,
bitmap_bh, -1, my_rsv, &fatal); bitmap_bh, -1, my_rsv, &num, &fatal);
if (fatal) if (fatal)
goto out; goto out;
if (ret_block >= 0) if (ret_block >= 0)
...@@ -1388,6 +1405,7 @@ allocated: ...@@ -1388,6 +1405,7 @@ allocated:
*errp = 0; *errp = 0;
brelse(bitmap_bh); brelse(bitmap_bh);
*count = num;
return ret_block; return ret_block;
io_error: io_error:
...@@ -1406,6 +1424,14 @@ out: ...@@ -1406,6 +1424,14 @@ out:
return 0; return 0;
} }
int ext3_new_block(handle_t *handle, struct inode *inode,
unsigned long goal, int *errp)
{
unsigned long count = 1;
return ext3_new_blocks(handle, inode, goal, &count, errp);
}
unsigned long ext3_count_free_blocks(struct super_block *sb) unsigned long ext3_count_free_blocks(struct super_block *sb)
{ {
unsigned long desc_count; unsigned long desc_count;
......
...@@ -36,7 +36,8 @@ struct statfs; ...@@ -36,7 +36,8 @@ struct statfs;
* Define EXT3_RESERVATION to reserve data blocks for expanding files * Define EXT3_RESERVATION to reserve data blocks for expanding files
*/ */
#define EXT3_DEFAULT_RESERVE_BLOCKS 8 #define EXT3_DEFAULT_RESERVE_BLOCKS 8
#define EXT3_MAX_RESERVE_BLOCKS 1024 /*max window size: 1024(direct blocks) + 3([t,d]indirect blocks) */
#define EXT3_MAX_RESERVE_BLOCKS 1027
#define EXT3_RESERVE_WINDOW_NOT_ALLOCATED 0 #define EXT3_RESERVE_WINDOW_NOT_ALLOCATED 0
/* /*
* Always enable hashed directories * Always enable hashed directories
...@@ -732,6 +733,8 @@ struct dir_private_info { ...@@ -732,6 +733,8 @@ struct dir_private_info {
extern int ext3_bg_has_super(struct super_block *sb, int group); extern int ext3_bg_has_super(struct super_block *sb, int group);
extern unsigned long ext3_bg_num_gdb(struct super_block *sb, int group); extern unsigned long ext3_bg_num_gdb(struct super_block *sb, int group);
extern int ext3_new_block (handle_t *, struct inode *, unsigned long, int *); extern int ext3_new_block (handle_t *, struct inode *, unsigned long, int *);
extern int ext3_new_blocks (handle_t *, struct inode *, unsigned long,
unsigned long *, int *);
extern void ext3_free_blocks (handle_t *, struct inode *, unsigned long, extern void ext3_free_blocks (handle_t *, struct inode *, unsigned long,
unsigned long); unsigned long);
extern void ext3_free_blocks_sb (handle_t *, struct super_block *, extern void ext3_free_blocks_sb (handle_t *, struct super_block *,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment