diff options
-rw-r--r-- | fs/quota/quota.c | 29 | ||||
-rw-r--r-- | include/linux/quota.h | 1 | ||||
-rw-r--r-- | include/uapi/linux/dqblk_xfs.h | 47 |
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 | ||
221 | static 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 | |||
220 | static int quota_setxquota(struct super_block *sb, int type, qid_t id, | 246 | static 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 | ||
333 | struct quota_format_type { | 334 | struct 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 | */ | ||
190 | struct 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 | |||
197 | struct 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 */ |