static int v1_commit_dqblk(struct dquot *dquot)
{
	short type = dquot->dq_type;
	ssize_t ret;
	struct v1_disk_dqblk dqblk;

	v1_mem2disk_dqblk(&dqblk, &dquot->dq_dqb);
	if (dquot->dq_id == 0) {
		dqblk.dqb_btime = sb_dqopt(dquot->dq_sb)->info[type].dqi_bgrace;
		dqblk.dqb_itime = sb_dqopt(dquot->dq_sb)->info[type].dqi_igrace;
	}
	ret = 0;
	if (sb_dqopt(dquot->dq_sb)->files[type])
		ret = dquot->dq_sb->s_op->quota_write(dquot->dq_sb, type, (char *)&dqblk,
					sizeof(struct v1_disk_dqblk), v1_dqoff(dquot->dq_id));
	if (ret != sizeof(struct v1_disk_dqblk)) {
		printk(KERN_WARNING "VFS: dquota write failed on dev %s\n",
			dquot->dq_sb->s_id);
		if (ret >= 0)
			ret = -EIO;
		goto out;
	}
	ret = 0;

out:
	dqstats.writes++;

	return ret;
}
Esempio n. 2
0
static int v1_commit_dqblk(struct dquot *dquot)
{
	short type = dquot->dq_id.type;
	ssize_t ret;
	struct v1_disk_dqblk dqblk;

	v1_mem2disk_dqblk(&dqblk, &dquot->dq_dqb);
	if (((type == USRQUOTA) && uid_eq(dquot->dq_id.uid, GLOBAL_ROOT_UID)) ||
	    ((type == GRPQUOTA) && gid_eq(dquot->dq_id.gid, GLOBAL_ROOT_GID))) {
		dqblk.dqb_btime =
			sb_dqopt(dquot->dq_sb)->info[type].dqi_bgrace;
		dqblk.dqb_itime =
			sb_dqopt(dquot->dq_sb)->info[type].dqi_igrace;
	}
	ret = 0;
	if (sb_dqopt(dquot->dq_sb)->files[type])
		ret = dquot->dq_sb->s_op->quota_write(dquot->dq_sb, type,
			(char *)&dqblk, sizeof(struct v1_disk_dqblk),
			v1_dqoff(from_kqid(&init_user_ns, dquot->dq_id)));
	if (ret != sizeof(struct v1_disk_dqblk)) {
		quota_error(dquot->dq_sb, "dquota write failed");
		if (ret >= 0)
			ret = -EIO;
		goto out;
	}
	ret = 0;

out:
	dqstats_inc(DQST_WRITES);

	return ret;
}
Esempio n. 3
0
static int v1_commit_dqblk(struct dquot *dquot)
{
	short type = dquot->dq_type;
	ssize_t ret;
	struct v1_disk_dqblk dqblk;

	v1_mem2disk_dqblk(&dqblk, &dquot->dq_dqb);
	if (dquot->dq_id == 0) {
		dqblk.dqb_btime =
			sb_dqopt(dquot->dq_sb)->info[type].dqi_bgrace;
		dqblk.dqb_itime =
			sb_dqopt(dquot->dq_sb)->info[type].dqi_igrace;
	}
	ret = 0;
	if (sb_dqopt(dquot->dq_sb)->files[type])
		ret = dquot->dq_sb->s_op->quota_write(dquot->dq_sb, type,
			(char *)&dqblk, sizeof(struct v1_disk_dqblk),
			v1_dqoff(dquot->dq_id));
	if (ret != sizeof(struct v1_disk_dqblk)) {
		quota_error(dquot->dq_sb, "dquota write failed");
		if (ret >= 0)
			ret = -EIO;
		goto out;
	}
	ret = 0;

out:
	dqstats_inc(DQST_WRITES);

	return ret;
}
Esempio n. 4
0
static int quota_getfmt(struct super_block *sb, int type, void __user *addr)
{
	__u32 fmt;

	down_read(&sb_dqopt(sb)->dqptr_sem);
	if (!sb_has_quota_active(sb, type)) {
		up_read(&sb_dqopt(sb)->dqptr_sem);
		return -ESRCH;
	}
	fmt = sb_dqopt(sb)->info[type].dqi_format->qf_fmt_id;
	up_read(&sb_dqopt(sb)->dqptr_sem);
	if (copy_to_user(addr, &fmt, sizeof(fmt)))
		return -EFAULT;
	return 0;
}
Esempio n. 5
0
File: quota.c Progetto: 3null/linux
static int quota_getfmt(struct super_block *sb, int type, void __user *addr)
{
	__u32 fmt;

	mutex_lock(&sb_dqopt(sb)->dqonoff_mutex);
	if (!sb_has_quota_active(sb, type)) {
		mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
		return -ESRCH;
	}
	fmt = sb_dqopt(sb)->info[type].dqi_format->qf_fmt_id;
	mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex);
	if (copy_to_user(addr, &fmt, sizeof(fmt)))
		return -EFAULT;
	return 0;
}
Esempio n. 6
0
static int v2_get_info(struct super_block *sb, int type, struct v2c_mem_dqinfo *oinfo)
{
    struct if_dqinfo info;
    int ret;

    if ((ret = sb->s_qcop->get_info(sb, type, &info)) < 0)
        return ret;
    oinfo->dqi_bgrace = info.dqi_bgrace;
    oinfo->dqi_igrace = info.dqi_igrace;
    oinfo->dqi_flags = info.dqi_flags;
    oinfo->dqi_blocks = sb_dqopt(sb)->info[type].u.v2_i.dqi_blocks;
    oinfo->dqi_free_blk = sb_dqopt(sb)->info[type].u.v2_i.dqi_free_blk;
    oinfo->dqi_free_entry = sb_dqopt(sb)->info[type].u.v2_i.dqi_free_entry;
    return 0;
}
Esempio n. 7
0
static int v1_read_dqblk(struct dquot *dquot)
{
	int type = dquot->dq_id.type;
	struct v1_disk_dqblk dqblk;
	struct quota_info *dqopt = sb_dqopt(dquot->dq_sb);

	if (!dqopt->files[type])
		return -EINVAL;

	/* Set structure to 0s in case read fails/is after end of file */
	memset(&dqblk, 0, sizeof(struct v1_disk_dqblk));
	dquot->dq_sb->s_op->quota_read(dquot->dq_sb, type, (char *)&dqblk,
			sizeof(struct v1_disk_dqblk),
			v1_dqoff(from_kqid(&init_user_ns, dquot->dq_id)));

	v1_disk2mem_dqblk(&dquot->dq_dqb, &dqblk);
	if (dquot->dq_dqb.dqb_bhardlimit == 0 &&
	    dquot->dq_dqb.dqb_bsoftlimit == 0 &&
	    dquot->dq_dqb.dqb_ihardlimit == 0 &&
	    dquot->dq_dqb.dqb_isoftlimit == 0)
		set_bit(DQ_FAKE_B, &dquot->dq_flags);
	dqstats_inc(DQST_READS);

	return 0;
}
Esempio n. 8
0
/* Write to quotafile */
static ssize_t ext2_quota_write(struct super_block *sb, int type,
				const char *data, size_t len, loff_t off)
{
	struct inode *inode = sb_dqopt(sb)->files[type];
	sector_t blk = off >> EXT2_BLOCK_SIZE_BITS(sb);
	int err = 0;
	int offset = off & (sb->s_blocksize - 1);
	int tocopy;
	size_t towrite = len;
	struct buffer_head tmp_bh;
	struct buffer_head *bh;

	mutex_lock_nested(&inode->i_mutex, I_MUTEX_QUOTA);
	while (towrite > 0) {
		tocopy = sb->s_blocksize - offset < towrite ?
				sb->s_blocksize - offset : towrite;

		tmp_bh.b_state = 0;
		err = ext2_get_block(inode, blk, &tmp_bh, 1);
		if (err < 0)
			goto out;
		if (offset || tocopy != EXT2_BLOCK_SIZE(sb))
			bh = sb_bread(sb, tmp_bh.b_blocknr);
		else
			bh = sb_getblk(sb, tmp_bh.b_blocknr);
		if (!bh) {
			err = -EIO;
			goto out;
		}
		lock_buffer(bh);
		memcpy(bh->b_data+offset, data, tocopy);
		flush_dcache_page(bh->b_page);
		set_buffer_uptodate(bh);
		mark_buffer_dirty(bh);
		unlock_buffer(bh);
		brelse(bh);
		offset = 0;
		towrite -= tocopy;
		data += tocopy;
		blk++;
	}
out:
	if (len == towrite) {
		mutex_unlock(&inode->i_mutex);
		return err;
	}
	if (inode->i_size < off+len-towrite)
		i_size_write(inode, off+len-towrite);
	inode->i_version++;
	inode->i_mtime = inode->i_ctime = CURRENT_TIME;
	mark_inode_dirty(inode);
	mutex_unlock(&inode->i_mutex);
	return len - towrite;
}
Esempio n. 9
0
/* Write to quotafile */
static ssize_t ufs_quota_write(struct super_block *sb, int type,
                               const char *data, size_t len, loff_t off)
{
    struct inode *inode = sb_dqopt(sb)->files[type];
    sector_t blk = off >> sb->s_blocksize_bits;
    int err = 0;
    int offset = off & (sb->s_blocksize - 1);
    int tocopy;
    size_t towrite = len;
    struct buffer_head *bh;

    mutex_lock_nested(&inode->i_mutex, I_MUTEX_QUOTA);
    while (towrite > 0) {
        tocopy = sb->s_blocksize - offset < towrite ?
                 sb->s_blocksize - offset : towrite;

        bh = ufs_bread(inode, blk, 1, &err);
        if (!bh)
            goto out;
        lock_buffer(bh);
        memcpy(bh->b_data+offset, data, tocopy);
        flush_dcache_page(bh->b_page);
        set_buffer_uptodate(bh);
        mark_buffer_dirty(bh);
        unlock_buffer(bh);
        brelse(bh);
        offset = 0;
        towrite -= tocopy;
        data += tocopy;
        blk++;
    }
out:
    if (len == towrite) {
        mutex_unlock(&inode->i_mutex);
        return err;
    }
    if (inode->i_size < off+len-towrite)
        i_size_write(inode, off+len-towrite);
    inode->i_version++;
    inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;
    mark_inode_dirty(inode);
    mutex_unlock(&inode->i_mutex);
    return len - towrite;
}
Esempio n. 10
0
/* Read data from quotafile - avoid pagecache and such because we cannot afford
 * acquiring the locks... As quota files are never truncated and quota code
 * itself serializes the operations (and noone else should touch the files)
 * we don't have to be afraid of races */
static ssize_t ext2_quota_read(struct super_block *sb, int type, char *data,
			       size_t len, loff_t off)
{
	struct inode *inode = sb_dqopt(sb)->files[type];
	sector_t blk = off >> EXT2_BLOCK_SIZE_BITS(sb);
	int err = 0;
	int offset = off & (sb->s_blocksize - 1);
	int tocopy;
	size_t toread;
	struct buffer_head tmp_bh;
	struct buffer_head *bh;
	loff_t i_size = i_size_read(inode);

	if (off > i_size)
		return 0;
	if (off+len > i_size)
		len = i_size-off;
	toread = len;
	while (toread > 0) {
		tocopy = sb->s_blocksize - offset < toread ?
				sb->s_blocksize - offset : toread;

		tmp_bh.b_state = 0;
		tmp_bh.b_size = sb->s_blocksize;
		err = ext2_get_block(inode, blk, &tmp_bh, 0);
		if (err < 0)
			return err;
		if (!buffer_mapped(&tmp_bh))	/* A hole? */
			memset(data, 0, tocopy);
		else {
			bh = sb_bread(sb, tmp_bh.b_blocknr);
			if (!bh)
				return -EIO;
			memcpy(data, bh->b_data+offset, tocopy);
			brelse(bh);
		}
		offset = 0;
		toread -= tocopy;
		data += tocopy;
		blk++;
	}
	return len;
}
Esempio n. 11
0
static int v1_read_dqblk(struct dquot *dquot)
{
	int type = dquot->dq_type;
	struct v1_disk_dqblk dqblk;

	if (!sb_dqopt(dquot->dq_sb)->files[type])
		return -EINVAL;

	/* Set structure to 0s in case read fails/is after end of file */
	memset(&dqblk, 0, sizeof(struct v1_disk_dqblk));
	dquot->dq_sb->s_op->quota_read(dquot->dq_sb, type, (char *)&dqblk, sizeof(struct v1_disk_dqblk), v1_dqoff(dquot->dq_id));

	v1_disk2mem_dqblk(&dquot->dq_dqb, &dqblk);
	if (dquot->dq_dqb.dqb_bhardlimit == 0 && dquot->dq_dqb.dqb_bsoftlimit == 0 &&
	    dquot->dq_dqb.dqb_ihardlimit == 0 && dquot->dq_dqb.dqb_isoftlimit == 0)
		set_bit(DQ_FAKE_B, &dquot->dq_flags);
	dqstats.reads++;

	return 0;
}
Esempio n. 12
0
File: super.c Progetto: mdamt/linux
static int ext2_quota_off(struct super_block *sb, int type)
{
	struct inode *inode = sb_dqopt(sb)->files[type];
	int err;

	if (!inode || !igrab(inode))
		goto out;

	err = dquot_quota_off(sb, type);
	if (err)
		goto out_put;

	inode_lock(inode);
	EXT2_I(inode)->i_flags &= ~(EXT2_NOATIME_FL | EXT2_IMMUTABLE_FL);
	inode_set_flags(inode, 0, S_NOATIME | S_IMMUTABLE);
	inode_unlock(inode);
	mark_inode_dirty(inode);
out_put:
	iput(inode);
	return err;
out:
	return dquot_quota_off(sb, type);
}
Esempio n. 13
0
/* Read data from quotafile - avoid pagecache and such because we cannot afford
 * acquiring the locks... As quota files are never truncated and quota code
 * itself serializes the operations (and noone else should touch the files)
 * we don't have to be afraid of races */
static ssize_t ufs_quota_read(struct super_block *sb, int type, char *data,
                              size_t len, loff_t off)
{
    struct inode *inode = sb_dqopt(sb)->files[type];
    sector_t blk = off >> sb->s_blocksize_bits;
    int err = 0;
    int offset = off & (sb->s_blocksize - 1);
    int tocopy;
    size_t toread;
    struct buffer_head *bh;
    loff_t i_size = i_size_read(inode);

    if (off > i_size)
        return 0;
    if (off+len > i_size)
        len = i_size-off;
    toread = len;
    while (toread > 0) {
        tocopy = sb->s_blocksize - offset < toread ?
                 sb->s_blocksize - offset : toread;

        bh = ufs_bread(inode, blk, 0, &err);
        if (err)
            return err;
        if (!bh)	/* A hole? */
            memset(data, 0, tocopy);
        else {
            memcpy(data, bh->b_data+offset, tocopy);
            brelse(bh);
        }
        offset = 0;
        toread -= tocopy;
        data += tocopy;
        blk++;
    }
    return len;
}
Esempio n. 14
0
static int check_compat_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id)
{
    if (type >= MAXQUOTAS)
        return -EINVAL;
    /* Is operation supported? */
    /* sb==NULL for GETSTATS calls */
    if (sb && !sb->s_qcop)
        return -ENOSYS;

    switch (cmd) {
    case Q_COMP_QUOTAON:
        if (!sb->s_qcop->quota_on)
            return -ENOSYS;
        break;
    case Q_COMP_QUOTAOFF:
        if (!sb->s_qcop->quota_off)
            return -ENOSYS;
        break;
    case Q_COMP_SYNC:
        if (!sb->s_qcop->quota_sync)
            return -ENOSYS;
        break;
#ifdef CONFIG_QIFACE_V2
    case Q_V2_SETFLAGS:
    case Q_V2_SETGRACE:
    case Q_V2_SETINFO:
        if (!sb->s_qcop->set_info)
            return -ENOSYS;
        break;
    case Q_V2_GETINFO:
        if (!sb->s_qcop->get_info)
            return -ENOSYS;
        break;
    case Q_V2_SETQLIM:
    case Q_V2_SETUSE:
    case Q_V2_SETQUOTA:
        if (!sb->s_qcop->set_dqblk)
            return -ENOSYS;
        break;
    case Q_V2_GETQUOTA:
        if (!sb->s_qcop->get_dqblk)
            return -ENOSYS;
        break;
    case Q_V2_GETSTATS:
        return 0;	/* GETSTATS need no other checks */
#endif
#ifdef CONFIG_QIFACE_V1
    case Q_V1_SETQLIM:
    case Q_V1_SETUSE:
    case Q_V1_SETQUOTA:
        if (!sb->s_qcop->set_dqblk)
            return -ENOSYS;
        break;
    case Q_V1_GETQUOTA:
        if (!sb->s_qcop->get_dqblk)
            return -ENOSYS;
        break;
    case Q_V1_RSQUASH:
        if (!sb->s_qcop->set_info)
            return -ENOSYS;
        break;
    case Q_V1_GETSTATS:
        return 0;	/* GETSTATS need no other checks */
#endif
    default:
        return -EINVAL;
    }

    /* Is quota turned on for commands which need it? */
    switch (cmd) {
    case Q_V2_SETFLAGS:
    case Q_V2_SETGRACE:
    case Q_V2_SETINFO:
    case Q_V2_GETINFO:
    case Q_COMP_QUOTAOFF:
    case Q_V1_RSQUASH:
    case Q_V1_SETQUOTA:
    case Q_V1_SETQLIM:
    case Q_V1_SETUSE:
    case Q_V2_SETQUOTA:
    /* Q_V2_SETQLIM: collision with Q_V1_SETQLIM */
    case Q_V2_SETUSE:
    case Q_V1_GETQUOTA:
    case Q_V2_GETQUOTA:
        if (!sb_has_quota_enabled(sb, type))
            return -ESRCH;
    }
#ifdef CONFIG_QIFACE_V1
    if (cmd != Q_COMP_QUOTAON && cmd != Q_COMP_QUOTAOFF && cmd != Q_COMP_SYNC && sb_dqopt(sb)->info[type].dqi_format->qf_fmt_id != QFMT_VFS_OLD)
#else
    if (cmd != Q_COMP_QUOTAON && cmd != Q_COMP_QUOTAOFF && cmd != Q_COMP_SYNC && sb_dqopt(sb)->info[type].dqi_format->qf_fmt_id != QFMT_VFS_V0)
#endif
        return -ESRCH;

    /* Check privileges */
    if (cmd == Q_V1_GETQUOTA || cmd == Q_V2_GETQUOTA) {
        if (((type == USRQUOTA && current->euid != id) ||
                (type == GRPQUOTA && !in_egroup_p(id))) &&
                !capable(CAP_SYS_ADMIN))
            return -EPERM;
    }
    else if (cmd != Q_V1_GETSTATS && cmd != Q_V2_GETSTATS && cmd != Q_V2_GETINFO && cmd != Q_COMP_SYNC)
        if (!capable(CAP_SYS_ADMIN))
            return -EPERM;
    return 0;
}
Esempio n. 15
0
/* Copy parameters and call proper function */
static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id, caddr_t addr)
{
    int ret;

    switch (cmd) {
    case Q_QUOTAON: {
        char *pathname;

        if (IS_ERR(pathname = getname(addr)))
            return PTR_ERR(pathname);
        ret = sb->s_qcop->quota_on(sb, type, id, pathname);
        putname(pathname);
        return ret;
    }
    case Q_QUOTAOFF:
        return sb->s_qcop->quota_off(sb, type);

    case Q_GETFMT: {
        __u32 fmt;

        fmt = sb_dqopt(sb)->info[type].dqi_format->qf_fmt_id;
        if (copy_to_user(addr, &fmt, sizeof(fmt)))
            return -EFAULT;
        return 0;
    }
    case Q_GETINFO: {
        struct if_dqinfo info;

        if ((ret = sb->s_qcop->get_info(sb, type, &info)))
            return ret;
        if (copy_to_user(addr, &info, sizeof(info)))
            return -EFAULT;
        return 0;
    }
    case Q_SETINFO: {
        struct if_dqinfo info;

        if (copy_from_user(&info, addr, sizeof(info)))
            return -EFAULT;
        return sb->s_qcop->set_info(sb, type, &info);
    }
    case Q_GETQUOTA: {
        struct if_dqblk idq;

        if ((ret = sb->s_qcop->get_dqblk(sb, type, id, &idq)))
            return ret;
        if (copy_to_user(addr, &idq, sizeof(idq)))
            return -EFAULT;
        return 0;
    }
    case Q_SETQUOTA: {
        struct if_dqblk idq;

        if (copy_from_user(&idq, addr, sizeof(idq)))
            return -EFAULT;
        return sb->s_qcop->set_dqblk(sb, type, id, &idq);
    }
    case Q_SYNC:
        return sb->s_qcop->quota_sync(sb, type);

    case Q_XQUOTAON:
    case Q_XQUOTAOFF:
    case Q_XQUOTARM: {
        __u32 flags;

        if (copy_from_user(&flags, addr, sizeof(flags)))
            return -EFAULT;
        return sb->s_qcop->set_xstate(sb, flags, cmd);
    }
    case Q_XGETQSTAT: {
        struct fs_quota_stat fqs;

        if ((ret = sb->s_qcop->get_xstate(sb, &fqs)))
            return ret;
        if (copy_to_user(addr, &fqs, sizeof(fqs)))
            return -EFAULT;
        return 0;
    }
    case Q_XSETQLIM: {
        struct fs_disk_quota fdq;

        if (copy_from_user(&fdq, addr, sizeof(fdq)))
            return -EFAULT;
        return sb->s_qcop->set_xquota(sb, type, id, &fdq);
    }
    case Q_XGETQUOTA: {
        struct fs_disk_quota fdq;

        if ((ret = sb->s_qcop->get_xquota(sb, type, id, &fdq)))
            return ret;
        if (copy_to_user(addr, &fdq, sizeof(fdq)))
            return -EFAULT;
        return 0;
    }
    /* We never reach here unless validity check is broken */
    default:
        BUG();
    }
    return 0;
}