Gentle ping?

It would be pretty nice to make it into the next merge windows (v5.1).

Thanks,
Qu

On 2019/1/25 上午7:55, Qu Wenruo wrote:
> [BUG]
> Btrfs qgroup will still hit EDQUOT under the following case:
> 
>   #!/bin/bash
> 
>   dev=/dev/test/test
>   mnt=/mnt/btrfs
>   umount $mnt &> /dev/null
>   umount $dev &> /dev/null
> 
>   mkfs.btrfs -f $dev
>   mount $dev $mnt -o nospace_cache
> 
>   btrfs subv create $mnt/subv
>   btrfs quota enable $mnt
>   btrfs quota rescan -w $mnt
>   btrfs qgroup limit -e 1G $mnt/subv
> 
>   fallocate -l 900M $mnt/subv/padding
>   sync
> 
>   rm $mnt/subv/padding
> 
>   # Hit EDQUOT
>   xfs_io -f -c "pwrite 0 512M" $mnt/subv/real_file
> 
> [CAUSE]
> Since commit a514d63882c3 ("btrfs: qgroup: Commit transaction in advance
> to reduce early EDQUOT"), btrfs is not forced to commit transaction to
> reclaim more quota space.
> 
> Instead, we just check pertrans metadata reservation against some
> threshold and try to do asynchronously transaction commit.
> 
> However in above case, the pertrans metadata reservation is pretty small
> thus it will never trigger asynchronous transaction commit.
> 
> [FIX]
> Instead of only accounting pertrans metadata reservation, we calculate
> how much free space we have, and if there isn't much free space left,
> commit transaction asynchronously to try to free some space.
> 
> This may slow down the fs when we have less than 32M free qgroup space,
> but should reduce a lot of false EDQUOT, so the cost should be
> acceptable.
> 
> Signed-off-by: Qu Wenruo <w...@suse.com>
> ---
>  fs/btrfs/qgroup.c | 29 ++++++++++++++++-------------
>  1 file changed, 16 insertions(+), 13 deletions(-)
> 
> diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c
> index 4e473a998219..f0b7425bf289 100644
> --- a/fs/btrfs/qgroup.c
> +++ b/fs/btrfs/qgroup.c
> @@ -2843,15 +2843,15 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle 
> *trans, u64 srcid,
>   * Two limits to commit transaction in advance.
>   *
>   * For RATIO, it will be 1/RATIO of the remaining limit
> - * (excluding data and prealloc meta) as threshold.
> + * as threshold.
>   * For SIZE, it will be in byte unit as threshold.
>   */
> -#define QGROUP_PERTRANS_RATIO                32
> -#define QGROUP_PERTRANS_SIZE         SZ_32M
> +#define QGROUP_FREE_RATIO            32
> +#define QGROUP_FREE_SIZE             SZ_32M
>  static bool qgroup_check_limits(struct btrfs_fs_info *fs_info,
>                               const struct btrfs_qgroup *qg, u64 num_bytes)
>  {
> -     u64 limit;
> +     u64 free;
>       u64 threshold;
>  
>       if ((qg->lim_flags & BTRFS_QGROUP_LIMIT_MAX_RFER) &&
> @@ -2870,20 +2870,23 @@ static bool qgroup_check_limits(struct btrfs_fs_info 
> *fs_info,
>        */
>       if ((qg->lim_flags & (BTRFS_QGROUP_LIMIT_MAX_RFER |
>                             BTRFS_QGROUP_LIMIT_MAX_EXCL))) {
> -             if (qg->lim_flags & BTRFS_QGROUP_LIMIT_MAX_EXCL)
> -                     limit = qg->max_excl;
> -             else
> -                     limit = qg->max_rfer;
> -             threshold = (limit - qg->rsv.values[BTRFS_QGROUP_RSV_DATA] -
> -                         qg->rsv.values[BTRFS_QGROUP_RSV_META_PREALLOC]) /
> -                         QGROUP_PERTRANS_RATIO;
> -             threshold = min_t(u64, threshold, QGROUP_PERTRANS_SIZE);
> +             if (qg->lim_flags & BTRFS_QGROUP_LIMIT_MAX_EXCL) {
> +                     free = (qg->max_excl - qgroup_rsv_total(qg) -
> +                                  qg->excl);
> +                     threshold = min_t(u64, qg->max_excl / QGROUP_FREE_RATIO,
> +                                       QGROUP_FREE_SIZE);
> +             } else {
> +                     free = (qg->max_rfer - qgroup_rsv_total(qg) -
> +                                  qg->rfer);
> +                     threshold = min_t(u64, qg->max_rfer / QGROUP_FREE_RATIO,
> +                                       QGROUP_FREE_SIZE);
> +             }
>  
>               /*
>                * Use transaction_kthread to commit transaction, so we no
>                * longer need to bother nested transaction nor lock context.
>                */
> -             if (qg->rsv.values[BTRFS_QGROUP_RSV_META_PERTRANS] > threshold)
> +             if (free < threshold)
>                       btrfs_commit_transaction_locksafe(fs_info);
>       }
>  
> 

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to