ACK: [PATCH][SRU][TRUSTY] Btrfs: fix a crash of clone with inline extents's split
Chris J Arges
chris.j.arges at canonical.com
Wed Jan 21 13:07:45 UTC 2015
Clean cherry-pick, and in v3.15-rc3~3^2~33.
Is this going to stable?
Acked-by: Chris J Arges <chris.j.arges at canonical.com>
On 01/21/2015 04:01 AM, Colin King wrote:
> From: Liu Bo <bo.li.liu at oracle.com>
>
> BugLink: http://bugs.launchpad.net/bugs/1413129
>
> xfstests's btrfs/035 triggers a BUG_ON, which we use to detect the split
> of inline extents in __btrfs_drop_extents().
>
> For inline extents, we cannot duplicate another EXTENT_DATA item, because
> it breaks the rule of inline extents, that is, 'start offset' needs to be 0.
>
> We have set limitations for the source inode's compressed inline extents,
> because it needs to decompress and recompress. Now the destination inode's
> inline extents also need similar limitations.
>
> With this, xfstests btrfs/035 doesn't run into panic.
>
> Signed-off-by: Liu Bo <bo.li.liu at oracle.com>
> Signed-off-by: Chris Mason <clm at fb.com>
> (cherry picked from commit 00fdf13a2e9f313a044288aa59d3b8ec29ff904a)
> Signed-off-by: Colin Ian King <colin.king at canonical.com>
> ---
> fs/btrfs/file.c | 15 ++++++++++++---
> fs/btrfs/ioctl.c | 10 ++++++----
> 2 files changed, 18 insertions(+), 7 deletions(-)
>
> diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
> index 82d0342..3d42eba 100644
> --- a/fs/btrfs/file.c
> +++ b/fs/btrfs/file.c
> @@ -791,7 +791,10 @@ next_slot:
> */
> 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;
> @@ -834,7 +837,10 @@ next_slot:
> * | -------- 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;
> @@ -857,7 +863,10 @@ next_slot:
> */
> 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 043d6cd..f2a5472 100644
> --- a/fs/btrfs/ioctl.c
> +++ b/fs/btrfs/ioctl.c
> @@ -3041,8 +3041,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;
> }
> @@ -3127,8 +3128,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 */
>
More information about the kernel-team
mailing list