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