diff options
Diffstat (limited to 'fs/btrfs/ioctl.c')
-rw-r--r-- | fs/btrfs/ioctl.c | 68 |
1 files changed, 21 insertions, 47 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 47aceb494d1d..8a8e29878c34 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); |
@@ -1052,8 +1019,10 @@ static bool defrag_check_next_extent(struct inode *inode, struct extent_map *em) | |||
1052 | return false; | 1019 | return false; |
1053 | 1020 | ||
1054 | next = defrag_lookup_extent(inode, em->start + em->len); | 1021 | next = defrag_lookup_extent(inode, em->start + em->len); |
1055 | if (!next || next->block_start >= EXTENT_MAP_LAST_BYTE || | 1022 | if (!next || next->block_start >= EXTENT_MAP_LAST_BYTE) |
1056 | (em->block_start + em->block_len == next->block_start)) | 1023 | ret = false; |
1024 | else if ((em->block_start + em->block_len == next->block_start) && | ||
1025 | (em->block_len > 128 * 1024 && next->block_len > 128 * 1024)) | ||
1057 | ret = false; | 1026 | ret = false; |
1058 | 1027 | ||
1059 | free_extent_map(next); | 1028 | free_extent_map(next); |
@@ -1088,7 +1057,6 @@ static int should_defrag_range(struct inode *inode, u64 start, int thresh, | |||
1088 | } | 1057 | } |
1089 | 1058 | ||
1090 | next_mergeable = defrag_check_next_extent(inode, em); | 1059 | next_mergeable = defrag_check_next_extent(inode, em); |
1091 | |||
1092 | /* | 1060 | /* |
1093 | * we hit a real extent, if it is big or the next extent is not a | 1061 | * we hit a real extent, if it is big or the next extent is not a |
1094 | * real extent, don't bother defragging it | 1062 | * real extent, don't bother defragging it |
@@ -1735,7 +1703,7 @@ static noinline int btrfs_ioctl_snap_create_v2(struct file *file, | |||
1735 | ~(BTRFS_SUBVOL_CREATE_ASYNC | BTRFS_SUBVOL_RDONLY | | 1703 | ~(BTRFS_SUBVOL_CREATE_ASYNC | BTRFS_SUBVOL_RDONLY | |
1736 | BTRFS_SUBVOL_QGROUP_INHERIT)) { | 1704 | BTRFS_SUBVOL_QGROUP_INHERIT)) { |
1737 | ret = -EOPNOTSUPP; | 1705 | ret = -EOPNOTSUPP; |
1738 | goto out; | 1706 | goto free_args; |
1739 | } | 1707 | } |
1740 | 1708 | ||
1741 | if (vol_args->flags & BTRFS_SUBVOL_CREATE_ASYNC) | 1709 | if (vol_args->flags & BTRFS_SUBVOL_CREATE_ASYNC) |
@@ -1745,27 +1713,31 @@ static noinline int btrfs_ioctl_snap_create_v2(struct file *file, | |||
1745 | if (vol_args->flags & BTRFS_SUBVOL_QGROUP_INHERIT) { | 1713 | if (vol_args->flags & BTRFS_SUBVOL_QGROUP_INHERIT) { |
1746 | if (vol_args->size > PAGE_CACHE_SIZE) { | 1714 | if (vol_args->size > PAGE_CACHE_SIZE) { |
1747 | ret = -EINVAL; | 1715 | ret = -EINVAL; |
1748 | goto out; | 1716 | goto free_args; |
1749 | } | 1717 | } |
1750 | inherit = memdup_user(vol_args->qgroup_inherit, vol_args->size); | 1718 | inherit = memdup_user(vol_args->qgroup_inherit, vol_args->size); |
1751 | if (IS_ERR(inherit)) { | 1719 | if (IS_ERR(inherit)) { |
1752 | ret = PTR_ERR(inherit); | 1720 | ret = PTR_ERR(inherit); |
1753 | goto out; | 1721 | goto free_args; |
1754 | } | 1722 | } |
1755 | } | 1723 | } |
1756 | 1724 | ||
1757 | ret = btrfs_ioctl_snap_create_transid(file, vol_args->name, | 1725 | ret = btrfs_ioctl_snap_create_transid(file, vol_args->name, |
1758 | vol_args->fd, subvol, ptr, | 1726 | vol_args->fd, subvol, ptr, |
1759 | readonly, inherit); | 1727 | readonly, inherit); |
1728 | if (ret) | ||
1729 | goto free_inherit; | ||
1760 | 1730 | ||
1761 | if (ret == 0 && ptr && | 1731 | if (ptr && copy_to_user(arg + |
1762 | copy_to_user(arg + | 1732 | offsetof(struct btrfs_ioctl_vol_args_v2, |
1763 | offsetof(struct btrfs_ioctl_vol_args_v2, | 1733 | transid), |
1764 | transid), ptr, sizeof(*ptr))) | 1734 | ptr, sizeof(*ptr))) |
1765 | ret = -EFAULT; | 1735 | ret = -EFAULT; |
1766 | out: | 1736 | |
1767 | kfree(vol_args); | 1737 | free_inherit: |
1768 | kfree(inherit); | 1738 | kfree(inherit); |
1739 | free_args: | ||
1740 | kfree(vol_args); | ||
1769 | return ret; | 1741 | return ret; |
1770 | } | 1742 | } |
1771 | 1743 | ||
@@ -2685,7 +2657,7 @@ static long btrfs_ioctl_rm_dev(struct file *file, void __user *arg) | |||
2685 | vol_args = memdup_user(arg, sizeof(*vol_args)); | 2657 | vol_args = memdup_user(arg, sizeof(*vol_args)); |
2686 | if (IS_ERR(vol_args)) { | 2658 | if (IS_ERR(vol_args)) { |
2687 | ret = PTR_ERR(vol_args); | 2659 | ret = PTR_ERR(vol_args); |
2688 | goto out; | 2660 | goto err_drop; |
2689 | } | 2661 | } |
2690 | 2662 | ||
2691 | vol_args->name[BTRFS_PATH_NAME_MAX] = '\0'; | 2663 | vol_args->name[BTRFS_PATH_NAME_MAX] = '\0'; |
@@ -2703,6 +2675,7 @@ static long btrfs_ioctl_rm_dev(struct file *file, void __user *arg) | |||
2703 | 2675 | ||
2704 | out: | 2676 | out: |
2705 | kfree(vol_args); | 2677 | kfree(vol_args); |
2678 | err_drop: | ||
2706 | mnt_drop_write_file(file); | 2679 | mnt_drop_write_file(file); |
2707 | return ret; | 2680 | return ret; |
2708 | } | 2681 | } |
@@ -3527,7 +3500,8 @@ process_slot: | |||
3527 | btrfs_mark_buffer_dirty(leaf); | 3500 | btrfs_mark_buffer_dirty(leaf); |
3528 | btrfs_release_path(path); | 3501 | btrfs_release_path(path); |
3529 | 3502 | ||
3530 | last_dest_end = new_key.offset + datal; | 3503 | last_dest_end = ALIGN(new_key.offset + datal, |
3504 | root->sectorsize); | ||
3531 | ret = clone_finish_inode_update(trans, inode, | 3505 | ret = clone_finish_inode_update(trans, inode, |
3532 | last_dest_end, | 3506 | last_dest_end, |
3533 | destoff, olen); | 3507 | destoff, olen); |