diff options
Diffstat (limited to 'fs/btrfs/ioctl.c')
-rw-r--r-- | fs/btrfs/ioctl.c | 18 |
1 files changed, 17 insertions, 1 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 5d91776e12a2..0770c91586ca 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -3090,7 +3090,7 @@ out_unlock: | |||
3090 | static long btrfs_ioctl_file_extent_same(struct file *file, | 3090 | static long btrfs_ioctl_file_extent_same(struct file *file, |
3091 | struct btrfs_ioctl_same_args __user *argp) | 3091 | struct btrfs_ioctl_same_args __user *argp) |
3092 | { | 3092 | { |
3093 | struct btrfs_ioctl_same_args *same; | 3093 | struct btrfs_ioctl_same_args *same = NULL; |
3094 | struct btrfs_ioctl_same_extent_info *info; | 3094 | struct btrfs_ioctl_same_extent_info *info; |
3095 | struct inode *src = file_inode(file); | 3095 | struct inode *src = file_inode(file); |
3096 | u64 off; | 3096 | u64 off; |
@@ -3120,6 +3120,7 @@ static long btrfs_ioctl_file_extent_same(struct file *file, | |||
3120 | 3120 | ||
3121 | if (IS_ERR(same)) { | 3121 | if (IS_ERR(same)) { |
3122 | ret = PTR_ERR(same); | 3122 | ret = PTR_ERR(same); |
3123 | same = NULL; | ||
3123 | goto out; | 3124 | goto out; |
3124 | } | 3125 | } |
3125 | 3126 | ||
@@ -3190,6 +3191,7 @@ static long btrfs_ioctl_file_extent_same(struct file *file, | |||
3190 | 3191 | ||
3191 | out: | 3192 | out: |
3192 | mnt_drop_write_file(file); | 3193 | mnt_drop_write_file(file); |
3194 | kfree(same); | ||
3193 | return ret; | 3195 | return ret; |
3194 | } | 3196 | } |
3195 | 3197 | ||
@@ -3586,6 +3588,20 @@ process_slot: | |||
3586 | u64 trim = 0; | 3588 | u64 trim = 0; |
3587 | u64 aligned_end = 0; | 3589 | u64 aligned_end = 0; |
3588 | 3590 | ||
3591 | /* | ||
3592 | * Don't copy an inline extent into an offset | ||
3593 | * greater than zero. Having an inline extent | ||
3594 | * at such an offset results in chaos as btrfs | ||
3595 | * isn't prepared for such cases. Just skip | ||
3596 | * this case for the same reasons as commented | ||
3597 | * at btrfs_ioctl_clone(). | ||
3598 | */ | ||
3599 | if (last_dest_end > 0) { | ||
3600 | ret = -EOPNOTSUPP; | ||
3601 | btrfs_end_transaction(trans, root); | ||
3602 | goto out; | ||
3603 | } | ||
3604 | |||
3589 | if (off > key.offset) { | 3605 | if (off > key.offset) { |
3590 | skip = off - key.offset; | 3606 | skip = off - key.offset; |
3591 | new_key.offset += skip; | 3607 | new_key.offset += skip; |