On Wed, Feb 27, 2019 at 12:12 PM David Sterba <dsterba@xxxxxxxx> wrote:
>
> The allocation happens with GFP_KERNEL after a transaction has been
> started, this can potentially cause deadlock if reclaim tries to get the
> memory by flushing filesystem data.
>
> The fs_info::qgroup_ulist is not used during transaction start when
> quotas are not enabled. The status bit BTRFS_FS_QUOTA_ENABLED is set
> later in btrfs_quota_enable so it's safe to move it before the
> transaction start.
>
> Signed-off-by: David Sterba <dsterba@xxxxxxxx>
Reviewed-by: Filipe Manana <fdmanana@xxxxxxxx>
Looks good now.
>
> v2:
> - use qgroup_ulist directly, drop the temporary variable
> - update changelog
> ---
> fs/btrfs/qgroup.c | 13 ++++++-------
> 1 file changed, 6 insertions(+), 7 deletions(-)
>
> diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c
> index c1cd5558a646..eb680b715dd6 100644
> --- a/fs/btrfs/qgroup.c
> +++ b/fs/btrfs/qgroup.c
> @@ -894,6 +894,12 @@ int btrfs_quota_enable(struct btrfs_fs_info *fs_info)
> if (fs_info->quota_root)
> goto out;
>
> + fs_info->qgroup_ulist = ulist_alloc(GFP_KERNEL);
> + if (!fs_info->qgroup_ulist) {
> + ret = -ENOMEM;
> + goto out;
> + }
> +
> /*
> * 1 for quota root item
> * 1 for BTRFS_QGROUP_STATUS item
> @@ -909,13 +915,6 @@ int btrfs_quota_enable(struct btrfs_fs_info *fs_info)
> goto out;
> }
>
> - fs_info->qgroup_ulist = ulist_alloc(GFP_KERNEL);
> - if (!fs_info->qgroup_ulist) {
> - ret = -ENOMEM;
> - btrfs_abort_transaction(trans, ret);
> - goto out;
> - }
> -
> /*
> * initially create the quota tree
> */
> --
> 2.20.1
>
--
Filipe David Manana,
“Whether you think you can, or you think you can't — you're right.”