ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / fs / quota.c
1 /*
2  * Quota code necessary even when VFS quota support is not compiled
3  * into the kernel.  The interesting stuff is over in dquot.c, here
4  * we have symbols for initial quotactl(2) handling, the sysctl(2)
5  * variables, etc - things needed even when quota support disabled.
6  */
7
8 #include <linux/fs.h>
9 #include <linux/namei.h>
10 #include <linux/slab.h>
11 #include <asm/current.h>
12 #include <asm/uaccess.h>
13 #include <linux/kernel.h>
14 #include <linux/smp_lock.h>
15 #include <linux/security.h>
16
17 /* Check validity of quotactl */
18 static int check_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id)
19 {
20         if (type >= MAXQUOTAS)
21                 return -EINVAL;
22         if (!sb && cmd != Q_SYNC)
23                 return -ENODEV;
24         /* Is operation supported? */
25         if (sb && !sb->s_qcop)
26                 return -ENOSYS;
27
28         switch (cmd) {
29                 case Q_GETFMT:
30                         break;
31                 case Q_QUOTAON:
32                         if (!sb->s_qcop->quota_on)
33                                 return -ENOSYS;
34                         break;
35                 case Q_QUOTAOFF:
36                         if (!sb->s_qcop->quota_off)
37                                 return -ENOSYS;
38                         break;
39                 case Q_SETINFO:
40                         if (!sb->s_qcop->set_info)
41                                 return -ENOSYS;
42                         break;
43                 case Q_GETINFO:
44                         if (!sb->s_qcop->get_info)
45                                 return -ENOSYS;
46                         break;
47                 case Q_SETQUOTA:
48                         if (!sb->s_qcop->set_dqblk)
49                                 return -ENOSYS;
50                         break;
51                 case Q_GETQUOTA:
52                         if (!sb->s_qcop->get_dqblk)
53                                 return -ENOSYS;
54                         break;
55                 case Q_SYNC:
56                         if (sb && !sb->s_qcop->quota_sync)
57                                 return -ENOSYS;
58                         break;
59                 case Q_XQUOTAON:
60                 case Q_XQUOTAOFF:
61                 case Q_XQUOTARM:
62                         if (!sb->s_qcop->set_xstate)
63                                 return -ENOSYS;
64                         break;
65                 case Q_XGETQSTAT:
66                         if (!sb->s_qcop->get_xstate)
67                                 return -ENOSYS;
68                         break;
69                 case Q_XSETQLIM:
70                         if (!sb->s_qcop->set_xquota)
71                                 return -ENOSYS;
72                         break;
73                 case Q_XGETQUOTA:
74                         if (!sb->s_qcop->get_xquota)
75                                 return -ENOSYS;
76                         break;
77                 default:
78                         return -EINVAL;
79         }
80
81         /* Is quota turned on for commands which need it? */
82         switch (cmd) {
83                 case Q_GETFMT:
84                 case Q_GETINFO:
85                 case Q_QUOTAOFF:
86                 case Q_SETINFO:
87                 case Q_SETQUOTA:
88                 case Q_GETQUOTA:
89                         /* This is just informative test so we are satisfied without a lock */
90                         if (!sb_has_quota_enabled(sb, type))
91                                 return -ESRCH;
92         }
93         /* Check privileges */
94         if (cmd == Q_GETQUOTA || cmd == Q_XGETQUOTA) {
95                 if (((type == USRQUOTA && current->euid != id) ||
96                      (type == GRPQUOTA && !in_egroup_p(id))) &&
97                     !capable(CAP_SYS_ADMIN))
98                         return -EPERM;
99         }
100         else if (cmd != Q_GETFMT && cmd != Q_SYNC && cmd != Q_GETINFO && cmd != Q_XGETQSTAT)
101                 if (!capable(CAP_SYS_ADMIN))
102                         return -EPERM;
103
104         return security_quotactl (cmd, type, id, sb);
105 }
106
107 static struct super_block *get_super_to_sync(int type)
108 {
109         struct list_head *head;
110         int cnt, dirty;
111
112 restart:
113         spin_lock(&sb_lock);
114         list_for_each(head, &super_blocks) {
115                 struct super_block *sb = list_entry(head, struct super_block, s_list);
116
117                 /* This test just improves performance so it needn't be reliable... */
118                 for (cnt = 0, dirty = 0; cnt < MAXQUOTAS; cnt++)
119                         if ((type == cnt || type == -1) && sb_has_quota_enabled(sb, cnt)
120                             && info_any_dirty(&sb_dqopt(sb)->info[cnt]))
121                                 dirty = 1;
122                 if (!dirty)
123                         continue;
124                 sb->s_count++;
125                 spin_unlock(&sb_lock);
126                 down_read(&sb->s_umount);
127                 if (!sb->s_root) {
128                         drop_super(sb);
129                         goto restart;
130                 }
131                 return sb;
132         }
133         spin_unlock(&sb_lock);
134         return NULL;
135 }
136
137 void sync_dquots(struct super_block *sb, int type)
138 {
139         if (sb) {
140                 if (sb->s_qcop->quota_sync)
141                         sb->s_qcop->quota_sync(sb, type);
142         }
143         else {
144                 while ((sb = get_super_to_sync(type))) {
145                         if (sb->s_qcop->quota_sync)
146                                 sb->s_qcop->quota_sync(sb, type);
147                         drop_super(sb);
148                 }
149         }
150 }
151
152 /* Copy parameters and call proper function */
153 static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id, caddr_t addr)
154 {
155         int ret;
156
157         switch (cmd) {
158                 case Q_QUOTAON: {
159                         char *pathname;
160
161                         if (IS_ERR(pathname = getname(addr)))
162                                 return PTR_ERR(pathname);
163                         ret = sb->s_qcop->quota_on(sb, type, id, pathname);
164                         putname(pathname);
165                         return ret;
166                 }
167                 case Q_QUOTAOFF:
168                         return sb->s_qcop->quota_off(sb, type);
169
170                 case Q_GETFMT: {
171                         __u32 fmt;
172
173                         down_read(&sb_dqopt(sb)->dqptr_sem);
174                         if (!sb_has_quota_enabled(sb, type)) {
175                                 up_read(&sb_dqopt(sb)->dqptr_sem);
176                                 return -ESRCH;
177                         }
178                         fmt = sb_dqopt(sb)->info[type].dqi_format->qf_fmt_id;
179                         up_read(&sb_dqopt(sb)->dqptr_sem);
180                         if (copy_to_user(addr, &fmt, sizeof(fmt)))
181                                 return -EFAULT;
182                         return 0;
183                 }
184                 case Q_GETINFO: {
185                         struct if_dqinfo info;
186
187                         if ((ret = sb->s_qcop->get_info(sb, type, &info)))
188                                 return ret;
189                         if (copy_to_user(addr, &info, sizeof(info)))
190                                 return -EFAULT;
191                         return 0;
192                 }
193                 case Q_SETINFO: {
194                         struct if_dqinfo info;
195
196                         if (copy_from_user(&info, addr, sizeof(info)))
197                                 return -EFAULT;
198                         return sb->s_qcop->set_info(sb, type, &info);
199                 }
200                 case Q_GETQUOTA: {
201                         struct if_dqblk idq;
202
203                         if ((ret = sb->s_qcop->get_dqblk(sb, type, id, &idq)))
204                                 return ret;
205                         if (copy_to_user(addr, &idq, sizeof(idq)))
206                                 return -EFAULT;
207                         return 0;
208                 }
209                 case Q_SETQUOTA: {
210                         struct if_dqblk idq;
211
212                         if (copy_from_user(&idq, addr, sizeof(idq)))
213                                 return -EFAULT;
214                         return sb->s_qcop->set_dqblk(sb, type, id, &idq);
215                 }
216                 case Q_SYNC:
217                         sync_dquots(sb, type);
218                         return 0;
219
220                 case Q_XQUOTAON:
221                 case Q_XQUOTAOFF:
222                 case Q_XQUOTARM: {
223                         __u32 flags;
224
225                         if (copy_from_user(&flags, addr, sizeof(flags)))
226                                 return -EFAULT;
227                         return sb->s_qcop->set_xstate(sb, flags, cmd);
228                 }
229                 case Q_XGETQSTAT: {
230                         struct fs_quota_stat fqs;
231                 
232                         if ((ret = sb->s_qcop->get_xstate(sb, &fqs)))
233                                 return ret;
234                         if (copy_to_user(addr, &fqs, sizeof(fqs)))
235                                 return -EFAULT;
236                         return 0;
237                 }
238                 case Q_XSETQLIM: {
239                         struct fs_disk_quota fdq;
240
241                         if (copy_from_user(&fdq, addr, sizeof(fdq)))
242                                 return -EFAULT;
243                        return sb->s_qcop->set_xquota(sb, type, id, &fdq);
244                 }
245                 case Q_XGETQUOTA: {
246                         struct fs_disk_quota fdq;
247
248                         if ((ret = sb->s_qcop->get_xquota(sb, type, id, &fdq)))
249                                 return ret;
250                         if (copy_to_user(addr, &fdq, sizeof(fdq)))
251                                 return -EFAULT;
252                         return 0;
253                 }
254                 /* We never reach here unless validity check is broken */
255                 default:
256                         BUG();
257         }
258         return 0;
259 }
260
261 /*
262  * This is the system call interface. This communicates with
263  * the user-level programs. Currently this only supports diskquota
264  * calls. Maybe we need to add the process quotas etc. in the future,
265  * but we probably should use rlimits for that.
266  */
267 asmlinkage long sys_quotactl(unsigned int cmd, const char *special, qid_t id, caddr_t addr)
268 {
269         uint cmds, type;
270         struct super_block *sb = NULL;
271         struct block_device *bdev;
272         char *tmp;
273         int ret;
274
275         cmds = cmd >> SUBCMDSHIFT;
276         type = cmd & SUBCMDMASK;
277
278         if (cmds != Q_SYNC || special) {
279                 tmp = getname(special);
280                 if (IS_ERR(tmp))
281                         return PTR_ERR(tmp);
282                 bdev = lookup_bdev(tmp);
283                 putname(tmp);
284                 if (IS_ERR(bdev))
285                         return PTR_ERR(bdev);
286                 sb = get_super(bdev);
287                 bdput(bdev);
288                 if (!sb)
289                         return -ENODEV;
290         }
291
292         ret = check_quotactl_valid(sb, type, cmds, id);
293         if (ret >= 0)
294                 ret = do_quotactl(sb, type, cmds, id, addr);
295         if (sb)
296                 drop_super(sb);
297
298         return ret;
299 }