diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-03-08 20:33:20 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-03-08 20:33:20 -0500 |
commit | 0aefda3e8188ad71168bd32152d41b3d72f04087 (patch) | |
tree | b0f57efd9dd5d7993ea9b3ff45842f5f1bd6d06c | |
parent | 2ef392042debb86003e3e1d756960a2e53930b60 (diff) | |
parent | de3cb945db4d8eb3b046dc7a5ea89a893372750c (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs
Pull btrfs fixes from Chris Mason:
"These are scattered fixes and one performance improvement. The
biggest functional change is in how we throttle metadata changes. The
new code bumps our average file creation rate up by ~13% in fs_mark,
and lowers CPU usage.
Stefan bisected out a regression in our allocation code that made
balance loop on extents larger than 256MB."
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs:
Btrfs: improve the delayed inode throttling
Btrfs: fix a mismerge in btrfs_balance()
Btrfs: enforce min_bytes parameter during extent allocation
Btrfs: allow running defrag in parallel to administrative tasks
Btrfs: avoid deadlock on transaction waiting list
Btrfs: do not BUG_ON on aborted situation
Btrfs: do not BUG_ON in prepare_to_reloc
Btrfs: free all recorded tree blocks on error
Btrfs: build up error handling for merge_reloc_roots
Btrfs: check for NULL pointer in updating reloc roots
Btrfs: fix unclosed transaction handler when the async transaction commitment fails
Btrfs: fix wrong handle at error path of create_snapshot() when the commit fails
Btrfs: use set_nlink if our i_nlink is 0
-rw-r--r-- | fs/btrfs/delayed-inode.c | 151 | ||||
-rw-r--r-- | fs/btrfs/delayed-inode.h | 2 | ||||
-rw-r--r-- | fs/btrfs/disk-io.c | 16 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 6 | ||||
-rw-r--r-- | fs/btrfs/ioctl.c | 18 | ||||
-rw-r--r-- | fs/btrfs/relocation.c | 74 | ||||
-rw-r--r-- | fs/btrfs/transaction.c | 65 | ||||
-rw-r--r-- | fs/btrfs/tree-log.c | 5 | ||||
-rw-r--r-- | fs/btrfs/volumes.c | 14 |
9 files changed, 221 insertions, 130 deletions
diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c index 0b278b117cbe..14fce27b4780 100644 --- a/fs/btrfs/delayed-inode.c +++ b/fs/btrfs/delayed-inode.c | |||
@@ -22,8 +22,9 @@ | |||
22 | #include "disk-io.h" | 22 | #include "disk-io.h" |
23 | #include "transaction.h" | 23 | #include "transaction.h" |
24 | 24 | ||
25 | #define BTRFS_DELAYED_WRITEBACK 400 | 25 | #define BTRFS_DELAYED_WRITEBACK 512 |
26 | #define BTRFS_DELAYED_BACKGROUND 100 | 26 | #define BTRFS_DELAYED_BACKGROUND 128 |
27 | #define BTRFS_DELAYED_BATCH 16 | ||
27 | 28 | ||
28 | static struct kmem_cache *delayed_node_cache; | 29 | static struct kmem_cache *delayed_node_cache; |
29 | 30 | ||
@@ -494,6 +495,15 @@ static int __btrfs_add_delayed_deletion_item(struct btrfs_delayed_node *node, | |||
494 | BTRFS_DELAYED_DELETION_ITEM); | 495 | BTRFS_DELAYED_DELETION_ITEM); |
495 | } | 496 | } |
496 | 497 | ||
498 | static void finish_one_item(struct btrfs_delayed_root *delayed_root) | ||
499 | { | ||
500 | int seq = atomic_inc_return(&delayed_root->items_seq); | ||
501 | if ((atomic_dec_return(&delayed_root->items) < | ||
502 | BTRFS_DELAYED_BACKGROUND || seq % BTRFS_DELAYED_BATCH == 0) && | ||
503 | waitqueue_active(&delayed_root->wait)) | ||
504 | wake_up(&delayed_root->wait); | ||
505 | } | ||
506 | |||
497 | static void __btrfs_remove_delayed_item(struct btrfs_delayed_item *delayed_item) | 507 | static void __btrfs_remove_delayed_item(struct btrfs_delayed_item *delayed_item) |
498 | { | 508 | { |
499 | struct rb_root *root; | 509 | struct rb_root *root; |
@@ -512,10 +522,8 @@ static void __btrfs_remove_delayed_item(struct btrfs_delayed_item *delayed_item) | |||
512 | 522 | ||
513 | rb_erase(&delayed_item->rb_node, root); | 523 | rb_erase(&delayed_item->rb_node, root); |
514 | delayed_item->delayed_node->count--; | 524 | delayed_item->delayed_node->count--; |
515 | if (atomic_dec_return(&delayed_root->items) < | 525 | |
516 | BTRFS_DELAYED_BACKGROUND && | 526 | finish_one_item(delayed_root); |
517 | waitqueue_active(&delayed_root->wait)) | ||
518 | wake_up(&delayed_root->wait); | ||
519 | } | 527 | } |
520 | 528 | ||
521 | static void btrfs_release_delayed_item(struct btrfs_delayed_item *item) | 529 | static void btrfs_release_delayed_item(struct btrfs_delayed_item *item) |
@@ -1056,10 +1064,7 @@ static void btrfs_release_delayed_inode(struct btrfs_delayed_node *delayed_node) | |||
1056 | delayed_node->count--; | 1064 | delayed_node->count--; |
1057 | 1065 | ||
1058 | delayed_root = delayed_node->root->fs_info->delayed_root; | 1066 | delayed_root = delayed_node->root->fs_info->delayed_root; |
1059 | if (atomic_dec_return(&delayed_root->items) < | 1067 | finish_one_item(delayed_root); |
1060 | BTRFS_DELAYED_BACKGROUND && | ||
1061 | waitqueue_active(&delayed_root->wait)) | ||
1062 | wake_up(&delayed_root->wait); | ||
1063 | } | 1068 | } |
1064 | } | 1069 | } |
1065 | 1070 | ||
@@ -1304,35 +1309,44 @@ void btrfs_remove_delayed_node(struct inode *inode) | |||
1304 | btrfs_release_delayed_node(delayed_node); | 1309 | btrfs_release_delayed_node(delayed_node); |
1305 | } | 1310 | } |
1306 | 1311 | ||
1307 | struct btrfs_async_delayed_node { | 1312 | struct btrfs_async_delayed_work { |
1308 | struct btrfs_root *root; | 1313 | struct btrfs_delayed_root *delayed_root; |
1309 | struct btrfs_delayed_node *delayed_node; | 1314 | int nr; |
1310 | struct btrfs_work work; | 1315 | struct btrfs_work work; |
1311 | }; | 1316 | }; |
1312 | 1317 | ||
1313 | static void btrfs_async_run_delayed_node_done(struct btrfs_work *work) | 1318 | static void btrfs_async_run_delayed_root(struct btrfs_work *work) |
1314 | { | 1319 | { |
1315 | struct btrfs_async_delayed_node *async_node; | 1320 | struct btrfs_async_delayed_work *async_work; |
1321 | struct btrfs_delayed_root *delayed_root; | ||
1316 | struct btrfs_trans_handle *trans; | 1322 | struct btrfs_trans_handle *trans; |
1317 | struct btrfs_path *path; | 1323 | struct btrfs_path *path; |
1318 | struct btrfs_delayed_node *delayed_node = NULL; | 1324 | struct btrfs_delayed_node *delayed_node = NULL; |
1319 | struct btrfs_root *root; | 1325 | struct btrfs_root *root; |
1320 | struct btrfs_block_rsv *block_rsv; | 1326 | struct btrfs_block_rsv *block_rsv; |
1321 | int need_requeue = 0; | 1327 | int total_done = 0; |
1322 | 1328 | ||
1323 | async_node = container_of(work, struct btrfs_async_delayed_node, work); | 1329 | async_work = container_of(work, struct btrfs_async_delayed_work, work); |
1330 | delayed_root = async_work->delayed_root; | ||
1324 | 1331 | ||
1325 | path = btrfs_alloc_path(); | 1332 | path = btrfs_alloc_path(); |
1326 | if (!path) | 1333 | if (!path) |
1327 | goto out; | 1334 | goto out; |
1328 | path->leave_spinning = 1; | ||
1329 | 1335 | ||
1330 | delayed_node = async_node->delayed_node; | 1336 | again: |
1337 | if (atomic_read(&delayed_root->items) < BTRFS_DELAYED_BACKGROUND / 2) | ||
1338 | goto free_path; | ||
1339 | |||
1340 | delayed_node = btrfs_first_prepared_delayed_node(delayed_root); | ||
1341 | if (!delayed_node) | ||
1342 | goto free_path; | ||
1343 | |||
1344 | path->leave_spinning = 1; | ||
1331 | root = delayed_node->root; | 1345 | root = delayed_node->root; |
1332 | 1346 | ||
1333 | trans = btrfs_join_transaction(root); | 1347 | trans = btrfs_join_transaction(root); |
1334 | if (IS_ERR(trans)) | 1348 | if (IS_ERR(trans)) |
1335 | goto free_path; | 1349 | goto release_path; |
1336 | 1350 | ||
1337 | block_rsv = trans->block_rsv; | 1351 | block_rsv = trans->block_rsv; |
1338 | trans->block_rsv = &root->fs_info->delayed_block_rsv; | 1352 | trans->block_rsv = &root->fs_info->delayed_block_rsv; |
@@ -1363,57 +1377,47 @@ static void btrfs_async_run_delayed_node_done(struct btrfs_work *work) | |||
1363 | * Task1 will sleep until the transaction is commited. | 1377 | * Task1 will sleep until the transaction is commited. |
1364 | */ | 1378 | */ |
1365 | mutex_lock(&delayed_node->mutex); | 1379 | mutex_lock(&delayed_node->mutex); |
1366 | if (delayed_node->count) | 1380 | btrfs_dequeue_delayed_node(root->fs_info->delayed_root, delayed_node); |
1367 | need_requeue = 1; | ||
1368 | else | ||
1369 | btrfs_dequeue_delayed_node(root->fs_info->delayed_root, | ||
1370 | delayed_node); | ||
1371 | mutex_unlock(&delayed_node->mutex); | 1381 | mutex_unlock(&delayed_node->mutex); |
1372 | 1382 | ||
1373 | trans->block_rsv = block_rsv; | 1383 | trans->block_rsv = block_rsv; |
1374 | btrfs_end_transaction_dmeta(trans, root); | 1384 | btrfs_end_transaction_dmeta(trans, root); |
1375 | btrfs_btree_balance_dirty_nodelay(root); | 1385 | btrfs_btree_balance_dirty_nodelay(root); |
1386 | |||
1387 | release_path: | ||
1388 | btrfs_release_path(path); | ||
1389 | total_done++; | ||
1390 | |||
1391 | btrfs_release_prepared_delayed_node(delayed_node); | ||
1392 | if (async_work->nr == 0 || total_done < async_work->nr) | ||
1393 | goto again; | ||
1394 | |||
1376 | free_path: | 1395 | free_path: |
1377 | btrfs_free_path(path); | 1396 | btrfs_free_path(path); |
1378 | out: | 1397 | out: |
1379 | if (need_requeue) | 1398 | wake_up(&delayed_root->wait); |
1380 | btrfs_requeue_work(&async_node->work); | 1399 | kfree(async_work); |
1381 | else { | ||
1382 | btrfs_release_prepared_delayed_node(delayed_node); | ||
1383 | kfree(async_node); | ||
1384 | } | ||
1385 | } | 1400 | } |
1386 | 1401 | ||
1402 | |||
1387 | static int btrfs_wq_run_delayed_node(struct btrfs_delayed_root *delayed_root, | 1403 | static int btrfs_wq_run_delayed_node(struct btrfs_delayed_root *delayed_root, |
1388 | struct btrfs_root *root, int all) | 1404 | struct btrfs_root *root, int nr) |
1389 | { | 1405 | { |
1390 | struct btrfs_async_delayed_node *async_node; | 1406 | struct btrfs_async_delayed_work *async_work; |
1391 | struct btrfs_delayed_node *curr; | ||
1392 | int count = 0; | ||
1393 | 1407 | ||
1394 | again: | 1408 | if (atomic_read(&delayed_root->items) < BTRFS_DELAYED_BACKGROUND) |
1395 | curr = btrfs_first_prepared_delayed_node(delayed_root); | ||
1396 | if (!curr) | ||
1397 | return 0; | 1409 | return 0; |
1398 | 1410 | ||
1399 | async_node = kmalloc(sizeof(*async_node), GFP_NOFS); | 1411 | async_work = kmalloc(sizeof(*async_work), GFP_NOFS); |
1400 | if (!async_node) { | 1412 | if (!async_work) |
1401 | btrfs_release_prepared_delayed_node(curr); | ||
1402 | return -ENOMEM; | 1413 | return -ENOMEM; |
1403 | } | ||
1404 | |||
1405 | async_node->root = root; | ||
1406 | async_node->delayed_node = curr; | ||
1407 | |||
1408 | async_node->work.func = btrfs_async_run_delayed_node_done; | ||
1409 | async_node->work.flags = 0; | ||
1410 | 1414 | ||
1411 | btrfs_queue_worker(&root->fs_info->delayed_workers, &async_node->work); | 1415 | async_work->delayed_root = delayed_root; |
1412 | count++; | 1416 | async_work->work.func = btrfs_async_run_delayed_root; |
1413 | 1417 | async_work->work.flags = 0; | |
1414 | if (all || count < 4) | 1418 | async_work->nr = nr; |
1415 | goto again; | ||
1416 | 1419 | ||
1420 | btrfs_queue_worker(&root->fs_info->delayed_workers, &async_work->work); | ||
1417 | return 0; | 1421 | return 0; |
1418 | } | 1422 | } |
1419 | 1423 | ||
@@ -1424,30 +1428,55 @@ void btrfs_assert_delayed_root_empty(struct btrfs_root *root) | |||
1424 | WARN_ON(btrfs_first_delayed_node(delayed_root)); | 1428 | WARN_ON(btrfs_first_delayed_node(delayed_root)); |
1425 | } | 1429 | } |
1426 | 1430 | ||
1431 | static int refs_newer(struct btrfs_delayed_root *delayed_root, | ||
1432 | int seq, int count) | ||
1433 | { | ||
1434 | int val = atomic_read(&delayed_root->items_seq); | ||
1435 | |||
1436 | if (val < seq || val >= seq + count) | ||
1437 | return 1; | ||
1438 | return 0; | ||
1439 | } | ||
1440 | |||
1427 | void btrfs_balance_delayed_items(struct btrfs_root *root) | 1441 | void btrfs_balance_delayed_items(struct btrfs_root *root) |
1428 | { | 1442 | { |
1429 | struct btrfs_delayed_root *delayed_root; | 1443 | struct btrfs_delayed_root *delayed_root; |
1444 | int seq; | ||
1430 | 1445 | ||
1431 | delayed_root = btrfs_get_delayed_root(root); | 1446 | delayed_root = btrfs_get_delayed_root(root); |
1432 | 1447 | ||
1433 | if (atomic_read(&delayed_root->items) < BTRFS_DELAYED_BACKGROUND) | 1448 | if (atomic_read(&delayed_root->items) < BTRFS_DELAYED_BACKGROUND) |
1434 | return; | 1449 | return; |
1435 | 1450 | ||
1451 | seq = atomic_read(&delayed_root->items_seq); | ||
1452 | |||
1436 | if (atomic_read(&delayed_root->items) >= BTRFS_DELAYED_WRITEBACK) { | 1453 | if (atomic_read(&delayed_root->items) >= BTRFS_DELAYED_WRITEBACK) { |
1437 | int ret; | 1454 | int ret; |
1438 | ret = btrfs_wq_run_delayed_node(delayed_root, root, 1); | 1455 | DEFINE_WAIT(__wait); |
1456 | |||
1457 | ret = btrfs_wq_run_delayed_node(delayed_root, root, 0); | ||
1439 | if (ret) | 1458 | if (ret) |
1440 | return; | 1459 | return; |
1441 | 1460 | ||
1442 | wait_event_interruptible_timeout( | 1461 | while (1) { |
1443 | delayed_root->wait, | 1462 | prepare_to_wait(&delayed_root->wait, &__wait, |
1444 | (atomic_read(&delayed_root->items) < | 1463 | TASK_INTERRUPTIBLE); |
1445 | BTRFS_DELAYED_BACKGROUND), | 1464 | |
1446 | HZ); | 1465 | if (refs_newer(delayed_root, seq, |
1447 | return; | 1466 | BTRFS_DELAYED_BATCH) || |
1467 | atomic_read(&delayed_root->items) < | ||
1468 | BTRFS_DELAYED_BACKGROUND) { | ||
1469 | break; | ||
1470 | } | ||
1471 | if (!signal_pending(current)) | ||
1472 | schedule(); | ||
1473 | else | ||
1474 | break; | ||
1475 | } | ||
1476 | finish_wait(&delayed_root->wait, &__wait); | ||
1448 | } | 1477 | } |
1449 | 1478 | ||
1450 | btrfs_wq_run_delayed_node(delayed_root, root, 0); | 1479 | btrfs_wq_run_delayed_node(delayed_root, root, BTRFS_DELAYED_BATCH); |
1451 | } | 1480 | } |
1452 | 1481 | ||
1453 | /* Will return 0 or -ENOMEM */ | 1482 | /* Will return 0 or -ENOMEM */ |
diff --git a/fs/btrfs/delayed-inode.h b/fs/btrfs/delayed-inode.h index 78b6ad0fc669..1d5c5f7abe3e 100644 --- a/fs/btrfs/delayed-inode.h +++ b/fs/btrfs/delayed-inode.h | |||
@@ -43,6 +43,7 @@ struct btrfs_delayed_root { | |||
43 | */ | 43 | */ |
44 | struct list_head prepare_list; | 44 | struct list_head prepare_list; |
45 | atomic_t items; /* for delayed items */ | 45 | atomic_t items; /* for delayed items */ |
46 | atomic_t items_seq; /* for delayed items */ | ||
46 | int nodes; /* for delayed nodes */ | 47 | int nodes; /* for delayed nodes */ |
47 | wait_queue_head_t wait; | 48 | wait_queue_head_t wait; |
48 | }; | 49 | }; |
@@ -86,6 +87,7 @@ static inline void btrfs_init_delayed_root( | |||
86 | struct btrfs_delayed_root *delayed_root) | 87 | struct btrfs_delayed_root *delayed_root) |
87 | { | 88 | { |
88 | atomic_set(&delayed_root->items, 0); | 89 | atomic_set(&delayed_root->items, 0); |
90 | atomic_set(&delayed_root->items_seq, 0); | ||
89 | delayed_root->nodes = 0; | 91 | delayed_root->nodes = 0; |
90 | spin_lock_init(&delayed_root->lock); | 92 | spin_lock_init(&delayed_root->lock); |
91 | init_waitqueue_head(&delayed_root->wait); | 93 | init_waitqueue_head(&delayed_root->wait); |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 02369a3c162e..7d84651e850b 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -62,7 +62,7 @@ static void btrfs_destroy_ordered_operations(struct btrfs_transaction *t, | |||
62 | static void btrfs_destroy_ordered_extents(struct btrfs_root *root); | 62 | static void btrfs_destroy_ordered_extents(struct btrfs_root *root); |
63 | static int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans, | 63 | static int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans, |
64 | struct btrfs_root *root); | 64 | struct btrfs_root *root); |
65 | static void btrfs_destroy_pending_snapshots(struct btrfs_transaction *t); | 65 | static void btrfs_evict_pending_snapshots(struct btrfs_transaction *t); |
66 | static void btrfs_destroy_delalloc_inodes(struct btrfs_root *root); | 66 | static void btrfs_destroy_delalloc_inodes(struct btrfs_root *root); |
67 | static int btrfs_destroy_marked_extents(struct btrfs_root *root, | 67 | static int btrfs_destroy_marked_extents(struct btrfs_root *root, |
68 | struct extent_io_tree *dirty_pages, | 68 | struct extent_io_tree *dirty_pages, |
@@ -3687,7 +3687,7 @@ int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans, | |||
3687 | return ret; | 3687 | return ret; |
3688 | } | 3688 | } |
3689 | 3689 | ||
3690 | static void btrfs_destroy_pending_snapshots(struct btrfs_transaction *t) | 3690 | static void btrfs_evict_pending_snapshots(struct btrfs_transaction *t) |
3691 | { | 3691 | { |
3692 | struct btrfs_pending_snapshot *snapshot; | 3692 | struct btrfs_pending_snapshot *snapshot; |
3693 | struct list_head splice; | 3693 | struct list_head splice; |
@@ -3700,10 +3700,8 @@ static void btrfs_destroy_pending_snapshots(struct btrfs_transaction *t) | |||
3700 | snapshot = list_entry(splice.next, | 3700 | snapshot = list_entry(splice.next, |
3701 | struct btrfs_pending_snapshot, | 3701 | struct btrfs_pending_snapshot, |
3702 | list); | 3702 | list); |
3703 | 3703 | snapshot->error = -ECANCELED; | |
3704 | list_del_init(&snapshot->list); | 3704 | list_del_init(&snapshot->list); |
3705 | |||
3706 | kfree(snapshot); | ||
3707 | } | 3705 | } |
3708 | } | 3706 | } |
3709 | 3707 | ||
@@ -3840,6 +3838,8 @@ void btrfs_cleanup_one_transaction(struct btrfs_transaction *cur_trans, | |||
3840 | cur_trans->blocked = 1; | 3838 | cur_trans->blocked = 1; |
3841 | wake_up(&root->fs_info->transaction_blocked_wait); | 3839 | wake_up(&root->fs_info->transaction_blocked_wait); |
3842 | 3840 | ||
3841 | btrfs_evict_pending_snapshots(cur_trans); | ||
3842 | |||
3843 | cur_trans->blocked = 0; | 3843 | cur_trans->blocked = 0; |
3844 | wake_up(&root->fs_info->transaction_wait); | 3844 | wake_up(&root->fs_info->transaction_wait); |
3845 | 3845 | ||
@@ -3849,8 +3849,6 @@ void btrfs_cleanup_one_transaction(struct btrfs_transaction *cur_trans, | |||
3849 | btrfs_destroy_delayed_inodes(root); | 3849 | btrfs_destroy_delayed_inodes(root); |
3850 | btrfs_assert_delayed_root_empty(root); | 3850 | btrfs_assert_delayed_root_empty(root); |
3851 | 3851 | ||
3852 | btrfs_destroy_pending_snapshots(cur_trans); | ||
3853 | |||
3854 | btrfs_destroy_marked_extents(root, &cur_trans->dirty_pages, | 3852 | btrfs_destroy_marked_extents(root, &cur_trans->dirty_pages, |
3855 | EXTENT_DIRTY); | 3853 | EXTENT_DIRTY); |
3856 | btrfs_destroy_pinned_extent(root, | 3854 | btrfs_destroy_pinned_extent(root, |
@@ -3894,6 +3892,8 @@ int btrfs_cleanup_transaction(struct btrfs_root *root) | |||
3894 | if (waitqueue_active(&root->fs_info->transaction_blocked_wait)) | 3892 | if (waitqueue_active(&root->fs_info->transaction_blocked_wait)) |
3895 | wake_up(&root->fs_info->transaction_blocked_wait); | 3893 | wake_up(&root->fs_info->transaction_blocked_wait); |
3896 | 3894 | ||
3895 | btrfs_evict_pending_snapshots(t); | ||
3896 | |||
3897 | t->blocked = 0; | 3897 | t->blocked = 0; |
3898 | smp_mb(); | 3898 | smp_mb(); |
3899 | if (waitqueue_active(&root->fs_info->transaction_wait)) | 3899 | if (waitqueue_active(&root->fs_info->transaction_wait)) |
@@ -3907,8 +3907,6 @@ int btrfs_cleanup_transaction(struct btrfs_root *root) | |||
3907 | btrfs_destroy_delayed_inodes(root); | 3907 | btrfs_destroy_delayed_inodes(root); |
3908 | btrfs_assert_delayed_root_empty(root); | 3908 | btrfs_assert_delayed_root_empty(root); |
3909 | 3909 | ||
3910 | btrfs_destroy_pending_snapshots(t); | ||
3911 | |||
3912 | btrfs_destroy_delalloc_inodes(root); | 3910 | btrfs_destroy_delalloc_inodes(root); |
3913 | 3911 | ||
3914 | spin_lock(&root->fs_info->trans_lock); | 3912 | spin_lock(&root->fs_info->trans_lock); |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index c226daefd65d..d1470adca8f8 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -8502,6 +8502,7 @@ static int __btrfs_prealloc_file_range(struct inode *inode, int mode, | |||
8502 | struct btrfs_key ins; | 8502 | struct btrfs_key ins; |
8503 | u64 cur_offset = start; | 8503 | u64 cur_offset = start; |
8504 | u64 i_size; | 8504 | u64 i_size; |
8505 | u64 cur_bytes; | ||
8505 | int ret = 0; | 8506 | int ret = 0; |
8506 | bool own_trans = true; | 8507 | bool own_trans = true; |
8507 | 8508 | ||
@@ -8516,8 +8517,9 @@ static int __btrfs_prealloc_file_range(struct inode *inode, int mode, | |||
8516 | } | 8517 | } |
8517 | } | 8518 | } |
8518 | 8519 | ||
8519 | ret = btrfs_reserve_extent(trans, root, | 8520 | cur_bytes = min(num_bytes, 256ULL * 1024 * 1024); |
8520 | min(num_bytes, 256ULL * 1024 * 1024), | 8521 | cur_bytes = max(cur_bytes, min_size); |
8522 | ret = btrfs_reserve_extent(trans, root, cur_bytes, | ||
8521 | min_size, 0, *alloc_hint, &ins, 1); | 8523 | min_size, 0, *alloc_hint, &ins, 1); |
8522 | if (ret) { | 8524 | if (ret) { |
8523 | if (own_trans) | 8525 | if (own_trans) |
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index c83086fdda05..2c02310ff2d9 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -527,6 +527,8 @@ fail: | |||
527 | if (async_transid) { | 527 | if (async_transid) { |
528 | *async_transid = trans->transid; | 528 | *async_transid = trans->transid; |
529 | err = btrfs_commit_transaction_async(trans, root, 1); | 529 | err = btrfs_commit_transaction_async(trans, root, 1); |
530 | if (err) | ||
531 | err = btrfs_commit_transaction(trans, root); | ||
530 | } else { | 532 | } else { |
531 | err = btrfs_commit_transaction(trans, root); | 533 | err = btrfs_commit_transaction(trans, root); |
532 | } | 534 | } |
@@ -592,16 +594,14 @@ static int create_snapshot(struct btrfs_root *root, struct inode *dir, | |||
592 | *async_transid = trans->transid; | 594 | *async_transid = trans->transid; |
593 | ret = btrfs_commit_transaction_async(trans, | 595 | ret = btrfs_commit_transaction_async(trans, |
594 | root->fs_info->extent_root, 1); | 596 | root->fs_info->extent_root, 1); |
597 | if (ret) | ||
598 | ret = btrfs_commit_transaction(trans, root); | ||
595 | } else { | 599 | } else { |
596 | ret = btrfs_commit_transaction(trans, | 600 | ret = btrfs_commit_transaction(trans, |
597 | root->fs_info->extent_root); | 601 | root->fs_info->extent_root); |
598 | } | 602 | } |
599 | if (ret) { | 603 | if (ret) |
600 | /* cleanup_transaction has freed this for us */ | ||
601 | if (trans->aborted) | ||
602 | pending_snapshot = NULL; | ||
603 | goto fail; | 604 | goto fail; |
604 | } | ||
605 | 605 | ||
606 | ret = pending_snapshot->error; | 606 | ret = pending_snapshot->error; |
607 | if (ret) | 607 | if (ret) |
@@ -2245,13 +2245,6 @@ static int btrfs_ioctl_defrag(struct file *file, void __user *argp) | |||
2245 | if (ret) | 2245 | if (ret) |
2246 | return ret; | 2246 | return ret; |
2247 | 2247 | ||
2248 | if (atomic_xchg(&root->fs_info->mutually_exclusive_operation_running, | ||
2249 | 1)) { | ||
2250 | pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n"); | ||
2251 | mnt_drop_write_file(file); | ||
2252 | return -EINVAL; | ||
2253 | } | ||
2254 | |||
2255 | if (btrfs_root_readonly(root)) { | 2248 | if (btrfs_root_readonly(root)) { |
2256 | ret = -EROFS; | 2249 | ret = -EROFS; |
2257 | goto out; | 2250 | goto out; |
@@ -2306,7 +2299,6 @@ static int btrfs_ioctl_defrag(struct file *file, void __user *argp) | |||
2306 | ret = -EINVAL; | 2299 | ret = -EINVAL; |
2307 | } | 2300 | } |
2308 | out: | 2301 | out: |
2309 | atomic_set(&root->fs_info->mutually_exclusive_operation_running, 0); | ||
2310 | mnt_drop_write_file(file); | 2302 | mnt_drop_write_file(file); |
2311 | return ret; | 2303 | return ret; |
2312 | } | 2304 | } |
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index 50695dc5e2ab..b67171e6d688 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c | |||
@@ -1269,6 +1269,8 @@ static int __update_reloc_root(struct btrfs_root *root, int del) | |||
1269 | } | 1269 | } |
1270 | spin_unlock(&rc->reloc_root_tree.lock); | 1270 | spin_unlock(&rc->reloc_root_tree.lock); |
1271 | 1271 | ||
1272 | if (!node) | ||
1273 | return 0; | ||
1272 | BUG_ON((struct btrfs_root *)node->data != root); | 1274 | BUG_ON((struct btrfs_root *)node->data != root); |
1273 | 1275 | ||
1274 | if (!del) { | 1276 | if (!del) { |
@@ -2238,13 +2240,28 @@ again: | |||
2238 | } | 2240 | } |
2239 | 2241 | ||
2240 | static noinline_for_stack | 2242 | static noinline_for_stack |
2243 | void free_reloc_roots(struct list_head *list) | ||
2244 | { | ||
2245 | struct btrfs_root *reloc_root; | ||
2246 | |||
2247 | while (!list_empty(list)) { | ||
2248 | reloc_root = list_entry(list->next, struct btrfs_root, | ||
2249 | root_list); | ||
2250 | __update_reloc_root(reloc_root, 1); | ||
2251 | free_extent_buffer(reloc_root->node); | ||
2252 | free_extent_buffer(reloc_root->commit_root); | ||
2253 | kfree(reloc_root); | ||
2254 | } | ||
2255 | } | ||
2256 | |||
2257 | static noinline_for_stack | ||
2241 | int merge_reloc_roots(struct reloc_control *rc) | 2258 | int merge_reloc_roots(struct reloc_control *rc) |
2242 | { | 2259 | { |
2243 | struct btrfs_root *root; | 2260 | struct btrfs_root *root; |
2244 | struct btrfs_root *reloc_root; | 2261 | struct btrfs_root *reloc_root; |
2245 | LIST_HEAD(reloc_roots); | 2262 | LIST_HEAD(reloc_roots); |
2246 | int found = 0; | 2263 | int found = 0; |
2247 | int ret; | 2264 | int ret = 0; |
2248 | again: | 2265 | again: |
2249 | root = rc->extent_root; | 2266 | root = rc->extent_root; |
2250 | 2267 | ||
@@ -2270,20 +2287,33 @@ again: | |||
2270 | BUG_ON(root->reloc_root != reloc_root); | 2287 | BUG_ON(root->reloc_root != reloc_root); |
2271 | 2288 | ||
2272 | ret = merge_reloc_root(rc, root); | 2289 | ret = merge_reloc_root(rc, root); |
2273 | BUG_ON(ret); | 2290 | if (ret) |
2291 | goto out; | ||
2274 | } else { | 2292 | } else { |
2275 | list_del_init(&reloc_root->root_list); | 2293 | list_del_init(&reloc_root->root_list); |
2276 | } | 2294 | } |
2277 | ret = btrfs_drop_snapshot(reloc_root, rc->block_rsv, 0, 1); | 2295 | ret = btrfs_drop_snapshot(reloc_root, rc->block_rsv, 0, 1); |
2278 | BUG_ON(ret < 0); | 2296 | if (ret < 0) { |
2297 | if (list_empty(&reloc_root->root_list)) | ||
2298 | list_add_tail(&reloc_root->root_list, | ||
2299 | &reloc_roots); | ||
2300 | goto out; | ||
2301 | } | ||
2279 | } | 2302 | } |
2280 | 2303 | ||
2281 | if (found) { | 2304 | if (found) { |
2282 | found = 0; | 2305 | found = 0; |
2283 | goto again; | 2306 | goto again; |
2284 | } | 2307 | } |
2308 | out: | ||
2309 | if (ret) { | ||
2310 | btrfs_std_error(root->fs_info, ret); | ||
2311 | if (!list_empty(&reloc_roots)) | ||
2312 | free_reloc_roots(&reloc_roots); | ||
2313 | } | ||
2314 | |||
2285 | BUG_ON(!RB_EMPTY_ROOT(&rc->reloc_root_tree.rb_root)); | 2315 | BUG_ON(!RB_EMPTY_ROOT(&rc->reloc_root_tree.rb_root)); |
2286 | return 0; | 2316 | return ret; |
2287 | } | 2317 | } |
2288 | 2318 | ||
2289 | static void free_block_list(struct rb_root *blocks) | 2319 | static void free_block_list(struct rb_root *blocks) |
@@ -2818,8 +2848,10 @@ int relocate_tree_blocks(struct btrfs_trans_handle *trans, | |||
2818 | int err = 0; | 2848 | int err = 0; |
2819 | 2849 | ||
2820 | path = btrfs_alloc_path(); | 2850 | path = btrfs_alloc_path(); |
2821 | if (!path) | 2851 | if (!path) { |
2822 | return -ENOMEM; | 2852 | err = -ENOMEM; |
2853 | goto out_path; | ||
2854 | } | ||
2823 | 2855 | ||
2824 | rb_node = rb_first(blocks); | 2856 | rb_node = rb_first(blocks); |
2825 | while (rb_node) { | 2857 | while (rb_node) { |
@@ -2858,10 +2890,11 @@ int relocate_tree_blocks(struct btrfs_trans_handle *trans, | |||
2858 | rb_node = rb_next(rb_node); | 2890 | rb_node = rb_next(rb_node); |
2859 | } | 2891 | } |
2860 | out: | 2892 | out: |
2861 | free_block_list(blocks); | ||
2862 | err = finish_pending_nodes(trans, rc, path, err); | 2893 | err = finish_pending_nodes(trans, rc, path, err); |
2863 | 2894 | ||
2864 | btrfs_free_path(path); | 2895 | btrfs_free_path(path); |
2896 | out_path: | ||
2897 | free_block_list(blocks); | ||
2865 | return err; | 2898 | return err; |
2866 | } | 2899 | } |
2867 | 2900 | ||
@@ -3698,7 +3731,15 @@ int prepare_to_relocate(struct reloc_control *rc) | |||
3698 | set_reloc_control(rc); | 3731 | set_reloc_control(rc); |
3699 | 3732 | ||
3700 | trans = btrfs_join_transaction(rc->extent_root); | 3733 | trans = btrfs_join_transaction(rc->extent_root); |
3701 | BUG_ON(IS_ERR(trans)); | 3734 | if (IS_ERR(trans)) { |
3735 | unset_reloc_control(rc); | ||
3736 | /* | ||
3737 | * extent tree is not a ref_cow tree and has no reloc_root to | ||
3738 | * cleanup. And callers are responsible to free the above | ||
3739 | * block rsv. | ||
3740 | */ | ||
3741 | return PTR_ERR(trans); | ||
3742 | } | ||
3702 | btrfs_commit_transaction(trans, rc->extent_root); | 3743 | btrfs_commit_transaction(trans, rc->extent_root); |
3703 | return 0; | 3744 | return 0; |
3704 | } | 3745 | } |
@@ -3730,7 +3771,11 @@ static noinline_for_stack int relocate_block_group(struct reloc_control *rc) | |||
3730 | while (1) { | 3771 | while (1) { |
3731 | progress++; | 3772 | progress++; |
3732 | trans = btrfs_start_transaction(rc->extent_root, 0); | 3773 | trans = btrfs_start_transaction(rc->extent_root, 0); |
3733 | BUG_ON(IS_ERR(trans)); | 3774 | if (IS_ERR(trans)) { |
3775 | err = PTR_ERR(trans); | ||
3776 | trans = NULL; | ||
3777 | break; | ||
3778 | } | ||
3734 | restart: | 3779 | restart: |
3735 | if (update_backref_cache(trans, &rc->backref_cache)) { | 3780 | if (update_backref_cache(trans, &rc->backref_cache)) { |
3736 | btrfs_end_transaction(trans, rc->extent_root); | 3781 | btrfs_end_transaction(trans, rc->extent_root); |
@@ -4264,14 +4309,9 @@ int btrfs_recover_relocation(struct btrfs_root *root) | |||
4264 | out_free: | 4309 | out_free: |
4265 | kfree(rc); | 4310 | kfree(rc); |
4266 | out: | 4311 | out: |
4267 | while (!list_empty(&reloc_roots)) { | 4312 | if (!list_empty(&reloc_roots)) |
4268 | reloc_root = list_entry(reloc_roots.next, | 4313 | free_reloc_roots(&reloc_roots); |
4269 | struct btrfs_root, root_list); | 4314 | |
4270 | list_del(&reloc_root->root_list); | ||
4271 | free_extent_buffer(reloc_root->node); | ||
4272 | free_extent_buffer(reloc_root->commit_root); | ||
4273 | kfree(reloc_root); | ||
4274 | } | ||
4275 | btrfs_free_path(path); | 4315 | btrfs_free_path(path); |
4276 | 4316 | ||
4277 | if (err == 0) { | 4317 | if (err == 0) { |
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index e52da6fb1165..9250b9c4f01e 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -1052,7 +1052,12 @@ int btrfs_defrag_root(struct btrfs_root *root) | |||
1052 | 1052 | ||
1053 | /* | 1053 | /* |
1054 | * new snapshots need to be created at a very specific time in the | 1054 | * new snapshots need to be created at a very specific time in the |
1055 | * transaction commit. This does the actual creation | 1055 | * transaction commit. This does the actual creation. |
1056 | * | ||
1057 | * Note: | ||
1058 | * If the error which may affect the commitment of the current transaction | ||
1059 | * happens, we should return the error number. If the error which just affect | ||
1060 | * the creation of the pending snapshots, just return 0. | ||
1056 | */ | 1061 | */ |
1057 | static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, | 1062 | static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, |
1058 | struct btrfs_fs_info *fs_info, | 1063 | struct btrfs_fs_info *fs_info, |
@@ -1071,7 +1076,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, | |||
1071 | struct extent_buffer *tmp; | 1076 | struct extent_buffer *tmp; |
1072 | struct extent_buffer *old; | 1077 | struct extent_buffer *old; |
1073 | struct timespec cur_time = CURRENT_TIME; | 1078 | struct timespec cur_time = CURRENT_TIME; |
1074 | int ret; | 1079 | int ret = 0; |
1075 | u64 to_reserve = 0; | 1080 | u64 to_reserve = 0; |
1076 | u64 index = 0; | 1081 | u64 index = 0; |
1077 | u64 objectid; | 1082 | u64 objectid; |
@@ -1080,40 +1085,36 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, | |||
1080 | 1085 | ||
1081 | path = btrfs_alloc_path(); | 1086 | path = btrfs_alloc_path(); |
1082 | if (!path) { | 1087 | if (!path) { |
1083 | ret = pending->error = -ENOMEM; | 1088 | pending->error = -ENOMEM; |
1084 | return ret; | 1089 | return 0; |
1085 | } | 1090 | } |
1086 | 1091 | ||
1087 | new_root_item = kmalloc(sizeof(*new_root_item), GFP_NOFS); | 1092 | new_root_item = kmalloc(sizeof(*new_root_item), GFP_NOFS); |
1088 | if (!new_root_item) { | 1093 | if (!new_root_item) { |
1089 | ret = pending->error = -ENOMEM; | 1094 | pending->error = -ENOMEM; |
1090 | goto root_item_alloc_fail; | 1095 | goto root_item_alloc_fail; |
1091 | } | 1096 | } |
1092 | 1097 | ||
1093 | ret = btrfs_find_free_objectid(tree_root, &objectid); | 1098 | pending->error = btrfs_find_free_objectid(tree_root, &objectid); |
1094 | if (ret) { | 1099 | if (pending->error) |
1095 | pending->error = ret; | ||
1096 | goto no_free_objectid; | 1100 | goto no_free_objectid; |
1097 | } | ||
1098 | 1101 | ||
1099 | btrfs_reloc_pre_snapshot(trans, pending, &to_reserve); | 1102 | btrfs_reloc_pre_snapshot(trans, pending, &to_reserve); |
1100 | 1103 | ||
1101 | if (to_reserve > 0) { | 1104 | if (to_reserve > 0) { |
1102 | ret = btrfs_block_rsv_add(root, &pending->block_rsv, | 1105 | pending->error = btrfs_block_rsv_add(root, |
1103 | to_reserve, | 1106 | &pending->block_rsv, |
1104 | BTRFS_RESERVE_NO_FLUSH); | 1107 | to_reserve, |
1105 | if (ret) { | 1108 | BTRFS_RESERVE_NO_FLUSH); |
1106 | pending->error = ret; | 1109 | if (pending->error) |
1107 | goto no_free_objectid; | 1110 | goto no_free_objectid; |
1108 | } | ||
1109 | } | 1111 | } |
1110 | 1112 | ||
1111 | ret = btrfs_qgroup_inherit(trans, fs_info, root->root_key.objectid, | 1113 | pending->error = btrfs_qgroup_inherit(trans, fs_info, |
1112 | objectid, pending->inherit); | 1114 | root->root_key.objectid, |
1113 | if (ret) { | 1115 | objectid, pending->inherit); |
1114 | pending->error = ret; | 1116 | if (pending->error) |
1115 | goto no_free_objectid; | 1117 | goto no_free_objectid; |
1116 | } | ||
1117 | 1118 | ||
1118 | key.objectid = objectid; | 1119 | key.objectid = objectid; |
1119 | key.offset = (u64)-1; | 1120 | key.offset = (u64)-1; |
@@ -1141,7 +1142,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, | |||
1141 | dentry->d_name.len, 0); | 1142 | dentry->d_name.len, 0); |
1142 | if (dir_item != NULL && !IS_ERR(dir_item)) { | 1143 | if (dir_item != NULL && !IS_ERR(dir_item)) { |
1143 | pending->error = -EEXIST; | 1144 | pending->error = -EEXIST; |
1144 | goto fail; | 1145 | goto dir_item_existed; |
1145 | } else if (IS_ERR(dir_item)) { | 1146 | } else if (IS_ERR(dir_item)) { |
1146 | ret = PTR_ERR(dir_item); | 1147 | ret = PTR_ERR(dir_item); |
1147 | btrfs_abort_transaction(trans, root, ret); | 1148 | btrfs_abort_transaction(trans, root, ret); |
@@ -1272,6 +1273,8 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, | |||
1272 | if (ret) | 1273 | if (ret) |
1273 | btrfs_abort_transaction(trans, root, ret); | 1274 | btrfs_abort_transaction(trans, root, ret); |
1274 | fail: | 1275 | fail: |
1276 | pending->error = ret; | ||
1277 | dir_item_existed: | ||
1275 | trans->block_rsv = rsv; | 1278 | trans->block_rsv = rsv; |
1276 | trans->bytes_reserved = 0; | 1279 | trans->bytes_reserved = 0; |
1277 | no_free_objectid: | 1280 | no_free_objectid: |
@@ -1287,12 +1290,17 @@ root_item_alloc_fail: | |||
1287 | static noinline int create_pending_snapshots(struct btrfs_trans_handle *trans, | 1290 | static noinline int create_pending_snapshots(struct btrfs_trans_handle *trans, |
1288 | struct btrfs_fs_info *fs_info) | 1291 | struct btrfs_fs_info *fs_info) |
1289 | { | 1292 | { |
1290 | struct btrfs_pending_snapshot *pending; | 1293 | struct btrfs_pending_snapshot *pending, *next; |
1291 | struct list_head *head = &trans->transaction->pending_snapshots; | 1294 | struct list_head *head = &trans->transaction->pending_snapshots; |
1295 | int ret = 0; | ||
1292 | 1296 | ||
1293 | list_for_each_entry(pending, head, list) | 1297 | list_for_each_entry_safe(pending, next, head, list) { |
1294 | create_pending_snapshot(trans, fs_info, pending); | 1298 | list_del(&pending->list); |
1295 | return 0; | 1299 | ret = create_pending_snapshot(trans, fs_info, pending); |
1300 | if (ret) | ||
1301 | break; | ||
1302 | } | ||
1303 | return ret; | ||
1296 | } | 1304 | } |
1297 | 1305 | ||
1298 | static void update_super_roots(struct btrfs_root *root) | 1306 | static void update_super_roots(struct btrfs_root *root) |
@@ -1448,6 +1456,13 @@ static void cleanup_transaction(struct btrfs_trans_handle *trans, | |||
1448 | btrfs_abort_transaction(trans, root, err); | 1456 | btrfs_abort_transaction(trans, root, err); |
1449 | 1457 | ||
1450 | spin_lock(&root->fs_info->trans_lock); | 1458 | spin_lock(&root->fs_info->trans_lock); |
1459 | |||
1460 | if (list_empty(&cur_trans->list)) { | ||
1461 | spin_unlock(&root->fs_info->trans_lock); | ||
1462 | btrfs_end_transaction(trans, root); | ||
1463 | return; | ||
1464 | } | ||
1465 | |||
1451 | list_del_init(&cur_trans->list); | 1466 | list_del_init(&cur_trans->list); |
1452 | if (cur_trans == root->fs_info->running_transaction) { | 1467 | if (cur_trans == root->fs_info->running_transaction) { |
1453 | root->fs_info->trans_no_join = 1; | 1468 | root->fs_info->trans_no_join = 1; |
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index c7ef569eb22a..451fad96ecd1 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c | |||
@@ -1382,7 +1382,10 @@ static noinline int link_to_fixup_dir(struct btrfs_trans_handle *trans, | |||
1382 | 1382 | ||
1383 | btrfs_release_path(path); | 1383 | btrfs_release_path(path); |
1384 | if (ret == 0) { | 1384 | if (ret == 0) { |
1385 | btrfs_inc_nlink(inode); | 1385 | if (!inode->i_nlink) |
1386 | set_nlink(inode, 1); | ||
1387 | else | ||
1388 | btrfs_inc_nlink(inode); | ||
1386 | ret = btrfs_update_inode(trans, root, inode); | 1389 | ret = btrfs_update_inode(trans, root, inode); |
1387 | } else if (ret == -EEXIST) { | 1390 | } else if (ret == -EEXIST) { |
1388 | ret = 0; | 1391 | ret = 0; |
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 35bb2d4ed29f..6b9cff42265d 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
@@ -2379,7 +2379,11 @@ static int btrfs_relocate_chunk(struct btrfs_root *root, | |||
2379 | return ret; | 2379 | return ret; |
2380 | 2380 | ||
2381 | trans = btrfs_start_transaction(root, 0); | 2381 | trans = btrfs_start_transaction(root, 0); |
2382 | BUG_ON(IS_ERR(trans)); | 2382 | if (IS_ERR(trans)) { |
2383 | ret = PTR_ERR(trans); | ||
2384 | btrfs_std_error(root->fs_info, ret); | ||
2385 | return ret; | ||
2386 | } | ||
2383 | 2387 | ||
2384 | lock_chunks(root); | 2388 | lock_chunks(root); |
2385 | 2389 | ||
@@ -3050,7 +3054,8 @@ static void __cancel_balance(struct btrfs_fs_info *fs_info) | |||
3050 | 3054 | ||
3051 | unset_balance_control(fs_info); | 3055 | unset_balance_control(fs_info); |
3052 | ret = del_balance_item(fs_info->tree_root); | 3056 | ret = del_balance_item(fs_info->tree_root); |
3053 | BUG_ON(ret); | 3057 | if (ret) |
3058 | btrfs_std_error(fs_info, ret); | ||
3054 | 3059 | ||
3055 | atomic_set(&fs_info->mutually_exclusive_operation_running, 0); | 3060 | atomic_set(&fs_info->mutually_exclusive_operation_running, 0); |
3056 | } | 3061 | } |
@@ -3230,6 +3235,11 @@ int btrfs_balance(struct btrfs_balance_control *bctl, | |||
3230 | update_ioctl_balance_args(fs_info, 0, bargs); | 3235 | update_ioctl_balance_args(fs_info, 0, bargs); |
3231 | } | 3236 | } |
3232 | 3237 | ||
3238 | if ((ret && ret != -ECANCELED && ret != -ENOSPC) || | ||
3239 | balance_need_close(fs_info)) { | ||
3240 | __cancel_balance(fs_info); | ||
3241 | } | ||
3242 | |||
3233 | wake_up(&fs_info->balance_wait_q); | 3243 | wake_up(&fs_info->balance_wait_q); |
3234 | 3244 | ||
3235 | return ret; | 3245 | return ret; |