[XFS] Add a mechanism for XFS to use the generic quota sync method.
[linux-2.6] / 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                 case Q_XQUOTASYNC:
122                         if (!sb->s_qcop->quota_sync)
123                                 return -ENOSYS;
124                         break;
125                 default:
126                         return -EINVAL;
127         }
128
129         /* Check privileges */
130         if (cmd == Q_XGETQUOTA) {
131                 if (((type == XQM_USRQUOTA && current->euid != id) ||
132                      (type == XQM_GRPQUOTA && !in_egroup_p(id))) &&
133                      !capable(CAP_SYS_ADMIN))
134                         return -EPERM;
135         } else if (cmd != Q_XGETQSTAT && cmd != Q_XQUOTASYNC) {
136                 if (!capable(CAP_SYS_ADMIN))
137                         return -EPERM;
138         }
139
140         return 0;
141 }
142
143 static int check_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id)
144 {
145         int error;
146
147         if (XQM_COMMAND(cmd))
148                 error = xqm_quotactl_valid(sb, type, cmd, id);
149         else
150                 error = generic_quotactl_valid(sb, type, cmd, id);
151         if (!error)
152                 error = security_quotactl(cmd, type, id, sb);
153         return error;
154 }
155
156 static void quota_sync_sb(struct super_block *sb, int type)
157 {
158         int cnt;
159         struct inode *discard[MAXQUOTAS];
160
161         sb->s_qcop->quota_sync(sb, type);
162         /* This is not very clever (and fast) but currently I don't know about
163          * any other simple way of getting quota data to disk and we must get
164          * them there for userspace to be visible... */
165         if (sb->s_op->sync_fs)
166                 sb->s_op->sync_fs(sb, 1);
167         sync_blockdev(sb->s_bdev);
168
169         /* Now when everything is written we can discard the pagecache so
170          * that userspace sees the changes. We need i_sem and so we could
171          * not do it inside dqonoff_sem. Moreover we need to be carefull
172          * about races with quotaoff() (that is the reason why we have own
173          * reference to inode). */
174         down(&sb_dqopt(sb)->dqonoff_sem);
175         for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
176                 discard[cnt] = NULL;
177                 if (type != -1 && cnt != type)
178                         continue;
179                 if (!sb_has_quota_enabled(sb, cnt))
180                         continue;
181                 discard[cnt] = igrab(sb_dqopt(sb)->files[cnt]);
182         }
183         up(&sb_dqopt(sb)->dqonoff_sem);
184         for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
185                 if (discard[cnt]) {
186                         down(&discard[cnt]->i_sem);
187                         truncate_inode_pages(&discard[cnt]->i_data, 0);
188                         up(&discard[cnt]->i_sem);
189                         iput(discard[cnt]);
190                 }
191         }
192 }
193
194 void sync_dquots(struct super_block *sb, int type)
195 {
196         int cnt, dirty;
197
198         if (sb) {
199                 if (sb->s_qcop->quota_sync)
200                         quota_sync_sb(sb, type);
201                 return;
202         }
203
204         spin_lock(&sb_lock);
205 restart:
206         list_for_each_entry(sb, &super_blocks, s_list) {
207                 /* This test just improves performance so it needn't be reliable... */
208                 for (cnt = 0, dirty = 0; cnt < MAXQUOTAS; cnt++)
209                         if ((type == cnt || type == -1) && sb_has_quota_enabled(sb, cnt)
210                             && info_any_dirty(&sb_dqopt(sb)->info[cnt]))
211                                 dirty = 1;
212                 if (!dirty)
213                         continue;
214                 sb->s_count++;
215                 spin_unlock(&sb_lock);
216                 down_read(&sb->s_umount);
217                 if (sb->s_root && sb->s_qcop->quota_sync)
218                         quota_sync_sb(sb, type);
219                 up_read(&sb->s_umount);
220                 spin_lock(&sb_lock);
221                 if (__put_super_and_need_restart(sb))
222                         goto restart;
223         }
224         spin_unlock(&sb_lock);
225 }
226
227 /* Copy parameters and call proper function */
228 static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id, void __user *addr)
229 {
230         int ret;
231
232         switch (cmd) {
233                 case Q_QUOTAON: {
234                         char *pathname;
235
236                         if (IS_ERR(pathname = getname(addr)))
237                                 return PTR_ERR(pathname);
238                         ret = sb->s_qcop->quota_on(sb, type, id, pathname);
239                         putname(pathname);
240                         return ret;
241                 }
242                 case Q_QUOTAOFF:
243                         return sb->s_qcop->quota_off(sb, type);
244
245                 case Q_GETFMT: {
246                         __u32 fmt;
247
248                         down_read(&sb_dqopt(sb)->dqptr_sem);
249                         if (!sb_has_quota_enabled(sb, type)) {
250                                 up_read(&sb_dqopt(sb)->dqptr_sem);
251                                 return -ESRCH;
252                         }
253                         fmt = sb_dqopt(sb)->info[type].dqi_format->qf_fmt_id;
254                         up_read(&sb_dqopt(sb)->dqptr_sem);
255                         if (copy_to_user(addr, &fmt, sizeof(fmt)))
256                                 return -EFAULT;
257                         return 0;
258                 }
259                 case Q_GETINFO: {
260                         struct if_dqinfo info;
261
262                         if ((ret = sb->s_qcop->get_info(sb, type, &info)))
263                                 return ret;
264                         if (copy_to_user(addr, &info, sizeof(info)))
265                                 return -EFAULT;
266                         return 0;
267                 }
268                 case Q_SETINFO: {
269                         struct if_dqinfo info;
270
271                         if (copy_from_user(&info, addr, sizeof(info)))
272                                 return -EFAULT;
273                         return sb->s_qcop->set_info(sb, type, &info);
274                 }
275                 case Q_GETQUOTA: {
276                         struct if_dqblk idq;
277
278                         if ((ret = sb->s_qcop->get_dqblk(sb, type, id, &idq)))
279                                 return ret;
280                         if (copy_to_user(addr, &idq, sizeof(idq)))
281                                 return -EFAULT;
282                         return 0;
283                 }
284                 case Q_SETQUOTA: {
285                         struct if_dqblk idq;
286
287                         if (copy_from_user(&idq, addr, sizeof(idq)))
288                                 return -EFAULT;
289                         return sb->s_qcop->set_dqblk(sb, type, id, &idq);
290                 }
291                 case Q_SYNC:
292                         sync_dquots(sb, type);
293                         return 0;
294
295                 case Q_XQUOTAON:
296                 case Q_XQUOTAOFF:
297                 case Q_XQUOTARM: {
298                         __u32 flags;
299
300                         if (copy_from_user(&flags, addr, sizeof(flags)))
301                                 return -EFAULT;
302                         return sb->s_qcop->set_xstate(sb, flags, cmd);
303                 }
304                 case Q_XGETQSTAT: {
305                         struct fs_quota_stat fqs;
306                 
307                         if ((ret = sb->s_qcop->get_xstate(sb, &fqs)))
308                                 return ret;
309                         if (copy_to_user(addr, &fqs, sizeof(fqs)))
310                                 return -EFAULT;
311                         return 0;
312                 }
313                 case Q_XSETQLIM: {
314                         struct fs_disk_quota fdq;
315
316                         if (copy_from_user(&fdq, addr, sizeof(fdq)))
317                                 return -EFAULT;
318                        return sb->s_qcop->set_xquota(sb, type, id, &fdq);
319                 }
320                 case Q_XGETQUOTA: {
321                         struct fs_disk_quota fdq;
322
323                         if ((ret = sb->s_qcop->get_xquota(sb, type, id, &fdq)))
324                                 return ret;
325                         if (copy_to_user(addr, &fdq, sizeof(fdq)))
326                                 return -EFAULT;
327                         return 0;
328                 }
329                 case Q_XQUOTASYNC:
330                         return sb->s_qcop->quota_sync(sb, type);
331                 /* We never reach here unless validity check is broken */
332                 default:
333                         BUG();
334         }
335         return 0;
336 }
337
338 /*
339  * This is the system call interface. This communicates with
340  * the user-level programs. Currently this only supports diskquota
341  * calls. Maybe we need to add the process quotas etc. in the future,
342  * but we probably should use rlimits for that.
343  */
344 asmlinkage long sys_quotactl(unsigned int cmd, const char __user *special, qid_t id, void __user *addr)
345 {
346         uint cmds, type;
347         struct super_block *sb = NULL;
348         struct block_device *bdev;
349         char *tmp;
350         int ret;
351
352         cmds = cmd >> SUBCMDSHIFT;
353         type = cmd & SUBCMDMASK;
354
355         if (cmds != Q_SYNC || special) {
356                 tmp = getname(special);
357                 if (IS_ERR(tmp))
358                         return PTR_ERR(tmp);
359                 bdev = lookup_bdev(tmp);
360                 putname(tmp);
361                 if (IS_ERR(bdev))
362                         return PTR_ERR(bdev);
363                 sb = get_super(bdev);
364                 bdput(bdev);
365                 if (!sb)
366                         return -ENODEV;
367         }
368
369         ret = check_quotactl_valid(sb, type, cmds, id);
370         if (ret >= 0)
371                 ret = do_quotactl(sb, type, cmds, id, addr);
372         if (sb)
373                 drop_super(sb);
374
375         return ret;
376 }