aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2014-10-09 10:03:13 -0400
committerJan Kara <jack@suse.cz>2015-01-28 03:01:40 -0500
commit14bf61ffe6ac54afcd1e888a4407fe16054483db (patch)
treeb5af94fc8771e82735064a82a7df4ec4de66744e /include/linux
parentb07ef35244424cbeda9844198607c7077099c82c (diff)
quota: Switch ->get_dqblk() and ->set_dqblk() to use bytes as space units
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. Hardly anyone tried this but reportedly some Samba users hit the problem in practice. So when we want interfaces compatible we need to fix this. 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 and another copying of quota structure slows down getting of quota information by about 2% but it seems cleaner than overloading e.g. units of d_bcount to bytes. CC: stable@vger.kernel.org Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'include/linux')
-rw-r--r--include/linux/quota.h47
-rw-r--r--include/linux/quotaops.h4
2 files changed, 47 insertions, 4 deletions
diff --git a/include/linux/quota.h b/include/linux/quota.h
index 50978b781a19..097d7eb2441e 100644
--- a/include/linux/quota.h
+++ b/include/linux/quota.h
@@ -321,6 +321,49 @@ struct dquot_operations {
321 321
322struct path; 322struct path;
323 323
324/* Structure for communicating via ->get_dqblk() & ->set_dqblk() */
325struct qc_dqblk {
326 int d_fieldmask; /* mask of fields to change in ->set_dqblk() */
327 u64 d_spc_hardlimit; /* absolute limit on used space */
328 u64 d_spc_softlimit; /* preferred limit on used space */
329 u64 d_ino_hardlimit; /* maximum # allocated inodes */
330 u64 d_ino_softlimit; /* preferred inode limit */
331 u64 d_space; /* Space owned by the user */
332 u64 d_ino_count; /* # inodes owned by the user */
333 s64 d_ino_timer; /* zero if within inode limits */
334 /* if not, we refuse service */
335 s64 d_spc_timer; /* similar to above; for space */
336 int d_ino_warns; /* # warnings issued wrt num inodes */
337 int d_spc_warns; /* # warnings issued wrt used space */
338 u64 d_rt_spc_hardlimit; /* absolute limit on realtime space */
339 u64 d_rt_spc_softlimit; /* preferred limit on RT space */
340 u64 d_rt_space; /* realtime space owned */
341 s64 d_rt_spc_timer; /* similar to above; for RT space */
342 int d_rt_spc_warns; /* # warnings issued wrt RT space */
343};
344
345/* Field specifiers for ->set_dqblk() in struct qc_dqblk */
346#define QC_INO_SOFT (1<<0)
347#define QC_INO_HARD (1<<1)
348#define QC_SPC_SOFT (1<<2)
349#define QC_SPC_HARD (1<<3)
350#define QC_RT_SPC_SOFT (1<<4)
351#define QC_RT_SPC_HARD (1<<5)
352#define QC_LIMIT_MASK (QC_INO_SOFT | QC_INO_HARD | QC_SPC_SOFT | QC_SPC_HARD | \
353 QC_RT_SPC_SOFT | QC_RT_SPC_HARD)
354#define QC_SPC_TIMER (1<<6)
355#define QC_INO_TIMER (1<<7)
356#define QC_RT_SPC_TIMER (1<<8)
357#define QC_TIMER_MASK (QC_SPC_TIMER | QC_INO_TIMER | QC_RT_SPC_TIMER)
358#define QC_SPC_WARNS (1<<9)
359#define QC_INO_WARNS (1<<10)
360#define QC_RT_SPC_WARNS (1<<11)
361#define QC_WARNS_MASK (QC_SPC_WARNS | QC_INO_WARNS | QC_RT_SPC_WARNS)
362#define QC_SPACE (1<<12)
363#define QC_INO_COUNT (1<<13)
364#define QC_RT_SPACE (1<<14)
365#define QC_ACCT_MASK (QC_SPACE | QC_INO_COUNT | QC_RT_SPACE)
366
324/* Operations handling requests from userspace */ 367/* Operations handling requests from userspace */
325struct quotactl_ops { 368struct quotactl_ops {
326 int (*quota_on)(struct super_block *, int, int, struct path *); 369 int (*quota_on)(struct super_block *, int, int, struct path *);
@@ -329,8 +372,8 @@ struct quotactl_ops {
329 int (*quota_sync)(struct super_block *, int); 372 int (*quota_sync)(struct super_block *, int);
330 int (*get_info)(struct super_block *, int, struct if_dqinfo *); 373 int (*get_info)(struct super_block *, int, struct if_dqinfo *);
331 int (*set_info)(struct super_block *, int, struct if_dqinfo *); 374 int (*set_info)(struct super_block *, int, struct if_dqinfo *);
332 int (*get_dqblk)(struct super_block *, struct kqid, struct fs_disk_quota *); 375 int (*get_dqblk)(struct super_block *, struct kqid, struct qc_dqblk *);
333 int (*set_dqblk)(struct super_block *, struct kqid, struct fs_disk_quota *); 376 int (*set_dqblk)(struct super_block *, struct kqid, struct qc_dqblk *);
334 int (*get_xstate)(struct super_block *, struct fs_quota_stat *); 377 int (*get_xstate)(struct super_block *, struct fs_quota_stat *);
335 int (*set_xstate)(struct super_block *, unsigned int, int); 378 int (*set_xstate)(struct super_block *, unsigned int, int);
336 int (*get_xstatev)(struct super_block *, struct fs_quota_statv *); 379 int (*get_xstatev)(struct super_block *, struct fs_quota_statv *);
diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h
index f23538a6e411..29e3455f7d41 100644
--- a/include/linux/quotaops.h
+++ b/include/linux/quotaops.h
@@ -98,9 +98,9 @@ int dquot_quota_sync(struct super_block *sb, int type);
98int dquot_get_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii); 98int dquot_get_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii);
99int dquot_set_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii); 99int dquot_set_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii);
100int dquot_get_dqblk(struct super_block *sb, struct kqid id, 100int dquot_get_dqblk(struct super_block *sb, struct kqid id,
101 struct fs_disk_quota *di); 101 struct qc_dqblk *di);
102int dquot_set_dqblk(struct super_block *sb, struct kqid id, 102int dquot_set_dqblk(struct super_block *sb, struct kqid id,
103 struct fs_disk_quota *di); 103 struct qc_dqblk *di);
104 104
105int __dquot_transfer(struct inode *inode, struct dquot **transfer_to); 105int __dquot_transfer(struct inode *inode, struct dquot **transfer_to);
106int dquot_transfer(struct inode *inode, struct iattr *iattr); 106int dquot_transfer(struct inode *inode, struct iattr *iattr);