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

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

 



On Fri, 2013-05-17 at 14:23 +1000, Dave Chinner wrote: 
> On Fri, May 10, 2013 at 04:21:26PM -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.
> 
> Looks pretty good. Some relatively minor changes below.
> 
> > @@ -568,6 +567,17 @@ xfs_qm_dqrepair(
> >  	return 0;
> >  }
> >  
> > +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;
> > +}
> 
> Consolidate this with xfs_dquot_tree() as a static inline function,
> I think. Let's try and keep all these little helpers together so
> they are easy to find ;)

will do. 
> 
> > +
> >  /*
> >   * Maps a dquot to the buffer containing its on-disk version.
> >   * This returns a ptr to the buffer containing the on-disk dquot
> > @@ -584,7 +594,7 @@ xfs_qm_dqtobp(
> >  	xfs_bmbt_irec_t map;
> >  	int		nmaps = 1, error;
> >  	xfs_buf_t	*bp;
> > -	xfs_inode_t	*quotip = XFS_DQ_TO_QIP(dqp);
> > +	xfs_inode_t	*quotip = xfs_dq_to_quota_inode(dqp);
> 
> convert to struct xfs_inode a the same time....

will do 
> 
> > @@ -52,7 +51,8 @@ typedef struct xfs_dquot {
> > @@ -144,9 +146,6 @@ static inline xfs_dquot_t *xfs_inode_dquot(struct xfs_inode *ip, int type)
> >  #define XFS_QM_ISPDQ(dqp)	((dqp)->dq_flags & XFS_DQ_PROJ)
> >  #define XFS_QM_ISGDQ(dqp)	((dqp)->dq_flags & XFS_DQ_GROUP)
> >  #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_DQ_TO_QINF can go away, too.

sure 
> 
> > --- a/fs/xfs/xfs_ioctl.c
> > +++ b/fs/xfs/xfs_ioctl.c
> > @@ -928,7 +928,7 @@ xfs_ioctl_setattr(
> >  	struct xfs_trans	*tp;
> >  	unsigned int		lock_flags = 0;
> >  	struct xfs_dquot	*udqp = NULL;
> > -	struct xfs_dquot	*gdqp = NULL;
> > +	struct xfs_dquot	*pdqp = NULL;
> >  	struct xfs_dquot	*olddquot = NULL;
> >  	int			code;
> >  
> > @@ -957,7 +957,7 @@ xfs_ioctl_setattr(
> >  	if (XFS_IS_QUOTA_ON(mp) && (mask & FSX_PROJID)) {
> >  		code = xfs_qm_vop_dqalloc(ip, ip->i_d.di_uid,
> >  					 ip->i_d.di_gid, fa->fsx_projid,
> > -					 XFS_QMOPT_PQUOTA, &udqp, &gdqp);
> > +					 XFS_QMOPT_PQUOTA, &udqp, NULL, &pdqp);
> 
> We're only passing in XFS_QMOPT_PQUOTA, so we do not need to pass in
> uid, gid, udqp or gdqp here....
> 
> Can you add a comment here that this may cause user/group quotas
> to be allocated, but we don't need it here in this function because
> we are only specifically changing the project quota via a chown
> operation.
> 
> Indeed, the only reason a user quota is passed in is to make use of
> the dquot hint that the udq might hold that points to the other
> dquots on the inode....

will do 
> 
> >  		if (code)
> >  			return code;
> >  	}
> > @@ -994,8 +994,8 @@ xfs_ioctl_setattr(
> >  		    XFS_IS_PQUOTA_ON(mp) &&
> >  		    xfs_get_projid(ip) != fa->fsx_projid) {
> >  			ASSERT(tp);
> > -			code = xfs_qm_vop_chown_reserve(tp, ip, udqp, gdqp,
> > -						capable(CAP_FOWNER) ?
> > +			code = xfs_qm_vop_chown_reserve(tp, ip, udqp, NULL,
> > +						pdqp, capable(CAP_FOWNER) ?
> >  						XFS_QMOPT_FORCE_RES : 0);
> > @@ -1113,7 +1113,7 @@ xfs_ioctl_setattr(
> >  		if (xfs_get_projid(ip) != fa->fsx_projid) {
> >  			if (XFS_IS_QUOTA_RUNNING(mp) && XFS_IS_PQUOTA_ON(mp)) {
> >  				olddquot = xfs_qm_vop_chown(tp, ip,
> > -							&ip->i_gdquot, gdqp);
> > +							&ip->i_pdquot, pdqp);
> 
> xfs_qm_vop_chown() is only called on one dquot at a time, so it can
> only exchange one dquot at a time. and udqp is not used for hints,
> so it looks to me like udqp and gdqp are wholly unnecessary in this
> function....

Did not fully understand this comment. Can you please elaborate ?

> 
> > diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
> > index d82efaa..7c54ea4 100644
> > --- a/fs/xfs/xfs_iops.c
> > +++ b/fs/xfs/xfs_iops.c
> > @@ -517,7 +517,7 @@ xfs_setattr_nonsize(
> >  		ASSERT(udqp == NULL);
> >  		ASSERT(gdqp == NULL);
> >  		error = xfs_qm_vop_dqalloc(ip, uid, gid, xfs_get_projid(ip),
> > -					 qflags, &udqp, &gdqp);
> > +					 qflags, &udqp, &gdqp, NULL);
> 
> Why is there no project quota support here, even though we pass in a
> project ID? I know the answer, but please add a comment so that a
> couple of years down the track I don't need to go remind myself of
> why....

Not clear what you are expecting here.

> 
> >  /*
> > - * 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)
> 
> Wrong format for the function header And it's not longer just for
> the group dquot, so I'd rename just to xfs_qm_dqattach_hint. i.e:

will fix.

> 
> STATIC void
> xfs_qm_dqattach_hint(
> 	struct xfs_inode	*ip,
> 	int			 type)
> 
> >  {
> > -	xfs_dquot_t	*tmp;
> > +	struct xfs_dquot **dqhint;
> > +	struct xfs_dquot *gpdq;
> 
> not a group dquot. so perhaps just call it dqp?

sure. 
> 
> > @@ -1395,19 +1453,27 @@ xfs_qm_init_quotainos(
> >  		if (XFS_IS_UQUOTA_ON(mp) &&
> >  		    mp->m_sb.sb_uquotino != NULLFSINO) {
> >  			ASSERT(mp->m_sb.sb_uquotino > 0);
> > -			if ((error = xfs_iget(mp, NULL, mp->m_sb.sb_uquotino,
> > -					     0, 0, &uip)))
> > +			error = xfs_iget(mp, NULL, mp->m_sb.sb_uquotino,
> > +					     0, 0, &uip);
> > +			if (error)
> >  				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,
> > -					     0, 0, &gip))) {
> > -				if (uip)
> > -					IRELE(uip);
> > -				return XFS_ERROR(error);
> > -			}
> > +			error = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino,
> > +					     0, 0, &gip);
> > +			if (error)
> > +				goto error_rele;
> > +		}
> > +		/* Use sb_gquotino for now */
> > +		if (XFS_IS_PQUOTA_ON(mp) &&
> > +		    mp->m_sb.sb_gquotino != NULLFSINO) {
> > +			ASSERT(mp->m_sb.sb_gquotino > 0);
> > +			error = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino,
> > +					     0, 0, &pip);
> > +			if (error)
> > +				goto error_rele;
> 
> There is no need for this trickery, right? All that is needed is:
> 
Will be taken care of in the next patch.

> 
> 
> 			qino = xfs_sb_version_has_pquota(&mp->m_sb) ?
> 						mp->m_sb.sb_pquotino :
> 						mp->m_sb.sb_gquotino;
> 
> And the correct on-disk inode is read....
> 
The object of this patch is to replace all gquota with pquota stuff. I
am not using the pquotino or xfs_sb_version_has_pquota() until patch 3.

If I get the change forward, I have to merge patch 3 and part of this
patch into patch 1, which adds up lots of work.

The way the patches are split now, IMO, is easy to follow and works
independently.
> 
> > @@ -1804,15 +1896,21 @@ xfs_qm_vop_chown(
> >   */
> >  int
> >  xfs_qm_vop_chown_reserve(
> > -	xfs_trans_t	*tp,
> > -	xfs_inode_t	*ip,
> > -	xfs_dquot_t	*udqp,
> > -	xfs_dquot_t	*gdqp,
> > -	uint		flags)
> > +	xfs_trans_t		*tp,
> > +	xfs_inode_t		*ip,
> 
> struct xfs_trans, struct xfs_inode.
> 
> > +	struct xfs_dquot	*udqp,
> > +	struct xfs_dquot	*gdqp,
> > +	struct xfs_dquot	*pdqp,
> > +	uint			flags)
> >  {
> >  	xfs_mount_t	*mp = ip->i_mount;
> >  	uint		delblks, blkflags, prjflags = 0;
> > -	xfs_dquot_t	*unresudq, *unresgdq, *delblksudq, *delblksgdq;
> > +	struct xfs_dquot	*unresudq = NULL;
> > +	struct xfs_dquot	*unresgdq = NULL;
> > +	struct xfs_dquot	*unrespdq = NULL;
> > +	struct xfs_dquot	*delblksudq = NULL;
> > +	struct xfs_dquot	*delblksgdq = NULL;
> > +	struct xfs_dquot	*delblkspdq = NULL;
> >  	int		error;
> 
> You may as well line up the other 3 declarations, and make is a
> struct xfs_mount....
> 
> .... and I just realised that looking through this code reviewing
> the xfs_ioctl_setattr() changes that I'd not read the existing
> code correctly.
> 
> Why not? becuse unresudq and unresgdq are not very different. The
> classic case of the brain not really seeing the difference between
> single letters inside a larger word, and that's where the single
> letter difference in the variables are. i.e: this phenomenon:
> 
> http://www.ecenglish.com/learnenglish/lessons/can-you-read
> 
> I can read that mess as fast as if it were spelt correctly, hence
> the importance of the first/last letter of variable names...
> 
> So, can you rename these variables:
> 
> 	udq_unres
> 	gdq_unres
> 	pdq_unres
> 	udq_delblks
> 	gdq_delblks
> 	pdq_delblks
> 
> so it's a little more obvious to my easily tricked brain that they
> are different....
> 
Why not :)

> 
> > @@ -1935,13 +2039,18 @@ xfs_qm_vop_create_dqattach(
> >  	}
> >  	if (gdqp) {
> >  		ASSERT(ip->i_gdquot == NULL);
> > -		ASSERT(XFS_IS_OQUOTA_ON(mp));
> > -		ASSERT((XFS_IS_GQUOTA_ON(mp) ?
> > -			ip->i_d.di_gid : xfs_get_projid(ip)) ==
> > -				be32_to_cpu(gdqp->q_core.d_id));
> > -
> > +		ASSERT(XFS_IS_GQUOTA_ON(mp));
> > +		ASSERT(ip->i_d.di_gid == be32_to_cpu(gdqp->q_core.d_id));
> >  		ip->i_gdquot = xfs_qm_dqhold(gdqp);
> >  		xfs_trans_mod_dquot(tp, gdqp, XFS_TRANS_DQ_ICOUNT, 1);
> >  	}
> > +	if (pdqp) {
> > +		ASSERT(ip->i_pdquot == NULL);
> > +		ASSERT(XFS_IS_PQUOTA_ON(mp));
> > +		ASSERT(xfs_get_projid(ip) == be32_to_cpu(pdqp->q_core.d_id));
> > +
> > +		ip->i_pdquot = xfs_qm_dqhold(pdqp);
> > +		xfs_trans_mod_dquot(tp, pdqp, XFS_TRANS_DQ_ICOUNT, 1);
> > +	}
> >  }
> 
> Something this just triggered. All transaction reservations that
> reserve space for dquots need to be upped from 2 to 3 dquots.

Can you elaborate please.

> 
> > -extern void	xfs_trans_mod_dquot(xfs_trans_t *, xfs_dquot_t *, uint, long);
> > -extern int	xfs_trans_reserve_quota_bydquots(xfs_trans_t *, xfs_mount_t *,
> > -			xfs_dquot_t *, xfs_dquot_t *, long, long, uint);
> > -extern void	xfs_trans_dqjoin(xfs_trans_t *, xfs_dquot_t *);
> > -extern void	xfs_trans_log_dquot(xfs_trans_t *, xfs_dquot_t *);
> > +extern void	xfs_trans_mod_dquot(xfs_trans_t *, struct xfs_dquot *, uint, long);
> > +extern void	xfs_trans_dqjoin(xfs_trans_t *, struct xfs_dquot *);
> > +extern void	xfs_trans_log_dquot(xfs_trans_t *, struct xfs_dquot *);
> 
> Remove the typedefs at the same time.

sure
> 
> 
> >  /*
> > - * We keep the usr and grp dquots separately so that locking will be easier
> > - * to do at commit time. All transactions that we know of at this point
> > + * We keep the usr, grp, and prj dquots separately so that locking will be
> > + * easier to do at commit time. All transactions that we know of at this point
> >   * affect no more than two dquots of one type. Hence, the TRANS_MAXDQS value.
> >   */
> > +enum {
> > +	XFS_QM_TRANS_USR = 0,
> > +	XFS_QM_TRANS_GRP,
> > +	XFS_QM_TRANS_PROJ,
> > +	XFS_QM_TRANS_DQTYPES
> > +};
> >  #define XFS_QM_TRANS_MAXDQS		2
> > -typedef struct xfs_dquot_acct {
> > -	xfs_dqtrx_t	dqa_usrdquots[XFS_QM_TRANS_MAXDQS];
> > -	xfs_dqtrx_t	dqa_grpdquots[XFS_QM_TRANS_MAXDQS];
> > -} xfs_dquot_acct_t;
> > +struct xfs_dquot_acct {
> > +	struct xfs_dqtrx dqs[XFS_QM_TRANS_DQTYPES][XFS_QM_TRANS_MAXDQS];
> > +};
> >  
> >  /*
> >   * Users are allowed to have a usage exceeding their softlimit for
> > diff --git a/fs/xfs/xfs_qm_bhv.c b/fs/xfs/xfs_qm_bhv.c
> > index 2d02eac..72a4fdd 100644
> > --- a/fs/xfs/xfs_qm_bhv.c
> > +++ b/fs/xfs/xfs_qm_bhv.c
> > @@ -115,7 +115,7 @@ xfs_qm_newmount(
> >  	     (pquotaondisk && !XFS_IS_PQUOTA_ON(mp)) ||
> >  	    (!pquotaondisk &&  XFS_IS_PQUOTA_ON(mp)) ||
> >  	     (gquotaondisk && !XFS_IS_GQUOTA_ON(mp)) ||
> > -	    (!gquotaondisk &&  XFS_IS_OQUOTA_ON(mp)))  &&
> > +	    (!gquotaondisk &&  XFS_IS_GQUOTA_ON(mp)))  &&
> >  	    xfs_dev_is_read_only(mp, "changing quota state")) {
> >  		xfs_warn(mp, "please mount with%s%s%s%s.",
> >  			(!quotaondisk ? "out quota" : ""),
> 
> Shouldn't this hunk be in the first patch?

No, the object of the first patch is to just handle on disk .*OQUOTA.*
flags in the sb_flags.

In this patch I replace the rest of OQUOTA
> 
> 
> > index 1501f4f..cd0d133 100644
> > --- a/fs/xfs/xfs_vnodeops.c
> > +++ b/fs/xfs/xfs_vnodeops.c
> > @@ -498,6 +498,7 @@ xfs_create(
> >  	prid_t			prid;
> >  	struct xfs_dquot	*udqp = NULL;
> >  	struct xfs_dquot	*gdqp = NULL;
> > +	struct xfs_dquot	*pdqp = NULL;
> >  	uint			resblks;
> >  	uint			log_res;
> >  	uint			log_count;
> > @@ -516,7 +517,7 @@ xfs_create(
> >  	 * Make sure that we have allocated dquot(s) on disk.
> >  	 */
> >  	error = xfs_qm_vop_dqalloc(dp, current_fsuid(), current_fsgid(), prid,
> > -			XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp);
> > +		XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp, &pdqp);
> 
> break that into two lines.
> 
> 				XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT,
> 				&udqp, &gdqp, &pdqp);
> 
will do
> 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