Example #1
0
/*
 * This is the system call interface. This communicates with
 * the user-level programs. Currently this only supports diskquota
 * calls. Maybe we need to add the process quotas etc. in the future,
 * but we probably should use rlimits for that.
 */
SYSCALL_DEFINE4(quotactl, unsigned int, cmd, const char __user *, special,
		qid_t, id, void __user *, addr)
{
	uint cmds, type;
	struct super_block *sb = NULL;
	struct path path, *pathp = NULL;
	int ret;

	cmds = cmd >> SUBCMDSHIFT;
	type = cmd & SUBCMDMASK;

	/*
	 * As a special case Q_SYNC can be called without a specific device.
	 * It will iterate all superblocks that have quota enabled and call
	 * the sync action on each of them.
	 */
	if (!special) {
		if (cmds == Q_SYNC)
			return quota_sync_all(type);
		return -ENODEV;
	}

	/*
	 * Path for quotaon has to be resolved before grabbing superblock
	 * because that gets s_umount sem which is also possibly needed by path
	 * resolution (think about autofs) and thus deadlocks could arise.
	 */
	if (cmds == Q_QUOTAON) {
		ret = user_path_at(AT_FDCWD, addr, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, &path);
		if (ret)
			pathp = ERR_PTR(ret);
		else
			pathp = &path;
	}

	sb = quotactl_block(special, cmds);
	if (IS_ERR(sb)) {
		ret = PTR_ERR(sb);
		goto out;
	}

	ret = do_quotactl(sb, type, cmds, id, addr, pathp);

	drop_super(sb);
out:
	if (pathp && !IS_ERR(pathp))
		path_put(pathp);
	return ret;
}
Example #2
0
/*
 * This is the system call interface. This communicates with
 * the user-level programs. Currently this only supports diskquota
 * calls. Maybe we need to add the process quotas etc. in the future,
 * but we probably should use rlimits for that.
 */
asmlinkage long sys_quotactl(unsigned int cmd, const char *special, qid_t id, caddr_t addr)
{
    uint cmds, type;
    struct super_block *sb = NULL;
    int ret = -EINVAL;

    lock_kernel();
    cmds = cmd >> SUBCMDSHIFT;
    type = cmd & SUBCMDMASK;

#ifdef CONFIG_QIFACE_COMPAT
    if (cmds != Q_V1_GETSTATS && cmds != Q_V2_GETSTATS && IS_ERR(sb = resolve_dev(special))) {
        ret = PTR_ERR(sb);
        sb = NULL;
        goto out;
    }
    if (!NEW_COMMAND(cmds) && !XQM_COMMAND(cmds)) {
        if ((ret = check_compat_quotactl_valid(sb, type, cmds, id)) < 0)
            goto out;
        ret = do_compat_quotactl(sb, type, cmds, id, addr);
        goto out;
    }
#else
    if (IS_ERR(sb = resolve_dev(special))) {
        ret = PTR_ERR(sb);
        sb = NULL;
        goto out;
    }
#endif
    if ((ret = check_quotactl_valid(sb, type, cmds, id)) < 0)
        goto out;
    ret = do_quotactl(sb, type, cmds, id, addr);
out:
    if (sb)
        drop_super(sb);
    unlock_kernel();
    return ret;
}
Example #3
0
/*
 *  do_quotas()
 *	do quotactl commands
 */
static int do_quotas(const dev_info_t *dev, const char *name)
{
	int tested = 0, failed = 0, enosys = 0;
#if defined(Q_GETQUOTA)
	if (opt_do_run) {
		struct dqblk dqblk;

		do_quotactl(name, DO_Q_GETQUOTA, "Q_GETQUOTA",
			&tested, &failed, &enosys,
			QCMD(Q_GETQUOTA, USRQUOTA),
			dev->name, 0, (caddr_t)&dqblk);
	}
#endif
#if defined(Q_GETFMT)
	if (opt_do_run) {
		uint32_t format;

		do_quotactl(name, DO_Q_GETFMT, "Q_GETFMT",
			&tested, &failed, &enosys,
			QCMD(Q_GETFMT, USRQUOTA),
			dev->name, 0, (caddr_t)&format);
	}
#endif
#if defined(Q_GETINFO)
	if (opt_do_run) {
		struct dqinfo dqinfo;

		do_quotactl(name, DO_Q_GETINFO, "Q_GETINFO",
			&tested, &failed, &enosys,
			QCMD(Q_GETINFO, USRQUOTA),
			dev->name, 0, (caddr_t)&dqinfo);
	}
#endif
#if defined(Q_GETSTATS)
	/* Obsolete in recent kernels */
	if (opt_do_run) {
		struct dqstats dqstats;

		do_quotactl(name, DO_Q_GETSTATS, "Q_GETSTATS",
			&tested, &failed, &enosys,
			QCMD(Q_GETSTATS, USRQUOTA),
			dev->name, 0, (caddr_t)&dqstats);
	}
#endif
#if defined(Q_SYNC)
	if (opt_do_run) {
		do_quotactl(name, DO_Q_SYNC, "Q_SYNC",
			&tested, &failed, &enosys,
			QCMD(Q_SYNC, USRQUOTA),
			dev->name, 0, 0);
	}
#endif
	if (tested == 0) {
		pr_err(stderr, "%s: quotactl() failed, quota commands not available\n", name);
		return -1;
	}
	if (tested == enosys) {
		pr_err(stderr, "%s: quotactl() failed, not available on this kernel\n", name);
		return -1;
	}
	if (tested == failed) {
		pr_err(stderr, "%s: quotactl() failed, all quota commands failed (maybe privilege issues, use -v to see why)\n", name);
		return -1;
	}
	return 0;
}