* [RFC PATCH 0/3] Allow pquota and gquota to be used together
@ 2011-10-18 0:09 Chandra Seetharaman
2011-10-18 0:09 ` [RFC PATCH 1/3] Remove in core use of XFS_OQUOTA_ENFD and XFS_OQUOTA_CHKD Chandra Seetharaman
` (2 more replies)
0 siblings, 3 replies; 11+ messages in thread
From: Chandra Seetharaman @ 2011-10-18 0:09 UTC (permalink / raw)
To: xfs; +Cc: Chandra Seetharaman
Hello All,
Few weeks back I asked for some work on XFS. Christoph suggested
me to make changes to allow pquota and gquota to be used
simultaneously in a filesystem.
All the xfs quota tests ran successfully. Currently running
the full suite.
I am currently working on the user space changes. In the mean
while I wanted to get some feedback on it.
Here are the changes.
These changes expect the pquotino to be already present in the
disk with a version bit. IOW, only mkfs has the ability to
create a filesystem with this specific information.
Also, when older superblocks are read, it will be written back
the same way. i.e, no semantic change to the superblock.
1. Expand the on disk XFS_OQUOTA_* to in core XFS_GQUOTA_.* and
XFS_PQUOTA_.*. But always store as XFS_OQUOTA_.* on disk.
2. Wherever gquota is used, introduce pquota, simply by way of
defining a macro for pquota(This is to make the changes
simple and easy to follow).
3. Start using a new field pquotino in on-disk super block, when
an appropriate version bit is set.
Thanks & Regards,
chandra
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 11+ messages in thread
* [RFC PATCH 1/3] Remove in core use of XFS_OQUOTA_ENFD and XFS_OQUOTA_CHKD
2011-10-18 0:09 [RFC PATCH 0/3] Allow pquota and gquota to be used together Chandra Seetharaman
@ 2011-10-18 0:09 ` Chandra Seetharaman
2011-10-18 5:16 ` Arkadiusz Miśkiewicz
2011-10-18 22:40 ` Alex Elder
2011-10-18 0:09 ` [RFC PATCH 2/3] Add pquota fields where gquota is used Chandra Seetharaman
2011-10-18 0:09 ` [RFC PATCH 3/3] Add pquotaino to on-disk super block Chandra Seetharaman
2 siblings, 2 replies; 11+ messages in thread
From: Chandra Seetharaman @ 2011-10-18 0:09 UTC (permalink / raw)
To: xfs; +Cc: Chandra Seetharaman
Remove incore use of XFS_OQUOTA_ENFD and XFS_OQUOTA_CHKD. Instead,
start using XFS_GQUOTA_.* XFS_PQUOTA_.* counterparts.
No changes is made to the on-disk version of the superblock yey. On-disk
copy still uses XFS_OQUOTA_ENFD and XFS_OQUOTA_CHKD.
Signed-off-by: Chandra Seetharaman <sekharan@us.ibm.com>
---
fs/xfs/xfs_mount.c | 14 ++++++++++++++
fs/xfs/xfs_qm.c | 11 +++++++----
fs/xfs/xfs_qm_syscalls.c | 26 ++++++++++++++------------
fs/xfs/xfs_quota.h | 37 ++++++++++++++++++++++++++-----------
fs/xfs/xfs_quotaops.c | 6 ++++--
fs/xfs/xfs_super.c | 19 ++++++++++---------
fs/xfs/xfs_trans_dquot.c | 4 ++--
7 files changed, 77 insertions(+), 40 deletions(-)
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index d06afbc..366bbb7 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -591,6 +591,14 @@ xfs_sb_from_disk(
to->sb_uquotino = be64_to_cpu(from->sb_uquotino);
to->sb_gquotino = be64_to_cpu(from->sb_gquotino);
to->sb_qflags = be16_to_cpu(from->sb_qflags);
+ if (to->sb_qflags & XFS_OQUOTA_ENFD)
+ to->sb_qflags |= (to->sb_qflags & XFS_PQUOTA_ACCT) ?
+ XFS_PQUOTA_ENFD : XFS_GQUOTA_ENFD;
+ if (to->sb_qflags & XFS_OQUOTA_CHKD)
+ to->sb_qflags |= (to->sb_qflags & XFS_PQUOTA_ACCT) ?
+ XFS_PQUOTA_CHKD : XFS_GQUOTA_CHKD;
+ to->sb_qflags &= ~(XFS_OQUOTA_ENFD | XFS_OQUOTA_CHKD);
+
to->sb_flags = from->sb_flags;
to->sb_shared_vn = from->sb_shared_vn;
to->sb_inoalignmt = be32_to_cpu(from->sb_inoalignmt);
@@ -625,6 +633,12 @@ xfs_sb_to_disk(
if (!fields)
return;
+ if (from->sb_qflags & (XFS_PQUOTA_ENFD | XFS_GQUOTA_ENFD))
+ from->sb_qflags |= XFS_OQUOTA_ENFD;
+ if (from->sb_qflags & (XFS_PQUOTA_CHKD | XFS_GQUOTA_CHKD))
+ from->sb_qflags |= XFS_OQUOTA_CHKD;
+ from->sb_qflags &= ~(XFS_PQUOTA_ENFD | XFS_PQUOTA_CHKD |
+ XFS_GQUOTA_ENFD | XFS_GQUOTA_CHKD);
while (fields) {
f = (xfs_sb_field_t)xfs_lowbit64((__uint64_t)fields);
first = xfs_sb_info[f].offset;
diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c
index 5cff443..cb2ed78 100644
--- a/fs/xfs/xfs_qm.c
+++ b/fs/xfs/xfs_qm.c
@@ -343,8 +343,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:
/*
@@ -1638,7 +1640,8 @@ xfs_qm_quotacheck(
XFS_QMOPT_GQUOTA : XFS_QMOPT_PQUOTA);
if (error)
goto error_return;
- flags |= XFS_OQUOTA_CHKD;
+ flags |= XFS_IS_GQUOTA_ON(mp) ?
+ XFS_GQUOTA_CHKD : XFS_PQUOTA_CHKD;
}
do {
@@ -1688,7 +1691,7 @@ xfs_qm_quotacheck(
* quotachecked status, since we won't be doing accounting for
* that type anymore.
*/
- mp->m_qflags &= ~(XFS_OQUOTA_CHKD | XFS_UQUOTA_CHKD);
+ mp->m_qflags &= ~(XFS_GQUOTA_CHKD | XFS_PQUOTA_CHKD | XFS_UQUOTA_CHKD);
mp->m_qflags |= flags;
error_return:
diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c
index 5cc3dde..3a67805 100644
--- a/fs/xfs/xfs_qm_syscalls.c
+++ b/fs/xfs/xfs_qm_syscalls.c
@@ -120,11 +120,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;
}
@@ -343,9 +343,11 @@ xfs_qm_scall_quotaon(
||
((flags & XFS_PQUOTA_ACCT) == 0 &&
(mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT) == 0 &&
- (flags & XFS_GQUOTA_ACCT) == 0 &&
+ (flags & XFS_PQUOTA_ENFD))
+ ||
+ ((flags & XFS_GQUOTA_ACCT) == 0 &&
(mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) == 0 &&
- (flags & XFS_OQUOTA_ENFD))) {
+ (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);
@@ -795,8 +797,8 @@ xfs_qm_export_dquot(
* so return zeroes in that case.
*/
if ((!XFS_IS_UQUOTA_ENFORCED(mp) && src->d_flags == XFS_DQ_USER) ||
- (!XFS_IS_OQUOTA_ENFORCED(mp) &&
- (src->d_flags & (XFS_DQ_PROJ | XFS_DQ_GROUP)))) {
+ (!XFS_IS_PQUOTA_ENFORCED(mp) && src->d_flags == XFS_DQ_PROJ) ||
+ (!XFS_IS_GQUOTA_ENFORCED(mp) && src->d_flags == XFS_DQ_GROUP)) {
dst->d_btimer = 0;
dst->d_itimer = 0;
dst->d_rtbtimer = 0;
@@ -804,8 +806,8 @@ xfs_qm_export_dquot(
#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 (((int) dst->d_bcount >= (int) dst->d_blk_softlimit) &&
(dst->d_blk_softlimit > 0)) {
@@ -854,10 +856,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 a595f29..41483d8 100644
--- a/fs/xfs/xfs_quota.h
+++ b/fs/xfs/xfs_quota.h
@@ -154,19 +154,35 @@ typedef struct xfs_qoff_logformat {
#define XFS_GQUOTA_ACCT 0x0040 /* group quota accounting ON */
/*
+ * If the superblock version is earlier than XFS_SB_VERSION_NO_OQUOTA,
+ * following flags will only be used in m_qflags and incore sb_qflags
+ * From XFS_SB_VERSION_NO_OQUOTA, these flags will be stored in
+ * on-disk sb_qflags too.
+ * Also from XFS_SB_VERSION_NO_OQUOTA, XFS_OQUOTA_.* will not be used
+ * in on-disk sb_qflags.
+ */
+#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)
@@ -260,24 +276,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 7e76f53..be5389e 100644
--- a/fs/xfs/xfs_quotaops.c
+++ b/fs/xfs/xfs_quotaops.c
@@ -76,8 +76,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 ba16248..b1c8d5b 100644
--- a/fs/xfs/xfs_super.c
+++ b/fs/xfs/xfs_super.c
@@ -328,7 +328,8 @@ xfs_parseargs(
mp->m_qflags &= ~(XFS_UQUOTA_ACCT | XFS_UQUOTA_ACTIVE |
XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE |
XFS_PQUOTA_ACCT | XFS_PQUOTA_ACTIVE |
- XFS_UQUOTA_ENFD | XFS_OQUOTA_ENFD);
+ XFS_UQUOTA_ENFD | XFS_PQUOTA_ENFD |
+ XFS_GQUOTA_ENFD);
} else if (!strcmp(this_char, MNTOPT_QUOTA) ||
!strcmp(this_char, MNTOPT_UQUOTA) ||
!strcmp(this_char, MNTOPT_USRQUOTA)) {
@@ -341,17 +342,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)) {
mp->m_flags |= XFS_MOUNT_DELAYLOG;
} else if (!strcmp(this_char, MNTOPT_NODELAYLOG)) {
@@ -552,12 +553,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);
@@ -1104,8 +1105,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 4d00ee6..bea957d 100644
--- a/fs/xfs/xfs_trans_dquot.c
+++ b/fs/xfs/xfs_trans_dquot.c
@@ -640,8 +640,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] 11+ messages in thread
* [RFC PATCH 2/3] Add pquota fields where gquota is used
2011-10-18 0:09 [RFC PATCH 0/3] Allow pquota and gquota to be used together Chandra Seetharaman
2011-10-18 0:09 ` [RFC PATCH 1/3] Remove in core use of XFS_OQUOTA_ENFD and XFS_OQUOTA_CHKD Chandra Seetharaman
@ 2011-10-18 0:09 ` Chandra Seetharaman
2011-10-19 9:57 ` Christoph Hellwig
2011-10-18 0:09 ` [RFC PATCH 3/3] Add pquotaino to on-disk super block Chandra Seetharaman
2 siblings, 1 reply; 11+ messages in thread
From: Chandra Seetharaman @ 2011-10-18 0:09 UTC (permalink / raw)
To: xfs; +Cc: Chandra Seetharaman
Add project quota changes to all the places where group quota field
is used. by use of macros.
No externally visible changed and no superblock changes, yet.
Signed-off-by: Chandra Seetharaman <sekharan@us.ibm.com>
---
fs/xfs/xfs_dquot.c | 20 +++-
fs/xfs/xfs_dquot.h | 14 ++-
fs/xfs/xfs_iget.c | 2 +-
fs/xfs/xfs_inode.h | 1 +
fs/xfs/xfs_ioctl.c | 12 +-
fs/xfs/xfs_iops.c | 4 +-
fs/xfs/xfs_mount.c | 2 +
fs/xfs/xfs_qm.c | 273 +++++++++++++++++++++++++++++++---------------
fs/xfs/xfs_qm.h | 4 +-
fs/xfs/xfs_qm_bhv.c | 2 +-
fs/xfs/xfs_qm_syscalls.c | 16 ++-
fs/xfs/xfs_quota.h | 38 ++++---
fs/xfs/xfs_sb.h | 1 +
fs/xfs/xfs_trans_dquot.c | 69 +++++++++---
fs/xfs/xfs_vnodeops.c | 23 +++--
15 files changed, 329 insertions(+), 152 deletions(-)
diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c
index 25d7280..e262936 100644
--- a/fs/xfs/xfs_dquot.c
+++ b/fs/xfs/xfs_dquot.c
@@ -841,8 +841,10 @@ xfs_qm_dqget(
ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
if (type == XFS_DQ_USER)
ASSERT(ip->i_udquot == NULL);
- else
+ else if (type == XFS_DQ_GROUP)
ASSERT(ip->i_gdquot == NULL);
+ else
+ ASSERT(ip->i_pdquot == NULL);
}
#endif
mutex_lock(&h->qh_lock);
@@ -933,8 +935,8 @@ xfs_qm_dqget(
xfs_dqlock(dqp);
goto dqret;
}
- } else {
- if (!XFS_IS_OQUOTA_ON(mp)) {
+ } else if (type == XFS_DQ_GROUP) {
+ if (!XFS_IS_GQUOTA_ON(mp)) {
/* inode stays locked on return */
xfs_qm_dqdestroy(dqp);
return XFS_ERROR(ESRCH);
@@ -945,6 +947,18 @@ xfs_qm_dqget(
xfs_dqlock(dqp);
goto dqret;
}
+ } else {
+ if (!XFS_IS_PQUOTA_ON(mp)) {
+ /* inode stays locked on return */
+ xfs_qm_dqdestroy(dqp);
+ return XFS_ERROR(ESRCH);
+ }
+ if (ip->i_pdquot) {
+ xfs_qm_dqdestroy(dqp);
+ dqp = ip->i_pdquot;
+ xfs_dqlock(dqp);
+ goto dqret;
+ }
}
}
diff --git a/fs/xfs/xfs_dquot.h b/fs/xfs/xfs_dquot.h
index 34b7e94..ed2c6bd 100644
--- a/fs/xfs/xfs_dquot.h
+++ b/fs/xfs/xfs_dquot.h
@@ -59,6 +59,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 */
@@ -110,11 +111,16 @@ static inline void xfs_dqfunlock(xfs_dquot_t *dqp)
#define XFS_DQ_TO_QINF(dqp) ((dqp)->q_mount->m_quotainfo)
#define XFS_DQ_TO_QIP(dqp) (XFS_QM_ISUDQ(dqp) ? \
XFS_DQ_TO_QINF(dqp)->qi_uquotaip : \
- XFS_DQ_TO_QINF(dqp)->qi_gquotaip)
+ ((XFS_QM_ISGDQ(dqp) ? \
+ XFS_DQ_TO_QINF(dqp)->qi_gquotaip :\
+ XFS_DQ_TO_QINF(dqp)->qi_pquotaip)))
-#define XFS_IS_THIS_QUOTA_OFF(d) (! (XFS_QM_ISUDQ(d) ? \
- (XFS_IS_UQUOTA_ON((d)->q_mount)) : \
- (XFS_IS_OQUOTA_ON((d)->q_mount))))
+#define XFS_IS_THIS_QUOTA_OFF(d) (! ((XFS_QM_ISUDQ(d) && \
+ XFS_IS_UQUOTA_ON((d)->q_mount)) || \
+ (XFS_QM_ISGDQ(d) && \
+ XFS_IS_GQUOTA_ON((d)->q_mount)) || \
+ (XFS_QM_ISPDQ(d) && \
+ XFS_IS_PQUOTA_ON((d)->q_mount))))
extern void xfs_qm_dqdestroy(xfs_dquot_t *);
extern int xfs_qm_dqflush(xfs_dquot_t *, uint);
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c
index 0fa98b1..bee588b 100644
--- a/fs/xfs/xfs_iget.c
+++ b/fs/xfs/xfs_iget.c
@@ -365,7 +365,7 @@ xfs_iget_cache_miss(
}
/* These values _must_ be set before releasing the radix tree lock! */
- ip->i_udquot = ip->i_gdquot = NULL;
+ ip->i_udquot = ip->i_gdquot = ip->i_pdquot = NULL;
xfs_iflags_set(ip, XFS_INEW);
spin_unlock(&pag->pag_ici_lock);
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index 760140d..26f95a6 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -231,6 +231,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 d99a905..48f2e57 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -907,7 +907,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;
@@ -936,7 +936,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;
}
@@ -973,7 +973,7 @@ 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,
+ code = xfs_qm_vop_chown_reserve(tp, ip, udqp, NULL, pdqp,
capable(CAP_FOWNER) ?
XFS_QMOPT_FORCE_RES : 0);
if (code) /* out of quota */
@@ -1092,7 +1092,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);
@@ -1139,13 +1139,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 556bbe7..abda70f 100644
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -568,7 +568,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;
}
@@ -603,7 +603,7 @@ xfs_setattr_nonsize(
((XFS_IS_UQUOTA_ON(mp) && iuid != uid) ||
(XFS_IS_GQUOTA_ON(mp) && igid != gid))) {
ASSERT(tp);
- error = xfs_qm_vop_chown_reserve(tp, ip, udqp, gdqp,
+ error = xfs_qm_vop_chown_reserve(tp, ip, udqp, gdqp, NULL,
capable(CAP_FOWNER) ?
XFS_QMOPT_FORCE_RES : 0);
if (error) /* out of quota */
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index 366bbb7..a60d555 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -628,6 +628,7 @@ xfs_sb_to_disk(
xfs_sb_field_t f;
int first;
int size;
+ __be16 saved_qflags = from->sb_qflags;
ASSERT(fields);
if (!fields)
@@ -669,6 +670,7 @@ xfs_sb_to_disk(
fields &= ~(1LL << f);
}
+ from->sb_qflags = saved_qflags;
}
/*
diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c
index cb2ed78..931adc5 100644
--- a/fs/xfs/xfs_qm.c
+++ b/fs/xfs/xfs_qm.c
@@ -408,6 +408,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;
+ }
}
}
@@ -693,29 +697,30 @@ 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. The idea sounds simple, but the
- * execution isn't, because the udquot might have a group dquot attached
+ * Given an ip, attach a ptr to the group/project dquot in ip->i_udquot
+ * as a hint for future lookups. The idea sounds simple, but the execution
+ * isn't, because the udquot might have a group/project dquot attached
* already and getting rid of that gets us into lock ordering constraints.
* The process is complicated more by the fact that the dquots may or may not
* be locked on entry.
*/
STATIC void
-xfs_qm_dqattach_grouphint(
- xfs_dquot_t *udq,
- xfs_dquot_t *gdq)
+xfs_qm_dqattach_grouphint(xfs_inode_t *ip, int type)
{
- xfs_dquot_t *tmp;
+ xfs_dquot_t *udq=ip->i_udquot, *gpdq, **tmp, *tmp1;
+ gpdq = (type == XFS_DQ_GROUP) ? ip->i_gdquot : ip->i_pdquot;
xfs_dqlock(udq);
- if ((tmp = udq->q_gdquot)) {
- if (tmp == gdq) {
+ tmp = (type == XFS_DQ_GROUP) ? &udq->q_gdquot : &udq->q_pdquot;
+ if (*tmp) {
+ if (*tmp == gpdq) {
xfs_dqunlock(udq);
return;
}
- udq->q_gdquot = NULL;
+ tmp1 = *tmp;
+ *tmp = NULL;
/*
* We can't keep any dqlocks when calling dqrele,
* because the freelist lock comes before dqlocks.
@@ -726,28 +731,28 @@ xfs_qm_dqattach_grouphint(
* so give it back when the udquot no longer points at it
* dqput() does the unlocking of the dquot.
*/
- xfs_qm_dqrele(tmp);
+ xfs_qm_dqrele(tmp1);
xfs_dqlock(udq);
- xfs_dqlock(gdq);
+ xfs_dqlock(gpdq);
} else {
ASSERT(XFS_DQ_IS_LOCKED(udq));
- xfs_dqlock(gdq);
+ xfs_dqlock(gpdq);
}
ASSERT(XFS_DQ_IS_LOCKED(udq));
- ASSERT(XFS_DQ_IS_LOCKED(gdq));
+ ASSERT(XFS_DQ_IS_LOCKED(gpdq));
/*
- * Somebody could have attached a gdquot here,
+ * Somebody could have attached a gdquot/pdquot here,
* when we dropped the uqlock. If so, just do nothing.
*/
- if (udq->q_gdquot == NULL) {
- XFS_DQHOLD(gdq);
- udq->q_gdquot = gdq;
+ if (*tmp == NULL) {
+ XFS_DQHOLD(gpdq);
+ *tmp = gpdq;
}
- xfs_dqunlock(gdq);
+ xfs_dqunlock(gpdq);
xfs_dqunlock(udq);
}
@@ -787,12 +792,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);
/*
@@ -804,14 +805,29 @@ 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) {
ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
ASSERT(ip->i_udquot);
ASSERT(ip->i_gdquot);
+ ASSERT(ip->i_pdquot);
/*
* We may or may not have the i_udquot locked at this point,
@@ -819,12 +835,22 @@ xfs_qm_dqattach_locked(
* be accurate 100% all the time. It is just a hint, and this
* will succeed in general.
*/
- if (ip->i_udquot->q_gdquot == ip->i_gdquot)
- goto done;
- /*
- * Attach i_gdquot to the gdquot hint inside the i_udquot.
- */
- xfs_qm_dqattach_grouphint(ip->i_udquot, ip->i_gdquot);
+ if (XFS_IS_GQUOTA_ON(mp) &&
+ ip->i_udquot->q_gdquot != ip->i_gdquot) {
+ /*
+ * Attach i_gdquot to the gdquot hint inside
+ * the i_udquot.
+ */
+ xfs_qm_dqattach_grouphint(ip, XFS_DQ_GROUP);
+ }
+ if (XFS_IS_PQUOTA_ON(mp) &&
+ ip->i_udquot->q_pdquot != ip->i_pdquot) {
+ /*
+ * Attach i_pdquot to the pdquot hint inside
+ * the i_udquot.
+ */
+ xfs_qm_dqattach_grouphint(ip, XFS_DQ_PROJ);
+ }
}
done:
@@ -832,8 +858,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
@@ -863,7 +891,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);
@@ -878,6 +906,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
@@ -1125,6 +1157,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;
@@ -1602,7 +1638,7 @@ xfs_qm_quotacheck(
int done, count, error;
xfs_ino_t lastino;
size_t structsz;
- xfs_inode_t *uip, *gip;
+ xfs_inode_t *uip, *gip, *pip;
uint flags;
count = INT_MAX;
@@ -1610,7 +1646,8 @@ xfs_qm_quotacheck(
lastino = 0;
flags = 0;
- ASSERT(mp->m_quotainfo->qi_uquotaip || mp->m_quotainfo->qi_gquotaip);
+ ASSERT(mp->m_quotainfo->qi_uquotaip || mp->m_quotainfo->qi_gquotaip
+ || mp->m_quotainfo->qi_pquotaip);
ASSERT(XFS_IS_QUOTA_RUNNING(mp));
/*
@@ -1636,12 +1673,18 @@ xfs_qm_quotacheck(
gip = mp->m_quotainfo->qi_gquotaip;
if (gip) {
- error = xfs_qm_dqiterate(mp, gip, XFS_IS_GQUOTA_ON(mp) ?
- XFS_QMOPT_GQUOTA : XFS_QMOPT_PQUOTA);
+ error = xfs_qm_dqiterate(mp, gip, XFS_QMOPT_GQUOTA);
+ if (error)
+ goto error_return;
+ flags |= XFS_GQUOTA_CHKD;
+ }
+
+ pip = mp->m_quotainfo->qi_pquotaip;
+ if (pip) {
+ error = xfs_qm_dqiterate(mp, pip, XFS_QMOPT_PQUOTA);
if (error)
goto error_return;
- flags |= XFS_IS_GQUOTA_ON(mp) ?
- XFS_GQUOTA_CHKD : XFS_PQUOTA_CHKD;
+ flags |= XFS_PQUOTA_CHKD;
}
do {
@@ -1722,13 +1765,13 @@ STATIC int
xfs_qm_init_quotainos(
xfs_mount_t *mp)
{
- xfs_inode_t *uip, *gip;
+ xfs_inode_t *uip, *gip, *pip;
int error;
__int64_t sbflags;
uint flags;
ASSERT(mp->m_quotainfo);
- uip = gip = NULL;
+ uip = gip = pip = NULL;
sbflags = 0;
flags = 0;
@@ -1743,7 +1786,7 @@ xfs_qm_init_quotainos(
0, 0, &uip)))
return XFS_ERROR(error);
}
- if (XFS_IS_OQUOTA_ON(mp) &&
+ if (XFS_IS_GQUOTA_ON(mp) &&
mp->m_sb.sb_gquotino != NULLFSINO) {
ASSERT(mp->m_sb.sb_gquotino > 0);
if ((error = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino,
@@ -1753,6 +1796,18 @@ xfs_qm_init_quotainos(
return XFS_ERROR(error);
}
}
+ if (XFS_IS_PQUOTA_ON(mp) &&
+ mp->m_sb.sb_pquotino != NULLFSINO) {
+ ASSERT(mp->m_sb.sb_pquotino > 0);
+ if ((error = xfs_iget(mp, NULL, mp->m_sb.sb_pquotino,
+ 0, 0, &pip))) {
+ if (uip)
+ IRELE(uip);
+ if (gip)
+ IRELE(gip);
+ return XFS_ERROR(error);
+ }
+ }
} else {
flags |= XFS_QMOPT_SBVERSION;
sbflags |= (XFS_SB_VERSIONNUM | XFS_SB_UQUOTINO |
@@ -1760,7 +1815,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.
@@ -1773,11 +1828,10 @@ 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) {
if (uip)
IRELE(uip);
@@ -1785,9 +1839,23 @@ xfs_qm_init_quotainos(
return XFS_ERROR(error);
}
}
+ 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) {
+ if (uip)
+ IRELE(uip);
+ if (gip)
+ IRELE(gip);
+
+ return XFS_ERROR(error);
+ }
+ }
mp->m_quotainfo->qi_uquotaip = uip;
mp->m_quotainfo->qi_gquotaip = gip;
+ mp->m_quotainfo->qi_pquotaip = pip;
return 0;
}
@@ -2092,10 +2160,11 @@ xfs_qm_vop_dqalloc(
prid_t prid,
uint flags,
struct xfs_dquot **O_udqpp,
- struct xfs_dquot **O_gdqpp)
+ struct xfs_dquot **O_gdqpp,
+ struct xfs_dquot **O_pdqpp)
{
struct xfs_mount *mp = ip->i_mount;
- struct xfs_dquot *uq, *gq;
+ struct xfs_dquot *uq, *gq, *pq;
int error;
uint lockflags;
@@ -2120,7 +2189,7 @@ xfs_qm_vop_dqalloc(
}
}
- uq = gq = NULL;
+ uq = gq = pq = NULL;
if ((flags & XFS_QMOPT_UQUOTA) && XFS_IS_UQUOTA_ON(mp)) {
if (ip->i_d.di_uid != uid) {
/*
@@ -2182,28 +2251,31 @@ xfs_qm_vop_dqalloc(
XFS_DQHOLD(gq);
xfs_dqunlock(gq);
}
- } else if ((flags & XFS_QMOPT_PQUOTA) && XFS_IS_PQUOTA_ON(mp)) {
+ }
+ if ((flags & XFS_QMOPT_PQUOTA) && XFS_IS_PQUOTA_ON(mp)) {
if (xfs_get_projid(ip) != prid) {
xfs_iunlock(ip, lockflags);
if ((error = xfs_qm_dqget(mp, NULL, (xfs_dqid_t)prid,
XFS_DQ_PROJ,
XFS_QMOPT_DQALLOC |
XFS_QMOPT_DOWARN,
- &gq))) {
+ &pq))) {
if (uq)
xfs_qm_dqrele(uq);
+ if (gq)
+ xfs_qm_dqrele(gq);
ASSERT(error != ENOENT);
return (error);
}
- xfs_dqunlock(gq);
+ xfs_dqunlock(pq);
lockflags = XFS_ILOCK_SHARED;
xfs_ilock(ip, lockflags);
} else {
- ASSERT(ip->i_gdquot);
- gq = ip->i_gdquot;
- xfs_dqlock(gq);
- XFS_DQHOLD(gq);
- xfs_dqunlock(gq);
+ ASSERT(ip->i_pdquot);
+ pq = ip->i_pdquot;
+ xfs_dqlock(pq);
+ XFS_DQHOLD(pq);
+ xfs_dqunlock(pq);
}
}
if (uq)
@@ -2218,6 +2290,10 @@ 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;
}
@@ -2274,11 +2350,13 @@ xfs_qm_vop_chown_reserve(
xfs_inode_t *ip,
xfs_dquot_t *udqp,
xfs_dquot_t *gdqp,
+ xfs_dquot_t *pdqp,
uint flags)
{
xfs_mount_t *mp = ip->i_mount;
uint delblks, blkflags, prjflags = 0;
- xfs_dquot_t *unresudq, *unresgdq, *delblksudq, *delblksgdq;
+ xfs_dquot_t *unresudq, *unresgdq, *unrespdq;
+ xfs_dquot_t *delblksudq, *delblksgdq, *delblkspdq;
int error;
@@ -2286,7 +2364,8 @@ xfs_qm_vop_chown_reserve(
ASSERT(XFS_IS_QUOTA_RUNNING(mp));
delblks = ip->i_delayed_blks;
- delblksudq = delblksgdq = unresudq = unresgdq = NULL;
+ delblksudq = delblksgdq = delblkspdq = NULL;
+ unresudq = unresgdq = unrespdq = NULL;
blkflags = XFS_IS_REALTIME_INODE(ip) ?
XFS_QMOPT_RES_RTBLKS : XFS_QMOPT_RES_REGBLKS;
@@ -2303,25 +2382,28 @@ xfs_qm_vop_chown_reserve(
unresudq = ip->i_udquot;
}
}
- if (XFS_IS_OQUOTA_ON(ip->i_mount) && gdqp) {
- if (XFS_IS_PQUOTA_ON(ip->i_mount) &&
- xfs_get_projid(ip) != be32_to_cpu(gdqp->q_core.d_id))
- prjflags = XFS_QMOPT_ENOSPC;
-
- if (prjflags ||
- (XFS_IS_GQUOTA_ON(ip->i_mount) &&
- ip->i_d.di_gid != be32_to_cpu(gdqp->q_core.d_id))) {
- delblksgdq = gdqp;
- if (delblks) {
- ASSERT(ip->i_gdquot);
- unresgdq = ip->i_gdquot;
- }
+ if (XFS_IS_GQUOTA_ON(ip->i_mount) && gdqp &&
+ ip->i_d.di_gid != be32_to_cpu(gdqp->q_core.d_id)) {
+ delblksgdq = gdqp;
+ if (delblks) {
+ ASSERT(ip->i_gdquot);
+ unresgdq = ip->i_gdquot;
+ }
+ }
+
+ if (XFS_IS_PQUOTA_ON(ip->i_mount) && pdqp &&
+ xfs_get_projid(ip) != be32_to_cpu(pdqp->q_core.d_id)) {
+ prjflags = XFS_QMOPT_ENOSPC;
+ delblkspdq = pdqp;
+ if (delblks) {
+ ASSERT(ip->i_pdquot);
+ unrespdq = ip->i_pdquot;
}
}
if ((error = xfs_trans_reserve_quota_bydquots(tp, ip->i_mount,
- delblksudq, delblksgdq, ip->i_d.di_nblocks, 1,
- flags | blkflags | prjflags)))
+ delblksudq, delblksgdq, delblkspdq, ip->i_d.di_nblocks,
+ 1, flags | blkflags | prjflags)))
return (error);
/*
@@ -2334,15 +2416,16 @@ xfs_qm_vop_chown_reserve(
/*
* Do the reservations first. Unreservation can't fail.
*/
- ASSERT(delblksudq || delblksgdq);
- ASSERT(unresudq || unresgdq);
+ ASSERT(delblksudq || delblksgdq || delblkspdq);
+ ASSERT(unresudq || unresgdq || unrespdq);
if ((error = xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount,
- delblksudq, delblksgdq, (xfs_qcnt_t)delblks, 0,
+ delblksudq, delblksgdq, delblkspdq,
+ (xfs_qcnt_t)delblks, 0,
flags | blkflags | prjflags)))
return (error);
xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount,
- unresudq, unresgdq, -((xfs_qcnt_t)delblks), 0,
- blkflags);
+ unresudq, unresgdq, unrespdq,
+ -((xfs_qcnt_t)delblks), 0, blkflags);
}
return (0);
@@ -2381,7 +2464,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;
@@ -2395,9 +2479,9 @@ xfs_qm_vop_create_dqattach(
xfs_dqlock(udqp);
XFS_DQHOLD(udqp);
xfs_dqunlock(udqp);
- ASSERT(ip->i_udquot == NULL);
+ ASSERT_ALWAYS(ip->i_udquot == NULL);
ip->i_udquot = udqp;
- ASSERT(XFS_IS_UQUOTA_ON(mp));
+ ASSERT_ALWAYS(XFS_IS_UQUOTA_ON(mp));
ASSERT(ip->i_d.di_uid == be32_to_cpu(udqp->q_core.d_id));
xfs_trans_mod_dquot(tp, udqp, XFS_TRANS_DQ_ICOUNT, 1);
}
@@ -2405,13 +2489,22 @@ xfs_qm_vop_create_dqattach(
xfs_dqlock(gdqp);
XFS_DQHOLD(gdqp);
xfs_dqunlock(gdqp);
- ASSERT(ip->i_gdquot == NULL);
+ ASSERT_ALWAYS(ip->i_gdquot == NULL);
ip->i_gdquot = gdqp;
- 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_ALWAYS(XFS_IS_GQUOTA_ON(mp));
+ ASSERT(ip->i_d.di_gid == be32_to_cpu(gdqp->q_core.d_id));
xfs_trans_mod_dquot(tp, gdqp, XFS_TRANS_DQ_ICOUNT, 1);
}
+ if (pdqp) {
+ xfs_dqlock(pdqp);
+ XFS_DQHOLD(pdqp);
+ xfs_dqunlock(pdqp);
+ ASSERT_ALWAYS(pdqp);
+ ASSERT_ALWAYS(ip->i_pdquot == NULL);
+ ip->i_pdquot = pdqp;
+ ASSERT_ALWAYS(XFS_IS_PQUOTA_ON(mp));
+ ASSERT(xfs_get_projid(ip) == be32_to_cpu(gdqp->q_core.d_id));
+ 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 43b9abe..289ae66 100644
--- a/fs/xfs/xfs_qm.h
+++ b/fs/xfs/xfs_qm.h
@@ -92,6 +92,7 @@ typedef struct xfs_qm {
typedef struct xfs_quotainfo {
xfs_inode_t *qi_uquotaip; /* user quota inode */
xfs_inode_t *qi_gquotaip; /* group quota inode */
+ xfs_inode_t *qi_pquotaip; /* project quota inode */
struct list_head qi_dqlist; /* all dquots in filesys */
struct mutex qi_dqlist_lock;
int qi_dquots;
@@ -116,8 +117,6 @@ typedef struct xfs_quotainfo {
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 *);
@@ -130,6 +129,7 @@ extern void xfs_trans_log_dquot(xfs_trans_t *, xfs_dquot_t *);
typedef struct xfs_dquot_acct {
xfs_dqtrx_t dqa_usrdquots[XFS_QM_TRANS_MAXDQS];
xfs_dqtrx_t dqa_grpdquots[XFS_QM_TRANS_MAXDQS];
+ xfs_dqtrx_t dqa_prjdquots[XFS_QM_TRANS_MAXDQS];
} xfs_dquot_acct_t;
/*
diff --git a/fs/xfs/xfs_qm_bhv.c b/fs/xfs/xfs_qm_bhv.c
index a0a829a..c9b05f1 100644
--- a/fs/xfs/xfs_qm_bhv.c
+++ b/fs/xfs/xfs_qm_bhv.c
@@ -117,7 +117,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 3a67805..5f3f2d3 100644
--- a/fs/xfs/xfs_qm_syscalls.c
+++ b/fs/xfs/xfs_qm_syscalls.c
@@ -222,10 +222,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);
@@ -872,9 +876,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;
}
@@ -883,10 +889,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 41483d8..c50dd76 100644
--- a/fs/xfs/xfs_quota.h
+++ b/fs/xfs/xfs_quota.h
@@ -189,9 +189,9 @@ typedef struct xfs_qoff_logformat {
* 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 */
/*
* Checking XFS_IS_*QUOTA_ON() while holding any inode lock guarantees
@@ -200,8 +200,6 @@ typedef struct xfs_qoff_logformat {
#define XFS_IS_QUOTA_ON(mp) ((mp)->m_qflags & (XFS_UQUOTA_ACTIVE | \
XFS_GQUOTA_ACTIVE | \
XFS_PQUOTA_ACTIVE))
-#define XFS_IS_OQUOTA_ON(mp) ((mp)->m_qflags & (XFS_GQUOTA_ACTIVE | \
- XFS_PQUOTA_ACTIVE))
#define XFS_IS_UQUOTA_ON(mp) ((mp)->m_qflags & XFS_UQUOTA_ACTIVE)
#define XFS_IS_GQUOTA_ON(mp) ((mp)->m_qflags & XFS_GQUOTA_ACTIVE)
#define XFS_IS_PQUOTA_ON(mp) ((mp)->m_qflags & XFS_PQUOTA_ACTIVE)
@@ -269,8 +267,10 @@ typedef struct xfs_qoff_logformat {
*/
#define XFS_NOT_DQATTACHED(mp, ip) ((XFS_IS_UQUOTA_ON(mp) &&\
(ip)->i_udquot == NULL) || \
- (XFS_IS_OQUOTA_ON(mp) && \
- (ip)->i_gdquot == NULL))
+ (XFS_IS_GQUOTA_ON(mp) && \
+ (ip)->i_gdquot == NULL) || \
+ (XFS_IS_PQUOTA_ON(mp) && \
+ (ip)->i_pdquot == NULL))
#define XFS_QM_NEED_QUOTACHECK(mp) \
((XFS_IS_UQUOTA_ON(mp) && \
@@ -325,17 +325,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 *);
@@ -350,10 +351,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,
+ xfs_dquot **pdqp)
{
*udqp = NULL;
*gdqp = NULL;
+ *pdqp = NULL;
return 0;
}
#define xfs_trans_dup_dqinfo(tp, tp2)
@@ -368,14 +371,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)
@@ -393,8 +397,8 @@ static inline int xfs_qm_sync(struct xfs_mount *mp, int flags)
#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_sb.h b/fs/xfs/xfs_sb.h
index cb6ae71..5242512 100644
--- a/fs/xfs/xfs_sb.h
+++ b/fs/xfs/xfs_sb.h
@@ -140,6 +140,7 @@ typedef struct xfs_sb {
*/
xfs_ino_t sb_uquotino; /* user quota inode */
xfs_ino_t sb_gquotino; /* group quota inode */
+#define sb_pquotino sb_gquotino
__uint16_t sb_qflags; /* quota flags */
__uint8_t sb_flags; /* misc. flags */
__uint8_t sb_shared_vn; /* shared version number */
diff --git a/fs/xfs/xfs_trans_dquot.c b/fs/xfs/xfs_trans_dquot.c
index bea957d..3f84601 100644
--- a/fs/xfs/xfs_trans_dquot.c
+++ b/fs/xfs/xfs_trans_dquot.c
@@ -115,7 +115,7 @@ xfs_trans_dup_dqinfo(
if(otp->t_flags & XFS_TRANS_DQ_DIRTY)
ntp->t_flags |= XFS_TRANS_DQ_DIRTY;
- for (j = 0; j < 2; j++) {
+ for (j = 0; j < 3; j++) { /* 0 - usr, 1 - grp, 2 - prj */
for (i = 0; i < XFS_QM_TRANS_MAXDQS; i++) {
if (oqa[i].qt_dquot == NULL)
break;
@@ -140,8 +140,13 @@ xfs_trans_dup_dqinfo(
oq->qt_ino_res = oq->qt_ino_res_used;
}
- oqa = otp->t_dqinfo->dqa_grpdquots;
- nqa = ntp->t_dqinfo->dqa_grpdquots;
+ if (oqa == otp->t_dqinfo->dqa_usrdquots) {
+ oqa = otp->t_dqinfo->dqa_grpdquots;
+ nqa = ntp->t_dqinfo->dqa_grpdquots;
+ } else {
+ oqa = otp->t_dqinfo->dqa_prjdquots;
+ nqa = ntp->t_dqinfo->dqa_prjdquots;
+ }
}
}
@@ -168,8 +173,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 xfs_dqtrx_t *
@@ -180,8 +187,12 @@ xfs_trans_get_dqtrx(
int i;
xfs_dqtrx_t *qa;
- qa = XFS_QM_ISUDQ(dqp) ?
- tp->t_dqinfo->dqa_usrdquots : tp->t_dqinfo->dqa_grpdquots;
+ if (XFS_QM_ISUDQ(dqp))
+ qa = tp->t_dqinfo->dqa_usrdquots;
+ else if (XFS_QM_ISGDQ(dqp))
+ qa = tp->t_dqinfo->dqa_grpdquots;
+ else
+ qa = tp->t_dqinfo->dqa_prjdquots;
for (i = 0; i < XFS_QM_TRANS_MAXDQS; i++) {
if (qa[i].qt_dquot == NULL ||
@@ -342,12 +353,14 @@ xfs_trans_apply_dquot_deltas(
ASSERT(tp->t_dqinfo);
qa = tp->t_dqinfo->dqa_usrdquots;
- for (j = 0; j < 2; j++) {
+ for (j = 0; j < 3; j++) { /* 0 - usr, 1 - grp, 2 - prj */
if (qa[0].qt_dquot == NULL) {
- qa = tp->t_dqinfo->dqa_grpdquots;
+ if (qa == tp->t_dqinfo->dqa_usrdquots)
+ qa = tp->t_dqinfo->dqa_grpdquots;
+ else
+ qa = tp->t_dqinfo->dqa_prjdquots;
continue;
}
-
/*
* Lock all of the dquots and join them to the transaction.
*/
@@ -498,9 +511,12 @@ xfs_trans_apply_dquot_deltas(
be64_to_cpu(dqp->q_core.d_rtbcount));
}
/*
- * Do the group quotas next
+ * Do the group quotas or project quotas next
*/
- qa = tp->t_dqinfo->dqa_grpdquots;
+ if (qa == tp->t_dqinfo->dqa_usrdquots)
+ qa = tp->t_dqinfo->dqa_grpdquots;
+ else
+ qa = tp->t_dqinfo->dqa_prjdquots;
}
}
@@ -525,7 +541,7 @@ xfs_trans_unreserve_and_mod_dquots(
qa = tp->t_dqinfo->dqa_usrdquots;
- for (j = 0; j < 2; j++) {
+ for (j = 0; j < 3; j++) { /* 0 - usr, 1 - grp, 2 - prj */
for (i = 0; i < XFS_QM_TRANS_MAXDQS; i++) {
qtrx = &qa[i];
/*
@@ -567,7 +583,10 @@ xfs_trans_unreserve_and_mod_dquots(
xfs_dqunlock(dqp);
}
- qa = tp->t_dqinfo->dqa_grpdquots;
+ if (qa == tp->t_dqinfo->dqa_usrdquots)
+ qa = tp->t_dqinfo->dqa_grpdquots;
+ else
+ qa = tp->t_dqinfo->dqa_prjdquots;
}
}
@@ -737,8 +756,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.
@@ -753,6 +772,7 @@ xfs_trans_reserve_quota_bydquots(
xfs_mount_t *mp,
xfs_dquot_t *udqp,
xfs_dquot_t *gdqp,
+ xfs_dquot_t *pdqp,
long nblks,
long ninos,
uint flags)
@@ -790,6 +810,24 @@ xfs_trans_reserve_quota_bydquots(
}
}
+ if (pdqp) {
+ error = xfs_trans_dqresv(tp, mp, pdqp, nblks, ninos, flags);
+ if (error) {
+ /*
+ * can't do it, so backout previous reservation
+ */
+ if (resvd) {
+ flags |= XFS_QMOPT_FORCE_RES;
+ xfs_trans_dqresv(tp, mp, udqp,
+ -nblks, -ninos, flags);
+ if (gdqp)
+ xfs_trans_dqresv(tp, mp, gdqp,
+ -nblks, -ninos, flags);
+ }
+ return error;
+ }
+ }
+
/*
* Didn't change anything critical, so, no need to log
*/
@@ -831,6 +869,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 4ecf2a5..404096a 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -833,6 +833,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;
@@ -851,7 +852,7 @@ xfs_create(
* Make sure that we have allocated dquot(s) on disk.
*/
error = xfs_qm_vop_dqalloc(dp, current_fsuid(), current_fsgid(), prid,
- XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp);
+ XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp, &pdqp);
if (error)
return error;
@@ -911,7 +912,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;
@@ -975,7 +977,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)
@@ -987,6 +989,7 @@ xfs_create(
xfs_qm_dqrele(udqp);
xfs_qm_dqrele(gdqp);
+ xfs_qm_dqrele(pdqp);
*ipp = ip;
return 0;
@@ -1008,6 +1011,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);
@@ -1498,7 +1502,7 @@ xfs_symlink(
int n;
xfs_buf_t *bp;
prid_t prid;
- struct xfs_dquot *udqp, *gdqp;
+ struct xfs_dquot *udqp, *gdqp, *pdqp;
uint resblks;
*ipp = NULL;
@@ -1528,7 +1532,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;
@@ -1569,7 +1573,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;
@@ -1607,7 +1612,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);
@@ -1691,6 +1696,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;
@@ -1704,6 +1710,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);
@@ -2170,7 +2177,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] 11+ messages in thread
* [RFC PATCH 3/3] Add pquotaino to on-disk super block
2011-10-18 0:09 [RFC PATCH 0/3] Allow pquota and gquota to be used together Chandra Seetharaman
2011-10-18 0:09 ` [RFC PATCH 1/3] Remove in core use of XFS_OQUOTA_ENFD and XFS_OQUOTA_CHKD Chandra Seetharaman
2011-10-18 0:09 ` [RFC PATCH 2/3] Add pquota fields where gquota is used Chandra Seetharaman
@ 2011-10-18 0:09 ` Chandra Seetharaman
2011-10-26 16:14 ` Alex Elder
2 siblings, 1 reply; 11+ messages in thread
From: Chandra Seetharaman @ 2011-10-18 0:09 UTC (permalink / raw)
To: xfs; +Cc: Chandra Seetharaman
Add a new field to the superblock to add support for seperate pquota
with a specific version.
No change made yet to gather both project and group quota with quotactl.
Signed-off-by: Chandra Seetharaman <sekharan@us.ibm.com>
---
fs/xfs/xfs_itable.c | 3 ++-
fs/xfs/xfs_mount.c | 32 +++++++++++++++++++++++++++++++-
fs/xfs/xfs_qm.c | 18 ++++++++++++------
fs/xfs/xfs_qm_syscalls.c | 27 ++++++++++++++++++++++-----
fs/xfs/xfs_sb.h | 18 ++++++++++++++----
fs/xfs/xfs_super.c | 15 +++++++++------
fs/xfs/xfs_trans_dquot.c | 4 +++-
include/linux/dqblk_xfs.h | 1 +
8 files changed, 94 insertions(+), 24 deletions(-)
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
index 751e94f..0ea4361 100644
--- a/fs/xfs/xfs_itable.c
+++ b/fs/xfs/xfs_itable.c
@@ -43,7 +43,8 @@ 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)));
+ (ino == mp->m_sb.sb_uquotino || ino == mp->m_sb.sb_gquotino ||
+ ino == mp->m_sb.sb_pquotino)));
}
/*
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index a60d555..935d0cb 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -108,6 +108,7 @@ static const struct {
{ offsetof(xfs_sb_t, sb_logsunit), 0 },
{ offsetof(xfs_sb_t, sb_features2), 0 },
{ offsetof(xfs_sb_t, sb_bad_features2), 0 },
+ { offsetof(xfs_sb_t, sb_pquotino), 0 },
{ sizeof(xfs_sb_t), 0 }
};
@@ -610,6 +611,11 @@ xfs_sb_from_disk(
to->sb_logsunit = be32_to_cpu(from->sb_logsunit);
to->sb_features2 = be32_to_cpu(from->sb_features2);
to->sb_bad_features2 = be32_to_cpu(from->sb_bad_features2);
+
+ if (xfs_sb_version_hasseparatepquota(to))
+ to->sb_pquotino = be64_to_cpu(from->sb_pquotino);
+ else if (to->sb_qflags & XFS_PQUOTA_ACCT)
+ to->sb_pquotino = to->sb_gquotino;
}
/*
@@ -627,7 +633,7 @@ xfs_sb_to_disk(
xfs_caddr_t from_ptr = (xfs_caddr_t)from;
xfs_sb_field_t f;
int first;
- int size;
+ int size, saved_pquot = B_FALSE;
__be16 saved_qflags = from->sb_qflags;
ASSERT(fields);
@@ -640,6 +646,14 @@ xfs_sb_to_disk(
from->sb_qflags |= XFS_OQUOTA_CHKD;
from->sb_qflags &= ~(XFS_PQUOTA_ENFD | XFS_PQUOTA_CHKD |
XFS_GQUOTA_ENFD | XFS_GQUOTA_CHKD);
+
+ if (!xfs_sb_version_hasseparatepquota(from) &&
+ (saved_qflags & (XFS_PQUOTA_ENFD | XFS_PQUOTA_CHKD))) {
+ from->sb_gquotino = from->sb_pquotino;
+ from->sb_pquotino = 0;
+ saved_pquot = B_TRUE;
+ }
+
while (fields) {
f = (xfs_sb_field_t)xfs_lowbit64((__uint64_t)fields);
first = xfs_sb_info[f].offset;
@@ -671,6 +685,10 @@ xfs_sb_to_disk(
fields &= ~(1LL << f);
}
from->sb_qflags = saved_qflags;
+ if (saved_pquot) {
+ from->sb_pquotino = from->sb_gquotino;
+ from->sb_gquotino = NULLFSINO;
+ }
}
/*
@@ -738,6 +756,12 @@ reread:
goto reread;
}
+ if (!xfs_sb_version_hasseparatepquota(&mp->m_sb) &&
+ XFS_IS_PQUOTA_ON(mp)) {
+ mp->m_sb.sb_pquotino = mp->m_sb.sb_gquotino;
+ mp->m_sb.sb_gquotino = NULLFSINO;
+ }
+
/* Initialize per-cpu counters */
xfs_icsb_reinit_counters(mp);
@@ -1656,6 +1680,12 @@ xfs_mod_sb(xfs_trans_t *tp, __int64_t fields)
first = sizeof(xfs_sb_t);
last = 0;
+ if (!xfs_sb_version_hasseparatepquota(&mp->m_sb) &&
+ XFS_IS_PQUOTA_ON(mp)) {
+ fields &= (__int64_t)~XFS_SB_PQUOTINO;
+ fields |= (__int64_t)XFS_SB_GQUOTINO;
+ }
+
/* translate/copy */
xfs_sb_to_disk(XFS_BUF_TO_SBP(bp), &mp->m_sb, fields);
diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c
index 931adc5..dc884f9 100644
--- a/fs/xfs/xfs_qm.c
+++ b/fs/xfs/xfs_qm.c
@@ -777,7 +777,8 @@ xfs_qm_dqattach_locked(
!XFS_IS_QUOTA_ON(mp) ||
!XFS_NOT_DQATTACHED(mp, ip) ||
ip->i_ino == mp->m_sb.sb_uquotino ||
- ip->i_ino == mp->m_sb.sb_gquotino)
+ ip->i_ino == mp->m_sb.sb_gquotino ||
+ ip->i_ino == mp->m_sb.sb_pquotino)
return 0;
ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
@@ -898,6 +899,7 @@ xfs_qm_dqdetach(
ASSERT(ip->i_ino != ip->i_mount->m_sb.sb_uquotino);
ASSERT(ip->i_ino != ip->i_mount->m_sb.sb_gquotino);
+ ASSERT(ip->i_ino != ip->i_mount->m_sb.sb_pquotino);
if (ip->i_udquot) {
xfs_qm_dqrele(ip->i_udquot);
ip->i_udquot = NULL;
@@ -1233,19 +1235,22 @@ xfs_qm_qino_alloc(
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_GQUOTINO | XFS_SB_PQUOTINO | 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);
@@ -1552,7 +1557,8 @@ 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 (ino == mp->m_sb.sb_uquotino || ino == mp->m_sb.sb_gquotino ||
+ ino == mp->m_sb.sb_pquotino) {
*res = BULKSTAT_RV_NOTHING;
return XFS_ERROR(EINVAL);
}
@@ -1811,7 +1817,7 @@ xfs_qm_init_quotainos(
} else {
flags |= XFS_QMOPT_SBVERSION;
sbflags |= (XFS_SB_VERSIONNUM | XFS_SB_UQUOTINO |
- XFS_SB_GQUOTINO | XFS_SB_QFLAGS);
+ XFS_SB_GQUOTINO | XFS_SB_PQUOTINO | XFS_SB_QFLAGS);
}
/*
@@ -1841,7 +1847,7 @@ xfs_qm_init_quotainos(
}
if (XFS_IS_PQUOTA_ON(mp) && pip == NULL) {
error = xfs_qm_qino_alloc(mp, &pip,
- sbflags | XFS_SB_GQUOTINO,
+ sbflags | XFS_SB_PQUOTINO,
flags | XFS_QMOPT_PQUOTA);
if (error) {
if (uip)
diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c
index 5f3f2d3..407a45d 100644
--- a/fs/xfs/xfs_qm_syscalls.c
+++ b/fs/xfs/xfs_qm_syscalls.c
@@ -299,8 +299,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;
}
@@ -416,17 +418,18 @@ xfs_qm_scall_getqstat(
struct fs_quota_stat *out)
{
struct xfs_quotainfo *q = mp->m_quotainfo;
- struct xfs_inode *uip, *gip;
- boolean_t tempuqip, tempgqip;
+ struct xfs_inode *uip, *gip, *pip;
+ boolean_t tempuqip, tempgqip, temppqip;
- uip = gip = NULL;
- tempuqip = tempgqip = B_FALSE;
+ uip = gip = pip = NULL;
+ tempuqip = tempgqip = temppqip = B_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;
+ out->qs_pquota.qfs_ino = NULLFSINO;
return (0);
}
out->qs_flags = (__uint16_t) xfs_qm_export_flags(mp->m_qflags &
@@ -435,10 +438,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,
@@ -450,6 +456,11 @@ xfs_qm_scall_getqstat(
0, 0, &gip) == 0)
tempgqip = B_TRUE;
}
+ if (!pip && mp->m_sb.sb_pquotino != NULLFSINO) {
+ if (xfs_iget(mp, NULL, mp->m_sb.sb_pquotino,
+ 0, 0, &pip) == 0)
+ temppqip = B_TRUE;
+ }
if (uip) {
out->qs_uquota.qfs_nblks = uip->i_d.di_nblocks;
out->qs_uquota.qfs_nextents = uip->i_d.di_nextents;
@@ -462,6 +473,12 @@ xfs_qm_scall_getqstat(
if (tempgqip)
IRELE(gip);
}
+ if (pip) {
+ out->qs_gquota.qfs_nblks = pip->i_d.di_nblocks;
+ out->qs_gquota.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_sb.h b/fs/xfs/xfs_sb.h
index 5242512..6ecd5b6 100644
--- a/fs/xfs/xfs_sb.h
+++ b/fs/xfs/xfs_sb.h
@@ -81,11 +81,13 @@ struct xfs_mount;
#define XFS_SB_VERSION2_ATTR2BIT 0x00000008 /* Inline attr rework */
#define XFS_SB_VERSION2_PARENTBIT 0x00000010 /* parent pointers */
#define XFS_SB_VERSION2_PROJID32BIT 0x00000080 /* 32 bit project id */
+#define XFS_SB_VERSION2_SEPER_PQUOTA 0x00000100 /* sep prj quota inode */
#define XFS_SB_VERSION2_OKREALFBITS \
(XFS_SB_VERSION2_LAZYSBCOUNTBIT | \
XFS_SB_VERSION2_ATTR2BIT | \
- XFS_SB_VERSION2_PROJID32BIT)
+ XFS_SB_VERSION2_PROJID32BIT | \
+ XFS_SB_VERSION2_SEPER_PQUOTA)
#define XFS_SB_VERSION2_OKSASHFBITS \
(0)
#define XFS_SB_VERSION2_OKREALBITS \
@@ -140,7 +142,6 @@ typedef struct xfs_sb {
*/
xfs_ino_t sb_uquotino; /* user quota inode */
xfs_ino_t sb_gquotino; /* group quota inode */
-#define sb_pquotino sb_gquotino
__uint16_t sb_qflags; /* quota flags */
__uint8_t sb_flags; /* misc. flags */
__uint8_t sb_shared_vn; /* shared version number */
@@ -160,6 +161,7 @@ typedef struct xfs_sb {
* it for anything else.
*/
__uint32_t sb_bad_features2;
+ xfs_ino_t sb_pquotino; /* project quota inode */
/* must be padded to 64 bit alignment */
} xfs_sb_t;
@@ -230,6 +232,7 @@ typedef struct xfs_dsb {
* it for anything else.
*/
__be32 sb_bad_features2;
+ __be64 sb_pquotino; /* project quota inode */
/* must be padded to 64 bit alignment */
} xfs_dsb_t;
@@ -250,7 +253,7 @@ typedef enum {
XFS_SBS_GQUOTINO, XFS_SBS_QFLAGS, XFS_SBS_FLAGS, XFS_SBS_SHARED_VN,
XFS_SBS_INOALIGNMT, XFS_SBS_UNIT, XFS_SBS_WIDTH, XFS_SBS_DIRBLKLOG,
XFS_SBS_LOGSECTLOG, XFS_SBS_LOGSECTSIZE, XFS_SBS_LOGSUNIT,
- XFS_SBS_FEATURES2, XFS_SBS_BAD_FEATURES2,
+ XFS_SBS_FEATURES2, XFS_SBS_BAD_FEATURES2, XFS_SBS_PQUOTINO,
XFS_SBS_FIELDCOUNT
} xfs_sb_field_t;
@@ -276,6 +279,7 @@ typedef enum {
#define XFS_SB_FDBLOCKS XFS_SB_MVAL(FDBLOCKS)
#define XFS_SB_FEATURES2 XFS_SB_MVAL(FEATURES2)
#define XFS_SB_BAD_FEATURES2 XFS_SB_MVAL(BAD_FEATURES2)
+#define XFS_SB_PQUOTINO XFS_SB_MVAL(PQUOTINO)
#define XFS_SB_NUM_BITS ((int)XFS_SBS_FIELDCOUNT)
#define XFS_SB_ALL_BITS ((1LL << XFS_SB_NUM_BITS) - 1)
#define XFS_SB_MOD_BITS \
@@ -283,7 +287,7 @@ typedef enum {
XFS_SB_VERSIONNUM | XFS_SB_UQUOTINO | XFS_SB_GQUOTINO | \
XFS_SB_QFLAGS | XFS_SB_SHARED_VN | XFS_SB_UNIT | XFS_SB_WIDTH | \
XFS_SB_ICOUNT | XFS_SB_IFREE | XFS_SB_FDBLOCKS | XFS_SB_FEATURES2 | \
- XFS_SB_BAD_FEATURES2)
+ XFS_SB_BAD_FEATURES2 | XFS_SB_PQUOTINO)
/*
@@ -504,6 +508,12 @@ static inline int xfs_sb_version_hasprojid32bit(xfs_sb_t *sbp)
(sbp->sb_features2 & XFS_SB_VERSION2_PROJID32BIT);
}
+static inline int xfs_sb_version_hasseparatepquota(xfs_sb_t *sbp)
+{
+ return xfs_sb_version_hasmorebits(sbp) &&
+ (sbp->sb_features2 & XFS_SB_VERSION2_SEPER_PQUOTA);
+}
+
/*
* end of superblock version macros
*/
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
index b1c8d5b..9c094bd 100644
--- a/fs/xfs/xfs_super.c
+++ b/fs/xfs/xfs_super.c
@@ -410,12 +410,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;
@@ -1362,6 +1356,15 @@ xfs_fs_fill_super(
if (error)
goto out_destroy_counters;
+ if ((mp->m_qflags & (XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE)) &&
+ (mp->m_qflags & (XFS_PQUOTA_ACCT | XFS_PQUOTA_ACTIVE)) &&
+ !xfs_sb_version_hasseparatepquota(&mp->m_sb)) {
+ xfs_warn(mp, "Super block does not support "
+ "project and group quota together");
+ error = EINVAL;
+ goto out_free_sb;
+ }
+
error = xfs_finish_flags(mp);
if (error)
goto out_free_sb;
diff --git a/fs/xfs/xfs_trans_dquot.c b/fs/xfs/xfs_trans_dquot.c
index 3f84601..c0d9957 100644
--- a/fs/xfs/xfs_trans_dquot.c
+++ b/fs/xfs/xfs_trans_dquot.c
@@ -165,7 +165,8 @@ 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)
+ ip->i_ino == mp->m_sb.sb_gquotino ||
+ ip->i_ino == mp->m_sb.sb_pquotino)
return;
if (tp->t_dqinfo == NULL)
@@ -857,6 +858,7 @@ xfs_trans_reserve_quota_nblks(
ASSERT(ip->i_ino != mp->m_sb.sb_uquotino);
ASSERT(ip->i_ino != mp->m_sb.sb_gquotino);
+ ASSERT(ip->i_ino != mp->m_sb.sb_pquotino);
ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
ASSERT((flags & ~(XFS_QMOPT_FORCE_RES | XFS_QMOPT_ENOSPC)) ==
diff --git a/include/linux/dqblk_xfs.h b/include/linux/dqblk_xfs.h
index 8655280..f17e3bb 100644
--- a/include/linux/dqblk_xfs.h
+++ b/include/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] 11+ messages in thread
* Re: [RFC PATCH 1/3] Remove in core use of XFS_OQUOTA_ENFD and XFS_OQUOTA_CHKD
2011-10-18 0:09 ` [RFC PATCH 1/3] Remove in core use of XFS_OQUOTA_ENFD and XFS_OQUOTA_CHKD Chandra Seetharaman
@ 2011-10-18 5:16 ` Arkadiusz Miśkiewicz
2011-10-18 14:15 ` Chandra Seetharaman
2011-10-18 22:40 ` Alex Elder
1 sibling, 1 reply; 11+ messages in thread
From: Arkadiusz Miśkiewicz @ 2011-10-18 5:16 UTC (permalink / raw)
To: xfs; +Cc: Chandra Seetharaman
On Tuesday 18 of October 2011, Chandra Seetharaman wrote:
Quick look for diff between your and mine patch when I was playing with
separate project quota some time ago and:
> diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c
> index 5cc3dde..3a67805 100644
> --- a/fs/xfs/xfs_qm_syscalls.c
> +++ b/fs/xfs/xfs_qm_syscalls.c
> @@ -120,11 +120,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) {
These can be separate so, no else if but just separate if.
> diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
> index ba16248..b1c8d5b 100644
> --- a/fs/xfs/xfs_super.c
> +++ b/fs/xfs/xfs_super.c
> @@ -552,12 +553,12 @@ xfs_showargs(
> /* Either project or group quotas can be active, not both */
No longer true.
>
> 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) {
Also not else if - just if.
> - if (mp->m_qflags & XFS_OQUOTA_ENFD)
> + if (mp->m_qflags & XFS_GQUOTA_ENFD)
--
Arkadiusz Miśkiewicz PLD/Linux Team
arekm / maven.pl http://ftp.pld-linux.org/
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFC PATCH 1/3] Remove in core use of XFS_OQUOTA_ENFD and XFS_OQUOTA_CHKD
2011-10-18 5:16 ` Arkadiusz Miśkiewicz
@ 2011-10-18 14:15 ` Chandra Seetharaman
0 siblings, 0 replies; 11+ messages in thread
From: Chandra Seetharaman @ 2011-10-18 14:15 UTC (permalink / raw)
To: Arkadiusz Miśkiewicz; +Cc: xfs
Good catch. Will fix them in the next iteration.
Thanks.
Chandra
On Tue, 2011-10-18 at 07:16 +0200, Arkadiusz Miśkiewicz wrote:
> On Tuesday 18 of October 2011, Chandra Seetharaman wrote:
>
> Quick look for diff between your and mine patch when I was playing with
> separate project quota some time ago and:
>
> > diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c
> > index 5cc3dde..3a67805 100644
> > --- a/fs/xfs/xfs_qm_syscalls.c
> > +++ b/fs/xfs/xfs_qm_syscalls.c
> > @@ -120,11 +120,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) {
>
> These can be separate so, no else if but just separate if.
>
>
> > diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
> > index ba16248..b1c8d5b 100644
> > --- a/fs/xfs/xfs_super.c
> > +++ b/fs/xfs/xfs_super.c
>
> > @@ -552,12 +553,12 @@ xfs_showargs(
> > /* Either project or group quotas can be active, not both */
>
> No longer true.
>
> >
> > 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) {
>
> Also not else if - just if.
>
> > - if (mp->m_qflags & XFS_OQUOTA_ENFD)
> > + if (mp->m_qflags & XFS_GQUOTA_ENFD)
>
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFC PATCH 1/3] Remove in core use of XFS_OQUOTA_ENFD and XFS_OQUOTA_CHKD
2011-10-18 0:09 ` [RFC PATCH 1/3] Remove in core use of XFS_OQUOTA_ENFD and XFS_OQUOTA_CHKD Chandra Seetharaman
2011-10-18 5:16 ` Arkadiusz Miśkiewicz
@ 2011-10-18 22:40 ` Alex Elder
2011-10-19 15:06 ` Chandra Seetharaman
1 sibling, 1 reply; 11+ messages in thread
From: Alex Elder @ 2011-10-18 22:40 UTC (permalink / raw)
To: Chandra Seetharaman; +Cc: xfs
On Mon, 2011-10-17 at 19:09 -0500, Chandra Seetharaman wrote:
> Remove incore use of XFS_OQUOTA_ENFD and XFS_OQUOTA_CHKD. Instead,
> start using XFS_GQUOTA_.* XFS_PQUOTA_.* counterparts.
>
> No changes is made to the on-disk version of the superblock yey. On-disk
> copy still uses XFS_OQUOTA_ENFD and XFS_OQUOTA_CHKD.
>
> Signed-off-by: Chandra Seetharaman <sekharan@us.ibm.com>
OK, I have a few things you should change below.
Some are based on the assumption that where we're
headed is to support *both* group *and* project
quotas simultaneously.
I haven't looked at the other two yet, I'll start
that tomorrow.
-Alex
. . .
> diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
> index d06afbc..366bbb7 100644
> --- a/fs/xfs/xfs_mount.c
> +++ b/fs/xfs/xfs_mount.c
> @@ -591,6 +591,14 @@ xfs_sb_from_disk(
> to->sb_uquotino = be64_to_cpu(from->sb_uquotino);
> to->sb_gquotino = be64_to_cpu(from->sb_gquotino);
> to->sb_qflags = be16_to_cpu(from->sb_qflags);
OK, based on the comment you have in "xfs_quota.h" below:
This stuff is coming off disk, so it will be done
unconditionally (i.e., not related to the superblock
version). However, you could add an assertion that
if OQUOTA_ENFD or OQUOTA_CHKD are set, then neither
{P,G}QUOTA_{CHKD,ENFD} is set, and vice-versa.
Or perhaps not an assertion, maybe just issue a
warning and correct it. (Or perhaps some other
handling is more appropriate, have to think it
through.)
> + if (to->sb_qflags & XFS_OQUOTA_ENFD)
> + to->sb_qflags |= (to->sb_qflags & XFS_PQUOTA_ACCT) ?
> + XFS_PQUOTA_ENFD : XFS_GQUOTA_ENFD;
> + if (to->sb_qflags & XFS_OQUOTA_CHKD)
> + to->sb_qflags |= (to->sb_qflags & XFS_PQUOTA_ACCT) ?
> + XFS_PQUOTA_CHKD : XFS_GQUOTA_CHKD;
> + to->sb_qflags &= ~(XFS_OQUOTA_ENFD | XFS_OQUOTA_CHKD);
> +
> to->sb_flags = from->sb_flags;
> to->sb_shared_vn = from->sb_shared_vn;
> to->sb_inoalignmt = be32_to_cpu(from->sb_inoalignmt);
> @@ -625,6 +633,12 @@ xfs_sb_to_disk(
> if (!fields)
> return;
>
Meanwhile, this will be going to disk, so will eventually
be done only if XFS_SB_VERSION_NO_OQUOTA is *not* set.
Otherwise the P and G flags will go as-is to disk. (Not
suggesting a change here--just sort of finishing my
thought from above.)
> + if (from->sb_qflags & (XFS_PQUOTA_ENFD | XFS_GQUOTA_ENFD))
> + from->sb_qflags |= XFS_OQUOTA_ENFD;
> + if (from->sb_qflags & (XFS_PQUOTA_CHKD | XFS_GQUOTA_CHKD))
> + from->sb_qflags |= XFS_OQUOTA_CHKD;
> + from->sb_qflags &= ~(XFS_PQUOTA_ENFD | XFS_PQUOTA_CHKD |
> + XFS_GQUOTA_ENFD | XFS_GQUOTA_CHKD);
> while (fields) {
> f = (xfs_sb_field_t)xfs_lowbit64((__uint64_t)fields);
> first = xfs_sb_info[f].offset;
> diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c
> index 5cff443..cb2ed78 100644
> --- a/fs/xfs/xfs_qm.c
> +++ b/fs/xfs/xfs_qm.c
. . .
> @@ -1688,7 +1691,7 @@ xfs_qm_quotacheck(
> * quotachecked status, since we won't be doing accounting for
> * that type anymore.
> */
> - mp->m_qflags &= ~(XFS_OQUOTA_CHKD | XFS_UQUOTA_CHKD);
> + mp->m_qflags &= ~(XFS_GQUOTA_CHKD | XFS_PQUOTA_CHKD | XFS_UQUOTA_CHKD);
mp->m_qflags &= ~XFS_ALL_QUOTA_CHKD;
> mp->m_qflags |= flags;
>
> error_return:
> diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c
> index 5cc3dde..3a67805 100644
> --- a/fs/xfs/xfs_qm_syscalls.c
> +++ b/fs/xfs/xfs_qm_syscalls.c
> @@ -120,11 +120,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) {
We don't want the "else" here, right? Only one
or the other branch will be taken at this point
anyway, since we distinguished between group and
project quotas when we read the superblock from
disk?
> dqtype |= XFS_QMOPT_PQUOTA;
> - flags |= (XFS_OQUOTA_CHKD | XFS_OQUOTA_ENFD);
> + flags |= (XFS_PQUOTA_CHKD | XFS_PQUOTA_ENFD);
> inactivate_flags |= XFS_PQUOTA_ACTIVE;
> }
>
. . .
> diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h
> index a595f29..41483d8 100644
> --- a/fs/xfs/xfs_quota.h
> +++ b/fs/xfs/xfs_quota.h
> @@ -154,19 +154,35 @@ typedef struct xfs_qoff_logformat {
> #define XFS_GQUOTA_ACCT 0x0040 /* group quota accounting ON */
>
> /*
> + * If the superblock version is earlier than XFS_SB_VERSION_NO_OQUOTA,
> + * following flags will only be used in m_qflags and incore sb_qflags
> + * From XFS_SB_VERSION_NO_OQUOTA, these flags will be stored in
> + * on-disk sb_qflags too.
> + * Also from XFS_SB_VERSION_NO_OQUOTA, XFS_OQUOTA_.* will not be used
> + * in on-disk sb_qflags.
I think this could benefit a little from rewording.
Maybe something that emphasizes things more in this
order:
- in-core, we (now) always distinguish between group and
project quotas using distinct flags
- on-disk, they may either be separate or combined,
depending on the whether XFS_SB_VERSION_NO_OQUOTA
is set in the superblock version bits
- conversion to and from the combined OQUOTA flag (if
necessary) is done only in xfs_sb_{to,from}_disk()
Also, I see in the later patch you use a macro like
xfs_sb_version_hasseparatepquota() (whose name I'm not
sure I like at this point), and it *might* read better
if you use that rather in describing things rather than
the XFS_SB_VERSION_NO_OQUOTA bit.
> + */
> +#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 */
> +
> +/*
. . .
>
> #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)
There is nothing preventing a SET3--only group and project
quotas enabled but not user quotas.
But the place these symbols are is xfs_qm_scall_quotaoff(),
and because you are no longer going to be combining the
group and project interpretation I think these two are
no longer needed and that logic can be simplified. Take a
look at that code and see if you can just get rid of these
SET1 and SET2 symbols altogether.
>
> #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_super.c b/fs/xfs/xfs_super.c
> index ba16248..b1c8d5b 100644
> --- a/fs/xfs/xfs_super.c
> +++ b/fs/xfs/xfs_super.c
> @@ -328,7 +328,8 @@ xfs_parseargs(
> mp->m_qflags &= ~(XFS_UQUOTA_ACCT | XFS_UQUOTA_ACTIVE |
> XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE |
> XFS_PQUOTA_ACCT | XFS_PQUOTA_ACTIVE |
> - XFS_UQUOTA_ENFD | XFS_OQUOTA_ENFD);
> + XFS_UQUOTA_ENFD | XFS_PQUOTA_ENFD |
> + XFS_GQUOTA_ENFD);
mp->m_qflags &= ~XFS_ALL_QUOTA_ACCT;
mp->m_qflags &= ~XFS_ALL_QUOTA_ENFD;
mp->m_qflags &= ~XFS_ALL_QUOTA_ACTIVE;
That last one is actually not yet defined.
> } else if (!strcmp(this_char, MNTOPT_QUOTA) ||
> !strcmp(this_char, MNTOPT_UQUOTA) ||
> !strcmp(this_char, MNTOPT_USRQUOTA)) {
. . .
> @@ -552,12 +553,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) {
I think you want to drop the "else" here also.
> - 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);
. . .
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFC PATCH 2/3] Add pquota fields where gquota is used
2011-10-18 0:09 ` [RFC PATCH 2/3] Add pquota fields where gquota is used Chandra Seetharaman
@ 2011-10-19 9:57 ` Christoph Hellwig
2011-10-19 15:17 ` Chandra Seetharaman
0 siblings, 1 reply; 11+ messages in thread
From: Christoph Hellwig @ 2011-10-19 9:57 UTC (permalink / raw)
To: Chandra Seetharaman; +Cc: xfs
> --- a/fs/xfs/xfs_dquot.c
> +++ b/fs/xfs/xfs_dquot.c
> @@ -841,8 +841,10 @@ xfs_qm_dqget(
> ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
> if (type == XFS_DQ_USER)
> ASSERT(ip->i_udquot == NULL);
> - else
> + else if (type == XFS_DQ_GROUP)
> ASSERT(ip->i_gdquot == NULL);
> + else
> + ASSERT(ip->i_pdquot == NULL);
An xfs_inode_dquot(ip, type) macro that gets you the right quota for
a given type would be highly useful. I'd love to see that as the
first patch in the series, as it would a) clean up a lot of code like
this and b) would also help with my TODO list of overlaying the
user/group dquots with the existing fields in the VFS inode and thus
shrinking the XFS inode.
> @@ -933,8 +935,8 @@ xfs_qm_dqget(
> xfs_dqlock(dqp);
> goto dqret;
> }
> - } else {
> - if (!XFS_IS_OQUOTA_ON(mp)) {
> + } else if (type == XFS_DQ_GROUP) {
> + if (!XFS_IS_GQUOTA_ON(mp)) {
> /* inode stays locked on return */
> xfs_qm_dqdestroy(dqp);
> return XFS_ERROR(ESRCH);
Together with a
XFS_IS_TYPE_QUOTA_ON(mp, type)
that should also really greatly simplify this error path in
xfs_qm_dqget.
> +#define XFS_IS_THIS_QUOTA_OFF(d) (! ((XFS_QM_ISUDQ(d) && \
> + XFS_IS_UQUOTA_ON((d)->q_mount)) || \
> + (XFS_QM_ISGDQ(d) && \
> + XFS_IS_GQUOTA_ON((d)->q_mount)) || \
> + (XFS_QM_ISPDQ(d) && \
> + XFS_IS_PQUOTA_ON((d)->q_mount))))
And the two callers of this could easily be converted to
!XFS_IS_TYPE_QUOTA_ON.
> diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
> index 760140d..26f95a6 100644
> --- a/fs/xfs/xfs_inode.h
> +++ b/fs/xfs/xfs_inode.h
> @@ -231,6 +231,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 */
I'd really prefer to leave growing the inode until we are fully done
adding it. So move this part to the back, just add the macro and quota
on check in the first patch, but always redirect it to i_gdquot for now.
> +++ b/fs/xfs/xfs_mount.c
> @@ -628,6 +628,7 @@ xfs_sb_to_disk(
> xfs_sb_field_t f;
> int first;
> int size;
> + __be16 saved_qflags = from->sb_qflags;
>
> ASSERT(fields);
> if (!fields)
> @@ -669,6 +670,7 @@ xfs_sb_to_disk(
>
> fields &= ~(1LL << f);
> }
> + from->sb_qflags = saved_qflags;
> }
What is this for? It will need some better documentation.
> - ASSERT(ip->i_udquot == NULL);
> + ASSERT_ALWAYS(ip->i_udquot == NULL);
Why the change to ASSERT_ALWAYS here?
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFC PATCH 1/3] Remove in core use of XFS_OQUOTA_ENFD and XFS_OQUOTA_CHKD
2011-10-18 22:40 ` Alex Elder
@ 2011-10-19 15:06 ` Chandra Seetharaman
0 siblings, 0 replies; 11+ messages in thread
From: Chandra Seetharaman @ 2011-10-19 15:06 UTC (permalink / raw)
To: aelder; +Cc: xfs
Hi Alex,
Thanks for the review.
responses inline below.
On Tue, 2011-10-18 at 17:40 -0500, Alex Elder wrote:
> On Mon, 2011-10-17 at 19:09 -0500, Chandra Seetharaman wrote:
> > Remove incore use of XFS_OQUOTA_ENFD and XFS_OQUOTA_CHKD. Instead,
> > start using XFS_GQUOTA_.* XFS_PQUOTA_.* counterparts.
> >
> > No changes is made to the on-disk version of the superblock yey. On-disk
> > copy still uses XFS_OQUOTA_ENFD and XFS_OQUOTA_CHKD.
> >
> > Signed-off-by: Chandra Seetharaman <sekharan@us.ibm.com>
>
> OK, I have a few things you should change below.
>
> Some are based on the assumption that where we're
> headed is to support *both* group *and* project
> quotas simultaneously.
>
> I haven't looked at the other two yet, I'll start
> that tomorrow.
>
> -Alex
>
> . . .
>
> > diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
> > index d06afbc..366bbb7 100644
> > --- a/fs/xfs/xfs_mount.c
> > +++ b/fs/xfs/xfs_mount.c
> > @@ -591,6 +591,14 @@ xfs_sb_from_disk(
> > to->sb_uquotino = be64_to_cpu(from->sb_uquotino);
> > to->sb_gquotino = be64_to_cpu(from->sb_gquotino);
> > to->sb_qflags = be16_to_cpu(from->sb_qflags);
>
> OK, based on the comment you have in "xfs_quota.h" below:
> This stuff is coming off disk, so it will be done
> unconditionally (i.e., not related to the superblock
> version). However, you could add an assertion that
> if OQUOTA_ENFD or OQUOTA_CHKD are set, then neither
> {P,G}QUOTA_{CHKD,ENFD} is set, and vice-versa.
> Or perhaps not an assertion, maybe just issue a
> warning and correct it. (Or perhaps some other
> handling is more appropriate, have to think it
> through.)
Since we correct it when we write it back, and it is not critical, IMO,
_no_ message would be fine as the user might get confused with the
message.
If you think a warning is needed, I will change it.
>
> > + if (to->sb_qflags & XFS_OQUOTA_ENFD)
> > + to->sb_qflags |= (to->sb_qflags & XFS_PQUOTA_ACCT) ?
> > + XFS_PQUOTA_ENFD : XFS_GQUOTA_ENFD;
> > + if (to->sb_qflags & XFS_OQUOTA_CHKD)
> > + to->sb_qflags |= (to->sb_qflags & XFS_PQUOTA_ACCT) ?
> > + XFS_PQUOTA_CHKD : XFS_GQUOTA_CHKD;
> > + to->sb_qflags &= ~(XFS_OQUOTA_ENFD | XFS_OQUOTA_CHKD);
> > +
> > to->sb_flags = from->sb_flags;
> > to->sb_shared_vn = from->sb_shared_vn;
> > to->sb_inoalignmt = be32_to_cpu(from->sb_inoalignmt);
> > @@ -625,6 +633,12 @@ xfs_sb_to_disk(
> > if (!fields)
> > return;
> >
>
> Meanwhile, this will be going to disk, so will eventually
> be done only if XFS_SB_VERSION_NO_OQUOTA is *not* set.
> Otherwise the P and G flags will go as-is to disk. (Not
> suggesting a change here--just sort of finishing my
> thought from above.)
During the creation of patch I evolved from having a version bit for
NO_OQUOTA to leaving XFS_OQUOTA_* as is in the superblock, but failed to
remove the NO_OQUOTA bit references from the patch. Sorry about it.
Do you think we should have a version bit for NO_OQUOTA ?
One more option is to use the same version bit in patch 3/3 to make sure
XFS_OQUOTA.* is no longer used in the in-disk version of superblock.
What do you think would be a right option ?
>
> > + if (from->sb_qflags & (XFS_PQUOTA_ENFD | XFS_GQUOTA_ENFD))
> > + from->sb_qflags |= XFS_OQUOTA_ENFD;
> > + if (from->sb_qflags & (XFS_PQUOTA_CHKD | XFS_GQUOTA_CHKD))
> > + from->sb_qflags |= XFS_OQUOTA_CHKD;
> > + from->sb_qflags &= ~(XFS_PQUOTA_ENFD | XFS_PQUOTA_CHKD |
> > + XFS_GQUOTA_ENFD | XFS_GQUOTA_CHKD);
> > while (fields) {
> > f = (xfs_sb_field_t)xfs_lowbit64((__uint64_t)fields);
> > first = xfs_sb_info[f].offset;
> > diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c
> > index 5cff443..cb2ed78 100644
> > --- a/fs/xfs/xfs_qm.c
> > +++ b/fs/xfs/xfs_qm.c
>
> . . .
>
> > @@ -1688,7 +1691,7 @@ xfs_qm_quotacheck(
> > * quotachecked status, since we won't be doing accounting for
> > * that type anymore.
> > */
> > - mp->m_qflags &= ~(XFS_OQUOTA_CHKD | XFS_UQUOTA_CHKD);
> > + mp->m_qflags &= ~(XFS_GQUOTA_CHKD | XFS_PQUOTA_CHKD | XFS_UQUOTA_CHKD);
>
> mp->m_qflags &= ~XFS_ALL_QUOTA_CHKD;
>
> > mp->m_qflags |= flags;
> >
> > error_return:
> > diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c
> > index 5cc3dde..3a67805 100644
> > --- a/fs/xfs/xfs_qm_syscalls.c
> > +++ b/fs/xfs/xfs_qm_syscalls.c
> > @@ -120,11 +120,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) {
>
> We don't want the "else" here, right? Only one
> or the other branch will be taken at this point
> anyway, since we distinguished between group and
> project quotas when we read the superblock from
> disk?
It was the case earlier too.
But, with patch 3/3, I need to remove it. will do it in the next
iteration.
>
> > dqtype |= XFS_QMOPT_PQUOTA;
> > - flags |= (XFS_OQUOTA_CHKD | XFS_OQUOTA_ENFD);
> > + flags |= (XFS_PQUOTA_CHKD | XFS_PQUOTA_ENFD);
> > inactivate_flags |= XFS_PQUOTA_ACTIVE;
> > }
> >
>
> . . .
>
> > diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h
> > index a595f29..41483d8 100644
> > --- a/fs/xfs/xfs_quota.h
> > +++ b/fs/xfs/xfs_quota.h
> > @@ -154,19 +154,35 @@ typedef struct xfs_qoff_logformat {
> > #define XFS_GQUOTA_ACCT 0x0040 /* group quota accounting ON */
> >
> > /*
> > + * If the superblock version is earlier than XFS_SB_VERSION_NO_OQUOTA,
> > + * following flags will only be used in m_qflags and incore sb_qflags
> > + * From XFS_SB_VERSION_NO_OQUOTA, these flags will be stored in
> > + * on-disk sb_qflags too.
> > + * Also from XFS_SB_VERSION_NO_OQUOTA, XFS_OQUOTA_.* will not be used
> > + * in on-disk sb_qflags.
>
> I think this could benefit a little from rewording.
> Maybe something that emphasizes things more in this
> order:
> - in-core, we (now) always distinguish between group and
> project quotas using distinct flags
> - on-disk, they may either be separate or combined,
> depending on the whether XFS_SB_VERSION_NO_OQUOTA
> is set in the superblock version bits
> - conversion to and from the combined OQUOTA flag (if
> necessary) is done only in xfs_sb_{to,from}_disk()
>
> Also, I see in the later patch you use a macro like
> xfs_sb_version_hasseparatepquota() (whose name I'm not
> sure I like at this point), and it *might* read better
> if you use that rather in describing things rather than
> the XFS_SB_VERSION_NO_OQUOTA bit.
>
Depending on what your suggestion above (if we need a separate bit for
NO_OQUOTA), I will update this with more details.
> > + */
> > +#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 */
> > +
> > +/*
>
> . . .
>
> >
> > #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)
>
> There is nothing preventing a SET3--only group and project
> quotas enabled but not user quotas.
>
> But the place these symbols are is xfs_qm_scall_quotaoff(),
> and because you are no longer going to be combining the
> group and project interpretation I think these two are
> no longer needed and that logic can be simplified. Take a
> look at that code and see if you can just get rid of these
> SET1 and SET2 symbols altogether.
Will look at the usage and simplify them.
>
> >
> > #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_super.c b/fs/xfs/xfs_super.c
> > index ba16248..b1c8d5b 100644
> > --- a/fs/xfs/xfs_super.c
> > +++ b/fs/xfs/xfs_super.c
> > @@ -328,7 +328,8 @@ xfs_parseargs(
> > mp->m_qflags &= ~(XFS_UQUOTA_ACCT | XFS_UQUOTA_ACTIVE |
> > XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE |
> > XFS_PQUOTA_ACCT | XFS_PQUOTA_ACTIVE |
> > - XFS_UQUOTA_ENFD | XFS_OQUOTA_ENFD);
> > + XFS_UQUOTA_ENFD | XFS_PQUOTA_ENFD |
> > + XFS_GQUOTA_ENFD);
>
> mp->m_qflags &= ~XFS_ALL_QUOTA_ACCT;
> mp->m_qflags &= ~XFS_ALL_QUOTA_ENFD;
> mp->m_qflags &= ~XFS_ALL_QUOTA_ACTIVE;
>
> That last one is actually not yet defined.
Will make the change.
>
> > } else if (!strcmp(this_char, MNTOPT_QUOTA) ||
> > !strcmp(this_char, MNTOPT_UQUOTA) ||
> > !strcmp(this_char, MNTOPT_USRQUOTA)) {
>
> . . .
>
> > @@ -552,12 +553,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) {
>
> I think you want to drop the "else" here also.
Same as above, will do after 3/3
>
> > - 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);
>
> . . .
>
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFC PATCH 2/3] Add pquota fields where gquota is used
2011-10-19 9:57 ` Christoph Hellwig
@ 2011-10-19 15:17 ` Chandra Seetharaman
0 siblings, 0 replies; 11+ messages in thread
From: Chandra Seetharaman @ 2011-10-19 15:17 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: xfs
Hi Christoph,
Thanks for the comments.
See responses inline below.
On Wed, 2011-10-19 at 05:57 -0400, Christoph Hellwig wrote:
> > --- a/fs/xfs/xfs_dquot.c
> > +++ b/fs/xfs/xfs_dquot.c
> > @@ -841,8 +841,10 @@ xfs_qm_dqget(
> > ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
> > if (type == XFS_DQ_USER)
> > ASSERT(ip->i_udquot == NULL);
> > - else
> > + else if (type == XFS_DQ_GROUP)
> > ASSERT(ip->i_gdquot == NULL);
> > + else
> > + ASSERT(ip->i_pdquot == NULL);
>
> An xfs_inode_dquot(ip, type) macro that gets you the right quota for
> a given type would be highly useful. I'd love to see that as the
> first patch in the series, as it would a) clean up a lot of code like
> this and b) would also help with my TODO list of overlaying the
> user/group dquots with the existing fields in the VFS inode and thus
> shrinking the XFS inode.
>
will do.
> > @@ -933,8 +935,8 @@ xfs_qm_dqget(
> > xfs_dqlock(dqp);
> > goto dqret;
> > }
> > - } else {
> > - if (!XFS_IS_OQUOTA_ON(mp)) {
> > + } else if (type == XFS_DQ_GROUP) {
> > + if (!XFS_IS_GQUOTA_ON(mp)) {
> > /* inode stays locked on return */
> > xfs_qm_dqdestroy(dqp);
> > return XFS_ERROR(ESRCH);
>
> Together with a
>
> XFS_IS_TYPE_QUOTA_ON(mp, type)
>
> that should also really greatly simplify this error path in
> xfs_qm_dqget.
>
> > +#define XFS_IS_THIS_QUOTA_OFF(d) (! ((XFS_QM_ISUDQ(d) && \
> > + XFS_IS_UQUOTA_ON((d)->q_mount)) || \
> > + (XFS_QM_ISGDQ(d) && \
> > + XFS_IS_GQUOTA_ON((d)->q_mount)) || \
> > + (XFS_QM_ISPDQ(d) && \
> > + XFS_IS_PQUOTA_ON((d)->q_mount))))
>
> And the two callers of this could easily be converted to
> !XFS_IS_TYPE_QUOTA_ON.
>
> > diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
> > index 760140d..26f95a6 100644
> > --- a/fs/xfs/xfs_inode.h
> > +++ b/fs/xfs/xfs_inode.h
> > @@ -231,6 +231,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 */
>
> I'd really prefer to leave growing the inode until we are fully done
> adding it. So move this part to the back, just add the macro and quota
> on check in the first patch, but always redirect it to i_gdquot for now.
Sure, will do.
>
> > +++ b/fs/xfs/xfs_mount.c
> > @@ -628,6 +628,7 @@ xfs_sb_to_disk(
> > xfs_sb_field_t f;
> > int first;
> > int size;
> > + __be16 saved_qflags = from->sb_qflags;
> >
> > ASSERT(fields);
> > if (!fields)
> > @@ -669,6 +670,7 @@ xfs_sb_to_disk(
> >
> > fields &= ~(1LL << f);
> > }
> > + from->sb_qflags = saved_qflags;
> > }
>
> What is this for? It will need some better documentation.
We want to keep XFS_OQUOTA_.* flags in-disk but on in-core. the while
loop between this save and restore copies the information from in-core
to a buffer destined to go to disk. So, I save the in-core information
then change it which is then copied to the buffer, then I restore the
in-core information back.
I will add some comments to that effect.
>
> > - ASSERT(ip->i_udquot == NULL);
> > + ASSERT_ALWAYS(ip->i_udquot == NULL);
>
> Why the change to ASSERT_ALWAYS here?
oops. debug left over. will remove it.
>
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [RFC PATCH 3/3] Add pquotaino to on-disk super block
2011-10-18 0:09 ` [RFC PATCH 3/3] Add pquotaino to on-disk super block Chandra Seetharaman
@ 2011-10-26 16:14 ` Alex Elder
0 siblings, 0 replies; 11+ messages in thread
From: Alex Elder @ 2011-10-26 16:14 UTC (permalink / raw)
To: Chandra Seetharaman; +Cc: xfs
On Mon, 2011-10-17 at 19:09 -0500, Chandra Seetharaman wrote:
> Add a new field to the superblock to add support for seperate pquota
> with a specific version.
>
> No change made yet to gather both project and group quota with quotactl.
>
> Signed-off-by: Chandra Seetharaman <sekharan@us.ibm.com>
Since you have already indicated you're going to
re-post this series after a bit of rework, I'm
not going to review this patch (or patch 2/3).
I'll wait for the next edition.
-Alex
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2011-10-26 16:14 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-10-18 0:09 [RFC PATCH 0/3] Allow pquota and gquota to be used together Chandra Seetharaman
2011-10-18 0:09 ` [RFC PATCH 1/3] Remove in core use of XFS_OQUOTA_ENFD and XFS_OQUOTA_CHKD Chandra Seetharaman
2011-10-18 5:16 ` Arkadiusz Miśkiewicz
2011-10-18 14:15 ` Chandra Seetharaman
2011-10-18 22:40 ` Alex Elder
2011-10-19 15:06 ` Chandra Seetharaman
2011-10-18 0:09 ` [RFC PATCH 2/3] Add pquota fields where gquota is used Chandra Seetharaman
2011-10-19 9:57 ` Christoph Hellwig
2011-10-19 15:17 ` Chandra Seetharaman
2011-10-18 0:09 ` [RFC PATCH 3/3] Add pquotaino to on-disk super block Chandra Seetharaman
2011-10-26 16:14 ` Alex Elder
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox