diff options
Diffstat (limited to 'fs/btrfs')
| -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; |
