aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/extent-tree.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r--fs/btrfs/extent-tree.c71
1 files changed, 42 insertions, 29 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 7527523c2d2d..376656f65b33 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -1323,8 +1323,25 @@ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans,
1323int btrfs_extent_post_op(struct btrfs_trans_handle *trans, 1323int btrfs_extent_post_op(struct btrfs_trans_handle *trans,
1324 struct btrfs_root *root) 1324 struct btrfs_root *root)
1325{ 1325{
1326 finish_current_insert(trans, root->fs_info->extent_root, 1); 1326 u64 start;
1327 del_pending_extents(trans, root->fs_info->extent_root, 1); 1327 u64 end;
1328 int ret;
1329
1330 while(1) {
1331 finish_current_insert(trans, root->fs_info->extent_root, 1);
1332 del_pending_extents(trans, root->fs_info->extent_root, 1);
1333
1334 /* is there more work to do? */
1335 ret = find_first_extent_bit(&root->fs_info->pending_del,
1336 0, &start, &end, EXTENT_WRITEBACK);
1337 if (!ret)
1338 continue;
1339 ret = find_first_extent_bit(&root->fs_info->extent_ins,
1340 0, &start, &end, EXTENT_WRITEBACK);
1341 if (!ret)
1342 continue;
1343 break;
1344 }
1328 return 0; 1345 return 0;
1329} 1346}
1330 1347
@@ -2211,13 +2228,12 @@ static int finish_current_insert(struct btrfs_trans_handle *trans,
2211 u64 end; 2228 u64 end;
2212 u64 priv; 2229 u64 priv;
2213 u64 search = 0; 2230 u64 search = 0;
2214 u64 skipped = 0;
2215 struct btrfs_fs_info *info = extent_root->fs_info; 2231 struct btrfs_fs_info *info = extent_root->fs_info;
2216 struct btrfs_path *path; 2232 struct btrfs_path *path;
2217 struct pending_extent_op *extent_op, *tmp; 2233 struct pending_extent_op *extent_op, *tmp;
2218 struct list_head insert_list, update_list; 2234 struct list_head insert_list, update_list;
2219 int ret; 2235 int ret;
2220 int num_inserts = 0, max_inserts; 2236 int num_inserts = 0, max_inserts, restart = 0;
2221 2237
2222 path = btrfs_alloc_path(); 2238 path = btrfs_alloc_path();
2223 INIT_LIST_HEAD(&insert_list); 2239 INIT_LIST_HEAD(&insert_list);
@@ -2233,19 +2249,19 @@ again:
2233 ret = find_first_extent_bit(&info->extent_ins, search, &start, 2249 ret = find_first_extent_bit(&info->extent_ins, search, &start,
2234 &end, EXTENT_WRITEBACK); 2250 &end, EXTENT_WRITEBACK);
2235 if (ret) { 2251 if (ret) {
2236 if (skipped && all && !num_inserts && 2252 if (restart && !num_inserts &&
2237 list_empty(&update_list)) { 2253 list_empty(&update_list)) {
2238 skipped = 0; 2254 restart = 0;
2239 search = 0; 2255 search = 0;
2240 continue; 2256 continue;
2241 } 2257 }
2242 mutex_unlock(&info->extent_ins_mutex);
2243 break; 2258 break;
2244 } 2259 }
2245 2260
2246 ret = try_lock_extent(&info->extent_ins, start, end, GFP_NOFS); 2261 ret = try_lock_extent(&info->extent_ins, start, end, GFP_NOFS);
2247 if (!ret) { 2262 if (!ret) {
2248 skipped = 1; 2263 if (all)
2264 restart = 1;
2249 search = end + 1; 2265 search = end + 1;
2250 if (need_resched()) { 2266 if (need_resched()) {
2251 mutex_unlock(&info->extent_ins_mutex); 2267 mutex_unlock(&info->extent_ins_mutex);
@@ -2264,7 +2280,7 @@ again:
2264 list_add_tail(&extent_op->list, &insert_list); 2280 list_add_tail(&extent_op->list, &insert_list);
2265 search = end + 1; 2281 search = end + 1;
2266 if (num_inserts == max_inserts) { 2282 if (num_inserts == max_inserts) {
2267 mutex_unlock(&info->extent_ins_mutex); 2283 restart = 1;
2268 break; 2284 break;
2269 } 2285 }
2270 } else if (extent_op->type == PENDING_BACKREF_UPDATE) { 2286 } else if (extent_op->type == PENDING_BACKREF_UPDATE) {
@@ -2280,7 +2296,6 @@ again:
2280 * somebody marked this thing for deletion then just unlock it and be 2296 * somebody marked this thing for deletion then just unlock it and be
2281 * done, the free_extents will handle it 2297 * done, the free_extents will handle it
2282 */ 2298 */
2283 mutex_lock(&info->extent_ins_mutex);
2284 list_for_each_entry_safe(extent_op, tmp, &update_list, list) { 2299 list_for_each_entry_safe(extent_op, tmp, &update_list, list) {
2285 clear_extent_bits(&info->extent_ins, extent_op->bytenr, 2300 clear_extent_bits(&info->extent_ins, extent_op->bytenr,
2286 extent_op->bytenr + extent_op->num_bytes - 1, 2301 extent_op->bytenr + extent_op->num_bytes - 1,
@@ -2302,6 +2317,10 @@ again:
2302 if (!list_empty(&update_list)) { 2317 if (!list_empty(&update_list)) {
2303 ret = update_backrefs(trans, extent_root, path, &update_list); 2318 ret = update_backrefs(trans, extent_root, path, &update_list);
2304 BUG_ON(ret); 2319 BUG_ON(ret);
2320
2321 /* we may have COW'ed new blocks, so lets start over */
2322 if (all)
2323 restart = 1;
2305 } 2324 }
2306 2325
2307 /* 2326 /*
@@ -2309,9 +2328,9 @@ again:
2309 * need to make sure everything is cleaned then reset everything and 2328 * need to make sure everything is cleaned then reset everything and
2310 * go back to the beginning 2329 * go back to the beginning
2311 */ 2330 */
2312 if (!num_inserts && all && skipped) { 2331 if (!num_inserts && restart) {
2313 search = 0; 2332 search = 0;
2314 skipped = 0; 2333 restart = 0;
2315 INIT_LIST_HEAD(&update_list); 2334 INIT_LIST_HEAD(&update_list);
2316 INIT_LIST_HEAD(&insert_list); 2335 INIT_LIST_HEAD(&insert_list);
2317 goto again; 2336 goto again;
@@ -2368,27 +2387,19 @@ again:
2368 BUG_ON(ret); 2387 BUG_ON(ret);
2369 2388
2370 /* 2389 /*
2371 * if we broke out of the loop in order to insert stuff because we hit 2390 * if restart is set for whatever reason we need to go back and start
2372 * the maximum number of inserts at a time we can handle, then loop 2391 * searching through the pending list again.
2373 * back and pick up where we left off 2392 *
2393 * We just inserted some extents, which could have resulted in new
2394 * blocks being allocated, which would result in new blocks needing
2395 * updates, so if all is set we _must_ restart to get the updated
2396 * blocks.
2374 */ 2397 */
2375 if (num_inserts == max_inserts) { 2398 if (restart || all) {
2376 INIT_LIST_HEAD(&insert_list);
2377 INIT_LIST_HEAD(&update_list);
2378 num_inserts = 0;
2379 goto again;
2380 }
2381
2382 /*
2383 * again, if we need to make absolutely sure there are no more pending
2384 * extent operations left and we know that we skipped some, go back to
2385 * the beginning and do it all again
2386 */
2387 if (all && skipped) {
2388 INIT_LIST_HEAD(&insert_list); 2399 INIT_LIST_HEAD(&insert_list);
2389 INIT_LIST_HEAD(&update_list); 2400 INIT_LIST_HEAD(&update_list);
2390 search = 0; 2401 search = 0;
2391 skipped = 0; 2402 restart = 0;
2392 num_inserts = 0; 2403 num_inserts = 0;
2393 goto again; 2404 goto again;
2394 } 2405 }
@@ -2709,6 +2720,8 @@ again:
2709 goto again; 2720 goto again;
2710 } 2721 }
2711 2722
2723 if (!err)
2724 finish_current_insert(trans, extent_root, 0);
2712 return err; 2725 return err;
2713} 2726}
2714 2727