aboutsummaryrefslogtreecommitdiffstats
path: root/fs/quota
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2010-02-16 03:44:55 -0500
committerJan Kara <jack@suse.cz>2010-03-04 18:20:25 -0500
commit5582c76f901d240f57329212b59b4d957ea8d6cf (patch)
tree3709746be14e89eebbd4099b59dff2aefc348167 /fs/quota
parent799a9d44023c069f46bc5933a930eab0bd37d0df (diff)
quota: split out compat_sys_quotactl support from quota.c
Instead of adding ifdefs just split it into a new file. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'fs/quota')
-rw-r--r--fs/quota/Kconfig5
-rw-r--r--fs/quota/Makefile1
-rw-r--r--fs/quota/compat.c118
-rw-r--r--fs/quota/quota.c117
4 files changed, 124 insertions, 117 deletions
diff --git a/fs/quota/Kconfig b/fs/quota/Kconfig
index efc02ebb8c70..dad7fb247ddc 100644
--- a/fs/quota/Kconfig
+++ b/fs/quota/Kconfig
@@ -59,3 +59,8 @@ config QUOTACTL
59 bool 59 bool
60 depends on XFS_QUOTA || QUOTA 60 depends on XFS_QUOTA || QUOTA
61 default y 61 default y
62
63config QUOTACTL_COMPAT
64 bool
65 depends on QUOTACTL && COMPAT_FOR_U64_ALIGNMENT
66 default y
diff --git a/fs/quota/Makefile b/fs/quota/Makefile
index dcba20445ccb..5f9e9e276af0 100644
--- a/fs/quota/Makefile
+++ b/fs/quota/Makefile
@@ -3,4 +3,5 @@ obj-$(CONFIG_QFMT_V1) += quota_v1.o
3obj-$(CONFIG_QFMT_V2) += quota_v2.o 3obj-$(CONFIG_QFMT_V2) += quota_v2.o
4obj-$(CONFIG_QUOTA_TREE) += quota_tree.o 4obj-$(CONFIG_QUOTA_TREE) += quota_tree.o
5obj-$(CONFIG_QUOTACTL) += quota.o 5obj-$(CONFIG_QUOTACTL) += quota.o
6obj-$(CONFIG_QUOTACTL_COMPAT) += compat.o
6obj-$(CONFIG_QUOTA_NETLINK_INTERFACE) += netlink.o 7obj-$(CONFIG_QUOTA_NETLINK_INTERFACE) += netlink.o
diff --git a/fs/quota/compat.c b/fs/quota/compat.c
new file mode 100644
index 000000000000..fb1892fe3e56
--- /dev/null
+++ b/fs/quota/compat.c
@@ -0,0 +1,118 @@
1
2#include <linux/syscalls.h>
3#include <linux/compat.h>
4#include <linux/quotaops.h>
5
6/*
7 * This code works only for 32 bit quota tools over 64 bit OS (x86_64, ia64)
8 * and is necessary due to alignment problems.
9 */
10struct compat_if_dqblk {
11 compat_u64 dqb_bhardlimit;
12 compat_u64 dqb_bsoftlimit;
13 compat_u64 dqb_curspace;
14 compat_u64 dqb_ihardlimit;
15 compat_u64 dqb_isoftlimit;
16 compat_u64 dqb_curinodes;
17 compat_u64 dqb_btime;
18 compat_u64 dqb_itime;
19 compat_uint_t dqb_valid;
20};
21
22/* XFS structures */
23struct compat_fs_qfilestat {
24 compat_u64 dqb_bhardlimit;
25 compat_u64 qfs_nblks;
26 compat_uint_t qfs_nextents;
27};
28
29struct compat_fs_quota_stat {
30 __s8 qs_version;
31 __u16 qs_flags;
32 __s8 qs_pad;
33 struct compat_fs_qfilestat qs_uquota;
34 struct compat_fs_qfilestat qs_gquota;
35 compat_uint_t qs_incoredqs;
36 compat_int_t qs_btimelimit;
37 compat_int_t qs_itimelimit;
38 compat_int_t qs_rtbtimelimit;
39 __u16 qs_bwarnlimit;
40 __u16 qs_iwarnlimit;
41};
42
43asmlinkage long sys32_quotactl(unsigned int cmd, const char __user *special,
44 qid_t id, void __user *addr)
45{
46 unsigned int cmds;
47 struct if_dqblk __user *dqblk;
48 struct compat_if_dqblk __user *compat_dqblk;
49 struct fs_quota_stat __user *fsqstat;
50 struct compat_fs_quota_stat __user *compat_fsqstat;
51 compat_uint_t data;
52 u16 xdata;
53 long ret;
54
55 cmds = cmd >> SUBCMDSHIFT;
56
57 switch (cmds) {
58 case Q_GETQUOTA:
59 dqblk = compat_alloc_user_space(sizeof(struct if_dqblk));
60 compat_dqblk = addr;
61 ret = sys_quotactl(cmd, special, id, dqblk);
62 if (ret)
63 break;
64 if (copy_in_user(compat_dqblk, dqblk, sizeof(*compat_dqblk)) ||
65 get_user(data, &dqblk->dqb_valid) ||
66 put_user(data, &compat_dqblk->dqb_valid))
67 ret = -EFAULT;
68 break;
69 case Q_SETQUOTA:
70 dqblk = compat_alloc_user_space(sizeof(struct if_dqblk));
71 compat_dqblk = addr;
72 ret = -EFAULT;
73 if (copy_in_user(dqblk, compat_dqblk, sizeof(*compat_dqblk)) ||
74 get_user(data, &compat_dqblk->dqb_valid) ||
75 put_user(data, &dqblk->dqb_valid))
76 break;
77 ret = sys_quotactl(cmd, special, id, dqblk);
78 break;
79 case Q_XGETQSTAT:
80 fsqstat = compat_alloc_user_space(sizeof(struct fs_quota_stat));
81 compat_fsqstat = addr;
82 ret = sys_quotactl(cmd, special, id, fsqstat);
83 if (ret)
84 break;
85 ret = -EFAULT;
86 /* Copying qs_version, qs_flags, qs_pad */
87 if (copy_in_user(compat_fsqstat, fsqstat,
88 offsetof(struct compat_fs_quota_stat, qs_uquota)))
89 break;
90 /* Copying qs_uquota */
91 if (copy_in_user(&compat_fsqstat->qs_uquota,
92 &fsqstat->qs_uquota,
93 sizeof(compat_fsqstat->qs_uquota)) ||
94 get_user(data, &fsqstat->qs_uquota.qfs_nextents) ||
95 put_user(data, &compat_fsqstat->qs_uquota.qfs_nextents))
96 break;
97 /* Copying qs_gquota */
98 if (copy_in_user(&compat_fsqstat->qs_gquota,
99 &fsqstat->qs_gquota,
100 sizeof(compat_fsqstat->qs_gquota)) ||
101 get_user(data, &fsqstat->qs_gquota.qfs_nextents) ||
102 put_user(data, &compat_fsqstat->qs_gquota.qfs_nextents))
103 break;
104 /* Copying the rest */
105 if (copy_in_user(&compat_fsqstat->qs_incoredqs,
106 &fsqstat->qs_incoredqs,
107 sizeof(struct compat_fs_quota_stat) -
108 offsetof(struct compat_fs_quota_stat, qs_incoredqs)) ||
109 get_user(xdata, &fsqstat->qs_iwarnlimit) ||
110 put_user(xdata, &compat_fsqstat->qs_iwarnlimit))
111 break;
112 ret = 0;
113 break;
114 default:
115 ret = sys_quotactl(cmd, special, id, addr);
116 }
117 return ret;
118}
diff --git a/fs/quota/quota.c b/fs/quota/quota.c
index 4506c6596347..95388f9b7356 100644
--- a/fs/quota/quota.c
+++ b/fs/quota/quota.c
@@ -10,7 +10,6 @@
10#include <linux/slab.h> 10#include <linux/slab.h>
11#include <asm/current.h> 11#include <asm/current.h>
12#include <asm/uaccess.h> 12#include <asm/uaccess.h>
13#include <linux/compat.h>
14#include <linux/kernel.h> 13#include <linux/kernel.h>
15#include <linux/security.h> 14#include <linux/security.h>
16#include <linux/syscalls.h> 15#include <linux/syscalls.h>
@@ -340,119 +339,3 @@ SYSCALL_DEFINE4(quotactl, unsigned int, cmd, const char __user *, special,
340 drop_super(sb); 339 drop_super(sb);
341 return ret; 340 return ret;
342} 341}
343
344#if defined(CONFIG_COMPAT_FOR_U64_ALIGNMENT)
345/*
346 * This code works only for 32 bit quota tools over 64 bit OS (x86_64, ia64)
347 * and is necessary due to alignment problems.
348 */
349struct compat_if_dqblk {
350 compat_u64 dqb_bhardlimit;
351 compat_u64 dqb_bsoftlimit;
352 compat_u64 dqb_curspace;
353 compat_u64 dqb_ihardlimit;
354 compat_u64 dqb_isoftlimit;
355 compat_u64 dqb_curinodes;
356 compat_u64 dqb_btime;
357 compat_u64 dqb_itime;
358 compat_uint_t dqb_valid;
359};
360
361/* XFS structures */
362struct compat_fs_qfilestat {
363 compat_u64 dqb_bhardlimit;
364 compat_u64 qfs_nblks;
365 compat_uint_t qfs_nextents;
366};
367
368struct compat_fs_quota_stat {
369 __s8 qs_version;
370 __u16 qs_flags;
371 __s8 qs_pad;
372 struct compat_fs_qfilestat qs_uquota;
373 struct compat_fs_qfilestat qs_gquota;
374 compat_uint_t qs_incoredqs;
375 compat_int_t qs_btimelimit;
376 compat_int_t qs_itimelimit;
377 compat_int_t qs_rtbtimelimit;
378 __u16 qs_bwarnlimit;
379 __u16 qs_iwarnlimit;
380};
381
382asmlinkage long sys32_quotactl(unsigned int cmd, const char __user *special,
383 qid_t id, void __user *addr)
384{
385 unsigned int cmds;
386 struct if_dqblk __user *dqblk;
387 struct compat_if_dqblk __user *compat_dqblk;
388 struct fs_quota_stat __user *fsqstat;
389 struct compat_fs_quota_stat __user *compat_fsqstat;
390 compat_uint_t data;
391 u16 xdata;
392 long ret;
393
394 cmds = cmd >> SUBCMDSHIFT;
395
396 switch (cmds) {
397 case Q_GETQUOTA:
398 dqblk = compat_alloc_user_space(sizeof(struct if_dqblk));
399 compat_dqblk = addr;
400 ret = sys_quotactl(cmd, special, id, dqblk);
401 if (ret)
402 break;
403 if (copy_in_user(compat_dqblk, dqblk, sizeof(*compat_dqblk)) ||
404 get_user(data, &dqblk->dqb_valid) ||
405 put_user(data, &compat_dqblk->dqb_valid))
406 ret = -EFAULT;
407 break;
408 case Q_SETQUOTA:
409 dqblk = compat_alloc_user_space(sizeof(struct if_dqblk));
410 compat_dqblk = addr;
411 ret = -EFAULT;
412 if (copy_in_user(dqblk, compat_dqblk, sizeof(*compat_dqblk)) ||
413 get_user(data, &compat_dqblk->dqb_valid) ||
414 put_user(data, &dqblk->dqb_valid))
415 break;
416 ret = sys_quotactl(cmd, special, id, dqblk);
417 break;
418 case Q_XGETQSTAT:
419 fsqstat = compat_alloc_user_space(sizeof(struct fs_quota_stat));
420 compat_fsqstat = addr;
421 ret = sys_quotactl(cmd, special, id, fsqstat);
422 if (ret)
423 break;
424 ret = -EFAULT;
425 /* Copying qs_version, qs_flags, qs_pad */
426 if (copy_in_user(compat_fsqstat, fsqstat,
427 offsetof(struct compat_fs_quota_stat, qs_uquota)))
428 break;
429 /* Copying qs_uquota */
430 if (copy_in_user(&compat_fsqstat->qs_uquota,
431 &fsqstat->qs_uquota,
432 sizeof(compat_fsqstat->qs_uquota)) ||
433 get_user(data, &fsqstat->qs_uquota.qfs_nextents) ||
434 put_user(data, &compat_fsqstat->qs_uquota.qfs_nextents))
435 break;
436 /* Copying qs_gquota */
437 if (copy_in_user(&compat_fsqstat->qs_gquota,
438 &fsqstat->qs_gquota,
439 sizeof(compat_fsqstat->qs_gquota)) ||
440 get_user(data, &fsqstat->qs_gquota.qfs_nextents) ||
441 put_user(data, &compat_fsqstat->qs_gquota.qfs_nextents))
442 break;
443 /* Copying the rest */
444 if (copy_in_user(&compat_fsqstat->qs_incoredqs,
445 &fsqstat->qs_incoredqs,
446 sizeof(struct compat_fs_quota_stat) -
447 offsetof(struct compat_fs_quota_stat, qs_incoredqs)) ||
448 get_user(xdata, &fsqstat->qs_iwarnlimit) ||
449 put_user(xdata, &compat_fsqstat->qs_iwarnlimit))
450 break;
451 ret = 0;
452 break;
453 default:
454 ret = sys_quotactl(cmd, special, id, addr);
455 }
456 return ret;
457}
458#endif