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