All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] btrfs: fix false enospc error when truncating heavily reflinked file
@ 2016-09-07 12:17 Wang Xiaoguang
  2016-09-07 15:56 ` Darrick J. Wong
  2017-01-04  7:52 ` Qu Wenruo
  0 siblings, 2 replies; 5+ messages in thread
From: Wang Xiaoguang @ 2016-09-07 12:17 UTC (permalink / raw)
  To: linux-btrfs

Below test script can reveal this bug:
    dd if=/dev/zero of=fs.img bs=$((1024*1024)) count=100
    dev=$(losetup --show -f fs.img)
    mkdir -p /mnt/mntpoint
    mkfs.btrfs  -f $dev
    mount $dev /mnt/mntpoint
    cd /mnt/mntpoint

    echo "workdir is: /mnt/mntpoint"
    blocksize=$((128 * 1024))
    dd if=/dev/zero of=testfile bs=$blocksize count=1
    sync
    count=$((17*1024*1024*1024/blocksize))
    echo "file size is:" $((count*blocksize))
    for ((i = 1; i <= $count; i++)); do
        dst_offset=$((blocksize * i))
        xfs_io -f -c "reflink testfile 0 $dst_offset $blocksize"\
                testfile > /dev/null
    done
    sync
    truncate --size 0 testfile

The last truncate operation will fail for ENOSPC reason, but indeed
it should not fail.

In btrfs_truncate(), we use a temporary block_rsv to do truncate
operation. With every btrfs_truncate_inode_items() call, we migrate space
to this block_rsv, but forget to cleanup previous reservation, which
will make this block_rsv's reserved bytes keep growing, and this reserved
space will only be released in the end of btrfs_truncate(), this metadata
leak will impact other's metadata reservation. In this case, it's
"btrfs_start_transaction(root, 2);" fails for enospc error, which make
this truncate operation fail.

Call btrfs_block_rsv_release() to fix this bug.

Signed-off-by: Wang Xiaoguang <wangxg.fnst@cn.fujitsu.com>
---
 fs/btrfs/inode.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index e6811c4..40f0762 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -9206,6 +9206,7 @@ static int btrfs_truncate(struct inode *inode)
 			break;
 		}
 
+		btrfs_block_rsv_release(root, rsv, -1);
 		ret = btrfs_block_rsv_migrate(&root->fs_info->trans_block_rsv,
 					      rsv, min_size, 0);
 		BUG_ON(ret);	/* shouldn't happen */
-- 
2.9.0




^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH] btrfs: fix false enospc error when truncating heavily reflinked file
  2016-09-07 12:17 [PATCH] btrfs: fix false enospc error when truncating heavily reflinked file Wang Xiaoguang
@ 2016-09-07 15:56 ` Darrick J. Wong
  2016-09-08  4:53   ` Wang Xiaoguang
  2017-01-04  7:52 ` Qu Wenruo
  1 sibling, 1 reply; 5+ messages in thread
From: Darrick J. Wong @ 2016-09-07 15:56 UTC (permalink / raw)
  To: Wang Xiaoguang; +Cc: linux-btrfs

On Wed, Sep 07, 2016 at 08:17:38PM +0800, Wang Xiaoguang wrote:
> Below test script can reveal this bug:
>     dd if=/dev/zero of=fs.img bs=$((1024*1024)) count=100
>     dev=$(losetup --show -f fs.img)
>     mkdir -p /mnt/mntpoint
>     mkfs.btrfs  -f $dev
>     mount $dev /mnt/mntpoint
>     cd /mnt/mntpoint
> 
>     echo "workdir is: /mnt/mntpoint"
>     blocksize=$((128 * 1024))
>     dd if=/dev/zero of=testfile bs=$blocksize count=1
>     sync
>     count=$((17*1024*1024*1024/blocksize))
>     echo "file size is:" $((count*blocksize))
>     for ((i = 1; i <= $count; i++)); do
>         dst_offset=$((blocksize * i))
>         xfs_io -f -c "reflink testfile 0 $dst_offset $blocksize"\
>                 testfile > /dev/null
>     done
>     sync
>     truncate --size 0 testfile
> 
> The last truncate operation will fail for ENOSPC reason, but indeed
> it should not fail.

Could you make this into an xfstest so we can avoid future regressions, please?

--D

> 
> In btrfs_truncate(), we use a temporary block_rsv to do truncate
> operation. With every btrfs_truncate_inode_items() call, we migrate space
> to this block_rsv, but forget to cleanup previous reservation, which
> will make this block_rsv's reserved bytes keep growing, and this reserved
> space will only be released in the end of btrfs_truncate(), this metadata
> leak will impact other's metadata reservation. In this case, it's
> "btrfs_start_transaction(root, 2);" fails for enospc error, which make
> this truncate operation fail.
> 
> Call btrfs_block_rsv_release() to fix this bug.
> 
> Signed-off-by: Wang Xiaoguang <wangxg.fnst@cn.fujitsu.com>
> ---
>  fs/btrfs/inode.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
> index e6811c4..40f0762 100644
> --- a/fs/btrfs/inode.c
> +++ b/fs/btrfs/inode.c
> @@ -9206,6 +9206,7 @@ static int btrfs_truncate(struct inode *inode)
>  			break;
>  		}
>  
> +		btrfs_block_rsv_release(root, rsv, -1);
>  		ret = btrfs_block_rsv_migrate(&root->fs_info->trans_block_rsv,
>  					      rsv, min_size, 0);
>  		BUG_ON(ret);	/* shouldn't happen */
> -- 
> 2.9.0
> 
> 
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] btrfs: fix false enospc error when truncating heavily reflinked file
  2016-09-07 15:56 ` Darrick J. Wong
@ 2016-09-08  4:53   ` Wang Xiaoguang
  0 siblings, 0 replies; 5+ messages in thread
From: Wang Xiaoguang @ 2016-09-08  4:53 UTC (permalink / raw)
  To: Darrick J. Wong; +Cc: linux-btrfs

Hi,

On 09/07/2016 11:56 PM, Darrick J. Wong wrote:
> On Wed, Sep 07, 2016 at 08:17:38PM +0800, Wang Xiaoguang wrote:
>> Below test script can reveal this bug:
>>      dd if=/dev/zero of=fs.img bs=$((1024*1024)) count=100
>>      dev=$(losetup --show -f fs.img)
>>      mkdir -p /mnt/mntpoint
>>      mkfs.btrfs  -f $dev
>>      mount $dev /mnt/mntpoint
>>      cd /mnt/mntpoint
>>
>>      echo "workdir is: /mnt/mntpoint"
>>      blocksize=$((128 * 1024))
>>      dd if=/dev/zero of=testfile bs=$blocksize count=1
>>      sync
>>      count=$((17*1024*1024*1024/blocksize))
>>      echo "file size is:" $((count*blocksize))
>>      for ((i = 1; i <= $count; i++)); do
>>          dst_offset=$((blocksize * i))
>>          xfs_io -f -c "reflink testfile 0 $dst_offset $blocksize"\
>>                  testfile > /dev/null
>>      done
>>      sync
>>      truncate --size 0 testfile
>>
>> The last truncate operation will fail for ENOSPC reason, but indeed
>> it should not fail.
> Could you make this into an xfstest so we can avoid future regressions, please?
OK.

Regards,
Xiaoguang Wang
>
> --D
>
>> In btrfs_truncate(), we use a temporary block_rsv to do truncate
>> operation. With every btrfs_truncate_inode_items() call, we migrate space
>> to this block_rsv, but forget to cleanup previous reservation, which
>> will make this block_rsv's reserved bytes keep growing, and this reserved
>> space will only be released in the end of btrfs_truncate(), this metadata
>> leak will impact other's metadata reservation. In this case, it's
>> "btrfs_start_transaction(root, 2);" fails for enospc error, which make
>> this truncate operation fail.
>>
>> Call btrfs_block_rsv_release() to fix this bug.
>>
>> Signed-off-by: Wang Xiaoguang <wangxg.fnst@cn.fujitsu.com>
>> ---
>>   fs/btrfs/inode.c | 1 +
>>   1 file changed, 1 insertion(+)
>>
>> diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
>> index e6811c4..40f0762 100644
>> --- a/fs/btrfs/inode.c
>> +++ b/fs/btrfs/inode.c
>> @@ -9206,6 +9206,7 @@ static int btrfs_truncate(struct inode *inode)
>>   			break;
>>   		}
>>   
>> +		btrfs_block_rsv_release(root, rsv, -1);
>>   		ret = btrfs_block_rsv_migrate(&root->fs_info->trans_block_rsv,
>>   					      rsv, min_size, 0);
>>   		BUG_ON(ret);	/* shouldn't happen */
>> -- 
>> 2.9.0
>>
>>
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>




^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] btrfs: fix false enospc error when truncating heavily reflinked file
  2016-09-07 12:17 [PATCH] btrfs: fix false enospc error when truncating heavily reflinked file Wang Xiaoguang
  2016-09-07 15:56 ` Darrick J. Wong
@ 2017-01-04  7:52 ` Qu Wenruo
  2017-01-05 17:43   ` David Sterba
  1 sibling, 1 reply; 5+ messages in thread
From: Qu Wenruo @ 2017-01-04  7:52 UTC (permalink / raw)
  To: Wang Xiaoguang, linux-btrfs

Hi,

Any comment on this patch?

Without it, btrfs will always fail for generic/387.

Thanks,
Qu

At 09/07/2016 08:17 PM, Wang Xiaoguang wrote:
> Below test script can reveal this bug:
>     dd if=/dev/zero of=fs.img bs=$((1024*1024)) count=100
>     dev=$(losetup --show -f fs.img)
>     mkdir -p /mnt/mntpoint
>     mkfs.btrfs  -f $dev
>     mount $dev /mnt/mntpoint
>     cd /mnt/mntpoint
>
>     echo "workdir is: /mnt/mntpoint"
>     blocksize=$((128 * 1024))
>     dd if=/dev/zero of=testfile bs=$blocksize count=1
>     sync
>     count=$((17*1024*1024*1024/blocksize))
>     echo "file size is:" $((count*blocksize))
>     for ((i = 1; i <= $count; i++)); do
>         dst_offset=$((blocksize * i))
>         xfs_io -f -c "reflink testfile 0 $dst_offset $blocksize"\
>                 testfile > /dev/null
>     done
>     sync
>     truncate --size 0 testfile
>
> The last truncate operation will fail for ENOSPC reason, but indeed
> it should not fail.
>
> In btrfs_truncate(), we use a temporary block_rsv to do truncate
> operation. With every btrfs_truncate_inode_items() call, we migrate space
> to this block_rsv, but forget to cleanup previous reservation, which
> will make this block_rsv's reserved bytes keep growing, and this reserved
> space will only be released in the end of btrfs_truncate(), this metadata
> leak will impact other's metadata reservation. In this case, it's
> "btrfs_start_transaction(root, 2);" fails for enospc error, which make
> this truncate operation fail.
>
> Call btrfs_block_rsv_release() to fix this bug.
>
> Signed-off-by: Wang Xiaoguang <wangxg.fnst@cn.fujitsu.com>
> ---
>  fs/btrfs/inode.c | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
> index e6811c4..40f0762 100644
> --- a/fs/btrfs/inode.c
> +++ b/fs/btrfs/inode.c
> @@ -9206,6 +9206,7 @@ static int btrfs_truncate(struct inode *inode)
>  			break;
>  		}
>
> +		btrfs_block_rsv_release(root, rsv, -1);
>  		ret = btrfs_block_rsv_migrate(&root->fs_info->trans_block_rsv,
>  					      rsv, min_size, 0);
>  		BUG_ON(ret);	/* shouldn't happen */
>



^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] btrfs: fix false enospc error when truncating heavily reflinked file
  2017-01-04  7:52 ` Qu Wenruo
@ 2017-01-05 17:43   ` David Sterba
  0 siblings, 0 replies; 5+ messages in thread
From: David Sterba @ 2017-01-05 17:43 UTC (permalink / raw)
  To: Qu Wenruo; +Cc: Wang Xiaoguang, linux-btrfs

On Wed, Jan 04, 2017 at 03:52:47PM +0800, Qu Wenruo wrote:
> Any comment on this patch?
> 
> Without it, btrfs will always fail for generic/387.

The fix looks good to me, adding it to next. There's a very similar
pattern in btrfs_punch_hole, but this function uses the trans reserve
and not truncate reserve. The modified reproducer does not trigger the
enospc, but it also could try harder.

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2017-01-05 17:43 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-09-07 12:17 [PATCH] btrfs: fix false enospc error when truncating heavily reflinked file Wang Xiaoguang
2016-09-07 15:56 ` Darrick J. Wong
2016-09-08  4:53   ` Wang Xiaoguang
2017-01-04  7:52 ` Qu Wenruo
2017-01-05 17:43   ` David Sterba

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.