diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index b2143b8c33c577528bb0133c923662818e74d382..036f506cabd8af2787734158940f14af8ef22b27 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -804,7 +804,10 @@ int __btrfs_drop_extents(struct btrfs_trans_handle *trans, */ if (start > key.offset && end < extent_end) { BUG_ON(del_nr > 0); - BUG_ON(extent_type == BTRFS_FILE_EXTENT_INLINE); + if (extent_type == BTRFS_FILE_EXTENT_INLINE) { + ret = -EINVAL; + break; + } memcpy(&new_key, &key, sizeof(new_key)); new_key.offset = start; @@ -847,7 +850,10 @@ int __btrfs_drop_extents(struct btrfs_trans_handle *trans, * | -------- extent -------- | */ if (start <= key.offset && end < extent_end) { - BUG_ON(extent_type == BTRFS_FILE_EXTENT_INLINE); + if (extent_type == BTRFS_FILE_EXTENT_INLINE) { + ret = -EINVAL; + break; + } memcpy(&new_key, &key, sizeof(new_key)); new_key.offset = end; @@ -870,7 +876,10 @@ int __btrfs_drop_extents(struct btrfs_trans_handle *trans, */ if (start > key.offset && end >= extent_end) { BUG_ON(del_nr > 0); - BUG_ON(extent_type == BTRFS_FILE_EXTENT_INLINE); + if (extent_type == BTRFS_FILE_EXTENT_INLINE) { + ret = -EINVAL; + break; + } btrfs_set_file_extent_num_bytes(leaf, fi, start - key.offset); diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 3ca313b138caf7d2b73c07fe9b3a4bd7ed95f4fd..6778fa3c6ed2f004094d24e00cc2cb725db72459 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -3087,8 +3087,9 @@ static int btrfs_clone(struct inode *src, struct inode *inode, new_key.offset + datal, 1); if (ret) { - btrfs_abort_transaction(trans, root, - ret); + if (ret != -EINVAL) + btrfs_abort_transaction(trans, + root, ret); btrfs_end_transaction(trans, root); goto out; } @@ -3246,8 +3247,9 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, * decompress into destination's address_space (the file offset * may change, so source mapping won't do), then recompress (or * otherwise reinsert) a subrange. - * - allow ranges within the same file to be cloned (provided - * they don't overlap)? + * + * - split destination inode's inline extents. The inline extents can + * be either compressed or non-compressed. */ /* the destination must be opened for writing */