diff options
Diffstat (limited to 'fs/ext3')
-rw-r--r-- | fs/ext3/balloc.c | 32 |
1 files changed, 31 insertions, 1 deletions
diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c index 7a2c7198b059..77927d6938f6 100644 --- a/fs/ext3/balloc.c +++ b/fs/ext3/balloc.c | |||
@@ -1011,6 +1011,31 @@ retry: | |||
1011 | goto retry; | 1011 | goto retry; |
1012 | } | 1012 | } |
1013 | 1013 | ||
1014 | static void try_to_extend_reservation(struct ext3_reserve_window_node *my_rsv, | ||
1015 | struct super_block *sb, int size) | ||
1016 | { | ||
1017 | struct ext3_reserve_window_node *next_rsv; | ||
1018 | struct rb_node *next; | ||
1019 | spinlock_t *rsv_lock = &EXT3_SB(sb)->s_rsv_window_lock; | ||
1020 | |||
1021 | if (!spin_trylock(rsv_lock)) | ||
1022 | return; | ||
1023 | |||
1024 | next = rb_next(&my_rsv->rsv_node); | ||
1025 | |||
1026 | if (!next) | ||
1027 | my_rsv->rsv_end += size; | ||
1028 | else { | ||
1029 | next_rsv = list_entry(next, struct ext3_reserve_window_node, rsv_node); | ||
1030 | |||
1031 | if ((next_rsv->rsv_start - my_rsv->rsv_end - 1) >= size) | ||
1032 | my_rsv->rsv_end += size; | ||
1033 | else | ||
1034 | my_rsv->rsv_end = next_rsv->rsv_start - 1; | ||
1035 | } | ||
1036 | spin_unlock(rsv_lock); | ||
1037 | } | ||
1038 | |||
1014 | /* | 1039 | /* |
1015 | * This is the main function used to allocate a new block and its reservation | 1040 | * This is the main function used to allocate a new block and its reservation |
1016 | * window. | 1041 | * window. |
@@ -1095,6 +1120,8 @@ ext3_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle, | |||
1095 | while (1) { | 1120 | while (1) { |
1096 | if (rsv_is_empty(&my_rsv->rsv_window) || (ret < 0) || | 1121 | if (rsv_is_empty(&my_rsv->rsv_window) || (ret < 0) || |
1097 | !goal_in_my_reservation(&my_rsv->rsv_window, goal, group, sb)) { | 1122 | !goal_in_my_reservation(&my_rsv->rsv_window, goal, group, sb)) { |
1123 | if (my_rsv->rsv_goal_size < *count) | ||
1124 | my_rsv->rsv_goal_size = *count; | ||
1098 | ret = alloc_new_reservation(my_rsv, goal, sb, | 1125 | ret = alloc_new_reservation(my_rsv, goal, sb, |
1099 | group, bitmap_bh); | 1126 | group, bitmap_bh); |
1100 | if (ret < 0) | 1127 | if (ret < 0) |
@@ -1102,7 +1129,10 @@ ext3_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle, | |||
1102 | 1129 | ||
1103 | if (!goal_in_my_reservation(&my_rsv->rsv_window, goal, group, sb)) | 1130 | if (!goal_in_my_reservation(&my_rsv->rsv_window, goal, group, sb)) |
1104 | goal = -1; | 1131 | goal = -1; |
1105 | } | 1132 | } else if (goal > 0 && (my_rsv->rsv_end-goal+1) < *count) |
1133 | try_to_extend_reservation(my_rsv, sb, | ||
1134 | *count-my_rsv->rsv_end + goal - 1); | ||
1135 | |||
1106 | if ((my_rsv->rsv_start >= group_first_block + EXT3_BLOCKS_PER_GROUP(sb)) | 1136 | if ((my_rsv->rsv_start >= group_first_block + EXT3_BLOCKS_PER_GROUP(sb)) |
1107 | || (my_rsv->rsv_end < group_first_block)) | 1137 | || (my_rsv->rsv_end < group_first_block)) |
1108 | BUG(); | 1138 | BUG(); |