diff options
Diffstat (limited to 'fs/ext3/balloc.c')
| -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(); |
