* [PATCH v9 0/6] Allow pquota and gquota to be used together
@ 2013-06-24 2:48 Chandra Seetharaman
2013-06-24 2:48 ` [PATCH v9 1/6] xfs: Move code around and remove typedefs Chandra Seetharaman
` (5 more replies)
0 siblings, 6 replies; 28+ messages in thread
From: Chandra Seetharaman @ 2013-06-24 2:48 UTC (permalink / raw)
To: xfs
Hello All,
This is the version 9 of the changes to allow pquota and gquota to be used
together.
Patchset applies cleanly on top of 2fb8b5027dbde32a45edf5f3d7ee082be9261d93
in xfs git tree.
Ran xfstests against it with DEBUG and do not see any regressions.
Changes from verion 8 to version 9:
- Made all the changes suggested by Dave
- Rearranged code to make the functional changes to
not be cluttered.
Version 8 can be found at:
http://oss.sgi.com/archives/xfs/2013-05/msg00296.html
Changes from version 7 to version 8:
- Rebased to the current code.
- Modified code to use the new pquotino field in version 5
of the superblock.
Version 7 can be found at:
http://oss.sgi.com/archives/xfs/2013-03/msg00671.html
Changes from version 6 to version 7:
- Made all the changes suggested by Dave Chinner
- Added padding to fs_quota_stat, which made the new
data structure field ordering different from the old data
structure field ordering. So, copied the old version
to be _v1 version and used that if old version of data
structure was provided from user space.
Version 6 can be found at:
http://oss.sgi.com/archives/xfs/2012-07/msg00286.html
Changes from version 5 to version 6:
- Use radix tree instead of hash table
Version 5 can be found at:
http://oss.sgi.com/archives/xfs/2012-03/msg00310.html
Changes fron version 4 to version 5:
rebase with the current tree one simple change.
Version 4 can be found at
http://oss.sgi.com/archives/xfs/2012-02/msg00528.html
Changes from version 3 to version 4:
- Remove save_flags with storing the value (in to superblock)
based on field type info
- fix checkpatch.pl warnings and errors
Version 3 of the posting can be found at
http://oss.sgi.com/archives/xfs/2012-01/msg00309.html
Changes from version 2 to version 3:
- hash table for pquota is added.
- changes to apply cleanly with the latest tree
version 2 of the posting can be found at
http://oss.sgi.com/archives/xfs/2011-10/msg00470.html
Changes from version 1 to version 2:
- Created a new prep patch to accomodate some generic changes that ease
the later patches.
- Created a new patch to add a new field qs_pquota to fs_quota_stat
with appropriate versioning changes
- Changed the logic to allow XFS_OQUOTA.* flags to be allowed only in
the older versions.
- Changed couple of places where PQUOTA checking was on the else if
construct so as to allow both GQUOTA and PQUOTA in those places.
- Fixed comments in xfs_quota.h to reflect the current changes.
- Changed the name of the macro XFS_SB_VERSION2_SEPER_PQUOTA to
XFS_SB_VERSION2_NO_OQUOTA
- got rid of the macros XFS_MOUNT_QUOTA_SET1 and XFS_MOUNT_QUOTA_SET2
- added a new inline function xfs_inode_dquot(ip, type) to simplify
the error path in xfs_qm_dqget()
- got rid of the macro XFS_IS_THIS_QUOTA_OFF
- added comment to explain why sb_qflags is saved and restored in
xfs_sb_to_disk()
version 1 of the posting can be found at
http://oss.sgi.com/archives/xfs/2011-10/msg00341.html
Thanks & Regards,
chandra
Chandra Seetharaman (5):
xfs: Remove incore use of XFS_OQUOTA_ENFD and XFS_OQUOTA_CHKD
xfs: Add pquota fields where gquota is used.
xfs: Start using pquotaino from the superblock
xfs: Add proper versioning support to fs_quota_stat
xfs: Use new qs_pquota field in fs_quota_stat for Q_XGETQSTAT
fs/gfs2/quota.c | 3 -
fs/quota/quota.c | 40 ++++-
fs/xfs/xfs_dquot.c | 33 +++-
fs/xfs/xfs_dquot.h | 13 +-
fs/xfs/xfs_icache.c | 4 +-
fs/xfs/xfs_inode.h | 1 +
fs/xfs/xfs_ioctl.c | 14 +-
fs/xfs/xfs_iops.c | 4 +-
fs/xfs/xfs_itable.c | 3 +-
fs/xfs/xfs_mount.c | 102 +++++++++++
fs/xfs/xfs_qm.c | 379 ++++++++++++++++++++++++++--------------
fs/xfs/xfs_qm.h | 53 ++++--
fs/xfs/xfs_qm_bhv.c | 2 +-
fs/xfs/xfs_qm_syscalls.c | 125 +++++++++-----
fs/xfs/xfs_quota.h | 78 +++++----
fs/xfs/xfs_quotaops.c | 6 +-
fs/xfs/xfs_sb.h | 5 +
fs/xfs/xfs_super.c | 35 ++--
fs/xfs/xfs_symlink.c | 13 +-
fs/xfs/xfs_trans_dquot.c | 102 ++++++-----
fs/xfs/xfs_vnodeops.c | 12 +-
include/uapi/linux/dqblk_xfs.h | 37 ++++-
22 files changed, 731 insertions(+), 333 deletions(-)
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 28+ messages in thread
* [PATCH v9 1/6] xfs: Move code around and remove typedefs
2013-06-24 2:48 [PATCH v9 0/6] Allow pquota and gquota to be used together Chandra Seetharaman
@ 2013-06-24 2:48 ` Chandra Seetharaman
2013-06-24 5:31 ` Dave Chinner
2013-06-24 21:36 ` Ben Myers
2013-06-24 2:48 ` [PATCH v9 2/6] xfs: Remove incore use of XFS_OQUOTA_ENFD and XFS_OQUOTA_CHKD Chandra Seetharaman
` (4 subsequent siblings)
5 siblings, 2 replies; 28+ messages in thread
From: Chandra Seetharaman @ 2013-06-24 2:48 UTC (permalink / raw)
To: xfs; +Cc: Chandra Seetharaman
Removed some typedefs, defined new functions, made some code clean up all in
preparation of the series.
No functional changes.
Signed-off-by: Chandra Seetharaman <sekharan@us.ibm.com>
---
fs/xfs/xfs_dquot.c | 16 ++--
fs/xfs/xfs_dquot.h | 4 -
fs/xfs/xfs_icache.c | 3 +-
fs/xfs/xfs_itable.c | 2 +-
fs/xfs/xfs_qm.c | 175 +++++++++++++++++++++++----------------------
fs/xfs/xfs_qm.h | 133 ++++++++++++++++++++++-------------
fs/xfs/xfs_qm_syscalls.c | 8 +-
fs/xfs/xfs_sb.h | 6 ++
fs/xfs/xfs_symlink.c | 3 +-
fs/xfs/xfs_trans_dquot.c | 83 +++++++++-------------
10 files changed, 230 insertions(+), 203 deletions(-)
diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c
index 044e97a..f01012d 100644
--- a/fs/xfs/xfs_dquot.c
+++ b/fs/xfs/xfs_dquot.c
@@ -570,13 +570,13 @@ xfs_qm_dqtobp(
xfs_buf_t **O_bpp,
uint flags)
{
- xfs_bmbt_irec_t map;
- int nmaps = 1, error;
- xfs_buf_t *bp;
- xfs_inode_t *quotip = XFS_DQ_TO_QIP(dqp);
- xfs_mount_t *mp = dqp->q_mount;
- xfs_dqid_t id = be32_to_cpu(dqp->q_core.d_id);
- xfs_trans_t *tp = (tpp ? *tpp : NULL);
+ struct xfs_bmbt_irec map;
+ int nmaps = 1, error;
+ struct xfs_buf *bp;
+ struct xfs_inode *quotip = xfs_dq_to_quota_inode(dqp);
+ struct xfs_mount *mp = dqp->q_mount;
+ xfs_dqid_t id = be32_to_cpu(dqp->q_core.d_id);
+ struct xfs_trans *tp = (tpp ? *tpp : NULL);
dqp->q_fileoffset = (xfs_fileoff_t)id / mp->m_quotainfo->qi_dqperchunk;
@@ -804,7 +804,7 @@ xfs_qm_dqget(
xfs_dquot_t **O_dqpp) /* OUT : locked incore dquot */
{
struct xfs_quotainfo *qi = mp->m_quotainfo;
- struct radix_tree_root *tree = XFS_DQUOT_TREE(qi, type);
+ struct radix_tree_root *tree = xfs_dquot_tree(qi, type);
struct xfs_dquot *dqp;
int error;
diff --git a/fs/xfs/xfs_dquot.h b/fs/xfs/xfs_dquot.h
index 4f0ebfc..b596626 100644
--- a/fs/xfs/xfs_dquot.h
+++ b/fs/xfs/xfs_dquot.h
@@ -143,10 +143,6 @@ static inline xfs_dquot_t *xfs_inode_dquot(struct xfs_inode *ip, int type)
#define XFS_QM_ISUDQ(dqp) ((dqp)->dq_flags & XFS_DQ_USER)
#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)
extern int xfs_qm_dqread(struct xfs_mount *, xfs_dqid_t, uint,
uint, struct xfs_dquot **);
diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c
index 96e344e..9560dc1 100644
--- a/fs/xfs/xfs_icache.c
+++ b/fs/xfs/xfs_icache.c
@@ -335,7 +335,8 @@ 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 = NULL;
+ ip->i_gdquot = NULL;
xfs_iflags_set(ip, iflags);
/* insert the new inode */
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
index 2ea7d40..9cbf9e0 100644
--- a/fs/xfs/xfs_itable.c
+++ b/fs/xfs/xfs_itable.c
@@ -43,7 +43,7 @@ xfs_internal_inum(
{
return (ino == mp->m_sb.sb_rbmino || ino == mp->m_sb.sb_rsumino ||
(xfs_sb_version_hasquota(&mp->m_sb) &&
- (ino == mp->m_sb.sb_uquotino || ino == mp->m_sb.sb_gquotino)));
+ xfs_is_quota_inode(&mp->m_sb, ino)));
}
/*
diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c
index b75c9bb..f5f9925 100644
--- a/fs/xfs/xfs_qm.c
+++ b/fs/xfs/xfs_qm.c
@@ -70,7 +70,7 @@ xfs_qm_dquot_walk(
void *data)
{
struct xfs_quotainfo *qi = mp->m_quotainfo;
- struct radix_tree_root *tree = XFS_DQUOT_TREE(qi, type);
+ struct radix_tree_root *tree = xfs_dquot_tree(qi, type);
uint32_t next_index;
int last_error = 0;
int skipped;
@@ -189,7 +189,7 @@ xfs_qm_dqpurge(
xfs_dqfunlock(dqp);
xfs_dqunlock(dqp);
- radix_tree_delete(XFS_DQUOT_TREE(qi, dqp->q_core.d_flags),
+ radix_tree_delete(xfs_dquot_tree(qi, dqp->q_core.d_flags),
be32_to_cpu(dqp->q_core.d_id));
qi->qi_dquots--;
@@ -489,8 +489,7 @@ xfs_qm_need_dqattach(
return false;
if (!XFS_NOT_DQATTACHED(mp, ip))
return false;
- if (ip->i_ino == mp->m_sb.sb_uquotino ||
- ip->i_ino == mp->m_sb.sb_gquotino)
+ if (xfs_is_quota_inode(&mp->m_sb, ip->i_ino))
return false;
return true;
}
@@ -606,8 +605,7 @@ xfs_qm_dqdetach(
trace_xfs_dquot_dqdetach(ip);
- ASSERT(ip->i_ino != ip->i_mount->m_sb.sb_uquotino);
- ASSERT(ip->i_ino != ip->i_mount->m_sb.sb_gquotino);
+ ASSERT(!xfs_is_quota_inode(&ip->i_mount->m_sb, ip->i_ino));
if (ip->i_udquot) {
xfs_qm_dqrele(ip->i_udquot);
ip->i_udquot = NULL;
@@ -1152,7 +1150,7 @@ xfs_qm_dqusage_adjust(
* rootino must have its resources accounted for, not so with the quota
* inodes.
*/
- if (ino == mp->m_sb.sb_uquotino || ino == mp->m_sb.sb_gquotino) {
+ if (xfs_is_quota_inode(&mp->m_sb, ino)) {
*res = BULKSTAT_RV_NOTHING;
return XFS_ERROR(EINVAL);
}
@@ -1262,19 +1260,20 @@ int
xfs_qm_quotacheck(
xfs_mount_t *mp)
{
- int done, count, error, error2;
- xfs_ino_t lastino;
- size_t structsz;
- xfs_inode_t *uip, *gip;
- uint flags;
- LIST_HEAD (buffer_list);
+ int done, count, error, error2;
+ xfs_ino_t lastino;
+ size_t structsz;
+ uint flags;
+ LIST_HEAD (buffer_list);
+ struct xfs_inode *uip = mp->m_quotainfo->qi_uquotaip;
+ struct xfs_inode *gip = mp->m_quotainfo->qi_gquotaip;
count = INT_MAX;
structsz = 1;
lastino = 0;
flags = 0;
- ASSERT(mp->m_quotainfo->qi_uquotaip || mp->m_quotainfo->qi_gquotaip);
+ ASSERT(uip || gip);
ASSERT(XFS_IS_QUOTA_RUNNING(mp));
xfs_notice(mp, "Quotacheck needed: Please wait.");
@@ -1284,7 +1283,6 @@ xfs_qm_quotacheck(
* their counters to zero. We need a clean slate.
* We don't log our changes till later.
*/
- uip = mp->m_quotainfo->qi_uquotaip;
if (uip) {
error = xfs_qm_dqiterate(mp, uip, XFS_QMOPT_UQUOTA,
&buffer_list);
@@ -1293,7 +1291,6 @@ xfs_qm_quotacheck(
flags |= XFS_UQUOTA_CHKD;
}
- 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,
@@ -1395,15 +1392,13 @@ STATIC int
xfs_qm_init_quotainos(
xfs_mount_t *mp)
{
- xfs_inode_t *uip, *gip;
- int error;
- __int64_t sbflags;
- uint flags;
+ struct xfs_inode *uip = NULL;
+ struct xfs_inode *gip = NULL;
+ int error;
+ __int64_t sbflags = 0;
+ uint flags = 0;
ASSERT(mp->m_quotainfo);
- uip = gip = NULL;
- sbflags = 0;
- flags = 0;
/*
* Get the uquota and gquota inodes
@@ -1412,19 +1407,18 @@ 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) &&
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;
}
} else {
flags |= XFS_QMOPT_SBVERSION;
@@ -1439,10 +1433,11 @@ xfs_qm_init_quotainos(
* temporarily switch to read-write to do this.
*/
if (XFS_IS_UQUOTA_ON(mp) && uip == NULL) {
- if ((error = xfs_qm_qino_alloc(mp, &uip,
+ error = xfs_qm_qino_alloc(mp, &uip,
sbflags | XFS_SB_UQUOTINO,
- flags | XFS_QMOPT_UQUOTA)))
- return XFS_ERROR(error);
+ flags | XFS_QMOPT_UQUOTA);
+ if (error)
+ goto error_rele;
flags &= ~XFS_QMOPT_SBVERSION;
}
@@ -1451,18 +1446,21 @@ xfs_qm_init_quotainos(
XFS_QMOPT_GQUOTA : XFS_QMOPT_PQUOTA);
error = xfs_qm_qino_alloc(mp, &gip,
sbflags | XFS_SB_GQUOTINO, flags);
- if (error) {
- if (uip)
- IRELE(uip);
-
- return XFS_ERROR(error);
- }
+ if (error)
+ goto error_rele;
}
mp->m_quotainfo->qi_uquotaip = uip;
mp->m_quotainfo->qi_gquotaip = gip;
return 0;
+
+error_rele:
+ if (uip)
+ IRELE(uip);
+ if (gip)
+ IRELE(gip);
+ return XFS_ERROR(error);
}
STATIC void
@@ -1473,7 +1471,7 @@ xfs_qm_dqfree_one(
struct xfs_quotainfo *qi = mp->m_quotainfo;
mutex_lock(&qi->qi_tree_lock);
- radix_tree_delete(XFS_DQUOT_TREE(qi, dqp->q_core.d_flags),
+ radix_tree_delete(xfs_dquot_tree(qi, dqp->q_core.d_flags),
be32_to_cpu(dqp->q_core.d_id));
qi->qi_dquots--;
@@ -1659,7 +1657,8 @@ xfs_qm_vop_dqalloc(
struct xfs_dquot **O_gdqpp)
{
struct xfs_mount *mp = ip->i_mount;
- struct xfs_dquot *uq, *gq;
+ struct xfs_dquot *uq = NULL;
+ struct xfs_dquot *gq = NULL;
int error;
uint lockflags;
@@ -1684,7 +1683,6 @@ xfs_qm_vop_dqalloc(
}
}
- uq = gq = NULL;
if ((flags & XFS_QMOPT_UQUOTA) && XFS_IS_UQUOTA_ON(mp)) {
if (ip->i_d.di_uid != uid) {
/*
@@ -1697,14 +1695,14 @@ xfs_qm_vop_dqalloc(
* holding ilock.
*/
xfs_iunlock(ip, lockflags);
- if ((error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t) uid,
+ error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t) uid,
XFS_DQ_USER,
XFS_QMOPT_DQALLOC |
XFS_QMOPT_DOWARN,
- &uq))) {
- ASSERT(error != ENOENT);
+ &uq);
+ ASSERT(error != ENOENT);
+ if (error)
return error;
- }
/*
* Get the ilock in the right order.
*/
@@ -1723,16 +1721,14 @@ xfs_qm_vop_dqalloc(
if ((flags & XFS_QMOPT_GQUOTA) && XFS_IS_GQUOTA_ON(mp)) {
if (ip->i_d.di_gid != gid) {
xfs_iunlock(ip, lockflags);
- if ((error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t)gid,
+ error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t)gid,
XFS_DQ_GROUP,
XFS_QMOPT_DQALLOC |
XFS_QMOPT_DOWARN,
- &gq))) {
- if (uq)
- xfs_qm_dqrele(uq);
- ASSERT(error != ENOENT);
- return error;
- }
+ &gq);
+ ASSERT(error != ENOENT);
+ if (error)
+ goto error_rele;
xfs_dqunlock(gq);
lockflags = XFS_ILOCK_SHARED;
xfs_ilock(ip, lockflags);
@@ -1743,16 +1739,14 @@ xfs_qm_vop_dqalloc(
} else 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,
+ error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t)prid,
XFS_DQ_PROJ,
XFS_QMOPT_DQALLOC |
XFS_QMOPT_DOWARN,
- &gq))) {
- if (uq)
- xfs_qm_dqrele(uq);
- ASSERT(error != ENOENT);
- return (error);
- }
+ &gq);
+ ASSERT(error != ENOENT);
+ if (error)
+ goto error_rele;
xfs_dqunlock(gq);
lockflags = XFS_ILOCK_SHARED;
xfs_ilock(ip, lockflags);
@@ -1774,6 +1768,11 @@ xfs_qm_vop_dqalloc(
else if (gq)
xfs_qm_dqrele(gq);
return 0;
+
+error_rele:
+ if (uq)
+ xfs_qm_dqrele(uq);
+ return error;
}
/*
@@ -1821,29 +1820,31 @@ 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)
+ struct xfs_trans *tp,
+ struct xfs_inode *ip,
+ struct xfs_dquot *udqp,
+ struct xfs_dquot *gdqp,
+ uint flags)
{
- xfs_mount_t *mp = ip->i_mount;
- uint delblks, blkflags, prjflags = 0;
- xfs_dquot_t *unresudq, *unresgdq, *delblksudq, *delblksgdq;
- int error;
+ struct xfs_mount *mp = ip->i_mount;
+ uint delblks, blkflags, prjflags = 0;
+ struct xfs_dquot *udq_unres = NULL;
+ struct xfs_dquot *gdq_unres = NULL;
+ struct xfs_dquot *udq_delblks = NULL;
+ struct xfs_dquot *gdq_delblks = NULL;
+ int error;
ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED));
ASSERT(XFS_IS_QUOTA_RUNNING(mp));
delblks = ip->i_delayed_blks;
- delblksudq = delblksgdq = unresudq = unresgdq = NULL;
blkflags = XFS_IS_REALTIME_INODE(ip) ?
XFS_QMOPT_RES_RTBLKS : XFS_QMOPT_RES_REGBLKS;
if (XFS_IS_UQUOTA_ON(mp) && udqp &&
ip->i_d.di_uid != (uid_t)be32_to_cpu(udqp->q_core.d_id)) {
- delblksudq = udqp;
+ udq_delblks = udqp;
/*
* If there are delayed allocation blocks, then we have to
* unreserve those from the old dquot, and add them to the
@@ -1851,7 +1852,7 @@ xfs_qm_vop_chown_reserve(
*/
if (delblks) {
ASSERT(ip->i_udquot);
- unresudq = ip->i_udquot;
+ udq_unres = ip->i_udquot;
}
}
if (XFS_IS_OQUOTA_ON(ip->i_mount) && gdqp) {
@@ -1862,18 +1863,19 @@ xfs_qm_vop_chown_reserve(
if (prjflags ||
(XFS_IS_GQUOTA_ON(ip->i_mount) &&
ip->i_d.di_gid != be32_to_cpu(gdqp->q_core.d_id))) {
- delblksgdq = gdqp;
+ gdq_delblks = gdqp;
if (delblks) {
ASSERT(ip->i_gdquot);
- unresgdq = ip->i_gdquot;
+ gdq_unres = ip->i_gdquot;
}
}
}
- if ((error = xfs_trans_reserve_quota_bydquots(tp, ip->i_mount,
- delblksudq, delblksgdq, ip->i_d.di_nblocks, 1,
- flags | blkflags | prjflags)))
- return (error);
+ error = xfs_trans_reserve_quota_bydquots(tp, ip->i_mount,
+ udq_delblks, gdq_delblks, ip->i_d.di_nblocks, 1,
+ flags | blkflags | prjflags);
+ if (error)
+ return error;
/*
* Do the delayed blks reservations/unreservations now. Since, these
@@ -1885,14 +1887,15 @@ xfs_qm_vop_chown_reserve(
/*
* Do the reservations first. Unreservation can't fail.
*/
- ASSERT(delblksudq || delblksgdq);
- ASSERT(unresudq || unresgdq);
- if ((error = xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount,
- delblksudq, delblksgdq, (xfs_qcnt_t)delblks, 0,
- flags | blkflags | prjflags)))
- return (error);
+ ASSERT(udq_delblks || gdq_delblks);
+ ASSERT(udq_unres || gdq_unres);
+ error = xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount,
+ udq_delblks, gdq_delblks, (xfs_qcnt_t)delblks, 0,
+ flags | blkflags | prjflags);
+ if (error)
+ return error;
xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount,
- unresudq, unresgdq, -((xfs_qcnt_t)delblks), 0,
+ udq_unres, gdq_unres, -((xfs_qcnt_t)delblks), 0,
blkflags);
}
diff --git a/fs/xfs/xfs_qm.h b/fs/xfs/xfs_qm.h
index 5d16a6e..4b330f2 100644
--- a/fs/xfs/xfs_qm.h
+++ b/fs/xfs/xfs_qm.h
@@ -42,57 +42,89 @@ extern struct kmem_zone *xfs_qm_dqtrxzone;
* The mount structure keeps a pointer to this.
*/
typedef struct xfs_quotainfo {
- struct radix_tree_root qi_uquota_tree;
- struct radix_tree_root qi_gquota_tree;
- struct mutex qi_tree_lock;
- xfs_inode_t *qi_uquotaip; /* user quota inode */
- xfs_inode_t *qi_gquotaip; /* group quota inode */
- struct list_head qi_lru_list;
- struct mutex qi_lru_lock;
- int qi_lru_count;
- int qi_dquots;
- time_t qi_btimelimit; /* limit for blks timer */
- time_t qi_itimelimit; /* limit for inodes timer */
- time_t qi_rtbtimelimit;/* limit for rt blks timer */
- xfs_qwarncnt_t qi_bwarnlimit; /* limit for blks warnings */
- xfs_qwarncnt_t qi_iwarnlimit; /* limit for inodes warnings */
- xfs_qwarncnt_t qi_rtbwarnlimit;/* limit for rt blks warnings */
- struct mutex qi_quotaofflock;/* to serialize quotaoff */
- xfs_filblks_t qi_dqchunklen; /* # BBs in a chunk of dqs */
- uint qi_dqperchunk; /* # ondisk dqs in above chunk */
- xfs_qcnt_t qi_bhardlimit; /* default data blk hard limit */
- xfs_qcnt_t qi_bsoftlimit; /* default data blk soft limit */
- xfs_qcnt_t qi_ihardlimit; /* default inode count hard limit */
- xfs_qcnt_t qi_isoftlimit; /* default inode count soft limit */
- xfs_qcnt_t qi_rtbhardlimit;/* default realtime blk hard limit */
- xfs_qcnt_t qi_rtbsoftlimit;/* default realtime blk soft limit */
- struct shrinker qi_shrinker;
+ struct radix_tree_root qi_uquota_tree;
+ struct radix_tree_root qi_gquota_tree;
+ struct mutex qi_tree_lock;
+ struct xfs_inode *qi_uquotaip; /* user quota inode */
+ struct xfs_inode *qi_gquotaip; /* group quota inode */
+ struct list_head qi_lru_list;
+ struct mutex qi_lru_lock;
+ int qi_lru_count;
+ int qi_dquots;
+ time_t qi_btimelimit; /* limit for blks timer */
+ time_t qi_itimelimit; /* limit for inodes timer */
+ time_t qi_rtbtimelimit;/* limit for rt blks timer */
+ xfs_qwarncnt_t qi_bwarnlimit; /* limit for blks warnings */
+ xfs_qwarncnt_t qi_iwarnlimit; /* limit for inodes warnings */
+ xfs_qwarncnt_t qi_rtbwarnlimit;/* limit for rt blks warnings */
+ struct mutex qi_quotaofflock;/* to serialize quotaoff */
+ xfs_filblks_t qi_dqchunklen; /* # BBs in a chunk of dqs */
+ uint qi_dqperchunk; /* # ondisk dqs in above chunk */
+ xfs_qcnt_t qi_bhardlimit; /* default data blk hard limit */
+ xfs_qcnt_t qi_bsoftlimit; /* default data blk soft limit */
+ xfs_qcnt_t qi_ihardlimit; /* default inode count hard limit */
+ xfs_qcnt_t qi_isoftlimit; /* default inode count soft limit */
+ xfs_qcnt_t qi_rtbhardlimit;/* default realtime blk hard limit */
+ xfs_qcnt_t qi_rtbsoftlimit;/* default realtime blk soft limit */
+ struct shrinker qi_shrinker;
} xfs_quotainfo_t;
-#define XFS_DQUOT_TREE(qi, type) \
- ((type & XFS_DQ_USER) ? \
- &((qi)->qi_uquota_tree) : \
- &((qi)->qi_gquota_tree))
+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:
+ case XFS_DQ_PROJ:
+ return &qi->qi_gquota_tree;
+ default:
+ ASSERT(0);
+ }
+ return NULL;
+}
+static inline struct xfs_inode *
+xfs_dq_to_quota_inode(struct xfs_dquot *dqp)
+{
+ switch (dqp->dq_flags & XFS_DQ_ALLTYPES) {
+ case XFS_DQ_USER:
+ return dqp->q_mount->m_quotainfo->qi_uquotaip;
+ case XFS_DQ_GROUP:
+ case XFS_DQ_PROJ:
+ return dqp->q_mount->m_quotainfo->qi_gquotaip;
+ default:
+ ASSERT(0);
+ }
+ return NULL;
+}
extern int xfs_qm_calc_dquots_per_chunk(struct xfs_mount *mp,
unsigned int nbblks);
-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(struct xfs_trans *,
+ struct xfs_dquot *, uint, long);
+extern int xfs_trans_reserve_quota_bydquots(struct xfs_trans *,
+ struct xfs_mount *, struct xfs_dquot *,
+ struct xfs_dquot *, long, long, uint);
+extern void xfs_trans_dqjoin(struct xfs_trans *, struct xfs_dquot *);
+extern void xfs_trans_log_dquot(struct xfs_trans *, struct xfs_dquot *);
/*
* 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
* 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_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
@@ -106,22 +138,23 @@ typedef struct xfs_dquot_acct {
#define XFS_QM_IWARNLIMIT 5
#define XFS_QM_RTBWARNLIMIT 5
-extern void xfs_qm_destroy_quotainfo(xfs_mount_t *);
-extern int xfs_qm_quotacheck(xfs_mount_t *);
-extern int xfs_qm_write_sb_changes(xfs_mount_t *, __int64_t);
+extern void xfs_qm_destroy_quotainfo(struct xfs_mount *);
+extern int xfs_qm_quotacheck(struct xfs_mount *);
+extern int xfs_qm_write_sb_changes(struct xfs_mount *, __int64_t);
/* dquot stuff */
-extern void xfs_qm_dqpurge_all(xfs_mount_t *, uint);
-extern void xfs_qm_dqrele_all_inodes(xfs_mount_t *, uint);
+extern void xfs_qm_dqpurge_all(struct xfs_mount *, uint);
+extern void xfs_qm_dqrele_all_inodes(struct xfs_mount *, uint);
/* quota ops */
-extern int xfs_qm_scall_trunc_qfiles(xfs_mount_t *, uint);
-extern int xfs_qm_scall_getquota(xfs_mount_t *, xfs_dqid_t, uint,
- fs_disk_quota_t *);
+extern int xfs_qm_scall_trunc_qfiles(struct xfs_mount *, uint);
+extern int xfs_qm_scall_getquota(struct xfs_mount *, xfs_dqid_t,
+ uint, struct fs_disk_quota *);
extern int xfs_qm_scall_setqlim(struct xfs_mount *, xfs_dqid_t, uint,
- fs_disk_quota_t *);
-extern int xfs_qm_scall_getqstat(xfs_mount_t *, fs_quota_stat_t *);
-extern int xfs_qm_scall_quotaon(xfs_mount_t *, uint);
-extern int xfs_qm_scall_quotaoff(xfs_mount_t *, uint);
+ struct fs_disk_quota *);
+extern int xfs_qm_scall_getqstat(struct xfs_mount *,
+ struct fs_quota_stat *);
+extern int xfs_qm_scall_quotaon(struct xfs_mount *, uint);
+extern int xfs_qm_scall_quotaoff(struct xfs_mount *, uint);
#endif /* __XFS_QM_H__ */
diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c
index 6cdf6ff..b03b2ab 100644
--- a/fs/xfs/xfs_qm_syscalls.c
+++ b/fs/xfs/xfs_qm_syscalls.c
@@ -407,11 +407,11 @@ xfs_qm_scall_getqstat(
struct fs_quota_stat *out)
{
struct xfs_quotainfo *q = mp->m_quotainfo;
- struct xfs_inode *uip, *gip;
- bool tempuqip, tempgqip;
+ struct xfs_inode *uip = NULL;
+ struct xfs_inode *gip = NULL;
+ bool tempuqip = false;
+ bool tempgqip = false;
- uip = gip = NULL;
- tempuqip = tempgqip = false;
memset(out, 0, sizeof(fs_quota_stat_t));
out->qs_version = FS_QSTAT_VERSION;
diff --git a/fs/xfs/xfs_sb.h b/fs/xfs/xfs_sb.h
index 2de58a8..78f9e70 100644
--- a/fs/xfs/xfs_sb.h
+++ b/fs/xfs/xfs_sb.h
@@ -618,6 +618,12 @@ xfs_sb_has_incompat_log_feature(
return (sbp->sb_features_log_incompat & feature) != 0;
}
+static inline bool
+xfs_is_quota_inode(struct xfs_sb *sbp, xfs_ino_t ino)
+{
+ return (ino == sbp->sb_uquotino || ino == sbp->sb_gquotino);
+}
+
/*
* end of superblock version macros
*/
diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c
index 738c04b..e830fb5 100644
--- a/fs/xfs/xfs_symlink.c
+++ b/fs/xfs/xfs_symlink.c
@@ -358,7 +358,8 @@ xfs_symlink(
int n;
xfs_buf_t *bp;
prid_t prid;
- struct xfs_dquot *udqp, *gdqp;
+ struct xfs_dquot *udqp = NULL;
+ struct xfs_dquot *gdqp = NULL;
uint resblks;
*ipp = NULL;
diff --git a/fs/xfs/xfs_trans_dquot.c b/fs/xfs/xfs_trans_dquot.c
index fec75d0..7ea7485 100644
--- a/fs/xfs/xfs_trans_dquot.c
+++ b/fs/xfs/xfs_trans_dquot.c
@@ -103,8 +103,6 @@ xfs_trans_dup_dqinfo(
return;
xfs_trans_alloc_dqinfo(ntp);
- oqa = otp->t_dqinfo->dqa_usrdquots;
- nqa = ntp->t_dqinfo->dqa_usrdquots;
/*
* Because the quota blk reservation is carried forward,
@@ -113,7 +111,9 @@ 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 < XFS_QM_TRANS_DQTYPES; j++) {
+ oqa = otp->t_dqinfo->dqs[j];
+ nqa = ntp->t_dqinfo->dqs[j];
for (i = 0; i < XFS_QM_TRANS_MAXDQS; i++) {
if (oqa[i].qt_dquot == NULL)
break;
@@ -138,8 +138,6 @@ 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;
}
}
@@ -157,8 +155,7 @@ xfs_trans_mod_dquot_byino(
if (!XFS_IS_QUOTA_RUNNING(mp) ||
!XFS_IS_QUOTA_ON(mp) ||
- ip->i_ino == mp->m_sb.sb_uquotino ||
- ip->i_ino == mp->m_sb.sb_gquotino)
+ xfs_is_quota_inode(&mp->m_sb, ip->i_ino))
return;
if (tp->t_dqinfo == NULL)
@@ -170,16 +167,18 @@ xfs_trans_mod_dquot_byino(
(void) xfs_trans_mod_dquot(tp, ip->i_gdquot, field, delta);
}
-STATIC xfs_dqtrx_t *
+STATIC struct xfs_dqtrx *
xfs_trans_get_dqtrx(
- xfs_trans_t *tp,
- xfs_dquot_t *dqp)
+ struct xfs_trans *tp,
+ struct xfs_dquot *dqp)
{
- int i;
- xfs_dqtrx_t *qa;
+ int i;
+ struct xfs_dqtrx *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->dqs[XFS_QM_TRANS_USR];
+ else
+ qa = tp->t_dqinfo->dqs[XFS_QM_TRANS_GRP];
for (i = 0; i < XFS_QM_TRANS_MAXDQS; i++) {
if (qa[i].qt_dquot == NULL ||
@@ -339,12 +338,10 @@ xfs_trans_apply_dquot_deltas(
return;
ASSERT(tp->t_dqinfo);
- qa = tp->t_dqinfo->dqa_usrdquots;
- for (j = 0; j < 2; j++) {
- if (qa[0].qt_dquot == NULL) {
- qa = tp->t_dqinfo->dqa_grpdquots;
+ for (j = 0; j < XFS_QM_TRANS_DQTYPES; j++) {
+ qa = tp->t_dqinfo->dqs[j];
+ if (qa[0].qt_dquot == NULL)
continue;
- }
/*
* Lock all of the dquots and join them to the transaction.
@@ -495,10 +492,6 @@ xfs_trans_apply_dquot_deltas(
ASSERT(dqp->q_res_rtbcount >=
be64_to_cpu(dqp->q_core.d_rtbcount));
}
- /*
- * Do the group quotas next
- */
- qa = tp->t_dqinfo->dqa_grpdquots;
}
}
@@ -521,9 +514,9 @@ xfs_trans_unreserve_and_mod_dquots(
if (!tp->t_dqinfo || !(tp->t_flags & XFS_TRANS_DQ_DIRTY))
return;
- qa = tp->t_dqinfo->dqa_usrdquots;
+ for (j = 0; j < XFS_QM_TRANS_DQTYPES; j++) {
+ qa = tp->t_dqinfo->dqs[j];
- for (j = 0; j < 2; j++) {
for (i = 0; i < XFS_QM_TRANS_MAXDQS; i++) {
qtrx = &qa[i];
/*
@@ -565,7 +558,6 @@ xfs_trans_unreserve_and_mod_dquots(
xfs_dqunlock(dqp);
}
- qa = tp->t_dqinfo->dqa_grpdquots;
}
}
@@ -748,15 +740,15 @@ error_return:
*/
int
xfs_trans_reserve_quota_bydquots(
- xfs_trans_t *tp,
- xfs_mount_t *mp,
- xfs_dquot_t *udqp,
- xfs_dquot_t *gdqp,
- long nblks,
- long ninos,
- uint flags)
+ struct xfs_trans *tp,
+ struct xfs_mount *mp,
+ struct xfs_dquot *udqp,
+ struct xfs_dquot *gdqp,
+ long nblks,
+ long ninos,
+ uint flags)
{
- int resvd = 0, error;
+ int error;
if (!XFS_IS_QUOTA_RUNNING(mp) || !XFS_IS_QUOTA_ON(mp))
return 0;
@@ -771,28 +763,24 @@ xfs_trans_reserve_quota_bydquots(
(flags & ~XFS_QMOPT_ENOSPC));
if (error)
return error;
- resvd = 1;
}
if (gdqp) {
error = xfs_trans_dqresv(tp, mp, gdqp, 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);
- }
- return error;
- }
+ if (error)
+ goto unwind_usr;
}
/*
* Didn't change anything critical, so, no need to log
*/
return 0;
+
+unwind_usr:
+ flags |= XFS_QMOPT_FORCE_RES;
+ if (udqp)
+ xfs_trans_dqresv(tp, mp, udqp, -nblks, -ninos, flags);
+ return error;
}
@@ -816,8 +804,7 @@ xfs_trans_reserve_quota_nblks(
if (XFS_IS_PQUOTA_ON(mp))
flags |= XFS_QMOPT_ENOSPC;
- ASSERT(ip->i_ino != mp->m_sb.sb_uquotino);
- ASSERT(ip->i_ino != mp->m_sb.sb_gquotino);
+ ASSERT(!xfs_is_quota_inode(&mp->m_sb, ip->i_ino));
ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
ASSERT((flags & ~(XFS_QMOPT_FORCE_RES | XFS_QMOPT_ENOSPC)) ==
--
1.7.1
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v9 2/6] xfs: Remove incore use of XFS_OQUOTA_ENFD and XFS_OQUOTA_CHKD
2013-06-24 2:48 [PATCH v9 0/6] Allow pquota and gquota to be used together Chandra Seetharaman
2013-06-24 2:48 ` [PATCH v9 1/6] xfs: Move code around and remove typedefs Chandra Seetharaman
@ 2013-06-24 2:48 ` Chandra Seetharaman
2013-06-24 5:59 ` Dave Chinner
2013-06-24 2:48 ` [PATCH v9 3/6] xfs: Add pquota fields where gquota is used Chandra Seetharaman
` (3 subsequent siblings)
5 siblings, 1 reply; 28+ messages in thread
From: Chandra Seetharaman @ 2013-06-24 2:48 UTC (permalink / raw)
To: xfs; +Cc: Chandra Seetharaman
Remove all incore use of XFS_OQUOTA_ENFD and XFS_OQUOTA_CHKD. Instead,
start using XFS_GQUOTA_.* XFS_PQUOTA_.* counterparts for GQUOTA and
PQUOTA respectively.
On-disk copy still uses XFS_OQUOTA_ENFD and XFS_OQUOTA_CHKD.
Read and write of the superblock does the conversion from *OQUOTA*
to *[PG]QUOTA*.
Signed-off-by: Chandra Seetharaman <sekharan@us.ibm.com>
---
fs/xfs/xfs_mount.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
fs/xfs/xfs_qm.c | 9 ++++++---
fs/xfs/xfs_qm_syscalls.c | 39 +++++++++++++++++++++------------------
fs/xfs/xfs_quota.h | 42 ++++++++++++++++++++++++++++--------------
fs/xfs/xfs_quotaops.c | 6 ++++--
fs/xfs/xfs_super.c | 16 ++++++++--------
fs/xfs/xfs_trans_dquot.c | 4 ++--
7 files changed, 115 insertions(+), 47 deletions(-)
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index 6a19434..e2e14cb 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -336,6 +336,14 @@ xfs_mount_validate_sb(
return XFS_ERROR(EWRONGFS);
}
+ if ((sbp->sb_qflags & (XFS_OQUOTA_ENFD | XFS_OQUOTA_CHKD)) &&
+ (sbp->sb_qflags & (XFS_PQUOTA_ENFD | XFS_GQUOTA_ENFD |
+ XFS_PQUOTA_CHKD | XFS_GQUOTA_CHKD))) {
+ xfs_notice(mp,
+"Super block has XFS_OQUOTA bits along with XFS_PQUOTA and/or XFS_GQUOTA bits.\n");
+ return XFS_ERROR(EFSCORRUPTED);
+ }
+
/*
* Version 5 superblock feature mask validation. Reject combinations the
* kernel cannot support up front before checking anything else. For
@@ -622,6 +630,35 @@ xfs_sb_from_disk(
to->sb_lsn = be64_to_cpu(from->sb_lsn);
}
+static inline void
+xfs_handle_quota_to_disk(
+ xfs_dsb_t *to,
+ xfs_sb_t *from,
+ __int64_t *fields)
+{
+ __uint16_t qflags = from->sb_qflags;
+
+ if (*fields & XFS_SB_QFLAGS) {
+ /*
+ * The in-core version of sb_qflags do not have
+ * XFS_OQUOTA_* flags, whereas the on-disk version
+ * does. So, convert incore XFS_{PG}QUOTA_* flags
+ * to on-disk XFS_OQUOTA_* flags.
+ */
+ qflags &= ~(XFS_PQUOTA_ENFD | XFS_PQUOTA_CHKD |
+ XFS_GQUOTA_ENFD | XFS_GQUOTA_CHKD);
+
+ if (from->sb_qflags &
+ (XFS_PQUOTA_ENFD | XFS_GQUOTA_ENFD))
+ qflags |= XFS_OQUOTA_ENFD;
+ if (from->sb_qflags &
+ (XFS_PQUOTA_CHKD | XFS_GQUOTA_CHKD))
+ qflags |= XFS_OQUOTA_CHKD;
+ to->sb_qflags = cpu_to_be16(qflags);
+ *fields &= ~XFS_SB_QFLAGS;
+ }
+}
+
/*
* Copy in core superblock to ondisk one.
*
@@ -643,6 +680,7 @@ xfs_sb_to_disk(
if (!fields)
return;
+ xfs_handle_quota_to_disk(to, from, &fields);
while (fields) {
f = (xfs_sb_field_t)xfs_lowbit64((__uint64_t)fields);
first = xfs_sb_info[f].offset;
@@ -835,6 +873,14 @@ reread:
*/
xfs_sb_from_disk(&mp->m_sb, XFS_BUF_TO_SBP(bp));
+ if (sbp->sb_qflags & XFS_OQUOTA_ENFD)
+ sbp->sb_qflags |= (sbp->sb_qflags & XFS_PQUOTA_ACCT) ?
+ XFS_PQUOTA_ENFD : XFS_GQUOTA_ENFD;
+ if (sbp->sb_qflags & XFS_OQUOTA_CHKD)
+ sbp->sb_qflags |= (sbp->sb_qflags & XFS_PQUOTA_ACCT) ?
+ XFS_PQUOTA_CHKD : XFS_GQUOTA_CHKD;
+ sbp->sb_qflags &= ~(XFS_OQUOTA_ENFD | XFS_OQUOTA_CHKD);
+
/*
* We must be able to do sector-sized and sector-aligned IO.
*/
diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c
index f5f9925..de7ecbd 100644
--- a/fs/xfs/xfs_qm.c
+++ b/fs/xfs/xfs_qm.c
@@ -299,8 +299,10 @@ xfs_qm_mount_quotas(
*/
if (!XFS_IS_UQUOTA_ON(mp))
mp->m_qflags &= ~XFS_UQUOTA_CHKD;
- if (!(XFS_IS_GQUOTA_ON(mp) || XFS_IS_PQUOTA_ON(mp)))
- mp->m_qflags &= ~XFS_OQUOTA_CHKD;
+ if (!XFS_IS_GQUOTA_ON(mp))
+ mp->m_qflags &= ~XFS_GQUOTA_CHKD;
+ if (!XFS_IS_PQUOTA_ON(mp))
+ mp->m_qflags &= ~XFS_PQUOTA_CHKD;
write_changes:
/*
@@ -1297,7 +1299,8 @@ xfs_qm_quotacheck(
&buffer_list);
if (error)
goto error_return;
- flags |= XFS_OQUOTA_CHKD;
+ flags |= XFS_IS_GQUOTA_ON(mp) ?
+ XFS_GQUOTA_CHKD : XFS_PQUOTA_CHKD;
}
do {
diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c
index b03b2ab..5e51227 100644
--- a/fs/xfs/xfs_qm_syscalls.c
+++ b/fs/xfs/xfs_qm_syscalls.c
@@ -117,11 +117,11 @@ xfs_qm_scall_quotaoff(
}
if (flags & XFS_GQUOTA_ACCT) {
dqtype |= XFS_QMOPT_GQUOTA;
- flags |= (XFS_OQUOTA_CHKD | XFS_OQUOTA_ENFD);
+ flags |= (XFS_GQUOTA_CHKD | XFS_GQUOTA_ENFD);
inactivate_flags |= XFS_GQUOTA_ACTIVE;
} else if (flags & XFS_PQUOTA_ACCT) {
dqtype |= XFS_QMOPT_PQUOTA;
- flags |= (XFS_OQUOTA_CHKD | XFS_OQUOTA_ENFD);
+ flags |= (XFS_PQUOTA_CHKD | XFS_PQUOTA_ENFD);
inactivate_flags |= XFS_PQUOTA_ACTIVE;
}
@@ -335,14 +335,14 @@ xfs_qm_scall_quotaon(
* quota acct on ondisk without m_qflags' knowing.
*/
if (((flags & XFS_UQUOTA_ACCT) == 0 &&
- (mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT) == 0 &&
- (flags & XFS_UQUOTA_ENFD))
- ||
+ (mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT) == 0 &&
+ (flags & XFS_UQUOTA_ENFD)) ||
((flags & XFS_PQUOTA_ACCT) == 0 &&
- (mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT) == 0 &&
- (flags & XFS_GQUOTA_ACCT) == 0 &&
- (mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) == 0 &&
- (flags & XFS_OQUOTA_ENFD))) {
+ (mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT) == 0 &&
+ (flags & XFS_PQUOTA_ENFD)) ||
+ ((flags & XFS_GQUOTA_ACCT) == 0 &&
+ (mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) == 0 &&
+ (flags & XFS_GQUOTA_ENFD))) {
xfs_debug(mp,
"%s: Can't enforce without acct, flags=%x sbflags=%x\n",
__func__, flags, mp->m_sb.sb_qflags);
@@ -776,9 +776,12 @@ xfs_qm_scall_getquota(
* gets turned off. No need to confuse the user level code,
* so return zeroes in that case.
*/
- if ((!XFS_IS_UQUOTA_ENFORCED(mp) && dqp->q_core.d_flags == XFS_DQ_USER) ||
- (!XFS_IS_OQUOTA_ENFORCED(mp) &&
- (dqp->q_core.d_flags & (XFS_DQ_PROJ | XFS_DQ_GROUP)))) {
+ if ((!XFS_IS_UQUOTA_ENFORCED(mp) &&
+ dqp->q_core.d_flags == XFS_DQ_USER) ||
+ (!XFS_IS_PQUOTA_ENFORCED(mp) &&
+ dqp->q_core.d_flags == XFS_DQ_PROJ) ||
+ (!XFS_IS_GQUOTA_ENFORCED(mp) &&
+ dqp->q_core.d_flags == XFS_DQ_GROUP)) {
dst->d_btimer = 0;
dst->d_itimer = 0;
dst->d_rtbtimer = 0;
@@ -786,8 +789,8 @@ xfs_qm_scall_getquota(
#ifdef DEBUG
if (((XFS_IS_UQUOTA_ENFORCED(mp) && dst->d_flags == FS_USER_QUOTA) ||
- (XFS_IS_OQUOTA_ENFORCED(mp) &&
- (dst->d_flags & (FS_PROJ_QUOTA | FS_GROUP_QUOTA)))) &&
+ (XFS_IS_PQUOTA_ENFORCED(mp) && dst->d_flags == FS_PROJ_QUOTA) ||
+ (XFS_IS_GQUOTA_ENFORCED(mp) && dst->d_flags == FS_GROUP_QUOTA)) &&
dst->d_id != 0) {
if ((dst->d_bcount > dst->d_blk_softlimit) &&
(dst->d_blk_softlimit > 0)) {
@@ -839,10 +842,10 @@ xfs_qm_export_flags(
uflags |= FS_QUOTA_GDQ_ACCT;
if (flags & XFS_UQUOTA_ENFD)
uflags |= FS_QUOTA_UDQ_ENFD;
- if (flags & (XFS_OQUOTA_ENFD)) {
- uflags |= (flags & XFS_GQUOTA_ACCT) ?
- FS_QUOTA_GDQ_ENFD : FS_QUOTA_PDQ_ENFD;
- }
+ if (flags & XFS_PQUOTA_ENFD)
+ uflags |= FS_QUOTA_PDQ_ENFD;
+ if (flags & XFS_GQUOTA_ENFD)
+ uflags |= FS_QUOTA_GDQ_ENFD;
return (uflags);
}
diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h
index c38068f..0596860 100644
--- a/fs/xfs/xfs_quota.h
+++ b/fs/xfs/xfs_quota.h
@@ -161,28 +161,43 @@ typedef struct xfs_qoff_logformat {
#define XFS_GQUOTA_ACCT 0x0040 /* group quota accounting ON */
/*
+ * Start differentiating group quota and project quota using
+ * distinct flags, instead of using the combined OQUOTA flags.
+ *
+ * Conversion to and from the combined OQUOTA flag (if necessary)
+ * is done only in xfs_readsb() and xfs_sb_to_disk()
+ */
+#define XFS_GQUOTA_ENFD 0x0080 /* group quota limits enforced */
+#define XFS_GQUOTA_CHKD 0x0100 /* quotacheck run on group quotas */
+#define XFS_PQUOTA_ENFD 0x0200 /* project quota limits enforced */
+#define XFS_PQUOTA_CHKD 0x0400 /* quotacheck run on project quotas */
+
+/*
* Quota Accounting/Enforcement flags
*/
#define XFS_ALL_QUOTA_ACCT \
(XFS_UQUOTA_ACCT | XFS_GQUOTA_ACCT | XFS_PQUOTA_ACCT)
-#define XFS_ALL_QUOTA_ENFD (XFS_UQUOTA_ENFD | XFS_OQUOTA_ENFD)
-#define XFS_ALL_QUOTA_CHKD (XFS_UQUOTA_CHKD | XFS_OQUOTA_CHKD)
+#define XFS_ALL_QUOTA_ENFD \
+ (XFS_UQUOTA_ENFD | XFS_GQUOTA_ENFD | XFS_PQUOTA_ENFD)
+#define XFS_ALL_QUOTA_CHKD \
+ (XFS_UQUOTA_CHKD | XFS_GQUOTA_CHKD | XFS_PQUOTA_CHKD)
#define XFS_IS_QUOTA_RUNNING(mp) ((mp)->m_qflags & XFS_ALL_QUOTA_ACCT)
#define XFS_IS_UQUOTA_RUNNING(mp) ((mp)->m_qflags & XFS_UQUOTA_ACCT)
#define XFS_IS_PQUOTA_RUNNING(mp) ((mp)->m_qflags & XFS_PQUOTA_ACCT)
#define XFS_IS_GQUOTA_RUNNING(mp) ((mp)->m_qflags & XFS_GQUOTA_ACCT)
#define XFS_IS_UQUOTA_ENFORCED(mp) ((mp)->m_qflags & XFS_UQUOTA_ENFD)
-#define XFS_IS_OQUOTA_ENFORCED(mp) ((mp)->m_qflags & XFS_OQUOTA_ENFD)
+#define XFS_IS_PQUOTA_ENFORCED(mp) ((mp)->m_qflags & XFS_PQUOTA_ENFD)
+#define XFS_IS_GQUOTA_ENFORCED(mp) ((mp)->m_qflags & XFS_GQUOTA_ENFD)
/*
* Incore only flags for quotaoff - these bits get cleared when quota(s)
* are in the process of getting turned off. These flags are in m_qflags but
* never in sb_qflags.
*/
-#define XFS_UQUOTA_ACTIVE 0x0100 /* uquotas are being turned off */
-#define XFS_PQUOTA_ACTIVE 0x0200 /* pquotas are being turned off */
-#define XFS_GQUOTA_ACTIVE 0x0400 /* gquotas are being turned off */
+#define XFS_UQUOTA_ACTIVE 0x1000 /* uquotas are being turned off */
+#define XFS_PQUOTA_ACTIVE 0x2000 /* pquotas are being turned off */
+#define XFS_GQUOTA_ACTIVE 0x4000 /* gquotas are being turned off */
#define XFS_ALL_QUOTA_ACTIVE \
(XFS_UQUOTA_ACTIVE | XFS_PQUOTA_ACTIVE | XFS_GQUOTA_ACTIVE)
@@ -268,24 +283,23 @@ typedef struct xfs_qoff_logformat {
((XFS_IS_UQUOTA_ON(mp) && \
(mp->m_sb.sb_qflags & XFS_UQUOTA_CHKD) == 0) || \
(XFS_IS_GQUOTA_ON(mp) && \
- ((mp->m_sb.sb_qflags & XFS_OQUOTA_CHKD) == 0 || \
- (mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT))) || \
+ (mp->m_sb.sb_qflags & XFS_GQUOTA_CHKD) == 0) || \
(XFS_IS_PQUOTA_ON(mp) && \
- ((mp->m_sb.sb_qflags & XFS_OQUOTA_CHKD) == 0 || \
- (mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT))))
+ (mp->m_sb.sb_qflags & XFS_PQUOTA_CHKD) == 0))
#define XFS_MOUNT_QUOTA_SET1 (XFS_UQUOTA_ACCT|XFS_UQUOTA_ENFD|\
XFS_UQUOTA_CHKD|XFS_PQUOTA_ACCT|\
- XFS_OQUOTA_ENFD|XFS_OQUOTA_CHKD)
+ XFS_PQUOTA_ENFD|XFS_PQUOTA_CHKD)
#define XFS_MOUNT_QUOTA_SET2 (XFS_UQUOTA_ACCT|XFS_UQUOTA_ENFD|\
XFS_UQUOTA_CHKD|XFS_GQUOTA_ACCT|\
- XFS_OQUOTA_ENFD|XFS_OQUOTA_CHKD)
+ XFS_GQUOTA_ENFD|XFS_GQUOTA_CHKD)
#define XFS_MOUNT_QUOTA_ALL (XFS_UQUOTA_ACCT|XFS_UQUOTA_ENFD|\
XFS_UQUOTA_CHKD|XFS_PQUOTA_ACCT|\
- XFS_OQUOTA_ENFD|XFS_OQUOTA_CHKD|\
- XFS_GQUOTA_ACCT)
+ XFS_PQUOTA_ENFD|XFS_PQUOTA_CHKD|\
+ XFS_GQUOTA_ACCT|XFS_GQUOTA_ENFD|\
+ XFS_GQUOTA_CHKD)
/*
diff --git a/fs/xfs/xfs_quotaops.c b/fs/xfs/xfs_quotaops.c
index 71926d6..056d62e 100644
--- a/fs/xfs/xfs_quotaops.c
+++ b/fs/xfs/xfs_quotaops.c
@@ -75,8 +75,10 @@ xfs_fs_set_xstate(
flags |= XFS_GQUOTA_ACCT;
if (uflags & FS_QUOTA_UDQ_ENFD)
flags |= XFS_UQUOTA_ENFD;
- if (uflags & (FS_QUOTA_PDQ_ENFD|FS_QUOTA_GDQ_ENFD))
- flags |= XFS_OQUOTA_ENFD;
+ if (uflags & FS_QUOTA_PDQ_ENFD)
+ flags |= XFS_PQUOTA_ENFD;
+ if (uflags & FS_QUOTA_GDQ_ENFD)
+ flags |= XFS_GQUOTA_ENFD;
switch (op) {
case Q_XQUOTAON:
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
index 3033ba5..2a76ba2 100644
--- a/fs/xfs/xfs_super.c
+++ b/fs/xfs/xfs_super.c
@@ -359,17 +359,17 @@ xfs_parseargs(
} else if (!strcmp(this_char, MNTOPT_PQUOTA) ||
!strcmp(this_char, MNTOPT_PRJQUOTA)) {
mp->m_qflags |= (XFS_PQUOTA_ACCT | XFS_PQUOTA_ACTIVE |
- XFS_OQUOTA_ENFD);
+ XFS_PQUOTA_ENFD);
} else if (!strcmp(this_char, MNTOPT_PQUOTANOENF)) {
mp->m_qflags |= (XFS_PQUOTA_ACCT | XFS_PQUOTA_ACTIVE);
- mp->m_qflags &= ~XFS_OQUOTA_ENFD;
+ mp->m_qflags &= ~XFS_PQUOTA_ENFD;
} else if (!strcmp(this_char, MNTOPT_GQUOTA) ||
!strcmp(this_char, MNTOPT_GRPQUOTA)) {
mp->m_qflags |= (XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE |
- XFS_OQUOTA_ENFD);
+ XFS_GQUOTA_ENFD);
} else if (!strcmp(this_char, MNTOPT_GQUOTANOENF)) {
mp->m_qflags |= (XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE);
- mp->m_qflags &= ~XFS_OQUOTA_ENFD;
+ mp->m_qflags &= ~XFS_GQUOTA_ENFD;
} else if (!strcmp(this_char, MNTOPT_DELAYLOG)) {
xfs_warn(mp,
"delaylog is the default now, option is deprecated.");
@@ -563,12 +563,12 @@ xfs_showargs(
/* Either project or group quotas can be active, not both */
if (mp->m_qflags & XFS_PQUOTA_ACCT) {
- if (mp->m_qflags & XFS_OQUOTA_ENFD)
+ if (mp->m_qflags & XFS_PQUOTA_ENFD)
seq_puts(m, "," MNTOPT_PRJQUOTA);
else
seq_puts(m, "," MNTOPT_PQUOTANOENF);
} else if (mp->m_qflags & XFS_GQUOTA_ACCT) {
- if (mp->m_qflags & XFS_OQUOTA_ENFD)
+ if (mp->m_qflags & XFS_GQUOTA_ENFD)
seq_puts(m, "," MNTOPT_GRPQUOTA);
else
seq_puts(m, "," MNTOPT_GQUOTANOENF);
@@ -1136,8 +1136,8 @@ xfs_fs_statfs(
spin_unlock(&mp->m_sb_lock);
if ((ip->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) &&
- ((mp->m_qflags & (XFS_PQUOTA_ACCT|XFS_OQUOTA_ENFD))) ==
- (XFS_PQUOTA_ACCT|XFS_OQUOTA_ENFD))
+ ((mp->m_qflags & (XFS_PQUOTA_ACCT|XFS_PQUOTA_ENFD))) ==
+ (XFS_PQUOTA_ACCT|XFS_PQUOTA_ENFD))
xfs_qm_statvfs(ip, statp);
return 0;
}
diff --git a/fs/xfs/xfs_trans_dquot.c b/fs/xfs/xfs_trans_dquot.c
index 7ea7485..80c81fe 100644
--- a/fs/xfs/xfs_trans_dquot.c
+++ b/fs/xfs/xfs_trans_dquot.c
@@ -632,8 +632,8 @@ xfs_trans_dqresv(
if ((flags & XFS_QMOPT_FORCE_RES) == 0 &&
dqp->q_core.d_id &&
((XFS_IS_UQUOTA_ENFORCED(dqp->q_mount) && XFS_QM_ISUDQ(dqp)) ||
- (XFS_IS_OQUOTA_ENFORCED(dqp->q_mount) &&
- (XFS_QM_ISPDQ(dqp) || XFS_QM_ISGDQ(dqp))))) {
+ (XFS_IS_PQUOTA_ENFORCED(dqp->q_mount) && XFS_QM_ISPDQ(dqp)) ||
+ (XFS_IS_GQUOTA_ENFORCED(dqp->q_mount) && XFS_QM_ISGDQ(dqp)))) {
if (nblks > 0) {
/*
* dquot is locked already. See if we'd go over the
--
1.7.1
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v9 3/6] xfs: Add pquota fields where gquota is used.
2013-06-24 2:48 [PATCH v9 0/6] Allow pquota and gquota to be used together Chandra Seetharaman
2013-06-24 2:48 ` [PATCH v9 1/6] xfs: Move code around and remove typedefs Chandra Seetharaman
2013-06-24 2:48 ` [PATCH v9 2/6] xfs: Remove incore use of XFS_OQUOTA_ENFD and XFS_OQUOTA_CHKD Chandra Seetharaman
@ 2013-06-24 2:48 ` Chandra Seetharaman
2013-06-24 8:00 ` Dave Chinner
2013-06-24 2:48 ` [PATCH v9 4/6] xfs: Start using pquotaino from the superblock Chandra Seetharaman
` (2 subsequent siblings)
5 siblings, 1 reply; 28+ messages in thread
From: Chandra Seetharaman @ 2013-06-24 2:48 UTC (permalink / raw)
To: xfs; +Cc: Chandra Seetharaman
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.
Not using the pquotino field from superblock yet.
Signed-off-by: Chandra Seetharaman <sekharan@us.ibm.com>
---
fs/xfs/xfs_dquot.c | 15 +++-
fs/xfs/xfs_dquot.h | 7 +-
fs/xfs/xfs_icache.c | 1 +
fs/xfs/xfs_inode.h | 1 +
fs/xfs/xfs_ioctl.c | 14 ++--
fs/xfs/xfs_iops.c | 4 +-
fs/xfs/xfs_qm.c | 244 +++++++++++++++++++++++++++++++++-------------
fs/xfs/xfs_qm.h | 16 ++-
fs/xfs/xfs_qm_bhv.c | 2 +-
fs/xfs/xfs_qm_syscalls.c | 19 +++-
fs/xfs/xfs_quota.h | 32 ++++---
fs/xfs/xfs_symlink.c | 10 ++-
fs/xfs/xfs_trans_dquot.c | 26 ++++-
fs/xfs/xfs_vnodeops.c | 13 ++-
14 files changed, 285 insertions(+), 119 deletions(-)
diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c
index f01012d..0adf27e 100644
--- a/fs/xfs/xfs_dquot.c
+++ b/fs/xfs/xfs_dquot.c
@@ -936,6 +936,7 @@ xfs_qm_dqput_final(
{
struct xfs_quotainfo *qi = dqp->q_mount->m_quotainfo;
struct xfs_dquot *gdqp;
+ struct xfs_dquot *pdqp;
trace_xfs_dqput_free(dqp);
@@ -949,21 +950,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;
+ }
xfs_dqunlock(dqp);
/*
- * If we had a group quota hint, release it now.
+ * If we had a group/project quota hint, release it now.
*/
if (gdqp)
xfs_qm_dqput(gdqp);
+ if (pdqp)
+ xfs_qm_dqput(pdqp);
}
/*
diff --git a/fs/xfs/xfs_dquot.h b/fs/xfs/xfs_dquot.h
index b596626..55abbca 100644
--- a/fs/xfs/xfs_dquot.h
+++ b/fs/xfs/xfs_dquot.h
@@ -53,6 +53,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 */
xfs_disk_dquot_t q_core; /* actual usage & quotas */
xfs_dq_logitem_t q_logitem; /* dquot log item */
xfs_qcnt_t q_res_bcount; /* total regular nblks used+reserved */
@@ -118,8 +119,9 @@ static inline int xfs_this_quota_on(struct xfs_mount *mp, int type)
case XFS_DQ_USER:
return XFS_IS_UQUOTA_ON(mp);
case XFS_DQ_GROUP:
+ return XFS_IS_GQUOTA_ON(mp);
case XFS_DQ_PROJ:
- return XFS_IS_OQUOTA_ON(mp);
+ return XFS_IS_PQUOTA_ON(mp);
default:
return 0;
}
@@ -131,8 +133,9 @@ static inline xfs_dquot_t *xfs_inode_dquot(struct xfs_inode *ip, int type)
case XFS_DQ_USER:
return ip->i_udquot;
case XFS_DQ_GROUP:
- case XFS_DQ_PROJ:
return ip->i_gdquot;
+ case XFS_DQ_PROJ:
+ return ip->i_pdquot;
default:
return NULL;
}
diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c
index 9560dc1..3f90e1c 100644
--- a/fs/xfs/xfs_icache.c
+++ b/fs/xfs/xfs_icache.c
@@ -337,6 +337,7 @@ xfs_iget_cache_miss(
iflags |= XFS_IDONTCACHE;
ip->i_udquot = NULL;
ip->i_gdquot = NULL;
+ ip->i_pdquot = NULL;
xfs_iflags_set(ip, iflags);
/* insert the new inode */
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index 9112979..b55fd34 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -250,6 +250,7 @@ typedef struct xfs_inode {
struct xfs_mount *i_mount; /* fs mount struct ptr */
struct xfs_dquot *i_udquot; /* user dquot */
struct xfs_dquot *i_gdquot; /* group dquot */
+ struct xfs_dquot *i_pdquot; /* project dquot */
/* Inode location stuff */
xfs_ino_t i_ino; /* inode number (agno/agino)*/
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index 5e99968..71a8bc5 100644
--- 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);
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);
if (code) /* out of quota */
goto error_return;
@@ -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_set_projid(ip, fa->fsx_projid);
@@ -1160,13 +1160,13 @@ xfs_ioctl_setattr(
*/
xfs_qm_dqrele(olddquot);
xfs_qm_dqrele(udqp);
- xfs_qm_dqrele(gdqp);
+ xfs_qm_dqrele(pdqp);
return code;
error_return:
xfs_qm_dqrele(udqp);
- xfs_qm_dqrele(gdqp);
+ xfs_qm_dqrele(pdqp);
xfs_trans_cancel(tp, 0);
if (lock_flags)
xfs_iunlock(ip, lock_flags);
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
index c69bbc4..2ae62d2 100644
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -539,7 +539,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);
if (error)
return error;
}
@@ -575,7 +575,7 @@ xfs_setattr_nonsize(
(XFS_IS_GQUOTA_ON(mp) && igid != gid))) {
ASSERT(tp);
error = xfs_qm_vop_chown_reserve(tp, ip, udqp, gdqp,
- capable(CAP_FOWNER) ?
+ NULL, capable(CAP_FOWNER) ?
XFS_QMOPT_FORCE_RES : 0);
if (error) /* out of quota */
goto out_trans_cancel;
diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c
index de7ecbd..b3e05ef 100644
--- a/fs/xfs/xfs_qm.c
+++ b/fs/xfs/xfs_qm.c
@@ -137,6 +137,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 *pdqp = NULL;
xfs_dqlock(dqp);
if ((dqp->dq_flags & XFS_DQ_FREEING) || dqp->q_nrefs != 0) {
@@ -145,8 +146,7 @@ xfs_qm_dqpurge(
}
/*
- * If this quota has a group hint attached, prepare for releasing it
- * now.
+ * If this quota has a hint attached, prepare for releasing it now.
*/
gdqp = dqp->q_gdquot;
if (gdqp) {
@@ -154,6 +154,12 @@ xfs_qm_dqpurge(
dqp->q_gdquot = NULL;
}
+ pdqp = dqp->q_pdquot;
+ if (pdqp) {
+ xfs_dqlock(pdqp);
+ dqp->q_pdquot = NULL;
+ }
+
dqp->dq_flags |= XFS_DQ_FREEING;
xfs_dqflock(dqp);
@@ -208,6 +214,8 @@ xfs_qm_dqpurge(
if (gdqp)
xfs_qm_dqput(gdqp);
+ if (pdqp)
+ xfs_qm_dqput(pdqp);
return 0;
}
@@ -364,6 +372,10 @@ xfs_qm_unmount_quotas(
IRELE(mp->m_quotainfo->qi_gquotaip);
mp->m_quotainfo->qi_gquotaip = NULL;
}
+ if (mp->m_quotainfo->qi_pquotaip) {
+ IRELE(mp->m_quotainfo->qi_pquotaip);
+ mp->m_quotainfo->qi_pquotaip = NULL;
+ }
}
}
@@ -410,7 +422,10 @@ xfs_qm_dqattach_one(
* be reclaimed as long as we have a ref from inode and we
* hold the ilock.
*/
- dqp = udqhint->q_gdquot;
+ if (type == XFS_DQ_GROUP)
+ dqp = udqhint->q_gdquot;
+ else
+ dqp = udqhint->q_pdquot;
if (dqp && be32_to_cpu(dqp->q_core.d_id) == id) {
ASSERT(*IO_idqpp == NULL);
@@ -453,28 +468,40 @@ xfs_qm_dqattach_one(
/*
- * Given a udquot and gdquot, attach a ptr to the group dquot in the
- * udquot as a hint for future lookups.
+ * Given a udquot and group/project type, attach the group/project
+ * dquot pointer to 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_hint(
+ struct xfs_inode *ip,
+ int type)
{
- xfs_dquot_t *tmp;
+ struct xfs_dquot **dqhint;
+ struct xfs_dquot *dqp;
+ struct xfs_dquot *udq = ip->i_udquot;
xfs_dqlock(udq);
- tmp = udq->q_gdquot;
- if (tmp) {
- if (tmp == gdq)
+ if (type == XFS_DQ_GROUP) {
+ dqp = ip->i_gdquot;
+ dqhint = &udq->q_gdquot;
+ } else {
+ dqp = ip->i_pdquot;
+ dqhint = &udq->q_pdquot;
+ }
+
+ if (*dqhint) {
+ struct xfs_dquot *tmp;
+
+ if (*dqhint == dqp)
goto done;
- udq->q_gdquot = NULL;
+ tmp = *dqhint;
+ *dqhint = NULL;
xfs_qm_dqrele(tmp);
}
- udq->q_gdquot = xfs_qm_dqhold(gdq);
+ *dqhint = xfs_qm_dqhold(dqp);
done:
xfs_dqunlock(udq);
}
@@ -527,12 +554,8 @@ xfs_qm_dqattach_locked(
}
ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
- if (XFS_IS_OQUOTA_ON(mp)) {
- error = XFS_IS_GQUOTA_ON(mp) ?
- xfs_qm_dqattach_one(ip, ip->i_d.di_gid, XFS_DQ_GROUP,
- flags & XFS_QMOPT_DQALLOC,
- ip->i_udquot, &ip->i_gdquot) :
- xfs_qm_dqattach_one(ip, xfs_get_projid(ip), XFS_DQ_PROJ,
+ if (XFS_IS_GQUOTA_ON(mp)) {
+ error = xfs_qm_dqattach_one(ip, ip->i_d.di_gid, XFS_DQ_GROUP,
flags & XFS_QMOPT_DQALLOC,
ip->i_udquot, &ip->i_gdquot);
/*
@@ -544,14 +567,28 @@ xfs_qm_dqattach_locked(
nquotas++;
}
+ ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
+ if (XFS_IS_PQUOTA_ON(mp)) {
+ error = xfs_qm_dqattach_one(ip, xfs_get_projid(ip), XFS_DQ_PROJ,
+ flags & XFS_QMOPT_DQALLOC,
+ ip->i_udquot, &ip->i_pdquot);
+ /*
+ * Don't worry about the udquot that we may have
+ * attached above. It'll get detached, if not already.
+ */
+ if (error)
+ goto done;
+ nquotas++;
+ }
+
/*
- * Attach this group quota to the user quota as a hint.
+ * Attach this group/project quota to the user quota as a hint.
* This WON'T, in general, result in a thrash.
*/
- if (nquotas == 2) {
+ if (nquotas > 1 && ip->i_udquot) {
ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
- ASSERT(ip->i_udquot);
- ASSERT(ip->i_gdquot);
+ ASSERT(ip->i_gdquot || !XFS_IS_GQUOTA_ON(mp));
+ ASSERT(ip->i_pdquot || !XFS_IS_PQUOTA_ON(mp));
/*
* We do not have i_udquot locked at this point, but this check
@@ -559,8 +596,13 @@ xfs_qm_dqattach_locked(
* 100% all the time. It is just a hint, and this will
* succeed in general.
*/
- if (ip->i_udquot->q_gdquot != ip->i_gdquot)
- xfs_qm_dqattach_grouphint(ip->i_udquot, ip->i_gdquot);
+ if (XFS_IS_GQUOTA_ON(mp) &&
+ ip->i_udquot->q_gdquot != ip->i_gdquot)
+ xfs_qm_dqattach_hint(ip, XFS_DQ_GROUP);
+
+ if (XFS_IS_PQUOTA_ON(mp) &&
+ ip->i_udquot->q_pdquot != ip->i_pdquot)
+ xfs_qm_dqattach_hint(ip, XFS_DQ_PROJ);
}
done:
@@ -568,8 +610,10 @@ xfs_qm_dqattach_locked(
if (!error) {
if (XFS_IS_UQUOTA_ON(mp))
ASSERT(ip->i_udquot);
- if (XFS_IS_OQUOTA_ON(mp))
+ if (XFS_IS_GQUOTA_ON(mp))
ASSERT(ip->i_gdquot);
+ if (XFS_IS_PQUOTA_ON(mp))
+ ASSERT(ip->i_pdquot);
}
ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
#endif
@@ -602,7 +646,7 @@ void
xfs_qm_dqdetach(
xfs_inode_t *ip)
{
- if (!(ip->i_udquot || ip->i_gdquot))
+ if (!(ip->i_udquot || ip->i_gdquot || ip->i_pdquot))
return;
trace_xfs_dquot_dqdetach(ip);
@@ -616,6 +660,10 @@ xfs_qm_dqdetach(
xfs_qm_dqrele(ip->i_gdquot);
ip->i_gdquot = NULL;
}
+ if (ip->i_pdquot) {
+ xfs_qm_dqrele(ip->i_pdquot);
+ ip->i_pdquot = NULL;
+ }
}
int
@@ -660,6 +708,7 @@ xfs_qm_init_quotainfo(
INIT_RADIX_TREE(&qinf->qi_uquota_tree, GFP_NOFS);
INIT_RADIX_TREE(&qinf->qi_gquota_tree, GFP_NOFS);
+ INIT_RADIX_TREE(&qinf->qi_pquota_tree, GFP_NOFS);
mutex_init(&qinf->qi_tree_lock);
INIT_LIST_HEAD(&qinf->qi_lru_list);
@@ -761,6 +810,10 @@ xfs_qm_destroy_quotainfo(
IRELE(qi->qi_gquotaip);
qi->qi_gquotaip = NULL;
}
+ if (qi->qi_pquotaip) {
+ IRELE(qi->qi_pquotaip);
+ qi->qi_pquotaip = NULL;
+ }
mutex_destroy(&qi->qi_quotaofflock);
kmem_free(qi);
mp->m_quotainfo = NULL;
@@ -1269,13 +1322,14 @@ xfs_qm_quotacheck(
LIST_HEAD (buffer_list);
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;
count = INT_MAX;
structsz = 1;
lastino = 0;
flags = 0;
- ASSERT(uip || gip);
+ ASSERT(uip || gip || pip);
ASSERT(XFS_IS_QUOTA_RUNNING(mp));
xfs_notice(mp, "Quotacheck needed: Please wait.");
@@ -1294,13 +1348,19 @@ xfs_qm_quotacheck(
}
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_GQUOTA_CHKD;
+ }
+
+ if (pip) {
+ error = xfs_qm_dqiterate(mp, pip, XFS_QMOPT_PQUOTA,
&buffer_list);
if (error)
goto error_return;
- flags |= XFS_IS_GQUOTA_ON(mp) ?
- XFS_GQUOTA_CHKD : XFS_PQUOTA_CHKD;
+ flags |= XFS_PQUOTA_CHKD;
}
do {
@@ -1397,6 +1457,7 @@ xfs_qm_init_quotainos(
{
struct xfs_inode *uip = NULL;
struct xfs_inode *gip = NULL;
+ struct xfs_inode *pip = NULL;
int error;
__int64_t sbflags = 0;
uint flags = 0;
@@ -1415,7 +1476,7 @@ xfs_qm_init_quotainos(
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);
error = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino,
@@ -1423,6 +1484,15 @@ xfs_qm_init_quotainos(
if (error)
goto error_rele;
}
+ /* Use 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;
+ }
} else {
flags |= XFS_QMOPT_SBVERSION;
sbflags |= (XFS_SB_VERSIONNUM | XFS_SB_UQUOTINO |
@@ -1430,7 +1500,7 @@ xfs_qm_init_quotainos(
}
/*
- * Create the two inodes, if they don't exist already. The changes
+ * Create the three inodes, if they don't exist already. The changes
* made above will get added to a transaction and logged in one of
* the qino_alloc calls below. If the device is readonly,
* temporarily switch to read-write to do this.
@@ -1444,17 +1514,26 @@ xfs_qm_init_quotainos(
flags &= ~XFS_QMOPT_SBVERSION;
}
- if (XFS_IS_OQUOTA_ON(mp) && gip == NULL) {
- flags |= (XFS_IS_GQUOTA_ON(mp) ?
- XFS_QMOPT_GQUOTA : XFS_QMOPT_PQUOTA);
+ if (XFS_IS_GQUOTA_ON(mp) && gip == NULL) {
error = xfs_qm_qino_alloc(mp, &gip,
- sbflags | XFS_SB_GQUOTINO, flags);
+ sbflags | XFS_SB_GQUOTINO,
+ flags | XFS_QMOPT_GQUOTA);
+ if (error)
+ goto error_rele;
+
+ flags &= ~XFS_QMOPT_SBVERSION;
+ }
+ if (XFS_IS_PQUOTA_ON(mp) && pip == NULL) {
+ error = xfs_qm_qino_alloc(mp, &pip,
+ sbflags | XFS_SB_GQUOTINO,
+ flags | XFS_QMOPT_PQUOTA);
if (error)
goto error_rele;
}
mp->m_quotainfo->qi_uquotaip = uip;
mp->m_quotainfo->qi_gquotaip = gip;
+ mp->m_quotainfo->qi_pquotaip = pip;
return 0;
@@ -1463,6 +1542,8 @@ error_rele:
IRELE(uip);
if (gip)
IRELE(gip);
+ if (pip)
+ IRELE(pip);
return XFS_ERROR(error);
}
@@ -1657,11 +1738,13 @@ 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 = NULL;
struct xfs_dquot *gq = NULL;
+ struct xfs_dquot *pq = NULL;
int error;
uint lockflags;
@@ -1739,23 +1822,24 @@ 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);
error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t)prid,
XFS_DQ_PROJ,
XFS_QMOPT_DQALLOC |
XFS_QMOPT_DOWARN,
- &gq);
+ &pq);
ASSERT(error != ENOENT);
if (error)
goto error_rele;
- xfs_dqunlock(gq);
+ xfs_dqunlock(pq);
lockflags = XFS_ILOCK_SHARED;
xfs_ilock(ip, lockflags);
} else {
- ASSERT(ip->i_gdquot);
- gq = xfs_qm_dqhold(ip->i_gdquot);
+ ASSERT(ip->i_pdquot);
+ pq = xfs_qm_dqhold(ip->i_pdquot);
}
}
if (uq)
@@ -1770,9 +1854,15 @@ xfs_qm_vop_dqalloc(
*O_gdqpp = gq;
else if (gq)
xfs_qm_dqrele(gq);
+ if (O_pdqpp)
+ *O_pdqpp = pq;
+ else if (pq)
+ xfs_qm_dqrele(pq);
return 0;
error_rele:
+ if (gq)
+ xfs_qm_dqrele(gq);
if (uq)
xfs_qm_dqrele(uq);
return error;
@@ -1827,14 +1917,17 @@ xfs_qm_vop_chown_reserve(
struct xfs_inode *ip,
struct xfs_dquot *udqp,
struct xfs_dquot *gdqp,
+ struct xfs_dquot *pdqp,
uint flags)
{
struct xfs_mount *mp = ip->i_mount;
uint delblks, blkflags, prjflags = 0;
struct xfs_dquot *udq_unres = NULL;
struct xfs_dquot *gdq_unres = NULL;
+ struct xfs_dquot *pdq_unres = NULL;
struct xfs_dquot *udq_delblks = NULL;
struct xfs_dquot *gdq_delblks = NULL;
+ struct xfs_dquot *pdq_delblks = NULL;
int error;
@@ -1858,24 +1951,28 @@ xfs_qm_vop_chown_reserve(
udq_unres = 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))) {
- gdq_delblks = gdqp;
- if (delblks) {
- ASSERT(ip->i_gdquot);
- gdq_unres = 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)) {
+ gdq_delblks = gdqp;
+ if (delblks) {
+ ASSERT(ip->i_gdquot);
+ gdq_unres = 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;
+ pdq_delblks = pdqp;
+ if (delblks) {
+ ASSERT(ip->i_pdquot);
+ pdq_unres = ip->i_pdquot;
}
}
error = xfs_trans_reserve_quota_bydquots(tp, ip->i_mount,
- udq_delblks, gdq_delblks, ip->i_d.di_nblocks, 1,
+ udq_delblks, gdq_delblks, pdq_delblks,
+ ip->i_d.di_nblocks, 1,
flags | blkflags | prjflags);
if (error)
return error;
@@ -1890,16 +1987,17 @@ xfs_qm_vop_chown_reserve(
/*
* Do the reservations first. Unreservation can't fail.
*/
- ASSERT(udq_delblks || gdq_delblks);
- ASSERT(udq_unres || gdq_unres);
+ ASSERT(udq_delblks || gdq_delblks || pdq_delblks);
+ ASSERT(udq_unres || gdq_unres || pdq_unres);
error = xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount,
- udq_delblks, gdq_delblks, (xfs_qcnt_t)delblks, 0,
+ udq_delblks, gdq_delblks, pdq_delblks,
+ (xfs_qcnt_t)delblks, 0,
flags | blkflags | prjflags);
if (error)
return error;
xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount,
- udq_unres, gdq_unres, -((xfs_qcnt_t)delblks), 0,
- blkflags);
+ udq_unres, gdq_unres, pdq_unres,
+ -((xfs_qcnt_t)delblks), 0, blkflags);
}
return (0);
@@ -1938,7 +2036,8 @@ xfs_qm_vop_create_dqattach(
struct xfs_trans *tp,
struct xfs_inode *ip,
struct xfs_dquot *udqp,
- struct xfs_dquot *gdqp)
+ struct xfs_dquot *gdqp,
+ struct xfs_dquot *pdqp)
{
struct xfs_mount *mp = tp->t_mountp;
@@ -1958,13 +2057,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);
+ }
}
diff --git a/fs/xfs/xfs_qm.h b/fs/xfs/xfs_qm.h
index 4b330f2..400889e 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;
struct xfs_inode *qi_uquotaip; /* user quota inode */
struct xfs_inode *qi_gquotaip; /* group quota inode */
+ struct xfs_inode *qi_pquotaip; /* project quota inode */
struct list_head qi_lru_list;
struct mutex qi_lru_lock;
int qi_lru_count;
@@ -78,8 +80,9 @@ xfs_dquot_tree(
case XFS_DQ_USER:
return &qi->qi_uquota_tree;
case XFS_DQ_GROUP:
- case XFS_DQ_PROJ:
return &qi->qi_gquota_tree;
+ case XFS_DQ_PROJ:
+ return &qi->qi_pquota_tree;
default:
ASSERT(0);
}
@@ -93,8 +96,9 @@ xfs_dq_to_quota_inode(struct xfs_dquot *dqp)
case XFS_DQ_USER:
return dqp->q_mount->m_quotainfo->qi_uquotaip;
case XFS_DQ_GROUP:
- case XFS_DQ_PROJ:
return dqp->q_mount->m_quotainfo->qi_gquotaip;
+ case XFS_DQ_PROJ:
+ return dqp->q_mount->m_quotainfo->qi_pquotaip;
default:
ASSERT(0);
}
@@ -107,18 +111,20 @@ extern void xfs_trans_mod_dquot(struct xfs_trans *,
struct xfs_dquot *, uint, long);
extern int xfs_trans_reserve_quota_bydquots(struct xfs_trans *,
struct xfs_mount *, struct xfs_dquot *,
- struct xfs_dquot *, long, long, uint);
+ struct xfs_dquot *, struct xfs_dquot *,
+ long, long, uint);
extern void xfs_trans_dqjoin(struct xfs_trans *, struct xfs_dquot *);
extern void xfs_trans_log_dquot(struct xfs_trans *, struct xfs_dquot *);
/*
- * 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_PRJ,
XFS_QM_TRANS_DQTYPES
};
#define XFS_QM_TRANS_MAXDQS 2
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" : ""),
diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c
index 5e51227..ed7cd55 100644
--- a/fs/xfs/xfs_qm_syscalls.c
+++ b/fs/xfs/xfs_qm_syscalls.c
@@ -119,7 +119,8 @@ xfs_qm_scall_quotaoff(
dqtype |= XFS_QMOPT_GQUOTA;
flags |= (XFS_GQUOTA_CHKD | XFS_GQUOTA_ENFD);
inactivate_flags |= XFS_GQUOTA_ACTIVE;
- } else if (flags & XFS_PQUOTA_ACCT) {
+ }
+ if (flags & XFS_PQUOTA_ACCT) {
dqtype |= XFS_QMOPT_PQUOTA;
flags |= (XFS_PQUOTA_CHKD | XFS_PQUOTA_ENFD);
inactivate_flags |= XFS_PQUOTA_ACTIVE;
@@ -214,10 +215,14 @@ xfs_qm_scall_quotaoff(
IRELE(q->qi_uquotaip);
q->qi_uquotaip = NULL;
}
- if ((dqtype & (XFS_QMOPT_GQUOTA|XFS_QMOPT_PQUOTA)) && q->qi_gquotaip) {
+ if ((dqtype & XFS_QMOPT_GQUOTA) && q->qi_gquotaip) {
IRELE(q->qi_gquotaip);
q->qi_gquotaip = NULL;
}
+ if ((dqtype & XFS_QMOPT_PQUOTA) && q->qi_pquotaip) {
+ IRELE(q->qi_pquotaip);
+ q->qi_pquotaip = NULL;
+ }
out_unlock:
mutex_unlock(&q->qi_quotaofflock);
@@ -859,9 +864,11 @@ xfs_dqrele_inode(
{
/* skip quota inodes */
if (ip == ip->i_mount->m_quotainfo->qi_uquotaip ||
- ip == ip->i_mount->m_quotainfo->qi_gquotaip) {
+ ip == ip->i_mount->m_quotainfo->qi_gquotaip ||
+ ip == ip->i_mount->m_quotainfo->qi_pquotaip) {
ASSERT(ip->i_udquot == NULL);
ASSERT(ip->i_gdquot == NULL);
+ ASSERT(ip->i_pdquot == NULL);
return 0;
}
@@ -870,10 +877,14 @@ xfs_dqrele_inode(
xfs_qm_dqrele(ip->i_udquot);
ip->i_udquot = NULL;
}
- if (flags & (XFS_PQUOTA_ACCT|XFS_GQUOTA_ACCT) && ip->i_gdquot) {
+ if ((flags & XFS_GQUOTA_ACCT) && ip->i_gdquot) {
xfs_qm_dqrele(ip->i_gdquot);
ip->i_gdquot = NULL;
}
+ if ((flags & XFS_PQUOTA_ACCT) && ip->i_pdquot) {
+ xfs_qm_dqrele(ip->i_pdquot);
+ ip->i_pdquot = NULL;
+ }
xfs_iunlock(ip, XFS_ILOCK_EXCL);
return 0;
}
diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h
index 0596860..d7668f9 100644
--- a/fs/xfs/xfs_quota.h
+++ b/fs/xfs/xfs_quota.h
@@ -274,10 +274,10 @@ typedef struct xfs_qoff_logformat {
* we didn't have the inode locked, the appropriate dquot(s) will be
* attached atomically.
*/
-#define XFS_NOT_DQATTACHED(mp, ip) ((XFS_IS_UQUOTA_ON(mp) &&\
- (ip)->i_udquot == NULL) || \
- (XFS_IS_OQUOTA_ON(mp) && \
- (ip)->i_gdquot == 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))
#define XFS_QM_NEED_QUOTACHECK(mp) \
((XFS_IS_UQUOTA_ON(mp) && \
@@ -332,17 +332,18 @@ extern int xfs_trans_reserve_quota_nblks(struct xfs_trans *,
struct xfs_inode *, long, long, uint);
extern int xfs_trans_reserve_quota_bydquots(struct xfs_trans *,
struct xfs_mount *, struct xfs_dquot *,
- struct xfs_dquot *, long, long, uint);
+ struct xfs_dquot *, struct xfs_dquot *, long, long, uint);
extern int xfs_qm_vop_dqalloc(struct xfs_inode *, uid_t, gid_t, prid_t, uint,
- struct xfs_dquot **, struct xfs_dquot **);
+ struct xfs_dquot **, struct xfs_dquot **, struct xfs_dquot **);
extern void xfs_qm_vop_create_dqattach(struct xfs_trans *, struct xfs_inode *,
- struct xfs_dquot *, struct xfs_dquot *);
+ struct xfs_dquot *, struct xfs_dquot *, struct xfs_dquot *);
extern int xfs_qm_vop_rename_dqattach(struct xfs_inode **);
extern struct xfs_dquot *xfs_qm_vop_chown(struct xfs_trans *,
struct xfs_inode *, struct xfs_dquot **, struct xfs_dquot *);
extern int xfs_qm_vop_chown_reserve(struct xfs_trans *, struct xfs_inode *,
- struct xfs_dquot *, struct xfs_dquot *, uint);
+ struct xfs_dquot *, struct xfs_dquot *,
+ struct xfs_dquot *, uint);
extern int xfs_qm_dqattach(struct xfs_inode *, uint);
extern int xfs_qm_dqattach_locked(struct xfs_inode *, uint);
extern void xfs_qm_dqdetach(struct xfs_inode *);
@@ -356,10 +357,12 @@ extern void xfs_qm_unmount_quotas(struct xfs_mount *);
#else
static inline int
xfs_qm_vop_dqalloc(struct xfs_inode *ip, uid_t uid, gid_t gid, prid_t prid,
- uint flags, struct xfs_dquot **udqp, struct xfs_dquot **gdqp)
+ uint flags, struct xfs_dquot **udqp, struct xfs_dquot **gdqp,
+ struct xfs_dquot **pdqp)
{
*udqp = NULL;
*gdqp = NULL;
+ *pdqp = NULL;
return 0;
}
#define xfs_trans_dup_dqinfo(tp, tp2)
@@ -374,14 +377,15 @@ static inline int xfs_trans_reserve_quota_nblks(struct xfs_trans *tp,
}
static inline int xfs_trans_reserve_quota_bydquots(struct xfs_trans *tp,
struct xfs_mount *mp, struct xfs_dquot *udqp,
- struct xfs_dquot *gdqp, long nblks, long nions, uint flags)
+ struct xfs_dquot *gdqp, struct xfs_dquot *pdqp,
+ long nblks, long nions, uint flags)
{
return 0;
}
-#define xfs_qm_vop_create_dqattach(tp, ip, u, g)
+#define xfs_qm_vop_create_dqattach(tp, ip, u, g, p)
#define xfs_qm_vop_rename_dqattach(it) (0)
#define xfs_qm_vop_chown(tp, ip, old, new) (NULL)
-#define xfs_qm_vop_chown_reserve(tp, ip, u, g, fl) (0)
+#define xfs_qm_vop_chown_reserve(tp, ip, u, g, p, fl) (0)
#define xfs_qm_dqattach(ip, fl) (0)
#define xfs_qm_dqattach_locked(ip, fl) (0)
#define xfs_qm_dqdetach(ip)
@@ -395,8 +399,8 @@ static inline int xfs_trans_reserve_quota_bydquots(struct xfs_trans *tp,
#define xfs_trans_unreserve_quota_nblks(tp, ip, nblks, ninos, flags) \
xfs_trans_reserve_quota_nblks(tp, ip, -(nblks), -(ninos), flags)
-#define xfs_trans_reserve_quota(tp, mp, ud, gd, nb, ni, f) \
- xfs_trans_reserve_quota_bydquots(tp, mp, ud, gd, nb, ni, \
+#define xfs_trans_reserve_quota(tp, mp, ud, gd, pd, nb, ni, f) \
+ xfs_trans_reserve_quota_bydquots(tp, mp, ud, gd, pd, nb, ni, \
f | XFS_QMOPT_RES_REGBLKS)
extern int xfs_qm_dqcheck(struct xfs_mount *, xfs_disk_dquot_t *,
diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c
index e830fb5..f4895b6 100644
--- a/fs/xfs/xfs_symlink.c
+++ b/fs/xfs/xfs_symlink.c
@@ -360,6 +360,7 @@ xfs_symlink(
prid_t prid;
struct xfs_dquot *udqp = NULL;
struct xfs_dquot *gdqp = NULL;
+ struct xfs_dquot *pdqp = NULL;
uint resblks;
*ipp = NULL;
@@ -386,7 +387,7 @@ xfs_symlink(
* 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);
if (error)
goto std_return;
@@ -427,7 +428,8 @@ xfs_symlink(
/*
* Reserve disk quota : blocks and inode.
*/
- error = xfs_trans_reserve_quota(tp, mp, udqp, gdqp, resblks, 1, 0);
+ error = xfs_trans_reserve_quota(tp, mp, udqp, gdqp,
+ pdqp, resblks, 1, 0);
if (error)
goto error_return;
@@ -465,7 +467,7 @@ xfs_symlink(
/*
* Also attach the dquot(s) to it, if applicable.
*/
- xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp);
+ xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp, pdqp);
if (resblks)
resblks -= XFS_IALLOC_SPACE_RES(mp);
@@ -563,6 +565,7 @@ xfs_symlink(
error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES);
xfs_qm_dqrele(udqp);
xfs_qm_dqrele(gdqp);
+ xfs_qm_dqrele(pdqp);
*ipp = ip;
return 0;
@@ -576,6 +579,7 @@ xfs_symlink(
xfs_trans_cancel(tp, cancel_flags);
xfs_qm_dqrele(udqp);
xfs_qm_dqrele(gdqp);
+ xfs_qm_dqrele(pdqp);
if (unlock_dp_on_error)
xfs_iunlock(dp, XFS_ILOCK_EXCL);
diff --git a/fs/xfs/xfs_trans_dquot.c b/fs/xfs/xfs_trans_dquot.c
index 80c81fe..f0b0d16 100644
--- a/fs/xfs/xfs_trans_dquot.c
+++ b/fs/xfs/xfs_trans_dquot.c
@@ -163,8 +163,10 @@ xfs_trans_mod_dquot_byino(
if (XFS_IS_UQUOTA_ON(mp) && ip->i_udquot)
(void) xfs_trans_mod_dquot(tp, ip->i_udquot, field, delta);
- if (XFS_IS_OQUOTA_ON(mp) && ip->i_gdquot)
+ if (XFS_IS_GQUOTA_ON(mp) && ip->i_gdquot)
(void) xfs_trans_mod_dquot(tp, ip->i_gdquot, field, delta);
+ if (XFS_IS_PQUOTA_ON(mp) && ip->i_pdquot)
+ (void) xfs_trans_mod_dquot(tp, ip->i_pdquot, field, delta);
}
STATIC struct xfs_dqtrx *
@@ -177,8 +179,12 @@ xfs_trans_get_dqtrx(
if (XFS_QM_ISUDQ(dqp))
qa = tp->t_dqinfo->dqs[XFS_QM_TRANS_USR];
- else
+ else if (XFS_QM_ISGDQ(dqp))
qa = tp->t_dqinfo->dqs[XFS_QM_TRANS_GRP];
+ else if (XFS_QM_ISPDQ(dqp))
+ qa = tp->t_dqinfo->dqs[XFS_QM_TRANS_PRJ];
+ else
+ return NULL;
for (i = 0; i < XFS_QM_TRANS_MAXDQS; i++) {
if (qa[i].qt_dquot == NULL ||
@@ -728,8 +734,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.
@@ -744,6 +750,7 @@ xfs_trans_reserve_quota_bydquots(
struct xfs_mount *mp,
struct xfs_dquot *udqp,
struct xfs_dquot *gdqp,
+ struct xfs_dquot *pdqp,
long nblks,
long ninos,
uint flags)
@@ -771,11 +778,21 @@ xfs_trans_reserve_quota_bydquots(
goto unwind_usr;
}
+ if (pdqp) {
+ error = xfs_trans_dqresv(tp, mp, pdqp, nblks, ninos, flags);
+ if (error)
+ goto unwind_grp;
+ }
+
/*
* Didn't change anything critical, so, no need to log
*/
return 0;
+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)
@@ -817,6 +834,7 @@ xfs_trans_reserve_quota_nblks(
*/
return xfs_trans_reserve_quota_bydquots(tp, mp,
ip->i_udquot, ip->i_gdquot,
+ ip->i_pdquot,
nblks, ninos, flags);
}
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index 42c0ef2..dc730ac 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -489,6 +489,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;
@@ -507,7 +508,8 @@ 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);
if (error)
return error;
@@ -559,7 +561,8 @@ xfs_create(
/*
* Reserve disk quota and the inode.
*/
- error = xfs_trans_reserve_quota(tp, mp, udqp, gdqp, resblks, 1, 0);
+ error = xfs_trans_reserve_quota(tp, mp, udqp, gdqp,
+ pdqp, resblks, 1, 0);
if (error)
goto out_trans_cancel;
@@ -623,7 +626,7 @@ xfs_create(
* These ids of the inode couldn't have changed since the new
* inode has been locked ever since it was created.
*/
- xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp);
+ xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp, pdqp);
error = xfs_bmap_finish(&tp, &free_list, &committed);
if (error)
@@ -635,6 +638,7 @@ xfs_create(
xfs_qm_dqrele(udqp);
xfs_qm_dqrele(gdqp);
+ xfs_qm_dqrele(pdqp);
*ipp = ip;
return 0;
@@ -656,6 +660,7 @@ xfs_create(
xfs_qm_dqrele(udqp);
xfs_qm_dqrele(gdqp);
+ xfs_qm_dqrele(pdqp);
if (unlock_dp_on_error)
xfs_iunlock(dp, XFS_ILOCK_EXCL);
@@ -1568,7 +1573,7 @@ xfs_free_file_space(
}
xfs_ilock(ip, XFS_ILOCK_EXCL);
error = xfs_trans_reserve_quota(tp, mp,
- ip->i_udquot, ip->i_gdquot,
+ ip->i_udquot, ip->i_gdquot, ip->i_pdquot,
resblks, 0, XFS_QMOPT_RES_REGBLKS);
if (error)
goto error1;
--
1.7.1
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v9 4/6] xfs: Start using pquotaino from the superblock.
2013-06-24 2:48 [PATCH v9 0/6] Allow pquota and gquota to be used together Chandra Seetharaman
` (2 preceding siblings ...)
2013-06-24 2:48 ` [PATCH v9 3/6] xfs: Add pquota fields where gquota is used Chandra Seetharaman
@ 2013-06-24 2:48 ` Chandra Seetharaman
2013-06-25 6:31 ` Dave Chinner
2013-06-24 2:48 ` [PATCH v9 5/6] xfs: Add proper versioning support to fs_quota_stat Chandra Seetharaman
2013-06-24 2:48 ` [PATCH v9 6/6] xfs: Use new qs_pquota field in fs_quota_stat for Q_XGETQSTAT Chandra Seetharaman
5 siblings, 1 reply; 28+ messages in thread
From: Chandra Seetharaman @ 2013-06-24 2:48 UTC (permalink / raw)
To: xfs; +Cc: Chandra Seetharaman
Start using pquotino and define a macro to check if the
superblock has pquotino.
Keep backward compatibilty by alowing mount of older superblock
with no separate pquota inode.
Signed-off-by: Chandra Seetharaman <sekharan@us.ibm.com>
---
fs/xfs/xfs_fsops.c | 3 +-
fs/xfs/xfs_mount.c | 51 +++++++++++++++++++++++++++++++--------
fs/xfs/xfs_qm.c | 22 +++++++++--------
fs/xfs/xfs_qm_syscalls.c | 24 ++++++++++++++++--
fs/xfs/xfs_quota.h | 8 ------
fs/xfs/xfs_sb.h | 16 +++++++++++-
fs/xfs/xfs_super.c | 14 ++++++----
include/uapi/linux/dqblk_xfs.h | 1 +
8 files changed, 99 insertions(+), 40 deletions(-)
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
index 614eb0c..3bf05f4 100644
--- a/fs/xfs/xfs_fsops.c
+++ b/fs/xfs/xfs_fsops.c
@@ -501,7 +501,8 @@ xfs_growfs_data_private(
error, agno);
break;
}
- xfs_sb_to_disk(XFS_BUF_TO_SBP(bp), &mp->m_sb, XFS_SB_ALL_BITS);
+ xfs_sb_to_disk(XFS_BUF_TO_SBP(bp), &mp->m_sb,
+ xfs_sb_all_bits(&mp->m_sb));
/*
* If we get an error writing out the alternate superblocks,
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index e2e14cb..bb7b23e 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -336,12 +336,17 @@ xfs_mount_validate_sb(
return XFS_ERROR(EWRONGFS);
}
- if ((sbp->sb_qflags & (XFS_OQUOTA_ENFD | XFS_OQUOTA_CHKD)) &&
- (sbp->sb_qflags & (XFS_PQUOTA_ENFD | XFS_GQUOTA_ENFD |
- XFS_PQUOTA_CHKD | XFS_GQUOTA_CHKD))) {
- xfs_notice(mp,
-"Super block has XFS_OQUOTA bits along with XFS_PQUOTA and/or XFS_GQUOTA bits.\n");
- return XFS_ERROR(EFSCORRUPTED);
+ if (xfs_sb_version_has_pquota(sbp)) {
+ if (sbp->sb_qflags & (XFS_OQUOTA_ENFD | XFS_OQUOTA_CHKD)) {
+ xfs_notice(mp,
+ "Version 5 of Super block has XFS_OQUOTA bits.\n");
+ return XFS_ERROR(EFSCORRUPTED);
+ }
+ } else if (sbp->sb_qflags & (XFS_PQUOTA_ENFD | XFS_GQUOTA_ENFD |
+ XFS_PQUOTA_CHKD | XFS_GQUOTA_CHKD)) {
+ xfs_notice(mp,
+"Superblock earlier than Version 5 has XFS_[PQ]UOTA_{ENFD|CHKD} bits.\n");
+ return XFS_ERROR(EFSCORRUPTED);
}
/*
@@ -638,6 +643,13 @@ xfs_handle_quota_to_disk(
{
__uint16_t qflags = from->sb_qflags;
+ /*
+ * We need to do these manipilations only if we are working
+ * with an older version of on-disk superblock.
+ */
+ if (xfs_sb_version_has_pquota(from))
+ return;
+
if (*fields & XFS_SB_QFLAGS) {
/*
* The in-core version of sb_qflags do not have
@@ -657,6 +669,10 @@ xfs_handle_quota_to_disk(
to->sb_qflags = cpu_to_be16(qflags);
*fields &= ~XFS_SB_QFLAGS;
}
+ if (*fields & XFS_SB_PQUOTINO) {
+ to->sb_gquotino = cpu_to_be64(from->sb_pquotino);
+ *fields &= ~XFS_SB_PQUOTINO;
+ }
}
/*
@@ -873,13 +889,26 @@ reread:
*/
xfs_sb_from_disk(&mp->m_sb, XFS_BUF_TO_SBP(bp));
- if (sbp->sb_qflags & XFS_OQUOTA_ENFD)
- sbp->sb_qflags |= (sbp->sb_qflags & XFS_PQUOTA_ACCT) ?
+ if (!xfs_sb_version_has_pquota(&mp->m_sb)) {
+ if (XFS_IS_PQUOTA_ON(mp)) {
+ /*
+ * On disk superblock only has sb_gquotino, and incore
+ * superblock has both sb_gquotino and sb_pquotino.
+ * But, only one them is supported at any point of time.
+ * So, if PQUOTA is set in disk superblock, copy over
+ * sb_gquotino to sb_pquotino.
+ */
+ mp->m_sb.sb_pquotino = mp->m_sb.sb_gquotino;
+ mp->m_sb.sb_gquotino = NULLFSINO;
+ }
+ if (sbp->sb_qflags & XFS_OQUOTA_ENFD)
+ sbp->sb_qflags |= (sbp->sb_qflags & XFS_PQUOTA_ACCT) ?
XFS_PQUOTA_ENFD : XFS_GQUOTA_ENFD;
- if (sbp->sb_qflags & XFS_OQUOTA_CHKD)
- sbp->sb_qflags |= (sbp->sb_qflags & XFS_PQUOTA_ACCT) ?
+ if (sbp->sb_qflags & XFS_OQUOTA_CHKD)
+ sbp->sb_qflags |= (sbp->sb_qflags & XFS_PQUOTA_ACCT) ?
XFS_PQUOTA_CHKD : XFS_GQUOTA_CHKD;
- sbp->sb_qflags &= ~(XFS_OQUOTA_ENFD | XFS_OQUOTA_CHKD);
+ sbp->sb_qflags &= ~(XFS_OQUOTA_ENFD | XFS_OQUOTA_CHKD);
+ }
/*
* We must be able to do sector-sized and sector-aligned IO.
diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c
index b3e05ef..12abcf0 100644
--- a/fs/xfs/xfs_qm.c
+++ b/fs/xfs/xfs_qm.c
@@ -859,22 +859,21 @@ xfs_qm_qino_alloc(
spin_lock(&mp->m_sb_lock);
if (flags & XFS_QMOPT_SBVERSION) {
ASSERT(!xfs_sb_version_hasquota(&mp->m_sb));
- ASSERT((sbfields & (XFS_SB_VERSIONNUM | XFS_SB_UQUOTINO |
- XFS_SB_GQUOTINO | XFS_SB_QFLAGS)) ==
- (XFS_SB_VERSIONNUM | XFS_SB_UQUOTINO |
- XFS_SB_GQUOTINO | XFS_SB_QFLAGS));
xfs_sb_version_addquota(&mp->m_sb);
mp->m_sb.sb_uquotino = NULLFSINO;
mp->m_sb.sb_gquotino = NULLFSINO;
+ mp->m_sb.sb_pquotino = NULLFSINO;
/* qflags will get updated _after_ quotacheck */
mp->m_sb.sb_qflags = 0;
}
if (flags & XFS_QMOPT_UQUOTA)
mp->m_sb.sb_uquotino = (*ip)->i_ino;
- else
+ else if (flags & XFS_QMOPT_GQUOTA)
mp->m_sb.sb_gquotino = (*ip)->i_ino;
+ else
+ mp->m_sb.sb_pquotino = (*ip)->i_ino;
spin_unlock(&mp->m_sb_lock);
xfs_mod_sb(tp, sbfields);
@@ -1484,11 +1483,10 @@ xfs_qm_init_quotainos(
if (error)
goto error_rele;
}
- /* Use 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,
+ 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)
goto error_rele;
@@ -1497,6 +1495,8 @@ xfs_qm_init_quotainos(
flags |= XFS_QMOPT_SBVERSION;
sbflags |= (XFS_SB_VERSIONNUM | XFS_SB_UQUOTINO |
XFS_SB_GQUOTINO | XFS_SB_QFLAGS);
+ if (xfs_sb_version_has_pquota(&mp->m_sb))
+ sbflags |= XFS_SB_PQUOTINO;
}
/*
@@ -1524,8 +1524,10 @@ xfs_qm_init_quotainos(
flags &= ~XFS_QMOPT_SBVERSION;
}
if (XFS_IS_PQUOTA_ON(mp) && pip == NULL) {
+ if (!xfs_sb_version_has_pquota(&mp->m_sb))
+ sbflags &= ~XFS_SB_GQUOTINO;
error = xfs_qm_qino_alloc(mp, &pip,
- sbflags | XFS_SB_GQUOTINO,
+ sbflags | XFS_SB_PQUOTINO,
flags | XFS_QMOPT_PQUOTA);
if (error)
goto error_rele;
diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c
index ed7cd55..d664a2d 100644
--- a/fs/xfs/xfs_qm_syscalls.c
+++ b/fs/xfs/xfs_qm_syscalls.c
@@ -201,8 +201,7 @@ xfs_qm_scall_quotaoff(
/*
* If quotas is completely disabled, close shop.
*/
- if (((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_SET1) ||
- ((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_SET2)) {
+ if ((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_ALL) {
mutex_unlock(&q->qi_quotaofflock);
xfs_qm_destroy_quotainfo(mp);
return (0);
@@ -297,8 +296,10 @@ xfs_qm_scall_trunc_qfiles(
if (flags & XFS_DQ_USER)
error = xfs_qm_scall_trunc_qfile(mp, mp->m_sb.sb_uquotino);
- if (flags & (XFS_DQ_GROUP|XFS_DQ_PROJ))
+ if (flags & XFS_DQ_GROUP)
error2 = xfs_qm_scall_trunc_qfile(mp, mp->m_sb.sb_gquotino);
+ if (flags & XFS_DQ_PROJ)
+ error2 = xfs_qm_scall_trunc_qfile(mp, mp->m_sb.sb_pquotino);
return error ? error : error2;
}
@@ -414,8 +415,10 @@ xfs_qm_scall_getqstat(
struct xfs_quotainfo *q = mp->m_quotainfo;
struct xfs_inode *uip = NULL;
struct xfs_inode *gip = NULL;
+ struct xfs_inode *pip = NULL;
bool tempuqip = false;
bool tempgqip = false;
+ bool temppqip = false;
memset(out, 0, sizeof(fs_quota_stat_t));
@@ -423,6 +426,7 @@ xfs_qm_scall_getqstat(
if (!xfs_sb_version_hasquota(&mp->m_sb)) {
out->qs_uquota.qfs_ino = NULLFSINO;
out->qs_gquota.qfs_ino = NULLFSINO;
+ out->qs_pquota.qfs_ino = NULLFSINO;
return (0);
}
out->qs_flags = (__uint16_t) xfs_qm_export_flags(mp->m_qflags &
@@ -431,10 +435,13 @@ xfs_qm_scall_getqstat(
out->qs_pad = 0;
out->qs_uquota.qfs_ino = mp->m_sb.sb_uquotino;
out->qs_gquota.qfs_ino = mp->m_sb.sb_gquotino;
+ if (&out->qs_gquota != &out->qs_pquota)
+ out->qs_pquota.qfs_ino = mp->m_sb.sb_pquotino;
if (q) {
uip = q->qi_uquotaip;
gip = q->qi_gquotaip;
+ pip = q->qi_pquotaip;
}
if (!uip && mp->m_sb.sb_uquotino != NULLFSINO) {
if (xfs_iget(mp, NULL, mp->m_sb.sb_uquotino,
@@ -446,6 +453,11 @@ xfs_qm_scall_getqstat(
0, 0, &gip) == 0)
tempgqip = true;
}
+ if (!pip && mp->m_sb.sb_pquotino != NULLFSINO) {
+ if (xfs_iget(mp, NULL, mp->m_sb.sb_pquotino,
+ 0, 0, &pip) == 0)
+ temppqip = true;
+ }
if (uip) {
out->qs_uquota.qfs_nblks = uip->i_d.di_nblocks;
out->qs_uquota.qfs_nextents = uip->i_d.di_nextents;
@@ -458,6 +470,12 @@ xfs_qm_scall_getqstat(
if (tempgqip)
IRELE(gip);
}
+ if (pip) {
+ out->qs_pquota.qfs_nblks = pip->i_d.di_nblocks;
+ out->qs_pquota.qfs_nextents = pip->i_d.di_nextents;
+ if (temppqip)
+ IRELE(pip);
+ }
if (q) {
out->qs_incoredqs = q->qi_dquots;
out->qs_btimelimit = q->qi_btimelimit;
diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h
index d7668f9..e59725c 100644
--- a/fs/xfs/xfs_quota.h
+++ b/fs/xfs/xfs_quota.h
@@ -287,14 +287,6 @@ typedef struct xfs_qoff_logformat {
(XFS_IS_PQUOTA_ON(mp) && \
(mp->m_sb.sb_qflags & XFS_PQUOTA_CHKD) == 0))
-#define XFS_MOUNT_QUOTA_SET1 (XFS_UQUOTA_ACCT|XFS_UQUOTA_ENFD|\
- XFS_UQUOTA_CHKD|XFS_PQUOTA_ACCT|\
- XFS_PQUOTA_ENFD|XFS_PQUOTA_CHKD)
-
-#define XFS_MOUNT_QUOTA_SET2 (XFS_UQUOTA_ACCT|XFS_UQUOTA_ENFD|\
- XFS_UQUOTA_CHKD|XFS_GQUOTA_ACCT|\
- XFS_GQUOTA_ENFD|XFS_GQUOTA_CHKD)
-
#define XFS_MOUNT_QUOTA_ALL (XFS_UQUOTA_ACCT|XFS_UQUOTA_ENFD|\
XFS_UQUOTA_CHKD|XFS_PQUOTA_ACCT|\
XFS_PQUOTA_ENFD|XFS_PQUOTA_CHKD|\
diff --git a/fs/xfs/xfs_sb.h b/fs/xfs/xfs_sb.h
index 78f9e70..d1d2407 100644
--- a/fs/xfs/xfs_sb.h
+++ b/fs/xfs/xfs_sb.h
@@ -621,7 +621,21 @@ xfs_sb_has_incompat_log_feature(
static inline bool
xfs_is_quota_inode(struct xfs_sb *sbp, xfs_ino_t ino)
{
- return (ino == sbp->sb_uquotino || ino == sbp->sb_gquotino);
+ return (ino == sbp->sb_uquotino ||
+ ino == sbp->sb_gquotino ||
+ ino == sbp->sb_pquotino);
+}
+
+static inline int xfs_sb_version_has_pquota(xfs_sb_t *sbp)
+{
+ return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5;
+}
+
+static inline __int64_t xfs_sb_all_bits(xfs_sb_t *sbp)
+{
+ if (xfs_sb_version_has_pquota(sbp))
+ return XFS_SB_ALL_BITS;
+ return XFS_SB_ALL_BITS & ~XFS_SB_PQUOTINO;
}
/*
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
index 2a76ba2..1bcc017 100644
--- a/fs/xfs/xfs_super.c
+++ b/fs/xfs/xfs_super.c
@@ -420,12 +420,6 @@ xfs_parseargs(
}
#endif
- if ((mp->m_qflags & (XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE)) &&
- (mp->m_qflags & (XFS_PQUOTA_ACCT | XFS_PQUOTA_ACTIVE))) {
- xfs_warn(mp, "cannot mount with both project and group quota");
- return EINVAL;
- }
-
if ((dsunit && !dswidth) || (!dsunit && dswidth)) {
xfs_warn(mp, "sunit and swidth must be specified together");
return EINVAL;
@@ -1400,6 +1394,14 @@ xfs_finish_flags(
return XFS_ERROR(EROFS);
}
+ if ((mp->m_qflags & (XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE)) &&
+ (mp->m_qflags & (XFS_PQUOTA_ACCT | XFS_PQUOTA_ACTIVE)) &&
+ !xfs_sb_version_has_pquota(&mp->m_sb)) {
+ xfs_warn(mp,
+ "Super block does not support project and group quota together");
+ return XFS_ERROR(EINVAL);
+ }
+
return 0;
}
diff --git a/include/uapi/linux/dqblk_xfs.h b/include/uapi/linux/dqblk_xfs.h
index 8655280..f17e3bb 100644
--- a/include/uapi/linux/dqblk_xfs.h
+++ b/include/uapi/linux/dqblk_xfs.h
@@ -155,6 +155,7 @@ typedef struct fs_quota_stat {
__s8 qs_pad; /* unused */
fs_qfilestat_t qs_uquota; /* user quota storage information */
fs_qfilestat_t qs_gquota; /* group quota storage information */
+#define qs_pquota qs_gquota
__u32 qs_incoredqs; /* number of dquots incore */
__s32 qs_btimelimit; /* limit for blks timer */
__s32 qs_itimelimit; /* limit for inodes timer */
--
1.7.1
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v9 5/6] xfs: Add proper versioning support to fs_quota_stat
2013-06-24 2:48 [PATCH v9 0/6] Allow pquota and gquota to be used together Chandra Seetharaman
` (3 preceding siblings ...)
2013-06-24 2:48 ` [PATCH v9 4/6] xfs: Start using pquotaino from the superblock Chandra Seetharaman
@ 2013-06-24 2:48 ` Chandra Seetharaman
2013-06-25 6:43 ` Dave Chinner
2013-06-24 2:48 ` [PATCH v9 6/6] xfs: Use new qs_pquota field in fs_quota_stat for Q_XGETQSTAT Chandra Seetharaman
5 siblings, 1 reply; 28+ messages in thread
From: Chandra Seetharaman @ 2013-06-24 2:48 UTC (permalink / raw)
To: xfs; +Cc: Chandra Seetharaman
Added appropriate pads and code for backward compatibility.
Copied over the old version as it is different from the newer padded
version.
New callers of the system call have to set the version of the data
structure being passed, and kernel will fill as much data as requested.
Signed-off-by: Chandra Seetharaman <sekharan@us.ibm.com>
---
fs/gfs2/quota.c | 3 --
fs/quota/quota.c | 49 +++++++++++++++++++++++++++++++++-
fs/xfs/xfs_qm_syscalls.c | 4 ---
fs/xfs/xfs_super.c | 5 +--
include/uapi/linux/dqblk_xfs.h | 57 +++++++++++++++++++++++++++++++++++-----
5 files changed, 99 insertions(+), 19 deletions(-)
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c
index c7c840e..ca0dccd 100644
--- a/fs/gfs2/quota.c
+++ b/fs/gfs2/quota.c
@@ -1443,9 +1443,6 @@ static int gfs2_quota_get_xstate(struct super_block *sb,
{
struct gfs2_sbd *sdp = sb->s_fs_info;
- memset(fqs, 0, sizeof(struct fs_quota_stat));
- fqs->qs_version = FS_QSTAT_VERSION;
-
switch (sdp->sd_args.ar_quota) {
case GFS2_QUOTA_ON:
fqs->qs_flags |= (FS_QUOTA_UDQ_ENFD | FS_QUOTA_GDQ_ENFD);
diff --git a/fs/quota/quota.c b/fs/quota/quota.c
index c7314f1..ae6526e 100644
--- a/fs/quota/quota.c
+++ b/fs/quota/quota.c
@@ -207,12 +207,57 @@ static int quota_setxstate(struct super_block *sb, int cmd, void __user *addr)
static int quota_getxstate(struct super_block *sb, void __user *addr)
{
struct fs_quota_stat fqs;
- int ret;
+ struct fs_quota_stat_v1 fqs_v1;
+ int ret, size;
+ void *fqsp;
if (!sb->s_qcop->get_xstate)
return -ENOSYS;
+
+ memset(&fqs, 0, sizeof(struct fs_quota_stat));
+ if (copy_from_user(&fqs, addr, 1)) /* just get the version */
+ return -EFAULT;
+
+ switch (fqs.qs_version) {
+ case FS_QSTAT_VERSION_2:
+ size = FS_QSTAT_V2_SIZE;
+ break;
+ default:
+ fqs.qs_version = FS_QSTAT_VERSION;
+ /* fallthrough */
+ case FS_QSTAT_VERSION:
+ size = FS_QSTAT_V1_SIZE;
+ break;
+ }
+
ret = sb->s_qcop->get_xstate(sb, &fqs);
- if (!ret && copy_to_user(addr, &fqs, sizeof(fqs)))
+ if (ret)
+ return ret;
+
+ if (fqs.qs_version == FS_QSTAT_VERSION) {
+ fqs_v1.qs_version = fqs.qs_version;
+ fqs_v1.qs_flags = fqs.qs_flags;
+ fqs_v1.qs_pad = 0;
+
+ fqs_v1.qs_uquota.qfs_ino = fqs.qs_uquota.qfs_ino;
+ fqs_v1.qs_uquota.qfs_nblks = fqs.qs_uquota.qfs_nblks;
+ fqs_v1.qs_uquota.qfs_nextents = fqs.qs_uquota.qfs_nextents;
+
+ fqs_v1.qs_gquota.qfs_ino = fqs.qs_gquota.qfs_ino;
+ fqs_v1.qs_gquota.qfs_nblks = fqs.qs_gquota.qfs_nblks;
+ fqs_v1.qs_gquota.qfs_nextents = fqs.qs_gquota.qfs_nextents;
+
+ fqs_v1.qs_incoredqs = fqs.qs_incoredqs;
+ fqs_v1.qs_btimelimit = fqs.qs_btimelimit;
+ fqs_v1.qs_itimelimit = fqs.qs_itimelimit;
+ fqs_v1.qs_rtbtimelimit = fqs.qs_rtbtimelimit;
+ fqs_v1.qs_bwarnlimit = fqs.qs_bwarnlimit;
+ fqs_v1.qs_iwarnlimit = fqs.qs_iwarnlimit;
+ fqsp = &fqs_v1;
+ } else
+ fqsp = &fqs;
+
+ if (copy_to_user(addr, fqsp, size))
return -EFAULT;
return ret;
}
diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c
index d664a2d..1918f48 100644
--- a/fs/xfs/xfs_qm_syscalls.c
+++ b/fs/xfs/xfs_qm_syscalls.c
@@ -420,9 +420,6 @@ xfs_qm_scall_getqstat(
bool tempgqip = false;
bool temppqip = false;
- memset(out, 0, sizeof(fs_quota_stat_t));
-
- out->qs_version = FS_QSTAT_VERSION;
if (!xfs_sb_version_hasquota(&mp->m_sb)) {
out->qs_uquota.qfs_ino = NULLFSINO;
out->qs_gquota.qfs_ino = NULLFSINO;
@@ -432,7 +429,6 @@ xfs_qm_scall_getqstat(
out->qs_flags = (__uint16_t) xfs_qm_export_flags(mp->m_qflags &
(XFS_ALL_QUOTA_ACCT|
XFS_ALL_QUOTA_ENFD));
- out->qs_pad = 0;
out->qs_uquota.qfs_ino = mp->m_sb.sb_uquotino;
out->qs_gquota.qfs_ino = mp->m_sb.sb_gquotino;
if (&out->qs_gquota != &out->qs_pquota)
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
index 1bcc017..ab90539 100644
--- a/fs/xfs/xfs_super.c
+++ b/fs/xfs/xfs_super.c
@@ -554,14 +554,13 @@ xfs_showargs(
else if (mp->m_qflags & XFS_UQUOTA_ACCT)
seq_puts(m, "," MNTOPT_UQUOTANOENF);
- /* Either project or group quotas can be active, not both */
-
if (mp->m_qflags & XFS_PQUOTA_ACCT) {
if (mp->m_qflags & XFS_PQUOTA_ENFD)
seq_puts(m, "," MNTOPT_PRJQUOTA);
else
seq_puts(m, "," MNTOPT_PQUOTANOENF);
- } else if (mp->m_qflags & XFS_GQUOTA_ACCT) {
+ }
+ if (mp->m_qflags & XFS_GQUOTA_ACCT) {
if (mp->m_qflags & XFS_GQUOTA_ENFD)
seq_puts(m, "," MNTOPT_GRPQUOTA);
else
diff --git a/include/uapi/linux/dqblk_xfs.h b/include/uapi/linux/dqblk_xfs.h
index f17e3bb..e8ca23b 100644
--- a/include/uapi/linux/dqblk_xfs.h
+++ b/include/uapi/linux/dqblk_xfs.h
@@ -47,6 +47,7 @@
* 512 bytes.
*/
#define FS_DQUOT_VERSION 1 /* fs_disk_quota.d_version */
+
typedef struct fs_disk_quota {
__s8 d_version; /* version of this structure */
__s8 d_flags; /* FS_{USER,PROJ,GROUP}_QUOTA */
@@ -137,31 +138,73 @@ typedef struct fs_disk_quota {
* Provides a centralized way to get meta information about the quota subsystem.
* eg. space taken up for user and group quotas, number of dquots currently
* incore.
+ * User space caller should set qs_version to the appropriate version
+ * of the fs_quota_stat data structure they are providing. Not providing
+ * a version will be treated as FS_QSTAT_VERSION.
*/
#define FS_QSTAT_VERSION 1 /* fs_quota_stat.qs_version */
+#define FS_QSTAT_VERSION_2 2 /* new field qs_pquota; realignment */
/*
* Some basic information about 'quota files'.
*/
-typedef struct fs_qfilestat {
+struct fs_qfilestat_v1 {
__u64 qfs_ino; /* inode number */
__u64 qfs_nblks; /* number of BBs 512-byte-blks */
__u32 qfs_nextents; /* number of extents */
-} fs_qfilestat_t;
+};
-typedef struct fs_quota_stat {
+struct fs_quota_stat_v1 {
__s8 qs_version; /* version number for future changes */
__u16 qs_flags; /* FS_QUOTA_{U,P,G}DQ_{ACCT,ENFD} */
__s8 qs_pad; /* unused */
- fs_qfilestat_t qs_uquota; /* user quota storage information */
- fs_qfilestat_t qs_gquota; /* group quota storage information */
-#define qs_pquota qs_gquota
+ struct fs_qfilestat_v1 qs_uquota; /* user quota information */
+ struct fs_qfilestat_v1 qs_gquota; /* group quota information */
__u32 qs_incoredqs; /* number of dquots incore */
__s32 qs_btimelimit; /* limit for blks timer */
__s32 qs_itimelimit; /* limit for inodes timer */
__s32 qs_rtbtimelimit;/* limit for rt blks timer */
__u16 qs_bwarnlimit; /* limit for num warnings */
__u16 qs_iwarnlimit; /* limit for num warnings */
-} fs_quota_stat_t;
+};
+
+/*
+ * Some basic information about 'quota files'. Version 2.
+ */
+struct fs_qfilestat {
+ __u64 qfs_ino; /* inode number */
+ __u64 qfs_nblks; /* number of BBs 512-byte-blks */
+ __u32 qfs_nextents; /* number of extents */
+ __u8 qfs_pad[4]; /* pad for 8-byte alignment */
+};
+
+struct fs_quota_stat {
+ __s8 qs_version; /* version for future changes */
+ __u8 qs_pad1; /* pad for 16bit alignment */
+ __u16 qs_flags; /* FS_QUOTA_.* flags */
+ __u8 qs_pad2[4]; /* pad for 8-byte alignment */
+ struct fs_qfilestat qs_uquota; /* user quota information */
+ struct fs_qfilestat qs_gquota; /* group quota information */
+ struct fs_qfilestat qs_pquota; /* project quota information */
+ __u32 qs_incoredqs; /* number of dquots incore */
+ __s32 qs_btimelimit; /* limit for blks timer */
+ __s32 qs_itimelimit; /* limit for inodes timer */
+ __s32 qs_rtbtimelimit;/* limit for rt blks timer */
+ __u16 qs_bwarnlimit; /* limit for num warnings */
+ __u16 qs_iwarnlimit; /* limit for num warnings */
+ __u8 qs_pad3[4]; /* pad for 8-byte alignment */
+ __u8 qs_pad4[64]; /* for future proofing */
+};
+
+/*
+ * Since Version 1 did not have padding at appropriate places,
+ * a new data structure has been defined for the older version to
+ * provide backward compatibility.
+ * Future extentions of this data structure won't require new
+ * data structure definitions as the current one can be extended
+ * with the logic and padding in place now.
+ */
+#define FS_QSTAT_V1_SIZE (sizeof(struct fs_quota_stat_v1))
+#define FS_QSTAT_V2_SIZE (sizeof(struct fs_quota_stat))
#endif /* _LINUX_DQBLK_XFS_H */
--
1.7.1
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply related [flat|nested] 28+ messages in thread
* [PATCH v9 6/6] xfs: Use new qs_pquota field in fs_quota_stat for Q_XGETQSTAT
2013-06-24 2:48 [PATCH v9 0/6] Allow pquota and gquota to be used together Chandra Seetharaman
` (4 preceding siblings ...)
2013-06-24 2:48 ` [PATCH v9 5/6] xfs: Add proper versioning support to fs_quota_stat Chandra Seetharaman
@ 2013-06-24 2:48 ` Chandra Seetharaman
2013-06-25 6:45 ` Dave Chinner
5 siblings, 1 reply; 28+ messages in thread
From: Chandra Seetharaman @ 2013-06-24 2:48 UTC (permalink / raw)
To: xfs; +Cc: Chandra Seetharaman
For the Q_XGETQSTAT quota command, if the new version of fs_quota_stat
data structure is used, fill the project quota information.
Signed-off-by: Chandra Seetharaman <sekharan@us.ibm.com>
---
fs/xfs/xfs_qm_syscalls.c | 38 ++++++++++++++++++++++++++------------
1 files changed, 26 insertions(+), 12 deletions(-)
diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c
index 1918f48..8711f37 100644
--- a/fs/xfs/xfs_qm_syscalls.c
+++ b/fs/xfs/xfs_qm_syscalls.c
@@ -406,6 +406,14 @@ xfs_qm_scall_quotaon(
/*
* Return quota status information, such as uquota-off, enforcements, etc.
+ *
+ * We support two different versions of the fs_quota_stat structure
+ * here. If the version is FS_QSTAT_VERSION, then there is no
+ * separate project quota fields, and so we write project quota
+ * information into the group quota fields. With FS_QSTAT_VERSION_2,
+ * there is a separate project quota field so we can use that
+ * instead to pass both group and project quota back to user space.
+ *
*/
int
xfs_qm_scall_getqstat(
@@ -420,19 +428,15 @@ xfs_qm_scall_getqstat(
bool tempgqip = false;
bool temppqip = false;
- if (!xfs_sb_version_hasquota(&mp->m_sb)) {
- out->qs_uquota.qfs_ino = NULLFSINO;
- out->qs_gquota.qfs_ino = NULLFSINO;
- out->qs_pquota.qfs_ino = NULLFSINO;
- return (0);
- }
+ out->qs_uquota.qfs_ino = NULLFSINO;
+ out->qs_gquota.qfs_ino = NULLFSINO;
+ out->qs_pquota.qfs_ino = NULLFSINO;
+ if (!xfs_sb_version_hasquota(&mp->m_sb))
+ return 0;
+
out->qs_flags = (__uint16_t) xfs_qm_export_flags(mp->m_qflags &
(XFS_ALL_QUOTA_ACCT|
XFS_ALL_QUOTA_ENFD));
- out->qs_uquota.qfs_ino = mp->m_sb.sb_uquotino;
- out->qs_gquota.qfs_ino = mp->m_sb.sb_gquotino;
- if (&out->qs_gquota != &out->qs_pquota)
- out->qs_pquota.qfs_ino = mp->m_sb.sb_pquotino;
if (q) {
uip = q->qi_uquotaip;
@@ -454,21 +458,31 @@ xfs_qm_scall_getqstat(
0, 0, &pip) == 0)
temppqip = true;
}
+
if (uip) {
+ out->qs_uquota.qfs_ino = mp->m_sb.sb_uquotino;
out->qs_uquota.qfs_nblks = uip->i_d.di_nblocks;
out->qs_uquota.qfs_nextents = uip->i_d.di_nextents;
if (tempuqip)
IRELE(uip);
}
if (gip) {
+ out->qs_gquota.qfs_ino = mp->m_sb.sb_gquotino;
out->qs_gquota.qfs_nblks = gip->i_d.di_nblocks;
out->qs_gquota.qfs_nextents = gip->i_d.di_nextents;
if (tempgqip)
IRELE(gip);
}
if (pip) {
- out->qs_pquota.qfs_nblks = pip->i_d.di_nblocks;
- out->qs_pquota.qfs_nextents = pip->i_d.di_nextents;
+ if (out->qs_version >= FS_QSTAT_VERSION_2) {
+ out->qs_pquota.qfs_ino = mp->m_sb.sb_pquotino;
+ out->qs_pquota.qfs_nblks = pip->i_d.di_nblocks;
+ out->qs_pquota.qfs_nextents = pip->i_d.di_nextents;
+ } else {
+ out->qs_gquota.qfs_ino = mp->m_sb.sb_pquotino;
+ out->qs_gquota.qfs_nblks = pip->i_d.di_nblocks;
+ out->qs_gquota.qfs_nextents = pip->i_d.di_nextents;
+ }
if (temppqip)
IRELE(pip);
}
--
1.7.1
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply related [flat|nested] 28+ messages in thread
* Re: [PATCH v9 1/6] xfs: Move code around and remove typedefs
2013-06-24 2:48 ` [PATCH v9 1/6] xfs: Move code around and remove typedefs Chandra Seetharaman
@ 2013-06-24 5:31 ` Dave Chinner
2013-06-24 22:21 ` Chandra Seetharaman
2013-06-24 21:36 ` Ben Myers
1 sibling, 1 reply; 28+ messages in thread
From: Dave Chinner @ 2013-06-24 5:31 UTC (permalink / raw)
To: Chandra Seetharaman; +Cc: xfs
On Sun, Jun 23, 2013 at 09:48:22PM -0500, Chandra Seetharaman wrote:
> Removed some typedefs, defined new functions, made some code clean up all in
> preparation of the series.
>
> No functional changes.
This does a lot of different stuff. Can you separate out the actual
factoring changes (e.g. xfs_is_quota_inode() and xfs_dquot_tree())
into separate patches, and the same with the struct xfs_dquot_acct
as it changes both logic and structure...
> diff --git a/fs/xfs/xfs_qm.h b/fs/xfs/xfs_qm.h
> index 5d16a6e..4b330f2 100644
> --- a/fs/xfs/xfs_qm.h
> +++ b/fs/xfs/xfs_qm.h
> @@ -42,57 +42,89 @@ extern struct kmem_zone *xfs_qm_dqtrxzone;
> * The mount structure keeps a pointer to this.
> */
> typedef struct xfs_quotainfo {
> - struct radix_tree_root qi_uquota_tree;
> - struct radix_tree_root qi_gquota_tree;
> - struct mutex qi_tree_lock;
> - xfs_inode_t *qi_uquotaip; /* user quota inode */
> - xfs_inode_t *qi_gquotaip; /* group quota inode */
> - struct list_head qi_lru_list;
> - struct mutex qi_lru_lock;
> - int qi_lru_count;
> - int qi_dquots;
> - time_t qi_btimelimit; /* limit for blks timer */
> - time_t qi_itimelimit; /* limit for inodes timer */
> - time_t qi_rtbtimelimit;/* limit for rt blks timer */
> - xfs_qwarncnt_t qi_bwarnlimit; /* limit for blks warnings */
> - xfs_qwarncnt_t qi_iwarnlimit; /* limit for inodes warnings */
> - xfs_qwarncnt_t qi_rtbwarnlimit;/* limit for rt blks warnings */
> - struct mutex qi_quotaofflock;/* to serialize quotaoff */
> - xfs_filblks_t qi_dqchunklen; /* # BBs in a chunk of dqs */
> - uint qi_dqperchunk; /* # ondisk dqs in above chunk */
> - xfs_qcnt_t qi_bhardlimit; /* default data blk hard limit */
> - xfs_qcnt_t qi_bsoftlimit; /* default data blk soft limit */
> - xfs_qcnt_t qi_ihardlimit; /* default inode count hard limit */
> - xfs_qcnt_t qi_isoftlimit; /* default inode count soft limit */
> - xfs_qcnt_t qi_rtbhardlimit;/* default realtime blk hard limit */
> - xfs_qcnt_t qi_rtbsoftlimit;/* default realtime blk soft limit */
> - struct shrinker qi_shrinker;
> + struct radix_tree_root qi_uquota_tree;
> + struct radix_tree_root qi_gquota_tree;
> + struct mutex qi_tree_lock;
> + struct xfs_inode *qi_uquotaip; /* user quota inode */
> + struct xfs_inode *qi_gquotaip; /* group quota inode */
> + struct list_head qi_lru_list;
> + struct mutex qi_lru_lock;
> + int qi_lru_count;
> + int qi_dquots;
> + time_t qi_btimelimit; /* limit for blks timer */
> + time_t qi_itimelimit; /* limit for inodes timer */
> + time_t qi_rtbtimelimit;/* limit for rt blks timer */
> + xfs_qwarncnt_t qi_bwarnlimit; /* limit for blks warnings */
> + xfs_qwarncnt_t qi_iwarnlimit; /* limit for inodes warnings */
> + xfs_qwarncnt_t qi_rtbwarnlimit;/* limit for rt blks warnings */
> + struct mutex qi_quotaofflock;/* to serialize quotaoff */
> + xfs_filblks_t qi_dqchunklen; /* # BBs in a chunk of dqs */
> + uint qi_dqperchunk; /* # ondisk dqs in above chunk */
> + xfs_qcnt_t qi_bhardlimit; /* default data blk hard limit */
> + xfs_qcnt_t qi_bsoftlimit; /* default data blk soft limit */
> + xfs_qcnt_t qi_ihardlimit; /* default inode count hard limit */
> + xfs_qcnt_t qi_isoftlimit; /* default inode count soft limit */
> + xfs_qcnt_t qi_rtbhardlimit;/* default realtime blk hard limit */
> + xfs_qcnt_t qi_rtbsoftlimit;/* default realtime blk soft limit */
> + struct shrinker qi_shrinker;
> } xfs_quotainfo_t;
I don't see much point in random whitespace cleanups like this. If
you are going to change them, at least clean it up properly, so all
variables are aligned, and all the comments are aligned as well. In
most cases, the comments are redundant because the variable names
are very descriptive and so probably could be removed....
Cheers,
Dave.
--
Dave Chinner
david@fromorbit.com
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH v9 2/6] xfs: Remove incore use of XFS_OQUOTA_ENFD and XFS_OQUOTA_CHKD
2013-06-24 2:48 ` [PATCH v9 2/6] xfs: Remove incore use of XFS_OQUOTA_ENFD and XFS_OQUOTA_CHKD Chandra Seetharaman
@ 2013-06-24 5:59 ` Dave Chinner
2013-06-24 22:25 ` Chandra Seetharaman
0 siblings, 1 reply; 28+ messages in thread
From: Dave Chinner @ 2013-06-24 5:59 UTC (permalink / raw)
To: Chandra Seetharaman; +Cc: xfs
On Sun, Jun 23, 2013 at 09:48:23PM -0500, Chandra Seetharaman wrote:
> Remove all incore use of XFS_OQUOTA_ENFD and XFS_OQUOTA_CHKD. Instead,
> start using XFS_GQUOTA_.* XFS_PQUOTA_.* counterparts for GQUOTA and
> PQUOTA respectively.
>
> On-disk copy still uses XFS_OQUOTA_ENFD and XFS_OQUOTA_CHKD.
>
> Read and write of the superblock does the conversion from *OQUOTA*
> to *[PG]QUOTA*.
>
> Signed-off-by: Chandra Seetharaman <sekharan@us.ibm.com>
> ---
> fs/xfs/xfs_mount.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
> fs/xfs/xfs_qm.c | 9 ++++++---
> fs/xfs/xfs_qm_syscalls.c | 39 +++++++++++++++++++++------------------
> fs/xfs/xfs_quota.h | 42 ++++++++++++++++++++++++++++--------------
> fs/xfs/xfs_quotaops.c | 6 ++++--
> fs/xfs/xfs_super.c | 16 ++++++++--------
> fs/xfs/xfs_trans_dquot.c | 4 ++--
> 7 files changed, 115 insertions(+), 47 deletions(-)
>
> diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
> index 6a19434..e2e14cb 100644
> --- a/fs/xfs/xfs_mount.c
> +++ b/fs/xfs/xfs_mount.c
> @@ -336,6 +336,14 @@ xfs_mount_validate_sb(
> return XFS_ERROR(EWRONGFS);
> }
>
> + if ((sbp->sb_qflags & (XFS_OQUOTA_ENFD | XFS_OQUOTA_CHKD)) &&
> + (sbp->sb_qflags & (XFS_PQUOTA_ENFD | XFS_GQUOTA_ENFD |
> + XFS_PQUOTA_CHKD | XFS_GQUOTA_CHKD))) {
> + xfs_notice(mp,
> +"Super block has XFS_OQUOTA bits along with XFS_PQUOTA and/or XFS_GQUOTA bits.\n");
> + return XFS_ERROR(EFSCORRUPTED);
> + }
> +
> /*
> * Version 5 superblock feature mask validation. Reject combinations the
> * kernel cannot support up front before checking anything else. For
> @@ -622,6 +630,35 @@ xfs_sb_from_disk(
> to->sb_lsn = be64_to_cpu(from->sb_lsn);
> }
>
> +static inline void
> +xfs_handle_quota_to_disk(
> + xfs_dsb_t *to,
> + xfs_sb_t *from,
> + __int64_t *fields)
An "XFS handle" has meaning in the namespace (i.e. an XFS filehandle
as used in xfs_ioctl.c and defined in xfs_fs.h, so this is not a
good name.
Realistically, xfs_sb_qflags_to_disk() is more appropriate for it's
function....
> @@ -643,6 +680,7 @@ xfs_sb_to_disk(
> if (!fields)
> return;
>
> + xfs_handle_quota_to_disk(to, from, &fields);
> while (fields) {
> f = (xfs_sb_field_t)xfs_lowbit64((__uint64_t)fields);
> first = xfs_sb_info[f].offset;
> @@ -835,6 +873,14 @@ reread:
> */
> xfs_sb_from_disk(&mp->m_sb, XFS_BUF_TO_SBP(bp));
>
> + if (sbp->sb_qflags & XFS_OQUOTA_ENFD)
> + sbp->sb_qflags |= (sbp->sb_qflags & XFS_PQUOTA_ACCT) ?
> + XFS_PQUOTA_ENFD : XFS_GQUOTA_ENFD;
> + if (sbp->sb_qflags & XFS_OQUOTA_CHKD)
> + sbp->sb_qflags |= (sbp->sb_qflags & XFS_PQUOTA_ACCT) ?
> + XFS_PQUOTA_CHKD : XFS_GQUOTA_CHKD;
> + sbp->sb_qflags &= ~(XFS_OQUOTA_ENFD | XFS_OQUOTA_CHKD);
and that as xfs_sb_qflags_from_disk()....
> +
> /*
> * We must be able to do sector-sized and sector-aligned IO.
> */
> diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c
> index f5f9925..de7ecbd 100644
> --- a/fs/xfs/xfs_qm.c
> +++ b/fs/xfs/xfs_qm.c
> @@ -299,8 +299,10 @@ xfs_qm_mount_quotas(
> */
> if (!XFS_IS_UQUOTA_ON(mp))
> mp->m_qflags &= ~XFS_UQUOTA_CHKD;
> - if (!(XFS_IS_GQUOTA_ON(mp) || XFS_IS_PQUOTA_ON(mp)))
> - mp->m_qflags &= ~XFS_OQUOTA_CHKD;
> + if (!XFS_IS_GQUOTA_ON(mp))
> + mp->m_qflags &= ~XFS_GQUOTA_CHKD;
> + if (!XFS_IS_PQUOTA_ON(mp))
> + mp->m_qflags &= ~XFS_PQUOTA_CHKD;
Order is user, group, project in the processing....
> diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c
> index b03b2ab..5e51227 100644
> --- a/fs/xfs/xfs_qm_syscalls.c
> +++ b/fs/xfs/xfs_qm_syscalls.c
> @@ -117,11 +117,11 @@ xfs_qm_scall_quotaoff(
> }
> if (flags & XFS_GQUOTA_ACCT) {
> dqtype |= XFS_QMOPT_GQUOTA;
> - flags |= (XFS_OQUOTA_CHKD | XFS_OQUOTA_ENFD);
> + flags |= (XFS_GQUOTA_CHKD | XFS_GQUOTA_ENFD);
> inactivate_flags |= XFS_GQUOTA_ACTIVE;
> } else if (flags & XFS_PQUOTA_ACCT) {
> dqtype |= XFS_QMOPT_PQUOTA;
> - flags |= (XFS_OQUOTA_CHKD | XFS_OQUOTA_ENFD);
> + flags |= (XFS_PQUOTA_CHKD | XFS_PQUOTA_ENFD);
> inactivate_flags |= XFS_PQUOTA_ACTIVE;
> }
Again, u/g/p order...
>
> @@ -335,14 +335,14 @@ xfs_qm_scall_quotaon(
> * quota acct on ondisk without m_qflags' knowing.
> */
> if (((flags & XFS_UQUOTA_ACCT) == 0 &&
> - (mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT) == 0 &&
> - (flags & XFS_UQUOTA_ENFD))
> - ||
> + (mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT) == 0 &&
> + (flags & XFS_UQUOTA_ENFD)) ||
> ((flags & XFS_PQUOTA_ACCT) == 0 &&
> - (mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT) == 0 &&
> - (flags & XFS_GQUOTA_ACCT) == 0 &&
> - (mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) == 0 &&
> - (flags & XFS_OQUOTA_ENFD))) {
> + (mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT) == 0 &&
> + (flags & XFS_PQUOTA_ENFD)) ||
> + ((flags & XFS_GQUOTA_ACCT) == 0 &&
> + (mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) == 0 &&
> + (flags & XFS_GQUOTA_ENFD))) {
> xfs_debug(mp,
> "%s: Can't enforce without acct, flags=%x sbflags=%x\n",
> __func__, flags, mp->m_sb.sb_qflags);
And now u/p/g order. That's a little confusing - let's try to keep
the ordering the same throughout the code...
> @@ -776,9 +776,12 @@ xfs_qm_scall_getquota(
> * gets turned off. No need to confuse the user level code,
> * so return zeroes in that case.
> */
> - if ((!XFS_IS_UQUOTA_ENFORCED(mp) && dqp->q_core.d_flags == XFS_DQ_USER) ||
> - (!XFS_IS_OQUOTA_ENFORCED(mp) &&
> - (dqp->q_core.d_flags & (XFS_DQ_PROJ | XFS_DQ_GROUP)))) {
> + if ((!XFS_IS_UQUOTA_ENFORCED(mp) &&
> + dqp->q_core.d_flags == XFS_DQ_USER) ||
> + (!XFS_IS_PQUOTA_ENFORCED(mp) &&
> + dqp->q_core.d_flags == XFS_DQ_PROJ) ||
> + (!XFS_IS_GQUOTA_ENFORCED(mp) &&
> + dqp->q_core.d_flags == XFS_DQ_GROUP)) {
> dst->d_btimer = 0;
> dst->d_itimer = 0;
> dst->d_rtbtimer = 0;
Same here - it's u/p/g order rather than u/g/p. Can you fix up all
the other cases so they are all in the same u/g/p order?
> diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h
> index c38068f..0596860 100644
> --- a/fs/xfs/xfs_quota.h
> +++ b/fs/xfs/xfs_quota.h
> @@ -161,28 +161,43 @@ typedef struct xfs_qoff_logformat {
> #define XFS_GQUOTA_ACCT 0x0040 /* group quota accounting ON */
>
> /*
> + * Start differentiating group quota and project quota using
> + * distinct flags, instead of using the combined OQUOTA flags.
> + *
> + * Conversion to and from the combined OQUOTA flag (if necessary)
> + * is done only in xfs_readsb() and xfs_sb_to_disk()
Try to describe the meaning of the flags, not the process you are
using to change the code. Hence I think, only the second paragraph
is needed here. Also, based on my comments above, conversion is
done in xfs_sb_qflags_to_disk() and xfs_sb_qflags_from_disk()....
Cheers,
Dave.
--
Dave Chinner
david@fromorbit.com
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH v9 3/6] xfs: Add pquota fields where gquota is used.
2013-06-24 2:48 ` [PATCH v9 3/6] xfs: Add pquota fields where gquota is used Chandra Seetharaman
@ 2013-06-24 8:00 ` Dave Chinner
2013-06-24 22:33 ` Chandra Seetharaman
2013-06-24 23:25 ` Chandra Seetharaman
0 siblings, 2 replies; 28+ messages in thread
From: Dave Chinner @ 2013-06-24 8:00 UTC (permalink / raw)
To: Chandra Seetharaman; +Cc: xfs
On Sun, Jun 23, 2013 at 09:48:24PM -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.
Formatting is a bit off there.
....
> @@ -949,21 +950,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;
> + }
> xfs_dqunlock(dqp);
FWIW, this is one of the reasons I mentioned being consistent about
order of quota processing being u/g/p - that's the lock ordering we
have to follow when locking multiple dquots.
> @@ -559,8 +596,13 @@ xfs_qm_dqattach_locked(
> * 100% all the time. It is just a hint, and this will
> * succeed in general.
> */
> - if (ip->i_udquot->q_gdquot != ip->i_gdquot)
> - xfs_qm_dqattach_grouphint(ip->i_udquot, ip->i_gdquot);
> + if (XFS_IS_GQUOTA_ON(mp) &&
> + ip->i_udquot->q_gdquot != ip->i_gdquot)
> + xfs_qm_dqattach_hint(ip, XFS_DQ_GROUP);
> +
> + if (XFS_IS_PQUOTA_ON(mp) &&
> + ip->i_udquot->q_pdquot != ip->i_pdquot)
> + xfs_qm_dqattach_hint(ip, XFS_DQ_PROJ);
Why do we need the XFS_IS_GQUOTA_ON/XFS_IS_PQUOTA_ON checks there?
If group quotas are not on, then both the hint and in the
inode pointers to the group dquot will be NULL, and therefore equal?
i.e. we don't need to even check if quotas are enabled here...
Indeed, why pass (ip, quota type) to xfs_qm_dqattach_hint()? why not
just pass the locations directly like:
xfs_qm_dqattach_hint(&ip->i_udquot->q_pdquot,
ip->i_pdquot):
> @@ -1423,6 +1484,15 @@ xfs_qm_init_quotainos(
> if (error)
> goto error_rele;
> }
> + /* Use gquotino for now */
/* XXX: Use 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;
> + }
.....
> @@ -1444,17 +1514,26 @@ xfs_qm_init_quotainos(
>
> flags &= ~XFS_QMOPT_SBVERSION;
> }
> - if (XFS_IS_OQUOTA_ON(mp) && gip == NULL) {
> - flags |= (XFS_IS_GQUOTA_ON(mp) ?
> - XFS_QMOPT_GQUOTA : XFS_QMOPT_PQUOTA);
> + if (XFS_IS_GQUOTA_ON(mp) && gip == NULL) {
> error = xfs_qm_qino_alloc(mp, &gip,
> - sbflags | XFS_SB_GQUOTINO, flags);
> + sbflags | XFS_SB_GQUOTINO,
> + flags | XFS_QMOPT_GQUOTA);
> + if (error)
> + goto error_rele;
> +
> + flags &= ~XFS_QMOPT_SBVERSION;
> + }
> + if (XFS_IS_PQUOTA_ON(mp) && pip == NULL) {
> + error = xfs_qm_qino_alloc(mp, &pip,
> + sbflags | XFS_SB_GQUOTINO,
> + flags | XFS_QMOPT_PQUOTA);
/* XXX: Use gquotino for now */
.....
> @@ -1958,13 +2057,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);
> + }
> }
3 dquots can be modified in transactions that call this function
now, not 2. That means transaction reservations for dquots need to
be increased by a dquot in size....
> @@ -107,18 +111,20 @@ extern void xfs_trans_mod_dquot(struct xfs_trans *,
> struct xfs_dquot *, uint, long);
> extern int xfs_trans_reserve_quota_bydquots(struct xfs_trans *,
> struct xfs_mount *, struct xfs_dquot *,
> - struct xfs_dquot *, long, long, uint);
> + struct xfs_dquot *, struct xfs_dquot *,
> + long, long, uint);
> extern void xfs_trans_dqjoin(struct xfs_trans *, struct xfs_dquot *);
> extern void xfs_trans_log_dquot(struct xfs_trans *, struct xfs_dquot *);
>
> /*
> - * 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_PRJ,
> XFS_QM_TRANS_DQTYPES
> };
> #define XFS_QM_TRANS_MAXDQS 2
OK, that works, but I still don't see anything about dquot
transaction reservations (i.e. XFS_DQUOT_LOGRES()) in this patch.
It defines the log space resservation for dquots being modified in a
transaction and we just bumped it by one for all transactions that
do block allocation or freeing.
Actually, I suspect that it is already wrong because it currently
reserves space for 3 dquots yet a chown operation can modify both
ATTR_UID and ATTR_GID at the same time. That will therefore modify
{old, new} x {udq, gdq}, and so we've got 4 dquots being modified.
Are there any cases where we might do {old, new} x {udq, gdq} + pdq
or {old, new} x {udq, gdq, pdq}, and hence need the reservation to
be 5 or 6 dquots?
<dig, ferret, dig, dig, blow away dust, ferret some more, dig, dig>
Indeed, the XFS_DQUOT_LOGRES() definition and comment around it is
unchanged from when it was first introduced in 1996. So whatever the
limitations on dquots in the one transaction are, they go back to
what was limited by Irix, not Linux....
And I just learnt something interesting - XFS on Irix only supported
user quota and project quota, there was no Irix group quota at all
prior to the linux port being completed. Group quotas weren't
implemented on Linux until well after the port to linux was out
there in 2001:
http://oss.sgi.com/cgi-bin/gitweb.cgi?p=archive/xfs-import.git;a=commit;h=749b2bf3ed5ff064efd69370e6b31ea44c4a78a6
And that commit basically swapped the project ID support for group
quota support (i.e. no more project quota!), and that meant XFS at
this point in time was not on-disk compatible between Irix and Linux
if you used project quotas on Irix or group quotas on Linux. But
because most of the code was common, the LInux code didn't change
the XFS_DQUOT_LOGRES() value which was defined at 3. And this
comment above xfs_trans_dqlockedjoin() is modified in that commit
like so:
@@ -303,8 +303,8 @@ xfs_trans_mod_dquot(
/*
* Given an array of dqtrx structures, lock all the dquots associated
* and join them to the transaction, provided they have been modified.
- * We know that the highest number of dquots (of one type - usr OR prj),
- * involved in a transaction is 2 and that both usr and prj combined - 3.
+ * We know that the highest number of dquots (of one type - usr OR grp),
+ * involved in a transaction is 2 and that both usr and grp combined - 3.
* So, we don't attempt to make this very generic.
*/
It was a search and replace that modified the comment, leaving the
value unchanged and, as such, incorrect.
IOWs, XFS_DQUOT_LOGRES() was defined on Irix where a chown call
could only change the UID. Hence there's only two dquots modified
in that operation and if blocks needed to be allocated/freed during
that setattr operation the project dquot would need to be modified
as well. So, there's the reason for it being defined as 3 dquots -
no support for group quota at all, despite what the comments say....
Hence I think XFS_DQUOT_LOGRES() actually needs to reserve space for
5 dquots that can be modified in a transaction on Linux. i.e. {old,
new} x {udq, gdq} + pdq, and that really needs a patch of it's own.
Chandra, do you want me to write that patch and commit message?
Cheers,
Dave.
PS: if anyone was wondering - it took about 3 hours of code
archaeology to pull that information out of the archives.
PPS: FWIW, project quota support wasn't reintroduced until 2005
where the differences between Irix and Linux were re-unified at the
source level via the "OQUOTA" names we have now.
http://oss.sgi.com/cgi-bin/gitweb.cgi?p=archive/xfs-import.git;a=commit;h=0ab041f659d7d51489a026b16d83ffddc80285bd
--
Dave Chinner
david@fromorbit.com
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH v9 1/6] xfs: Move code around and remove typedefs
2013-06-24 2:48 ` [PATCH v9 1/6] xfs: Move code around and remove typedefs Chandra Seetharaman
2013-06-24 5:31 ` Dave Chinner
@ 2013-06-24 21:36 ` Ben Myers
2013-06-24 23:23 ` Chandra Seetharaman
1 sibling, 1 reply; 28+ messages in thread
From: Ben Myers @ 2013-06-24 21:36 UTC (permalink / raw)
To: Chandra Seetharaman; +Cc: xfs
Hi Chandra,
On Sun, Jun 23, 2013 at 09:48:22PM -0500, Chandra Seetharaman wrote:
> Removed some typedefs, defined new functions, made some code clean up all in
> preparation of the series.
>
> No functional changes.
>
> Signed-off-by: Chandra Seetharaman <sekharan@us.ibm.com>
As Dave mentioned, there are a few categories of changes that would probably be
better as separate patches. I count 6:
1) the addition of xfs_is_quota_inode
2) conversion of XFS_DQUOT_TREE macro to xfs_dquot_tree inlined function
3) addition of xfs_dq_to_quota_inode
4) cleanups in xfs_dquot.c (xfs_qm_quotacheck,xfs_qm_init_quotainos,
xfs_qm_vop_dqalloc,xfs_qm_vop_chown_reserve) and xfs_trans_dquot.c
(xfs_trans_reserve_quota_bydquots)
5) changes to struct xfs_quotainfo. I don't have an aversion to the comments
in the structure. I'm guessing that you updated from xfs_inode_t to
struct xfs_inode and then ran into an 80 column issue later in the
structure. It'd be nice to have the entries all line up, but I think
your compromise is fine. Might have been better off touching only
the quota inodes and leaving the rest, but... style.
6) add dqtypes enum, make an array in xfs_dquot_acct, update
xfs_trans_dup_dqinfo. Now we have a two dimensional array in there, and
I wonder if it would be better if it were more strongly typed. e.g.
tp->t_dqinfo->dq_type[j]->dqt_ents[i]
(or something)
A couple more style notes below. If have the time and see fit to split this
up, great. Otherwise I will happily take it as is.
Reviewed-by: Ben Myers <bpm@sgi.com>
> ---
> fs/xfs/xfs_dquot.c | 16 ++--
> fs/xfs/xfs_dquot.h | 4 -
> fs/xfs/xfs_icache.c | 3 +-
> fs/xfs/xfs_itable.c | 2 +-
> fs/xfs/xfs_qm.c | 175 +++++++++++++++++++++++----------------------
> fs/xfs/xfs_qm.h | 133 ++++++++++++++++++++++-------------
> fs/xfs/xfs_qm_syscalls.c | 8 +-
> fs/xfs/xfs_sb.h | 6 ++
> fs/xfs/xfs_symlink.c | 3 +-
> fs/xfs/xfs_trans_dquot.c | 83 +++++++++-------------
> 10 files changed, 230 insertions(+), 203 deletions(-)
>
> diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c
> index 044e97a..f01012d 100644
> --- a/fs/xfs/xfs_dquot.c
> +++ b/fs/xfs/xfs_dquot.c
> @@ -570,13 +570,13 @@ xfs_qm_dqtobp(
> xfs_buf_t **O_bpp,
> uint flags)
> {
> - xfs_bmbt_irec_t map;
> - int nmaps = 1, error;
> - xfs_buf_t *bp;
> - xfs_inode_t *quotip = XFS_DQ_TO_QIP(dqp);
> - xfs_mount_t *mp = dqp->q_mount;
> - xfs_dqid_t id = be32_to_cpu(dqp->q_core.d_id);
> - xfs_trans_t *tp = (tpp ? *tpp : NULL);
> + struct xfs_bmbt_irec map;
> + int nmaps = 1, error;
> + struct xfs_buf *bp;
> + struct xfs_inode *quotip = xfs_dq_to_quota_inode(dqp);
> + struct xfs_mount *mp = dqp->q_mount;
> + xfs_dqid_t id = be32_to_cpu(dqp->q_core.d_id);
> + struct xfs_trans *tp = (tpp ? *tpp : NULL);
>
> dqp->q_fileoffset = (xfs_fileoff_t)id / mp->m_quotainfo->qi_dqperchunk;
>
> @@ -804,7 +804,7 @@ xfs_qm_dqget(
> xfs_dquot_t **O_dqpp) /* OUT : locked incore dquot */
> {
> struct xfs_quotainfo *qi = mp->m_quotainfo;
> - struct radix_tree_root *tree = XFS_DQUOT_TREE(qi, type);
> + struct radix_tree_root *tree = xfs_dquot_tree(qi, type);
> struct xfs_dquot *dqp;
> int error;
>
> diff --git a/fs/xfs/xfs_dquot.h b/fs/xfs/xfs_dquot.h
> index 4f0ebfc..b596626 100644
> --- a/fs/xfs/xfs_dquot.h
> +++ b/fs/xfs/xfs_dquot.h
> @@ -143,10 +143,6 @@ static inline xfs_dquot_t *xfs_inode_dquot(struct xfs_inode *ip, int type)
> #define XFS_QM_ISUDQ(dqp) ((dqp)->dq_flags & XFS_DQ_USER)
> #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)
>
> extern int xfs_qm_dqread(struct xfs_mount *, xfs_dqid_t, uint,
> uint, struct xfs_dquot **);
> diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c
> index 96e344e..9560dc1 100644
> --- a/fs/xfs/xfs_icache.c
> +++ b/fs/xfs/xfs_icache.c
> @@ -335,7 +335,8 @@ 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 = NULL;
> + ip->i_gdquot = NULL;
> xfs_iflags_set(ip, iflags);
>
> /* insert the new inode */
> diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
> index 2ea7d40..9cbf9e0 100644
> --- a/fs/xfs/xfs_itable.c
> +++ b/fs/xfs/xfs_itable.c
> @@ -43,7 +43,7 @@ xfs_internal_inum(
> {
> return (ino == mp->m_sb.sb_rbmino || ino == mp->m_sb.sb_rsumino ||
> (xfs_sb_version_hasquota(&mp->m_sb) &&
> - (ino == mp->m_sb.sb_uquotino || ino == mp->m_sb.sb_gquotino)));
> + xfs_is_quota_inode(&mp->m_sb, ino)));
> }
>
> /*
> diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c
> index b75c9bb..f5f9925 100644
> --- a/fs/xfs/xfs_qm.c
> +++ b/fs/xfs/xfs_qm.c
> @@ -70,7 +70,7 @@ xfs_qm_dquot_walk(
> void *data)
> {
> struct xfs_quotainfo *qi = mp->m_quotainfo;
> - struct radix_tree_root *tree = XFS_DQUOT_TREE(qi, type);
> + struct radix_tree_root *tree = xfs_dquot_tree(qi, type);
> uint32_t next_index;
> int last_error = 0;
> int skipped;
> @@ -189,7 +189,7 @@ xfs_qm_dqpurge(
> xfs_dqfunlock(dqp);
> xfs_dqunlock(dqp);
>
> - radix_tree_delete(XFS_DQUOT_TREE(qi, dqp->q_core.d_flags),
> + radix_tree_delete(xfs_dquot_tree(qi, dqp->q_core.d_flags),
> be32_to_cpu(dqp->q_core.d_id));
> qi->qi_dquots--;
>
> @@ -489,8 +489,7 @@ xfs_qm_need_dqattach(
> return false;
> if (!XFS_NOT_DQATTACHED(mp, ip))
> return false;
> - if (ip->i_ino == mp->m_sb.sb_uquotino ||
> - ip->i_ino == mp->m_sb.sb_gquotino)
> + if (xfs_is_quota_inode(&mp->m_sb, ip->i_ino))
> return false;
> return true;
> }
> @@ -606,8 +605,7 @@ xfs_qm_dqdetach(
>
> trace_xfs_dquot_dqdetach(ip);
>
> - ASSERT(ip->i_ino != ip->i_mount->m_sb.sb_uquotino);
> - ASSERT(ip->i_ino != ip->i_mount->m_sb.sb_gquotino);
> + ASSERT(!xfs_is_quota_inode(&ip->i_mount->m_sb, ip->i_ino));
> if (ip->i_udquot) {
> xfs_qm_dqrele(ip->i_udquot);
> ip->i_udquot = NULL;
> @@ -1152,7 +1150,7 @@ xfs_qm_dqusage_adjust(
> * rootino must have its resources accounted for, not so with the quota
> * inodes.
> */
> - if (ino == mp->m_sb.sb_uquotino || ino == mp->m_sb.sb_gquotino) {
> + if (xfs_is_quota_inode(&mp->m_sb, ino)) {
> *res = BULKSTAT_RV_NOTHING;
> return XFS_ERROR(EINVAL);
> }
> @@ -1262,19 +1260,20 @@ int
> xfs_qm_quotacheck(
> xfs_mount_t *mp)
> {
> - int done, count, error, error2;
> - xfs_ino_t lastino;
> - size_t structsz;
> - xfs_inode_t *uip, *gip;
> - uint flags;
> - LIST_HEAD (buffer_list);
> + int done, count, error, error2;
> + xfs_ino_t lastino;
> + size_t structsz;
> + uint flags;
> + LIST_HEAD (buffer_list);
> + struct xfs_inode *uip = mp->m_quotainfo->qi_uquotaip;
> + struct xfs_inode *gip = mp->m_quotainfo->qi_gquotaip;
>
> count = INT_MAX;
> structsz = 1;
> lastino = 0;
> flags = 0;
>
> - ASSERT(mp->m_quotainfo->qi_uquotaip || mp->m_quotainfo->qi_gquotaip);
> + ASSERT(uip || gip);
> ASSERT(XFS_IS_QUOTA_RUNNING(mp));
>
> xfs_notice(mp, "Quotacheck needed: Please wait.");
> @@ -1284,7 +1283,6 @@ xfs_qm_quotacheck(
> * their counters to zero. We need a clean slate.
> * We don't log our changes till later.
> */
> - uip = mp->m_quotainfo->qi_uquotaip;
> if (uip) {
> error = xfs_qm_dqiterate(mp, uip, XFS_QMOPT_UQUOTA,
> &buffer_list);
> @@ -1293,7 +1291,6 @@ xfs_qm_quotacheck(
> flags |= XFS_UQUOTA_CHKD;
> }
>
> - 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,
> @@ -1395,15 +1392,13 @@ STATIC int
> xfs_qm_init_quotainos(
> xfs_mount_t *mp)
> {
> - xfs_inode_t *uip, *gip;
> - int error;
> - __int64_t sbflags;
> - uint flags;
> + struct xfs_inode *uip = NULL;
> + struct xfs_inode *gip = NULL;
> + int error;
> + __int64_t sbflags = 0;
> + uint flags = 0;
>
> ASSERT(mp->m_quotainfo);
> - uip = gip = NULL;
> - sbflags = 0;
> - flags = 0;
>
> /*
> * Get the uquota and gquota inodes
> @@ -1412,19 +1407,18 @@ 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) &&
> 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;
> }
> } else {
> flags |= XFS_QMOPT_SBVERSION;
> @@ -1439,10 +1433,11 @@ xfs_qm_init_quotainos(
> * temporarily switch to read-write to do this.
> */
> if (XFS_IS_UQUOTA_ON(mp) && uip == NULL) {
> - if ((error = xfs_qm_qino_alloc(mp, &uip,
> + error = xfs_qm_qino_alloc(mp, &uip,
> sbflags | XFS_SB_UQUOTINO,
> - flags | XFS_QMOPT_UQUOTA)))
> - return XFS_ERROR(error);
> + flags | XFS_QMOPT_UQUOTA);
> + if (error)
> + goto error_rele;
>
> flags &= ~XFS_QMOPT_SBVERSION;
> }
> @@ -1451,18 +1446,21 @@ xfs_qm_init_quotainos(
> XFS_QMOPT_GQUOTA : XFS_QMOPT_PQUOTA);
> error = xfs_qm_qino_alloc(mp, &gip,
> sbflags | XFS_SB_GQUOTINO, flags);
> - if (error) {
> - if (uip)
> - IRELE(uip);
> -
> - return XFS_ERROR(error);
> - }
> + if (error)
> + goto error_rele;
> }
>
> mp->m_quotainfo->qi_uquotaip = uip;
> mp->m_quotainfo->qi_gquotaip = gip;
>
> return 0;
> +
> +error_rele:
> + if (uip)
> + IRELE(uip);
> + if (gip)
> + IRELE(gip);
> + return XFS_ERROR(error);
> }
>
> STATIC void
> @@ -1473,7 +1471,7 @@ xfs_qm_dqfree_one(
> struct xfs_quotainfo *qi = mp->m_quotainfo;
>
> mutex_lock(&qi->qi_tree_lock);
> - radix_tree_delete(XFS_DQUOT_TREE(qi, dqp->q_core.d_flags),
> + radix_tree_delete(xfs_dquot_tree(qi, dqp->q_core.d_flags),
> be32_to_cpu(dqp->q_core.d_id));
>
> qi->qi_dquots--;
> @@ -1659,7 +1657,8 @@ xfs_qm_vop_dqalloc(
> struct xfs_dquot **O_gdqpp)
> {
> struct xfs_mount *mp = ip->i_mount;
> - struct xfs_dquot *uq, *gq;
> + struct xfs_dquot *uq = NULL;
> + struct xfs_dquot *gq = NULL;
> int error;
> uint lockflags;
>
> @@ -1684,7 +1683,6 @@ xfs_qm_vop_dqalloc(
> }
> }
>
> - uq = gq = NULL;
> if ((flags & XFS_QMOPT_UQUOTA) && XFS_IS_UQUOTA_ON(mp)) {
> if (ip->i_d.di_uid != uid) {
> /*
> @@ -1697,14 +1695,14 @@ xfs_qm_vop_dqalloc(
> * holding ilock.
> */
> xfs_iunlock(ip, lockflags);
> - if ((error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t) uid,
> + error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t) uid,
> XFS_DQ_USER,
> XFS_QMOPT_DQALLOC |
> XFS_QMOPT_DOWARN,
> - &uq))) {
> - ASSERT(error != ENOENT);
> + &uq);
> + ASSERT(error != ENOENT);
You have a series of these asserts which used to be in the error case taken out
of the error case. Clearly the assertion is still true when error == 0... but
I tend to prefer that it still be in the error curlies. A silly style thing
which I welcome you to reject with prejudice.
> + if (error)
> return error;
> - }
> /*
> * Get the ilock in the right order.
> */
> @@ -1723,16 +1721,14 @@ xfs_qm_vop_dqalloc(
> if ((flags & XFS_QMOPT_GQUOTA) && XFS_IS_GQUOTA_ON(mp)) {
> if (ip->i_d.di_gid != gid) {
> xfs_iunlock(ip, lockflags);
> - if ((error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t)gid,
> + error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t)gid,
> XFS_DQ_GROUP,
> XFS_QMOPT_DQALLOC |
> XFS_QMOPT_DOWARN,
> - &gq))) {
> - if (uq)
> - xfs_qm_dqrele(uq);
> - ASSERT(error != ENOENT);
> - return error;
> - }
> + &gq);
> + ASSERT(error != ENOENT);
> + if (error)
> + goto error_rele;
> xfs_dqunlock(gq);
> lockflags = XFS_ILOC_SHARED;
> xfs_ilock(ip, lockflags);
> @@ -1743,16 +1739,14 @@ xfs_qm_vop_dqalloc(
> } else 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,
> + error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t)prid,
> XFS_DQ_PROJ,
> XFS_QMOPT_DQALLOC |
> XFS_QMOPT_DOWARN,
> - &gq))) {
> - if (uq)
> - xfs_qm_dqrele(uq);
> - ASSERT(error != ENOENT);
> - return (error);
> - }
> + &gq);
> + ASSERT(error != ENOENT);
> + if (error)
> + goto error_rele;
> xfs_dqunlock(gq);
> lockflags = XFS_ILOCK_SHARED;
> xfs_ilock(ip, lockflags);
> @@ -1774,6 +1768,11 @@ xfs_qm_vop_dqalloc(
> else if (gq)
> xfs_qm_dqrele(gq);
> return 0;
> +
> +error_rele:
> + if (uq)
> + xfs_qm_dqrele(uq);
> + return error;
> }
>
> /*
> @@ -1821,29 +1820,31 @@ 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)
> + struct xfs_trans *tp,
> + struct xfs_inode *ip,
> + struct xfs_dquot *udqp,
> + struct xfs_dquot *gdqp,
> + uint flags)
> {
> - xfs_mount_t *mp = ip->i_mount;
> - uint delblks, blkflags, prjflags = 0;
> - xfs_dquot_t *unresudq, *unresgdq, *delblksudq, *delblksgdq;
> - int error;
> + struct xfs_mount *mp = ip->i_mount;
> + uint delblks, blkflags, prjflags = 0;
> + struct xfs_dquot *udq_unres = NULL;
> + struct xfs_dquot *gdq_unres = NULL;
> + struct xfs_dquot *udq_delblks = NULL;
> + struct xfs_dquot *gdq_delblks = NULL;
> + int error;
>
>
> ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED));
> ASSERT(XFS_IS_QUOTA_RUNNING(mp));
>
> delblks = ip->i_delayed_blks;
> - delblksudq = delblksgdq = unresudq = unresgdq = NULL;
> blkflags = XFS_IS_REALTIME_INODE(ip) ?
> XFS_QMOPT_RES_RTBLKS : XFS_QMOPT_RES_REGBLKS;
>
> if (XFS_IS_UQUOTA_ON(mp) && udqp &&
> ip->i_d.di_uid != (uid_t)be32_to_cpu(udqp->q_core.d_id)) {
> - delblksudq = udqp;
> + udq_delblks = udqp;
> /*
> * If there are delayed allocation blocks, then we have to
> * unreserve those from the old dquot, and add them to the
> @@ -1851,7 +1852,7 @@ xfs_qm_vop_chown_reserve(
> */
> if (delblks) {
> ASSERT(ip->i_udquot);
> - unresudq = ip->i_udquot;
> + udq_unres = ip->i_udquot;
> }
> }
> if (XFS_IS_OQUOTA_ON(ip->i_mount) && gdqp) {
> @@ -1862,18 +1863,19 @@ xfs_qm_vop_chown_reserve(
> if (prjflags ||
> (XFS_IS_GQUOTA_ON(ip->i_mount) &&
> ip->i_d.di_gid != be32_to_cpu(gdqp->q_core.d_id))) {
> - delblksgdq = gdqp;
> + gdq_delblks = gdqp;
> if (delblks) {
> ASSERT(ip->i_gdquot);
> - unresgdq = ip->i_gdquot;
> + gdq_unres = ip->i_gdquot;
> }
> }
> }
>
> - if ((error = xfs_trans_reserve_quota_bydquots(tp, ip->i_mount,
> - delblksudq, delblksgdq, ip->i_d.di_nblocks, 1,
> - flags | blkflags | prjflags)))
> - return (error);
> + error = xfs_trans_reserve_quota_bydquots(tp, ip->i_mount,
> + udq_delblks, gdq_delblks, ip->i_d.di_nblocks, 1,
> + flags | blkflags | prjflags);
> + if (error)
> + return error;
>
> /*
> * Do the delayed blks reservations/unreservations now. Since, these
> @@ -1885,14 +1887,15 @@ xfs_qm_vop_chown_reserve(
> /*
> * Do the reservations first. Unreservation can't fail.
> */
> - ASSERT(delblksudq || delblksgdq);
> - ASSERT(unresudq || unresgdq);
> - if ((error = xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount,
> - delblksudq, delblksgdq, (xfs_qcnt_t)delblks, 0,
> - flags | blkflags | prjflags)))
> - return (error);
> + ASSERT(udq_delblks || gdq_delblks);
> + ASSERT(udq_unres || gdq_unres);
> + error = xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount,
> + udq_delblks, gdq_delblks, (xfs_qcnt_t)delblks, 0,
> + flags | blkflags | prjflags);
> + if (error)
> + return error;
> xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount,
> - unresudq, unresgdq, -((xfs_qcnt_t)delblks), 0,
> + udq_unres, gdq_unres, -((xfs_qcnt_t)delblks), 0,
> blkflags);
> }
>
> diff --git a/fs/xfs/xfs_qm.h b/fs/xfs/xfs_qm.h
> index 5d16a6e..4b330f2 100644
> --- a/fs/xfs/xfs_qm.h
> +++ b/fs/xfs/xfs_qm.h
> @@ -42,57 +42,89 @@ extern struct kmem_zone *xfs_qm_dqtrxzone;
> * The mount structure keeps a pointer to this.
> */
> typedef struct xfs_quotainfo {
> - struct radix_tree_root qi_uquota_tree;
> - struct radix_tree_root qi_gquota_tree;
> - struct mutex qi_tree_lock;
> - xfs_inode_t *qi_uquotaip; /* user quota inode */
> - xfs_inode_t *qi_gquotaip; /* group quota inode */
> - struct list_head qi_lru_list;
> - struct mutex qi_lru_lock;
> - int qi_lru_count;
> - int qi_dquots;
> - time_t qi_btimelimit; /* limit for blks timer */
> - time_t qi_itimelimit; /* limit for inodes timer */
> - time_t qi_rtbtimelimit;/* limit for rt blks timer */
> - xfs_qwarncnt_t qi_bwarnlimit; /* limit for blks warnings */
> - xfs_qwarncnt_t qi_iwarnlimit; /* limit for inodes warnings */
> - xfs_qwarncnt_t qi_rtbwarnlimit;/* limit for rt blks warnings */
> - struct mutex qi_quotaofflock;/* to serialize quotaoff */
> - xfs_filblks_t qi_dqchunklen; /* # BBs in a chunk of dqs */
> - uint qi_dqperchunk; /* # ondisk dqs in above chunk */
> - xfs_qcnt_t qi_bhardlimit; /* default data blk hard limit */
> - xfs_qcnt_t qi_bsoftlimit; /* default data blk soft limit */
> - xfs_qcnt_t qi_ihardlimit; /* default inode count hard limit */
> - xfs_qcnt_t qi_isoftlimit; /* default inode count soft limit */
> - xfs_qcnt_t qi_rtbhardlimit;/* default realtime blk hard limit */
> - xfs_qcnt_t qi_rtbsoftlimit;/* default realtime blk soft limit */
> - struct shrinker qi_shrinker;
> + struct radix_tree_root qi_uquota_tree;
> + struct radix_tree_root qi_gquota_tree;
> + struct mutex qi_tree_lock;
> + struct xfs_inode *qi_uquotaip; /* user quota inode */
> + struct xfs_inode *qi_gquotaip; /* group quota inode */
> + struct list_head qi_lru_list;
> + struct mutex qi_lru_lock;
> + int qi_lru_count;
> + int qi_dquots;
> + time_t qi_btimelimit; /* limit for blks timer */
> + time_t qi_itimelimit; /* limit for inodes timer */
> + time_t qi_rtbtimelimit;/* limit for rt blks timer */
> + xfs_qwarncnt_t qi_bwarnlimit; /* limit for blks warnings */
> + xfs_qwarncnt_t qi_iwarnlimit; /* limit for inodes warnings */
> + xfs_qwarncnt_t qi_rtbwarnlimit;/* limit for rt blks warnings */
> + struct mutex qi_quotaofflock;/* to serialize quotaoff */
> + xfs_filblks_t qi_dqchunklen; /* # BBs in a chunk of dqs */
> + uint qi_dqperchunk; /* # ondisk dqs in above chunk */
> + xfs_qcnt_t qi_bhardlimit; /* default data blk hard limit */
> + xfs_qcnt_t qi_bsoftlimit; /* default data blk soft limit */
> + xfs_qcnt_t qi_ihardlimit; /* default inode count hard limit */
> + xfs_qcnt_t qi_isoftlimit; /* default inode count soft limit */
> + xfs_qcnt_t qi_rtbhardlimit;/* default realtime blk hard limit */
> + xfs_qcnt_t qi_rtbsoftlimit;/* default realtime blk soft limit */
> + struct shrinker qi_shrinker;
> } xfs_quotainfo_t;
>
> -#define XFS_DQUOT_TREE(qi, type) \
> - ((type & XFS_DQ_USER) ? \
> - &((qi)->qi_uquota_tree) : \
> - &((qi)->qi_gquota_tree))
> +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:
> + case XFS_DQ_PROJ:
> + return &qi->qi_gquota_tree;
> + default:
> + ASSERT(0);
> + }
> + return NULL;
> +}
>
> +static inline struct xfs_inode *
> +xfs_dq_to_quota_inode(struct xfs_dquot *dqp)
> +{
> + switch (dqp->dq_flags & XFS_DQ_ALLTYPES) {
> + case XFS_DQ_USER:
> + return dqp->q_mount->m_quotainfo->qi_uquotaip;
> + case XFS_DQ_GROUP:
> + case XFS_DQ_PROJ:
> + return dqp->q_mount->m_quotainfo->qi_gquotaip;
> + default:
> + ASSERT(0);
> + }
> + return NULL;
> +}
>
> extern int xfs_qm_calc_dquots_per_chunk(struct xfs_mount *mp,
> unsigned int nbblks);
> -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(struct xfs_trans *,
> + struct xfs_dquot *, uint, long);
> +extern int xfs_trans_reserve_quota_bydquots(struct xfs_trans *,
> + struct xfs_mount *, struct xfs_dquot *,
> + struct xfs_dquot *, long, long, uint);
> +extern void xfs_trans_dqjoin(struct xfs_trans *, struct xfs_dquot *);
> +extern void xfs_trans_log_dquot(struct xfs_trans *, struct xfs_dquot *);
>
> /*
> * 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
> * 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_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
> @@ -106,22 +138,23 @@ typedef struct xfs_dquot_acct {
> #define XFS_QM_IWARNLIMIT 5
> #define XFS_QM_RTBWARNLIMIT 5
>
> -extern void xfs_qm_destroy_quotainfo(xfs_mount_t *);
> -extern int xfs_qm_quotacheck(xfs_mount_t *);
> -extern int xfs_qm_write_sb_changes(xfs_mount_t *, __int64_t);
> +extern void xfs_qm_destroy_quotainfo(struct xfs_mount *);
> +extern int xfs_qm_quotacheck(struct xfs_mount *);
> +extern int xfs_qm_write_sb_changes(struct xfs_mount *, __int64_t);
>
> /* dquot stuff */
> -extern void xfs_qm_dqpurge_all(xfs_mount_t *, uint);
> -extern void xfs_qm_dqrele_all_inodes(xfs_mount_t *, uint);
> +extern void xfs_qm_dqpurge_all(struct xfs_mount *, uint);
> +extern void xfs_qm_dqrele_all_inodes(struct xfs_mount *, uint);
>
> /* quota ops */
> -extern int xfs_qm_scall_trunc_qfiles(xfs_mount_t *, uint);
> -extern int xfs_qm_scall_getquota(xfs_mount_t *, xfs_dqid_t, uint,
> - fs_disk_quota_t *);
> +extern int xfs_qm_scall_trunc_qfiles(struct xfs_mount *, uint);
> +extern int xfs_qm_scall_getquota(struct xfs_mount *, xfs_dqid_t,
> + uint, struct fs_disk_quota *);
> extern int xfs_qm_scall_setqlim(struct xfs_mount *, xfs_dqid_t, uint,
> - fs_disk_quota_t *);
> -extern int xfs_qm_scall_getqstat(xfs_mount_t *, fs_quota_stat_t *);
> -extern int xfs_qm_scall_quotaon(xfs_mount_t *, uint);
> -extern int xfs_qm_scall_quotaoff(xfs_mount_t *, uint);
> + struct fs_disk_quota *);
> +extern int xfs_qm_scall_getqstat(struct xfs_mount *,
> + struct fs_quota_stat *);
> +extern int xfs_qm_scall_quotaon(struct xfs_mount *, uint);
> +extern int xfs_qm_scall_quotaoff(struct xfs_mount *, uint);
>
> #endif /* __XFS_QM_H__ */
> diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c
> index 6cdf6ff..b03b2ab 100644
> --- a/fs/xfs/xfs_qm_syscalls.c
> +++ b/fs/xfs/xfs_qm_syscalls.c
> @@ -407,11 +407,11 @@ xfs_qm_scall_getqstat(
> struct fs_quota_stat *out)
> {
> struct xfs_quotainfo *q = mp->m_quotainfo;
> - struct xfs_inode *uip, *gip;
> - bool tempuqip, tempgqip;
> + struct xfs_inode *uip = NULL;
> + struct xfs_inode *gip = NULL;
> + bool tempuqip = false;
> + bool tempgqip = false;
>
> - uip = gip = NULL;
> - tempuqip = tempgqip = false;
> memset(out, 0, sizeof(fs_quota_stat_t));
>
> out->qs_version = FS_QSTAT_VERSION;
> diff --git a/fs/xfs/xfs_sb.h b/fs/xfs/xfs_sb.h
> index 2de58a8..78f9e70 100644
> --- a/fs/xfs/xfs_sb.h
> +++ b/fs/xfs/xfs_sb.h
> @@ -618,6 +618,12 @@ xfs_sb_has_incompat_log_feature(
> return (sbp->sb_features_log_incompat & feature) != 0;
> }
>
> +static inline bool
> +xfs_is_quota_inode(struct xfs_sb *sbp, xfs_ino_t ino)
> +{
> + return (ino == sbp->sb_uquotino || ino == sbp->sb_gquotino);
> +}
> +
> /*
> * end of superblock version macros
> */
> diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c
> index 738c04b..e830fb5 100644
> --- a/fs/xfs/xfs_symlink.c
> +++ b/fs/xfs/xfs_symlink.c
> @@ -358,7 +358,8 @@ xfs_symlink(
> int n;
> xfs_buf_t *bp;
> prid_t prid;
> - struct xfs_dquot *udqp, *gdqp;
> + struct xfs_dquot *udqp = NULL;
> + struct xfs_dquot *gdqp = NULL;
> uint resblks;
>
> *ipp = NULL;
> diff --git a/fs/xfs/xfs_trans_dquot.c b/fs/xfs/xfs_trans_dquot.c
> index fec75d0..7ea7485 100644
> --- a/fs/xfs/xfs_trans_dquot.c
> +++ b/fs/xfs/xfs_trans_dquot.c
> @@ -103,8 +103,6 @@ xfs_trans_dup_dqinfo(
> return;
>
> xfs_trans_alloc_dqinfo(ntp);
> - oqa = otp->t_dqinfo->dqa_usrdquots;
> - nqa = ntp->t_dqinfo->dqa_usrdquots;
>
> /*
> * Because the quota blk reservation is carried forward,
> @@ -113,7 +111,9 @@ 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 < XFS_QM_TRANS_DQTYPES; j++) {
> + oqa = otp->t_dqinfo->dqs[j];
> + nqa = ntp->t_dqinfo->dqs[j];
> for (i = 0; i < XFS_QM_TRANS_MAXDQS; i++) {
> if (oqa[i].qt_dquot == NULL)
> break;
> @@ -138,8 +138,6 @@ xfs_trans_dup_dqinfo(
> oq->qt_ino_res = oq->qt_ino_res_used;
>
Could clean up this extra line...
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH v9 1/6] xfs: Move code around and remove typedefs
2013-06-24 5:31 ` Dave Chinner
@ 2013-06-24 22:21 ` Chandra Seetharaman
0 siblings, 0 replies; 28+ messages in thread
From: Chandra Seetharaman @ 2013-06-24 22:21 UTC (permalink / raw)
To: Dave Chinner; +Cc: xfs
On Mon, 2013-06-24 at 15:31 +1000, Dave Chinner wrote:
> On Sun, Jun 23, 2013 at 09:48:22PM -0500, Chandra Seetharaman wrote:
> > Removed some typedefs, defined new functions, made some code clean up all in
> > preparation of the series.
> >
> > No functional changes.
>
> This does a lot of different stuff. Can you separate out the actual
> factoring changes (e.g. xfs_is_quota_inode() and xfs_dquot_tree())
> into separate patches, and the same with the struct xfs_dquot_acct
> as it changes both logic and structure...
Sure. I will follow Ben's suggestion in splitting these.
>
> > diff --git a/fs/xfs/xfs_qm.h b/fs/xfs/xfs_qm.h
> > index 5d16a6e..4b330f2 100644
> > --- a/fs/xfs/xfs_qm.h
> > +++ b/fs/xfs/xfs_qm.h
> > @@ -42,57 +42,89 @@ extern struct kmem_zone *xfs_qm_dqtrxzone;
> > * The mount structure keeps a pointer to this.
> > */
> > typedef struct xfs_quotainfo {
> > - struct radix_tree_root qi_uquota_tree;
> > - struct radix_tree_root qi_gquota_tree;
> > - struct mutex qi_tree_lock;
> > - xfs_inode_t *qi_uquotaip; /* user quota inode */
> > - xfs_inode_t *qi_gquotaip; /* group quota inode */
> > - struct list_head qi_lru_list;
> > - struct mutex qi_lru_lock;
> > - int qi_lru_count;
> > - int qi_dquots;
> > - time_t qi_btimelimit; /* limit for blks timer */
> > - time_t qi_itimelimit; /* limit for inodes timer */
> > - time_t qi_rtbtimelimit;/* limit for rt blks timer */
> > - xfs_qwarncnt_t qi_bwarnlimit; /* limit for blks warnings */
> > - xfs_qwarncnt_t qi_iwarnlimit; /* limit for inodes warnings */
> > - xfs_qwarncnt_t qi_rtbwarnlimit;/* limit for rt blks warnings */
> > - struct mutex qi_quotaofflock;/* to serialize quotaoff */
> > - xfs_filblks_t qi_dqchunklen; /* # BBs in a chunk of dqs */
> > - uint qi_dqperchunk; /* # ondisk dqs in above chunk */
> > - xfs_qcnt_t qi_bhardlimit; /* default data blk hard limit */
> > - xfs_qcnt_t qi_bsoftlimit; /* default data blk soft limit */
> > - xfs_qcnt_t qi_ihardlimit; /* default inode count hard limit */
> > - xfs_qcnt_t qi_isoftlimit; /* default inode count soft limit */
> > - xfs_qcnt_t qi_rtbhardlimit;/* default realtime blk hard limit */
> > - xfs_qcnt_t qi_rtbsoftlimit;/* default realtime blk soft limit */
> > - struct shrinker qi_shrinker;
> > + struct radix_tree_root qi_uquota_tree;
> > + struct radix_tree_root qi_gquota_tree;
> > + struct mutex qi_tree_lock;
> > + struct xfs_inode *qi_uquotaip; /* user quota inode */
> > + struct xfs_inode *qi_gquotaip; /* group quota inode */
> > + struct list_head qi_lru_list;
> > + struct mutex qi_lru_lock;
> > + int qi_lru_count;
> > + int qi_dquots;
> > + time_t qi_btimelimit; /* limit for blks timer */
> > + time_t qi_itimelimit; /* limit for inodes timer */
> > + time_t qi_rtbtimelimit;/* limit for rt blks timer */
> > + xfs_qwarncnt_t qi_bwarnlimit; /* limit for blks warnings */
> > + xfs_qwarncnt_t qi_iwarnlimit; /* limit for inodes warnings */
> > + xfs_qwarncnt_t qi_rtbwarnlimit;/* limit for rt blks warnings */
> > + struct mutex qi_quotaofflock;/* to serialize quotaoff */
> > + xfs_filblks_t qi_dqchunklen; /* # BBs in a chunk of dqs */
> > + uint qi_dqperchunk; /* # ondisk dqs in above chunk */
> > + xfs_qcnt_t qi_bhardlimit; /* default data blk hard limit */
> > + xfs_qcnt_t qi_bsoftlimit; /* default data blk soft limit */
> > + xfs_qcnt_t qi_ihardlimit; /* default inode count hard limit */
> > + xfs_qcnt_t qi_isoftlimit; /* default inode count soft limit */
> > + xfs_qcnt_t qi_rtbhardlimit;/* default realtime blk hard limit */
> > + xfs_qcnt_t qi_rtbsoftlimit;/* default realtime blk soft limit */
> > + struct shrinker qi_shrinker;
> > } xfs_quotainfo_t;
>
> I don't see much point in random whitespace cleanups like this. If
> you are going to change them, at least clean it up properly, so all
> variables are aligned, and all the comments are aligned as well. In
> most cases, the comments are redundant because the variable names
> are very descriptive and so probably could be removed....
I will align all these at the cost of these "valuable" comments :)
>
> Cheers,
>
> Dave.
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH v9 2/6] xfs: Remove incore use of XFS_OQUOTA_ENFD and XFS_OQUOTA_CHKD
2013-06-24 5:59 ` Dave Chinner
@ 2013-06-24 22:25 ` Chandra Seetharaman
2013-06-25 5:32 ` Dave Chinner
0 siblings, 1 reply; 28+ messages in thread
From: Chandra Seetharaman @ 2013-06-24 22:25 UTC (permalink / raw)
To: Dave Chinner; +Cc: xfs
On Mon, 2013-06-24 at 15:59 +1000, Dave Chinner wrote:
> On Sun, Jun 23, 2013 at 09:48:23PM -0500, Chandra Seetharaman wrote:
> > Remove all incore use of XFS_OQUOTA_ENFD and XFS_OQUOTA_CHKD. Instead,
> > start using XFS_GQUOTA_.* XFS_PQUOTA_.* counterparts for GQUOTA and
> > PQUOTA respectively.
> >
> > On-disk copy still uses XFS_OQUOTA_ENFD and XFS_OQUOTA_CHKD.
> >
> > Read and write of the superblock does the conversion from *OQUOTA*
> > to *[PG]QUOTA*.
> >
> > Signed-off-by: Chandra Seetharaman <sekharan@us.ibm.com>
> > ---
> > fs/xfs/xfs_mount.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
> > fs/xfs/xfs_qm.c | 9 ++++++---
> > fs/xfs/xfs_qm_syscalls.c | 39 +++++++++++++++++++++------------------
> > fs/xfs/xfs_quota.h | 42 ++++++++++++++++++++++++++++--------------
> > fs/xfs/xfs_quotaops.c | 6 ++++--
> > fs/xfs/xfs_super.c | 16 ++++++++--------
> > fs/xfs/xfs_trans_dquot.c | 4 ++--
> > 7 files changed, 115 insertions(+), 47 deletions(-)
> >
> > diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
> > index 6a19434..e2e14cb 100644
> > --- a/fs/xfs/xfs_mount.c
> > +++ b/fs/xfs/xfs_mount.c
> > @@ -336,6 +336,14 @@ xfs_mount_validate_sb(
> > return XFS_ERROR(EWRONGFS);
> > }
> >
> > + if ((sbp->sb_qflags & (XFS_OQUOTA_ENFD | XFS_OQUOTA_CHKD)) &&
> > + (sbp->sb_qflags & (XFS_PQUOTA_ENFD | XFS_GQUOTA_ENFD |
> > + XFS_PQUOTA_CHKD | XFS_GQUOTA_CHKD))) {
> > + xfs_notice(mp,
> > +"Super block has XFS_OQUOTA bits along with XFS_PQUOTA and/or XFS_GQUOTA bits.\n");
> > + return XFS_ERROR(EFSCORRUPTED);
> > + }
> > +
> > /*
> > * Version 5 superblock feature mask validation. Reject combinations the
> > * kernel cannot support up front before checking anything else. For
> > @@ -622,6 +630,35 @@ xfs_sb_from_disk(
> > to->sb_lsn = be64_to_cpu(from->sb_lsn);
> > }
> >
> > +static inline void
> > +xfs_handle_quota_to_disk(
> > + xfs_dsb_t *to,
> > + xfs_sb_t *from,
> > + __int64_t *fields)
>
> An "XFS handle" has meaning in the namespace (i.e. an XFS filehandle
> as used in xfs_ioctl.c and defined in xfs_fs.h, so this is not a
> good name.
>
> Realistically, xfs_sb_qflags_to_disk() is more appropriate for it's
> function....
I agree with your "handle" comment.
As you can see in patch 4/6, PQUOTINO logic is also added to this
function. Can you suggest a name inclusive of that ?
>
> > @@ -643,6 +680,7 @@ xfs_sb_to_disk(
> > if (!fields)
> > return;
> >
> > + xfs_handle_quota_to_disk(to, from, &fields);
> > while (fields) {
> > f = (xfs_sb_field_t)xfs_lowbit64((__uint64_t)fields);
> > first = xfs_sb_info[f].offset;
> > @@ -835,6 +873,14 @@ reread:
> > */
> > xfs_sb_from_disk(&mp->m_sb, XFS_BUF_TO_SBP(bp));
> >
> > + if (sbp->sb_qflags & XFS_OQUOTA_ENFD)
> > + sbp->sb_qflags |= (sbp->sb_qflags & XFS_PQUOTA_ACCT) ?
> > + XFS_PQUOTA_ENFD : XFS_GQUOTA_ENFD;
> > + if (sbp->sb_qflags & XFS_OQUOTA_CHKD)
> > + sbp->sb_qflags |= (sbp->sb_qflags & XFS_PQUOTA_ACCT) ?
> > + XFS_PQUOTA_CHKD : XFS_GQUOTA_CHKD;
> > + sbp->sb_qflags &= ~(XFS_OQUOTA_ENFD | XFS_OQUOTA_CHKD);
>
> and that as xfs_sb_qflags_from_disk()....
ok, will do.
>
> > +
> > /*
> > * We must be able to do sector-sized and sector-aligned IO.
> > */
> > diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c
> > index f5f9925..de7ecbd 100644
> > --- a/fs/xfs/xfs_qm.c
> > +++ b/fs/xfs/xfs_qm.c
> > @@ -299,8 +299,10 @@ xfs_qm_mount_quotas(
> > */
> > if (!XFS_IS_UQUOTA_ON(mp))
> > mp->m_qflags &= ~XFS_UQUOTA_CHKD;
> > - if (!(XFS_IS_GQUOTA_ON(mp) || XFS_IS_PQUOTA_ON(mp)))
> > - mp->m_qflags &= ~XFS_OQUOTA_CHKD;
> > + if (!XFS_IS_GQUOTA_ON(mp))
> > + mp->m_qflags &= ~XFS_GQUOTA_CHKD;
> > + if (!XFS_IS_PQUOTA_ON(mp))
> > + mp->m_qflags &= ~XFS_PQUOTA_CHKD;
>
> Order is user, group, project in the processing....
>
> > diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c
> > index b03b2ab..5e51227 100644
> > --- a/fs/xfs/xfs_qm_syscalls.c
> > +++ b/fs/xfs/xfs_qm_syscalls.c
> > @@ -117,11 +117,11 @@ xfs_qm_scall_quotaoff(
> > }
> > if (flags & XFS_GQUOTA_ACCT) {
> > dqtype |= XFS_QMOPT_GQUOTA;
> > - flags |= (XFS_OQUOTA_CHKD | XFS_OQUOTA_ENFD);
> > + flags |= (XFS_GQUOTA_CHKD | XFS_GQUOTA_ENFD);
> > inactivate_flags |= XFS_GQUOTA_ACTIVE;
> > } else if (flags & XFS_PQUOTA_ACCT) {
> > dqtype |= XFS_QMOPT_PQUOTA;
> > - flags |= (XFS_OQUOTA_CHKD | XFS_OQUOTA_ENFD);
> > + flags |= (XFS_PQUOTA_CHKD | XFS_PQUOTA_ENFD);
> > inactivate_flags |= XFS_PQUOTA_ACTIVE;
> > }
>
> Again, u/g/p order...
>
> >
> > @@ -335,14 +335,14 @@ xfs_qm_scall_quotaon(
> > * quota acct on ondisk without m_qflags' knowing.
> > */
> > if (((flags & XFS_UQUOTA_ACCT) == 0 &&
> > - (mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT) == 0 &&
> > - (flags & XFS_UQUOTA_ENFD))
> > - ||
> > + (mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT) == 0 &&
> > + (flags & XFS_UQUOTA_ENFD)) ||
> > ((flags & XFS_PQUOTA_ACCT) == 0 &&
> > - (mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT) == 0 &&
> > - (flags & XFS_GQUOTA_ACCT) == 0 &&
> > - (mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) == 0 &&
> > - (flags & XFS_OQUOTA_ENFD))) {
> > + (mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT) == 0 &&
> > + (flags & XFS_PQUOTA_ENFD)) ||
> > + ((flags & XFS_GQUOTA_ACCT) == 0 &&
> > + (mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) == 0 &&
> > + (flags & XFS_GQUOTA_ENFD))) {
> > xfs_debug(mp,
> > "%s: Can't enforce without acct, flags=%x sbflags=%x\n",
> > __func__, flags, mp->m_sb.sb_qflags);
>
> And now u/p/g order. That's a little confusing - let's try to keep
> the ordering the same throughout the code...
Sure, will do
>
> > @@ -776,9 +776,12 @@ xfs_qm_scall_getquota(
> > * gets turned off. No need to confuse the user level code,
> > * so return zeroes in that case.
> > */
> > - if ((!XFS_IS_UQUOTA_ENFORCED(mp) && dqp->q_core.d_flags == XFS_DQ_USER) ||
> > - (!XFS_IS_OQUOTA_ENFORCED(mp) &&
> > - (dqp->q_core.d_flags & (XFS_DQ_PROJ | XFS_DQ_GROUP)))) {
> > + if ((!XFS_IS_UQUOTA_ENFORCED(mp) &&
> > + dqp->q_core.d_flags == XFS_DQ_USER) ||
> > + (!XFS_IS_PQUOTA_ENFORCED(mp) &&
> > + dqp->q_core.d_flags == XFS_DQ_PROJ) ||
> > + (!XFS_IS_GQUOTA_ENFORCED(mp) &&
> > + dqp->q_core.d_flags == XFS_DQ_GROUP)) {
> > dst->d_btimer = 0;
> > dst->d_itimer = 0;
> > dst->d_rtbtimer = 0;
>
> Same here - it's u/p/g order rather than u/g/p. Can you fix up all
> the other cases so they are all in the same u/g/p order?
>
> > diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h
> > index c38068f..0596860 100644
> > --- a/fs/xfs/xfs_quota.h
> > +++ b/fs/xfs/xfs_quota.h
> > @@ -161,28 +161,43 @@ typedef struct xfs_qoff_logformat {
> > #define XFS_GQUOTA_ACCT 0x0040 /* group quota accounting ON */
> >
> > /*
> > + * Start differentiating group quota and project quota using
> > + * distinct flags, instead of using the combined OQUOTA flags.
> > + *
> > + * Conversion to and from the combined OQUOTA flag (if necessary)
> > + * is done only in xfs_readsb() and xfs_sb_to_disk()
>
> Try to describe the meaning of the flags, not the process you are
> using to change the code. Hence I think, only the second paragraph
> is needed here. Also, based on my comments above, conversion is
> done in xfs_sb_qflags_to_disk() and xfs_sb_qflags_from_disk()....
Sure. will do.
>
> Cheers,
>
> Dave.
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH v9 3/6] xfs: Add pquota fields where gquota is used.
2013-06-24 8:00 ` Dave Chinner
@ 2013-06-24 22:33 ` Chandra Seetharaman
2013-06-24 23:25 ` Chandra Seetharaman
1 sibling, 0 replies; 28+ messages in thread
From: Chandra Seetharaman @ 2013-06-24 22:33 UTC (permalink / raw)
To: Dave Chinner; +Cc: xfs
On Mon, 2013-06-24 at 18:00 +1000, Dave Chinner wrote:
> On Sun, Jun 23, 2013 at 09:48:24PM -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.
>
> Formatting is a bit off there.
>
will fix.
> ....
>
> > @@ -949,21 +950,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;
> > + }
> > xfs_dqunlock(dqp);
>
> FWIW, this is one of the reasons I mentioned being consistent about
> order of quota processing being u/g/p - that's the lock ordering we
> have to follow when locking multiple dquots.
>
> > @@ -559,8 +596,13 @@ xfs_qm_dqattach_locked(
> > * 100% all the time. It is just a hint, and this will
> > * succeed in general.
> > */
> > - if (ip->i_udquot->q_gdquot != ip->i_gdquot)
> > - xfs_qm_dqattach_grouphint(ip->i_udquot, ip->i_gdquot);
> > + if (XFS_IS_GQUOTA_ON(mp) &&
> > + ip->i_udquot->q_gdquot != ip->i_gdquot)
> > + xfs_qm_dqattach_hint(ip, XFS_DQ_GROUP);
> > +
> > + if (XFS_IS_PQUOTA_ON(mp) &&
> > + ip->i_udquot->q_pdquot != ip->i_pdquot)
> > + xfs_qm_dqattach_hint(ip, XFS_DQ_PROJ);
>
> Why do we need the XFS_IS_GQUOTA_ON/XFS_IS_PQUOTA_ON checks there?
> If group quotas are not on, then both the hint and in the
> inode pointers to the group dquot will be NULL, and therefore equal?
> i.e. we don't need to even check if quotas are enabled here...
ok.
>
> Indeed, why pass (ip, quota type) to xfs_qm_dqattach_hint()? why not
> just pass the locations directly like:
>
> xfs_qm_dqattach_hint(&ip->i_udquot->q_pdquot,
> ip->i_pdquot):
will change.
>
> > @@ -1423,6 +1484,15 @@ xfs_qm_init_quotainos(
> > if (error)
> > goto error_rele;
> > }
> > + /* Use gquotino for now */
>
> /* XXX: Use 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;
> > + }
> .....
> > @@ -1444,17 +1514,26 @@ xfs_qm_init_quotainos(
> >
> > flags &= ~XFS_QMOPT_SBVERSION;
> > }
> > - if (XFS_IS_OQUOTA_ON(mp) && gip == NULL) {
> > - flags |= (XFS_IS_GQUOTA_ON(mp) ?
> > - XFS_QMOPT_GQUOTA : XFS_QMOPT_PQUOTA);
> > + if (XFS_IS_GQUOTA_ON(mp) && gip == NULL) {
> > error = xfs_qm_qino_alloc(mp, &gip,
> > - sbflags | XFS_SB_GQUOTINO, flags);
> > + sbflags | XFS_SB_GQUOTINO,
> > + flags | XFS_QMOPT_GQUOTA);
> > + if (error)
> > + goto error_rele;
> > +
> > + flags &= ~XFS_QMOPT_SBVERSION;
> > + }
> > + if (XFS_IS_PQUOTA_ON(mp) && pip == NULL) {
> > + error = xfs_qm_qino_alloc(mp, &pip,
> > + sbflags | XFS_SB_GQUOTINO,
> > + flags | XFS_QMOPT_PQUOTA);
>
> /* XXX: Use gquotino for now */
>
> .....
>
> > @@ -1958,13 +2057,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);
> > + }
> > }
>
> 3 dquots can be modified in transactions that call this function
> now, not 2. That means transaction reservations for dquots need to
> be increased by a dquot in size....
>
> > @@ -107,18 +111,20 @@ extern void xfs_trans_mod_dquot(struct xfs_trans *,
> > struct xfs_dquot *, uint, long);
> > extern int xfs_trans_reserve_quota_bydquots(struct xfs_trans *,
> > struct xfs_mount *, struct xfs_dquot *,
> > - struct xfs_dquot *, long, long, uint);
> > + struct xfs_dquot *, struct xfs_dquot *,
> > + long, long, uint);
> > extern void xfs_trans_dqjoin(struct xfs_trans *, struct xfs_dquot *);
> > extern void xfs_trans_log_dquot(struct xfs_trans *, struct xfs_dquot *);
> >
> > /*
> > - * 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_PRJ,
> > XFS_QM_TRANS_DQTYPES
> > };
> > #define XFS_QM_TRANS_MAXDQS 2
>
> OK, that works, but I still don't see anything about dquot
> transaction reservations (i.e. XFS_DQUOT_LOGRES()) in this patch.
> It defines the log space resservation for dquots being modified in a
> transaction and we just bumped it by one for all transactions that
> do block allocation or freeing.
>
> Actually, I suspect that it is already wrong because it currently
> reserves space for 3 dquots yet a chown operation can modify both
> ATTR_UID and ATTR_GID at the same time. That will therefore modify
> {old, new} x {udq, gdq}, and so we've got 4 dquots being modified.
> Are there any cases where we might do {old, new} x {udq, gdq} + pdq
> or {old, new} x {udq, gdq, pdq}, and hence need the reservation to
> be 5 or 6 dquots?
>
> <dig, ferret, dig, dig, blow away dust, ferret some more, dig, dig>
>
> Indeed, the XFS_DQUOT_LOGRES() definition and comment around it is
> unchanged from when it was first introduced in 1996. So whatever the
> limitations on dquots in the one transaction are, they go back to
> what was limited by Irix, not Linux....
>
> And I just learnt something interesting - XFS on Irix only supported
> user quota and project quota, there was no Irix group quota at all
> prior to the linux port being completed. Group quotas weren't
> implemented on Linux until well after the port to linux was out
> there in 2001:
>
> http://oss.sgi.com/cgi-bin/gitweb.cgi?p=archive/xfs-import.git;a=commit;h=749b2bf3ed5ff064efd69370e6b31ea44c4a78a6
>
> And that commit basically swapped the project ID support for group
> quota support (i.e. no more project quota!), and that meant XFS at
> this point in time was not on-disk compatible between Irix and Linux
> if you used project quotas on Irix or group quotas on Linux. But
> because most of the code was common, the LInux code didn't change
> the XFS_DQUOT_LOGRES() value which was defined at 3. And this
> comment above xfs_trans_dqlockedjoin() is modified in that commit
> like so:
>
> @@ -303,8 +303,8 @@ xfs_trans_mod_dquot(
> /*
> * Given an array of dqtrx structures, lock all the dquots associated
> * and join them to the transaction, provided they have been modified.
> - * We know that the highest number of dquots (of one type - usr OR prj),
> - * involved in a transaction is 2 and that both usr and prj combined - 3.
> + * We know that the highest number of dquots (of one type - usr OR grp),
> + * involved in a transaction is 2 and that both usr and grp combined - 3.
> * So, we don't attempt to make this very generic.
> */
>
> It was a search and replace that modified the comment, leaving the
> value unchanged and, as such, incorrect.
>
> IOWs, XFS_DQUOT_LOGRES() was defined on Irix where a chown call
> could only change the UID. Hence there's only two dquots modified
> in that operation and if blocks needed to be allocated/freed during
> that setattr operation the project dquot would need to be modified
> as well. So, there's the reason for it being defined as 3 dquots -
> no support for group quota at all, despite what the comments say....
>
> Hence I think XFS_DQUOT_LOGRES() actually needs to reserve space for
> 5 dquots that can be modified in a transaction on Linux. i.e. {old,
> new} x {udq, gdq} + pdq, and that really needs a patch of it's own.
Nice explanation. Thanks a lot for digging into this.
I replied to your earlier message in the previous revision
(http://oss.sgi.com/archives/xfs/2013-06/msg00295.html), and didn't get
any response. So, assumed my approach is correct.
>
> Chandra, do you want me to write that patch and commit message?
After your explanation the change looks very simple and straight
forward. But, I do not think I can write a commit message including all
the rationale :)
Please go ahead and provide a pa
> Cheers,
>
> Dave.
>
> PS: if anyone was wondering - it took about 3 hours of code
> archaeology to pull that information out of the archives.
>
> PPS: FWIW, project quota support wasn't reintroduced until 2005
> where the differences between Irix and Linux were re-unified at the
> source level via the "OQUOTA" names we have now.
>
> http://oss.sgi.com/cgi-bin/gitweb.cgi?p=archive/xfs-import.git;a=commit;h=0ab041f659d7d51489a026b16d83ffddc80285bd
>
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH v9 1/6] xfs: Move code around and remove typedefs
2013-06-24 21:36 ` Ben Myers
@ 2013-06-24 23:23 ` Chandra Seetharaman
0 siblings, 0 replies; 28+ messages in thread
From: Chandra Seetharaman @ 2013-06-24 23:23 UTC (permalink / raw)
To: Ben Myers; +Cc: xfs
On Mon, 2013-06-24 at 16:36 -0500, Ben Myers wrote:
> Hi Chandra,
>
> On Sun, Jun 23, 2013 at 09:48:22PM -0500, Chandra Seetharaman wrote:
> > Removed some typedefs, defined new functions, made some code clean up all in
> > preparation of the series.
> >
> > No functional changes.
> >
> > Signed-off-by: Chandra Seetharaman <sekharan@us.ibm.com>
>
> As Dave mentioned, there are a few categories of changes that would probably be
> better as separate patches. I count 6:
>
> 1) the addition of xfs_is_quota_inode
>
> 2) conversion of XFS_DQUOT_TREE macro to xfs_dquot_tree inlined function
>
> 3) addition of xfs_dq_to_quota_inode
>
> 4) cleanups in xfs_dquot.c (xfs_qm_quotacheck,xfs_qm_init_quotainos,
> xfs_qm_vop_dqalloc,xfs_qm_vop_chown_reserve) and xfs_trans_dquot.c
> (xfs_trans_reserve_quota_bydquots)
>
> 5) changes to struct xfs_quotainfo. I don't have an aversion to the comments
> in the structure. I'm guessing that you updated from xfs_inode_t to
> struct xfs_inode and then ran into an 80 column issue later in the
> structure. It'd be nice to have the entries all line up, but I think
> your compromise is fine. Might have been better off touching only
> the quota inodes and leaving the rest, but... style.
>
> 6) add dqtypes enum, make an array in xfs_dquot_acct, update
> xfs_trans_dup_dqinfo. Now we have a two dimensional array in there, and
> I wonder if it would be better if it were more strongly typed. e.g.
>
> tp->t_dqinfo->dq_type[j]->dqt_ents[i]
>
> (or something)
I will repost based on these suggestions.
<snip>
> > @@ -1697,14 +1695,14 @@ xfs_qm_vop_dqalloc(
> > * holding ilock.
> > */
> > xfs_iunlock(ip, lockflags);
> > - if ((error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t) uid,
> > + error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t) uid,
> > XFS_DQ_USER,
> > XFS_QMOPT_DQALLOC |
> > XFS_QMOPT_DOWARN,
> > - &uq))) {
> > - ASSERT(error != ENOENT);
> > + &uq);
> > + ASSERT(error != ENOENT);
>
> You have a series of these asserts which used to be in the error case taken out
> of the error case. Clearly the assertion is still true when error == 0... but
> I tend to prefer that it still be in the error curlies. A silly style thing
> which I welcome you to reject with prejudice.
This way I avoided a set of curly-braces for the error case. thats all.
>
<snip>
> > @@ -113,7 +111,9 @@ 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 < XFS_QM_TRANS_DQTYPES; j++) {
> > + oqa = otp->t_dqinfo->dqs[j];
> > + nqa = ntp->t_dqinfo->dqs[j];
> > for (i = 0; i < XFS_QM_TRANS_MAXDQS; i++) {
> > if (oqa[i].qt_dquot == NULL)
> > break;
> > @@ -138,8 +138,6 @@ xfs_trans_dup_dqinfo(
> > oq->qt_ino_res = oq->qt_ino_res_used;
> >
>
> Could clean up this extra line...
will do
>
>
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH v9 3/6] xfs: Add pquota fields where gquota is used.
2013-06-24 8:00 ` Dave Chinner
2013-06-24 22:33 ` Chandra Seetharaman
@ 2013-06-24 23:25 ` Chandra Seetharaman
2013-06-25 5:33 ` Dave Chinner
1 sibling, 1 reply; 28+ messages in thread
From: Chandra Seetharaman @ 2013-06-24 23:25 UTC (permalink / raw)
To: Dave Chinner; +Cc: xfs
On Mon, 2013-06-24 at 18:00 +1000, Dave Chinner wrote:
<snip>
> > @@ -559,8 +596,13 @@ xfs_qm_dqattach_locked(
> > * 100% all the time. It is just a hint, and this will
> > * succeed in general.
> > */
> > - if (ip->i_udquot->q_gdquot != ip->i_gdquot)
> > - xfs_qm_dqattach_grouphint(ip->i_udquot, ip->i_gdquot);
> > + if (XFS_IS_GQUOTA_ON(mp) &&
> > + ip->i_udquot->q_gdquot != ip->i_gdquot)
> > + xfs_qm_dqattach_hint(ip, XFS_DQ_GROUP);
> > +
> > + if (XFS_IS_PQUOTA_ON(mp) &&
> > + ip->i_udquot->q_pdquot != ip->i_pdquot)
> > + xfs_qm_dqattach_hint(ip, XFS_DQ_PROJ);
>
> Why do we need the XFS_IS_GQUOTA_ON/XFS_IS_PQUOTA_ON checks there?
> If group quotas are not on, then both the hint and in the
> inode pointers to the group dquot will be NULL, and therefore equal?
> i.e. we don't need to even check if quotas are enabled here...
>
> Indeed, why pass (ip, quota type) to xfs_qm_dqattach_hint()? why not
> just pass the locations directly like:
>
> xfs_qm_dqattach_hint(&ip->i_udquot->q_pdquot,
> ip->i_pdquot):
>
Just looked at xfs_qm_dqattach_hint(), it grabs the dqlock of
ip->i_udquot, which means I have to have i_udquot also as another
parameter.
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH v9 2/6] xfs: Remove incore use of XFS_OQUOTA_ENFD and XFS_OQUOTA_CHKD
2013-06-24 22:25 ` Chandra Seetharaman
@ 2013-06-25 5:32 ` Dave Chinner
0 siblings, 0 replies; 28+ messages in thread
From: Dave Chinner @ 2013-06-25 5:32 UTC (permalink / raw)
To: Chandra Seetharaman; +Cc: xfs
On Mon, Jun 24, 2013 at 05:25:24PM -0500, Chandra Seetharaman wrote:
> On Mon, 2013-06-24 at 15:59 +1000, Dave Chinner wrote:
> > On Sun, Jun 23, 2013 at 09:48:23PM -0500, Chandra Seetharaman wrote:
> > > Remove all incore use of XFS_OQUOTA_ENFD and XFS_OQUOTA_CHKD. Instead,
> > > start using XFS_GQUOTA_.* XFS_PQUOTA_.* counterparts for GQUOTA and
> > > PQUOTA respectively.
> > >
> > > On-disk copy still uses XFS_OQUOTA_ENFD and XFS_OQUOTA_CHKD.
> > >
> > > Read and write of the superblock does the conversion from *OQUOTA*
> > > to *[PG]QUOTA*.
> > >
> > > Signed-off-by: Chandra Seetharaman <sekharan@us.ibm.com>
> > > ---
> > > fs/xfs/xfs_mount.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
> > > fs/xfs/xfs_qm.c | 9 ++++++---
> > > fs/xfs/xfs_qm_syscalls.c | 39 +++++++++++++++++++++------------------
> > > fs/xfs/xfs_quota.h | 42 ++++++++++++++++++++++++++++--------------
> > > fs/xfs/xfs_quotaops.c | 6 ++++--
> > > fs/xfs/xfs_super.c | 16 ++++++++--------
> > > fs/xfs/xfs_trans_dquot.c | 4 ++--
> > > 7 files changed, 115 insertions(+), 47 deletions(-)
> > >
> > > diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
> > > index 6a19434..e2e14cb 100644
> > > --- a/fs/xfs/xfs_mount.c
> > > +++ b/fs/xfs/xfs_mount.c
> > > @@ -336,6 +336,14 @@ xfs_mount_validate_sb(
> > > return XFS_ERROR(EWRONGFS);
> > > }
> > >
> > > + if ((sbp->sb_qflags & (XFS_OQUOTA_ENFD | XFS_OQUOTA_CHKD)) &&
> > > + (sbp->sb_qflags & (XFS_PQUOTA_ENFD | XFS_GQUOTA_ENFD |
> > > + XFS_PQUOTA_CHKD | XFS_GQUOTA_CHKD))) {
> > > + xfs_notice(mp,
> > > +"Super block has XFS_OQUOTA bits along with XFS_PQUOTA and/or XFS_GQUOTA bits.\n");
> > > + return XFS_ERROR(EFSCORRUPTED);
> > > + }
> > > +
> > > /*
> > > * Version 5 superblock feature mask validation. Reject combinations the
> > > * kernel cannot support up front before checking anything else. For
> > > @@ -622,6 +630,35 @@ xfs_sb_from_disk(
> > > to->sb_lsn = be64_to_cpu(from->sb_lsn);
> > > }
> > >
> > > +static inline void
> > > +xfs_handle_quota_to_disk(
> > > + xfs_dsb_t *to,
> > > + xfs_sb_t *from,
> > > + __int64_t *fields)
> >
> > An "XFS handle" has meaning in the namespace (i.e. an XFS filehandle
> > as used in xfs_ioctl.c and defined in xfs_fs.h, so this is not a
> > good name.
> >
> > Realistically, xfs_sb_qflags_to_disk() is more appropriate for it's
> > function....
>
> I agree with your "handle" comment.
>
> As you can see in patch 4/6, PQUOTINO logic is also added to this
> function. Can you suggest a name inclusive of that ?
xfs_sb_quota_to/from_disk()?
Cheers,
Dave.
--
Dave Chinner
david@fromorbit.com
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH v9 3/6] xfs: Add pquota fields where gquota is used.
2013-06-24 23:25 ` Chandra Seetharaman
@ 2013-06-25 5:33 ` Dave Chinner
0 siblings, 0 replies; 28+ messages in thread
From: Dave Chinner @ 2013-06-25 5:33 UTC (permalink / raw)
To: Chandra Seetharaman; +Cc: xfs
On Mon, Jun 24, 2013 at 06:25:04PM -0500, Chandra Seetharaman wrote:
> On Mon, 2013-06-24 at 18:00 +1000, Dave Chinner wrote:
>
> <snip>
> > > @@ -559,8 +596,13 @@ xfs_qm_dqattach_locked(
> > > * 100% all the time. It is just a hint, and this will
> > > * succeed in general.
> > > */
> > > - if (ip->i_udquot->q_gdquot != ip->i_gdquot)
> > > - xfs_qm_dqattach_grouphint(ip->i_udquot, ip->i_gdquot);
> > > + if (XFS_IS_GQUOTA_ON(mp) &&
> > > + ip->i_udquot->q_gdquot != ip->i_gdquot)
> > > + xfs_qm_dqattach_hint(ip, XFS_DQ_GROUP);
> > > +
> > > + if (XFS_IS_PQUOTA_ON(mp) &&
> > > + ip->i_udquot->q_pdquot != ip->i_pdquot)
> > > + xfs_qm_dqattach_hint(ip, XFS_DQ_PROJ);
> >
> > Why do we need the XFS_IS_GQUOTA_ON/XFS_IS_PQUOTA_ON checks there?
> > If group quotas are not on, then both the hint and in the
> > inode pointers to the group dquot will be NULL, and therefore equal?
> > i.e. we don't need to even check if quotas are enabled here...
> >
> > Indeed, why pass (ip, quota type) to xfs_qm_dqattach_hint()? why not
> > just pass the locations directly like:
> >
> > xfs_qm_dqattach_hint(&ip->i_udquot->q_pdquot,
> > ip->i_pdquot):
> >
>
> Just looked at xfs_qm_dqattach_hint(), it grabs the dqlock of
> ip->i_udquot, which means I have to have i_udquot also as another
> parameter.
Ah, it does too. Never mind, leave it as it is then. :)
Cheers,
Dave.
--
Dave Chinner
david@fromorbit.com
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH v9 4/6] xfs: Start using pquotaino from the superblock.
2013-06-24 2:48 ` [PATCH v9 4/6] xfs: Start using pquotaino from the superblock Chandra Seetharaman
@ 2013-06-25 6:31 ` Dave Chinner
2013-07-01 15:50 ` Chandra Seetharaman
0 siblings, 1 reply; 28+ messages in thread
From: Dave Chinner @ 2013-06-25 6:31 UTC (permalink / raw)
To: Chandra Seetharaman; +Cc: xfs
On Sun, Jun 23, 2013 at 09:48:25PM -0500, Chandra Seetharaman wrote:
> Start using pquotino and define a macro to check if the
> superblock has pquotino.
>
> Keep backward compatibilty by alowing mount of older superblock
> with no separate pquota inode.
>
> Signed-off-by: Chandra Seetharaman <sekharan@us.ibm.com>
> ---
> fs/xfs/xfs_fsops.c | 3 +-
> fs/xfs/xfs_mount.c | 51 +++++++++++++++++++++++++++++++--------
> fs/xfs/xfs_qm.c | 22 +++++++++--------
> fs/xfs/xfs_qm_syscalls.c | 24 ++++++++++++++++--
> fs/xfs/xfs_quota.h | 8 ------
> fs/xfs/xfs_sb.h | 16 +++++++++++-
> fs/xfs/xfs_super.c | 14 ++++++----
> include/uapi/linux/dqblk_xfs.h | 1 +
> 8 files changed, 99 insertions(+), 40 deletions(-)
>
> diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
> index 614eb0c..3bf05f4 100644
> --- a/fs/xfs/xfs_fsops.c
> +++ b/fs/xfs/xfs_fsops.c
> @@ -501,7 +501,8 @@ xfs_growfs_data_private(
> error, agno);
> break;
> }
> - xfs_sb_to_disk(XFS_BUF_TO_SBP(bp), &mp->m_sb, XFS_SB_ALL_BITS);
> + xfs_sb_to_disk(XFS_BUF_TO_SBP(bp), &mp->m_sb,
> + xfs_sb_all_bits(&mp->m_sb));
I think you could still pass XFS_SB_ALL_BITS to xfs_sb_to_disk(),
and do the XFS_SB_PQUOTINO filtering inside xfs_sb_quota_to_disk().
Actually xfs_sb_all_bits() is only used here, and it seems to me
that it is not necessary as we do a pquota support check inside
xfs_sb_to_disk() and can handle this in that place...
>
> /*
> * If we get an error writing out the alternate superblocks,
> diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
> index e2e14cb..bb7b23e 100644
> --- a/fs/xfs/xfs_mount.c
> +++ b/fs/xfs/xfs_mount.c
> @@ -336,12 +336,17 @@ xfs_mount_validate_sb(
> return XFS_ERROR(EWRONGFS);
> }
>
> - if ((sbp->sb_qflags & (XFS_OQUOTA_ENFD | XFS_OQUOTA_CHKD)) &&
> - (sbp->sb_qflags & (XFS_PQUOTA_ENFD | XFS_GQUOTA_ENFD |
> - XFS_PQUOTA_CHKD | XFS_GQUOTA_CHKD))) {
> - xfs_notice(mp,
> -"Super block has XFS_OQUOTA bits along with XFS_PQUOTA and/or XFS_GQUOTA bits.\n");
> - return XFS_ERROR(EFSCORRUPTED);
> + if (xfs_sb_version_has_pquota(sbp)) {
> + if (sbp->sb_qflags & (XFS_OQUOTA_ENFD | XFS_OQUOTA_CHKD)) {
> + xfs_notice(mp,
> + "Version 5 of Super block has XFS_OQUOTA bits.\n");
> + return XFS_ERROR(EFSCORRUPTED);
> + }
> + } else if (sbp->sb_qflags & (XFS_PQUOTA_ENFD | XFS_GQUOTA_ENFD |
> + XFS_PQUOTA_CHKD | XFS_GQUOTA_CHKD)) {
> + xfs_notice(mp,
> +"Superblock earlier than Version 5 has XFS_[PQ]UOTA_{ENFD|CHKD} bits.\n");
> + return XFS_ERROR(EFSCORRUPTED);
[ xfs_alert() for those, I think. ]
> @@ -638,6 +643,13 @@ xfs_handle_quota_to_disk(
> {
> __uint16_t qflags = from->sb_qflags;
>
> + /*
> + * We need to do these manipilations only if we are working
> + * with an older version of on-disk superblock.
> + */
> + if (xfs_sb_version_has_pquota(from))
> + return;
> +
> if (*fields & XFS_SB_QFLAGS) {
> /*
> * The in-core version of sb_qflags do not have
xfs_sb_all_bits() does:
if (xfs_sb_version_has_pquota(sbp))
return XFS_SB_ALL_BITS;
return XFS_SB_ALL_BITS & ~XFS_SB_PQUOTINO;
which means that we enter xfs_handle_quota_to_disk() with
XFS_SB_ALL_BITS intact for the pquota case, but without it in the
non-pquota case. Hence if we don't have pquota set, we continue
onwards and....
> @@ -657,6 +669,10 @@ xfs_handle_quota_to_disk(
> to->sb_qflags = cpu_to_be16(qflags);
> *fields &= ~XFS_SB_QFLAGS;
> }
> + if (*fields & XFS_SB_PQUOTINO) {
> + to->sb_gquotino = cpu_to_be64(from->sb_pquotino);
> + *fields &= ~XFS_SB_PQUOTINO;
> + }
We will never do this because we've already cleared XFS_SB_PQUOTINO
before we entered xfs_sb_to_disk(). That doesn't seem right to me...
> @@ -1524,8 +1524,10 @@ xfs_qm_init_quotainos(
> flags &= ~XFS_QMOPT_SBVERSION;
> }
> if (XFS_IS_PQUOTA_ON(mp) && pip == NULL) {
> + if (!xfs_sb_version_has_pquota(&mp->m_sb))
> + sbflags &= ~XFS_SB_GQUOTINO;
That's taken me a while to work out - it needs a comment explaining
why XFS_SB_GQUOTINO is being cleared here.
> error = xfs_qm_qino_alloc(mp, &pip,
> - sbflags | XFS_SB_GQUOTINO,
> + sbflags | XFS_SB_PQUOTINO,
> flags | XFS_QMOPT_PQUOTA);
> if (error)
> goto error_rele;
> diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c
> index ed7cd55..d664a2d 100644
> --- a/fs/xfs/xfs_qm_syscalls.c
> +++ b/fs/xfs/xfs_qm_syscalls.c
> @@ -201,8 +201,7 @@ xfs_qm_scall_quotaoff(
> /*
> * If quotas is completely disabled, close shop.
> */
> - if (((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_SET1) ||
> - ((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_SET2)) {
> + if ((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_ALL) {
> mutex_unlock(&q->qi_quotaofflock);
> xfs_qm_destroy_quotainfo(mp);
> return (0);
This makes the assumption that userspace passes all three quota
types into the kernel in a single quota off call as the only way to
turn quotas off completely. What happens if they are turned off one
at a time? Shouldn't we detect when no more quotas are actually
enabled and then do this?
Cheers,
Dave.
--
Dave Chinner
david@fromorbit.com
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH v9 5/6] xfs: Add proper versioning support to fs_quota_stat
2013-06-24 2:48 ` [PATCH v9 5/6] xfs: Add proper versioning support to fs_quota_stat Chandra Seetharaman
@ 2013-06-25 6:43 ` Dave Chinner
2013-06-25 22:36 ` Chandra Seetharaman
0 siblings, 1 reply; 28+ messages in thread
From: Dave Chinner @ 2013-06-25 6:43 UTC (permalink / raw)
To: Chandra Seetharaman; +Cc: xfs
On Sun, Jun 23, 2013 at 09:48:26PM -0500, Chandra Seetharaman wrote:
> Added appropriate pads and code for backward compatibility.
>
> Copied over the old version as it is different from the newer padded
> version.
>
> New callers of the system call have to set the version of the data
> structure being passed, and kernel will fill as much data as requested.
Is there are test for this? i.e. that the different version
structures return the same information?
>
> Signed-off-by: Chandra Seetharaman <sekharan@us.ibm.com>
> ---
> fs/gfs2/quota.c | 3 --
> fs/quota/quota.c | 49 +++++++++++++++++++++++++++++++++-
> fs/xfs/xfs_qm_syscalls.c | 4 ---
> fs/xfs/xfs_super.c | 5 +--
> include/uapi/linux/dqblk_xfs.h | 57 +++++++++++++++++++++++++++++++++++-----
> 5 files changed, 99 insertions(+), 19 deletions(-)
>
> diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c
> index c7c840e..ca0dccd 100644
> --- a/fs/gfs2/quota.c
> +++ b/fs/gfs2/quota.c
> @@ -1443,9 +1443,6 @@ static int gfs2_quota_get_xstate(struct super_block *sb,
> {
> struct gfs2_sbd *sdp = sb->s_fs_info;
>
> - memset(fqs, 0, sizeof(struct fs_quota_stat));
> - fqs->qs_version = FS_QSTAT_VERSION;
> -
> switch (sdp->sd_args.ar_quota) {
> case GFS2_QUOTA_ON:
> fqs->qs_flags |= (FS_QUOTA_UDQ_ENFD | FS_QUOTA_GDQ_ENFD);
> diff --git a/fs/quota/quota.c b/fs/quota/quota.c
> index c7314f1..ae6526e 100644
> --- a/fs/quota/quota.c
> +++ b/fs/quota/quota.c
> @@ -207,12 +207,57 @@ static int quota_setxstate(struct super_block *sb, int cmd, void __user *addr)
> static int quota_getxstate(struct super_block *sb, void __user *addr)
> {
> struct fs_quota_stat fqs;
> - int ret;
> + struct fs_quota_stat_v1 fqs_v1;
> + int ret, size;
> + void *fqsp;
>
> if (!sb->s_qcop->get_xstate)
> return -ENOSYS;
> +
> + memset(&fqs, 0, sizeof(struct fs_quota_stat));
> + if (copy_from_user(&fqs, addr, 1)) /* just get the version */
> + return -EFAULT;
> +
> + switch (fqs.qs_version) {
> + case FS_QSTAT_VERSION_2:
> + size = FS_QSTAT_V2_SIZE;
> + break;
> + default:
> + fqs.qs_version = FS_QSTAT_VERSION;
> + /* fallthrough */
> + case FS_QSTAT_VERSION:
> + size = FS_QSTAT_V1_SIZE;
> + break;
> + }
> +
> ret = sb->s_qcop->get_xstate(sb, &fqs);
> - if (!ret && copy_to_user(addr, &fqs, sizeof(fqs)))
> + if (ret)
> + return ret;
> +
> + if (fqs.qs_version == FS_QSTAT_VERSION) {
> + fqs_v1.qs_version = fqs.qs_version;
> + fqs_v1.qs_flags = fqs.qs_flags;
> + fqs_v1.qs_pad = 0;
> +
> + fqs_v1.qs_uquota.qfs_ino = fqs.qs_uquota.qfs_ino;
> + fqs_v1.qs_uquota.qfs_nblks = fqs.qs_uquota.qfs_nblks;
> + fqs_v1.qs_uquota.qfs_nextents = fqs.qs_uquota.qfs_nextents;
> +
> + fqs_v1.qs_gquota.qfs_ino = fqs.qs_gquota.qfs_ino;
> + fqs_v1.qs_gquota.qfs_nblks = fqs.qs_gquota.qfs_nblks;
> + fqs_v1.qs_gquota.qfs_nextents = fqs.qs_gquota.qfs_nextents;
> +
> + fqs_v1.qs_incoredqs = fqs.qs_incoredqs;
> + fqs_v1.qs_btimelimit = fqs.qs_btimelimit;
> + fqs_v1.qs_itimelimit = fqs.qs_itimelimit;
> + fqs_v1.qs_rtbtimelimit = fqs.qs_rtbtimelimit;
> + fqs_v1.qs_bwarnlimit = fqs.qs_bwarnlimit;
> + fqs_v1.qs_iwarnlimit = fqs.qs_iwarnlimit;
> + fqsp = &fqs_v1;
> + } else
> + fqsp = &fqs;
> +
> + if (copy_to_user(addr, fqsp, size))
> return -EFAULT;
> return ret;
> }
> diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c
> index d664a2d..1918f48 100644
> --- a/fs/xfs/xfs_qm_syscalls.c
> +++ b/fs/xfs/xfs_qm_syscalls.c
> @@ -420,9 +420,6 @@ xfs_qm_scall_getqstat(
> bool tempgqip = false;
> bool temppqip = false;
>
> - memset(out, 0, sizeof(fs_quota_stat_t));
> -
> - out->qs_version = FS_QSTAT_VERSION;
> if (!xfs_sb_version_hasquota(&mp->m_sb)) {
> out->qs_uquota.qfs_ino = NULLFSINO;
> out->qs_gquota.qfs_ino = NULLFSINO;
> @@ -432,7 +429,6 @@ xfs_qm_scall_getqstat(
> out->qs_flags = (__uint16_t) xfs_qm_export_flags(mp->m_qflags &
> (XFS_ALL_QUOTA_ACCT|
> XFS_ALL_QUOTA_ENFD));
> - out->qs_pad = 0;
> out->qs_uquota.qfs_ino = mp->m_sb.sb_uquotino;
> out->qs_gquota.qfs_ino = mp->m_sb.sb_gquotino;
> if (&out->qs_gquota != &out->qs_pquota)
> diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
> index 1bcc017..ab90539 100644
> --- a/fs/xfs/xfs_super.c
> +++ b/fs/xfs/xfs_super.c
> @@ -554,14 +554,13 @@ xfs_showargs(
> else if (mp->m_qflags & XFS_UQUOTA_ACCT)
> seq_puts(m, "," MNTOPT_UQUOTANOENF);
>
> - /* Either project or group quotas can be active, not both */
> -
> if (mp->m_qflags & XFS_PQUOTA_ACCT) {
> if (mp->m_qflags & XFS_PQUOTA_ENFD)
> seq_puts(m, "," MNTOPT_PRJQUOTA);
> else
> seq_puts(m, "," MNTOPT_PQUOTANOENF);
> - } else if (mp->m_qflags & XFS_GQUOTA_ACCT) {
> + }
> + if (mp->m_qflags & XFS_GQUOTA_ACCT) {
> if (mp->m_qflags & XFS_GQUOTA_ENFD)
> seq_puts(m, "," MNTOPT_GRPQUOTA);
> else
> diff --git a/include/uapi/linux/dqblk_xfs.h b/include/uapi/linux/dqblk_xfs.h
> index f17e3bb..e8ca23b 100644
> --- a/include/uapi/linux/dqblk_xfs.h
> +++ b/include/uapi/linux/dqblk_xfs.h
> @@ -47,6 +47,7 @@
> * 512 bytes.
> */
> #define FS_DQUOT_VERSION 1 /* fs_disk_quota.d_version */
> +
> typedef struct fs_disk_quota {
> __s8 d_version; /* version of this structure */
> __s8 d_flags; /* FS_{USER,PROJ,GROUP}_QUOTA */
> @@ -137,31 +138,73 @@ typedef struct fs_disk_quota {
> * Provides a centralized way to get meta information about the quota subsystem.
> * eg. space taken up for user and group quotas, number of dquots currently
> * incore.
> + * User space caller should set qs_version to the appropriate version
> + * of the fs_quota_stat data structure they are providing. Not providing
> + * a version will be treated as FS_QSTAT_VERSION.
> */
> #define FS_QSTAT_VERSION 1 /* fs_quota_stat.qs_version */
> +#define FS_QSTAT_VERSION_2 2 /* new field qs_pquota; realignment */
>
> /*
> * Some basic information about 'quota files'.
> */
> -typedef struct fs_qfilestat {
> +struct fs_qfilestat_v1 {
> __u64 qfs_ino; /* inode number */
> __u64 qfs_nblks; /* number of BBs 512-byte-blks */
> __u32 qfs_nextents; /* number of extents */
> -} fs_qfilestat_t;
> +};
>
> -typedef struct fs_quota_stat {
> +struct fs_quota_stat_v1 {
> __s8 qs_version; /* version number for future changes */
> __u16 qs_flags; /* FS_QUOTA_{U,P,G}DQ_{ACCT,ENFD} */
> __s8 qs_pad; /* unused */
> - fs_qfilestat_t qs_uquota; /* user quota storage information */
> - fs_qfilestat_t qs_gquota; /* group quota storage information */
> -#define qs_pquota qs_gquota
> + struct fs_qfilestat_v1 qs_uquota; /* user quota information */
> + struct fs_qfilestat_v1 qs_gquota; /* group quota information */
> __u32 qs_incoredqs; /* number of dquots incore */
> __s32 qs_btimelimit; /* limit for blks timer */
> __s32 qs_itimelimit; /* limit for inodes timer */
> __s32 qs_rtbtimelimit;/* limit for rt blks timer */
> __u16 qs_bwarnlimit; /* limit for num warnings */
> __u16 qs_iwarnlimit; /* limit for num warnings */
> -} fs_quota_stat_t;
> +};
> +
> +/*
> + * Some basic information about 'quota files'. Version 2.
> + */
> +struct fs_qfilestat {
> + __u64 qfs_ino; /* inode number */
> + __u64 qfs_nblks; /* number of BBs 512-byte-blks */
> + __u32 qfs_nextents; /* number of extents */
> + __u8 qfs_pad[4]; /* pad for 8-byte alignment */
Just pad it as:
__u32 qfs_pad;
So the size of the hole being filled is obvious.
> +};
> +
> +struct fs_quota_stat {
> + __s8 qs_version; /* version for future changes */
> + __u8 qs_pad1; /* pad for 16bit alignment */
> + __u16 qs_flags; /* FS_QUOTA_.* flags */
> + __u8 qs_pad2[4]; /* pad for 8-byte alignment */
Actually, we can reorder this structure so there aren't intermediate
holes like this. The only thing that matters is that the first byte
is the version number. So:
struct fs_quota_stat {
__s8 qs_version; /* version for future changes */
__u8 qs_pad1; /* pad for 16bit alignment */
__u16 qs_flags; /* FS_QUOTA_.* flags */
__u32 qs_incoredqs; /* number of dquots incore */
struct fs_qfilestat qs_uquota; /* user quota information */
struct fs_qfilestat qs_gquota; /* group quota information */
struct fs_qfilestat qs_pquota; /* project quota information */
__s32 qs_btimelimit; /* limit for blks timer */
__s32 qs_itimelimit; /* limit for inodes timer */
__s32 qs_rtbtimelimit;/* limit for rt blks timer */
__u16 qs_bwarnlimit; /* limit for num warnings */
__u16 qs_iwarnlimit; /* limit for num warnings */
__u32 qs_pad2; /* pad for 8-byte alignment */
__u64 qs_pad3[8]; /* for future proofing */
};
Cheers,
Dave.
--
Dave Chinner
david@fromorbit.com
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH v9 6/6] xfs: Use new qs_pquota field in fs_quota_stat for Q_XGETQSTAT
2013-06-24 2:48 ` [PATCH v9 6/6] xfs: Use new qs_pquota field in fs_quota_stat for Q_XGETQSTAT Chandra Seetharaman
@ 2013-06-25 6:45 ` Dave Chinner
0 siblings, 0 replies; 28+ messages in thread
From: Dave Chinner @ 2013-06-25 6:45 UTC (permalink / raw)
To: Chandra Seetharaman; +Cc: xfs
On Sun, Jun 23, 2013 at 09:48:27PM -0500, Chandra Seetharaman wrote:
> For the Q_XGETQSTAT quota command, if the new version of fs_quota_stat
> data structure is used, fill the project quota information.
>
> Signed-off-by: Chandra Seetharaman <sekharan@us.ibm.com>
looks fine.
Cheers,
Dave.
--
Dave Chinner
david@fromorbit.com
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH v9 5/6] xfs: Add proper versioning support to fs_quota_stat
2013-06-25 6:43 ` Dave Chinner
@ 2013-06-25 22:36 ` Chandra Seetharaman
2013-06-26 1:20 ` Dave Chinner
0 siblings, 1 reply; 28+ messages in thread
From: Chandra Seetharaman @ 2013-06-25 22:36 UTC (permalink / raw)
To: Dave Chinner; +Cc: xfs
On Tue, 2013-06-25 at 16:43 +1000, Dave Chinner wrote:
> On Sun, Jun 23, 2013 at 09:48:26PM -0500, Chandra Seetharaman wrote:
> > Added appropriate pads and code for backward compatibility.
> >
> > Copied over the old version as it is different from the newer padded
> > version.
> >
> > New callers of the system call have to set the version of the data
> > structure being passed, and kernel will fill as much data as requested.
>
> Is there are test for this? i.e. that the different version
> structures return the same information?
You want me to add it to xfstests ?
>
> >
> > Signed-off-by: Chandra Seetharaman <sekharan@us.ibm.com>
> > ---
> > fs/gfs2/quota.c | 3 --
> > fs/quota/quota.c | 49 +++++++++++++++++++++++++++++++++-
> > fs/xfs/xfs_qm_syscalls.c | 4 ---
> > fs/xfs/xfs_super.c | 5 +--
> > include/uapi/linux/dqblk_xfs.h | 57 +++++++++++++++++++++++++++++++++++-----
> > 5 files changed, 99 insertions(+), 19 deletions(-)
> >
> > diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c
> > index c7c840e..ca0dccd 100644
> > --- a/fs/gfs2/quota.c
> > +++ b/fs/gfs2/quota.c
> > @@ -1443,9 +1443,6 @@ static int gfs2_quota_get_xstate(struct super_block *sb,
> > {
> > struct gfs2_sbd *sdp = sb->s_fs_info;
> >
> > - memset(fqs, 0, sizeof(struct fs_quota_stat));
> > - fqs->qs_version = FS_QSTAT_VERSION;
> > -
> > switch (sdp->sd_args.ar_quota) {
> > case GFS2_QUOTA_ON:
> > fqs->qs_flags |= (FS_QUOTA_UDQ_ENFD | FS_QUOTA_GDQ_ENFD);
> > diff --git a/fs/quota/quota.c b/fs/quota/quota.c
> > index c7314f1..ae6526e 100644
> > --- a/fs/quota/quota.c
> > +++ b/fs/quota/quota.c
> > @@ -207,12 +207,57 @@ static int quota_setxstate(struct super_block *sb, int cmd, void __user *addr)
> > static int quota_getxstate(struct super_block *sb, void __user *addr)
> > {
> > struct fs_quota_stat fqs;
> > - int ret;
> > + struct fs_quota_stat_v1 fqs_v1;
> > + int ret, size;
> > + void *fqsp;
> >
> > if (!sb->s_qcop->get_xstate)
> > return -ENOSYS;
> > +
> > + memset(&fqs, 0, sizeof(struct fs_quota_stat));
> > + if (copy_from_user(&fqs, addr, 1)) /* just get the version */
> > + return -EFAULT;
> > +
> > + switch (fqs.qs_version) {
> > + case FS_QSTAT_VERSION_2:
> > + size = FS_QSTAT_V2_SIZE;
> > + break;
> > + default:
> > + fqs.qs_version = FS_QSTAT_VERSION;
> > + /* fallthrough */
> > + case FS_QSTAT_VERSION:
> > + size = FS_QSTAT_V1_SIZE;
> > + break;
> > + }
> > +
> > ret = sb->s_qcop->get_xstate(sb, &fqs);
> > - if (!ret && copy_to_user(addr, &fqs, sizeof(fqs)))
> > + if (ret)
> > + return ret;
> > +
> > + if (fqs.qs_version == FS_QSTAT_VERSION) {
> > + fqs_v1.qs_version = fqs.qs_version;
> > + fqs_v1.qs_flags = fqs.qs_flags;
> > + fqs_v1.qs_pad = 0;
> > +
> > + fqs_v1.qs_uquota.qfs_ino = fqs.qs_uquota.qfs_ino;
> > + fqs_v1.qs_uquota.qfs_nblks = fqs.qs_uquota.qfs_nblks;
> > + fqs_v1.qs_uquota.qfs_nextents = fqs.qs_uquota.qfs_nextents;
> > +
> > + fqs_v1.qs_gquota.qfs_ino = fqs.qs_gquota.qfs_ino;
> > + fqs_v1.qs_gquota.qfs_nblks = fqs.qs_gquota.qfs_nblks;
> > + fqs_v1.qs_gquota.qfs_nextents = fqs.qs_gquota.qfs_nextents;
> > +
> > + fqs_v1.qs_incoredqs = fqs.qs_incoredqs;
> > + fqs_v1.qs_btimelimit = fqs.qs_btimelimit;
> > + fqs_v1.qs_itimelimit = fqs.qs_itimelimit;
> > + fqs_v1.qs_rtbtimelimit = fqs.qs_rtbtimelimit;
> > + fqs_v1.qs_bwarnlimit = fqs.qs_bwarnlimit;
> > + fqs_v1.qs_iwarnlimit = fqs.qs_iwarnlimit;
> > + fqsp = &fqs_v1;
> > + } else
> > + fqsp = &fqs;
> > +
> > + if (copy_to_user(addr, fqsp, size))
> > return -EFAULT;
> > return ret;
> > }
> > diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c
> > index d664a2d..1918f48 100644
> > --- a/fs/xfs/xfs_qm_syscalls.c
> > +++ b/fs/xfs/xfs_qm_syscalls.c
> > @@ -420,9 +420,6 @@ xfs_qm_scall_getqstat(
> > bool tempgqip = false;
> > bool temppqip = false;
> >
> > - memset(out, 0, sizeof(fs_quota_stat_t));
> > -
> > - out->qs_version = FS_QSTAT_VERSION;
> > if (!xfs_sb_version_hasquota(&mp->m_sb)) {
> > out->qs_uquota.qfs_ino = NULLFSINO;
> > out->qs_gquota.qfs_ino = NULLFSINO;
> > @@ -432,7 +429,6 @@ xfs_qm_scall_getqstat(
> > out->qs_flags = (__uint16_t) xfs_qm_export_flags(mp->m_qflags &
> > (XFS_ALL_QUOTA_ACCT|
> > XFS_ALL_QUOTA_ENFD));
> > - out->qs_pad = 0;
> > out->qs_uquota.qfs_ino = mp->m_sb.sb_uquotino;
> > out->qs_gquota.qfs_ino = mp->m_sb.sb_gquotino;
> > if (&out->qs_gquota != &out->qs_pquota)
> > diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
> > index 1bcc017..ab90539 100644
> > --- a/fs/xfs/xfs_super.c
> > +++ b/fs/xfs/xfs_super.c
> > @@ -554,14 +554,13 @@ xfs_showargs(
> > else if (mp->m_qflags & XFS_UQUOTA_ACCT)
> > seq_puts(m, "," MNTOPT_UQUOTANOENF);
> >
> > - /* Either project or group quotas can be active, not both */
> > -
> > if (mp->m_qflags & XFS_PQUOTA_ACCT) {
> > if (mp->m_qflags & XFS_PQUOTA_ENFD)
> > seq_puts(m, "," MNTOPT_PRJQUOTA);
> > else
> > seq_puts(m, "," MNTOPT_PQUOTANOENF);
> > - } else if (mp->m_qflags & XFS_GQUOTA_ACCT) {
> > + }
> > + if (mp->m_qflags & XFS_GQUOTA_ACCT) {
> > if (mp->m_qflags & XFS_GQUOTA_ENFD)
> > seq_puts(m, "," MNTOPT_GRPQUOTA);
> > else
> > diff --git a/include/uapi/linux/dqblk_xfs.h b/include/uapi/linux/dqblk_xfs.h
> > index f17e3bb..e8ca23b 100644
> > --- a/include/uapi/linux/dqblk_xfs.h
> > +++ b/include/uapi/linux/dqblk_xfs.h
> > @@ -47,6 +47,7 @@
> > * 512 bytes.
> > */
> > #define FS_DQUOT_VERSION 1 /* fs_disk_quota.d_version */
> > +
> > typedef struct fs_disk_quota {
> > __s8 d_version; /* version of this structure */
> > __s8 d_flags; /* FS_{USER,PROJ,GROUP}_QUOTA */
> > @@ -137,31 +138,73 @@ typedef struct fs_disk_quota {
> > * Provides a centralized way to get meta information about the quota subsystem.
> > * eg. space taken up for user and group quotas, number of dquots currently
> > * incore.
> > + * User space caller should set qs_version to the appropriate version
> > + * of the fs_quota_stat data structure they are providing. Not providing
> > + * a version will be treated as FS_QSTAT_VERSION.
> > */
> > #define FS_QSTAT_VERSION 1 /* fs_quota_stat.qs_version */
> > +#define FS_QSTAT_VERSION_2 2 /* new field qs_pquota; realignment */
> >
> > /*
> > * Some basic information about 'quota files'.
> > */
> > -typedef struct fs_qfilestat {
> > +struct fs_qfilestat_v1 {
> > __u64 qfs_ino; /* inode number */
> > __u64 qfs_nblks; /* number of BBs 512-byte-blks */
> > __u32 qfs_nextents; /* number of extents */
> > -} fs_qfilestat_t;
> > +};
> >
> > -typedef struct fs_quota_stat {
> > +struct fs_quota_stat_v1 {
> > __s8 qs_version; /* version number for future changes */
> > __u16 qs_flags; /* FS_QUOTA_{U,P,G}DQ_{ACCT,ENFD} */
> > __s8 qs_pad; /* unused */
> > - fs_qfilestat_t qs_uquota; /* user quota storage information */
> > - fs_qfilestat_t qs_gquota; /* group quota storage information */
> > -#define qs_pquota qs_gquota
> > + struct fs_qfilestat_v1 qs_uquota; /* user quota information */
> > + struct fs_qfilestat_v1 qs_gquota; /* group quota information */
> > __u32 qs_incoredqs; /* number of dquots incore */
> > __s32 qs_btimelimit; /* limit for blks timer */
> > __s32 qs_itimelimit; /* limit for inodes timer */
> > __s32 qs_rtbtimelimit;/* limit for rt blks timer */
> > __u16 qs_bwarnlimit; /* limit for num warnings */
> > __u16 qs_iwarnlimit; /* limit for num warnings */
> > -} fs_quota_stat_t;
> > +};
> > +
> > +/*
> > + * Some basic information about 'quota files'. Version 2.
> > + */
> > +struct fs_qfilestat {
> > + __u64 qfs_ino; /* inode number */
> > + __u64 qfs_nblks; /* number of BBs 512-byte-blks */
> > + __u32 qfs_nextents; /* number of extents */
> > + __u8 qfs_pad[4]; /* pad for 8-byte alignment */
>
> Just pad it as:
>
> __u32 qfs_pad;
>
will do
> So the size of the hole being filled is obvious.
>
> > +};
> > +
> > +struct fs_quota_stat {
> > + __s8 qs_version; /* version for future changes */
> > + __u8 qs_pad1; /* pad for 16bit alignment */
> > + __u16 qs_flags; /* FS_QUOTA_.* flags */
> > + __u8 qs_pad2[4]; /* pad for 8-byte alignment */
>
> Actually, we can reorder this structure so there aren't intermediate
> holes like this. The only thing that matters is that the first byte
> is the version number. So:
>
> struct fs_quota_stat {
> __s8 qs_version; /* version for future changes */
> __u8 qs_pad1; /* pad for 16bit alignment */
> __u16 qs_flags; /* FS_QUOTA_.* flags */
> __u32 qs_incoredqs; /* number of dquots incore */
> struct fs_qfilestat qs_uquota; /* user quota information */
> struct fs_qfilestat qs_gquota; /* group quota information */
> struct fs_qfilestat qs_pquota; /* project quota information */
> __s32 qs_btimelimit; /* limit for blks timer */
> __s32 qs_itimelimit; /* limit for inodes timer */
> __s32 qs_rtbtimelimit;/* limit for rt blks timer */
> __u16 qs_bwarnlimit; /* limit for num warnings */
> __u16 qs_iwarnlimit; /* limit for num warnings */
> __u32 qs_pad2; /* pad for 8-byte alignment */
> __u64 qs_pad3[8]; /* for future proofing */
> };
>
will do
> Cheers,
>
> Dave.
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH v9 5/6] xfs: Add proper versioning support to fs_quota_stat
2013-06-25 22:36 ` Chandra Seetharaman
@ 2013-06-26 1:20 ` Dave Chinner
0 siblings, 0 replies; 28+ messages in thread
From: Dave Chinner @ 2013-06-26 1:20 UTC (permalink / raw)
To: Chandra Seetharaman; +Cc: xfs
On Tue, Jun 25, 2013 at 05:36:24PM -0500, Chandra Seetharaman wrote:
> On Tue, 2013-06-25 at 16:43 +1000, Dave Chinner wrote:
> > On Sun, Jun 23, 2013 at 09:48:26PM -0500, Chandra Seetharaman wrote:
> > > Added appropriate pads and code for backward compatibility.
> > >
> > > Copied over the old version as it is different from the newer padded
> > > version.
> > >
> > > New callers of the system call have to set the version of the data
> > > structure being passed, and kernel will fill as much data as requested.
> >
> > Is there are test for this? i.e. that the different version
> > structures return the same information?
>
> You want me to add it to xfstests ?
Yes, please. :)
Cheers,
Dave.
--
Dave Chinner
david@fromorbit.com
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH v9 4/6] xfs: Start using pquotaino from the superblock.
2013-06-25 6:31 ` Dave Chinner
@ 2013-07-01 15:50 ` Chandra Seetharaman
2013-07-04 1:12 ` Dave Chinner
0 siblings, 1 reply; 28+ messages in thread
From: Chandra Seetharaman @ 2013-07-01 15:50 UTC (permalink / raw)
To: Dave Chinner; +Cc: xfs
Hi Dave,
I sent this email on 6/25 (just before my reply on 5/6 w.r.t adding the
test to xfstests). Since I didn't get any response from you on this and
got reply on the other one, I concluded that you accepted my
justification/clarification.
I just looked at the archives and do not see my original email :(... but
is intact in my sent folder!!
Please see if my justification below is valid.
Chandra
On Tue, 2013-06-25 at 16:31 +1000, Dave Chinner wrote:
> On Sun, Jun 23, 2013 at 09:48:25PM -0500, Chandra Seetharaman wrote:
> > Start using pquotino and define a macro to check if the
> > superblock has pquotino.
> >
> > Keep backward compatibilty by alowing mount of older superblock
> > with no separate pquota inode.
> >
> > Signed-off-by: Chandra Seetharaman <sekharan@us.ibm.com>
> > ---
> > fs/xfs/xfs_fsops.c | 3 +-
> > fs/xfs/xfs_mount.c | 51 +++++++++++++++++++++++++++++++--------
> > fs/xfs/xfs_qm.c | 22 +++++++++--------
> > fs/xfs/xfs_qm_syscalls.c | 24 ++++++++++++++++--
> > fs/xfs/xfs_quota.h | 8 ------
> > fs/xfs/xfs_sb.h | 16 +++++++++++-
> > fs/xfs/xfs_super.c | 14 ++++++----
> > include/uapi/linux/dqblk_xfs.h | 1 +
> > 8 files changed, 99 insertions(+), 40 deletions(-)
> >
> > diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
> > index 614eb0c..3bf05f4 100644
> > --- a/fs/xfs/xfs_fsops.c
> > +++ b/fs/xfs/xfs_fsops.c
> > @@ -501,7 +501,8 @@ xfs_growfs_data_private(
> > error, agno);
> > break;
> > }
> > - xfs_sb_to_disk(XFS_BUF_TO_SBP(bp), &mp->m_sb, XFS_SB_ALL_BITS);
> > + xfs_sb_to_disk(XFS_BUF_TO_SBP(bp), &mp->m_sb,
> > + xfs_sb_all_bits(&mp->m_sb));
>
> I think you could still pass XFS_SB_ALL_BITS to xfs_sb_to_disk(),
> and do the XFS_SB_PQUOTINO filtering inside xfs_sb_quota_to_disk().
>
> Actually xfs_sb_all_bits() is only used here, and it seems to me
> that it is not necessary as we do a pquota support check inside
> xfs_sb_to_disk() and can handle this in that place...
Yes, this is the only place that uses XFS_SB_ALL_BITS, and the purpose
is to copy over the superblock to secondary.
The change I made ensures that the caller does what is correct. i.e if
it is copying an earlier version of superblock, it does not try to copy
the pquotino, and if it uses the newer version of superblock it copies
over the pquotino.
At some point (in my internal tree) I did have the way you suggested.
But, doing it that way looked like a band-aid/hack, and felt this is the
right way to do it (since the caller should provide appropriate
information to the function).
>
> >
> > /*
> > * If we get an error writing out the alternate superblocks,
> > diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
> > index e2e14cb..bb7b23e 100644
> > --- a/fs/xfs/xfs_mount.c
> > +++ b/fs/xfs/xfs_mount.c
> > @@ -336,12 +336,17 @@ xfs_mount_validate_sb(
> > return XFS_ERROR(EWRONGFS);
> > }
> >
> > - if ((sbp->sb_qflags & (XFS_OQUOTA_ENFD | XFS_OQUOTA_CHKD)) &&
> > - (sbp->sb_qflags & (XFS_PQUOTA_ENFD | XFS_GQUOTA_ENFD |
> > - XFS_PQUOTA_CHKD | XFS_GQUOTA_CHKD))) {
> > - xfs_notice(mp,
> > -"Super block has XFS_OQUOTA bits along with XFS_PQUOTA and/or XFS_GQUOTA bits.\n");
> > - return XFS_ERROR(EFSCORRUPTED);
> > + if (xfs_sb_version_has_pquota(sbp)) {
> > + if (sbp->sb_qflags & (XFS_OQUOTA_ENFD | XFS_OQUOTA_CHKD)) {
> > + xfs_notice(mp,
> > + "Version 5 of Super block has XFS_OQUOTA bits.\n");
> > + return XFS_ERROR(EFSCORRUPTED);
> > + }
> > + } else if (sbp->sb_qflags & (XFS_PQUOTA_ENFD | XFS_GQUOTA_ENFD |
> > + XFS_PQUOTA_CHKD | XFS_GQUOTA_CHKD)) {
> > + xfs_notice(mp,
> > +"Superblock earlier than Version 5 has XFS_[PQ]UOTA_{ENFD|CHKD} bits.\n");
> > + return XFS_ERROR(EFSCORRUPTED);
>
> [ xfs_alert() for those, I think. ]
will do.
>
> > @@ -638,6 +643,13 @@ xfs_handle_quota_to_disk(
> > {
> > __uint16_t qflags = from->sb_qflags;
> >
> > + /*
> > + * We need to do these manipilations only if we are working
> > + * with an older version of on-disk superblock.
> > + */
> > + if (xfs_sb_version_has_pquota(from))
> > + return;
> > +
> > if (*fields & XFS_SB_QFLAGS) {
> > /*
> > * The in-core version of sb_qflags do not have
>
> xfs_sb_all_bits() does:
>
> if (xfs_sb_version_has_pquota(sbp))
> return XFS_SB_ALL_BITS;
> return XFS_SB_ALL_BITS & ~XFS_SB_PQUOTINO;
>
> which means that we enter xfs_handle_quota_to_disk() with
> XFS_SB_ALL_BITS intact for the pquota case, but without it in the
> non-pquota case. Hence if we don't have pquota set, we continue
> onwards and....
>
> > @@ -657,6 +669,10 @@ xfs_handle_quota_to_disk(
> > to->sb_qflags = cpu_to_be16(qflags);
> > *fields &= ~XFS_SB_QFLAGS;
> > }
> > + if (*fields & XFS_SB_PQUOTINO) {
> > + to->sb_gquotino = cpu_to_be64(from->sb_pquotino);
> > + *fields &= ~XFS_SB_PQUOTINO;
> > + }
>
> We will never do this because we've already cleared XFS_SB_PQUOTINO
> before we entered xfs_sb_to_disk(). That doesn't seem right to me...
Yes, if we are using a version of superblock where pquotino should not
be used, we do not want to get into this block.
If we are using PQUOTA in the superblock, that inode information will be
in gquotino and will be converted over appropriately in
xfs_sb_to_disk().
>
> > @@ -1524,8 +1524,10 @@ xfs_qm_init_quotainos(
> > flags &= ~XFS_QMOPT_SBVERSION;
> > }
> > if (XFS_IS_PQUOTA_ON(mp) && pip == NULL) {
> > + if (!xfs_sb_version_has_pquota(&mp->m_sb))
> > + sbflags &= ~XFS_SB_GQUOTINO;
>
> That's taken me a while to work out - it needs a comment explaining
> why XFS_SB_GQUOTINO is being cleared here.
will do.
>
> > error = xfs_qm_qino_alloc(mp, &pip,
> > - sbflags | XFS_SB_GQUOTINO,
> > + sbflags | XFS_SB_PQUOTINO,
> > flags | XFS_QMOPT_PQUOTA);
> > if (error)
> > goto error_rele;
> > diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c
> > index ed7cd55..d664a2d 100644
> > --- a/fs/xfs/xfs_qm_syscalls.c
> > +++ b/fs/xfs/xfs_qm_syscalls.c
> > @@ -201,8 +201,7 @@ xfs_qm_scall_quotaoff(
> > /*
> > * If quotas is completely disabled, close shop.
> > */
> > - if (((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_SET1) ||
> > - ((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_SET2)) {
> > + if ((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_ALL) {
> > mutex_unlock(&q->qi_quotaofflock);
> > xfs_qm_destroy_quotainfo(mp);
> > return (0);
>
> This makes the assumption that userspace passes all three quota
> types into the kernel in a single quota off call as the only way to
> turn quotas off completely. What happens if they are turned off one
> at a time? Shouldn't we detect when no more quotas are actually
> enabled and then do this?
Yes, I agree that there is a difference in behavior if the user turns
off quota one-by-one Vs turns off all quota at once. But, the behavior
difference is not seen by the user space. And, I did not make the
change :)
I just included project quota into the fold.
>
> Cheers,
>
> Dave.
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH v9 4/6] xfs: Start using pquotaino from the superblock.
2013-07-01 15:50 ` Chandra Seetharaman
@ 2013-07-04 1:12 ` Dave Chinner
2013-07-08 23:20 ` Chandra Seetharaman
0 siblings, 1 reply; 28+ messages in thread
From: Dave Chinner @ 2013-07-04 1:12 UTC (permalink / raw)
To: Chandra Seetharaman; +Cc: xfs
On Mon, Jul 01, 2013 at 10:50:30AM -0500, Chandra Seetharaman wrote:
> Hi Dave,
>
> I sent this email on 6/25 (just before my reply on 5/6 w.r.t adding the
> test to xfstests). Since I didn't get any response from you on this and
> got reply on the other one, I concluded that you accepted my
> justification/clarification.
>
> I just looked at the archives and do not see my original email :(... but
> is intact in my sent folder!!
>
> Please see if my justification below is valid.
>
> Chandra
>
> On Tue, 2013-06-25 at 16:31 +1000, Dave Chinner wrote:
> > On Sun, Jun 23, 2013 at 09:48:25PM -0500, Chandra Seetharaman wrote:
> > > Start using pquotino and define a macro to check if the
> > > superblock has pquotino.
> > >
> > > Keep backward compatibilty by alowing mount of older superblock
> > > with no separate pquota inode.
> > >
> > > Signed-off-by: Chandra Seetharaman <sekharan@us.ibm.com>
> > > ---
> > > fs/xfs/xfs_fsops.c | 3 +-
> > > fs/xfs/xfs_mount.c | 51 +++++++++++++++++++++++++++++++--------
> > > fs/xfs/xfs_qm.c | 22 +++++++++--------
> > > fs/xfs/xfs_qm_syscalls.c | 24 ++++++++++++++++--
> > > fs/xfs/xfs_quota.h | 8 ------
> > > fs/xfs/xfs_sb.h | 16 +++++++++++-
> > > fs/xfs/xfs_super.c | 14 ++++++----
> > > include/uapi/linux/dqblk_xfs.h | 1 +
> > > 8 files changed, 99 insertions(+), 40 deletions(-)
> > >
> > > diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
> > > index 614eb0c..3bf05f4 100644
> > > --- a/fs/xfs/xfs_fsops.c
> > > +++ b/fs/xfs/xfs_fsops.c
> > > @@ -501,7 +501,8 @@ xfs_growfs_data_private(
> > > error, agno);
> > > break;
> > > }
> > > - xfs_sb_to_disk(XFS_BUF_TO_SBP(bp), &mp->m_sb, XFS_SB_ALL_BITS);
> > > + xfs_sb_to_disk(XFS_BUF_TO_SBP(bp), &mp->m_sb,
> > > + xfs_sb_all_bits(&mp->m_sb));
> >
> > I think you could still pass XFS_SB_ALL_BITS to xfs_sb_to_disk(),
> > and do the XFS_SB_PQUOTINO filtering inside xfs_sb_quota_to_disk().
> >
> > Actually xfs_sb_all_bits() is only used here, and it seems to me
> > that it is not necessary as we do a pquota support check inside
> > xfs_sb_to_disk() and can handle this in that place...
>
> Yes, this is the only place that uses XFS_SB_ALL_BITS, and the purpose
> is to copy over the superblock to secondary.
>
> The change I made ensures that the caller does what is correct. i.e if
> it is copying an earlier version of superblock, it does not try to copy
> the pquotino, and if it uses the newer version of superblock it copies
> over the pquotino.
The caller does not need to know anything about how the quota bits
are encoded in the superblock.
> At some point (in my internal tree) I did have the way you suggested.
> But, doing it that way looked like a band-aid/hack, and felt this is the
> right way to do it (since the caller should provide appropriate
> information to the function).
The caller should not have to know anything about the specific
on-disk encoding the filesystem is currently using
That's the reason for encapsulating such on-disk format conversion
inside xfs_sb_to/from_disk(). Same with all the mount flags and so on
- the differences between what the code uses and what is on disk is
all encapsulated inside xfs_sb_quota_to/from_disk.
IOWs, from the outside, XFS_SB_ALL_BITS is all a caller needs to
pass into xfs_sb_to_disk() to get everything written to disk. Making
the caller have to be aware of the on-disk format when the function
being called is supposed to hide the details of the on-disk format
from the callers is, well, a bit silly.
> > > + if (*fields & XFS_SB_PQUOTINO) {
> > > + to->sb_gquotino = cpu_to_be64(from->sb_pquotino);
> > > + *fields &= ~XFS_SB_PQUOTINO;
> > > + }
> >
> > We will never do this because we've already cleared XFS_SB_PQUOTINO
> > before we entered xfs_sb_to_disk(). That doesn't seem right to me...
>
> Yes, if we are using a version of superblock where pquotino should not
> be used, we do not want to get into this block.
Why not? this code is executing the conversion from in-memory format
to the old on-disk format. This is exactly where such conversion
should be handled. This code looks right, but if you strip
XFS_SB_PQUOTINO at a high level, then it doesn't *ever* get used.
> If we are using PQUOTA in the superblock, that inode information will be
> in gquotino and will be converted over appropriately in
> xfs_sb_to_disk().
Sorry, I don't follow. You mean OQUOTA, yes?
Besides, all quota format conversions should be done in
xfs_sb_quota_to_disk(), not split between that function and
xfs_sb_to_disk()...
> > > @@ -201,8 +201,7 @@ xfs_qm_scall_quotaoff(
> > > /*
> > > * If quotas is completely disabled, close shop.
> > > */
> > > - if (((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_SET1) ||
> > > - ((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_SET2)) {
> > > + if ((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_ALL) {
> > > mutex_unlock(&q->qi_quotaofflock);
> > > xfs_qm_destroy_quotainfo(mp);
> > > return (0);
> >
> > This makes the assumption that userspace passes all three quota
> > types into the kernel in a single quota off call as the only way to
> > turn quotas off completely. What happens if they are turned off one
> > at a time? Shouldn't we detect when no more quotas are actually
> > enabled and then do this?
>
> Yes, I agree that there is a difference in behavior if the user turns
> off quota one-by-one Vs turns off all quota at once. But, the behavior
> difference is not seen by the user space. And, I did not make the
> change :)
>
> I just included project quota into the fold.
Sure, but my point still stands - if userspace currently expects
quota to be turned off by turning of user+group quota at the same
time, or user+project quota at the same time, then this will no
longer turn quotas off even if u/g or u/p were the only quotas
enabled. It's an unexpected change of behaviour, especially for
filesystems that don't support the separate pquota inode...
Cheers,
Dave.
--
Dave Chinner
david@fromorbit.com
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH v9 4/6] xfs: Start using pquotaino from the superblock.
2013-07-04 1:12 ` Dave Chinner
@ 2013-07-08 23:20 ` Chandra Seetharaman
2013-07-09 1:21 ` Dave Chinner
0 siblings, 1 reply; 28+ messages in thread
From: Chandra Seetharaman @ 2013-07-08 23:20 UTC (permalink / raw)
To: Dave Chinner; +Cc: xfs
On Thu, 2013-07-04 at 11:12 +1000, Dave Chinner wrote:
> On Mon, Jul 01, 2013 at 10:50:30AM -0500, Chandra Seetharaman wrote:
> > Hi Dave,
> >
> > I sent this email on 6/25 (just before my reply on 5/6 w.r.t adding the
> > test to xfstests). Since I didn't get any response from you on this and
> > got reply on the other one, I concluded that you accepted my
> > justification/clarification.
> >
> > I just looked at the archives and do not see my original email :(... but
> > is intact in my sent folder!!
> >
> > Please see if my justification below is valid.
> >
> > Chandra
> >
> > On Tue, 2013-06-25 at 16:31 +1000, Dave Chinner wrote:
> > > On Sun, Jun 23, 2013 at 09:48:25PM -0500, Chandra Seetharaman wrote:
> > > > Start using pquotino and define a macro to check if the
> > > > superblock has pquotino.
> > > >
> > > > Keep backward compatibilty by alowing mount of older superblock
> > > > with no separate pquota inode.
> > > >
> > > > Signed-off-by: Chandra Seetharaman <sekharan@us.ibm.com>
> > > > ---
> > > > fs/xfs/xfs_fsops.c | 3 +-
> > > > fs/xfs/xfs_mount.c | 51 +++++++++++++++++++++++++++++++--------
> > > > fs/xfs/xfs_qm.c | 22 +++++++++--------
> > > > fs/xfs/xfs_qm_syscalls.c | 24 ++++++++++++++++--
> > > > fs/xfs/xfs_quota.h | 8 ------
> > > > fs/xfs/xfs_sb.h | 16 +++++++++++-
> > > > fs/xfs/xfs_super.c | 14 ++++++----
> > > > include/uapi/linux/dqblk_xfs.h | 1 +
> > > > 8 files changed, 99 insertions(+), 40 deletions(-)
> > > >
> > > > diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
> > > > index 614eb0c..3bf05f4 100644
> > > > --- a/fs/xfs/xfs_fsops.c
> > > > +++ b/fs/xfs/xfs_fsops.c
> > > > @@ -501,7 +501,8 @@ xfs_growfs_data_private(
> > > > error, agno);
> > > > break;
> > > > }
> > > > - xfs_sb_to_disk(XFS_BUF_TO_SBP(bp), &mp->m_sb, XFS_SB_ALL_BITS);
> > > > + xfs_sb_to_disk(XFS_BUF_TO_SBP(bp), &mp->m_sb,
> > > > + xfs_sb_all_bits(&mp->m_sb));
> > >
> > > I think you could still pass XFS_SB_ALL_BITS to xfs_sb_to_disk(),
> > > and do the XFS_SB_PQUOTINO filtering inside xfs_sb_quota_to_disk().
> > >
> > > Actually xfs_sb_all_bits() is only used here, and it seems to me
> > > that it is not necessary as we do a pquota support check inside
> > > xfs_sb_to_disk() and can handle this in that place...
> >
> > Yes, this is the only place that uses XFS_SB_ALL_BITS, and the purpose
> > is to copy over the superblock to secondary.
> >
> > The change I made ensures that the caller does what is correct. i.e if
> > it is copying an earlier version of superblock, it does not try to copy
> > the pquotino, and if it uses the newer version of superblock it copies
> > over the pquotino.
>
> The caller does not need to know anything about how the quota bits
> are encoded in the superblock.
Caller doesn't need to know about quota bits, that is why I encapsulated
it into the function xfs_sb_all_bits().
Previously, it was fine to have the ALL_BITS to be independent of the
superblock, with my change we need to know which version of superblock
is being used to get all _only_ the bits that are used.
So, I do feel this is the right way to do it.
>
> > At some point (in my internal tree) I did have the way you suggested.
> > But, doing it that way looked like a band-aid/hack, and felt this is the
> > right way to do it (since the caller should provide appropriate
> > information to the function).
>
> The caller should not have to know anything about the specific
> on-disk encoding the filesystem is currently using
>
> That's the reason for encapsulating such on-disk format conversion
> inside xfs_sb_to/from_disk(). Same with all the mount flags and so on
> - the differences between what the code uses and what is on disk is
> all encapsulated inside xfs_sb_quota_to/from_disk.
Encapsulation in xfs_sb_to_disk() is not enough for this situation. If
both PQUOTINO and GQUOTINO is set for version 4 of the superblock,
xfs_sb_to_disk will not be able to know if it has to treat PQUOTINO as
valid or GQUOTINO as valid.
Of course, we can use the value of sb_pquotino and sb_gquotino to make
the decision if both PQUOTINO and GQUOTINO are set and (as I mentioned
in my earlier response) it looked more like a hack. So, I chose to do it
this way.
>
> IOWs, from the outside, XFS_SB_ALL_BITS is all a caller needs to
> pass into xfs_sb_to_disk() to get everything written to disk. Making
> the caller have to be aware of the on-disk format when the function
> being called is supposed to hide the details of the on-disk format
> from the callers is, well, a bit silly.
>
> > > > + if (*fields & XFS_SB_PQUOTINO) {
> > > > + to->sb_gquotino = cpu_to_be64(from->sb_pquotino);
> > > > + *fields &= ~XFS_SB_PQUOTINO;
> > > > + }
> > >
> > > We will never do this because we've already cleared XFS_SB_PQUOTINO
> > > before we entered xfs_sb_to_disk(). That doesn't seem right to me...
> >
> > Yes, if we are using a version of superblock where pquotino should not
> > be used, we do not want to get into this block.
>
> Why not? this code is executing the conversion from in-memory format
> to the old on-disk format. This is exactly where such conversion
As I mentioned above with superblock version less than 5, we can nicely
handle the case where both PQUOTINO and GQUOTINO is set when only one of
them is valid.
> should be handled. This code looks right, but if you strip
> XFS_SB_PQUOTINO at a high level, then it doesn't *ever* get used.
PQUOTINO is not stripped in all code paths. PQUOTINO is not set _only_
if the older superblock is copied to new secondary areas.
>
> > If we are using PQUOTA in the superblock, that inode information will be
> > in gquotino and will be converted over appropriately in
> > xfs_sb_to_disk().
>
> Sorry, I don't follow. You mean OQUOTA, yes?
What I meant to say is... if pquota is used in the superblock, (of
course OQUOTA will be set in the on-disk superblock), then that
information would be available in sb_gquotino, and that value will be
copied over to secondary superblocks appropriately.
>
> Besides, all quota format conversions should be done in
> xfs_sb_quota_to_disk(), not split between that function and
> xfs_sb_to_disk()...
>
> > > > @@ -201,8 +201,7 @@ xfs_qm_scall_quotaoff(
> > > > /*
> > > > * If quotas is completely disabled, close shop.
> > > > */
> > > > - if (((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_SET1) ||
> > > > - ((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_SET2)) {
> > > > + if ((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_ALL) {
> > > > mutex_unlock(&q->qi_quotaofflock);
> > > > xfs_qm_destroy_quotainfo(mp);
> > > > return (0);
> > >
> > > This makes the assumption that userspace passes all three quota
> > > types into the kernel in a single quota off call as the only way to
> > > turn quotas off completely. What happens if they are turned off one
> > > at a time? Shouldn't we detect when no more quotas are actually
> > > enabled and then do this?
> >
> > Yes, I agree that there is a difference in behavior if the user turns
> > off quota one-by-one Vs turns off all quota at once. But, the behavior
> > difference is not seen by the user space. And, I did not make the
> > change :)
> >
> > I just included project quota into the fold.
>
> Sure, but my point still stands - if userspace currently expects
> quota to be turned off by turning of user+group quota at the same
> time, or user+project quota at the same time, then this will no
> longer turn quotas off even if u/g or u/p were the only quotas
> enabled. It's an unexpected change of behaviour, especially for
> filesystems that don't support the separate pquota inode...
IIUC, user space will not see any difference in behavior even if this
specific code block is not present in this function. Whatever is being
done in xfs_qm_destroy_quotainfo() is done by the code just below the
above block in xfs_qm_scall_quotaoff(). Only additional thing
xfs_qm_destroy_quotainfo() does is to clean up all other in-kernel data
structures associated with quota for this mount point.
The behavior was that if _all_ the quotas are turned off at the same
time, clean up all in-kernel data structures associated with quota. If
the quotas were turned off one at a time, leave the in-kernel stuff even
when the last quota is turned off.
I maintained the same behavior.
I understand your point that _all_ mean u/g or u/p in older version of
superblock. But, the difference in behavior is not drastic and is not
seen by the user space at all.
If still unconvinced, is this the code you want to see there ?
if (((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_ALL) &&
xfs_sb_version_has_pquota(&mp->sb)) ||
((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_SET1) ||
((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_SET2)) {
:
:
}
> Cheers,
>
> Dave.
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH v9 4/6] xfs: Start using pquotaino from the superblock.
2013-07-08 23:20 ` Chandra Seetharaman
@ 2013-07-09 1:21 ` Dave Chinner
2013-07-09 21:06 ` Chandra Seetharaman
0 siblings, 1 reply; 28+ messages in thread
From: Dave Chinner @ 2013-07-09 1:21 UTC (permalink / raw)
To: Chandra Seetharaman; +Cc: xfs
On Mon, Jul 08, 2013 at 06:20:30PM -0500, Chandra Seetharaman wrote:
> On Thu, 2013-07-04 at 11:12 +1000, Dave Chinner wrote:
> > On Mon, Jul 01, 2013 at 10:50:30AM -0500, Chandra Seetharaman wrote:
> > > Hi Dave,
> > >
> > > I sent this email on 6/25 (just before my reply on 5/6 w.r.t adding the
> > > test to xfstests). Since I didn't get any response from you on this and
> > > got reply on the other one, I concluded that you accepted my
> > > justification/clarification.
> > >
> > > I just looked at the archives and do not see my original email :(... but
> > > is intact in my sent folder!!
> > >
> > > Please see if my justification below is valid.
> > >
> > > Chandra
> > >
> > > On Tue, 2013-06-25 at 16:31 +1000, Dave Chinner wrote:
> > > > On Sun, Jun 23, 2013 at 09:48:25PM -0500, Chandra Seetharaman wrote:
> > > > > Start using pquotino and define a macro to check if the
> > > > > superblock has pquotino.
> > > > >
> > > > > Keep backward compatibilty by alowing mount of older superblock
> > > > > with no separate pquota inode.
> > > > >
> > > > > Signed-off-by: Chandra Seetharaman <sekharan@us.ibm.com>
> > > > > ---
> > > > > fs/xfs/xfs_fsops.c | 3 +-
> > > > > fs/xfs/xfs_mount.c | 51 +++++++++++++++++++++++++++++++--------
> > > > > fs/xfs/xfs_qm.c | 22 +++++++++--------
> > > > > fs/xfs/xfs_qm_syscalls.c | 24 ++++++++++++++++--
> > > > > fs/xfs/xfs_quota.h | 8 ------
> > > > > fs/xfs/xfs_sb.h | 16 +++++++++++-
> > > > > fs/xfs/xfs_super.c | 14 ++++++----
> > > > > include/uapi/linux/dqblk_xfs.h | 1 +
> > > > > 8 files changed, 99 insertions(+), 40 deletions(-)
> > > > >
> > > > > diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
> > > > > index 614eb0c..3bf05f4 100644
> > > > > --- a/fs/xfs/xfs_fsops.c
> > > > > +++ b/fs/xfs/xfs_fsops.c
> > > > > @@ -501,7 +501,8 @@ xfs_growfs_data_private(
> > > > > error, agno);
> > > > > break;
> > > > > }
> > > > > - xfs_sb_to_disk(XFS_BUF_TO_SBP(bp), &mp->m_sb, XFS_SB_ALL_BITS);
> > > > > + xfs_sb_to_disk(XFS_BUF_TO_SBP(bp), &mp->m_sb,
> > > > > + xfs_sb_all_bits(&mp->m_sb));
> > > >
> > > > I think you could still pass XFS_SB_ALL_BITS to xfs_sb_to_disk(),
> > > > and do the XFS_SB_PQUOTINO filtering inside xfs_sb_quota_to_disk().
> > > >
> > > > Actually xfs_sb_all_bits() is only used here, and it seems to me
> > > > that it is not necessary as we do a pquota support check inside
> > > > xfs_sb_to_disk() and can handle this in that place...
> > >
> > > Yes, this is the only place that uses XFS_SB_ALL_BITS, and the purpose
> > > is to copy over the superblock to secondary.
> > >
> > > The change I made ensures that the caller does what is correct. i.e if
> > > it is copying an earlier version of superblock, it does not try to copy
> > > the pquotino, and if it uses the newer version of superblock it copies
> > > over the pquotino.
> >
> > The caller does not need to know anything about how the quota bits
> > are encoded in the superblock.
>
> Caller doesn't need to know about quota bits, that is why I encapsulated
> it into the function xfs_sb_all_bits().
Requiring a function at the caller site to filter bits out is saying
"the caller needs to know it has to filter certain options out".
What happens if we add a new piece of optional functionality that is
conditional for superblock writeback? So sometimes we need to filter
only PQUOTINO_BIT, sometimes we nee dto filter FOO_BIT, sometimes
we need to filter BAR_BIT, and so on?
What you are proposing effectively sets us down the path of having
to do this in future:
if (xfs_sb_version_hasfoo)
xfs_sb_to_disk(XFS_SB_FOO_BIT)
if (xfs_sb_version_hasbar)
xfs_sb_to_disk(XFS_SB_BAR_BIT)
xfs_sb_to_disk((XFS_SB_ALL_BITS & ~(XFS_SB_FOO_BIT|XFS_SB_BAR_BIT)));
All this needs to be handled in xfs_sb_to_disk().
> > That's the reason for encapsulating such on-disk format conversion
> > inside xfs_sb_to/from_disk(). Same with all the mount flags and so on
> > - the differences between what the code uses and what is on disk is
> > all encapsulated inside xfs_sb_quota_to/from_disk.
>
> Encapsulation in xfs_sb_to_disk() is not enough for this situation. If
> both PQUOTINO and GQUOTINO is set for version 4 of the superblock,
> xfs_sb_to_disk will not be able to know if it has to treat PQUOTINO as
> valid or GQUOTINO as valid.
The contents of from->sb_qflags tells you which one is valid.
Indeed, you have to look at from->sb_qflags to set the OQUOTA flags
correctly in to->sb_qflags, so I don't see why you can't use
from->sb_qflags to determine which of G/PQUOTINO needs to copied
across to to->sb_gquotino....
> > > > > /*
> > > > > * If quotas is completely disabled, close shop.
> > > > > */
> > > > > - if (((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_SET1) ||
> > > > > - ((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_SET2)) {
> > > > > + if ((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_ALL) {
> > > > > mutex_unlock(&q->qi_quotaofflock);
> > > > > xfs_qm_destroy_quotainfo(mp);
> > > > > return (0);
> > > >
> > > > This makes the assumption that userspace passes all three quota
> > > > types into the kernel in a single quota off call as the only way to
> > > > turn quotas off completely. What happens if they are turned off one
> > > > at a time? Shouldn't we detect when no more quotas are actually
> > > > enabled and then do this?
> > >
> > > Yes, I agree that there is a difference in behavior if the user turns
> > > off quota one-by-one Vs turns off all quota at once. But, the behavior
> > > difference is not seen by the user space. And, I did not make the
> > > change :)
> > >
> > > I just included project quota into the fold.
> >
> > Sure, but my point still stands - if userspace currently expects
> > quota to be turned off by turning of user+group quota at the same
> > time, or user+project quota at the same time, then this will no
> > longer turn quotas off even if u/g or u/p were the only quotas
> > enabled. It's an unexpected change of behaviour, especially for
> > filesystems that don't support the separate pquota inode...
>
> IIUC, user space will not see any difference in behavior even if this
> specific code block is not present in this function. Whatever is being
> done in xfs_qm_destroy_quotainfo() is done by the code just below the
> above block in xfs_qm_scall_quotaoff(). Only additional thing
> xfs_qm_destroy_quotainfo() does is to clean up all other in-kernel data
> structures associated with quota for this mount point.
>
> The behavior was that if _all_ the quotas are turned off at the same
> time, clean up all in-kernel data structures associated with quota. If
> the quotas were turned off one at a time, leave the in-kernel stuff even
> when the last quota is turned off.
>
> I maintained the same behavior.
That's where I disagree. You kept the same /line of reasoning/ as the
original code, not the same behaviour. What I'm saying is that
the line of reasoning is wrong to begin with, and hence keeping it
is not the right thing to do.
Indeed, code archeology shows this line of reasoning is zero-day
Irix behaviour:
http://oss.sgi.com/cgi-bin/gitweb.cgi?p=archive/xfs-import.git;a=blob;f=fs/xfs/xfs_qm_syscalls.c;hb=0d5ad8383061fbc0a9804fbb98218750000fe032
730 /*
731 * If quotas is completely disabled, close shop.
732 */
733 if ((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_ALL) {
734 mutex_unlock(&mp->QI_QOFFLOCK);
735 xfs_qm_destroy_quotainfo(mp);
736 return (0);
737 }
Hmmm, looks kind of familiar, doesn't it? But what's the caller
context?
155 case Q_QUOTAOFF:
156 /* */
157 flags = addr?
158 xfs_qm_import_flags((uint *)addr) :
159 XFS_ALL_QUOTA_ACCT_ENFD;
160 error = xfs_qm_scall_quotaoff(mp, flags);
161
And from xfs_dquot.h:
95 #define XFS_ALL_QUOTA_ACCT_ENFD (XFS_UQUOTA_ACCT|XFS_UQUOTA_ENFD|\
96 XFS_PQUOTA_ACCT|XFS_PQUOTA_ENFD)
If no parameter was passed, the default behaviour is to turn off
all quotas. IOWs, this logic made sense Irix, but the linux case has no
such default behaviour - it only passes what userspace says to turn
off.
And that's exactly my point - these semantics made sense for Irix all
those years ago, but they simply don't make sense now. Hence while
we are touching this code we should fix it up. i.e. if we've turned
off all the quotas, clean up properly.
> I understand your point that _all_ mean u/g or u/p in older version of
> superblock. But, the difference in behavior is not drastic and is not
> seen by the user space at all.
>
> If still unconvinced, is this the code you want to see there ?
>
> if (((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_ALL) &&
> xfs_sb_version_has_pquota(&mp->sb)) ||
> ((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_SET1) ||
> ((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_SET2)) {
> :
> :
> }
No. If, as a result of turning off quotas, there are no active
quotas then turn off the quota subsystem. mp->m_qflags will tell us
exactly what quota is still running when we get to this point...
Cheers,
Dave.
--
Dave Chinner
david@fromorbit.com
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH v9 4/6] xfs: Start using pquotaino from the superblock.
2013-07-09 1:21 ` Dave Chinner
@ 2013-07-09 21:06 ` Chandra Seetharaman
0 siblings, 0 replies; 28+ messages in thread
From: Chandra Seetharaman @ 2013-07-09 21:06 UTC (permalink / raw)
To: Dave Chinner; +Cc: xfs
On Tue, 2013-07-09 at 11:21 +1000, Dave Chinner wrote:
> On Mon, Jul 08, 2013 at 06:20:30PM -0500, Chandra Seetharaman wrote:
> > On Thu, 2013-07-04 at 11:12 +1000, Dave Chinner wrote:
> > > On Mon, Jul 01, 2013 at 10:50:30AM -0500, Chandra Seetharaman wrote:
> > > > Hi Dave,
> > > >
> > > > I sent this email on 6/25 (just before my reply on 5/6 w.r.t adding the
> > > > test to xfstests). Since I didn't get any response from you on this and
> > > > got reply on the other one, I concluded that you accepted my
> > > > justification/clarification.
> > > >
> > > > I just looked at the archives and do not see my original email :(... but
> > > > is intact in my sent folder!!
> > > >
> > > > Please see if my justification below is valid.
> > > >
> > > > Chandra
> > > >
> > > > On Tue, 2013-06-25 at 16:31 +1000, Dave Chinner wrote:
> > > > > On Sun, Jun 23, 2013 at 09:48:25PM -0500, Chandra Seetharaman wrote:
> > > > > > Start using pquotino and define a macro to check if the
> > > > > > superblock has pquotino.
> > > > > >
> > > > > > Keep backward compatibilty by alowing mount of older superblock
> > > > > > with no separate pquota inode.
> > > > > >
> > > > > > Signed-off-by: Chandra Seetharaman <sekharan@us.ibm.com>
> > > > > > ---
> > > > > > fs/xfs/xfs_fsops.c | 3 +-
> > > > > > fs/xfs/xfs_mount.c | 51 +++++++++++++++++++++++++++++++--------
> > > > > > fs/xfs/xfs_qm.c | 22 +++++++++--------
> > > > > > fs/xfs/xfs_qm_syscalls.c | 24 ++++++++++++++++--
> > > > > > fs/xfs/xfs_quota.h | 8 ------
> > > > > > fs/xfs/xfs_sb.h | 16 +++++++++++-
> > > > > > fs/xfs/xfs_super.c | 14 ++++++----
> > > > > > include/uapi/linux/dqblk_xfs.h | 1 +
> > > > > > 8 files changed, 99 insertions(+), 40 deletions(-)
> > > > > >
> > > > > > diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
> > > > > > index 614eb0c..3bf05f4 100644
> > > > > > --- a/fs/xfs/xfs_fsops.c
> > > > > > +++ b/fs/xfs/xfs_fsops.c
> > > > > > @@ -501,7 +501,8 @@ xfs_growfs_data_private(
> > > > > > error, agno);
> > > > > > break;
> > > > > > }
> > > > > > - xfs_sb_to_disk(XFS_BUF_TO_SBP(bp), &mp->m_sb, XFS_SB_ALL_BITS);
> > > > > > + xfs_sb_to_disk(XFS_BUF_TO_SBP(bp), &mp->m_sb,
> > > > > > + xfs_sb_all_bits(&mp->m_sb));
> > > > >
> > > > > I think you could still pass XFS_SB_ALL_BITS to xfs_sb_to_disk(),
> > > > > and do the XFS_SB_PQUOTINO filtering inside xfs_sb_quota_to_disk().
> > > > >
> > > > > Actually xfs_sb_all_bits() is only used here, and it seems to me
> > > > > that it is not necessary as we do a pquota support check inside
> > > > > xfs_sb_to_disk() and can handle this in that place...
> > > >
> > > > Yes, this is the only place that uses XFS_SB_ALL_BITS, and the purpose
> > > > is to copy over the superblock to secondary.
> > > >
> > > > The change I made ensures that the caller does what is correct. i.e if
> > > > it is copying an earlier version of superblock, it does not try to copy
> > > > the pquotino, and if it uses the newer version of superblock it copies
> > > > over the pquotino.
> > >
> > > The caller does not need to know anything about how the quota bits
> > > are encoded in the superblock.
> >
> > Caller doesn't need to know about quota bits, that is why I encapsulated
> > it into the function xfs_sb_all_bits().
>
> Requiring a function at the caller site to filter bits out is saying
> "the caller needs to know it has to filter certain options out".
>
> What happens if we add a new piece of optional functionality that is
> conditional for superblock writeback? So sometimes we need to filter
> only PQUOTINO_BIT, sometimes we nee dto filter FOO_BIT, sometimes
> we need to filter BAR_BIT, and so on?
>
> What you are proposing effectively sets us down the path of having
> to do this in future:
>
> if (xfs_sb_version_hasfoo)
> xfs_sb_to_disk(XFS_SB_FOO_BIT)
> if (xfs_sb_version_hasbar)
> xfs_sb_to_disk(XFS_SB_BAR_BIT)
> xfs_sb_to_disk((XFS_SB_ALL_BITS & ~(XFS_SB_FOO_BIT|XFS_SB_BAR_BIT)));
>
> All this needs to be handled in xfs_sb_to_disk().
>
> > > That's the reason for encapsulating such on-disk format conversion
> > > inside xfs_sb_to/from_disk(). Same with all the mount flags and so on
> > > - the differences between what the code uses and what is on disk is
> > > all encapsulated inside xfs_sb_quota_to/from_disk.
> >
> > Encapsulation in xfs_sb_to_disk() is not enough for this situation. If
> > both PQUOTINO and GQUOTINO is set for version 4 of the superblock,
> > xfs_sb_to_disk will not be able to know if it has to treat PQUOTINO as
> > valid or GQUOTINO as valid.
>
> The contents of from->sb_qflags tells you which one is valid.
> Indeed, you have to look at from->sb_qflags to set the OQUOTA flags
> correctly in to->sb_qflags, so I don't see why you can't use
> from->sb_qflags to determine which of G/PQUOTINO needs to copied
> across to to->sb_gquotino....
>
Ok. That is a good option. So, this is what I am thinking that I will
add before the PQUOTINO check in xfs_sb_quota_to_disk():
if ((*fields & XFS_SB_PQUOTINO) && (*fields & XFS_SB_GQUOTINO)) {
/*
* PQUOTINO and GQUOTINO cannot be used together in versions
* earlier than version 5 of superblock. If used, use sb_flags
* to resolve which one should be set.
*/
if (from->sb_qflags & XFS_PQUOTA_ACCT)
*fields &= ~XFS_SB_GQUOTINO;
else
*fields &= ~XFS_SB_PQUOTINO;
}
> > > > > > /*
> > > > > > * If quotas is completely disabled, close shop.
> > > > > > */
> > > > > > - if (((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_SET1) ||
> > > > > > - ((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_SET2)) {
> > > > > > + if ((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_ALL) {
> > > > > > mutex_unlock(&q->qi_quotaofflock);
> > > > > > xfs_qm_destroy_quotainfo(mp);
> > > > > > return (0);
> > > > >
> > > > > This makes the assumption that userspace passes all three quota
> > > > > types into the kernel in a single quota off call as the only way to
> > > > > turn quotas off completely. What happens if they are turned off one
> > > > > at a time? Shouldn't we detect when no more quotas are actually
> > > > > enabled and then do this?
> > > >
> > > > Yes, I agree that there is a difference in behavior if the user turns
> > > > off quota one-by-one Vs turns off all quota at once. But, the behavior
> > > > difference is not seen by the user space. And, I did not make the
> > > > change :)
> > > >
> > > > I just included project quota into the fold.
> > >
> > > Sure, but my point still stands - if userspace currently expects
> > > quota to be turned off by turning of user+group quota at the same
> > > time, or user+project quota at the same time, then this will no
> > > longer turn quotas off even if u/g or u/p were the only quotas
> > > enabled. It's an unexpected change of behaviour, especially for
> > > filesystems that don't support the separate pquota inode...
> >
> > IIUC, user space will not see any difference in behavior even if this
> > specific code block is not present in this function. Whatever is being
> > done in xfs_qm_destroy_quotainfo() is done by the code just below the
> > above block in xfs_qm_scall_quotaoff(). Only additional thing
> > xfs_qm_destroy_quotainfo() does is to clean up all other in-kernel data
> > structures associated with quota for this mount point.
> >
> > The behavior was that if _all_ the quotas are turned off at the same
> > time, clean up all in-kernel data structures associated with quota. If
> > the quotas were turned off one at a time, leave the in-kernel stuff even
> > when the last quota is turned off.
> >
> > I maintained the same behavior.
>
> That's where I disagree. You kept the same /line of reasoning/ as the
> original code, not the same behaviour. What I'm saying is that
> the line of reasoning is wrong to begin with, and hence keeping it
> is not the right thing to do.
>
> Indeed, code archeology shows this line of reasoning is zero-day
> Irix behaviour:
>
> http://oss.sgi.com/cgi-bin/gitweb.cgi?p=archive/xfs-import.git;a=blob;f=fs/xfs/xfs_qm_syscalls.c;hb=0d5ad8383061fbc0a9804fbb98218750000fe032
>
> 730 /*
> 731 * If quotas is completely disabled, close shop.
> 732 */
> 733 if ((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_ALL) {
> 734 mutex_unlock(&mp->QI_QOFFLOCK);
> 735 xfs_qm_destroy_quotainfo(mp);
> 736 return (0);
> 737 }
>
> Hmmm, looks kind of familiar, doesn't it? But what's the caller
> context?
>
> 155 case Q_QUOTAOFF:
> 156 /* */
> 157 flags = addr?
> 158 xfs_qm_import_flags((uint *)addr) :
> 159 XFS_ALL_QUOTA_ACCT_ENFD;
> 160 error = xfs_qm_scall_quotaoff(mp, flags);
> 161
>
> And from xfs_dquot.h:
>
> 95 #define XFS_ALL_QUOTA_ACCT_ENFD (XFS_UQUOTA_ACCT|XFS_UQUOTA_ENFD|\
> 96 XFS_PQUOTA_ACCT|XFS_PQUOTA_ENFD)
>
> If no parameter was passed, the default behaviour is to turn off
> all quotas. IOWs, this logic made sense Irix, but the linux case has no
> such default behaviour - it only passes what userspace says to turn
> off.
>
> And that's exactly my point - these semantics made sense for Irix all
> those years ago, but they simply don't make sense now. Hence while
> we are touching this code we should fix it up. i.e. if we've turned
> off all the quotas, clean up properly.
In effect, you are asking me to fix a problem that existed when xfs was
ported to Linux.
Sure, will do it.
I will send a separate patch to fix the problem and change my patch
accordingly.
>
> > I understand your point that _all_ mean u/g or u/p in older version of
> > superblock. But, the difference in behavior is not drastic and is not
> > seen by the user space at all.
> >
> > If still unconvinced, is this the code you want to see there ?
> >
> > if (((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_ALL) &&
> > xfs_sb_version_has_pquota(&mp->sb)) ||
> > ((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_SET1) ||
> > ((flags & XFS_MOUNT_QUOTA_ALL) == XFS_MOUNT_QUOTA_SET2)) {
> > :
> > :
> > }
>
> No. If, as a result of turning off quotas, there are no active
> quotas then turn off the quota subsystem. mp->m_qflags will tell us
> exactly what quota is still running when we get to this point...
>
> Cheers,
>
> Dave.
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 28+ messages in thread
end of thread, other threads:[~2013-07-09 21:07 UTC | newest]
Thread overview: 28+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-06-24 2:48 [PATCH v9 0/6] Allow pquota and gquota to be used together Chandra Seetharaman
2013-06-24 2:48 ` [PATCH v9 1/6] xfs: Move code around and remove typedefs Chandra Seetharaman
2013-06-24 5:31 ` Dave Chinner
2013-06-24 22:21 ` Chandra Seetharaman
2013-06-24 21:36 ` Ben Myers
2013-06-24 23:23 ` Chandra Seetharaman
2013-06-24 2:48 ` [PATCH v9 2/6] xfs: Remove incore use of XFS_OQUOTA_ENFD and XFS_OQUOTA_CHKD Chandra Seetharaman
2013-06-24 5:59 ` Dave Chinner
2013-06-24 22:25 ` Chandra Seetharaman
2013-06-25 5:32 ` Dave Chinner
2013-06-24 2:48 ` [PATCH v9 3/6] xfs: Add pquota fields where gquota is used Chandra Seetharaman
2013-06-24 8:00 ` Dave Chinner
2013-06-24 22:33 ` Chandra Seetharaman
2013-06-24 23:25 ` Chandra Seetharaman
2013-06-25 5:33 ` Dave Chinner
2013-06-24 2:48 ` [PATCH v9 4/6] xfs: Start using pquotaino from the superblock Chandra Seetharaman
2013-06-25 6:31 ` Dave Chinner
2013-07-01 15:50 ` Chandra Seetharaman
2013-07-04 1:12 ` Dave Chinner
2013-07-08 23:20 ` Chandra Seetharaman
2013-07-09 1:21 ` Dave Chinner
2013-07-09 21:06 ` Chandra Seetharaman
2013-06-24 2:48 ` [PATCH v9 5/6] xfs: Add proper versioning support to fs_quota_stat Chandra Seetharaman
2013-06-25 6:43 ` Dave Chinner
2013-06-25 22:36 ` Chandra Seetharaman
2013-06-26 1:20 ` Dave Chinner
2013-06-24 2:48 ` [PATCH v9 6/6] xfs: Use new qs_pquota field in fs_quota_stat for Q_XGETQSTAT Chandra Seetharaman
2013-06-25 6:45 ` Dave Chinner
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox