diff options
Diffstat (limited to 'fs/btrfs/ioctl.c')
-rw-r--r-- | fs/btrfs/ioctl.c | 36 |
1 files changed, 2 insertions, 34 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 47aceb494d1d..fce6fd0e3f50 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -711,39 +711,6 @@ static int create_snapshot(struct btrfs_root *root, struct inode *dir, | |||
711 | if (ret) | 711 | if (ret) |
712 | goto fail; | 712 | goto fail; |
713 | 713 | ||
714 | ret = btrfs_orphan_cleanup(pending_snapshot->snap); | ||
715 | if (ret) | ||
716 | goto fail; | ||
717 | |||
718 | /* | ||
719 | * If orphan cleanup did remove any orphans, it means the tree was | ||
720 | * modified and therefore the commit root is not the same as the | ||
721 | * current root anymore. This is a problem, because send uses the | ||
722 | * commit root and therefore can see inode items that don't exist | ||
723 | * in the current root anymore, and for example make calls to | ||
724 | * btrfs_iget, which will do tree lookups based on the current root | ||
725 | * and not on the commit root. Those lookups will fail, returning a | ||
726 | * -ESTALE error, and making send fail with that error. So make sure | ||
727 | * a send does not see any orphans we have just removed, and that it | ||
728 | * will see the same inodes regardless of whether a transaction | ||
729 | * commit happened before it started (meaning that the commit root | ||
730 | * will be the same as the current root) or not. | ||
731 | */ | ||
732 | if (readonly && pending_snapshot->snap->node != | ||
733 | pending_snapshot->snap->commit_root) { | ||
734 | trans = btrfs_join_transaction(pending_snapshot->snap); | ||
735 | if (IS_ERR(trans) && PTR_ERR(trans) != -ENOENT) { | ||
736 | ret = PTR_ERR(trans); | ||
737 | goto fail; | ||
738 | } | ||
739 | if (!IS_ERR(trans)) { | ||
740 | ret = btrfs_commit_transaction(trans, | ||
741 | pending_snapshot->snap); | ||
742 | if (ret) | ||
743 | goto fail; | ||
744 | } | ||
745 | } | ||
746 | |||
747 | inode = btrfs_lookup_dentry(dentry->d_parent->d_inode, dentry); | 714 | inode = btrfs_lookup_dentry(dentry->d_parent->d_inode, dentry); |
748 | if (IS_ERR(inode)) { | 715 | if (IS_ERR(inode)) { |
749 | ret = PTR_ERR(inode); | 716 | ret = PTR_ERR(inode); |
@@ -3527,7 +3494,8 @@ process_slot: | |||
3527 | btrfs_mark_buffer_dirty(leaf); | 3494 | btrfs_mark_buffer_dirty(leaf); |
3528 | btrfs_release_path(path); | 3495 | btrfs_release_path(path); |
3529 | 3496 | ||
3530 | last_dest_end = new_key.offset + datal; | 3497 | last_dest_end = ALIGN(new_key.offset + datal, |
3498 | root->sectorsize); | ||
3531 | ret = clone_finish_inode_update(trans, inode, | 3499 | ret = clone_finish_inode_update(trans, inode, |
3532 | last_dest_end, | 3500 | last_dest_end, |
3533 | destoff, olen); | 3501 | destoff, olen); |