* [PATCH 0/11 RFC] quota: Unify VFS and XFS quota interfaces
@ 2014-11-11 21:04 Jan Kara
2014-11-11 21:04 ` [PATCH 01/11] xfs: Remove useless test Jan Kara
` (10 more replies)
0 siblings, 11 replies; 22+ messages in thread
From: Jan Kara @ 2014-11-11 21:04 UTC (permalink / raw)
To: linux-fsdevel; +Cc: linux-ext4, xfs, Jan Kara
Hello,
this is a first (still partial) attempt to unify VFS and XFS quota interfaces
so that XFS quotactls work for filesystems with VFS quotas and vice versa.
This is useful so that userspace doesn't have to care that much about which
filesystem it is using at least when using basic quota functionality. In
particular we should be able to reuse project quota tests in xfstests for
ext4.
In this patch set I unify quotaon / quotaoff handling (Q_QUOTAON, Q_QUOTAOFF,
Q_XQUOTAON, Q_XQUOTAOFF calls) and fix some bugs in the Q_XGETQUOTA,
Q_XSETQLIM, Q_GETQUOTA, Q_SETQUOTA calls done by Christoph some time ago. I
have actually verified that xfs_quota is able to work with ext4 filesystem
(after tweaking it to not check fs type) when these patches are applied.
What is still missing is unification of Q_XGETQSTATV, Q_GETINFO, Q_SETINFO.
Comments are welcome.
Honza
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH 01/11] xfs: Remove useless test
2014-11-11 21:04 [PATCH 0/11 RFC] quota: Unify VFS and XFS quota interfaces Jan Kara
@ 2014-11-11 21:04 ` Jan Kara
2014-11-11 23:27 ` Dave Chinner
2014-11-11 21:04 ` [PATCH 02/11] xfs: Remove unused variable in xfs_qm_scall_quotaon() Jan Kara
` (9 subsequent siblings)
10 siblings, 1 reply; 22+ messages in thread
From: Jan Kara @ 2014-11-11 21:04 UTC (permalink / raw)
To: linux-fsdevel; +Cc: linux-ext4, xfs, Jan Kara
Q_XQUOTARM is never passed to xfs_fs_set_xstate() so remove the test.
Signed-off-by: Jan Kara <jack@suse.cz>
---
fs/xfs/xfs_quotaops.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/xfs/xfs_quotaops.c b/fs/xfs/xfs_quotaops.c
index b238027df987..9ad73240ed54 100644
--- a/fs/xfs/xfs_quotaops.c
+++ b/fs/xfs/xfs_quotaops.c
@@ -77,7 +77,7 @@ xfs_fs_set_xstate(
if (sb->s_flags & MS_RDONLY)
return -EROFS;
- if (op != Q_XQUOTARM && !XFS_IS_QUOTA_RUNNING(mp))
+ if (!XFS_IS_QUOTA_RUNNING(mp))
return -ENOSYS;
if (uflags & FS_QUOTA_UDQ_ACCT)
--
1.8.1.4
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 02/11] xfs: Remove unused variable in xfs_qm_scall_quotaon()
2014-11-11 21:04 [PATCH 0/11 RFC] quota: Unify VFS and XFS quota interfaces Jan Kara
2014-11-11 21:04 ` [PATCH 01/11] xfs: Remove useless test Jan Kara
@ 2014-11-11 21:04 ` Jan Kara
2014-11-11 23:23 ` Dave Chinner
2014-11-11 21:04 ` [PATCH 03/11] xfs: Remove some useless flags tests Jan Kara
` (8 subsequent siblings)
10 siblings, 1 reply; 22+ messages in thread
From: Jan Kara @ 2014-11-11 21:04 UTC (permalink / raw)
To: linux-fsdevel; +Cc: linux-ext4, Jan Kara, xfs
sbflags variable in xfs_qm_scall_quotaon() was practically unused (we
only set it to constant at one place and used it elsewhere). Remove it.
Signed-off-by: Jan Kara <jack@suse.cz>
---
fs/xfs/xfs_qm_syscalls.c | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c
index 80f2d77d929a..5e4944973587 100644
--- a/fs/xfs/xfs_qm_syscalls.c
+++ b/fs/xfs/xfs_qm_syscalls.c
@@ -315,7 +315,6 @@ xfs_qm_scall_quotaon(
{
int error;
uint qf;
- __int64_t sbflags;
flags &= (XFS_ALL_QUOTA_ACCT | XFS_ALL_QUOTA_ENFD);
/*
@@ -323,8 +322,6 @@ xfs_qm_scall_quotaon(
*/
flags &= ~(XFS_ALL_QUOTA_ACCT);
- sbflags = 0;
-
if (flags == 0) {
xfs_debug(mp, "%s: zero flags, m_qflags=%x",
__func__, mp->m_qflags);
@@ -371,11 +368,10 @@ xfs_qm_scall_quotaon(
/*
* There's nothing to change if it's the same.
*/
- if ((qf & flags) == flags && sbflags == 0)
+ if ((qf & flags) == flags)
return -EEXIST;
- sbflags |= XFS_SB_QFLAGS;
- if ((error = xfs_qm_write_sb_changes(mp, sbflags)))
+ if ((error = xfs_qm_write_sb_changes(mp, XFS_SB_QFLAGS)))
return error;
/*
* If we aren't trying to switch on quota enforcement, we are done.
--
1.8.1.4
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 03/11] xfs: Remove some useless flags tests
2014-11-11 21:04 [PATCH 0/11 RFC] quota: Unify VFS and XFS quota interfaces Jan Kara
2014-11-11 21:04 ` [PATCH 01/11] xfs: Remove useless test Jan Kara
2014-11-11 21:04 ` [PATCH 02/11] xfs: Remove unused variable in xfs_qm_scall_quotaon() Jan Kara
@ 2014-11-11 21:04 ` Jan Kara
2014-11-11 23:26 ` Dave Chinner
2014-11-11 21:04 ` [PATCH 04/11] quota: Split ->set_xstate callback into two Jan Kara
` (7 subsequent siblings)
10 siblings, 1 reply; 22+ messages in thread
From: Jan Kara @ 2014-11-11 21:04 UTC (permalink / raw)
To: linux-fsdevel; +Cc: linux-ext4, Jan Kara, xfs
'flags' have XFS_ALL_QUOTA_ACCT cleared immediately on function entry.
There's no point in checking these bits later in the function. Also
because we check something is going to change, we know some enforcement
bits are being added and thus there's no point in testing that later.
Signed-off-by: Jan Kara <jack@suse.cz>
---
fs/xfs/xfs_qm_syscalls.c | 15 ++++-----------
1 file changed, 4 insertions(+), 11 deletions(-)
diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c
index 5e4944973587..60bca27d3d04 100644
--- a/fs/xfs/xfs_qm_syscalls.c
+++ b/fs/xfs/xfs_qm_syscalls.c
@@ -328,22 +328,16 @@ xfs_qm_scall_quotaon(
return -EINVAL;
}
- /* No fs can turn on quotas with a delayed effect */
- ASSERT((flags & XFS_ALL_QUOTA_ACCT) == 0);
-
/*
* Can't enforce without accounting. We check the superblock
* qflags here instead of m_qflags because rootfs can have
* quota acct on ondisk without m_qflags' knowing.
*/
- if (((flags & XFS_UQUOTA_ACCT) == 0 &&
- (mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT) == 0 &&
+ if (((mp->m_sb.sb_qflags & XFS_UQUOTA_ACCT) == 0 &&
(flags & XFS_UQUOTA_ENFD)) ||
- ((flags & XFS_GQUOTA_ACCT) == 0 &&
- (mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) == 0 &&
+ ((mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) == 0 &&
(flags & XFS_GQUOTA_ENFD)) ||
- ((flags & XFS_PQUOTA_ACCT) == 0 &&
- (mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT) == 0 &&
+ ((mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT) == 0 &&
(flags & XFS_PQUOTA_ENFD))) {
xfs_debug(mp,
"%s: Can't enforce without acct, flags=%x sbflags=%x",
@@ -381,8 +375,7 @@ xfs_qm_scall_quotaon(
((mp->m_sb.sb_qflags & XFS_PQUOTA_ACCT) !=
(mp->m_qflags & XFS_PQUOTA_ACCT)) ||
((mp->m_sb.sb_qflags & XFS_GQUOTA_ACCT) !=
- (mp->m_qflags & XFS_GQUOTA_ACCT)) ||
- (flags & XFS_ALL_QUOTA_ENFD) == 0)
+ (mp->m_qflags & XFS_GQUOTA_ACCT)))
return 0;
if (! XFS_IS_QUOTA_RUNNING(mp))
--
1.8.1.4
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 04/11] quota: Split ->set_xstate callback into two
2014-11-11 21:04 [PATCH 0/11 RFC] quota: Unify VFS and XFS quota interfaces Jan Kara
` (2 preceding siblings ...)
2014-11-11 21:04 ` [PATCH 03/11] xfs: Remove some useless flags tests Jan Kara
@ 2014-11-11 21:04 ` Jan Kara
2014-11-13 17:34 ` Christoph Hellwig
2014-11-11 21:04 ` [PATCH 05/11] quota: Wire up ->sysquota_{on,off} callbacks into Q_QUOTA{ON,OFF} Jan Kara
` (6 subsequent siblings)
10 siblings, 1 reply; 22+ messages in thread
From: Jan Kara @ 2014-11-11 21:04 UTC (permalink / raw)
To: linux-fsdevel; +Cc: linux-ext4, Jan Kara, xfs
Split ->set_xstate callback into two callbacks - one for turning quotas
on (->sysquota_on) and one for turning quotas off (->sysquota_off). That
way we don't have to pass quotactl command into the callback which seems
cleaner.
Signed-off-by: Jan Kara <jack@suse.cz>
---
fs/quota/quota.c | 20 ++++++++++++++----
fs/xfs/xfs_quotaops.c | 58 ++++++++++++++++++++++++++++++++-------------------
include/linux/quota.h | 3 ++-
3 files changed, 54 insertions(+), 27 deletions(-)
diff --git a/fs/quota/quota.c b/fs/quota/quota.c
index 75621649dbd7..fb22cebff946 100644
--- a/fs/quota/quota.c
+++ b/fs/quota/quota.c
@@ -195,15 +195,26 @@ static int quota_setquota(struct super_block *sb, int type, qid_t id,
return sb->s_qcop->set_dqblk(sb, qid, &fdq);
}
-static int quota_setxstate(struct super_block *sb, int cmd, void __user *addr)
+static int quota_sysquota_on(struct super_block *sb, void __user *addr)
{
__u32 flags;
if (copy_from_user(&flags, addr, sizeof(flags)))
return -EFAULT;
- if (!sb->s_qcop->set_xstate)
+ if (!sb->s_qcop->sysquota_on)
return -ENOSYS;
- return sb->s_qcop->set_xstate(sb, flags, cmd);
+ return sb->s_qcop->sysquota_on(sb, flags);
+}
+
+static int quota_sysquota_off(struct super_block *sb, void __user *addr)
+{
+ __u32 flags;
+
+ if (copy_from_user(&flags, addr, sizeof(flags)))
+ return -EFAULT;
+ if (!sb->s_qcop->sysquota_off)
+ return -ENOSYS;
+ return sb->s_qcop->sysquota_off(sb, flags);
}
static int quota_getxstate(struct super_block *sb, void __user *addr)
@@ -326,8 +337,9 @@ static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id,
return -ENOSYS;
return sb->s_qcop->quota_sync(sb, type);
case Q_XQUOTAON:
+ return quota_sysquota_on(sb, addr);
case Q_XQUOTAOFF:
- return quota_setxstate(sb, cmd, addr);
+ return quota_sysquota_off(sb, addr);
case Q_XQUOTARM:
return quota_rmxquota(sb, addr);
case Q_XGETQSTAT:
diff --git a/fs/xfs/xfs_quotaops.c b/fs/xfs/xfs_quotaops.c
index 9ad73240ed54..a3836ac0f2f8 100644
--- a/fs/xfs/xfs_quotaops.c
+++ b/fs/xfs/xfs_quotaops.c
@@ -66,19 +66,9 @@ xfs_fs_get_xstatev(
return xfs_qm_scall_getqstatv(mp, fqs);
}
-STATIC int
-xfs_fs_set_xstate(
- struct super_block *sb,
- unsigned int uflags,
- int op)
+static unsigned int generic_to_xfs_flags(unsigned int uflags)
{
- struct xfs_mount *mp = XFS_M(sb);
- unsigned int flags = 0;
-
- if (sb->s_flags & MS_RDONLY)
- return -EROFS;
- if (!XFS_IS_QUOTA_RUNNING(mp))
- return -ENOSYS;
+ unsigned int flags = 0;
if (uflags & FS_QUOTA_UDQ_ACCT)
flags |= XFS_UQUOTA_ACCT;
@@ -93,16 +83,39 @@ xfs_fs_set_xstate(
if (uflags & FS_QUOTA_PDQ_ENFD)
flags |= XFS_PQUOTA_ENFD;
- switch (op) {
- case Q_XQUOTAON:
- return xfs_qm_scall_quotaon(mp, flags);
- case Q_XQUOTAOFF:
- if (!XFS_IS_QUOTA_ON(mp))
- return -EINVAL;
- return xfs_qm_scall_quotaoff(mp, flags);
- }
+ return flags;
+}
+
+STATIC int
+xfs_sysquota_on(
+ struct super_block *sb,
+ unsigned int uflags)
+{
+ struct xfs_mount *mp = XFS_M(sb);
+
+ if (sb->s_flags & MS_RDONLY)
+ return -EROFS;
+ if (!XFS_IS_QUOTA_RUNNING(mp))
+ return -ENOSYS;
+
+ return xfs_qm_scall_quotaon(mp, generic_to_xfs_flags(uflags));
+}
+
+STATIC int
+xfs_sysquota_off(
+ struct super_block *sb,
+ unsigned int uflags)
+{
+ struct xfs_mount *mp = XFS_M(sb);
+
+ if (sb->s_flags & MS_RDONLY)
+ return -EROFS;
+ if (!XFS_IS_QUOTA_RUNNING(mp))
+ return -ENOSYS;
+ if (!XFS_IS_QUOTA_ON(mp))
+ return -EINVAL;
- return -EINVAL;
+ return xfs_qm_scall_quotaoff(mp, generic_to_xfs_flags(uflags));
}
STATIC int
@@ -168,7 +181,8 @@ xfs_fs_set_dqblk(
const struct quotactl_ops xfs_quotactl_operations = {
.get_xstatev = xfs_fs_get_xstatev,
.get_xstate = xfs_fs_get_xstate,
- .set_xstate = xfs_fs_set_xstate,
+ .sysquota_on = xfs_sysquota_on,
+ .sysquota_off = xfs_sysquota_off,
.rm_xquota = xfs_fs_rm_xquota,
.get_dqblk = xfs_fs_get_dqblk,
.set_dqblk = xfs_fs_set_dqblk,
diff --git a/include/linux/quota.h b/include/linux/quota.h
index 80d345a3524c..3a046676e4aa 100644
--- a/include/linux/quota.h
+++ b/include/linux/quota.h
@@ -326,8 +326,9 @@ struct quotactl_ops {
int (*set_info)(struct super_block *, int, struct if_dqinfo *);
int (*get_dqblk)(struct super_block *, struct kqid, struct fs_disk_quota *);
int (*set_dqblk)(struct super_block *, struct kqid, struct fs_disk_quota *);
+ int (*sysquota_on)(struct super_block *, unsigned int);
+ int (*sysquota_off)(struct super_block *, unsigned int);
int (*get_xstate)(struct super_block *, struct fs_quota_stat *);
- int (*set_xstate)(struct super_block *, unsigned int, int);
int (*get_xstatev)(struct super_block *, struct fs_quota_statv *);
int (*rm_xquota)(struct super_block *, unsigned int);
};
--
1.8.1.4
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 05/11] quota: Wire up ->sysquota_{on,off} callbacks into Q_QUOTA{ON,OFF}
2014-11-11 21:04 [PATCH 0/11 RFC] quota: Unify VFS and XFS quota interfaces Jan Kara
` (3 preceding siblings ...)
2014-11-11 21:04 ` [PATCH 04/11] quota: Split ->set_xstate callback into two Jan Kara
@ 2014-11-11 21:04 ` Jan Kara
2014-11-11 21:04 ` [PATCH 06/11] quota: Add ->sysquota_{on,off} callbacks for VFS quotas Jan Kara
` (5 subsequent siblings)
10 siblings, 0 replies; 22+ messages in thread
From: Jan Kara @ 2014-11-11 21:04 UTC (permalink / raw)
To: linux-fsdevel; +Cc: linux-ext4, xfs, Jan Kara
Make Q_QUOTAON / Q_QUOTAOFF quotactl call ->sysquota_on / ->sysquota_off
callback when provided. To match current behavior of ocfs2 & ext4 we
make these quotactls turn on / off quota enforcement for appropriate
quota type.
Signed-off-by: Jan Kara <jack@suse.cz>
---
fs/quota/quota.c | 31 +++++++++++++++++++++++++++----
include/linux/quotaops.h | 2 ++
2 files changed, 29 insertions(+), 4 deletions(-)
diff --git a/fs/quota/quota.c b/fs/quota/quota.c
index fb22cebff946..162d533c4997 100644
--- a/fs/quota/quota.c
+++ b/fs/quota/quota.c
@@ -63,18 +63,43 @@ static int quota_sync_all(int type)
return ret;
}
+unsigned int qtype_limit_flag(int type)
+{
+ switch (type) {
+ case USRQUOTA:
+ return FS_QUOTA_UDQ_ENFD;
+ case GRPQUOTA:
+ return FS_QUOTA_GDQ_ENFD;
+ case PRJQUOTA:
+ return FS_QUOTA_PDQ_ENFD;
+ }
+ return 0;
+}
+
static int quota_quotaon(struct super_block *sb, int type, int cmd, qid_t id,
struct path *path)
{
- if (!sb->s_qcop->quota_on && !sb->s_qcop->quota_on_meta)
+ if (!sb->s_qcop->quota_on && !sb->s_qcop->quota_on_meta &&
+ !sb->s_qcop->sysquota_on)
return -ENOSYS;
if (sb->s_qcop->quota_on_meta)
return sb->s_qcop->quota_on_meta(sb, type, id);
+ if (sb->s_qcop->sysquota_on)
+ return sb->s_qcop->sysquota_on(sb, qtype_limit_flag(type));
if (IS_ERR(path))
return PTR_ERR(path);
return sb->s_qcop->quota_on(sb, type, id, path);
}
+static int quota_quotaoff(struct super_block *sb, int type)
+{
+ if (!sb->s_qcop->quota_off && !sb->s_qcop->sysquota_off)
+ return -ENOSYS;
+ if (sb->s_qcop->sysquota_off)
+ return sb->s_qcop->sysquota_off(sb, qtype_limit_flag(type));
+ return sb->s_qcop->quota_off(sb, type);
+}
+
static int quota_getfmt(struct super_block *sb, int type, void __user *addr)
{
__u32 fmt;
@@ -319,9 +344,7 @@ static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id,
case Q_QUOTAON:
return quota_quotaon(sb, type, cmd, id, path);
case Q_QUOTAOFF:
- if (!sb->s_qcop->quota_off)
- return -ENOSYS;
- return sb->s_qcop->quota_off(sb, type);
+ return quota_quotaoff(sb, type);
case Q_GETFMT:
return quota_getfmt(sb, type, addr);
case Q_GETINFO:
diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h
index 1d3eee594cd6..5947a9e54862 100644
--- a/include/linux/quotaops.h
+++ b/include/linux/quotaops.h
@@ -386,4 +386,6 @@ static inline void dquot_release_reservation_block(struct inode *inode,
__dquot_free_space(inode, nr << inode->i_blkbits, DQUOT_SPACE_RESERVE);
}
+unsigned int qtype_limit_flag(int type);
+
#endif /* _LINUX_QUOTAOPS_ */
--
1.8.1.4
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 06/11] quota: Add ->sysquota_{on,off} callbacks for VFS quotas
2014-11-11 21:04 [PATCH 0/11 RFC] quota: Unify VFS and XFS quota interfaces Jan Kara
` (4 preceding siblings ...)
2014-11-11 21:04 ` [PATCH 05/11] quota: Wire up ->sysquota_{on,off} callbacks into Q_QUOTA{ON,OFF} Jan Kara
@ 2014-11-11 21:04 ` Jan Kara
2014-11-11 21:04 ` [PATCH 07/11] ext4: Use generic helpers for quotaon and quotaoff Jan Kara
` (4 subsequent siblings)
10 siblings, 0 replies; 22+ messages in thread
From: Jan Kara @ 2014-11-11 21:04 UTC (permalink / raw)
To: linux-fsdevel; +Cc: linux-ext4, xfs, Jan Kara
Add functions which translate ->sysquota_on / ->sysquota_off calls into
appropriate changes in VFS quota. This will enable filesystems
supporting VFS quota files in system inodes to be controlled via
Q_XQUOTA[ON|OFF] quotactls for better userspace compatibility.
Signed-off-by: Jan Kara <jack@suse.cz>
---
fs/quota/dquot.c | 82 ++++++++++++++++++++++++++++++++++++++++++++++++
include/linux/quotaops.h | 2 ++
2 files changed, 84 insertions(+)
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c
index 6b4527216a7f..b7359c9da61e 100644
--- a/fs/quota/dquot.c
+++ b/fs/quota/dquot.c
@@ -2380,6 +2380,88 @@ out:
}
EXPORT_SYMBOL(dquot_quota_on_mount);
+int dquot_sysquota_on(struct super_block *sb, unsigned int flags)
+{
+ int ret;
+ int type;
+ struct quota_info *dqopt = sb_dqopt(sb);
+
+ if (!(dqopt->flags & DQUOT_QUOTA_SYS_FILE))
+ return -ENOSYS;
+ /* Accounting cannot be turned on while fs is mounted */
+ flags &= ~(FS_QUOTA_UDQ_ACCT | FS_QUOTA_GDQ_ACCT | FS_QUOTA_PDQ_ACCT);
+ if (!flags)
+ return -EINVAL;
+ for (type = 0; type < MAXQUOTAS; type++) {
+ if (!(flags & qtype_limit_flag(type)))
+ continue;
+ /* Can't enforce without accounting */
+ if (!sb_has_quota_usage_enabled(sb, type))
+ return -EINVAL;
+ ret = dquot_enable(dqopt->files[type], type,
+ dqopt->info[type].dqi_fmt_id,
+ DQUOT_LIMITS_ENABLED);
+ if (ret < 0)
+ goto out_err;
+ }
+ return 0;
+out_err:
+ /* Backout enforcement enablement we already did */
+ for (type--; type >= 0; type--) {
+ if (flags & qtype_limit_flag(type))
+ dquot_disable(sb, type, DQUOT_LIMITS_ENABLED);
+ }
+ /* Error code translation for better compatibility with XFS */
+ if (ret == -EBUSY)
+ ret = -EEXIST;
+ return ret;
+}
+EXPORT_SYMBOL(dquot_sysquota_on);
+
+int dquot_sysquota_off(struct super_block *sb, unsigned int flags)
+{
+ int ret;
+ int type;
+ struct quota_info *dqopt = sb_dqopt(sb);
+
+ if (!(dqopt->flags & DQUOT_QUOTA_SYS_FILE))
+ return -ENOSYS;
+ /*
+ * We don't support turning off accounting via quotactl. In principle
+ * quota infrastructure can do this but filesystems don't expect
+ * userspace to be able to do it.
+ */
+ if (flags &
+ (FS_QUOTA_UDQ_ACCT | FS_QUOTA_GDQ_ACCT | FS_QUOTA_PDQ_ACCT))
+ return -EOPNOTSUPP;
+
+ /* Filter out limits not enabled */
+ for (type = 0; type < MAXQUOTAS; type++)
+ if (!sb_has_quota_limits_enabled(sb, type))
+ flags &= ~qtype_limit_flag(type);
+ /* Nothing left? */
+ if (!flags)
+ return -EEXIST;
+ for (type = 0; type < MAXQUOTAS; type++) {
+ if (flags & qtype_limit_flag(type)) {
+ ret = dquot_disable(sb, type, DQUOT_LIMITS_ENABLED);
+ if (ret < 0)
+ goto out_err;
+ }
+ }
+ return 0;
+out_err:
+ /* Backout enforcement disabling we already did */
+ for (type--; type >= 0; type--) {
+ if (flags & qtype_limit_flag(type))
+ dquot_enable(dqopt->files[type], type,
+ dqopt->info[type].dqi_fmt_id,
+ DQUOT_LIMITS_ENABLED);
+ }
+ return ret;
+}
+EXPORT_SYMBOL(dquot_sysquota_off);
+
static inline qsize_t qbtos(qsize_t blocks)
{
return blocks << QIF_DQBLKSIZE_BITS;
diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h
index 5947a9e54862..6f5dc7e397a7 100644
--- a/include/linux/quotaops.h
+++ b/include/linux/quotaops.h
@@ -93,6 +93,8 @@ int dquot_quota_on(struct super_block *sb, int type, int format_id,
int dquot_quota_on_mount(struct super_block *sb, char *qf_name,
int format_id, int type);
int dquot_quota_off(struct super_block *sb, int type);
+int dquot_sysquota_on(struct super_block *sb, unsigned int flags);
+int dquot_sysquota_off(struct super_block *sb, unsigned int flags);
int dquot_writeback_dquots(struct super_block *sb, int type);
int dquot_quota_sync(struct super_block *sb, int type);
int dquot_get_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii);
--
1.8.1.4
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 07/11] ext4: Use generic helpers for quotaon and quotaoff
2014-11-11 21:04 [PATCH 0/11 RFC] quota: Unify VFS and XFS quota interfaces Jan Kara
` (5 preceding siblings ...)
2014-11-11 21:04 ` [PATCH 06/11] quota: Add ->sysquota_{on,off} callbacks for VFS quotas Jan Kara
@ 2014-11-11 21:04 ` Jan Kara
2014-11-13 17:36 ` Christoph Hellwig
2014-11-11 21:04 ` [PATCH 08/11] ocfs2: " Jan Kara
` (3 subsequent siblings)
10 siblings, 1 reply; 22+ messages in thread
From: Jan Kara @ 2014-11-11 21:04 UTC (permalink / raw)
To: linux-fsdevel; +Cc: linux-ext4, Jan Kara, xfs
Ext4 can just use the generic helpers provided by quota code for turning
quotas on and off when quota files are stored as system inodes. The only
difference is the feature test in ext4_quota_on_sysfile() but the same
is achieved in dquot_sysquota_on() by checking whether usage tracking for
the corresponding quota type is enabled (which can happen only if quota
feature is set).
Signed-off-by: Jan Kara <jack@suse.cz>
---
fs/ext4/super.c | 34 ++--------------------------------
1 file changed, 2 insertions(+), 32 deletions(-)
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 2c9e6864abd9..45be29119e42 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -1055,10 +1055,7 @@ static int ext4_mark_dquot_dirty(struct dquot *dquot);
static int ext4_write_info(struct super_block *sb, int type);
static int ext4_quota_on(struct super_block *sb, int type, int format_id,
struct path *path);
-static int ext4_quota_on_sysfile(struct super_block *sb, int type,
- int format_id);
static int ext4_quota_off(struct super_block *sb, int type);
-static int ext4_quota_off_sysfile(struct super_block *sb, int type);
static int ext4_quota_on_mount(struct super_block *sb, int type);
static ssize_t ext4_quota_read(struct super_block *sb, int type, char *data,
size_t len, loff_t off);
@@ -1090,8 +1087,8 @@ static const struct quotactl_ops ext4_qctl_operations = {
};
static const struct quotactl_ops ext4_qctl_sysfile_operations = {
- .quota_on_meta = ext4_quota_on_sysfile,
- .quota_off = ext4_quota_off_sysfile,
+ .sysquota_on = dquot_sysquota_on,
+ .sysquota_off = dquot_sysquota_off,
.quota_sync = dquot_quota_sync,
.get_info = dquot_get_dqinfo,
.set_info = dquot_set_dqinfo,
@@ -5273,21 +5270,6 @@ static int ext4_enable_quotas(struct super_block *sb)
return 0;
}
-/*
- * quota_on function that is used when QUOTA feature is set.
- */
-static int ext4_quota_on_sysfile(struct super_block *sb, int type,
- int format_id)
-{
- if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA))
- return -EINVAL;
-
- /*
- * USAGE was enabled at mount time. Only need to enable LIMITS now.
- */
- return ext4_quota_enable(sb, type, format_id, DQUOT_LIMITS_ENABLED);
-}
-
static int ext4_quota_off(struct super_block *sb, int type)
{
struct inode *inode = sb_dqopt(sb)->files[type];
@@ -5314,18 +5296,6 @@ out:
return dquot_quota_off(sb, type);
}
-/*
- * quota_off function that is used when QUOTA feature is set.
- */
-static int ext4_quota_off_sysfile(struct super_block *sb, int type)
-{
- if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA))
- return -EINVAL;
-
- /* Disable only the limits. */
- return dquot_disable(sb, type, DQUOT_LIMITS_ENABLED);
-}
-
/* Read data from quotafile - avoid pagecache and such because we cannot afford
* acquiring the locks... As quota files are never truncated and quota code
* itself serializes the operations (and no one else should touch the files)
--
1.8.1.4
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 08/11] ocfs2: Use generic helpers for quotaon and quotaoff
2014-11-11 21:04 [PATCH 0/11 RFC] quota: Unify VFS and XFS quota interfaces Jan Kara
` (6 preceding siblings ...)
2014-11-11 21:04 ` [PATCH 07/11] ext4: Use generic helpers for quotaon and quotaoff Jan Kara
@ 2014-11-11 21:04 ` Jan Kara
2014-11-11 21:04 ` [PATCH 09/11] quota: Remove quota_on_meta callback Jan Kara
` (2 subsequent siblings)
10 siblings, 0 replies; 22+ messages in thread
From: Jan Kara @ 2014-11-11 21:04 UTC (permalink / raw)
To: linux-fsdevel; +Cc: linux-ext4, Jan Kara, xfs
Ocfs2 can just use the generic helpers provided by quota code for turning
quotas on and off when quota files are stored as system inodes. The only
difference is the feature test in ocfs2_quota_on() and that is covered
by dquot_sysquota_on() checking whether usage tracking is enabled (which
can happen only if the filesystem has the quota feature set).
Signed-off-by: Jan Kara <jack@suse.cz>
---
fs/ocfs2/super.c | 24 ++----------------------
1 file changed, 2 insertions(+), 22 deletions(-)
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
index 93c85bc745e1..1cfedaa24a9d 100644
--- a/fs/ocfs2/super.c
+++ b/fs/ocfs2/super.c
@@ -993,29 +993,9 @@ static void ocfs2_disable_quotas(struct ocfs2_super *osb)
}
}
-/* Handle quota on quotactl */
-static int ocfs2_quota_on(struct super_block *sb, int type, int format_id)
-{
- unsigned int feature[OCFS2_MAXQUOTAS] = {
- OCFS2_FEATURE_RO_COMPAT_USRQUOTA,
- OCFS2_FEATURE_RO_COMPAT_GRPQUOTA};
-
- if (!OCFS2_HAS_RO_COMPAT_FEATURE(sb, feature[type]))
- return -EINVAL;
-
- return dquot_enable(sb_dqopt(sb)->files[type], type,
- format_id, DQUOT_LIMITS_ENABLED);
-}
-
-/* Handle quota off quotactl */
-static int ocfs2_quota_off(struct super_block *sb, int type)
-{
- return dquot_disable(sb, type, DQUOT_LIMITS_ENABLED);
-}
-
static const struct quotactl_ops ocfs2_quotactl_ops = {
- .quota_on_meta = ocfs2_quota_on,
- .quota_off = ocfs2_quota_off,
+ .sysquota_on = dquot_sysquota_on,
+ .sysquota_off = dquot_sysquota_off,
.quota_sync = dquot_quota_sync,
.get_info = dquot_get_dqinfo,
.set_info = dquot_set_dqinfo,
--
1.8.1.4
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 09/11] quota: Remove quota_on_meta callback
2014-11-11 21:04 [PATCH 0/11 RFC] quota: Unify VFS and XFS quota interfaces Jan Kara
` (7 preceding siblings ...)
2014-11-11 21:04 ` [PATCH 08/11] ocfs2: " Jan Kara
@ 2014-11-11 21:04 ` Jan Kara
2014-11-11 21:04 ` [PATCH 10/11] quota: Switch ->get_dqblk() and ->set_dqblk() to use bytes as space units Jan Kara
2014-11-11 21:04 ` [PATCH 11/11] quota: Store maximum space limit in bytes Jan Kara
10 siblings, 0 replies; 22+ messages in thread
From: Jan Kara @ 2014-11-11 21:04 UTC (permalink / raw)
To: linux-fsdevel; +Cc: linux-ext4, Jan Kara, xfs
There are no more users for quota_on_meta callback. Just remove it.
Signed-off-by: Jan Kara <jack@suse.cz>
---
fs/quota/quota.c | 5 +----
include/linux/quota.h | 1 -
2 files changed, 1 insertion(+), 5 deletions(-)
diff --git a/fs/quota/quota.c b/fs/quota/quota.c
index 162d533c4997..5650b7ce4714 100644
--- a/fs/quota/quota.c
+++ b/fs/quota/quota.c
@@ -79,11 +79,8 @@ unsigned int qtype_limit_flag(int type)
static int quota_quotaon(struct super_block *sb, int type, int cmd, qid_t id,
struct path *path)
{
- if (!sb->s_qcop->quota_on && !sb->s_qcop->quota_on_meta &&
- !sb->s_qcop->sysquota_on)
+ if (!sb->s_qcop->quota_on && !sb->s_qcop->sysquota_on)
return -ENOSYS;
- if (sb->s_qcop->quota_on_meta)
- return sb->s_qcop->quota_on_meta(sb, type, id);
if (sb->s_qcop->sysquota_on)
return sb->s_qcop->sysquota_on(sb, qtype_limit_flag(type));
if (IS_ERR(path))
diff --git a/include/linux/quota.h b/include/linux/quota.h
index 3a046676e4aa..06a214a21778 100644
--- a/include/linux/quota.h
+++ b/include/linux/quota.h
@@ -319,7 +319,6 @@ struct path;
/* Operations handling requests from userspace */
struct quotactl_ops {
int (*quota_on)(struct super_block *, int, int, struct path *);
- int (*quota_on_meta)(struct super_block *, int, int);
int (*quota_off)(struct super_block *, int);
int (*quota_sync)(struct super_block *, int);
int (*get_info)(struct super_block *, int, struct if_dqinfo *);
--
1.8.1.4
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 10/11] quota: Switch ->get_dqblk() and ->set_dqblk() to use bytes as space units
2014-11-11 21:04 [PATCH 0/11 RFC] quota: Unify VFS and XFS quota interfaces Jan Kara
` (8 preceding siblings ...)
2014-11-11 21:04 ` [PATCH 09/11] quota: Remove quota_on_meta callback Jan Kara
@ 2014-11-11 21:04 ` Jan Kara
2014-11-18 22:29 ` Dave Chinner
2014-11-11 21:04 ` [PATCH 11/11] quota: Store maximum space limit in bytes Jan Kara
10 siblings, 1 reply; 22+ messages in thread
From: Jan Kara @ 2014-11-11 21:04 UTC (permalink / raw)
To: linux-fsdevel; +Cc: linux-ext4, xfs, Jan Kara
Currently ->get_dqblk() and ->set_dqblk() use struct fs_disk_quota which
tracks space limits and usage in 512-byte blocks. However VFS quotas
track usage in bytes (as some filesystems require that) and we need to
somehow pass this information. Upto now it wasn't a problem because we
didn't do any unit conversion (thus VFS quota routines happily stuck
number of bytes into d_bcount field of struct fd_disk_quota). Only if
you tried to use Q_XGETQUOTA or Q_XSETQLIM for VFS quotas (or Q_GETQUOTA
/ Q_SETQUOTA for XFS quotas), you got bogus results but noone really
tried that. But when we want interfaces compatible we need to fix this.
So we bite the bullet and define another quota structure used for
passing information from/to ->get_dqblk()/->set_dqblk. It's somewhat
sad we have to have more conversion routines in fs/quota/quota.c but
it seems cleaner than overloading e.g. units of d_bcount to bytes.
Signed-off-by: Jan Kara <jack@suse.cz>
---
fs/gfs2/quota.c | 49 +++++++--------
fs/quota/dquot.c | 83 ++++++++++++-------------
fs/quota/quota.c | 157 +++++++++++++++++++++++++++++++++++++++--------
fs/xfs/xfs_qm.h | 4 +-
fs/xfs/xfs_qm_syscalls.c | 156 ++++++++++++++++++++--------------------------
fs/xfs/xfs_quotaops.c | 8 +--
include/linux/quota.h | 47 +++++++++++++-
include/linux/quotaops.h | 4 +-
8 files changed, 313 insertions(+), 195 deletions(-)
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c
index 64b29f7f6b4c..dc482ffff659 100644
--- a/fs/gfs2/quota.c
+++ b/fs/gfs2/quota.c
@@ -667,7 +667,7 @@ static void do_qc(struct gfs2_quota_data *qd, s64 change)
static int gfs2_adjust_quota(struct gfs2_inode *ip, loff_t loc,
s64 change, struct gfs2_quota_data *qd,
- struct fs_disk_quota *fdq)
+ struct qc_dqblk *fdq)
{
struct inode *inode = &ip->i_inode;
struct gfs2_sbd *sdp = GFS2_SB(inode);
@@ -697,16 +697,16 @@ static int gfs2_adjust_quota(struct gfs2_inode *ip, loff_t loc,
be64_add_cpu(&q.qu_value, change);
qd->qd_qb.qb_value = q.qu_value;
if (fdq) {
- if (fdq->d_fieldmask & FS_DQ_BSOFT) {
- q.qu_warn = cpu_to_be64(fdq->d_blk_softlimit >> sdp->sd_fsb2bb_shift);
+ if (fdq->d_fieldmask & QC_SPC_SOFT) {
+ q.qu_warn = cpu_to_be64(fdq->d_spc_softlimit >> sdp->sd_sb.sb_bsize_shift);
qd->qd_qb.qb_warn = q.qu_warn;
}
- if (fdq->d_fieldmask & FS_DQ_BHARD) {
- q.qu_limit = cpu_to_be64(fdq->d_blk_hardlimit >> sdp->sd_fsb2bb_shift);
+ if (fdq->d_fieldmask & QC_SPC_HARD) {
+ q.qu_limit = cpu_to_be64(fdq->d_spc_hardlimit >> sdp->sd_sb.sb_bsize_shift);
qd->qd_qb.qb_limit = q.qu_limit;
}
- if (fdq->d_fieldmask & FS_DQ_BCOUNT) {
- q.qu_value = cpu_to_be64(fdq->d_bcount >> sdp->sd_fsb2bb_shift);
+ if (fdq->d_fieldmask & QC_SPACE) {
+ q.qu_value = cpu_to_be64(fdq->d_space >> sdp->sd_sb.sb_bsize_shift);
qd->qd_qb.qb_value = q.qu_value;
}
}
@@ -1502,7 +1502,7 @@ static int gfs2_quota_get_xstate(struct super_block *sb,
}
static int gfs2_get_dqblk(struct super_block *sb, struct kqid qid,
- struct fs_disk_quota *fdq)
+ struct qc_dqblk *fdq)
{
struct gfs2_sbd *sdp = sb->s_fs_info;
struct gfs2_quota_lvb *qlvb;
@@ -1510,7 +1510,7 @@ static int gfs2_get_dqblk(struct super_block *sb, struct kqid qid,
struct gfs2_holder q_gh;
int error;
- memset(fdq, 0, sizeof(struct fs_disk_quota));
+ memset(fdq, 0, sizeof(*fdq));
if (sdp->sd_args.ar_quota == GFS2_QUOTA_OFF)
return -ESRCH; /* Crazy XFS error code */
@@ -1527,12 +1527,9 @@ static int gfs2_get_dqblk(struct super_block *sb, struct kqid qid,
goto out;
qlvb = (struct gfs2_quota_lvb *)qd->qd_gl->gl_lksb.sb_lvbptr;
- fdq->d_version = FS_DQUOT_VERSION;
- fdq->d_flags = (qid.type == USRQUOTA) ? FS_USER_QUOTA : FS_GROUP_QUOTA;
- fdq->d_id = from_kqid_munged(current_user_ns(), qid);
- fdq->d_blk_hardlimit = be64_to_cpu(qlvb->qb_limit) << sdp->sd_fsb2bb_shift;
- fdq->d_blk_softlimit = be64_to_cpu(qlvb->qb_warn) << sdp->sd_fsb2bb_shift;
- fdq->d_bcount = be64_to_cpu(qlvb->qb_value) << sdp->sd_fsb2bb_shift;
+ fdq->d_spc_hardlimit = be64_to_cpu(qlvb->qb_limit) << sdp->sd_sb.sb_bsize_shift;
+ fdq->d_spc_softlimit = be64_to_cpu(qlvb->qb_warn) << sdp->sd_sb.sb_bsize_shift;
+ fdq->d_space = be64_to_cpu(qlvb->qb_value) << sdp->sd_sb.sb_bsize_shift;
gfs2_glock_dq_uninit(&q_gh);
out:
@@ -1541,10 +1538,10 @@ out:
}
/* GFS2 only supports a subset of the XFS fields */
-#define GFS2_FIELDMASK (FS_DQ_BSOFT|FS_DQ_BHARD|FS_DQ_BCOUNT)
+#define GFS2_FIELDMASK (QC_SPC_SOFT|QC_SPC_HARD|QC_SPACE)
static int gfs2_set_dqblk(struct super_block *sb, struct kqid qid,
- struct fs_disk_quota *fdq)
+ struct qc_dqblk *fdq)
{
struct gfs2_sbd *sdp = sb->s_fs_info;
struct gfs2_inode *ip = GFS2_I(sdp->sd_quota_inode);
@@ -1588,17 +1585,17 @@ static int gfs2_set_dqblk(struct super_block *sb, struct kqid qid,
goto out_i;
/* If nothing has changed, this is a no-op */
- if ((fdq->d_fieldmask & FS_DQ_BSOFT) &&
- ((fdq->d_blk_softlimit >> sdp->sd_fsb2bb_shift) == be64_to_cpu(qd->qd_qb.qb_warn)))
- fdq->d_fieldmask ^= FS_DQ_BSOFT;
+ if ((fdq->d_fieldmask & QC_SPC_SOFT) &&
+ ((fdq->d_spc_softlimit >> sdp->sd_sb.sb_bsize_shift) == be64_to_cpu(qd->qd_qb.qb_warn)))
+ fdq->d_fieldmask ^= QC_SPC_SOFT;
- if ((fdq->d_fieldmask & FS_DQ_BHARD) &&
- ((fdq->d_blk_hardlimit >> sdp->sd_fsb2bb_shift) == be64_to_cpu(qd->qd_qb.qb_limit)))
- fdq->d_fieldmask ^= FS_DQ_BHARD;
+ if ((fdq->d_fieldmask & QC_SPC_HARD) &&
+ ((fdq->d_spc_hardlimit >> sdp->sd_sb.sb_bsize_shift) == be64_to_cpu(qd->qd_qb.qb_limit)))
+ fdq->d_fieldmask ^= QC_SPC_HARD;
- if ((fdq->d_fieldmask & FS_DQ_BCOUNT) &&
- ((fdq->d_bcount >> sdp->sd_fsb2bb_shift) == be64_to_cpu(qd->qd_qb.qb_value)))
- fdq->d_fieldmask ^= FS_DQ_BCOUNT;
+ if ((fdq->d_fieldmask & QC_SPACE) &&
+ ((fdq->d_space >> sdp->sd_sb.sb_bsize_shift) == be64_to_cpu(qd->qd_qb.qb_value)))
+ fdq->d_fieldmask ^= QC_SPACE;
if (fdq->d_fieldmask == 0)
goto out_i;
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c
index b7359c9da61e..887ead8c88e2 100644
--- a/fs/quota/dquot.c
+++ b/fs/quota/dquot.c
@@ -2473,30 +2473,25 @@ static inline qsize_t stoqb(qsize_t space)
}
/* Generic routine for getting common part of quota structure */
-static void do_get_dqblk(struct dquot *dquot, struct fs_disk_quota *di)
+static void do_get_dqblk(struct dquot *dquot, struct qc_dqblk *di)
{
struct mem_dqblk *dm = &dquot->dq_dqb;
memset(di, 0, sizeof(*di));
- di->d_version = FS_DQUOT_VERSION;
- di->d_flags = dquot->dq_id.type == USRQUOTA ?
- FS_USER_QUOTA : FS_GROUP_QUOTA;
- di->d_id = from_kqid_munged(current_user_ns(), dquot->dq_id);
-
spin_lock(&dq_data_lock);
- di->d_blk_hardlimit = stoqb(dm->dqb_bhardlimit);
- di->d_blk_softlimit = stoqb(dm->dqb_bsoftlimit);
+ di->d_spc_hardlimit = dm->dqb_bhardlimit;
+ di->d_spc_softlimit = dm->dqb_bsoftlimit;
di->d_ino_hardlimit = dm->dqb_ihardlimit;
di->d_ino_softlimit = dm->dqb_isoftlimit;
- di->d_bcount = dm->dqb_curspace + dm->dqb_rsvspace;
- di->d_icount = dm->dqb_curinodes;
- di->d_btimer = dm->dqb_btime;
- di->d_itimer = dm->dqb_itime;
+ di->d_space = dm->dqb_curspace + dm->dqb_rsvspace;
+ di->d_ino_count = dm->dqb_curinodes;
+ di->d_spc_timer = dm->dqb_btime;
+ di->d_ino_timer = dm->dqb_itime;
spin_unlock(&dq_data_lock);
}
int dquot_get_dqblk(struct super_block *sb, struct kqid qid,
- struct fs_disk_quota *di)
+ struct qc_dqblk *di)
{
struct dquot *dquot;
@@ -2510,70 +2505,70 @@ int dquot_get_dqblk(struct super_block *sb, struct kqid qid,
}
EXPORT_SYMBOL(dquot_get_dqblk);
-#define VFS_FS_DQ_MASK \
- (FS_DQ_BCOUNT | FS_DQ_BSOFT | FS_DQ_BHARD | \
- FS_DQ_ICOUNT | FS_DQ_ISOFT | FS_DQ_IHARD | \
- FS_DQ_BTIMER | FS_DQ_ITIMER)
+#define VFS_QC_MASK \
+ (QC_SPACE | QC_SPC_SOFT | QC_SPC_HARD | \
+ QC_INO_COUNT | QC_INO_SOFT | QC_INO_HARD | \
+ QC_SPC_TIMER | QC_INO_TIMER)
/* Generic routine for setting common part of quota structure */
-static int do_set_dqblk(struct dquot *dquot, struct fs_disk_quota *di)
+static int do_set_dqblk(struct dquot *dquot, struct qc_dqblk *di)
{
struct mem_dqblk *dm = &dquot->dq_dqb;
int check_blim = 0, check_ilim = 0;
struct mem_dqinfo *dqi = &sb_dqopt(dquot->dq_sb)->info[dquot->dq_id.type];
- if (di->d_fieldmask & ~VFS_FS_DQ_MASK)
+ if (di->d_fieldmask & ~VFS_QC_MASK)
return -EINVAL;
- if (((di->d_fieldmask & FS_DQ_BSOFT) &&
- (di->d_blk_softlimit > dqi->dqi_maxblimit)) ||
- ((di->d_fieldmask & FS_DQ_BHARD) &&
- (di->d_blk_hardlimit > dqi->dqi_maxblimit)) ||
- ((di->d_fieldmask & FS_DQ_ISOFT) &&
+ if (((di->d_fieldmask & QC_SPC_SOFT) &&
+ stoqb(di->d_spc_softlimit) > dqi->dqi_maxblimit) ||
+ ((di->d_fieldmask & QC_SPC_HARD) &&
+ stoqb(di->d_spc_hardlimit) > dqi->dqi_maxblimit) ||
+ ((di->d_fieldmask & QC_INO_SOFT) &&
(di->d_ino_softlimit > dqi->dqi_maxilimit)) ||
- ((di->d_fieldmask & FS_DQ_IHARD) &&
+ ((di->d_fieldmask & QC_INO_HARD) &&
(di->d_ino_hardlimit > dqi->dqi_maxilimit)))
return -ERANGE;
spin_lock(&dq_data_lock);
- if (di->d_fieldmask & FS_DQ_BCOUNT) {
- dm->dqb_curspace = di->d_bcount - dm->dqb_rsvspace;
+ if (di->d_fieldmask & QC_SPACE) {
+ dm->dqb_curspace = di->d_space - dm->dqb_rsvspace;
check_blim = 1;
set_bit(DQ_LASTSET_B + QIF_SPACE_B, &dquot->dq_flags);
}
- if (di->d_fieldmask & FS_DQ_BSOFT)
- dm->dqb_bsoftlimit = qbtos(di->d_blk_softlimit);
- if (di->d_fieldmask & FS_DQ_BHARD)
- dm->dqb_bhardlimit = qbtos(di->d_blk_hardlimit);
- if (di->d_fieldmask & (FS_DQ_BSOFT | FS_DQ_BHARD)) {
+ if (di->d_fieldmask & QC_SPC_SOFT)
+ dm->dqb_bsoftlimit = di->d_spc_softlimit;
+ if (di->d_fieldmask & QC_SPC_HARD)
+ dm->dqb_bhardlimit = di->d_spc_hardlimit;
+ if (di->d_fieldmask & (QC_SPC_SOFT | QC_SPC_HARD)) {
check_blim = 1;
set_bit(DQ_LASTSET_B + QIF_BLIMITS_B, &dquot->dq_flags);
}
- if (di->d_fieldmask & FS_DQ_ICOUNT) {
- dm->dqb_curinodes = di->d_icount;
+ if (di->d_fieldmask & QC_INO_COUNT) {
+ dm->dqb_curinodes = di->d_ino_count;
check_ilim = 1;
set_bit(DQ_LASTSET_B + QIF_INODES_B, &dquot->dq_flags);
}
- if (di->d_fieldmask & FS_DQ_ISOFT)
+ if (di->d_fieldmask & QC_INO_SOFT)
dm->dqb_isoftlimit = di->d_ino_softlimit;
- if (di->d_fieldmask & FS_DQ_IHARD)
+ if (di->d_fieldmask & QC_INO_HARD)
dm->dqb_ihardlimit = di->d_ino_hardlimit;
- if (di->d_fieldmask & (FS_DQ_ISOFT | FS_DQ_IHARD)) {
+ if (di->d_fieldmask & (QC_INO_SOFT | QC_INO_HARD)) {
check_ilim = 1;
set_bit(DQ_LASTSET_B + QIF_ILIMITS_B, &dquot->dq_flags);
}
- if (di->d_fieldmask & FS_DQ_BTIMER) {
- dm->dqb_btime = di->d_btimer;
+ if (di->d_fieldmask & QC_SPC_TIMER) {
+ dm->dqb_btime = di->d_spc_timer;
check_blim = 1;
set_bit(DQ_LASTSET_B + QIF_BTIME_B, &dquot->dq_flags);
}
- if (di->d_fieldmask & FS_DQ_ITIMER) {
- dm->dqb_itime = di->d_itimer;
+ if (di->d_fieldmask & QC_INO_TIMER) {
+ dm->dqb_itime = di->d_ino_timer;
check_ilim = 1;
set_bit(DQ_LASTSET_B + QIF_ITIME_B, &dquot->dq_flags);
}
@@ -2583,7 +2578,7 @@ static int do_set_dqblk(struct dquot *dquot, struct fs_disk_quota *di)
dm->dqb_curspace < dm->dqb_bsoftlimit) {
dm->dqb_btime = 0;
clear_bit(DQ_BLKS_B, &dquot->dq_flags);
- } else if (!(di->d_fieldmask & FS_DQ_BTIMER))
+ } else if (!(di->d_fieldmask & QC_SPC_TIMER))
/* Set grace only if user hasn't provided his own... */
dm->dqb_btime = get_seconds() + dqi->dqi_bgrace;
}
@@ -2592,7 +2587,7 @@ static int do_set_dqblk(struct dquot *dquot, struct fs_disk_quota *di)
dm->dqb_curinodes < dm->dqb_isoftlimit) {
dm->dqb_itime = 0;
clear_bit(DQ_INODES_B, &dquot->dq_flags);
- } else if (!(di->d_fieldmask & FS_DQ_ITIMER))
+ } else if (!(di->d_fieldmask & QC_INO_TIMER))
/* Set grace only if user hasn't provided his own... */
dm->dqb_itime = get_seconds() + dqi->dqi_igrace;
}
@@ -2608,7 +2603,7 @@ static int do_set_dqblk(struct dquot *dquot, struct fs_disk_quota *di)
}
int dquot_set_dqblk(struct super_block *sb, struct kqid qid,
- struct fs_disk_quota *di)
+ struct qc_dqblk *di)
{
struct dquot *dquot;
int rc;
diff --git a/fs/quota/quota.c b/fs/quota/quota.c
index 5650b7ce4714..84275f74dc7f 100644
--- a/fs/quota/quota.c
+++ b/fs/quota/quota.c
@@ -137,17 +137,27 @@ static int quota_setinfo(struct super_block *sb, int type, void __user *addr)
return sb->s_qcop->set_info(sb, type, &info);
}
-static void copy_to_if_dqblk(struct if_dqblk *dst, struct fs_disk_quota *src)
+static inline qsize_t qbtos(qsize_t blocks)
+{
+ return blocks << QIF_DQBLKSIZE_BITS;
+}
+
+static inline qsize_t stoqb(qsize_t space)
+{
+ return (space + QIF_DQBLKSIZE - 1) >> QIF_DQBLKSIZE_BITS;
+}
+
+static void copy_to_if_dqblk(struct if_dqblk *dst, struct qc_dqblk *src)
{
memset(dst, 0, sizeof(*dst));
- dst->dqb_bhardlimit = src->d_blk_hardlimit;
- dst->dqb_bsoftlimit = src->d_blk_softlimit;
- dst->dqb_curspace = src->d_bcount;
+ dst->dqb_bhardlimit = stoqb(src->d_spc_hardlimit);
+ dst->dqb_bsoftlimit = stoqb(src->d_spc_softlimit);
+ dst->dqb_curspace = src->d_space;
dst->dqb_ihardlimit = src->d_ino_hardlimit;
dst->dqb_isoftlimit = src->d_ino_softlimit;
- dst->dqb_curinodes = src->d_icount;
- dst->dqb_btime = src->d_btimer;
- dst->dqb_itime = src->d_itimer;
+ dst->dqb_curinodes = src->d_ino_count;
+ dst->dqb_btime = src->d_spc_timer;
+ dst->dqb_itime = src->d_ino_timer;
dst->dqb_valid = QIF_ALL;
}
@@ -155,7 +165,7 @@ static int quota_getquota(struct super_block *sb, int type, qid_t id,
void __user *addr)
{
struct kqid qid;
- struct fs_disk_quota fdq;
+ struct qc_dqblk fdq;
struct if_dqblk idq;
int ret;
@@ -173,36 +183,36 @@ static int quota_getquota(struct super_block *sb, int type, qid_t id,
return 0;
}
-static void copy_from_if_dqblk(struct fs_disk_quota *dst, struct if_dqblk *src)
+static void copy_from_if_dqblk(struct qc_dqblk *dst, struct if_dqblk *src)
{
- dst->d_blk_hardlimit = src->dqb_bhardlimit;
- dst->d_blk_softlimit = src->dqb_bsoftlimit;
- dst->d_bcount = src->dqb_curspace;
+ dst->d_spc_hardlimit = qbtos(src->dqb_bhardlimit);
+ dst->d_spc_softlimit = qbtos(src->dqb_bsoftlimit);
+ dst->d_space = src->dqb_curspace;
dst->d_ino_hardlimit = src->dqb_ihardlimit;
dst->d_ino_softlimit = src->dqb_isoftlimit;
- dst->d_icount = src->dqb_curinodes;
- dst->d_btimer = src->dqb_btime;
- dst->d_itimer = src->dqb_itime;
+ dst->d_ino_count = src->dqb_curinodes;
+ dst->d_spc_timer = src->dqb_btime;
+ dst->d_ino_timer = src->dqb_itime;
dst->d_fieldmask = 0;
if (src->dqb_valid & QIF_BLIMITS)
- dst->d_fieldmask |= FS_DQ_BSOFT | FS_DQ_BHARD;
+ dst->d_fieldmask |= QC_SPC_SOFT | QC_SPC_HARD;
if (src->dqb_valid & QIF_SPACE)
- dst->d_fieldmask |= FS_DQ_BCOUNT;
+ dst->d_fieldmask |= QC_SPACE;
if (src->dqb_valid & QIF_ILIMITS)
- dst->d_fieldmask |= FS_DQ_ISOFT | FS_DQ_IHARD;
+ dst->d_fieldmask |= QC_INO_SOFT | QC_INO_HARD;
if (src->dqb_valid & QIF_INODES)
- dst->d_fieldmask |= FS_DQ_ICOUNT;
+ dst->d_fieldmask |= QC_INO_COUNT;
if (src->dqb_valid & QIF_BTIME)
- dst->d_fieldmask |= FS_DQ_BTIMER;
+ dst->d_fieldmask |= QC_SPC_TIMER;
if (src->dqb_valid & QIF_ITIME)
- dst->d_fieldmask |= FS_DQ_ITIMER;
+ dst->d_fieldmask |= QC_INO_TIMER;
}
static int quota_setquota(struct super_block *sb, int type, qid_t id,
void __user *addr)
{
- struct fs_disk_quota fdq;
+ struct qc_dqblk fdq;
struct if_dqblk idq;
struct kqid qid;
@@ -277,10 +287,73 @@ static int quota_getxstatev(struct super_block *sb, void __user *addr)
return ret;
}
+/* XFS blocks to space conversion */
+static u64 xfs_btos(u64 blocks)
+{
+ return blocks << 9;
+}
+
+/* Space to XFS blocks conversion */
+static u64 xfs_stob(u64 space)
+{
+ return (space + 511) >> 9;
+}
+
+static void copy_from_xfs_dqblk(struct qc_dqblk *dst, struct fs_disk_quota *src)
+{
+ dst->d_spc_hardlimit = xfs_btos(src->d_blk_hardlimit);
+ dst->d_spc_softlimit = xfs_btos(src->d_blk_softlimit);
+ dst->d_ino_hardlimit = src->d_ino_hardlimit;
+ dst->d_ino_softlimit = src->d_ino_softlimit;
+ dst->d_space = xfs_btos(src->d_bcount);
+ dst->d_ino_count = src->d_icount;
+ dst->d_ino_timer = src->d_itimer;
+ dst->d_spc_timer = src->d_btimer;
+ dst->d_ino_warns = src->d_iwarns;
+ dst->d_spc_warns = src->d_bwarns;
+ dst->d_rt_spc_hardlimit = xfs_btos(src->d_rtb_hardlimit);
+ dst->d_rt_spc_softlimit = xfs_btos(src->d_rtb_softlimit);
+ dst->d_rt_space = xfs_btos(src->d_rtbcount);
+ dst->d_rt_spc_timer = src->d_rtbtimer;
+ dst->d_rt_spc_warns = src->d_rtbwarns;
+ dst->d_fieldmask = 0;
+ if (src->d_fieldmask & FS_DQ_ISOFT)
+ dst->d_fieldmask |= QC_INO_SOFT;
+ if (src->d_fieldmask & FS_DQ_IHARD)
+ dst->d_fieldmask |= QC_INO_HARD;
+ if (src->d_fieldmask & FS_DQ_BSOFT)
+ dst->d_fieldmask |= QC_SPC_SOFT;
+ if (src->d_fieldmask & FS_DQ_BHARD)
+ dst->d_fieldmask |= QC_SPC_HARD;
+ if (src->d_fieldmask & FS_DQ_RTBSOFT)
+ dst->d_fieldmask |= QC_RT_SPC_SOFT;
+ if (src->d_fieldmask & FS_DQ_RTBHARD)
+ dst->d_fieldmask |= QC_RT_SPC_HARD;
+ if (src->d_fieldmask & FS_DQ_BTIMER)
+ dst->d_fieldmask |= QC_SPC_TIMER;
+ if (src->d_fieldmask & FS_DQ_ITIMER)
+ dst->d_fieldmask |= QC_INO_TIMER;
+ if (src->d_fieldmask & FS_DQ_RTBTIMER)
+ dst->d_fieldmask |= QC_RT_SPC_TIMER;
+ if (src->d_fieldmask & FS_DQ_BWARNS)
+ dst->d_fieldmask |= QC_SPC_WARNS;
+ if (src->d_fieldmask & FS_DQ_IWARNS)
+ dst->d_fieldmask |= QC_INO_WARNS;
+ if (src->d_fieldmask & FS_DQ_RTBWARNS)
+ dst->d_fieldmask |= QC_RT_SPC_WARNS;
+ if (src->d_fieldmask & FS_DQ_BCOUNT)
+ dst->d_fieldmask |= QC_SPACE;
+ if (src->d_fieldmask & FS_DQ_ICOUNT)
+ dst->d_fieldmask |= QC_INO_COUNT;
+ if (src->d_fieldmask & FS_DQ_RTBCOUNT)
+ dst->d_fieldmask |= QC_RT_SPACE;
+}
+
static int quota_setxquota(struct super_block *sb, int type, qid_t id,
void __user *addr)
{
struct fs_disk_quota fdq;
+ struct qc_dqblk qdq;
struct kqid qid;
if (copy_from_user(&fdq, addr, sizeof(fdq)))
@@ -290,13 +363,44 @@ static int quota_setxquota(struct super_block *sb, int type, qid_t id,
qid = make_kqid(current_user_ns(), type, id);
if (!qid_valid(qid))
return -EINVAL;
- return sb->s_qcop->set_dqblk(sb, qid, &fdq);
+ copy_from_xfs_dqblk(&qdq, &fdq);
+ return sb->s_qcop->set_dqblk(sb, qid, &qdq);
+}
+
+static void copy_to_xfs_dqblk(struct fs_disk_quota *dst, struct qc_dqblk *src,
+ int type, qid_t id)
+{
+ memset(dst, 0, sizeof(*dst));
+ dst->d_version = FS_DQUOT_VERSION;
+ dst->d_id = id;
+ if (type == USRQUOTA)
+ dst->d_flags = FS_USER_QUOTA;
+ else if (type == PRJQUOTA)
+ dst->d_flags = FS_PROJ_QUOTA;
+ else
+ dst->d_flags = FS_GROUP_QUOTA;
+ dst->d_blk_hardlimit = xfs_stob(src->d_spc_hardlimit);
+ dst->d_blk_softlimit = xfs_stob(src->d_spc_softlimit);
+ dst->d_ino_hardlimit = src->d_ino_hardlimit;
+ dst->d_ino_softlimit = src->d_ino_softlimit;
+ dst->d_bcount = xfs_stob(src->d_space);
+ dst->d_icount = src->d_ino_count;
+ dst->d_itimer = src->d_ino_timer;
+ dst->d_btimer = src->d_spc_timer;
+ dst->d_iwarns = src->d_ino_warns;
+ dst->d_bwarns = src->d_spc_warns;
+ dst->d_rtb_hardlimit = xfs_stob(src->d_rt_spc_hardlimit);
+ dst->d_rtb_softlimit = xfs_stob(src->d_rt_spc_softlimit);
+ dst->d_rtbcount = xfs_stob(src->d_rt_space);
+ dst->d_rtbtimer = src->d_rt_spc_timer;
+ dst->d_rtbwarns = src->d_rt_spc_warns;
}
static int quota_getxquota(struct super_block *sb, int type, qid_t id,
void __user *addr)
{
struct fs_disk_quota fdq;
+ struct qc_dqblk qdq;
struct kqid qid;
int ret;
@@ -305,8 +409,11 @@ static int quota_getxquota(struct super_block *sb, int type, qid_t id,
qid = make_kqid(current_user_ns(), type, id);
if (!qid_valid(qid))
return -EINVAL;
- ret = sb->s_qcop->get_dqblk(sb, qid, &fdq);
- if (!ret && copy_to_user(addr, &fdq, sizeof(fdq)))
+ ret = sb->s_qcop->get_dqblk(sb, qid, &qdq);
+ if (ret)
+ return ret;
+ copy_to_xfs_dqblk(&fdq, &qdq, type, id);
+ if (copy_to_user(addr, &fdq, sizeof(fdq)))
return -EFAULT;
return ret;
}
diff --git a/fs/xfs/xfs_qm.h b/fs/xfs/xfs_qm.h
index 3a07a937e232..41f6c0b9d51c 100644
--- a/fs/xfs/xfs_qm.h
+++ b/fs/xfs/xfs_qm.h
@@ -166,9 +166,9 @@ extern void xfs_qm_dqrele_all_inodes(struct xfs_mount *, uint);
/* quota ops */
extern int xfs_qm_scall_trunc_qfiles(struct xfs_mount *, uint);
extern int xfs_qm_scall_getquota(struct xfs_mount *, xfs_dqid_t,
- uint, struct fs_disk_quota *);
+ uint, struct qc_dqblk *);
extern int xfs_qm_scall_setqlim(struct xfs_mount *, xfs_dqid_t, uint,
- struct fs_disk_quota *);
+ struct qc_dqblk *);
extern int xfs_qm_scall_getqstat(struct xfs_mount *,
struct fs_quota_stat *);
extern int xfs_qm_scall_getqstatv(struct xfs_mount *,
diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c
index 60bca27d3d04..72a53ab93844 100644
--- a/fs/xfs/xfs_qm_syscalls.c
+++ b/fs/xfs/xfs_qm_syscalls.c
@@ -40,7 +40,6 @@ STATIC int xfs_qm_log_quotaoff(xfs_mount_t *, xfs_qoff_logitem_t **, uint);
STATIC int xfs_qm_log_quotaoff_end(xfs_mount_t *, xfs_qoff_logitem_t *,
uint);
STATIC uint xfs_qm_export_flags(uint);
-STATIC uint xfs_qm_export_qtype_flags(uint);
/*
* Turn off quota accounting and/or enforcement for all udquots and/or
@@ -563,8 +562,8 @@ xfs_qm_scall_getqstatv(
return 0;
}
-#define XFS_DQ_MASK \
- (FS_DQ_LIMIT_MASK | FS_DQ_TIMER_MASK | FS_DQ_WARNS_MASK)
+#define XFS_QC_MASK \
+ (QC_LIMIT_MASK | QC_TIMER_MASK | QC_WARNS_MASK)
/*
* Adjust quota limits, and start/stop timers accordingly.
@@ -574,7 +573,7 @@ xfs_qm_scall_setqlim(
struct xfs_mount *mp,
xfs_dqid_t id,
uint type,
- fs_disk_quota_t *newlim)
+ struct qc_dqblk *newlim)
{
struct xfs_quotainfo *q = mp->m_quotainfo;
struct xfs_disk_dquot *ddq;
@@ -583,9 +582,9 @@ xfs_qm_scall_setqlim(
int error;
xfs_qcnt_t hard, soft;
- if (newlim->d_fieldmask & ~XFS_DQ_MASK)
+ if (newlim->d_fieldmask & ~XFS_QC_MASK)
return -EINVAL;
- if ((newlim->d_fieldmask & XFS_DQ_MASK) == 0)
+ if ((newlim->d_fieldmask & XFS_QC_MASK) == 0)
return 0;
/*
@@ -623,11 +622,11 @@ xfs_qm_scall_setqlim(
/*
* Make sure that hardlimits are >= soft limits before changing.
*/
- hard = (newlim->d_fieldmask & FS_DQ_BHARD) ?
- (xfs_qcnt_t) XFS_BB_TO_FSB(mp, newlim->d_blk_hardlimit) :
+ hard = (newlim->d_fieldmask & QC_SPC_HARD) ?
+ (xfs_qcnt_t) XFS_B_TO_FSB(mp, newlim->d_spc_hardlimit) :
be64_to_cpu(ddq->d_blk_hardlimit);
- soft = (newlim->d_fieldmask & FS_DQ_BSOFT) ?
- (xfs_qcnt_t) XFS_BB_TO_FSB(mp, newlim->d_blk_softlimit) :
+ soft = (newlim->d_fieldmask & QC_SPC_SOFT) ?
+ (xfs_qcnt_t) XFS_B_TO_FSB(mp, newlim->d_spc_softlimit) :
be64_to_cpu(ddq->d_blk_softlimit);
if (hard == 0 || hard >= soft) {
ddq->d_blk_hardlimit = cpu_to_be64(hard);
@@ -640,11 +639,11 @@ xfs_qm_scall_setqlim(
} else {
xfs_debug(mp, "blkhard %Ld < blksoft %Ld", hard, soft);
}
- hard = (newlim->d_fieldmask & FS_DQ_RTBHARD) ?
- (xfs_qcnt_t) XFS_BB_TO_FSB(mp, newlim->d_rtb_hardlimit) :
+ hard = (newlim->d_fieldmask & QC_RT_SPC_HARD) ?
+ (xfs_qcnt_t) XFS_B_TO_FSB(mp, newlim->d_rt_spc_hardlimit) :
be64_to_cpu(ddq->d_rtb_hardlimit);
- soft = (newlim->d_fieldmask & FS_DQ_RTBSOFT) ?
- (xfs_qcnt_t) XFS_BB_TO_FSB(mp, newlim->d_rtb_softlimit) :
+ soft = (newlim->d_fieldmask & QC_RT_SPC_SOFT) ?
+ (xfs_qcnt_t) XFS_B_TO_FSB(mp, newlim->d_rt_spc_softlimit) :
be64_to_cpu(ddq->d_rtb_softlimit);
if (hard == 0 || hard >= soft) {
ddq->d_rtb_hardlimit = cpu_to_be64(hard);
@@ -657,10 +656,10 @@ xfs_qm_scall_setqlim(
xfs_debug(mp, "rtbhard %Ld < rtbsoft %Ld", hard, soft);
}
- hard = (newlim->d_fieldmask & FS_DQ_IHARD) ?
+ hard = (newlim->d_fieldmask & QC_INO_HARD) ?
(xfs_qcnt_t) newlim->d_ino_hardlimit :
be64_to_cpu(ddq->d_ino_hardlimit);
- soft = (newlim->d_fieldmask & FS_DQ_ISOFT) ?
+ soft = (newlim->d_fieldmask & QC_INO_SOFT) ?
(xfs_qcnt_t) newlim->d_ino_softlimit :
be64_to_cpu(ddq->d_ino_softlimit);
if (hard == 0 || hard >= soft) {
@@ -677,12 +676,12 @@ xfs_qm_scall_setqlim(
/*
* Update warnings counter(s) if requested
*/
- if (newlim->d_fieldmask & FS_DQ_BWARNS)
- ddq->d_bwarns = cpu_to_be16(newlim->d_bwarns);
- if (newlim->d_fieldmask & FS_DQ_IWARNS)
- ddq->d_iwarns = cpu_to_be16(newlim->d_iwarns);
- if (newlim->d_fieldmask & FS_DQ_RTBWARNS)
- ddq->d_rtbwarns = cpu_to_be16(newlim->d_rtbwarns);
+ if (newlim->d_fieldmask & QC_SPC_WARNS)
+ ddq->d_bwarns = cpu_to_be16(newlim->d_spc_warns);
+ if (newlim->d_fieldmask & QC_INO_WARNS)
+ ddq->d_iwarns = cpu_to_be16(newlim->d_ino_warns);
+ if (newlim->d_fieldmask & QC_RT_SPC_WARNS)
+ ddq->d_rtbwarns = cpu_to_be16(newlim->d_rt_spc_warns);
if (id == 0) {
/*
@@ -692,24 +691,24 @@ xfs_qm_scall_setqlim(
* soft and hard limit values (already done, above), and
* for warnings.
*/
- if (newlim->d_fieldmask & FS_DQ_BTIMER) {
- q->qi_btimelimit = newlim->d_btimer;
- ddq->d_btimer = cpu_to_be32(newlim->d_btimer);
+ if (newlim->d_fieldmask & QC_SPC_TIMER) {
+ q->qi_btimelimit = newlim->d_spc_timer;
+ ddq->d_btimer = cpu_to_be32(newlim->d_spc_timer);
}
- if (newlim->d_fieldmask & FS_DQ_ITIMER) {
- q->qi_itimelimit = newlim->d_itimer;
- ddq->d_itimer = cpu_to_be32(newlim->d_itimer);
+ if (newlim->d_fieldmask & QC_INO_TIMER) {
+ q->qi_itimelimit = newlim->d_ino_timer;
+ ddq->d_itimer = cpu_to_be32(newlim->d_ino_timer);
}
- if (newlim->d_fieldmask & FS_DQ_RTBTIMER) {
- q->qi_rtbtimelimit = newlim->d_rtbtimer;
- ddq->d_rtbtimer = cpu_to_be32(newlim->d_rtbtimer);
+ if (newlim->d_fieldmask & QC_RT_SPC_TIMER) {
+ q->qi_rtbtimelimit = newlim->d_rt_spc_timer;
+ ddq->d_rtbtimer = cpu_to_be32(newlim->d_rt_spc_timer);
}
- if (newlim->d_fieldmask & FS_DQ_BWARNS)
- q->qi_bwarnlimit = newlim->d_bwarns;
- if (newlim->d_fieldmask & FS_DQ_IWARNS)
- q->qi_iwarnlimit = newlim->d_iwarns;
- if (newlim->d_fieldmask & FS_DQ_RTBWARNS)
- q->qi_rtbwarnlimit = newlim->d_rtbwarns;
+ if (newlim->d_fieldmask & QC_SPC_WARNS)
+ q->qi_bwarnlimit = newlim->d_spc_warns;
+ if (newlim->d_fieldmask & QC_INO_WARNS)
+ q->qi_iwarnlimit = newlim->d_ino_warns;
+ if (newlim->d_fieldmask & QC_RT_SPC_WARNS)
+ q->qi_rtbwarnlimit = newlim->d_rt_spc_warns;
} else {
/*
* If the user is now over quota, start the timelimit.
@@ -820,7 +819,7 @@ xfs_qm_scall_getquota(
struct xfs_mount *mp,
xfs_dqid_t id,
uint type,
- struct fs_disk_quota *dst)
+ struct qc_dqblk *dst)
{
struct xfs_dquot *dqp;
int error;
@@ -844,28 +843,25 @@ xfs_qm_scall_getquota(
}
memset(dst, 0, sizeof(*dst));
- dst->d_version = FS_DQUOT_VERSION;
- dst->d_flags = xfs_qm_export_qtype_flags(dqp->q_core.d_flags);
- dst->d_id = be32_to_cpu(dqp->q_core.d_id);
- dst->d_blk_hardlimit =
- XFS_FSB_TO_BB(mp, be64_to_cpu(dqp->q_core.d_blk_hardlimit));
- dst->d_blk_softlimit =
- XFS_FSB_TO_BB(mp, be64_to_cpu(dqp->q_core.d_blk_softlimit));
+ dst->d_spc_hardlimit =
+ XFS_FSB_TO_B(mp, be64_to_cpu(dqp->q_core.d_blk_hardlimit));
+ dst->d_spc_softlimit =
+ XFS_FSB_TO_B(mp, be64_to_cpu(dqp->q_core.d_blk_softlimit));
dst->d_ino_hardlimit = be64_to_cpu(dqp->q_core.d_ino_hardlimit);
dst->d_ino_softlimit = be64_to_cpu(dqp->q_core.d_ino_softlimit);
- dst->d_bcount = XFS_FSB_TO_BB(mp, dqp->q_res_bcount);
- dst->d_icount = dqp->q_res_icount;
- dst->d_btimer = be32_to_cpu(dqp->q_core.d_btimer);
- dst->d_itimer = be32_to_cpu(dqp->q_core.d_itimer);
- dst->d_iwarns = be16_to_cpu(dqp->q_core.d_iwarns);
- dst->d_bwarns = be16_to_cpu(dqp->q_core.d_bwarns);
- dst->d_rtb_hardlimit =
- XFS_FSB_TO_BB(mp, be64_to_cpu(dqp->q_core.d_rtb_hardlimit));
- dst->d_rtb_softlimit =
- XFS_FSB_TO_BB(mp, be64_to_cpu(dqp->q_core.d_rtb_softlimit));
- dst->d_rtbcount = XFS_FSB_TO_BB(mp, dqp->q_res_rtbcount);
- dst->d_rtbtimer = be32_to_cpu(dqp->q_core.d_rtbtimer);
- dst->d_rtbwarns = be16_to_cpu(dqp->q_core.d_rtbwarns);
+ dst->d_space = XFS_FSB_TO_B(mp, dqp->q_res_bcount);
+ dst->d_ino_count = dqp->q_res_icount;
+ dst->d_spc_timer = be32_to_cpu(dqp->q_core.d_btimer);
+ dst->d_ino_timer = be32_to_cpu(dqp->q_core.d_itimer);
+ dst->d_ino_warns = be16_to_cpu(dqp->q_core.d_iwarns);
+ dst->d_spc_warns = be16_to_cpu(dqp->q_core.d_bwarns);
+ dst->d_rt_spc_hardlimit =
+ XFS_FSB_TO_B(mp, be64_to_cpu(dqp->q_core.d_rtb_hardlimit));
+ dst->d_rt_spc_softlimit =
+ XFS_FSB_TO_B(mp, be64_to_cpu(dqp->q_core.d_rtb_softlimit));
+ dst->d_rt_space = XFS_FSB_TO_B(mp, dqp->q_res_rtbcount);
+ dst->d_rt_spc_timer = be32_to_cpu(dqp->q_core.d_rtbtimer);
+ dst->d_rt_spc_warns = be16_to_cpu(dqp->q_core.d_rtbwarns);
/*
* Internally, we don't reset all the timers when quota enforcement
@@ -878,23 +874,23 @@ xfs_qm_scall_getquota(
dqp->q_core.d_flags == XFS_DQ_GROUP) ||
(!XFS_IS_PQUOTA_ENFORCED(mp) &&
dqp->q_core.d_flags == XFS_DQ_PROJ)) {
- dst->d_btimer = 0;
- dst->d_itimer = 0;
- dst->d_rtbtimer = 0;
+ dst->d_spc_timer = 0;
+ dst->d_ino_timer = 0;
+ dst->d_rt_spc_timer = 0;
}
#ifdef DEBUG
- if (((XFS_IS_UQUOTA_ENFORCED(mp) && dst->d_flags == FS_USER_QUOTA) ||
- (XFS_IS_GQUOTA_ENFORCED(mp) && dst->d_flags == FS_GROUP_QUOTA) ||
- (XFS_IS_PQUOTA_ENFORCED(mp) && dst->d_flags == FS_PROJ_QUOTA)) &&
- dst->d_id != 0) {
- if ((dst->d_bcount > dst->d_blk_softlimit) &&
- (dst->d_blk_softlimit > 0)) {
- ASSERT(dst->d_btimer != 0);
+ if (((XFS_IS_UQUOTA_ENFORCED(mp) && type == XFS_DQ_USER) ||
+ (XFS_IS_GQUOTA_ENFORCED(mp) && type == XFS_DQ_GROUP) ||
+ (XFS_IS_PQUOTA_ENFORCED(mp) && type == XFS_DQ_PROJ)) &&
+ id != 0) {
+ if ((dst->d_space > dst->d_spc_softlimit) &&
+ (dst->d_spc_softlimit > 0)) {
+ ASSERT(dst->d_spc_timer != 0);
}
- if ((dst->d_icount > dst->d_ino_softlimit) &&
+ if ((dst->d_ino_count > dst->d_ino_softlimit) &&
(dst->d_ino_softlimit > 0)) {
- ASSERT(dst->d_itimer != 0);
+ ASSERT(dst->d_ino_timer != 0);
}
}
#endif
@@ -904,26 +900,6 @@ out_put:
}
STATIC uint
-xfs_qm_export_qtype_flags(
- uint flags)
-{
- /*
- * Can't be more than one, or none.
- */
- ASSERT((flags & (FS_PROJ_QUOTA | FS_USER_QUOTA)) !=
- (FS_PROJ_QUOTA | FS_USER_QUOTA));
- ASSERT((flags & (FS_PROJ_QUOTA | FS_GROUP_QUOTA)) !=
- (FS_PROJ_QUOTA | FS_GROUP_QUOTA));
- ASSERT((flags & (FS_USER_QUOTA | FS_GROUP_QUOTA)) !=
- (FS_USER_QUOTA | FS_GROUP_QUOTA));
- ASSERT((flags & (FS_PROJ_QUOTA|FS_USER_QUOTA|FS_GROUP_QUOTA)) != 0);
-
- return (flags & XFS_DQ_USER) ?
- FS_USER_QUOTA : (flags & XFS_DQ_PROJ) ?
- FS_PROJ_QUOTA : FS_GROUP_QUOTA;
-}
-
-STATIC uint
xfs_qm_export_flags(
uint flags)
{
diff --git a/fs/xfs/xfs_quotaops.c b/fs/xfs/xfs_quotaops.c
index a3836ac0f2f8..e46b1f6abd78 100644
--- a/fs/xfs/xfs_quotaops.c
+++ b/fs/xfs/xfs_quotaops.c
@@ -146,7 +146,7 @@ STATIC int
xfs_fs_get_dqblk(
struct super_block *sb,
struct kqid qid,
- struct fs_disk_quota *fdq)
+ struct qc_dqblk *qdq)
{
struct xfs_mount *mp = XFS_M(sb);
@@ -156,14 +156,14 @@ xfs_fs_get_dqblk(
return -ESRCH;
return xfs_qm_scall_getquota(mp, from_kqid(&init_user_ns, qid),
- xfs_quota_type(qid.type), fdq);
+ xfs_quota_type(qid.type), qdq);
}
STATIC int
xfs_fs_set_dqblk(
struct super_block *sb,
struct kqid qid,
- struct fs_disk_quota *fdq)
+ struct qc_dqblk *qdq)
{
struct xfs_mount *mp = XFS_M(sb);
@@ -175,7 +175,7 @@ xfs_fs_set_dqblk(
return -ESRCH;
return xfs_qm_scall_setqlim(mp, from_kqid(&init_user_ns, qid),
- xfs_quota_type(qid.type), fdq);
+ xfs_quota_type(qid.type), qdq);
}
const struct quotactl_ops xfs_quotactl_operations = {
diff --git a/include/linux/quota.h b/include/linux/quota.h
index 06a214a21778..903db093bbe9 100644
--- a/include/linux/quota.h
+++ b/include/linux/quota.h
@@ -316,6 +316,49 @@ struct dquot_operations {
struct path;
+/* Structure for communicating via ->get_dqblk() & ->set_dqblk() */
+struct qc_dqblk {
+ int d_fieldmask; /* mask of fields to change in ->set_dqblk() */
+ u64 d_spc_hardlimit; /* absolute limit on used space */
+ u64 d_spc_softlimit; /* preferred limit on used space */
+ u64 d_ino_hardlimit; /* maximum # allocated inodes */
+ u64 d_ino_softlimit; /* preferred inode limit */
+ u64 d_space; /* Space owned by the user */
+ u64 d_ino_count; /* # inodes owned by the user */
+ s64 d_ino_timer; /* zero if within inode limits */
+ /* if not, we refuse service */
+ s64 d_spc_timer; /* similar to above; for space */
+ int d_ino_warns; /* # warnings issued wrt num inodes */
+ int d_spc_warns; /* # warnings issued wrt used space */
+ u64 d_rt_spc_hardlimit; /* absolute limit on realtime space */
+ u64 d_rt_spc_softlimit; /* preferred limit on RT space */
+ u64 d_rt_space; /* realtime space owned */
+ s64 d_rt_spc_timer; /* similar to above; for RT space */
+ int d_rt_spc_warns; /* # warnings issued wrt RT space */
+};
+
+/* Field specifiers for ->set_dqblk() in struct qc_dqblk */
+#define QC_INO_SOFT (1<<0)
+#define QC_INO_HARD (1<<1)
+#define QC_SPC_SOFT (1<<2)
+#define QC_SPC_HARD (1<<3)
+#define QC_RT_SPC_SOFT (1<<4)
+#define QC_RT_SPC_HARD (1<<5)
+#define QC_LIMIT_MASK (QC_INO_SOFT | QC_INO_HARD | QC_SPC_SOFT | QC_SPC_HARD | \
+ QC_RT_SPC_SOFT | QC_RT_SPC_HARD)
+#define QC_SPC_TIMER (1<<6)
+#define QC_INO_TIMER (1<<7)
+#define QC_RT_SPC_TIMER (1<<8)
+#define QC_TIMER_MASK (QC_SPC_TIMER | QC_INO_TIMER | QC_RT_SPC_TIMER)
+#define QC_SPC_WARNS (1<<9)
+#define QC_INO_WARNS (1<<10)
+#define QC_RT_SPC_WARNS (1<<11)
+#define QC_WARNS_MASK (QC_SPC_WARNS | QC_INO_WARNS | QC_RT_SPC_WARNS)
+#define QC_SPACE (1<<12)
+#define QC_INO_COUNT (1<<13)
+#define QC_RT_SPACE (1<<14)
+#define QC_ACCT_MASK (QC_SPACE | QC_INO_COUNT | QC_RT_SPACE)
+
/* Operations handling requests from userspace */
struct quotactl_ops {
int (*quota_on)(struct super_block *, int, int, struct path *);
@@ -323,8 +366,8 @@ struct quotactl_ops {
int (*quota_sync)(struct super_block *, int);
int (*get_info)(struct super_block *, int, struct if_dqinfo *);
int (*set_info)(struct super_block *, int, struct if_dqinfo *);
- int (*get_dqblk)(struct super_block *, struct kqid, struct fs_disk_quota *);
- int (*set_dqblk)(struct super_block *, struct kqid, struct fs_disk_quota *);
+ int (*get_dqblk)(struct super_block *, struct kqid, struct qc_dqblk *);
+ int (*set_dqblk)(struct super_block *, struct kqid, struct qc_dqblk *);
int (*sysquota_on)(struct super_block *, unsigned int);
int (*sysquota_off)(struct super_block *, unsigned int);
int (*get_xstate)(struct super_block *, struct fs_quota_stat *);
diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h
index 6f5dc7e397a7..fd72408ae685 100644
--- a/include/linux/quotaops.h
+++ b/include/linux/quotaops.h
@@ -100,9 +100,9 @@ int dquot_quota_sync(struct super_block *sb, int type);
int dquot_get_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii);
int dquot_set_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii);
int dquot_get_dqblk(struct super_block *sb, struct kqid id,
- struct fs_disk_quota *di);
+ struct qc_dqblk *di);
int dquot_set_dqblk(struct super_block *sb, struct kqid id,
- struct fs_disk_quota *di);
+ struct qc_dqblk *di);
int __dquot_transfer(struct inode *inode, struct dquot **transfer_to);
int dquot_transfer(struct inode *inode, struct iattr *iattr);
--
1.8.1.4
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH 11/11] quota: Store maximum space limit in bytes
2014-11-11 21:04 [PATCH 0/11 RFC] quota: Unify VFS and XFS quota interfaces Jan Kara
` (9 preceding siblings ...)
2014-11-11 21:04 ` [PATCH 10/11] quota: Switch ->get_dqblk() and ->set_dqblk() to use bytes as space units Jan Kara
@ 2014-11-11 21:04 ` Jan Kara
10 siblings, 0 replies; 22+ messages in thread
From: Jan Kara @ 2014-11-11 21:04 UTC (permalink / raw)
To: linux-fsdevel; +Cc: linux-ext4, xfs, Jan Kara
Currently maximum space limit quota format supports is in blocks however
since we store space limits in bytes, this is somewhat confusing. So
store the maximum limit in bytes as well. Also rename the field to match
the new unit and related inode field to match the new naming scheme.
Signed-off-by: Jan Kara <jack@suse.cz>
---
fs/ocfs2/quota_local.c | 4 ++--
fs/quota/dquot.c | 18 ++++--------------
fs/quota/quota_v1.c | 4 ++--
fs/quota/quota_v2.c | 10 +++++-----
include/linux/quota.h | 4 ++--
5 files changed, 15 insertions(+), 25 deletions(-)
diff --git a/fs/ocfs2/quota_local.c b/fs/ocfs2/quota_local.c
index 10b653930ee2..465223b7592e 100644
--- a/fs/ocfs2/quota_local.c
+++ b/fs/ocfs2/quota_local.c
@@ -701,8 +701,8 @@ static int ocfs2_local_read_info(struct super_block *sb, int type)
/* We don't need the lock and we have to acquire quota file locks
* which will later depend on this lock */
mutex_unlock(&sb_dqopt(sb)->dqio_mutex);
- info->dqi_maxblimit = 0x7fffffffffffffffLL;
- info->dqi_maxilimit = 0x7fffffffffffffffLL;
+ info->dqi_max_spc_limit = 0x7fffffffffffffffLL;
+ info->dqi_max_ino_limit = 0x7fffffffffffffffLL;
oinfo = kmalloc(sizeof(struct ocfs2_mem_dqinfo), GFP_NOFS);
if (!oinfo) {
mlog(ML_ERROR, "failed to allocate memory for ocfs2 quota"
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c
index 887ead8c88e2..2e28d47b8798 100644
--- a/fs/quota/dquot.c
+++ b/fs/quota/dquot.c
@@ -2462,16 +2462,6 @@ out_err:
}
EXPORT_SYMBOL(dquot_sysquota_off);
-static inline qsize_t qbtos(qsize_t blocks)
-{
- return blocks << QIF_DQBLKSIZE_BITS;
-}
-
-static inline qsize_t stoqb(qsize_t space)
-{
- return (space + QIF_DQBLKSIZE - 1) >> QIF_DQBLKSIZE_BITS;
-}
-
/* Generic routine for getting common part of quota structure */
static void do_get_dqblk(struct dquot *dquot, struct qc_dqblk *di)
{
@@ -2521,13 +2511,13 @@ static int do_set_dqblk(struct dquot *dquot, struct qc_dqblk *di)
return -EINVAL;
if (((di->d_fieldmask & QC_SPC_SOFT) &&
- stoqb(di->d_spc_softlimit) > dqi->dqi_maxblimit) ||
+ di->d_spc_softlimit > dqi->dqi_max_spc_limit) ||
((di->d_fieldmask & QC_SPC_HARD) &&
- stoqb(di->d_spc_hardlimit) > dqi->dqi_maxblimit) ||
+ di->d_spc_hardlimit > dqi->dqi_max_spc_limit) ||
((di->d_fieldmask & QC_INO_SOFT) &&
- (di->d_ino_softlimit > dqi->dqi_maxilimit)) ||
+ (di->d_ino_softlimit > dqi->dqi_max_ino_limit)) ||
((di->d_fieldmask & QC_INO_HARD) &&
- (di->d_ino_hardlimit > dqi->dqi_maxilimit)))
+ (di->d_ino_hardlimit > dqi->dqi_max_ino_limit)))
return -ERANGE;
spin_lock(&dq_data_lock);
diff --git a/fs/quota/quota_v1.c b/fs/quota/quota_v1.c
index 469c6848b322..8fe79beced5c 100644
--- a/fs/quota/quota_v1.c
+++ b/fs/quota/quota_v1.c
@@ -169,8 +169,8 @@ static int v1_read_file_info(struct super_block *sb, int type)
}
ret = 0;
/* limits are stored as unsigned 32-bit data */
- dqopt->info[type].dqi_maxblimit = 0xffffffff;
- dqopt->info[type].dqi_maxilimit = 0xffffffff;
+ dqopt->info[type].dqi_max_spc_limit = 0xffffffffULL << QUOTABLOCK_BITS;
+ dqopt->info[type].dqi_max_ino_limit = 0xffffffff;
dqopt->info[type].dqi_igrace =
dqblk.dqb_itime ? dqblk.dqb_itime : MAX_IQ_TIME;
dqopt->info[type].dqi_bgrace =
diff --git a/fs/quota/quota_v2.c b/fs/quota/quota_v2.c
index 02751ec695c5..d1a8054bba9a 100644
--- a/fs/quota/quota_v2.c
+++ b/fs/quota/quota_v2.c
@@ -117,12 +117,12 @@ static int v2_read_file_info(struct super_block *sb, int type)
qinfo = info->dqi_priv;
if (version == 0) {
/* limits are stored as unsigned 32-bit data */
- info->dqi_maxblimit = 0xffffffff;
- info->dqi_maxilimit = 0xffffffff;
+ info->dqi_max_spc_limit = 0xffffffffULL << QUOTABLOCK_BITS;
+ info->dqi_max_ino_limit = 0xffffffff;
} else {
- /* used space is stored as unsigned 64-bit value */
- info->dqi_maxblimit = 0xffffffffffffffffULL; /* 2^64-1 */
- info->dqi_maxilimit = 0xffffffffffffffffULL;
+ /* used space is stored as unsigned 64-bit value in bytes */
+ info->dqi_max_spc_limit = 0xffffffffffffffffULL; /* 2^64-1 */
+ info->dqi_max_ino_limit = 0xffffffffffffffffULL;
}
info->dqi_bgrace = le32_to_cpu(dinfo.dqi_bgrace);
info->dqi_igrace = le32_to_cpu(dinfo.dqi_igrace);
diff --git a/include/linux/quota.h b/include/linux/quota.h
index 903db093bbe9..36ce30130bea 100644
--- a/include/linux/quota.h
+++ b/include/linux/quota.h
@@ -211,8 +211,8 @@ struct mem_dqinfo {
unsigned long dqi_flags;
unsigned int dqi_bgrace;
unsigned int dqi_igrace;
- qsize_t dqi_maxblimit;
- qsize_t dqi_maxilimit;
+ qsize_t dqi_max_spc_limit;
+ qsize_t dqi_max_ino_limit;
void *dqi_priv;
};
--
1.8.1.4
^ permalink raw reply related [flat|nested] 22+ messages in thread
* Re: [PATCH 02/11] xfs: Remove unused variable in xfs_qm_scall_quotaon()
2014-11-11 21:04 ` [PATCH 02/11] xfs: Remove unused variable in xfs_qm_scall_quotaon() Jan Kara
@ 2014-11-11 23:23 ` Dave Chinner
0 siblings, 0 replies; 22+ messages in thread
From: Dave Chinner @ 2014-11-11 23:23 UTC (permalink / raw)
To: Jan Kara; +Cc: linux-fsdevel, linux-ext4, xfs
On Tue, Nov 11, 2014 at 10:04:16PM +0100, Jan Kara wrote:
> sbflags variable in xfs_qm_scall_quotaon() was practically unused (we
> only set it to constant at one place and used it elsewhere). Remove it.
>
> Signed-off-by: Jan Kara <jack@suse.cz>
I have patches in my queue that change the superblock logging
quite a bit and remove the functionality you're changing in this
patch, so eventually you'll be able to drop this patch.
Cheers,
Dave.
--
Dave Chinner
david@fromorbit.com
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 03/11] xfs: Remove some useless flags tests
2014-11-11 21:04 ` [PATCH 03/11] xfs: Remove some useless flags tests Jan Kara
@ 2014-11-11 23:26 ` Dave Chinner
0 siblings, 0 replies; 22+ messages in thread
From: Dave Chinner @ 2014-11-11 23:26 UTC (permalink / raw)
To: Jan Kara; +Cc: linux-fsdevel, linux-ext4, xfs
On Tue, Nov 11, 2014 at 10:04:17PM +0100, Jan Kara wrote:
> 'flags' have XFS_ALL_QUOTA_ACCT cleared immediately on function entry.
> There's no point in checking these bits later in the function. Also
> because we check something is going to change, we know some enforcement
> bits are being added and thus there's no point in testing that later.
>
> Signed-off-by: Jan Kara <jack@suse.cz>
Looks sane. I'll pick this up straight away.
Cheers,
Dave.
--
Dave Chinner
david@fromorbit.com
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 01/11] xfs: Remove useless test
2014-11-11 21:04 ` [PATCH 01/11] xfs: Remove useless test Jan Kara
@ 2014-11-11 23:27 ` Dave Chinner
0 siblings, 0 replies; 22+ messages in thread
From: Dave Chinner @ 2014-11-11 23:27 UTC (permalink / raw)
To: Jan Kara; +Cc: linux-fsdevel, linux-ext4, xfs
On Tue, Nov 11, 2014 at 10:04:15PM +0100, Jan Kara wrote:
> Q_XQUOTARM is never passed to xfs_fs_set_xstate() so remove the test.
>
> Signed-off-by: Jan Kara <jack@suse.cz>
Looks fine - the higher layers ahave changed since this was added.
I'll pick this one up straight away.
-Dave.
--
Dave Chinner
david@fromorbit.com
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 04/11] quota: Split ->set_xstate callback into two
2014-11-11 21:04 ` [PATCH 04/11] quota: Split ->set_xstate callback into two Jan Kara
@ 2014-11-13 17:34 ` Christoph Hellwig
2014-11-18 16:05 ` Jan Kara
0 siblings, 1 reply; 22+ messages in thread
From: Christoph Hellwig @ 2014-11-13 17:34 UTC (permalink / raw)
To: Jan Kara; +Cc: linux-fsdevel, linux-ext4, xfs
On Tue, Nov 11, 2014 at 10:04:18PM +0100, Jan Kara wrote:
> Split ->set_xstate callback into two callbacks - one for turning quotas
> on (->sysquota_on) and one for turning quotas off (->sysquota_off). That
> way we don't have to pass quotactl command into the callback which seems
> cleaner.
Yes, I much prefer these to be split. But the names seem a little odd,
why not enable_quota/disable_quota?
> +static unsigned int generic_to_xfs_flags(unsigned int uflags)
xfs_quota_flags() ?
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 07/11] ext4: Use generic helpers for quotaon and quotaoff
2014-11-11 21:04 ` [PATCH 07/11] ext4: Use generic helpers for quotaon and quotaoff Jan Kara
@ 2014-11-13 17:36 ` Christoph Hellwig
2014-11-18 16:07 ` Jan Kara
0 siblings, 1 reply; 22+ messages in thread
From: Christoph Hellwig @ 2014-11-13 17:36 UTC (permalink / raw)
To: Jan Kara; +Cc: linux-fsdevel, linux-ext4, xfs
> static const struct quotactl_ops ext4_qctl_sysfile_operations = {
> - .quota_on_meta = ext4_quota_on_sysfile,
> - .quota_off = ext4_quota_off_sysfile,
> + .sysquota_on = dquot_sysquota_on,
> + .sysquota_off = dquot_sysquota_off,
> .quota_sync = dquot_quota_sync,
> .get_info = dquot_get_dqinfo,
> .set_info = dquot_set_dqinfo,
This vector now only has generic dquot_ methods. Maybe move the
vector to fs/quota/dquot.c and allow multiple filesystems to share it?
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 04/11] quota: Split ->set_xstate callback into two
2014-11-13 17:34 ` Christoph Hellwig
@ 2014-11-18 16:05 ` Jan Kara
0 siblings, 0 replies; 22+ messages in thread
From: Jan Kara @ 2014-11-18 16:05 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: linux-fsdevel, linux-ext4, Jan Kara, xfs
On Thu 13-11-14 09:34:16, Christoph Hellwig wrote:
> On Tue, Nov 11, 2014 at 10:04:18PM +0100, Jan Kara wrote:
> > Split ->set_xstate callback into two callbacks - one for turning quotas
> > on (->sysquota_on) and one for turning quotas off (->sysquota_off). That
> > way we don't have to pass quotactl command into the callback which seems
> > cleaner.
>
> Yes, I much prefer these to be split. But the names seem a little odd,
> why not enable_quota/disable_quota?
I wanted to clearly separate this from quota_on() / quota_off() callbacks
which are for userspace visible quota files. However enable_quota /
disable_quota sound fine as well.
> > +static unsigned int generic_to_xfs_flags(unsigned int uflags)
>
> xfs_quota_flags() ?
OK.
Honza
--
Jan Kara <jack@suse.cz>
SUSE Labs, CR
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 07/11] ext4: Use generic helpers for quotaon and quotaoff
2014-11-13 17:36 ` Christoph Hellwig
@ 2014-11-18 16:07 ` Jan Kara
0 siblings, 0 replies; 22+ messages in thread
From: Jan Kara @ 2014-11-18 16:07 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: Jan Kara, linux-fsdevel, linux-ext4, xfs
On Thu 13-11-14 09:36:00, Christoph Hellwig wrote:
> > static const struct quotactl_ops ext4_qctl_sysfile_operations = {
> > - .quota_on_meta = ext4_quota_on_sysfile,
> > - .quota_off = ext4_quota_off_sysfile,
> > + .sysquota_on = dquot_sysquota_on,
> > + .sysquota_off = dquot_sysquota_off,
> > .quota_sync = dquot_quota_sync,
> > .get_info = dquot_get_dqinfo,
> > .set_info = dquot_set_dqinfo,
>
> This vector now only has generic dquot_ methods. Maybe move the
> vector to fs/quota/dquot.c and allow multiple filesystems to share it?
Right. ocfs2 actually has the same vector now. I'll unify it.
Honza
--
Jan Kara <jack@suse.cz>
SUSE Labs, CR
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 10/11] quota: Switch ->get_dqblk() and ->set_dqblk() to use bytes as space units
2014-11-11 21:04 ` [PATCH 10/11] quota: Switch ->get_dqblk() and ->set_dqblk() to use bytes as space units Jan Kara
@ 2014-11-18 22:29 ` Dave Chinner
2014-12-12 9:52 ` Jan Kara
0 siblings, 1 reply; 22+ messages in thread
From: Dave Chinner @ 2014-11-18 22:29 UTC (permalink / raw)
To: Jan Kara; +Cc: linux-fsdevel, linux-ext4, xfs
On Tue, Nov 11, 2014 at 10:04:24PM +0100, Jan Kara wrote:
> Currently ->get_dqblk() and ->set_dqblk() use struct fs_disk_quota which
> tracks space limits and usage in 512-byte blocks. However VFS quotas
> track usage in bytes (as some filesystems require that) and we need to
> somehow pass this information. Upto now it wasn't a problem because we
> didn't do any unit conversion (thus VFS quota routines happily stuck
> number of bytes into d_bcount field of struct fd_disk_quota). Only if
> you tried to use Q_XGETQUOTA or Q_XSETQLIM for VFS quotas (or Q_GETQUOTA
> / Q_SETQUOTA for XFS quotas), you got bogus results but noone really
> tried that. But when we want interfaces compatible we need to fix this.
>
> So we bite the bullet and define another quota structure used for
> passing information from/to ->get_dqblk()/->set_dqblk. It's somewhat
> sad we have to have more conversion routines in fs/quota/quota.c but
> it seems cleaner than overloading e.g. units of d_bcount to bytes.
I don't really like the idea of having to copy the dquot information
an extra time. We now:
- copy from internal dquot to the new qc_dqblk
- copy from the new qc_dqblk to if_dqblk/xfs_dqblk
- copy if_dqblk/xfs_dqblk to the user buffer.
That's now three copies, and when we are having to deal with quota
reports containing hundreds of thousands of dquots that's going to
hrut performance.
We could probably get away with just one copy by passing a
filldir()-like context down into the filesystems to format their
internal dquot information directly into the user buffer in the
appropriate format. That way fs/quota/quota.c doesn't need
conversion routines, filesystems can optimise the formating to
minimise copying, and we can still provide generic routines for
filesystems using the generic quota infrastructure....
[...]
> @@ -277,10 +287,73 @@ static int quota_getxstatev(struct super_block *sb, void __user *addr)
> return ret;
> }
>
> +/* XFS blocks to space conversion */
> +static u64 xfs_btos(u64 blocks)
> +{
> + return blocks << 9;
> +}
> +
> +/* Space to XFS blocks conversion */
> +static u64 xfs_stob(u64 space)
> +{
> + return (space + 511) >> 9;
> +}
Which is just redefining BBTOB() [Basic Blocks to Bytes] and BTOBB()
with magic numbers and no explanation of what a "block" actually is.
We already export those macros to userspace, and they are used by
xfs_quota to convert the block counts to bytes....
Cheers,
Dave.
--
Dave Chinner
david@fromorbit.com
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 10/11] quota: Switch ->get_dqblk() and ->set_dqblk() to use bytes as space units
2014-11-18 22:29 ` Dave Chinner
@ 2014-12-12 9:52 ` Jan Kara
2014-12-12 22:51 ` Jan Kara
0 siblings, 1 reply; 22+ messages in thread
From: Jan Kara @ 2014-12-12 9:52 UTC (permalink / raw)
To: Dave Chinner; +Cc: Jan Kara, linux-fsdevel, linux-ext4, xfs
On Wed 19-11-14 09:29:52, Dave Chinner wrote:
> On Tue, Nov 11, 2014 at 10:04:24PM +0100, Jan Kara wrote:
> > Currently ->get_dqblk() and ->set_dqblk() use struct fs_disk_quota which
> > tracks space limits and usage in 512-byte blocks. However VFS quotas
> > track usage in bytes (as some filesystems require that) and we need to
> > somehow pass this information. Upto now it wasn't a problem because we
> > didn't do any unit conversion (thus VFS quota routines happily stuck
> > number of bytes into d_bcount field of struct fd_disk_quota). Only if
> > you tried to use Q_XGETQUOTA or Q_XSETQLIM for VFS quotas (or Q_GETQUOTA
> > / Q_SETQUOTA for XFS quotas), you got bogus results but noone really
> > tried that. But when we want interfaces compatible we need to fix this.
> >
> > So we bite the bullet and define another quota structure used for
> > passing information from/to ->get_dqblk()/->set_dqblk. It's somewhat
> > sad we have to have more conversion routines in fs/quota/quota.c but
> > it seems cleaner than overloading e.g. units of d_bcount to bytes.
>
> I don't really like the idea of having to copy the dquot information
> an extra time. We now:
>
> - copy from internal dquot to the new qc_dqblk
> - copy from the new qc_dqblk to if_dqblk/xfs_dqblk
> - copy if_dqblk/xfs_dqblk to the user buffer.
>
> That's now three copies, and when we are having to deal with quota
> reports containing hundreds of thousands of dquots that's going to
> hrut performance.
>
> We could probably get away with just one copy by passing a
> filldir()-like context down into the filesystems to format their
> internal dquot information directly into the user buffer in the
> appropriate format. That way fs/quota/quota.c doesn't need
> conversion routines, filesystems can optimise the formating to
> minimise copying, and we can still provide generic routines for
> filesystems using the generic quota infrastructure....
I was thinking about how this would look like. I don't have a problem to
create a filldir() like callback that will be used for getting quota
structures. However I don't see how we could reasonably get away with just
one copy in general - that would mean that the interface functions in
fs/quota.c (e.g. quota_getquota()) would have to determine whether XFS of
VFS quota structures are used in the backing filesystem to provide proper
callback and that's IMO too ugly to live.
We could definitely reduce the number of copies to two by changing e.g.
copy_to_xfs_dqblk() to directly use __put_user() instead of first
formatting proper structure on stack and then using copy_to_user(). However
I'm not sure whether this will be any real performance win and using
copy_to_user() seems easier to me...
Anyway I'll probably try changing number of copies to two and see whether
there's any measurable impact.
> > @@ -277,10 +287,73 @@ static int quota_getxstatev(struct super_block *sb, void __user *addr)
> > return ret;
> > }
> >
> > +/* XFS blocks to space conversion */
> > +static u64 xfs_btos(u64 blocks)
> > +{
> > + return blocks << 9;
> > +}
> > +
> > +/* Space to XFS blocks conversion */
> > +static u64 xfs_stob(u64 space)
> > +{
> > + return (space + 511) >> 9;
> > +}
>
> Which is just redefining BBTOB() [Basic Blocks to Bytes] and BTOBB()
> with magic numbers and no explanation of what a "block" actually is.
> We already export those macros to userspace, and they are used by
> xfs_quota to convert the block counts to bytes....
Sure, I will use XFS macros.
Honza
--
Jan Kara <jack@suse.cz>
SUSE Labs, CR
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH 10/11] quota: Switch ->get_dqblk() and ->set_dqblk() to use bytes as space units
2014-12-12 9:52 ` Jan Kara
@ 2014-12-12 22:51 ` Jan Kara
0 siblings, 0 replies; 22+ messages in thread
From: Jan Kara @ 2014-12-12 22:51 UTC (permalink / raw)
To: Dave Chinner; +Cc: Jan Kara, linux-fsdevel, linux-ext4, xfs
On Fri 12-12-14 10:52:30, Jan Kara wrote:
> On Wed 19-11-14 09:29:52, Dave Chinner wrote:
> > On Tue, Nov 11, 2014 at 10:04:24PM +0100, Jan Kara wrote:
> > > Currently ->get_dqblk() and ->set_dqblk() use struct fs_disk_quota which
> > > tracks space limits and usage in 512-byte blocks. However VFS quotas
> > > track usage in bytes (as some filesystems require that) and we need to
> > > somehow pass this information. Upto now it wasn't a problem because we
> > > didn't do any unit conversion (thus VFS quota routines happily stuck
> > > number of bytes into d_bcount field of struct fd_disk_quota). Only if
> > > you tried to use Q_XGETQUOTA or Q_XSETQLIM for VFS quotas (or Q_GETQUOTA
> > > / Q_SETQUOTA for XFS quotas), you got bogus results but noone really
> > > tried that. But when we want interfaces compatible we need to fix this.
> > >
> > > So we bite the bullet and define another quota structure used for
> > > passing information from/to ->get_dqblk()/->set_dqblk. It's somewhat
> > > sad we have to have more conversion routines in fs/quota/quota.c but
> > > it seems cleaner than overloading e.g. units of d_bcount to bytes.
> >
> > I don't really like the idea of having to copy the dquot information
> > an extra time. We now:
> >
> > - copy from internal dquot to the new qc_dqblk
> > - copy from the new qc_dqblk to if_dqblk/xfs_dqblk
> > - copy if_dqblk/xfs_dqblk to the user buffer.
> >
> > That's now three copies, and when we are having to deal with quota
> > reports containing hundreds of thousands of dquots that's going to
> > hrut performance.
> >
> > We could probably get away with just one copy by passing a
> > filldir()-like context down into the filesystems to format their
> > internal dquot information directly into the user buffer in the
> > appropriate format. That way fs/quota/quota.c doesn't need
> > conversion routines, filesystems can optimise the formating to
> > minimise copying, and we can still provide generic routines for
> > filesystems using the generic quota infrastructure....
> I was thinking about how this would look like. I don't have a problem to
> create a filldir() like callback that will be used for getting quota
> structures. However I don't see how we could reasonably get away with just
> one copy in general - that would mean that the interface functions in
> fs/quota.c (e.g. quota_getquota()) would have to determine whether XFS of
> VFS quota structures are used in the backing filesystem to provide proper
> callback and that's IMO too ugly to live.
>
> We could definitely reduce the number of copies to two by changing e.g.
> copy_to_xfs_dqblk() to directly use __put_user() instead of first
> formatting proper structure on stack and then using copy_to_user(). However
> I'm not sure whether this will be any real performance win and using
> copy_to_user() seems easier to me...
>
> Anyway I'll probably try changing number of copies to two and see whether
> there's any measurable impact.
So when I change the number of copies to two by using __put_user, I get
about about 2.3% reduction in time for getting quota information for vfs
quotas (fully cached) and about 1.7% reduction in time for getting quota
information for xfs quotas.
For VFS quotas numbers are:
Average of 4 runs with 3 copies is 2.212286s (for 100000 getquota calls).
Average of 4 runs with 2 copies is 2.160500s (for 100000 getquota calls).
For XFS quotas numbers are:
Average of 4 runs with 3 copies is 1.584250s (for 100000 getquota calls).
Average of 4 runs with 2 copies is 1.557250s (for 100000 getquota calls).
So overall it seems to me that avoiding another copy is not worth the
bother...
Honza
--
Jan Kara <jack@suse.cz>
SUSE Labs, CR
^ permalink raw reply [flat|nested] 22+ messages in thread
end of thread, other threads:[~2014-12-12 22:51 UTC | newest]
Thread overview: 22+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-11-11 21:04 [PATCH 0/11 RFC] quota: Unify VFS and XFS quota interfaces Jan Kara
2014-11-11 21:04 ` [PATCH 01/11] xfs: Remove useless test Jan Kara
2014-11-11 23:27 ` Dave Chinner
2014-11-11 21:04 ` [PATCH 02/11] xfs: Remove unused variable in xfs_qm_scall_quotaon() Jan Kara
2014-11-11 23:23 ` Dave Chinner
2014-11-11 21:04 ` [PATCH 03/11] xfs: Remove some useless flags tests Jan Kara
2014-11-11 23:26 ` Dave Chinner
2014-11-11 21:04 ` [PATCH 04/11] quota: Split ->set_xstate callback into two Jan Kara
2014-11-13 17:34 ` Christoph Hellwig
2014-11-18 16:05 ` Jan Kara
2014-11-11 21:04 ` [PATCH 05/11] quota: Wire up ->sysquota_{on,off} callbacks into Q_QUOTA{ON,OFF} Jan Kara
2014-11-11 21:04 ` [PATCH 06/11] quota: Add ->sysquota_{on,off} callbacks for VFS quotas Jan Kara
2014-11-11 21:04 ` [PATCH 07/11] ext4: Use generic helpers for quotaon and quotaoff Jan Kara
2014-11-13 17:36 ` Christoph Hellwig
2014-11-18 16:07 ` Jan Kara
2014-11-11 21:04 ` [PATCH 08/11] ocfs2: " Jan Kara
2014-11-11 21:04 ` [PATCH 09/11] quota: Remove quota_on_meta callback Jan Kara
2014-11-11 21:04 ` [PATCH 10/11] quota: Switch ->get_dqblk() and ->set_dqblk() to use bytes as space units Jan Kara
2014-11-18 22:29 ` Dave Chinner
2014-12-12 9:52 ` Jan Kara
2014-12-12 22:51 ` Jan Kara
2014-11-11 21:04 ` [PATCH 11/11] quota: Store maximum space limit in bytes Jan Kara
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).