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.
9 #include <linux/slab.h>
10 #include <asm/current.h>
11 #include <asm/uaccess.h>
12 #include <linux/kernel.h>
13 #include <linux/smp_lock.h>
14 #include <linux/quotaops.h>
15 #include <linux/quotacompat.h>
17 struct dqstats dqstats;
19 /* Check validity of quotactl */
20 static int check_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id)
22 if (type >= MAXQUOTAS)
24 if (!sb && cmd != Q_SYNC)
26 /* Is operation supported? */
27 if (sb && !sb->s_qcop)
34 if (!sb->s_qcop->quota_on)
38 if (!sb->s_qcop->quota_off)
42 if (!sb->s_qcop->set_info)
46 if (!sb->s_qcop->get_info)
50 if (!sb->s_qcop->set_dqblk)
54 if (!sb->s_qcop->get_dqblk)
58 if (sb && !sb->s_qcop->quota_sync)
64 if (!sb->s_qcop->set_xstate)
68 if (!sb->s_qcop->get_xstate)
72 if (!sb->s_qcop->set_xquota)
76 if (!sb->s_qcop->get_xquota)
83 /* Is quota turned on for commands which need it? */
91 if (!sb_has_quota_enabled(sb, type))
94 /* Check privileges */
95 if (cmd == Q_GETQUOTA || cmd == Q_XGETQUOTA) {
96 if (((type == USRQUOTA && current->euid != id) ||
97 (type == GRPQUOTA && !in_egroup_p(id))) &&
98 !capable(CAP_SYS_ADMIN))
101 else if (cmd != Q_GETFMT && cmd != Q_SYNC && cmd != Q_GETINFO && cmd != Q_XGETQSTAT)
102 if (!capable(CAP_SYS_ADMIN))
107 /* Resolve device pathname to superblock */
108 static struct super_block *resolve_dev(const char *path)
114 struct super_block *sb;
116 ret = user_path_walk(path, &nd);
120 dev = nd.dentry->d_inode->i_rdev;
121 mode = nd.dentry->d_inode->i_mode;
136 /* Copy parameters and call proper function */
137 static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id, caddr_t addr)
145 if (IS_ERR(pathname = getname(addr)))
146 return PTR_ERR(pathname);
147 ret = sb->s_qcop->quota_on(sb, type, id, pathname);
152 return sb->s_qcop->quota_off(sb, type);
157 fmt = sb_dqopt(sb)->info[type].dqi_format->qf_fmt_id;
158 if (copy_to_user(addr, &fmt, sizeof(fmt)))
163 struct if_dqinfo info;
165 if ((ret = sb->s_qcop->get_info(sb, type, &info)))
167 if (copy_to_user(addr, &info, sizeof(info)))
172 struct if_dqinfo info;
174 if (copy_from_user(&info, addr, sizeof(info)))
176 return sb->s_qcop->set_info(sb, type, &info);
181 if ((ret = sb->s_qcop->get_dqblk(sb, type, id, &idq)))
183 if (copy_to_user(addr, &idq, sizeof(idq)))
190 if (copy_from_user(&idq, addr, sizeof(idq)))
192 return sb->s_qcop->set_dqblk(sb, type, id, &idq);
196 return sb->s_qcop->quota_sync(sb, type);
197 sync_dquots_dev(NODEV, type);
204 if (copy_from_user(&flags, addr, sizeof(flags)))
206 return sb->s_qcop->set_xstate(sb, flags, cmd);
209 struct fs_quota_stat fqs;
211 if ((ret = sb->s_qcop->get_xstate(sb, &fqs)))
213 if (copy_to_user(addr, &fqs, sizeof(fqs)))
218 struct fs_disk_quota fdq;
220 if (copy_from_user(&fdq, addr, sizeof(fdq)))
222 return sb->s_qcop->set_xquota(sb, type, id, &fdq);
225 struct fs_disk_quota fdq;
227 if ((ret = sb->s_qcop->get_xquota(sb, type, id, &fdq)))
229 if (copy_to_user(addr, &fdq, sizeof(fdq)))
233 /* We never reach here unless validity check is broken */
240 static int check_compat_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id)
242 if (type >= MAXQUOTAS)
244 /* Is operation supported? */
245 /* sb==NULL for GETSTATS calls */
246 if (sb && !sb->s_qcop)
251 if (!sb->s_qcop->quota_on)
254 case Q_COMP_QUOTAOFF:
255 if (!sb->s_qcop->quota_off)
259 if (sb && !sb->s_qcop->quota_sync)
265 if (!sb->s_qcop->set_dqblk)
269 if (!sb->s_qcop->get_dqblk)
273 if (!sb->s_qcop->set_info)
277 return 0; /* GETSTATS need no other checks */
282 /* Is quota turned on for commands which need it? */
288 case Q_COMP_QUOTAOFF:
294 /* Q_V2_SETQLIM: collision with Q_V1_SETQLIM */
298 if (!sb_has_quota_enabled(sb, type))
301 if (cmd != Q_COMP_QUOTAON &&
302 cmd != Q_COMP_QUOTAOFF &&
303 cmd != Q_COMP_SYNC &&
304 sb_dqopt(sb)->info[type].dqi_format->qf_fmt_id != QFMT_VFS_OLD)
307 /* Check privileges */
308 if (cmd == Q_V1_GETQUOTA || cmd == Q_V2_GETQUOTA) {
309 if (((type == USRQUOTA && current->euid != id) ||
310 (type == GRPQUOTA && !in_egroup_p(id))) &&
311 !capable(CAP_SYS_ADMIN))
314 else if (cmd != Q_V1_GETSTATS && cmd != Q_V2_GETSTATS && cmd != Q_V2_GETINFO && cmd != Q_COMP_SYNC)
315 if (!capable(CAP_SYS_ADMIN))
320 static int v1_set_rsquash(struct super_block *sb, int type, int flag)
322 struct if_dqinfo info;
324 info.dqi_valid = IIF_FLAGS;
325 info.dqi_flags = flag ? V1_DQF_RSQUASH : 0;
326 return sb->s_qcop->set_info(sb, type, &info);
329 static int v1_get_dqblk(struct super_block *sb, int type, qid_t id, struct v1c_mem_dqblk *mdq)
334 if ((ret = sb->s_qcop->get_dqblk(sb, type, id, &idq)) < 0)
336 mdq->dqb_ihardlimit = idq.dqb_ihardlimit;
337 mdq->dqb_isoftlimit = idq.dqb_isoftlimit;
338 mdq->dqb_curinodes = idq.dqb_curinodes;
339 mdq->dqb_bhardlimit = idq.dqb_bhardlimit;
340 mdq->dqb_bsoftlimit = idq.dqb_bsoftlimit;
341 mdq->dqb_curblocks = toqb(idq.dqb_curspace);
342 mdq->dqb_itime = idq.dqb_itime;
343 mdq->dqb_btime = idq.dqb_btime;
344 if (id == 0) { /* Times for id 0 are in fact grace times */
345 struct if_dqinfo info;
347 if ((ret = sb->s_qcop->get_info(sb, type, &info)) < 0)
349 mdq->dqb_btime = info.dqi_bgrace;
350 mdq->dqb_itime = info.dqi_igrace;
355 static int v1_set_dqblk(struct super_block *sb, int type, int cmd, qid_t id, struct v1c_mem_dqblk *mdq)
361 if (cmd == Q_V1_SETQUOTA || cmd == Q_V1_SETQLIM) {
362 idq.dqb_ihardlimit = mdq->dqb_ihardlimit;
363 idq.dqb_isoftlimit = mdq->dqb_isoftlimit;
364 idq.dqb_bhardlimit = mdq->dqb_bhardlimit;
365 idq.dqb_bsoftlimit = mdq->dqb_bsoftlimit;
366 idq.dqb_valid |= QIF_LIMITS;
368 if (cmd == Q_V1_SETQUOTA || cmd == Q_V1_SETUSE) {
369 idq.dqb_curinodes = mdq->dqb_curinodes;
370 idq.dqb_curspace = ((qsize_t)mdq->dqb_curblocks) << QUOTABLOCK_BITS;
371 idq.dqb_valid |= QIF_USAGE;
373 ret = sb->s_qcop->set_dqblk(sb, type, id, &idq);
374 if (!ret && id == 0 && cmd == Q_V1_SETQUOTA) { /* Times for id 0 are in fact grace times */
375 struct if_dqinfo info;
377 info.dqi_bgrace = mdq->dqb_btime;
378 info.dqi_igrace = mdq->dqb_itime;
379 info.dqi_valid = IIF_BGRACE | IIF_IGRACE;
380 ret = sb->s_qcop->set_info(sb, type, &info);
385 static void v1_get_stats(struct v1c_dqstats *dst)
387 memcpy(dst, &dqstats, sizeof(dqstats));
390 /* Handle requests to old interface */
391 static int do_compat_quotactl(struct super_block *sb, int type, int cmd, qid_t id, caddr_t addr)
396 case Q_COMP_QUOTAON: {
399 if (IS_ERR(pathname = getname(addr)))
400 return PTR_ERR(pathname);
401 ret = sb->s_qcop->quota_on(sb, type, QFMT_VFS_OLD, pathname);
405 case Q_COMP_QUOTAOFF:
406 return sb->s_qcop->quota_off(sb, type);
409 return sb->s_qcop->quota_sync(sb, type);
410 sync_dquots_dev(NODEV, type);
415 if (copy_from_user(&flag, addr, sizeof(flag)))
417 return v1_set_rsquash(sb, type, flag);
419 case Q_V1_GETQUOTA: {
420 struct v1c_mem_dqblk mdq;
422 if ((ret = v1_get_dqblk(sb, type, id, &mdq)))
424 if (copy_to_user(addr, &mdq, sizeof(mdq)))
430 case Q_V1_SETQUOTA: {
431 struct v1c_mem_dqblk mdq;
433 if (copy_from_user(&mdq, addr, sizeof(mdq)))
435 return v1_set_dqblk(sb, type, cmd, id, &mdq);
437 case Q_V1_GETSTATS: {
438 struct v1c_dqstats dst;
441 if (copy_to_user(addr, &dst, sizeof(dst)))
450 /* Macros for short-circuiting the compatibility tests */
451 #define NEW_COMMAND(c) ((c) & (0x80 << 16))
452 #define XQM_COMMAND(c) (((c) & ('X' << 8)) == ('X' << 8))
455 * This is the system call interface. This communicates with
456 * the user-level programs. Currently this only supports diskquota
457 * calls. Maybe we need to add the process quotas etc. in the future,
458 * but we probably should use rlimits for that.
460 asmlinkage long sys_quotactl(unsigned int cmd, const char *special, qid_t id, caddr_t addr)
463 struct super_block *sb = NULL;
467 cmds = cmd >> SUBCMDSHIFT;
468 type = cmd & SUBCMDMASK;
470 if (cmds != Q_V1_GETSTATS && cmds != Q_V2_GETSTATS && IS_ERR(sb = resolve_dev(special))) {
475 if (!NEW_COMMAND(cmds) && !XQM_COMMAND(cmds)) {
476 if ((ret = check_compat_quotactl_valid(sb, type, cmds, id)) < 0)
478 ret = do_compat_quotactl(sb, type, cmds, id, addr);
481 if ((ret = check_quotactl_valid(sb, type, cmds, id)) < 0)
483 ret = do_quotactl(sb, type, cmds, id, addr);