[PATCH] reiserfs endianness: comp_short_keys() cleanup
[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 #include <linux/syscalls.h>
17 #include <linux/buffer_head.h>
18
19 /* Check validity of generic quotactl commands */
20 static int generic_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id)
21 {
22         if (type >= MAXQUOTAS)
23                 return -EINVAL;
24         if (!sb && cmd != Q_SYNC)
25                 return -ENODEV;
26         /* Is operation supported? */
27         if (sb && !sb->s_qcop)
28                 return -ENOSYS;
29
30         switch (cmd) {
31                 case Q_GETFMT:
32                         break;
33                 case Q_QUOTAON:
34                         if (!sb->s_qcop->quota_on)
35                                 return -ENOSYS;
36                         break;
37                 case Q_QUOTAOFF:
38                         if (!sb->s_qcop->quota_off)
39                                 return -ENOSYS;
40                         break;
41                 case Q_SETINFO:
42                         if (!sb->s_qcop->set_info)
43                                 return -ENOSYS;
44                         break;
45                 case Q_GETINFO:
46                         if (!sb->s_qcop->get_info)
47                                 return -ENOSYS;
48                         break;
49                 case Q_SETQUOTA:
50                         if (!sb->s_qcop->set_dqblk)
51                                 return -ENOSYS;
52                         break;
53                 case Q_GETQUOTA:
54                         if (!sb->s_qcop->get_dqblk)
55                                 return -ENOSYS;
56                         break;
57                 case Q_SYNC:
58                         if (sb && !sb->s_qcop->quota_sync)
59                                 return -ENOSYS;
60                         break;
61                 default:
62                         return -EINVAL;
63         }
64
65         /* Is quota turned on for commands which need it? */
66         switch (cmd) {
67                 case Q_GETFMT:
68                 case Q_GETINFO:
69                 case Q_QUOTAOFF:
70                 case Q_SETINFO:
71                 case Q_SETQUOTA:
72                 case Q_GETQUOTA:
73                         /* This is just informative test so we are satisfied without a lock */
74                         if (!sb_has_quota_enabled(sb, type))
75                                 return -ESRCH;
76         }
77
78         /* Check privileges */
79         if (cmd == Q_GETQUOTA) {
80                 if (((type == USRQUOTA && current->euid != id) ||
81                      (type == GRPQUOTA && !in_egroup_p(id))) &&
82                     !capable(CAP_SYS_ADMIN))
83                         return -EPERM;
84         }
85         else if (cmd != Q_GETFMT && cmd != Q_SYNC && cmd != Q_GETINFO)
86                 if (!capable(CAP_SYS_ADMIN))
87                         return -EPERM;
88
89         return 0;
90 }
91
92 /* Check validity of XFS Quota Manager commands */
93 static int xqm_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id)
94 {
95         if (type >= XQM_MAXQUOTAS)
96                 return -EINVAL;
97         if (!sb)
98                 return -ENODEV;
99         if (!sb->s_qcop)
100                 return -ENOSYS;
101
102         switch (cmd) {
103                 case Q_XQUOTAON:
104                 case Q_XQUOTAOFF:
105                 case Q_XQUOTARM:
106                         if (!sb->s_qcop->set_xstate)
107                                 return -ENOSYS;
108                         break;
109                 case Q_XGETQSTAT:
110                         if (!sb->s_qcop->get_xstate)
111                                 return -ENOSYS;
112                         break;
113                 case Q_XSETQLIM:
114                         if (!sb->s_qcop->set_xquota)
115                                 return -ENOSYS;
116                         break;
117                 case Q_XGETQUOTA:
118                         if (!sb->s_qcop->get_xquota)
119                                 return -ENOSYS;
120                         break;
121                 default:
122                         return -EINVAL;
123         }
124
125         /* Check privileges */
126         if (cmd == Q_XGETQUOTA) {
127                 if (((type == XQM_USRQUOTA && current->euid != id) ||
128                      (type == XQM_GRPQUOTA && !in_egroup_p(id))) &&
129                      !capable(CAP_SYS_ADMIN))
130                         return -EPERM;
131         } else if (cmd != Q_XGETQSTAT) {
132                 if (!capable(CAP_SYS_ADMIN))
133                         return -EPERM;
134         }
135
136         return 0;
137 }
138
139 static int check_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id)
140 {
141         int error;
142
143         if (XQM_COMMAND(cmd))
144                 error = xqm_quotactl_valid(sb, type, cmd, id);
145         else
146                 error = generic_quotactl_valid(sb, type, cmd, id);
147         if (!error)
148                 error = security_quotactl(cmd, type, id, sb);
149         return error;
150 }
151
152 static struct super_block *get_super_to_sync(int type)
153 {
154         struct list_head *head;
155         int cnt, dirty;
156
157 restart:
158         spin_lock(&sb_lock);
159         list_for_each(head, &super_blocks) {
160                 struct super_block *sb = list_entry(head, struct super_block, s_list);
161
162                 /* This test just improves performance so it needn't be reliable... */
163                 for (cnt = 0, dirty = 0; cnt < MAXQUOTAS; cnt++)
164                         if ((type == cnt || type == -1) && sb_has_quota_enabled(sb, cnt)
165                             && info_any_dirty(&sb_dqopt(sb)->info[cnt]))
166                                 dirty = 1;
167                 if (!dirty)
168                         continue;
169                 sb->s_count++;
170                 spin_unlock(&sb_lock);
171                 down_read(&sb->s_umount);
172                 if (!sb->s_root) {
173                         drop_super(sb);
174                         goto restart;
175                 }
176                 return sb;
177         }
178         spin_unlock(&sb_lock);
179         return NULL;
180 }
181
182 static void quota_sync_sb(struct super_block *sb, int type)
183 {
184         int cnt;
185         struct inode *discard[MAXQUOTAS];
186
187         sb->s_qcop->quota_sync(sb, type);
188         /* This is not very clever (and fast) but currently I don't know about
189          * any other simple way of getting quota data to disk and we must get
190          * them there for userspace to be visible... */
191         if (sb->s_op->sync_fs)
192                 sb->s_op->sync_fs(sb, 1);
193         sync_blockdev(sb->s_bdev);
194
195         /* Now when everything is written we can discard the pagecache so
196          * that userspace sees the changes. We need i_sem and so we could
197          * not do it inside dqonoff_sem. Moreover we need to be carefull
198          * about races with quotaoff() (that is the reason why we have own
199          * reference to inode). */
200         down(&sb_dqopt(sb)->dqonoff_sem);
201         for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
202                 discard[cnt] = NULL;
203                 if (type != -1 && cnt != type)
204                         continue;
205                 if (!sb_has_quota_enabled(sb, cnt))
206                         continue;
207                 discard[cnt] = igrab(sb_dqopt(sb)->files[cnt]);
208         }
209         up(&sb_dqopt(sb)->dqonoff_sem);
210         for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
211                 if (discard[cnt]) {
212                         down(&discard[cnt]->i_sem);
213                         truncate_inode_pages(&discard[cnt]->i_data, 0);
214                         up(&discard[cnt]->i_sem);
215                         iput(discard[cnt]);
216                 }
217         }
218 }
219
220 void sync_dquots(struct super_block *sb, int type)
221 {
222         if (sb) {
223                 if (sb->s_qcop->quota_sync)
224                         quota_sync_sb(sb, type);
225         }
226         else {
227                 while ((sb = get_super_to_sync(type)) != NULL) {
228                         if (sb->s_qcop->quota_sync)
229                                 quota_sync_sb(sb, type);
230                         drop_super(sb);
231                 }
232         }
233 }
234
235 /* Copy parameters and call proper function */
236 static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id, void __user *addr)
237 {
238         int ret;
239
240         switch (cmd) {
241                 case Q_QUOTAON: {
242                         char *pathname;
243
244                         if (IS_ERR(pathname = getname(addr)))
245                                 return PTR_ERR(pathname);
246                         ret = sb->s_qcop->quota_on(sb, type, id, pathname);
247                         putname(pathname);
248                         return ret;
249                 }
250                 case Q_QUOTAOFF:
251                         return sb->s_qcop->quota_off(sb, type);
252
253                 case Q_GETFMT: {
254                         __u32 fmt;
255
256                         down_read(&sb_dqopt(sb)->dqptr_sem);
257                         if (!sb_has_quota_enabled(sb, type)) {
258                                 up_read(&sb_dqopt(sb)->dqptr_sem);
259                                 return -ESRCH;
260                         }
261                         fmt = sb_dqopt(sb)->info[type].dqi_format->qf_fmt_id;
262                         up_read(&sb_dqopt(sb)->dqptr_sem);
263                         if (copy_to_user(addr, &fmt, sizeof(fmt)))
264                                 return -EFAULT;
265                         return 0;
266                 }
267                 case Q_GETINFO: {
268                         struct if_dqinfo info;
269
270                         if ((ret = sb->s_qcop->get_info(sb, type, &info)))
271                                 return ret;
272                         if (copy_to_user(addr, &info, sizeof(info)))
273                                 return -EFAULT;
274                         return 0;
275                 }
276                 case Q_SETINFO: {
277                         struct if_dqinfo info;
278
279                         if (copy_from_user(&info, addr, sizeof(info)))
280                                 return -EFAULT;
281                         return sb->s_qcop->set_info(sb, type, &info);
282                 }
283                 case Q_GETQUOTA: {
284                         struct if_dqblk idq;
285
286                         if ((ret = sb->s_qcop->get_dqblk(sb, type, id, &idq)))
287                                 return ret;
288                         if (copy_to_user(addr, &idq, sizeof(idq)))
289                                 return -EFAULT;
290                         return 0;
291                 }
292                 case Q_SETQUOTA: {
293                         struct if_dqblk idq;
294
295                         if (copy_from_user(&idq, addr, sizeof(idq)))
296                                 return -EFAULT;
297                         return sb->s_qcop->set_dqblk(sb, type, id, &idq);
298                 }
299                 case Q_SYNC:
300                         sync_dquots(sb, type);
301                         return 0;
302
303                 case Q_XQUOTAON:
304                 case Q_XQUOTAOFF:
305                 case Q_XQUOTARM: {
306                         __u32 flags;
307
308                         if (copy_from_user(&flags, addr, sizeof(flags)))
309                                 return -EFAULT;
310                         return sb->s_qcop->set_xstate(sb, flags, cmd);
311                 }
312                 case Q_XGETQSTAT: {
313                         struct fs_quota_stat fqs;
314                 
315                         if ((ret = sb->s_qcop->get_xstate(sb, &fqs)))
316                                 return ret;
317                         if (copy_to_user(addr, &fqs, sizeof(fqs)))
318                                 return -EFAULT;
319                         return 0;
320                 }
321                 case Q_XSETQLIM: {
322                         struct fs_disk_quota fdq;
323
324                         if (copy_from_user(&fdq, addr, sizeof(fdq)))
325                                 return -EFAULT;
326                        return sb->s_qcop->set_xquota(sb, type, id, &fdq);
327                 }
328                 case Q_XGETQUOTA: {
329                         struct fs_disk_quota fdq;
330
331                         if ((ret = sb->s_qcop->get_xquota(sb, type, id, &fdq)))
332                                 return ret;
333                         if (copy_to_user(addr, &fdq, sizeof(fdq)))
334                                 return -EFAULT;
335                         return 0;
336                 }
337                 /* We never reach here unless validity check is broken */
338                 default:
339                         BUG();
340         }
341         return 0;
342 }
343
344 /*
345  * This is the system call interface. This communicates with
346  * the user-level programs. Currently this only supports diskquota
347  * calls. Maybe we need to add the process quotas etc. in the future,
348  * but we probably should use rlimits for that.
349  */
350 asmlinkage long sys_quotactl(unsigned int cmd, const char __user *special, qid_t id, void __user *addr)
351 {
352         uint cmds, type;
353         struct super_block *sb = NULL;
354         struct block_device *bdev;
355         char *tmp;
356         int ret;
357
358         cmds = cmd >> SUBCMDSHIFT;
359         type = cmd & SUBCMDMASK;
360
361         if (cmds != Q_SYNC || special) {
362                 tmp = getname(special);
363                 if (IS_ERR(tmp))
364                         return PTR_ERR(tmp);
365                 bdev = lookup_bdev(tmp);
366                 putname(tmp);
367                 if (IS_ERR(bdev))
368                         return PTR_ERR(bdev);
369                 sb = get_super(bdev);
370                 bdput(bdev);
371                 if (!sb)
372                         return -ENODEV;
373         }
374
375         ret = check_quotactl_valid(sb, type, cmds, id);
376         if (ret >= 0)
377                 ret = do_quotactl(sb, type, cmds, id, addr);
378         if (sb)
379                 drop_super(sb);
380
381         return ret;
382 }