diff options
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r-- | fs/btrfs/inode.c | 117 |
1 files changed, 84 insertions, 33 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 9357a19d2bff..3ea5339603cf 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -1271,7 +1271,7 @@ static noinline int run_delalloc_nocow(struct inode *inode, | |||
1271 | u64 disk_num_bytes; | 1271 | u64 disk_num_bytes; |
1272 | u64 ram_bytes; | 1272 | u64 ram_bytes; |
1273 | int extent_type; | 1273 | int extent_type; |
1274 | int ret, err; | 1274 | int ret; |
1275 | int type; | 1275 | int type; |
1276 | int nocow; | 1276 | int nocow; |
1277 | int check_prev = 1; | 1277 | int check_prev = 1; |
@@ -1403,11 +1403,8 @@ next_slot: | |||
1403 | * if there are pending snapshots for this root, | 1403 | * if there are pending snapshots for this root, |
1404 | * we fall into common COW way. | 1404 | * we fall into common COW way. |
1405 | */ | 1405 | */ |
1406 | if (!nolock) { | 1406 | if (!nolock && atomic_read(&root->snapshot_force_cow)) |
1407 | err = btrfs_start_write_no_snapshotting(root); | 1407 | goto out_check; |
1408 | if (!err) | ||
1409 | goto out_check; | ||
1410 | } | ||
1411 | /* | 1408 | /* |
1412 | * force cow if csum exists in the range. | 1409 | * force cow if csum exists in the range. |
1413 | * this ensure that csum for a given extent are | 1410 | * this ensure that csum for a given extent are |
@@ -1416,9 +1413,6 @@ next_slot: | |||
1416 | ret = csum_exist_in_range(fs_info, disk_bytenr, | 1413 | ret = csum_exist_in_range(fs_info, disk_bytenr, |
1417 | num_bytes); | 1414 | num_bytes); |
1418 | if (ret) { | 1415 | if (ret) { |
1419 | if (!nolock) | ||
1420 | btrfs_end_write_no_snapshotting(root); | ||
1421 | |||
1422 | /* | 1416 | /* |
1423 | * ret could be -EIO if the above fails to read | 1417 | * ret could be -EIO if the above fails to read |
1424 | * metadata. | 1418 | * metadata. |
@@ -1431,11 +1425,8 @@ next_slot: | |||
1431 | WARN_ON_ONCE(nolock); | 1425 | WARN_ON_ONCE(nolock); |
1432 | goto out_check; | 1426 | goto out_check; |
1433 | } | 1427 | } |
1434 | if (!btrfs_inc_nocow_writers(fs_info, disk_bytenr)) { | 1428 | if (!btrfs_inc_nocow_writers(fs_info, disk_bytenr)) |
1435 | if (!nolock) | ||
1436 | btrfs_end_write_no_snapshotting(root); | ||
1437 | goto out_check; | 1429 | goto out_check; |
1438 | } | ||
1439 | nocow = 1; | 1430 | nocow = 1; |
1440 | } else if (extent_type == BTRFS_FILE_EXTENT_INLINE) { | 1431 | } else if (extent_type == BTRFS_FILE_EXTENT_INLINE) { |
1441 | extent_end = found_key.offset + | 1432 | extent_end = found_key.offset + |
@@ -1448,8 +1439,6 @@ next_slot: | |||
1448 | out_check: | 1439 | out_check: |
1449 | if (extent_end <= start) { | 1440 | if (extent_end <= start) { |
1450 | path->slots[0]++; | 1441 | path->slots[0]++; |
1451 | if (!nolock && nocow) | ||
1452 | btrfs_end_write_no_snapshotting(root); | ||
1453 | if (nocow) | 1442 | if (nocow) |
1454 | btrfs_dec_nocow_writers(fs_info, disk_bytenr); | 1443 | btrfs_dec_nocow_writers(fs_info, disk_bytenr); |
1455 | goto next_slot; | 1444 | goto next_slot; |
@@ -1471,8 +1460,6 @@ out_check: | |||
1471 | end, page_started, nr_written, 1, | 1460 | end, page_started, nr_written, 1, |
1472 | NULL); | 1461 | NULL); |
1473 | if (ret) { | 1462 | if (ret) { |
1474 | if (!nolock && nocow) | ||
1475 | btrfs_end_write_no_snapshotting(root); | ||
1476 | if (nocow) | 1463 | if (nocow) |
1477 | btrfs_dec_nocow_writers(fs_info, | 1464 | btrfs_dec_nocow_writers(fs_info, |
1478 | disk_bytenr); | 1465 | disk_bytenr); |
@@ -1492,8 +1479,6 @@ out_check: | |||
1492 | ram_bytes, BTRFS_COMPRESS_NONE, | 1479 | ram_bytes, BTRFS_COMPRESS_NONE, |
1493 | BTRFS_ORDERED_PREALLOC); | 1480 | BTRFS_ORDERED_PREALLOC); |
1494 | if (IS_ERR(em)) { | 1481 | if (IS_ERR(em)) { |
1495 | if (!nolock && nocow) | ||
1496 | btrfs_end_write_no_snapshotting(root); | ||
1497 | if (nocow) | 1482 | if (nocow) |
1498 | btrfs_dec_nocow_writers(fs_info, | 1483 | btrfs_dec_nocow_writers(fs_info, |
1499 | disk_bytenr); | 1484 | disk_bytenr); |
@@ -1532,8 +1517,6 @@ out_check: | |||
1532 | EXTENT_CLEAR_DATA_RESV, | 1517 | EXTENT_CLEAR_DATA_RESV, |
1533 | PAGE_UNLOCK | PAGE_SET_PRIVATE2); | 1518 | PAGE_UNLOCK | PAGE_SET_PRIVATE2); |
1534 | 1519 | ||
1535 | if (!nolock && nocow) | ||
1536 | btrfs_end_write_no_snapshotting(root); | ||
1537 | cur_offset = extent_end; | 1520 | cur_offset = extent_end; |
1538 | 1521 | ||
1539 | /* | 1522 | /* |
@@ -6639,6 +6622,8 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir, | |||
6639 | drop_inode = 1; | 6622 | drop_inode = 1; |
6640 | } else { | 6623 | } else { |
6641 | struct dentry *parent = dentry->d_parent; | 6624 | struct dentry *parent = dentry->d_parent; |
6625 | int ret; | ||
6626 | |||
6642 | err = btrfs_update_inode(trans, root, inode); | 6627 | err = btrfs_update_inode(trans, root, inode); |
6643 | if (err) | 6628 | if (err) |
6644 | goto fail; | 6629 | goto fail; |
@@ -6652,7 +6637,12 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir, | |||
6652 | goto fail; | 6637 | goto fail; |
6653 | } | 6638 | } |
6654 | d_instantiate(dentry, inode); | 6639 | d_instantiate(dentry, inode); |
6655 | btrfs_log_new_name(trans, BTRFS_I(inode), NULL, parent); | 6640 | ret = btrfs_log_new_name(trans, BTRFS_I(inode), NULL, parent, |
6641 | true, NULL); | ||
6642 | if (ret == BTRFS_NEED_TRANS_COMMIT) { | ||
6643 | err = btrfs_commit_transaction(trans); | ||
6644 | trans = NULL; | ||
6645 | } | ||
6656 | } | 6646 | } |
6657 | 6647 | ||
6658 | fail: | 6648 | fail: |
@@ -9388,14 +9378,21 @@ static int btrfs_rename_exchange(struct inode *old_dir, | |||
9388 | u64 new_idx = 0; | 9378 | u64 new_idx = 0; |
9389 | u64 root_objectid; | 9379 | u64 root_objectid; |
9390 | int ret; | 9380 | int ret; |
9391 | int ret2; | ||
9392 | bool root_log_pinned = false; | 9381 | bool root_log_pinned = false; |
9393 | bool dest_log_pinned = false; | 9382 | bool dest_log_pinned = false; |
9383 | struct btrfs_log_ctx ctx_root; | ||
9384 | struct btrfs_log_ctx ctx_dest; | ||
9385 | bool sync_log_root = false; | ||
9386 | bool sync_log_dest = false; | ||
9387 | bool commit_transaction = false; | ||
9394 | 9388 | ||
9395 | /* we only allow rename subvolume link between subvolumes */ | 9389 | /* we only allow rename subvolume link between subvolumes */ |
9396 | if (old_ino != BTRFS_FIRST_FREE_OBJECTID && root != dest) | 9390 | if (old_ino != BTRFS_FIRST_FREE_OBJECTID && root != dest) |
9397 | return -EXDEV; | 9391 | return -EXDEV; |
9398 | 9392 | ||
9393 | btrfs_init_log_ctx(&ctx_root, old_inode); | ||
9394 | btrfs_init_log_ctx(&ctx_dest, new_inode); | ||
9395 | |||
9399 | /* close the race window with snapshot create/destroy ioctl */ | 9396 | /* close the race window with snapshot create/destroy ioctl */ |
9400 | if (old_ino == BTRFS_FIRST_FREE_OBJECTID) | 9397 | if (old_ino == BTRFS_FIRST_FREE_OBJECTID) |
9401 | down_read(&fs_info->subvol_sem); | 9398 | down_read(&fs_info->subvol_sem); |
@@ -9542,15 +9539,29 @@ static int btrfs_rename_exchange(struct inode *old_dir, | |||
9542 | 9539 | ||
9543 | if (root_log_pinned) { | 9540 | if (root_log_pinned) { |
9544 | parent = new_dentry->d_parent; | 9541 | parent = new_dentry->d_parent; |
9545 | btrfs_log_new_name(trans, BTRFS_I(old_inode), BTRFS_I(old_dir), | 9542 | ret = btrfs_log_new_name(trans, BTRFS_I(old_inode), |
9546 | parent); | 9543 | BTRFS_I(old_dir), parent, |
9544 | false, &ctx_root); | ||
9545 | if (ret == BTRFS_NEED_LOG_SYNC) | ||
9546 | sync_log_root = true; | ||
9547 | else if (ret == BTRFS_NEED_TRANS_COMMIT) | ||
9548 | commit_transaction = true; | ||
9549 | ret = 0; | ||
9547 | btrfs_end_log_trans(root); | 9550 | btrfs_end_log_trans(root); |
9548 | root_log_pinned = false; | 9551 | root_log_pinned = false; |
9549 | } | 9552 | } |
9550 | if (dest_log_pinned) { | 9553 | if (dest_log_pinned) { |
9551 | parent = old_dentry->d_parent; | 9554 | if (!commit_transaction) { |
9552 | btrfs_log_new_name(trans, BTRFS_I(new_inode), BTRFS_I(new_dir), | 9555 | parent = old_dentry->d_parent; |
9553 | parent); | 9556 | ret = btrfs_log_new_name(trans, BTRFS_I(new_inode), |
9557 | BTRFS_I(new_dir), parent, | ||
9558 | false, &ctx_dest); | ||
9559 | if (ret == BTRFS_NEED_LOG_SYNC) | ||
9560 | sync_log_dest = true; | ||
9561 | else if (ret == BTRFS_NEED_TRANS_COMMIT) | ||
9562 | commit_transaction = true; | ||
9563 | ret = 0; | ||
9564 | } | ||
9554 | btrfs_end_log_trans(dest); | 9565 | btrfs_end_log_trans(dest); |
9555 | dest_log_pinned = false; | 9566 | dest_log_pinned = false; |
9556 | } | 9567 | } |
@@ -9583,8 +9594,26 @@ out_fail: | |||
9583 | dest_log_pinned = false; | 9594 | dest_log_pinned = false; |
9584 | } | 9595 | } |
9585 | } | 9596 | } |
9586 | ret2 = btrfs_end_transaction(trans); | 9597 | if (!ret && sync_log_root && !commit_transaction) { |
9587 | ret = ret ? ret : ret2; | 9598 | ret = btrfs_sync_log(trans, BTRFS_I(old_inode)->root, |
9599 | &ctx_root); | ||
9600 | if (ret) | ||
9601 | commit_transaction = true; | ||
9602 | } | ||
9603 | if (!ret && sync_log_dest && !commit_transaction) { | ||
9604 | ret = btrfs_sync_log(trans, BTRFS_I(new_inode)->root, | ||
9605 | &ctx_dest); | ||
9606 | if (ret) | ||
9607 | commit_transaction = true; | ||
9608 | } | ||
9609 | if (commit_transaction) { | ||
9610 | ret = btrfs_commit_transaction(trans); | ||
9611 | } else { | ||
9612 | int ret2; | ||
9613 | |||
9614 | ret2 = btrfs_end_transaction(trans); | ||
9615 | ret = ret ? ret : ret2; | ||
9616 | } | ||
9588 | out_notrans: | 9617 | out_notrans: |
9589 | if (new_ino == BTRFS_FIRST_FREE_OBJECTID) | 9618 | if (new_ino == BTRFS_FIRST_FREE_OBJECTID) |
9590 | up_read(&fs_info->subvol_sem); | 9619 | up_read(&fs_info->subvol_sem); |
@@ -9661,6 +9690,9 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
9661 | int ret; | 9690 | int ret; |
9662 | u64 old_ino = btrfs_ino(BTRFS_I(old_inode)); | 9691 | u64 old_ino = btrfs_ino(BTRFS_I(old_inode)); |
9663 | bool log_pinned = false; | 9692 | bool log_pinned = false; |
9693 | struct btrfs_log_ctx ctx; | ||
9694 | bool sync_log = false; | ||
9695 | bool commit_transaction = false; | ||
9664 | 9696 | ||
9665 | if (btrfs_ino(BTRFS_I(new_dir)) == BTRFS_EMPTY_SUBVOL_DIR_OBJECTID) | 9697 | if (btrfs_ino(BTRFS_I(new_dir)) == BTRFS_EMPTY_SUBVOL_DIR_OBJECTID) |
9666 | return -EPERM; | 9698 | return -EPERM; |
@@ -9818,8 +9850,15 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
9818 | if (log_pinned) { | 9850 | if (log_pinned) { |
9819 | struct dentry *parent = new_dentry->d_parent; | 9851 | struct dentry *parent = new_dentry->d_parent; |
9820 | 9852 | ||
9821 | btrfs_log_new_name(trans, BTRFS_I(old_inode), BTRFS_I(old_dir), | 9853 | btrfs_init_log_ctx(&ctx, old_inode); |
9822 | parent); | 9854 | ret = btrfs_log_new_name(trans, BTRFS_I(old_inode), |
9855 | BTRFS_I(old_dir), parent, | ||
9856 | false, &ctx); | ||
9857 | if (ret == BTRFS_NEED_LOG_SYNC) | ||
9858 | sync_log = true; | ||
9859 | else if (ret == BTRFS_NEED_TRANS_COMMIT) | ||
9860 | commit_transaction = true; | ||
9861 | ret = 0; | ||
9823 | btrfs_end_log_trans(root); | 9862 | btrfs_end_log_trans(root); |
9824 | log_pinned = false; | 9863 | log_pinned = false; |
9825 | } | 9864 | } |
@@ -9856,7 +9895,19 @@ out_fail: | |||
9856 | btrfs_end_log_trans(root); | 9895 | btrfs_end_log_trans(root); |
9857 | log_pinned = false; | 9896 | log_pinned = false; |
9858 | } | 9897 | } |
9859 | btrfs_end_transaction(trans); | 9898 | if (!ret && sync_log) { |
9899 | ret = btrfs_sync_log(trans, BTRFS_I(old_inode)->root, &ctx); | ||
9900 | if (ret) | ||
9901 | commit_transaction = true; | ||
9902 | } | ||
9903 | if (commit_transaction) { | ||
9904 | ret = btrfs_commit_transaction(trans); | ||
9905 | } else { | ||
9906 | int ret2; | ||
9907 | |||
9908 | ret2 = btrfs_end_transaction(trans); | ||
9909 | ret = ret ? ret : ret2; | ||
9910 | } | ||
9860 | out_notrans: | 9911 | out_notrans: |
9861 | if (old_ino == BTRFS_FIRST_FREE_OBJECTID) | 9912 | if (old_ino == BTRFS_FIRST_FREE_OBJECTID) |
9862 | up_read(&fs_info->subvol_sem); | 9913 | up_read(&fs_info->subvol_sem); |