diff options
Diffstat (limited to 'fs/btrfs/volumes.c')
-rw-r--r-- | fs/btrfs/volumes.c | 63 |
1 files changed, 39 insertions, 24 deletions
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 88e2fe931bde..7c84a8122c37 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
@@ -1116,15 +1116,18 @@ out: | |||
1116 | return ret; | 1116 | return ret; |
1117 | } | 1117 | } |
1118 | 1118 | ||
1119 | static int contains_pending_extent(struct btrfs_trans_handle *trans, | 1119 | static int contains_pending_extent(struct btrfs_transaction *transaction, |
1120 | struct btrfs_device *device, | 1120 | struct btrfs_device *device, |
1121 | u64 *start, u64 len) | 1121 | u64 *start, u64 len) |
1122 | { | 1122 | { |
1123 | struct btrfs_fs_info *fs_info = device->dev_root->fs_info; | ||
1123 | struct extent_map *em; | 1124 | struct extent_map *em; |
1124 | struct list_head *search_list = &trans->transaction->pending_chunks; | 1125 | struct list_head *search_list = &fs_info->pinned_chunks; |
1125 | int ret = 0; | 1126 | int ret = 0; |
1126 | u64 physical_start = *start; | 1127 | u64 physical_start = *start; |
1127 | 1128 | ||
1129 | if (transaction) | ||
1130 | search_list = &transaction->pending_chunks; | ||
1128 | again: | 1131 | again: |
1129 | list_for_each_entry(em, search_list, list) { | 1132 | list_for_each_entry(em, search_list, list) { |
1130 | struct map_lookup *map; | 1133 | struct map_lookup *map; |
@@ -1159,8 +1162,8 @@ again: | |||
1159 | } | 1162 | } |
1160 | } | 1163 | } |
1161 | } | 1164 | } |
1162 | if (search_list == &trans->transaction->pending_chunks) { | 1165 | if (search_list != &fs_info->pinned_chunks) { |
1163 | search_list = &trans->root->fs_info->pinned_chunks; | 1166 | search_list = &fs_info->pinned_chunks; |
1164 | goto again; | 1167 | goto again; |
1165 | } | 1168 | } |
1166 | 1169 | ||
@@ -1169,12 +1172,13 @@ again: | |||
1169 | 1172 | ||
1170 | 1173 | ||
1171 | /* | 1174 | /* |
1172 | * find_free_dev_extent - find free space in the specified device | 1175 | * find_free_dev_extent_start - find free space in the specified device |
1173 | * @device: the device which we search the free space in | 1176 | * @device: the device which we search the free space in |
1174 | * @num_bytes: the size of the free space that we need | 1177 | * @num_bytes: the size of the free space that we need |
1175 | * @start: store the start of the free space. | 1178 | * @search_start: the position from which to begin the search |
1176 | * @len: the size of the free space. that we find, or the size of the max | 1179 | * @start: store the start of the free space. |
1177 | * free space if we don't find suitable free space | 1180 | * @len: the size of the free space. that we find, or the size |
1181 | * of the max free space if we don't find suitable free space | ||
1178 | * | 1182 | * |
1179 | * this uses a pretty simple search, the expectation is that it is | 1183 | * this uses a pretty simple search, the expectation is that it is |
1180 | * called very infrequently and that a given device has a small number | 1184 | * called very infrequently and that a given device has a small number |
@@ -1188,9 +1192,9 @@ again: | |||
1188 | * But if we don't find suitable free space, it is used to store the size of | 1192 | * But if we don't find suitable free space, it is used to store the size of |
1189 | * the max free space. | 1193 | * the max free space. |
1190 | */ | 1194 | */ |
1191 | int find_free_dev_extent(struct btrfs_trans_handle *trans, | 1195 | int find_free_dev_extent_start(struct btrfs_transaction *transaction, |
1192 | struct btrfs_device *device, u64 num_bytes, | 1196 | struct btrfs_device *device, u64 num_bytes, |
1193 | u64 *start, u64 *len) | 1197 | u64 search_start, u64 *start, u64 *len) |
1194 | { | 1198 | { |
1195 | struct btrfs_key key; | 1199 | struct btrfs_key key; |
1196 | struct btrfs_root *root = device->dev_root; | 1200 | struct btrfs_root *root = device->dev_root; |
@@ -1200,19 +1204,11 @@ int find_free_dev_extent(struct btrfs_trans_handle *trans, | |||
1200 | u64 max_hole_start; | 1204 | u64 max_hole_start; |
1201 | u64 max_hole_size; | 1205 | u64 max_hole_size; |
1202 | u64 extent_end; | 1206 | u64 extent_end; |
1203 | u64 search_start; | ||
1204 | u64 search_end = device->total_bytes; | 1207 | u64 search_end = device->total_bytes; |
1205 | int ret; | 1208 | int ret; |
1206 | int slot; | 1209 | int slot; |
1207 | struct extent_buffer *l; | 1210 | struct extent_buffer *l; |
1208 | 1211 | ||
1209 | /* FIXME use last free of some kind */ | ||
1210 | |||
1211 | /* we don't want to overwrite the superblock on the drive, | ||
1212 | * so we make sure to start at an offset of at least 1MB | ||
1213 | */ | ||
1214 | search_start = max(root->fs_info->alloc_start, 1024ull * 1024); | ||
1215 | |||
1216 | path = btrfs_alloc_path(); | 1212 | path = btrfs_alloc_path(); |
1217 | if (!path) | 1213 | if (!path) |
1218 | return -ENOMEM; | 1214 | return -ENOMEM; |
@@ -1273,7 +1269,7 @@ again: | |||
1273 | * Have to check before we set max_hole_start, otherwise | 1269 | * Have to check before we set max_hole_start, otherwise |
1274 | * we could end up sending back this offset anyway. | 1270 | * we could end up sending back this offset anyway. |
1275 | */ | 1271 | */ |
1276 | if (contains_pending_extent(trans, device, | 1272 | if (contains_pending_extent(transaction, device, |
1277 | &search_start, | 1273 | &search_start, |
1278 | hole_size)) { | 1274 | hole_size)) { |
1279 | if (key.offset >= search_start) { | 1275 | if (key.offset >= search_start) { |
@@ -1322,7 +1318,7 @@ next: | |||
1322 | if (search_end > search_start) { | 1318 | if (search_end > search_start) { |
1323 | hole_size = search_end - search_start; | 1319 | hole_size = search_end - search_start; |
1324 | 1320 | ||
1325 | if (contains_pending_extent(trans, device, &search_start, | 1321 | if (contains_pending_extent(transaction, device, &search_start, |
1326 | hole_size)) { | 1322 | hole_size)) { |
1327 | btrfs_release_path(path); | 1323 | btrfs_release_path(path); |
1328 | goto again; | 1324 | goto again; |
@@ -1348,6 +1344,24 @@ out: | |||
1348 | return ret; | 1344 | return ret; |
1349 | } | 1345 | } |
1350 | 1346 | ||
1347 | int find_free_dev_extent(struct btrfs_trans_handle *trans, | ||
1348 | struct btrfs_device *device, u64 num_bytes, | ||
1349 | u64 *start, u64 *len) | ||
1350 | { | ||
1351 | struct btrfs_root *root = device->dev_root; | ||
1352 | u64 search_start; | ||
1353 | |||
1354 | /* FIXME use last free of some kind */ | ||
1355 | |||
1356 | /* | ||
1357 | * we don't want to overwrite the superblock on the drive, | ||
1358 | * so we make sure to start at an offset of at least 1MB | ||
1359 | */ | ||
1360 | search_start = max(root->fs_info->alloc_start, 1024ull * 1024); | ||
1361 | return find_free_dev_extent_start(trans->transaction, device, | ||
1362 | num_bytes, search_start, start, len); | ||
1363 | } | ||
1364 | |||
1351 | static int btrfs_free_dev_extent(struct btrfs_trans_handle *trans, | 1365 | static int btrfs_free_dev_extent(struct btrfs_trans_handle *trans, |
1352 | struct btrfs_device *device, | 1366 | struct btrfs_device *device, |
1353 | u64 start, u64 *dev_extent_len) | 1367 | u64 start, u64 *dev_extent_len) |
@@ -4196,7 +4210,8 @@ again: | |||
4196 | u64 start = new_size; | 4210 | u64 start = new_size; |
4197 | u64 len = old_size - new_size; | 4211 | u64 len = old_size - new_size; |
4198 | 4212 | ||
4199 | if (contains_pending_extent(trans, device, &start, len)) { | 4213 | if (contains_pending_extent(trans->transaction, device, |
4214 | &start, len)) { | ||
4200 | unlock_chunks(root); | 4215 | unlock_chunks(root); |
4201 | checked_pending_chunks = true; | 4216 | checked_pending_chunks = true; |
4202 | failed = 0; | 4217 | failed = 0; |