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