aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/inode.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r--fs/btrfs/inode.c117
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:
1448out_check: 1439out_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
6658fail: 6648fail:
@@ -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 }
9588out_notrans: 9617out_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 }
9860out_notrans: 9911out_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);