Re: [RFC v6 PATCH 2/5] xfs: Add pquota fields where gquota is used.

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

 



Will rework as per your suggestion.

Thanks for the review.

Chandra
On Wed, 2012-08-15 at 11:15 +1000, Dave Chinner wrote:
> On Fri, Jul 20, 2012 at 06:02:25PM -0500, Chandra Seetharaman wrote:
> > Add project quota changes to all the places where group quota field
> > is used:
> >    * add separate project quota members into various structures
> >    * split project quota and group quotas so that instead of overriding
> >      the group quota members incore, the new project quota members are
> >      used instead
> >    * get rid of usage of the OQUOTA flag incore, in favor of separate group
> >      and project quota flags.
> >    * add a project dquot argument to various functions.
> > 
> > No externally visible interfaces changed and no superblock changes yet.
> 
> Lots of comments below.
> 
> > 
> > Signed-off-by: Chandra Seetharaman <sekharan@xxxxxxxxxx>
> > ---
> >  fs/xfs/xfs_dquot.c       |   16 ++-
> >  fs/xfs/xfs_dquot.h       |   11 ++-
> >  fs/xfs/xfs_iget.c        |    2 +-
> >  fs/xfs/xfs_inode.h       |    1 +
> >  fs/xfs/xfs_ioctl.c       |   14 ++--
> >  fs/xfs/xfs_iops.c        |    4 +-
> >  fs/xfs/xfs_qm.c          |  255 ++++++++++++++++++++++++++++++++--------------
> >  fs/xfs/xfs_qm.h          |   15 ++--
> >  fs/xfs/xfs_qm_bhv.c      |    2 +-
> >  fs/xfs/xfs_qm_syscalls.c |   19 +++-
> >  fs/xfs/xfs_quota.h       |   38 ++++---
> >  fs/xfs/xfs_sb.h          |    1 +
> >  fs/xfs/xfs_super.c       |    5 +-
> >  fs/xfs/xfs_trans_dquot.c |   71 ++++++++++---
> >  fs/xfs/xfs_vnodeops.c    |   23 +++--
> >  15 files changed, 326 insertions(+), 151 deletions(-)
> > 
> > diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c
> > index bf27fcc..42b8b79 100644
> > --- a/fs/xfs/xfs_dquot.c
> > +++ b/fs/xfs/xfs_dquot.c
> > @@ -751,7 +751,7 @@ xfs_qm_dqput_final(
> >  	struct xfs_dquot	*dqp)
> >  {
> >  	struct xfs_quotainfo	*qi = dqp->q_mount->m_quotainfo;
> > -	struct xfs_dquot	*gdqp;
> > +	struct xfs_dquot	*gdqp, *pdqp;
> 
> We tend not to declare multiple variables on the one line - just add
> a new line with the new variable.
> 
> >  
> >  	trace_xfs_dqput_free(dqp);
> >  
> > @@ -765,21 +765,29 @@ xfs_qm_dqput_final(
> >  
> >  	/*
> >  	 * If we just added a udquot to the freelist, then we want to release
> > -	 * the gdquot reference that it (probably) has. Otherwise it'll keep
> > -	 * the gdquot from getting reclaimed.
> > +	 * the gdquot/pdquot reference that it (probably) has. Otherwise it'll
> > +	 * keep the gdquot/pdquot from getting reclaimed.
> >  	 */
> >  	gdqp = dqp->q_gdquot;
> >  	if (gdqp) {
> >  		xfs_dqlock(gdqp);
> >  		dqp->q_gdquot = NULL;
> >  	}
> > +
> > +	pdqp = dqp->q_pdquot;
> > +	if (pdqp) {
> > +		xfs_dqlock(pdqp);
> > +		dqp->q_pdquot = NULL;
> > +	}
> 
> seeing this (and the various dupilications in this patch) makes me
> wonder if we'd be better off with array based abstractions and
> loops. That's not important for this patch set, but if we ever want
> to add another type of quota, then it would make sense...
> 
> > diff --git a/fs/xfs/xfs_dquot.h b/fs/xfs/xfs_dquot.h
> > index 7d20af2..893cd5e 100644
> > --- a/fs/xfs/xfs_dquot.h
> > +++ b/fs/xfs/xfs_dquot.h
> > @@ -46,6 +46,7 @@ typedef struct xfs_dquot {
> >  	xfs_fileoff_t	 q_fileoffset;	/* offset in quotas file */
> >  
> >  	struct xfs_dquot*q_gdquot;	/* group dquot, hint only */
> > +	struct xfs_dquot *q_pdquot;	/* project dquot, hint only */
> 
> You may as well put a space in the q_gdquot declaration so they are
> consistent....
> 
> > +		return ip->i_pdquot;
> >  	default:
> >  		return NULL;
> >  	}
> > @@ -136,7 +139,9 @@ static inline xfs_dquot_t *xfs_inode_dquot(struct xfs_inode *ip, int type)
> >  #define XFS_DQ_TO_QINF(dqp)	((dqp)->q_mount->m_quotainfo)
> >  #define XFS_DQ_TO_QIP(dqp)	(XFS_QM_ISUDQ(dqp) ? \
> >  				 XFS_DQ_TO_QINF(dqp)->qi_uquotaip : \
> > -				 XFS_DQ_TO_QINF(dqp)->qi_gquotaip)
> > +				 (XFS_QM_ISGDQ(dqp) ? \
> > +				 XFS_DQ_TO_QINF(dqp)->qi_gquotaip : \
> > +				 XFS_DQ_TO_QINF(dqp)->qi_pquotaip))
> 
> nested ?: constructs are a bit nasty. Perhaps this should be
> converted to a static inline function like:
> 
> static inline struct xfs_inode *
> xfs_dq_to_quota_inode(
> 	struct xfs_dquot	*dqp)
> {
> 	if (XFS_QM_ISUDQ(dqp))
> 		return dqp->q_mount->m_quotainfo->qi_uquotaip;
> 	if (XFS_QM_ISGDQ(dqp))
> 		return dqp->q_mount->m_quotainfo->qi_gquotaip;
> 	ASSERT(XFS_QM_ISPDQ(dqp)));
> 	return dqp->q_mount->m_quotainfo->qi_pquotaip;
> }
> 
> 
> >  
> >  extern int		xfs_qm_dqread(struct xfs_mount *, xfs_dqid_t, uint,
> >  					uint, struct xfs_dquot	**);
> > diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c
> > index 1bb4365..e97fb18 100644
> > --- a/fs/xfs/xfs_iget.c
> > +++ b/fs/xfs/xfs_iget.c
> > @@ -346,7 +346,7 @@ xfs_iget_cache_miss(
> >  	iflags = XFS_INEW;
> >  	if (flags & XFS_IGET_DONTCACHE)
> >  		iflags |= XFS_IDONTCACHE;
> > -	ip->i_udquot = ip->i_gdquot = NULL;
> > +	ip->i_udquot = ip->i_gdquot = ip->i_pdquot = NULL;
> 
> That's getting a little messy. I think you should convert these to
> an assignment per line. i.e:
> 
> 	ip->i_udquot = NULL;
> 	ip->i_gdquot = NULL;
> 	ip->i_pdquot = NULL;
> 
> > diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c
> > index 3fb3730..46c7e4c 100644
> > --- a/fs/xfs/xfs_qm.c
> > +++ b/fs/xfs/xfs_qm.c
> > @@ -134,7 +134,7 @@ xfs_qm_dqpurge(
> >  {
> >  	struct xfs_mount	*mp = dqp->q_mount;
> >  	struct xfs_quotainfo	*qi = mp->m_quotainfo;
> > -	struct xfs_dquot	*gdqp = NULL;
> > +	struct xfs_dquot	*gdqp = NULL, *pdqp = NULL;
> 
> New variable on a new line.
> 
> >  
> >  	xfs_dqlock(dqp);
> >  	if ((dqp->dq_flags & XFS_DQ_FREEING) || dqp->q_nrefs != 0) {
> > @@ -143,8 +143,8 @@ xfs_qm_dqpurge(
> >  	}
> >  
> >  	/*
> > -	 * If this quota has a group hint attached, prepare for releasing it
> > -	 * now.
> > +	 * If this quota has a group/project hint attached, prepare for
> > +	 * releasing it now.
> 
> I'd just say "If this quota has a hint attached..."
> 
> >  /*
> > - * Given a udquot and gdquot, attach a ptr to the group dquot in the
> > + * Given a udquot and gdquot, attach a ptr to the group/project dquot in the
> >   * udquot as a hint for future lookups.
> >   */
> >  STATIC void
> > -xfs_qm_dqattach_grouphint(
> > -	xfs_dquot_t	*udq,
> > -	xfs_dquot_t	*gdq)
> > +xfs_qm_dqattach_grouphint(xfs_inode_t *ip, int type)
> >  {
> > -	xfs_dquot_t	*tmp;
> > +	xfs_dquot_t	**tmp, *gpdq, *tmp1, *udq = ip->i_udquot;
> 
> Don't use typedefs for new definitions, tmp is a really bad name,
> and use consistent style:
> 
> STATIC void
> xfs_qm_dqattach_grouphint(
> 	struct xfs_inode	*ip,
> 	int			type)
> {
> 	struct xfs_dquot	*udq = ip->i_udquot;
> 	struct xfs_dquot	*gpdq;
> 	struct xfs_dquot	**dqhint;
> 	struct xfs_dquot	*tmp1;
> 
> > +	gpdq = (type == XFS_DQ_GROUP) ? ip->i_gdquot : ip->i_pdquot;
> >  	xfs_dqlock(udq);
> >  
> > -	tmp = udq->q_gdquot;
> > -	if (tmp) {
> > -		if (tmp == gdq)
> > +	tmp = (type == XFS_DQ_GROUP) ? &udq->q_gdquot : &udq->q_pdquot;
> 
> 	if (type == XFS_DQ_GROUP) {
> 		gpdq = ip->i_gdquot;
> 		dqhint = &udq->q_gdquot;
> 	} else {
> 		gpdq = ip->i_gdquot;
> 		dqhint = &udq->q_gdquot;
> 	}
> 
> > +
> > +	if (*tmp) {
> > +		if (*tmp == gpdq)
> >  			goto done;
> >  
> > -		udq->q_gdquot = NULL;
> > -		xfs_qm_dqrele(tmp);
> > +		tmp1 = *tmp;
> > +		*tmp = NULL;
> > +		xfs_qm_dqrele(tmp1);
> >  	}
> >  
> > -	udq->q_gdquot = xfs_qm_dqhold(gdq);
> > +	*tmp = xfs_qm_dqhold(gpdq);
> 
> 	if (*dqhint) {
> 		struct xfs_dquot	*tmp;
> 
> 		if (*dqhint == gpdq)
> 			goto done;
> 
> 		tmp = *dqhint;
> 		*dqhint = NULL;
> 		xfs_qm_rele(tmp);
> 	}
> 	*dqhint = xfs_qm_dqhold(gpdq);
> 
> And when we get rid of the tmp names, all of a sudden the code goes
> from being unreadable to being obviously suboptimal. i.e:
> 
> 	if (*dqhint == gpdq)
> 		goto done;
> 
> 	if (*dqhint)
> 		xfs_qm_rele(*dqhint);
> 	*dqhint = xfs_qm_dqhold(gpdq);
> 
> We don't need the second temp variable because we have the dquot
> locked and so nobody is going to be accessing the hint in the dquot
> after we've released it. If they are accessing it unlocked, then it
> is already racy and setting the dqhint to null doesn't change
> anything....
> 
> > @@ -1227,7 +1269,7 @@ xfs_qm_quotacheck(
> >  	int		done, count, error, error2;
> >  	xfs_ino_t	lastino;
> >  	size_t		structsz;
> > -	xfs_inode_t	*uip, *gip;
> > +	xfs_inode_t	*uip, *gip, *pip;
> 
> 	struct xfs_inode *uip = mp->m_quotainfo->qi_uquotaip;
> 	struct xfs_inode *gip = mp->m_quotainfo->qi_gquotaip;
> 	struct xfs_inode *pip = mp->m_quotainfo->qi_pquotaip;
> 
> >  	uint		flags;
> >  	LIST_HEAD	(buffer_list);
> >  
> > @@ -1236,7 +1278,8 @@ xfs_qm_quotacheck(
> >  	lastino = 0;
> >  	flags = 0;
> >  
> > -	ASSERT(mp->m_quotainfo->qi_uquotaip || mp->m_quotainfo->qi_gquotaip);
> > +	ASSERT(mp->m_quotainfo->qi_uquotaip || mp->m_quotainfo->qi_gquotaip
> > +			|| mp->m_quotainfo->qi_pquotaip);
> 
> 	ASSERT(uip || gip || pip);
> 
> >  	ASSERT(XFS_IS_QUOTA_RUNNING(mp));
> >  
> >  	xfs_notice(mp, "Quotacheck needed: Please wait.");
> > @@ -1257,13 +1300,20 @@ xfs_qm_quotacheck(
> >  
> >  	gip = mp->m_quotainfo->qi_gquotaip;
> >  	if (gip) {
> > -		error = xfs_qm_dqiterate(mp, gip, XFS_IS_GQUOTA_ON(mp) ?
> > -					 XFS_QMOPT_GQUOTA : XFS_QMOPT_PQUOTA,
> > +		error = xfs_qm_dqiterate(mp, gip, XFS_QMOPT_GQUOTA,
> >  					 &buffer_list);
> >  		if (error)
> >  			goto error_return;
> > -		flags |= XFS_IS_GQUOTA_ON(mp) ?
> > -					XFS_GQUOTA_CHKD : XFS_PQUOTA_CHKD;
> > +		flags |= XFS_GQUOTA_CHKD;
> > +	}
> > +
> > +	pip = mp->m_quotainfo->qi_pquotaip;
> > +	if (pip) {
> > +		error = xfs_qm_dqiterate(mp, pip, XFS_QMOPT_PQUOTA,
> > +					 &buffer_list);
> > +		if (error)
> > +			goto error_return;
> > +		flags |= XFS_PQUOTA_CHKD;
> >  	}
> >  
> >  	do {
> > @@ -1358,13 +1408,13 @@ STATIC int
> >  xfs_qm_init_quotainos(
> >  	xfs_mount_t	*mp)
> >  {
> > -	xfs_inode_t	*uip, *gip;
> > +	xfs_inode_t	*uip, *gip, *pip;
> >  	int		error;
> >  	__int64_t	sbflags;
> >  	uint		flags;
> >  
> >  	ASSERT(mp->m_quotainfo);
> > -	uip = gip = NULL;
> > +	uip = gip = pip = NULL;
> 
> Same as above.
> 
> >  	sbflags = 0;
> >  	flags = 0;
> >  
> > @@ -1379,7 +1429,7 @@ xfs_qm_init_quotainos(
> >  					     0, 0, &uip)))
> >  				return XFS_ERROR(error);
> >  		}
> > -		if (XFS_IS_OQUOTA_ON(mp) &&
> > +		if (XFS_IS_GQUOTA_ON(mp) &&
> >  		    mp->m_sb.sb_gquotino != NULLFSINO) {
> >  			ASSERT(mp->m_sb.sb_gquotino > 0);
> >  			if ((error = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino,
> > @@ -1389,6 +1439,19 @@ xfs_qm_init_quotainos(
> >  				return XFS_ERROR(error);
> >  			}
> >  		}
> > +		if (XFS_IS_PQUOTA_ON(mp) &&
> > +		    mp->m_sb.sb_pquotino != NULLFSINO) {
> > +			ASSERT(mp->m_sb.sb_pquotino > 0);
> > +			error = xfs_iget(mp, NULL, mp->m_sb.sb_pquotino,
> > +					     0, 0, &pip);
> > +			if (error) {
> > +				if (uip)
> > +					IRELE(uip);
> > +				if (gip)
> > +					IRELE(gip);
> > +				return XFS_ERROR(error);
> > +			}
> 
> This error handling is repeated a couple of times. It is better to
> use an error stack at the end of the function for this. i.e.
> 
> 			if (error)
> 				goto error_rele;
> 	...
> 
> 	return 0;
> 
> error_rele:
> 	if (uip)
> 		IRELE(uip);
> 	if (gip)
> 		IRELE(gip);
> 	if (pip)
> 		IRELE(pip);
> 	return XFS_ERROR(error);
> }
> 
> > @@ -1621,10 +1697,11 @@ xfs_qm_vop_dqalloc(
> >  	prid_t			prid,
> >  	uint			flags,
> >  	struct xfs_dquot	**O_udqpp,
> > -	struct xfs_dquot	**O_gdqpp)
> > +	struct xfs_dquot	**O_gdqpp,
> > +	struct xfs_dquot	**O_pdqpp)
> >  {
> >  	struct xfs_mount	*mp = ip->i_mount;
> > -	struct xfs_dquot	*uq, *gq;
> > +	struct xfs_dquot	*uq, *gq, *pq;
> 
> Separate lines with initialisation...
> 
> >  	int			error;
> >  	uint			lockflags;
> >  
> > @@ -1649,7 +1726,7 @@ xfs_qm_vop_dqalloc(
> >  		}
> >  	}
> >  
> > -	uq = gq = NULL;
> > +	uq = gq = pq = NULL;
> 
> So this can be killed.
> 
> >  	if ((flags & XFS_QMOPT_UQUOTA) && XFS_IS_UQUOTA_ON(mp)) {
> >  		if (ip->i_d.di_uid != uid) {
> >  			/*
> > @@ -1705,25 +1782,28 @@ xfs_qm_vop_dqalloc(
> >  			ASSERT(ip->i_gdquot);
> >  			gq = xfs_qm_dqhold(ip->i_gdquot);
> >  		}
> > -	} else if ((flags & XFS_QMOPT_PQUOTA) && XFS_IS_PQUOTA_ON(mp)) {
> > +	}
> > +	if ((flags & XFS_QMOPT_PQUOTA) && XFS_IS_PQUOTA_ON(mp)) {
> >  		if (xfs_get_projid(ip) != prid) {
> >  			xfs_iunlock(ip, lockflags);
> >  			if ((error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t)prid,
> >  						 XFS_DQ_PROJ,
> >  						 XFS_QMOPT_DQALLOC |
> >  						 XFS_QMOPT_DOWARN,
> > -						 &gq))) {
> > +						 &pq))) {
> 
> Separate the function call fro the if() statement. Also, both dqid_t
> and prid_t are uint32_t, so there is no need for a cast:
> 
> 			error = xfs_qm_dqget(mp, NULL, prid, XFS_DQ_PROJ,
> 					XFS_QMOPT_DQALLOC | XFS_QMOPT_DOWARN,
> 					&gq);
> 			if (error) {
> 				....
> 
> > @@ -1790,11 +1874,13 @@ xfs_qm_vop_chown_reserve(
> >  	xfs_inode_t	*ip,
> >  	xfs_dquot_t	*udqp,
> >  	xfs_dquot_t	*gdqp,
> > +	xfs_dquot_t	*pdqp,
> 
> Probably should remove the typedefs while adding new parameters.
> >  	uint		flags)
> >  {
> >  	xfs_mount_t	*mp = ip->i_mount;
> >  	uint		delblks, blkflags, prjflags = 0;
> > -	xfs_dquot_t	*unresudq, *unresgdq, *delblksudq, *delblksgdq;
> > +	xfs_dquot_t	*unresudq, *unresgdq, *unrespdq;
> > +	xfs_dquot_t	*delblksudq, *delblksgdq, *delblkspdq;
> >  	int		error;
> 
> Same here, and use one variable per line with initialisation.
> >  
> >  
> > @@ -1802,7 +1888,8 @@ xfs_qm_vop_chown_reserve(
> >  	ASSERT(XFS_IS_QUOTA_RUNNING(mp));
> >  
> >  	delblks = ip->i_delayed_blks;
> > -	delblksudq = delblksgdq = unresudq = unresgdq = NULL;
> > +	delblksudq = delblksgdq = delblkspdq = NULL;
> > +	unresudq = unresgdq = unrespdq = NULL;
> 
> So this can be removed.
> 
> >  	blkflags = XFS_IS_REALTIME_INODE(ip) ?
> >  			XFS_QMOPT_RES_RTBLKS : XFS_QMOPT_RES_REGBLKS;
> >  
> > @@ -1819,25 +1906,28 @@ xfs_qm_vop_chown_reserve(
> >  			unresudq = ip->i_udquot;
> >  		}
> >  	}
> > -	if (XFS_IS_OQUOTA_ON(ip->i_mount) && gdqp) {
> > -		if (XFS_IS_PQUOTA_ON(ip->i_mount) &&
> > -		     xfs_get_projid(ip) != be32_to_cpu(gdqp->q_core.d_id))
> > -			prjflags = XFS_QMOPT_ENOSPC;
> > -
> > -		if (prjflags ||
> > -		    (XFS_IS_GQUOTA_ON(ip->i_mount) &&
> > -		     ip->i_d.di_gid != be32_to_cpu(gdqp->q_core.d_id))) {
> > -			delblksgdq = gdqp;
> > -			if (delblks) {
> > -				ASSERT(ip->i_gdquot);
> > -				unresgdq = ip->i_gdquot;
> > -			}
> > +	if (XFS_IS_GQUOTA_ON(ip->i_mount) && gdqp &&
> > +	    ip->i_d.di_gid != be32_to_cpu(gdqp->q_core.d_id)) {
> > +		delblksgdq = gdqp;
> > +		if (delblks) {
> > +			ASSERT(ip->i_gdquot);
> > +			unresgdq = ip->i_gdquot;
> > +		}
> > +	}
> > +
> > +	if (XFS_IS_PQUOTA_ON(ip->i_mount) && pdqp &&
> > +	    xfs_get_projid(ip) != be32_to_cpu(pdqp->q_core.d_id)) {
> > +		prjflags = XFS_QMOPT_ENOSPC;
> > +		delblkspdq = pdqp;
> > +		if (delblks) {
> > +			ASSERT(ip->i_pdquot);
> > +			unrespdq = ip->i_pdquot;
> >  		}
> >  	}
> >  
> >  	if ((error = xfs_trans_reserve_quota_bydquots(tp, ip->i_mount,
> > -				delblksudq, delblksgdq, ip->i_d.di_nblocks, 1,
> > -				flags | blkflags | prjflags)))
> > +			delblksudq, delblksgdq, delblkspdq, ip->i_d.di_nblocks,
> > +			1, flags | blkflags | prjflags)))
> 
> Separate the function call from the if().
> 
> >  		return (error);
> >  
> >  	/*
> > @@ -1850,15 +1940,16 @@ xfs_qm_vop_chown_reserve(
> >  		/*
> >  		 * Do the reservations first. Unreservation can't fail.
> >  		 */
> > -		ASSERT(delblksudq || delblksgdq);
> > -		ASSERT(unresudq || unresgdq);
> > +		ASSERT(delblksudq || delblksgdq || delblkspdq);
> > +		ASSERT(unresudq || unresgdq || unrespdq);
> >  		if ((error = xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount,
> > -				delblksudq, delblksgdq, (xfs_qcnt_t)delblks, 0,
> > +				delblksudq, delblksgdq, delblkspdq,
> > +				(xfs_qcnt_t)delblks, 0,
> >  				flags | blkflags | prjflags)))
> 
> Same again.
> 
> > diff --git a/fs/xfs/xfs_qm.h b/fs/xfs/xfs_qm.h
> > index 44b858b..256ff71 100644
> > --- a/fs/xfs/xfs_qm.h
> > +++ b/fs/xfs/xfs_qm.h
> > @@ -44,9 +44,11 @@ extern struct kmem_zone	*xfs_qm_dqtrxzone;
> >  typedef struct xfs_quotainfo {
> >  	struct radix_tree_root qi_uquota_tree;
> >  	struct radix_tree_root qi_gquota_tree;
> > +	struct radix_tree_root qi_pquota_tree;
> >  	struct mutex qi_tree_lock;
> >  	xfs_inode_t	*qi_uquotaip;	 /* user quota inode */
> >  	xfs_inode_t	*qi_gquotaip;	 /* group quota inode */
> > +	xfs_inode_t	*qi_pquotaip;	 /* project quota inode */
> 
> convert to struct xfs_inode.
> 
> >  	struct list_head qi_lru_list;
> >  	struct mutex	 qi_lru_lock;
> >  	int		 qi_lru_count;
> > @@ -70,26 +72,25 @@ typedef struct xfs_quotainfo {
> >  } xfs_quotainfo_t;
> >  
> >  #define XFS_DQUOT_TREE(qi, type) \
> > -	((type & XFS_DQ_USER) ? \
> > -	 &((qi)->qi_uquota_tree) : \
> > -	 &((qi)->qi_gquota_tree))
> > +	((type & XFS_DQ_USER) ? &((qi)->qi_uquota_tree) : \
> > +	((type & XFS_DQ_GROUP) ? &((qi)->qi_gquota_tree) : \
> > +	 &((qi)->qi_pquota_tree)))
> 
> Convert to static inline, I think.
> 
> static inline struct radix_tree_root *
> xfs_dquot_tree(
> 	struct xfs_quotainfo	*qi,
> 	int			type)
> {
> 	switch(type) {
> 	case XFS_DQ_USER:
> 		return qi->qi_uquota_tree;
> 	case XFS_DQ_GROUP:
> 		return qi->qi_gquota_tree;
> 	case XFS_DQ_PROJ:
> 		return qi->qi_pquota_tree;
> 	default:
> 		ASSERT(0);
> 	}
> 	return NULL;
> }
> 
> > @@ -267,8 +265,10 @@ typedef struct xfs_qoff_logformat {
> >   */
> >  #define XFS_NOT_DQATTACHED(mp, ip) ((XFS_IS_UQUOTA_ON(mp) &&\
> >  				     (ip)->i_udquot == NULL) || \
> > -				    (XFS_IS_OQUOTA_ON(mp) && \
> > -				     (ip)->i_gdquot == NULL))
> > +				    (XFS_IS_GQUOTA_ON(mp) && \
> > +				     (ip)->i_gdquot == NULL) || \
> > +				    (XFS_IS_PQUOTA_ON(mp) && \
> > +				     (ip)->i_pdquot == NULL))
> 
> #define XFS_NOT_DQATTACHED(mp, ip)	\
> 	((XFS_IS_UQUOTA_ON(mp) && (ip)->i_udquot == NULL) || \
> 	 (XFS_IS_GQUOTA_ON(mp) && (ip)->i_gdquot == NULL) || \
> 	 (XFS_IS_PQUOTA_ON(mp) && (ip)->i_pdquot == NULL))
> 
> > +++ b/fs/xfs/xfs_trans_dquot.c
> > @@ -113,7 +113,7 @@ xfs_trans_dup_dqinfo(
> >  	if(otp->t_flags & XFS_TRANS_DQ_DIRTY)
> >  		ntp->t_flags |= XFS_TRANS_DQ_DIRTY;
> >  
> > -	for (j = 0; j < 2; j++) {
> > +	for (j = 0; j < 3; j++) { /* 0 - usr, 1 - grp, 2 - prj */
> >  		for (i = 0; i < XFS_QM_TRANS_MAXDQS; i++) {
> >  			if (oqa[i].qt_dquot == NULL)
> >  				break;
> > @@ -138,8 +138,13 @@ xfs_trans_dup_dqinfo(
> >  			oq->qt_ino_res = oq->qt_ino_res_used;
> >  
> >  		}
> > -		oqa = otp->t_dqinfo->dqa_grpdquots;
> > -		nqa = ntp->t_dqinfo->dqa_grpdquots;
> > +		if (oqa == otp->t_dqinfo->dqa_usrdquots) {
> > +			oqa = otp->t_dqinfo->dqa_grpdquots;
> > +			nqa = ntp->t_dqinfo->dqa_grpdquots;
> > +		} else {
> > +			oqa = otp->t_dqinfo->dqa_prjdquots;
> > +			nqa = ntp->t_dqinfo->dqa_prjdquots;
> > +		}
> >  	}
> 
> Ok, that's just plain nasty. And it's repeated nastiness.
> 
> I think that the best thing to do is redefine the struct
> xfs_dquot_acct to something like:
> 
> enum {
> 	XFS_QM_TRANS_USR = 0,
> 	XFS_QM_TRANS_GRP,
> 	XFS_QM_TRANS_PROJ,
> 	XFS_QM_TRANS_DQTYPES,
> };
> #define XFS_QM_TRANS_MAXDQS 2
> struct xfs_dquot_acct {
> 	struct xfs_dqtrx dqs[XFS_QM_TRANS_DQTYPES][XFS_QM_TRANS_MAXDQS];
> }
> 
> 
> and that makes all these loops something like:
> 
> 	for (j = 0; j < XFS_QM_TRANS_DQTYPES; j++) {
> 		oqa = &otp->t_dqinfo->dqs[j];
> 
> 		for (i = 0; i < XFS_QM_TRANS_MAXDQS; i++) {
> 		....
> 		}
> 	}
> 
> And all this nastiness of selecting the next structure element goes
> away.
> 
> >  STATIC xfs_dqtrx_t *
> > @@ -178,15 +185,20 @@ xfs_trans_get_dqtrx(
> >  	int		i;
> >  	xfs_dqtrx_t	*qa;
> >  
> > -	qa = XFS_QM_ISUDQ(dqp) ?
> > -		tp->t_dqinfo->dqa_usrdquots : tp->t_dqinfo->dqa_grpdquots;
> > +	if (XFS_QM_ISUDQ(dqp))
> > +		qa = tp->t_dqinfo->dqa_usrdquots;
> 
> 		qa = &tp->t_dqinfo->dqs[XFS_QM_TRANS_USR];
> 
> > +	else if (XFS_QM_ISGDQ(dqp))
> > +		qa = tp->t_dqinfo->dqa_grpdquots;
> 
> 		qa = &tp->t_dqinfo->dqs[XFS_QM_TRANS_GRP];
> 
> > +	else if (XFS_QM_ISPDQ(dqp))
> > +		qa = tp->t_dqinfo->dqa_prjdquots;
> 
> 		qa = &tp->t_dqinfo->dqs[XFS_QM_TRANS_PROJ];
> 
> > +	else
> > +		return NULL;
> >  
> >  	for (i = 0; i < XFS_QM_TRANS_MAXDQS; i++) {
> >  		if (qa[i].qt_dquot == NULL ||
> >  		    qa[i].qt_dquot == dqp)
> >  			return &qa[i];
> >  	}
> > -
> >  	return NULL;
> >  }
> >  
> > @@ -340,9 +352,12 @@ xfs_trans_apply_dquot_deltas(
> >  
> >  	ASSERT(tp->t_dqinfo);
> >  	qa = tp->t_dqinfo->dqa_usrdquots;
> > -	for (j = 0; j < 2; j++) {
> > +	for (j = 0; j < 3; j++) { /* 0 - usr, 1 - grp, 2 - prj */
> 
> Comments aren't necessary like this if the above enum/array
> construct is used.
> 
> >  		if (qa[0].qt_dquot == NULL) {
> > -			qa = tp->t_dqinfo->dqa_grpdquots;
> > +			if (qa == tp->t_dqinfo->dqa_usrdquots)
> > +				qa = tp->t_dqinfo->dqa_grpdquots;
> > +			else
> > +				qa = tp->t_dqinfo->dqa_prjdquots;
> >  			continue;
> >  		}
> >  
> > @@ -496,9 +511,12 @@ xfs_trans_apply_dquot_deltas(
> >  				be64_to_cpu(dqp->q_core.d_rtbcount));
> >  		}
> >  		/*
> > -		 * Do the group quotas next
> > +		 * Do the group quotas or project quotas next
> >  		 */
> > -		qa = tp->t_dqinfo->dqa_grpdquots;
> > +		if (qa == tp->t_dqinfo->dqa_usrdquots)
> > +			qa = tp->t_dqinfo->dqa_grpdquots;
> > +		else
> > +			qa = tp->t_dqinfo->dqa_prjdquots;
> >  	}
> >  }
> >  
> > @@ -523,7 +541,7 @@ xfs_trans_unreserve_and_mod_dquots(
> >  
> >  	qa = tp->t_dqinfo->dqa_usrdquots;
> >  
> > -	for (j = 0; j < 2; j++) {
> > +	for (j = 0; j < 3; j++) { /* 0 - usr, 1 - grp, 2 - prj */
> >  		for (i = 0; i < XFS_QM_TRANS_MAXDQS; i++) {
> >  			qtrx = &qa[i];
> >  			/*
> > @@ -565,7 +583,10 @@ xfs_trans_unreserve_and_mod_dquots(
> >  				xfs_dqunlock(dqp);
> >  
> >  		}
> > -		qa = tp->t_dqinfo->dqa_grpdquots;
> > +		if (qa == tp->t_dqinfo->dqa_usrdquots)
> > +			qa = tp->t_dqinfo->dqa_grpdquots;
> > +		else
> > +			qa = tp->t_dqinfo->dqa_prjdquots;
> >  	}
> 
> And all this repeated nastiness goes away...
> 
> >  }
> >  
> > @@ -734,8 +755,8 @@ error_return:
> >  
> >  /*
> >   * Given dquot(s), make disk block and/or inode reservations against them.
> > - * The fact that this does the reservation against both the usr and
> > - * grp/prj quotas is important, because this follows a both-or-nothing
> > + * The fact that this does the reservation against user, group and
> > + * project quotas is important, because this follows a all-or-nothing
> >   * approach.
> >   *
> >   * flags = XFS_QMOPT_FORCE_RES evades limit enforcement. Used by chown.
> > @@ -750,6 +771,7 @@ xfs_trans_reserve_quota_bydquots(
> >  	xfs_mount_t	*mp,
> >  	xfs_dquot_t	*udqp,
> >  	xfs_dquot_t	*gdqp,
> > +	xfs_dquot_t	*pdqp,
> >  	long		nblks,
> >  	long		ninos,
> >  	uint		flags)
> 
> kill the typedefs.
> 
> > @@ -787,6 +809,24 @@ xfs_trans_reserve_quota_bydquots(
> >  		}
> >  	}
> >  
> > +	if (pdqp) {
> > +		error = xfs_trans_dqresv(tp, mp, pdqp, nblks, ninos, flags);
> > +		if (error) {
> > +			/*
> > +			 * can't do it, so backout previous reservation
> > +			 */
> > +			if (resvd) {
> > +				flags |= XFS_QMOPT_FORCE_RES;
> > +				xfs_trans_dqresv(tp, mp, udqp,
> > +						 -nblks, -ninos, flags);
> > +				if (gdqp)
> > +					xfs_trans_dqresv(tp, mp, gdqp,
> > +						 -nblks, -ninos, flags);
> > +			}
> > +			return error;
> > +		}
> > +	}
> > +
> 
> This will only unwind group reservation is there was a user quota
> reservation. I think that is wrong.
> 
> I think an unwind stack is better than the nested error
> handling, and it removes the need for the "resvd" variable to
> indicate that a user quota modification was made. i.e.
> 
> 	if (udqp) {
> 		....
> 		if (error)
> 			return error;
> 		....
> 	}
> 	if (gdqp) {
> 		....
> 		if (error)
> 			goto unwind_usr;
> 		....
> 	}
> 	if (pdqp) {
> 		....
> 		if (error)
> 			goto unwind_grp;
> 		....
> 	}
> 
> 
> unwind_grp:
> 	flags |= XFS_QMOPT_FORCE_RES
> 	if (gdqp)
> 		xfs_trans_dqresv(tp, mp, gdqp, -nblks, -ninos, flags);
> unwind_usr:
> 	flags |= XFS_QMOPT_FORCE_RES
> 	if (udqp)
> 		xfs_trans_dqresv(tp, mp, udqp, -nblks, -ninos, flags);
> 	return error;
> 
> > @@ -1498,7 +1502,7 @@ xfs_symlink(
> >  	int			n;
> >  	xfs_buf_t		*bp;
> >  	prid_t			prid;
> > -	struct xfs_dquot	*udqp, *gdqp;
> > +	struct xfs_dquot	*udqp = NULL, *gdqp = NULL, *pdqp = NULL;
> 
> One per line.
> 
> Cheers,
> 
> Dave.


_______________________________________________
xfs mailing list
xfs@xxxxxxxxxxx
http://oss.sgi.com/mailman/listinfo/xfs


[Index of Archives]     [Linux XFS Devel]     [Linux Filesystem Development]     [Filesystem Testing]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux