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.f...@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 majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to