Bury __put_super_and_need_restart()
[deliverable/linux.git] / fs / quota / 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/security.h>
15 #include <linux/syscalls.h>
16 #include <linux/buffer_head.h>
17 #include <linux/capability.h>
18 #include <linux/quotaops.h>
19 #include <linux/types.h>
20 #include <linux/writeback.h>
21 #include "../internal.h"
22
23 static int check_quotactl_permission(struct super_block *sb, int type, int cmd,
24 qid_t id)
25 {
26 switch (cmd) {
27 /* these commands do not require any special privilegues */
28 case Q_GETFMT:
29 case Q_SYNC:
30 case Q_GETINFO:
31 case Q_XGETQSTAT:
32 case Q_XQUOTASYNC:
33 break;
34 /* allow to query information for dquots we "own" */
35 case Q_GETQUOTA:
36 case Q_XGETQUOTA:
37 if ((type == USRQUOTA && current_euid() == id) ||
38 (type == GRPQUOTA && in_egroup_p(id)))
39 break;
40 /*FALLTHROUGH*/
41 default:
42 if (!capable(CAP_SYS_ADMIN))
43 return -EPERM;
44 }
45
46 return security_quotactl(cmd, type, id, sb);
47 }
48
49 static int quota_sync_all(int type)
50 {
51 struct super_block *sb, *n;
52 int ret;
53
54 if (type >= MAXQUOTAS)
55 return -EINVAL;
56 ret = security_quotactl(Q_SYNC, type, 0, NULL);
57 if (ret)
58 return ret;
59
60 spin_lock(&sb_lock);
61 list_for_each_entry_safe(sb, n, &super_blocks, s_list) {
62 if (list_empty(&sb->s_instances))
63 continue;
64 if (!sb->s_qcop || !sb->s_qcop->quota_sync)
65 continue;
66
67 sb->s_count++;
68 spin_unlock(&sb_lock);
69 down_read(&sb->s_umount);
70 if (sb->s_root)
71 sb->s_qcop->quota_sync(sb, type, 1);
72 up_read(&sb->s_umount);
73 spin_lock(&sb_lock);
74 __put_super(sb);
75 }
76 spin_unlock(&sb_lock);
77
78 return 0;
79 }
80
81 static int quota_quotaon(struct super_block *sb, int type, int cmd, qid_t id,
82 void __user *addr)
83 {
84 char *pathname;
85 int ret = -ENOSYS;
86
87 pathname = getname(addr);
88 if (IS_ERR(pathname))
89 return PTR_ERR(pathname);
90 if (sb->s_qcop->quota_on)
91 ret = sb->s_qcop->quota_on(sb, type, id, pathname, 0);
92 putname(pathname);
93 return ret;
94 }
95
96 static int quota_getfmt(struct super_block *sb, int type, void __user *addr)
97 {
98 __u32 fmt;
99
100 down_read(&sb_dqopt(sb)->dqptr_sem);
101 if (!sb_has_quota_active(sb, type)) {
102 up_read(&sb_dqopt(sb)->dqptr_sem);
103 return -ESRCH;
104 }
105 fmt = sb_dqopt(sb)->info[type].dqi_format->qf_fmt_id;
106 up_read(&sb_dqopt(sb)->dqptr_sem);
107 if (copy_to_user(addr, &fmt, sizeof(fmt)))
108 return -EFAULT;
109 return 0;
110 }
111
112 static int quota_getinfo(struct super_block *sb, int type, void __user *addr)
113 {
114 struct if_dqinfo info;
115 int ret;
116
117 if (!sb->s_qcop->get_info)
118 return -ENOSYS;
119 ret = sb->s_qcop->get_info(sb, type, &info);
120 if (!ret && copy_to_user(addr, &info, sizeof(info)))
121 return -EFAULT;
122 return ret;
123 }
124
125 static int quota_setinfo(struct super_block *sb, int type, void __user *addr)
126 {
127 struct if_dqinfo info;
128
129 if (copy_from_user(&info, addr, sizeof(info)))
130 return -EFAULT;
131 if (!sb->s_qcop->set_info)
132 return -ENOSYS;
133 return sb->s_qcop->set_info(sb, type, &info);
134 }
135
136 static void copy_to_if_dqblk(struct if_dqblk *dst, struct fs_disk_quota *src)
137 {
138 dst->dqb_bhardlimit = src->d_blk_hardlimit;
139 dst->dqb_bsoftlimit = src->d_blk_softlimit;
140 dst->dqb_curspace = src->d_bcount;
141 dst->dqb_ihardlimit = src->d_ino_hardlimit;
142 dst->dqb_isoftlimit = src->d_ino_softlimit;
143 dst->dqb_curinodes = src->d_icount;
144 dst->dqb_btime = src->d_btimer;
145 dst->dqb_itime = src->d_itimer;
146 dst->dqb_valid = QIF_ALL;
147 }
148
149 static int quota_getquota(struct super_block *sb, int type, qid_t id,
150 void __user *addr)
151 {
152 struct fs_disk_quota fdq;
153 struct if_dqblk idq;
154 int ret;
155
156 if (!sb->s_qcop->get_dqblk)
157 return -ENOSYS;
158 ret = sb->s_qcop->get_dqblk(sb, type, id, &fdq);
159 if (ret)
160 return ret;
161 copy_to_if_dqblk(&idq, &fdq);
162 if (copy_to_user(addr, &idq, sizeof(idq)))
163 return -EFAULT;
164 return 0;
165 }
166
167 static void copy_from_if_dqblk(struct fs_disk_quota *dst, struct if_dqblk *src)
168 {
169 dst->d_blk_hardlimit = src->dqb_bhardlimit;
170 dst->d_blk_softlimit = src->dqb_bsoftlimit;
171 dst->d_bcount = src->dqb_curspace;
172 dst->d_ino_hardlimit = src->dqb_ihardlimit;
173 dst->d_ino_softlimit = src->dqb_isoftlimit;
174 dst->d_icount = src->dqb_curinodes;
175 dst->d_btimer = src->dqb_btime;
176 dst->d_itimer = src->dqb_itime;
177
178 dst->d_fieldmask = 0;
179 if (src->dqb_valid & QIF_BLIMITS)
180 dst->d_fieldmask |= FS_DQ_BSOFT | FS_DQ_BHARD;
181 if (src->dqb_valid & QIF_SPACE)
182 dst->d_fieldmask |= FS_DQ_BCOUNT;
183 if (src->dqb_valid & QIF_ILIMITS)
184 dst->d_fieldmask |= FS_DQ_ISOFT | FS_DQ_IHARD;
185 if (src->dqb_valid & QIF_INODES)
186 dst->d_fieldmask |= FS_DQ_ICOUNT;
187 if (src->dqb_valid & QIF_BTIME)
188 dst->d_fieldmask |= FS_DQ_BTIMER;
189 if (src->dqb_valid & QIF_ITIME)
190 dst->d_fieldmask |= FS_DQ_ITIMER;
191 }
192
193 static int quota_setquota(struct super_block *sb, int type, qid_t id,
194 void __user *addr)
195 {
196 struct fs_disk_quota fdq;
197 struct if_dqblk idq;
198
199 if (copy_from_user(&idq, addr, sizeof(idq)))
200 return -EFAULT;
201 if (!sb->s_qcop->set_dqblk)
202 return -ENOSYS;
203 copy_from_if_dqblk(&fdq, &idq);
204 return sb->s_qcop->set_dqblk(sb, type, id, &fdq);
205 }
206
207 static int quota_setxstate(struct super_block *sb, int cmd, void __user *addr)
208 {
209 __u32 flags;
210
211 if (copy_from_user(&flags, addr, sizeof(flags)))
212 return -EFAULT;
213 if (!sb->s_qcop->set_xstate)
214 return -ENOSYS;
215 return sb->s_qcop->set_xstate(sb, flags, cmd);
216 }
217
218 static int quota_getxstate(struct super_block *sb, void __user *addr)
219 {
220 struct fs_quota_stat fqs;
221 int ret;
222
223 if (!sb->s_qcop->get_xstate)
224 return -ENOSYS;
225 ret = sb->s_qcop->get_xstate(sb, &fqs);
226 if (!ret && copy_to_user(addr, &fqs, sizeof(fqs)))
227 return -EFAULT;
228 return ret;
229 }
230
231 static int quota_setxquota(struct super_block *sb, int type, qid_t id,
232 void __user *addr)
233 {
234 struct fs_disk_quota fdq;
235
236 if (copy_from_user(&fdq, addr, sizeof(fdq)))
237 return -EFAULT;
238 if (!sb->s_qcop->set_dqblk)
239 return -ENOSYS;
240 return sb->s_qcop->set_dqblk(sb, type, id, &fdq);
241 }
242
243 static int quota_getxquota(struct super_block *sb, int type, qid_t id,
244 void __user *addr)
245 {
246 struct fs_disk_quota fdq;
247 int ret;
248
249 if (!sb->s_qcop->get_dqblk)
250 return -ENOSYS;
251 ret = sb->s_qcop->get_dqblk(sb, type, id, &fdq);
252 if (!ret && copy_to_user(addr, &fdq, sizeof(fdq)))
253 return -EFAULT;
254 return ret;
255 }
256
257 /* Copy parameters and call proper function */
258 static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id,
259 void __user *addr)
260 {
261 int ret;
262
263 if (type >= (XQM_COMMAND(cmd) ? XQM_MAXQUOTAS : MAXQUOTAS))
264 return -EINVAL;
265 if (!sb->s_qcop)
266 return -ENOSYS;
267
268 ret = check_quotactl_permission(sb, type, cmd, id);
269 if (ret < 0)
270 return ret;
271
272 switch (cmd) {
273 case Q_QUOTAON:
274 return quota_quotaon(sb, type, cmd, id, addr);
275 case Q_QUOTAOFF:
276 if (!sb->s_qcop->quota_off)
277 return -ENOSYS;
278 return sb->s_qcop->quota_off(sb, type, 0);
279 case Q_GETFMT:
280 return quota_getfmt(sb, type, addr);
281 case Q_GETINFO:
282 return quota_getinfo(sb, type, addr);
283 case Q_SETINFO:
284 return quota_setinfo(sb, type, addr);
285 case Q_GETQUOTA:
286 return quota_getquota(sb, type, id, addr);
287 case Q_SETQUOTA:
288 return quota_setquota(sb, type, id, addr);
289 case Q_SYNC:
290 if (!sb->s_qcop->quota_sync)
291 return -ENOSYS;
292 return sb->s_qcop->quota_sync(sb, type, 1);
293 case Q_XQUOTAON:
294 case Q_XQUOTAOFF:
295 case Q_XQUOTARM:
296 return quota_setxstate(sb, cmd, addr);
297 case Q_XGETQSTAT:
298 return quota_getxstate(sb, addr);
299 case Q_XSETQLIM:
300 return quota_setxquota(sb, type, id, addr);
301 case Q_XGETQUOTA:
302 return quota_getxquota(sb, type, id, addr);
303 case Q_XQUOTASYNC:
304 /* caller already holds s_umount */
305 if (sb->s_flags & MS_RDONLY)
306 return -EROFS;
307 writeback_inodes_sb(sb);
308 return 0;
309 default:
310 return -EINVAL;
311 }
312 }
313
314 /*
315 * look up a superblock on which quota ops will be performed
316 * - use the name of a block device to find the superblock thereon
317 */
318 static struct super_block *quotactl_block(const char __user *special)
319 {
320 #ifdef CONFIG_BLOCK
321 struct block_device *bdev;
322 struct super_block *sb;
323 char *tmp = getname(special);
324
325 if (IS_ERR(tmp))
326 return ERR_CAST(tmp);
327 bdev = lookup_bdev(tmp);
328 putname(tmp);
329 if (IS_ERR(bdev))
330 return ERR_CAST(bdev);
331 sb = get_super(bdev);
332 bdput(bdev);
333 if (!sb)
334 return ERR_PTR(-ENODEV);
335
336 return sb;
337 #else
338 return ERR_PTR(-ENODEV);
339 #endif
340 }
341
342 /*
343 * This is the system call interface. This communicates with
344 * the user-level programs. Currently this only supports diskquota
345 * calls. Maybe we need to add the process quotas etc. in the future,
346 * but we probably should use rlimits for that.
347 */
348 SYSCALL_DEFINE4(quotactl, unsigned int, cmd, const char __user *, special,
349 qid_t, id, void __user *, addr)
350 {
351 uint cmds, type;
352 struct super_block *sb = NULL;
353 int ret;
354
355 cmds = cmd >> SUBCMDSHIFT;
356 type = cmd & SUBCMDMASK;
357
358 /*
359 * As a special case Q_SYNC can be called without a specific device.
360 * It will iterate all superblocks that have quota enabled and call
361 * the sync action on each of them.
362 */
363 if (!special) {
364 if (cmds == Q_SYNC)
365 return quota_sync_all(type);
366 return -ENODEV;
367 }
368
369 sb = quotactl_block(special);
370 if (IS_ERR(sb))
371 return PTR_ERR(sb);
372
373 ret = do_quotactl(sb, type, cmds, id, addr);
374
375 drop_super(sb);
376 return ret;
377 }
This page took 0.038967 seconds and 5 git commands to generate.