diff options
-rw-r--r-- | fs/ext3/balloc.c | 46 | ||||
-rw-r--r-- | include/linux/ext3_fs.h | 5 |
2 files changed, 40 insertions, 11 deletions
diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c index 46623f77666b..bba4aeb4a708 100644 --- a/fs/ext3/balloc.c +++ b/fs/ext3/balloc.c | |||
@@ -653,9 +653,11 @@ claim_block(spinlock_t *lock, int block, struct buffer_head *bh) | |||
653 | */ | 653 | */ |
654 | static int | 654 | static int |
655 | ext3_try_to_allocate(struct super_block *sb, handle_t *handle, int group, | 655 | ext3_try_to_allocate(struct super_block *sb, handle_t *handle, int group, |
656 | struct buffer_head *bitmap_bh, int goal, struct ext3_reserve_window *my_rsv) | 656 | struct buffer_head *bitmap_bh, int goal, |
657 | unsigned long *count, struct ext3_reserve_window *my_rsv) | ||
657 | { | 658 | { |
658 | int group_first_block, start, end; | 659 | int group_first_block, start, end; |
660 | unsigned long num = 0; | ||
659 | 661 | ||
660 | /* we do allocation within the reservation window if we have a window */ | 662 | /* we do allocation within the reservation window if we have a window */ |
661 | if (my_rsv) { | 663 | if (my_rsv) { |
@@ -713,8 +715,18 @@ repeat: | |||
713 | goto fail_access; | 715 | goto fail_access; |
714 | goto repeat; | 716 | goto repeat; |
715 | } | 717 | } |
716 | return goal; | 718 | num++; |
719 | goal++; | ||
720 | while (num < *count && goal < end | ||
721 | && ext3_test_allocatable(goal, bitmap_bh) | ||
722 | && claim_block(sb_bgl_lock(EXT3_SB(sb), group), goal, bitmap_bh)) { | ||
723 | num++; | ||
724 | goal++; | ||
725 | } | ||
726 | *count = num; | ||
727 | return goal - num; | ||
717 | fail_access: | 728 | fail_access: |
729 | *count = num; | ||
718 | return -1; | 730 | return -1; |
719 | } | 731 | } |
720 | 732 | ||
@@ -1024,11 +1036,12 @@ static int | |||
1024 | ext3_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle, | 1036 | ext3_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle, |
1025 | unsigned int group, struct buffer_head *bitmap_bh, | 1037 | unsigned int group, struct buffer_head *bitmap_bh, |
1026 | int goal, struct ext3_reserve_window_node * my_rsv, | 1038 | int goal, struct ext3_reserve_window_node * my_rsv, |
1027 | int *errp) | 1039 | unsigned long *count, int *errp) |
1028 | { | 1040 | { |
1029 | unsigned long group_first_block; | 1041 | unsigned long group_first_block; |
1030 | int ret = 0; | 1042 | int ret = 0; |
1031 | int fatal; | 1043 | int fatal; |
1044 | unsigned long num = *count; | ||
1032 | 1045 | ||
1033 | *errp = 0; | 1046 | *errp = 0; |
1034 | 1047 | ||
@@ -1051,7 +1064,8 @@ ext3_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle, | |||
1051 | * or last attempt to allocate a block with reservation turned on failed | 1064 | * or last attempt to allocate a block with reservation turned on failed |
1052 | */ | 1065 | */ |
1053 | if (my_rsv == NULL ) { | 1066 | if (my_rsv == NULL ) { |
1054 | ret = ext3_try_to_allocate(sb, handle, group, bitmap_bh, goal, NULL); | 1067 | ret = ext3_try_to_allocate(sb, handle, group, bitmap_bh, |
1068 | goal, count, NULL); | ||
1055 | goto out; | 1069 | goto out; |
1056 | } | 1070 | } |
1057 | /* | 1071 | /* |
@@ -1093,11 +1107,13 @@ ext3_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle, | |||
1093 | || (my_rsv->rsv_end < group_first_block)) | 1107 | || (my_rsv->rsv_end < group_first_block)) |
1094 | BUG(); | 1108 | BUG(); |
1095 | ret = ext3_try_to_allocate(sb, handle, group, bitmap_bh, goal, | 1109 | ret = ext3_try_to_allocate(sb, handle, group, bitmap_bh, goal, |
1096 | &my_rsv->rsv_window); | 1110 | &num, &my_rsv->rsv_window); |
1097 | if (ret >= 0) { | 1111 | if (ret >= 0) { |
1098 | my_rsv->rsv_alloc_hit++; | 1112 | my_rsv->rsv_alloc_hit += num; |
1113 | *count = num; | ||
1099 | break; /* succeed */ | 1114 | break; /* succeed */ |
1100 | } | 1115 | } |
1116 | num = *count; | ||
1101 | } | 1117 | } |
1102 | out: | 1118 | out: |
1103 | if (ret >= 0) { | 1119 | if (ret >= 0) { |
@@ -1154,8 +1170,8 @@ int ext3_should_retry_alloc(struct super_block *sb, int *retries) | |||
1154 | * bitmap, and then for any free bit if that fails. | 1170 | * bitmap, and then for any free bit if that fails. |
1155 | * This function also updates quota and i_blocks field. | 1171 | * This function also updates quota and i_blocks field. |
1156 | */ | 1172 | */ |
1157 | int ext3_new_block(handle_t *handle, struct inode *inode, | 1173 | int ext3_new_blocks(handle_t *handle, struct inode *inode, |
1158 | unsigned long goal, int *errp) | 1174 | unsigned long goal, unsigned long *count, int *errp) |
1159 | { | 1175 | { |
1160 | struct buffer_head *bitmap_bh = NULL; | 1176 | struct buffer_head *bitmap_bh = NULL; |
1161 | struct buffer_head *gdp_bh; | 1177 | struct buffer_head *gdp_bh; |
@@ -1178,6 +1194,7 @@ int ext3_new_block(handle_t *handle, struct inode *inode, | |||
1178 | static int goal_hits, goal_attempts; | 1194 | static int goal_hits, goal_attempts; |
1179 | #endif | 1195 | #endif |
1180 | unsigned long ngroups; | 1196 | unsigned long ngroups; |
1197 | unsigned long num = *count; | ||
1181 | 1198 | ||
1182 | *errp = -ENOSPC; | 1199 | *errp = -ENOSPC; |
1183 | sb = inode->i_sb; | 1200 | sb = inode->i_sb; |
@@ -1244,7 +1261,7 @@ retry: | |||
1244 | if (!bitmap_bh) | 1261 | if (!bitmap_bh) |
1245 | goto io_error; | 1262 | goto io_error; |
1246 | ret_block = ext3_try_to_allocate_with_rsv(sb, handle, group_no, | 1263 | ret_block = ext3_try_to_allocate_with_rsv(sb, handle, group_no, |
1247 | bitmap_bh, ret_block, my_rsv, &fatal); | 1264 | bitmap_bh, ret_block, my_rsv, &num, &fatal); |
1248 | if (fatal) | 1265 | if (fatal) |
1249 | goto out; | 1266 | goto out; |
1250 | if (ret_block >= 0) | 1267 | if (ret_block >= 0) |
@@ -1281,7 +1298,7 @@ retry: | |||
1281 | if (!bitmap_bh) | 1298 | if (!bitmap_bh) |
1282 | goto io_error; | 1299 | goto io_error; |
1283 | ret_block = ext3_try_to_allocate_with_rsv(sb, handle, group_no, | 1300 | ret_block = ext3_try_to_allocate_with_rsv(sb, handle, group_no, |
1284 | bitmap_bh, -1, my_rsv, &fatal); | 1301 | bitmap_bh, -1, my_rsv, &num, &fatal); |
1285 | if (fatal) | 1302 | if (fatal) |
1286 | goto out; | 1303 | goto out; |
1287 | if (ret_block >= 0) | 1304 | if (ret_block >= 0) |
@@ -1388,6 +1405,7 @@ allocated: | |||
1388 | 1405 | ||
1389 | *errp = 0; | 1406 | *errp = 0; |
1390 | brelse(bitmap_bh); | 1407 | brelse(bitmap_bh); |
1408 | *count = num; | ||
1391 | return ret_block; | 1409 | return ret_block; |
1392 | 1410 | ||
1393 | io_error: | 1411 | io_error: |
@@ -1406,6 +1424,14 @@ out: | |||
1406 | return 0; | 1424 | return 0; |
1407 | } | 1425 | } |
1408 | 1426 | ||
1427 | int ext3_new_block(handle_t *handle, struct inode *inode, | ||
1428 | unsigned long goal, int *errp) | ||
1429 | { | ||
1430 | unsigned long count = 1; | ||
1431 | |||
1432 | return ext3_new_blocks(handle, inode, goal, &count, errp); | ||
1433 | } | ||
1434 | |||
1409 | unsigned long ext3_count_free_blocks(struct super_block *sb) | 1435 | unsigned long ext3_count_free_blocks(struct super_block *sb) |
1410 | { | 1436 | { |
1411 | unsigned long desc_count; | 1437 | unsigned long desc_count; |
diff --git a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h index 0adadd85fa66..8bb4f842cded 100644 --- a/include/linux/ext3_fs.h +++ b/include/linux/ext3_fs.h | |||
@@ -36,7 +36,8 @@ struct statfs; | |||
36 | * Define EXT3_RESERVATION to reserve data blocks for expanding files | 36 | * Define EXT3_RESERVATION to reserve data blocks for expanding files |
37 | */ | 37 | */ |
38 | #define EXT3_DEFAULT_RESERVE_BLOCKS 8 | 38 | #define EXT3_DEFAULT_RESERVE_BLOCKS 8 |
39 | #define EXT3_MAX_RESERVE_BLOCKS 1024 | 39 | /*max window size: 1024(direct blocks) + 3([t,d]indirect blocks) */ |
40 | #define EXT3_MAX_RESERVE_BLOCKS 1027 | ||
40 | #define EXT3_RESERVE_WINDOW_NOT_ALLOCATED 0 | 41 | #define EXT3_RESERVE_WINDOW_NOT_ALLOCATED 0 |
41 | /* | 42 | /* |
42 | * Always enable hashed directories | 43 | * Always enable hashed directories |
@@ -732,6 +733,8 @@ struct dir_private_info { | |||
732 | extern int ext3_bg_has_super(struct super_block *sb, int group); | 733 | extern int ext3_bg_has_super(struct super_block *sb, int group); |
733 | extern unsigned long ext3_bg_num_gdb(struct super_block *sb, int group); | 734 | extern unsigned long ext3_bg_num_gdb(struct super_block *sb, int group); |
734 | extern int ext3_new_block (handle_t *, struct inode *, unsigned long, int *); | 735 | extern int ext3_new_block (handle_t *, struct inode *, unsigned long, int *); |
736 | extern int ext3_new_blocks (handle_t *, struct inode *, unsigned long, | ||
737 | unsigned long *, int *); | ||
735 | extern void ext3_free_blocks (handle_t *, struct inode *, unsigned long, | 738 | extern void ext3_free_blocks (handle_t *, struct inode *, unsigned long, |
736 | unsigned long); | 739 | unsigned long); |
737 | extern void ext3_free_blocks_sb (handle_t *, struct super_block *, | 740 | extern void ext3_free_blocks_sb (handle_t *, struct super_block *, |