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