Re: [PATCH 08/12] xfs: flush eof/cowblocks if we can't reserve quota for inode creation

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Sun, Jan 31, 2021 at 06:06:11PM -0800, Darrick J. Wong wrote:
> From: Darrick J. Wong <djwong@xxxxxxxxxx>
> 
> If an inode creation is unable to reserve enough quota to handle the
> modification, try clearing whatever space the filesystem might have been
> hanging onto in the hopes of speeding up the filesystem.  The flushing
> behavior will become particularly important when we add deferred inode
> inactivation because that will increase the amount of space that isn't
> actively tied to user data.
> 
> Signed-off-by: Darrick J. Wong <djwong@xxxxxxxxxx>
> ---

Reviewed-by: Brian Foster <bfoster@xxxxxxxxxx>

>  fs/xfs/xfs_icache.c |   73 ++++++++++++++++++++++++++++++---------------------
>  fs/xfs/xfs_icache.h |    2 +
>  fs/xfs/xfs_trans.c  |    8 ++++++
>  3 files changed, 53 insertions(+), 30 deletions(-)
> 
> 
> diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c
> index 4a074aa12b52..cd369dd48818 100644
> --- a/fs/xfs/xfs_icache.c
> +++ b/fs/xfs/xfs_icache.c
> @@ -1646,64 +1646,77 @@ xfs_start_block_reaping(
>  }
>  
>  /*
> - * Run cow/eofblocks scans on the quotas applicable to the inode. For inodes
> - * with multiple quotas, we don't know exactly which quota caused an allocation
> - * failure. We make a best effort by including each quota under low free space
> - * conditions (less than 1% free space) in the scan.
> + * Run cow/eofblocks scans on the supplied dquots.  We don't know exactly which
> + * quota caused an allocation failure, so we make a best effort by including
> + * each quota under low free space conditions (less than 1% free space) in the
> + * scan.
>   *
>   * Callers must not hold any inode's ILOCK.  If requesting a synchronous scan
>   * (XFS_EOF_FLAGS_SYNC), the caller also must not hold any inode's IOLOCK or
>   * MMAPLOCK.
>   */
>  int
> -xfs_blockgc_free_quota(
> -	struct xfs_inode	*ip,
> +xfs_blockgc_free_dquots(
> +	struct xfs_dquot	*udqp,
> +	struct xfs_dquot	*gdqp,
> +	struct xfs_dquot	*pdqp,
>  	unsigned int		eof_flags)
>  {
>  	struct xfs_eofblocks	eofb = {0};
> -	struct xfs_dquot	*dq;
> +	struct xfs_mount	*mp = NULL;
>  	bool			do_work = false;
>  	int			error;
>  
> +	if (!udqp && !gdqp && !pdqp)
> +		return 0;
> +	if (udqp)
> +		mp = udqp->q_mount;
> +	if (!mp && gdqp)
> +		mp = gdqp->q_mount;
> +	if (!mp && pdqp)
> +		mp = pdqp->q_mount;
> +
>  	/*
>  	 * Run a scan to free blocks using the union filter to cover all
>  	 * applicable quotas in a single scan.
>  	 */
>  	eofb.eof_flags = XFS_EOF_FLAGS_UNION | eof_flags;
>  
> -	if (XFS_IS_UQUOTA_ENFORCED(ip->i_mount)) {
> -		dq = xfs_inode_dquot(ip, XFS_DQTYPE_USER);
> -		if (dq && xfs_dquot_lowsp(dq)) {
> -			eofb.eof_uid = VFS_I(ip)->i_uid;
> -			eofb.eof_flags |= XFS_EOF_FLAGS_UID;
> -			do_work = true;
> -		}
> +	if (XFS_IS_UQUOTA_ENFORCED(mp) && udqp && xfs_dquot_lowsp(udqp)) {
> +		eofb.eof_uid = make_kuid(mp->m_super->s_user_ns, udqp->q_id);
> +		eofb.eof_flags |= XFS_EOF_FLAGS_UID;
> +		do_work = true;
>  	}
>  
> -	if (XFS_IS_GQUOTA_ENFORCED(ip->i_mount)) {
> -		dq = xfs_inode_dquot(ip, XFS_DQTYPE_GROUP);
> -		if (dq && xfs_dquot_lowsp(dq)) {
> -			eofb.eof_gid = VFS_I(ip)->i_gid;
> -			eofb.eof_flags |= XFS_EOF_FLAGS_GID;
> -			do_work = true;
> -		}
> +	if (XFS_IS_UQUOTA_ENFORCED(mp) && gdqp && xfs_dquot_lowsp(gdqp)) {
> +		eofb.eof_gid = make_kgid(mp->m_super->s_user_ns, gdqp->q_id);
> +		eofb.eof_flags |= XFS_EOF_FLAGS_GID;
> +		do_work = true;
>  	}
>  
> -	if (XFS_IS_PQUOTA_ENFORCED(ip->i_mount)) {
> -		dq = xfs_inode_dquot(ip, XFS_DQTYPE_PROJ);
> -		if (dq && xfs_dquot_lowsp(dq)) {
> -			eofb.eof_prid = ip->i_d.di_projid;
> -			eofb.eof_flags |= XFS_EOF_FLAGS_PRID;
> -			do_work = true;
> -		}
> +	if (XFS_IS_PQUOTA_ENFORCED(mp) && pdqp && xfs_dquot_lowsp(pdqp)) {
> +		eofb.eof_prid = pdqp->q_id;
> +		eofb.eof_flags |= XFS_EOF_FLAGS_PRID;
> +		do_work = true;
>  	}
>  
>  	if (!do_work)
>  		return 0;
>  
> -	error = xfs_icache_free_eofblocks(ip->i_mount, &eofb);
> +	error = xfs_icache_free_eofblocks(mp, &eofb);
>  	if (error)
>  		return error;
>  
> -	return xfs_icache_free_cowblocks(ip->i_mount, &eofb);
> +	return xfs_icache_free_cowblocks(mp, &eofb);
> +}
> +
> +/* Run cow/eofblocks scans on the quotas attached to the inode. */
> +int
> +xfs_blockgc_free_quota(
> +	struct xfs_inode	*ip,
> +	unsigned int		eof_flags)
> +{
> +	return xfs_blockgc_free_dquots(xfs_inode_dquot(ip, XFS_DQTYPE_USER),
> +			xfs_inode_dquot(ip, XFS_DQTYPE_GROUP),
> +			xfs_inode_dquot(ip, XFS_DQTYPE_PROJ), eof_flags);
>  }
> diff --git a/fs/xfs/xfs_icache.h b/fs/xfs/xfs_icache.h
> index d64ea8f5c589..5f520de637f6 100644
> --- a/fs/xfs/xfs_icache.h
> +++ b/fs/xfs/xfs_icache.h
> @@ -54,6 +54,8 @@ long xfs_reclaim_inodes_nr(struct xfs_mount *mp, int nr_to_scan);
>  
>  void xfs_inode_set_reclaim_tag(struct xfs_inode *ip);
>  
> +int xfs_blockgc_free_dquots(struct xfs_dquot *udqp, struct xfs_dquot *gdqp,
> +		struct xfs_dquot *pdqp, unsigned int eof_flags);
>  int xfs_blockgc_free_quota(struct xfs_inode *ip, unsigned int eof_flags);
>  
>  void xfs_inode_set_eofblocks_tag(struct xfs_inode *ip);
> diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
> index f62c1c5f210f..ee3cb916c5c9 100644
> --- a/fs/xfs/xfs_trans.c
> +++ b/fs/xfs/xfs_trans.c
> @@ -1102,13 +1102,21 @@ xfs_trans_alloc_icreate(
>  	struct xfs_trans	**tpp)
>  {
>  	struct xfs_trans	*tp;
> +	bool			retried = false;
>  	int			error;
>  
> +retry:
>  	error = xfs_trans_alloc(mp, resv, dblocks, 0, 0, &tp);
>  	if (error)
>  		return error;
>  
>  	error = xfs_trans_reserve_quota_icreate(tp, udqp, gdqp, pdqp, dblocks);
> +	if (!retried && (error == -EDQUOT || error == -ENOSPC)) {
> +		xfs_trans_cancel(tp);
> +		xfs_blockgc_free_dquots(udqp, gdqp, pdqp, 0);
> +		retried = true;
> +		goto retry;
> +	}
>  	if (error) {
>  		xfs_trans_cancel(tp);
>  		return error;
> 




[Index of Archives]     [XFS Filesystem Development (older mail)]     [Linux Filesystem Development]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux RAID]     [Linux SCSI]


  Powered by Linux