aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChandra Seetharaman <sekharan@us.ibm.com>2013-08-06 18:27:07 -0400
committerBen Myers <bpm@sgi.com>2013-08-20 17:53:58 -0400
commitaf30cb446dd5f4ad5b93d7d4188c49a864c0d643 (patch)
tree44e7d582ecffbcb91310a271ba80b218efdce9eb
parentc2bfbc9b485a750b6af4a97ff3ad22b576e74d20 (diff)
quota: Add a new quotactl command Q_XGETQSTATV
XFS now supports three types of quotas (user, group and project). Current version of Q_XGETSTAT has support for only two types of quotas. In order to support three types of quotas, the interface, specifically struct fs_quota_stat, need to be expanded. Current version of fs_quota_stat does not allow expansion without breaking backward compatibility. So, a quotactl command and new fs_quota_stat structure need to be added. This patch adds a new command Q_XGETQSTATV to quotactl() which takes a new data structure fs_quota_statv. This new data structure provides support for future expansion and backward compatibility. Callers of the new quotactl command have to set the version of the data structure being passed, and kernel will fill as much data as requested. If the kernel does not support the user-space provided version, EINVAL will be returned. User-space can reduce the version number and call the same quotactl again. Signed-off-by: Chandra Seetharaman <sekharan@us.ibm.com> Reviewed-by: Jan Kara <jack@suse.cz> Reviewed-by: Rich Johnston <rjohnston@sgi.com> Signed-off-by: Ben Myers <bpm@sgi.com> [v2: Applied rjohnston's suggestions as per Chandra's request. -bpm]
-rw-r--r--fs/quota/quota.c29
-rw-r--r--include/linux/quota.h1
-rw-r--r--include/uapi/linux/dqblk_xfs.h47
3 files changed, 77 insertions, 0 deletions
diff --git a/fs/quota/quota.c b/fs/quota/quota.c
index c7314f1771f5..dea86e8967ee 100644
--- a/fs/quota/quota.c
+++ b/fs/quota/quota.c
@@ -27,6 +27,7 @@ static int check_quotactl_permission(struct super_block *sb, int type, int cmd,
27 case Q_SYNC: 27 case Q_SYNC:
28 case Q_GETINFO: 28 case Q_GETINFO:
29 case Q_XGETQSTAT: 29 case Q_XGETQSTAT:
30 case Q_XGETQSTATV:
30 case Q_XQUOTASYNC: 31 case Q_XQUOTASYNC:
31 break; 32 break;
32 /* allow to query information for dquots we "own" */ 33 /* allow to query information for dquots we "own" */
@@ -217,6 +218,31 @@ static int quota_getxstate(struct super_block *sb, void __user *addr)
217 return ret; 218 return ret;
218} 219}
219 220
221static int quota_getxstatev(struct super_block *sb, void __user *addr)
222{
223 struct fs_quota_statv fqs;
224 int ret;
225
226 if (!sb->s_qcop->get_xstatev)
227 return -ENOSYS;
228
229 memset(&fqs, 0, sizeof(fqs));
230 if (copy_from_user(&fqs, addr, 1)) /* Just read qs_version */
231 return -EFAULT;
232
233 /* If this kernel doesn't support user specified version, fail */
234 switch (fqs.qs_version) {
235 case FS_QSTATV_VERSION1:
236 break;
237 default:
238 return -EINVAL;
239 }
240 ret = sb->s_qcop->get_xstatev(sb, &fqs);
241 if (!ret && copy_to_user(addr, &fqs, sizeof(fqs)))
242 return -EFAULT;
243 return ret;
244}
245
220static int quota_setxquota(struct super_block *sb, int type, qid_t id, 246static int quota_setxquota(struct super_block *sb, int type, qid_t id,
221 void __user *addr) 247 void __user *addr)
222{ 248{
@@ -293,6 +319,8 @@ static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id,
293 return quota_setxstate(sb, cmd, addr); 319 return quota_setxstate(sb, cmd, addr);
294 case Q_XGETQSTAT: 320 case Q_XGETQSTAT:
295 return quota_getxstate(sb, addr); 321 return quota_getxstate(sb, addr);
322 case Q_XGETQSTATV:
323 return quota_getxstatev(sb, addr);
296 case Q_XSETQLIM: 324 case Q_XSETQLIM:
297 return quota_setxquota(sb, type, id, addr); 325 return quota_setxquota(sb, type, id, addr);
298 case Q_XGETQUOTA: 326 case Q_XGETQUOTA:
@@ -317,6 +345,7 @@ static int quotactl_cmd_write(int cmd)
317 case Q_GETINFO: 345 case Q_GETINFO:
318 case Q_SYNC: 346 case Q_SYNC:
319 case Q_XGETQSTAT: 347 case Q_XGETQSTAT:
348 case Q_XGETQSTATV:
320 case Q_XGETQUOTA: 349 case Q_XGETQUOTA:
321 case Q_XQUOTASYNC: 350 case Q_XQUOTASYNC:
322 return 0; 351 return 0;
diff --git a/include/linux/quota.h b/include/linux/quota.h
index d13371134c59..cc7494a35429 100644
--- a/include/linux/quota.h
+++ b/include/linux/quota.h
@@ -328,6 +328,7 @@ struct quotactl_ops {
328 int (*set_dqblk)(struct super_block *, struct kqid, struct fs_disk_quota *); 328 int (*set_dqblk)(struct super_block *, struct kqid, struct fs_disk_quota *);
329 int (*get_xstate)(struct super_block *, struct fs_quota_stat *); 329 int (*get_xstate)(struct super_block *, struct fs_quota_stat *);
330 int (*set_xstate)(struct super_block *, unsigned int, int); 330 int (*set_xstate)(struct super_block *, unsigned int, int);
331 int (*get_xstatev)(struct super_block *, struct fs_quota_statv *);
331}; 332};
332 333
333struct quota_format_type { 334struct quota_format_type {
diff --git a/include/uapi/linux/dqblk_xfs.h b/include/uapi/linux/dqblk_xfs.h
index 86552807aed9..dcd75cc26196 100644
--- a/include/uapi/linux/dqblk_xfs.h
+++ b/include/uapi/linux/dqblk_xfs.h
@@ -38,6 +38,7 @@
38#define Q_XGETQSTAT XQM_CMD(5) /* get quota subsystem status */ 38#define Q_XGETQSTAT XQM_CMD(5) /* get quota subsystem status */
39#define Q_XQUOTARM XQM_CMD(6) /* free disk space used by dquots */ 39#define Q_XQUOTARM XQM_CMD(6) /* free disk space used by dquots */
40#define Q_XQUOTASYNC XQM_CMD(7) /* delalloc flush, updates dquots */ 40#define Q_XQUOTASYNC XQM_CMD(7) /* delalloc flush, updates dquots */
41#define Q_XGETQSTATV XQM_CMD(8) /* newer version of get quota */
41 42
42/* 43/*
43 * fs_disk_quota structure: 44 * fs_disk_quota structure:
@@ -163,4 +164,50 @@ typedef struct fs_quota_stat {
163 __u16 qs_iwarnlimit; /* limit for num warnings */ 164 __u16 qs_iwarnlimit; /* limit for num warnings */
164} fs_quota_stat_t; 165} fs_quota_stat_t;
165 166
167/*
168 * fs_quota_statv is used by Q_XGETQSTATV for a given file system. It provides
169 * a centralized way to get meta information about the quota subsystem. eg.
170 * space taken up for user, group, and project quotas, number of dquots
171 * currently incore.
172 *
173 * This version has proper versioning support with appropriate padding for
174 * future expansions, and ability to expand for future without creating any
175 * backward compatibility issues.
176 *
177 * Q_XGETQSTATV uses the passed in value of the requested version via
178 * fs_quota_statv.qs_version to determine the return data layout of
179 * fs_quota_statv. The kernel will fill the data fields relevant to that
180 * version.
181 *
182 * If kernel does not support user space caller specified version, EINVAL will
183 * be returned. User space caller can then reduce the version number and retry
184 * the same command.
185 */
186#define FS_QSTATV_VERSION1 1 /* fs_quota_statv.qs_version */
187/*
188 * Some basic information about 'quota files' for Q_XGETQSTATV command
189 */
190struct fs_qfilestatv {
191 __u64 qfs_ino; /* inode number */
192 __u64 qfs_nblks; /* number of BBs 512-byte-blks */
193 __u32 qfs_nextents; /* number of extents */
194 __u32 qfs_pad; /* pad for 8-byte alignment */
195};
196
197struct fs_quota_statv {
198 __s8 qs_version; /* version for future changes */
199 __u8 qs_pad1; /* pad for 16bit alignment */
200 __u16 qs_flags; /* FS_QUOTA_.* flags */
201 __u32 qs_incoredqs; /* number of dquots incore */
202 struct fs_qfilestatv qs_uquota; /* user quota information */
203 struct fs_qfilestatv qs_gquota; /* group quota information */
204 struct fs_qfilestatv qs_pquota; /* project quota information */
205 __s32 qs_btimelimit; /* limit for blks timer */
206 __s32 qs_itimelimit; /* limit for inodes timer */
207 __s32 qs_rtbtimelimit;/* limit for rt blks timer */
208 __u16 qs_bwarnlimit; /* limit for num warnings */
209 __u16 qs_iwarnlimit; /* limit for num warnings */
210 __u64 qs_pad2[8]; /* for future proofing */
211};
212
166#endif /* _LINUX_DQBLK_XFS_H */ 213#endif /* _LINUX_DQBLK_XFS_H */