OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [fs/] [quota.c] - Diff between revs 1275 and 1765

Only display areas with differences | Details | Blame | View Log

Rev 1275 Rev 1765
/*
/*
 * Quota code necessary even when VFS quota support is not compiled
 * Quota code necessary even when VFS quota support is not compiled
 * into the kernel.  The interesting stuff is over in dquot.c, here
 * into the kernel.  The interesting stuff is over in dquot.c, here
 * we have symbols for initial quotactl(2) handling, the sysctl(2)
 * we have symbols for initial quotactl(2) handling, the sysctl(2)
 * variables, etc - things needed even when quota support disabled.
 * variables, etc - things needed even when quota support disabled.
 */
 */
 
 
#include <linux/fs.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/slab.h>
#include <asm/current.h>
#include <asm/current.h>
#include <asm/uaccess.h>
#include <asm/uaccess.h>
#include <linux/kernel.h>
#include <linux/kernel.h>
#include <linux/smp_lock.h>
#include <linux/smp_lock.h>
#include <linux/quotaops.h>
#include <linux/quotaops.h>
#include <linux/quotacompat.h>
#include <linux/quotacompat.h>
 
 
struct dqstats dqstats;
struct dqstats dqstats;
 
 
/* Check validity of quotactl */
/* Check validity of quotactl */
static int check_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id)
static int check_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id)
{
{
        if (type >= MAXQUOTAS)
        if (type >= MAXQUOTAS)
                return -EINVAL;
                return -EINVAL;
        if (!sb && cmd != Q_SYNC)
        if (!sb && cmd != Q_SYNC)
                return -ENODEV;
                return -ENODEV;
        /* Is operation supported? */
        /* Is operation supported? */
        if (sb && !sb->s_qcop)
        if (sb && !sb->s_qcop)
                return -ENOSYS;
                return -ENOSYS;
 
 
        switch (cmd) {
        switch (cmd) {
                case Q_GETFMT:
                case Q_GETFMT:
                        break;
                        break;
                case Q_QUOTAON:
                case Q_QUOTAON:
                        if (!sb->s_qcop->quota_on)
                        if (!sb->s_qcop->quota_on)
                                return -ENOSYS;
                                return -ENOSYS;
                        break;
                        break;
                case Q_QUOTAOFF:
                case Q_QUOTAOFF:
                        if (!sb->s_qcop->quota_off)
                        if (!sb->s_qcop->quota_off)
                                return -ENOSYS;
                                return -ENOSYS;
                        break;
                        break;
                case Q_SETINFO:
                case Q_SETINFO:
                        if (!sb->s_qcop->set_info)
                        if (!sb->s_qcop->set_info)
                                return -ENOSYS;
                                return -ENOSYS;
                        break;
                        break;
                case Q_GETINFO:
                case Q_GETINFO:
                        if (!sb->s_qcop->get_info)
                        if (!sb->s_qcop->get_info)
                                return -ENOSYS;
                                return -ENOSYS;
                        break;
                        break;
                case Q_SETQUOTA:
                case Q_SETQUOTA:
                        if (!sb->s_qcop->set_dqblk)
                        if (!sb->s_qcop->set_dqblk)
                                return -ENOSYS;
                                return -ENOSYS;
                        break;
                        break;
                case Q_GETQUOTA:
                case Q_GETQUOTA:
                        if (!sb->s_qcop->get_dqblk)
                        if (!sb->s_qcop->get_dqblk)
                                return -ENOSYS;
                                return -ENOSYS;
                        break;
                        break;
                case Q_SYNC:
                case Q_SYNC:
                        if (sb && !sb->s_qcop->quota_sync)
                        if (sb && !sb->s_qcop->quota_sync)
                                return -ENOSYS;
                                return -ENOSYS;
                        break;
                        break;
                case Q_XQUOTAON:
                case Q_XQUOTAON:
                case Q_XQUOTAOFF:
                case Q_XQUOTAOFF:
                case Q_XQUOTARM:
                case Q_XQUOTARM:
                        if (!sb->s_qcop->set_xstate)
                        if (!sb->s_qcop->set_xstate)
                                return -ENOSYS;
                                return -ENOSYS;
                        break;
                        break;
                case Q_XGETQSTAT:
                case Q_XGETQSTAT:
                        if (!sb->s_qcop->get_xstate)
                        if (!sb->s_qcop->get_xstate)
                                return -ENOSYS;
                                return -ENOSYS;
                        break;
                        break;
                case Q_XSETQLIM:
                case Q_XSETQLIM:
                        if (!sb->s_qcop->set_xquota)
                        if (!sb->s_qcop->set_xquota)
                                return -ENOSYS;
                                return -ENOSYS;
                        break;
                        break;
                case Q_XGETQUOTA:
                case Q_XGETQUOTA:
                        if (!sb->s_qcop->get_xquota)
                        if (!sb->s_qcop->get_xquota)
                                return -ENOSYS;
                                return -ENOSYS;
                        break;
                        break;
                default:
                default:
                        return -EINVAL;
                        return -EINVAL;
        }
        }
 
 
        /* Is quota turned on for commands which need it? */
        /* Is quota turned on for commands which need it? */
        switch (cmd) {
        switch (cmd) {
                case Q_GETFMT:
                case Q_GETFMT:
                case Q_GETINFO:
                case Q_GETINFO:
                case Q_QUOTAOFF:
                case Q_QUOTAOFF:
                case Q_SETINFO:
                case Q_SETINFO:
                case Q_SETQUOTA:
                case Q_SETQUOTA:
                case Q_GETQUOTA:
                case Q_GETQUOTA:
                        if (!sb_has_quota_enabled(sb, type))
                        if (!sb_has_quota_enabled(sb, type))
                                return -ESRCH;
                                return -ESRCH;
        }
        }
        /* Check privileges */
        /* Check privileges */
        if (cmd == Q_GETQUOTA || cmd == Q_XGETQUOTA) {
        if (cmd == Q_GETQUOTA || cmd == Q_XGETQUOTA) {
                if (((type == USRQUOTA && current->euid != id) ||
                if (((type == USRQUOTA && current->euid != id) ||
                     (type == GRPQUOTA && !in_egroup_p(id))) &&
                     (type == GRPQUOTA && !in_egroup_p(id))) &&
                    !capable(CAP_SYS_ADMIN))
                    !capable(CAP_SYS_ADMIN))
                        return -EPERM;
                        return -EPERM;
        }
        }
        else if (cmd != Q_GETFMT && cmd != Q_SYNC && cmd != Q_GETINFO && cmd != Q_XGETQSTAT)
        else if (cmd != Q_GETFMT && cmd != Q_SYNC && cmd != Q_GETINFO && cmd != Q_XGETQSTAT)
                if (!capable(CAP_SYS_ADMIN))
                if (!capable(CAP_SYS_ADMIN))
                        return -EPERM;
                        return -EPERM;
        return 0;
        return 0;
}
}
 
 
/* Resolve device pathname to superblock */
/* Resolve device pathname to superblock */
static struct super_block *resolve_dev(const char *path)
static struct super_block *resolve_dev(const char *path)
{
{
        int ret;
        int ret;
        mode_t mode;
        mode_t mode;
        struct nameidata nd;
        struct nameidata nd;
        kdev_t dev;
        kdev_t dev;
        struct super_block *sb;
        struct super_block *sb;
 
 
        ret = user_path_walk(path, &nd);
        ret = user_path_walk(path, &nd);
        if (ret)
        if (ret)
                goto out;
                goto out;
 
 
        dev = nd.dentry->d_inode->i_rdev;
        dev = nd.dentry->d_inode->i_rdev;
        mode = nd.dentry->d_inode->i_mode;
        mode = nd.dentry->d_inode->i_mode;
        path_release(&nd);
        path_release(&nd);
 
 
        ret = -ENOTBLK;
        ret = -ENOTBLK;
        if (!S_ISBLK(mode))
        if (!S_ISBLK(mode))
                goto out;
                goto out;
        ret = -ENODEV;
        ret = -ENODEV;
        sb = get_super(dev);
        sb = get_super(dev);
        if (!sb)
        if (!sb)
                goto out;
                goto out;
        return sb;
        return sb;
out:
out:
        return ERR_PTR(ret);
        return ERR_PTR(ret);
}
}
 
 
/* Copy parameters and call proper function */
/* Copy parameters and call proper function */
static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id, caddr_t addr)
static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id, caddr_t addr)
{
{
        int ret;
        int ret;
 
 
        switch (cmd) {
        switch (cmd) {
                case Q_QUOTAON: {
                case Q_QUOTAON: {
                        char *pathname;
                        char *pathname;
 
 
                        if (IS_ERR(pathname = getname(addr)))
                        if (IS_ERR(pathname = getname(addr)))
                                return PTR_ERR(pathname);
                                return PTR_ERR(pathname);
                        ret = sb->s_qcop->quota_on(sb, type, id, pathname);
                        ret = sb->s_qcop->quota_on(sb, type, id, pathname);
                        putname(pathname);
                        putname(pathname);
                        return ret;
                        return ret;
                }
                }
                case Q_QUOTAOFF:
                case Q_QUOTAOFF:
                        return sb->s_qcop->quota_off(sb, type);
                        return sb->s_qcop->quota_off(sb, type);
 
 
                case Q_GETFMT: {
                case Q_GETFMT: {
                        __u32 fmt;
                        __u32 fmt;
 
 
                        fmt = sb_dqopt(sb)->info[type].dqi_format->qf_fmt_id;
                        fmt = sb_dqopt(sb)->info[type].dqi_format->qf_fmt_id;
                        if (copy_to_user(addr, &fmt, sizeof(fmt)))
                        if (copy_to_user(addr, &fmt, sizeof(fmt)))
                                return -EFAULT;
                                return -EFAULT;
                        return 0;
                        return 0;
                }
                }
                case Q_GETINFO: {
                case Q_GETINFO: {
                        struct if_dqinfo info;
                        struct if_dqinfo info;
 
 
                        if ((ret = sb->s_qcop->get_info(sb, type, &info)))
                        if ((ret = sb->s_qcop->get_info(sb, type, &info)))
                                return ret;
                                return ret;
                        if (copy_to_user(addr, &info, sizeof(info)))
                        if (copy_to_user(addr, &info, sizeof(info)))
                                return -EFAULT;
                                return -EFAULT;
                        return 0;
                        return 0;
                }
                }
                case Q_SETINFO: {
                case Q_SETINFO: {
                        struct if_dqinfo info;
                        struct if_dqinfo info;
 
 
                        if (copy_from_user(&info, addr, sizeof(info)))
                        if (copy_from_user(&info, addr, sizeof(info)))
                                return -EFAULT;
                                return -EFAULT;
                        return sb->s_qcop->set_info(sb, type, &info);
                        return sb->s_qcop->set_info(sb, type, &info);
                }
                }
                case Q_GETQUOTA: {
                case Q_GETQUOTA: {
                        struct if_dqblk idq;
                        struct if_dqblk idq;
 
 
                        if ((ret = sb->s_qcop->get_dqblk(sb, type, id, &idq)))
                        if ((ret = sb->s_qcop->get_dqblk(sb, type, id, &idq)))
                                return ret;
                                return ret;
                        if (copy_to_user(addr, &idq, sizeof(idq)))
                        if (copy_to_user(addr, &idq, sizeof(idq)))
                                return -EFAULT;
                                return -EFAULT;
                        return 0;
                        return 0;
                }
                }
                case Q_SETQUOTA: {
                case Q_SETQUOTA: {
                        struct if_dqblk idq;
                        struct if_dqblk idq;
 
 
                        if (copy_from_user(&idq, addr, sizeof(idq)))
                        if (copy_from_user(&idq, addr, sizeof(idq)))
                                return -EFAULT;
                                return -EFAULT;
                        return sb->s_qcop->set_dqblk(sb, type, id, &idq);
                        return sb->s_qcop->set_dqblk(sb, type, id, &idq);
                }
                }
                case Q_SYNC:
                case Q_SYNC:
                        if (sb)
                        if (sb)
                                return sb->s_qcop->quota_sync(sb, type);
                                return sb->s_qcop->quota_sync(sb, type);
                        sync_dquots_dev(NODEV, type);
                        sync_dquots_dev(NODEV, type);
                        return 0;
                        return 0;
                case Q_XQUOTAON:
                case Q_XQUOTAON:
                case Q_XQUOTAOFF:
                case Q_XQUOTAOFF:
                case Q_XQUOTARM: {
                case Q_XQUOTARM: {
                        __u32 flags;
                        __u32 flags;
 
 
                        if (copy_from_user(&flags, addr, sizeof(flags)))
                        if (copy_from_user(&flags, addr, sizeof(flags)))
                                return -EFAULT;
                                return -EFAULT;
                        return sb->s_qcop->set_xstate(sb, flags, cmd);
                        return sb->s_qcop->set_xstate(sb, flags, cmd);
                }
                }
                case Q_XGETQSTAT: {
                case Q_XGETQSTAT: {
                        struct fs_quota_stat fqs;
                        struct fs_quota_stat fqs;
 
 
                        if ((ret = sb->s_qcop->get_xstate(sb, &fqs)))
                        if ((ret = sb->s_qcop->get_xstate(sb, &fqs)))
                                return ret;
                                return ret;
                        if (copy_to_user(addr, &fqs, sizeof(fqs)))
                        if (copy_to_user(addr, &fqs, sizeof(fqs)))
                                return -EFAULT;
                                return -EFAULT;
                        return 0;
                        return 0;
                }
                }
                case Q_XSETQLIM: {
                case Q_XSETQLIM: {
                        struct fs_disk_quota fdq;
                        struct fs_disk_quota fdq;
 
 
                        if (copy_from_user(&fdq, addr, sizeof(fdq)))
                        if (copy_from_user(&fdq, addr, sizeof(fdq)))
                                return -EFAULT;
                                return -EFAULT;
                       return sb->s_qcop->set_xquota(sb, type, id, &fdq);
                       return sb->s_qcop->set_xquota(sb, type, id, &fdq);
                }
                }
                case Q_XGETQUOTA: {
                case Q_XGETQUOTA: {
                        struct fs_disk_quota fdq;
                        struct fs_disk_quota fdq;
 
 
                        if ((ret = sb->s_qcop->get_xquota(sb, type, id, &fdq)))
                        if ((ret = sb->s_qcop->get_xquota(sb, type, id, &fdq)))
                                return ret;
                                return ret;
                        if (copy_to_user(addr, &fdq, sizeof(fdq)))
                        if (copy_to_user(addr, &fdq, sizeof(fdq)))
                                return -EFAULT;
                                return -EFAULT;
                        return 0;
                        return 0;
                }
                }
                /* We never reach here unless validity check is broken */
                /* We never reach here unless validity check is broken */
                default:
                default:
                        BUG();
                        BUG();
        }
        }
        return 0;
        return 0;
}
}
 
 
static int check_compat_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id)
static int check_compat_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id)
{
{
        if (type >= MAXQUOTAS)
        if (type >= MAXQUOTAS)
                return -EINVAL;
                return -EINVAL;
        /* Is operation supported? */
        /* Is operation supported? */
        /* sb==NULL for GETSTATS calls */
        /* sb==NULL for GETSTATS calls */
        if (sb && !sb->s_qcop)
        if (sb && !sb->s_qcop)
                return -ENOSYS;
                return -ENOSYS;
 
 
        switch (cmd) {
        switch (cmd) {
                case Q_COMP_QUOTAON:
                case Q_COMP_QUOTAON:
                        if (!sb->s_qcop->quota_on)
                        if (!sb->s_qcop->quota_on)
                                return -ENOSYS;
                                return -ENOSYS;
                        break;
                        break;
                case Q_COMP_QUOTAOFF:
                case Q_COMP_QUOTAOFF:
                        if (!sb->s_qcop->quota_off)
                        if (!sb->s_qcop->quota_off)
                                return -ENOSYS;
                                return -ENOSYS;
                        break;
                        break;
                case Q_COMP_SYNC:
                case Q_COMP_SYNC:
                        if (sb && !sb->s_qcop->quota_sync)
                        if (sb && !sb->s_qcop->quota_sync)
                                return -ENOSYS;
                                return -ENOSYS;
                        break;
                        break;
                case Q_V1_SETQLIM:
                case Q_V1_SETQLIM:
                case Q_V1_SETUSE:
                case Q_V1_SETUSE:
                case Q_V1_SETQUOTA:
                case Q_V1_SETQUOTA:
                        if (!sb->s_qcop->set_dqblk)
                        if (!sb->s_qcop->set_dqblk)
                                return -ENOSYS;
                                return -ENOSYS;
                        break;
                        break;
                case Q_V1_GETQUOTA:
                case Q_V1_GETQUOTA:
                        if (!sb->s_qcop->get_dqblk)
                        if (!sb->s_qcop->get_dqblk)
                                return -ENOSYS;
                                return -ENOSYS;
                        break;
                        break;
                case Q_V1_RSQUASH:
                case Q_V1_RSQUASH:
                        if (!sb->s_qcop->set_info)
                        if (!sb->s_qcop->set_info)
                                return -ENOSYS;
                                return -ENOSYS;
                        break;
                        break;
                case Q_V1_GETSTATS:
                case Q_V1_GETSTATS:
                        return 0;        /* GETSTATS need no other checks */
                        return 0;        /* GETSTATS need no other checks */
                default:
                default:
                        return -EINVAL;
                        return -EINVAL;
        }
        }
 
 
        /* Is quota turned on for commands which need it? */
        /* Is quota turned on for commands which need it? */
        switch (cmd) {
        switch (cmd) {
                case Q_V2_SETFLAGS:
                case Q_V2_SETFLAGS:
                case Q_V2_SETGRACE:
                case Q_V2_SETGRACE:
                case Q_V2_SETINFO:
                case Q_V2_SETINFO:
                case Q_V2_GETINFO:
                case Q_V2_GETINFO:
                case Q_COMP_QUOTAOFF:
                case Q_COMP_QUOTAOFF:
                case Q_V1_RSQUASH:
                case Q_V1_RSQUASH:
                case Q_V1_SETQUOTA:
                case Q_V1_SETQUOTA:
                case Q_V1_SETQLIM:
                case Q_V1_SETQLIM:
                case Q_V1_SETUSE:
                case Q_V1_SETUSE:
                case Q_V2_SETQUOTA:
                case Q_V2_SETQUOTA:
                /* Q_V2_SETQLIM: collision with Q_V1_SETQLIM */
                /* Q_V2_SETQLIM: collision with Q_V1_SETQLIM */
                case Q_V2_SETUSE:
                case Q_V2_SETUSE:
                case Q_V1_GETQUOTA:
                case Q_V1_GETQUOTA:
                case Q_V2_GETQUOTA:
                case Q_V2_GETQUOTA:
                        if (!sb_has_quota_enabled(sb, type))
                        if (!sb_has_quota_enabled(sb, type))
                                return -ESRCH;
                                return -ESRCH;
        }
        }
        if (cmd != Q_COMP_QUOTAON &&
        if (cmd != Q_COMP_QUOTAON &&
            cmd != Q_COMP_QUOTAOFF &&
            cmd != Q_COMP_QUOTAOFF &&
            cmd != Q_COMP_SYNC &&
            cmd != Q_COMP_SYNC &&
            sb_dqopt(sb)->info[type].dqi_format->qf_fmt_id != QFMT_VFS_OLD)
            sb_dqopt(sb)->info[type].dqi_format->qf_fmt_id != QFMT_VFS_OLD)
                return -ESRCH;
                return -ESRCH;
 
 
        /* Check privileges */
        /* Check privileges */
        if (cmd == Q_V1_GETQUOTA || cmd == Q_V2_GETQUOTA) {
        if (cmd == Q_V1_GETQUOTA || cmd == Q_V2_GETQUOTA) {
                if (((type == USRQUOTA && current->euid != id) ||
                if (((type == USRQUOTA && current->euid != id) ||
                     (type == GRPQUOTA && !in_egroup_p(id))) &&
                     (type == GRPQUOTA && !in_egroup_p(id))) &&
                    !capable(CAP_SYS_ADMIN))
                    !capable(CAP_SYS_ADMIN))
                        return -EPERM;
                        return -EPERM;
        }
        }
        else if (cmd != Q_V1_GETSTATS && cmd != Q_V2_GETSTATS && cmd != Q_V2_GETINFO && cmd != Q_COMP_SYNC)
        else if (cmd != Q_V1_GETSTATS && cmd != Q_V2_GETSTATS && cmd != Q_V2_GETINFO && cmd != Q_COMP_SYNC)
                if (!capable(CAP_SYS_ADMIN))
                if (!capable(CAP_SYS_ADMIN))
                        return -EPERM;
                        return -EPERM;
        return 0;
        return 0;
}
}
 
 
static int v1_set_rsquash(struct super_block *sb, int type, int flag)
static int v1_set_rsquash(struct super_block *sb, int type, int flag)
{
{
        struct if_dqinfo info;
        struct if_dqinfo info;
 
 
        info.dqi_valid = IIF_FLAGS;
        info.dqi_valid = IIF_FLAGS;
        info.dqi_flags = flag ? V1_DQF_RSQUASH : 0;
        info.dqi_flags = flag ? V1_DQF_RSQUASH : 0;
        return sb->s_qcop->set_info(sb, type, &info);
        return sb->s_qcop->set_info(sb, type, &info);
}
}
 
 
static int v1_get_dqblk(struct super_block *sb, int type, qid_t id, struct v1c_mem_dqblk *mdq)
static int v1_get_dqblk(struct super_block *sb, int type, qid_t id, struct v1c_mem_dqblk *mdq)
{
{
        struct if_dqblk idq;
        struct if_dqblk idq;
        int ret;
        int ret;
 
 
        if ((ret = sb->s_qcop->get_dqblk(sb, type, id, &idq)) < 0)
        if ((ret = sb->s_qcop->get_dqblk(sb, type, id, &idq)) < 0)
                return ret;
                return ret;
        mdq->dqb_ihardlimit = idq.dqb_ihardlimit;
        mdq->dqb_ihardlimit = idq.dqb_ihardlimit;
        mdq->dqb_isoftlimit = idq.dqb_isoftlimit;
        mdq->dqb_isoftlimit = idq.dqb_isoftlimit;
        mdq->dqb_curinodes = idq.dqb_curinodes;
        mdq->dqb_curinodes = idq.dqb_curinodes;
        mdq->dqb_bhardlimit = idq.dqb_bhardlimit;
        mdq->dqb_bhardlimit = idq.dqb_bhardlimit;
        mdq->dqb_bsoftlimit = idq.dqb_bsoftlimit;
        mdq->dqb_bsoftlimit = idq.dqb_bsoftlimit;
        mdq->dqb_curblocks = toqb(idq.dqb_curspace);
        mdq->dqb_curblocks = toqb(idq.dqb_curspace);
        mdq->dqb_itime = idq.dqb_itime;
        mdq->dqb_itime = idq.dqb_itime;
        mdq->dqb_btime = idq.dqb_btime;
        mdq->dqb_btime = idq.dqb_btime;
        if (id == 0) {   /* Times for id 0 are in fact grace times */
        if (id == 0) {   /* Times for id 0 are in fact grace times */
                struct if_dqinfo info;
                struct if_dqinfo info;
 
 
                if ((ret = sb->s_qcop->get_info(sb, type, &info)) < 0)
                if ((ret = sb->s_qcop->get_info(sb, type, &info)) < 0)
                        return ret;
                        return ret;
                mdq->dqb_btime = info.dqi_bgrace;
                mdq->dqb_btime = info.dqi_bgrace;
                mdq->dqb_itime = info.dqi_igrace;
                mdq->dqb_itime = info.dqi_igrace;
        }
        }
        return 0;
        return 0;
}
}
 
 
static int v1_set_dqblk(struct super_block *sb, int type, int cmd, qid_t id, struct v1c_mem_dqblk *mdq)
static int v1_set_dqblk(struct super_block *sb, int type, int cmd, qid_t id, struct v1c_mem_dqblk *mdq)
{
{
        struct if_dqblk idq;
        struct if_dqblk idq;
        int ret;
        int ret;
 
 
        idq.dqb_valid = 0;
        idq.dqb_valid = 0;
        if (cmd == Q_V1_SETQUOTA || cmd == Q_V1_SETQLIM) {
        if (cmd == Q_V1_SETQUOTA || cmd == Q_V1_SETQLIM) {
                idq.dqb_ihardlimit = mdq->dqb_ihardlimit;
                idq.dqb_ihardlimit = mdq->dqb_ihardlimit;
                idq.dqb_isoftlimit = mdq->dqb_isoftlimit;
                idq.dqb_isoftlimit = mdq->dqb_isoftlimit;
                idq.dqb_bhardlimit = mdq->dqb_bhardlimit;
                idq.dqb_bhardlimit = mdq->dqb_bhardlimit;
                idq.dqb_bsoftlimit = mdq->dqb_bsoftlimit;
                idq.dqb_bsoftlimit = mdq->dqb_bsoftlimit;
                idq.dqb_valid |= QIF_LIMITS;
                idq.dqb_valid |= QIF_LIMITS;
        }
        }
        if (cmd == Q_V1_SETQUOTA || cmd == Q_V1_SETUSE) {
        if (cmd == Q_V1_SETQUOTA || cmd == Q_V1_SETUSE) {
                idq.dqb_curinodes = mdq->dqb_curinodes;
                idq.dqb_curinodes = mdq->dqb_curinodes;
                idq.dqb_curspace = ((qsize_t)mdq->dqb_curblocks) << QUOTABLOCK_BITS;
                idq.dqb_curspace = ((qsize_t)mdq->dqb_curblocks) << QUOTABLOCK_BITS;
                idq.dqb_valid |= QIF_USAGE;
                idq.dqb_valid |= QIF_USAGE;
        }
        }
        ret = sb->s_qcop->set_dqblk(sb, type, id, &idq);
        ret = sb->s_qcop->set_dqblk(sb, type, id, &idq);
        if (!ret && id == 0 && cmd == Q_V1_SETQUOTA) {   /* Times for id 0 are in fact grace times */
        if (!ret && id == 0 && cmd == Q_V1_SETQUOTA) {   /* Times for id 0 are in fact grace times */
                struct if_dqinfo info;
                struct if_dqinfo info;
 
 
                info.dqi_bgrace = mdq->dqb_btime;
                info.dqi_bgrace = mdq->dqb_btime;
                info.dqi_igrace = mdq->dqb_itime;
                info.dqi_igrace = mdq->dqb_itime;
                info.dqi_valid = IIF_BGRACE | IIF_IGRACE;
                info.dqi_valid = IIF_BGRACE | IIF_IGRACE;
                ret = sb->s_qcop->set_info(sb, type, &info);
                ret = sb->s_qcop->set_info(sb, type, &info);
        }
        }
        return ret;
        return ret;
}
}
 
 
static void v1_get_stats(struct v1c_dqstats *dst)
static void v1_get_stats(struct v1c_dqstats *dst)
{
{
        memcpy(dst, &dqstats, sizeof(dqstats));
        memcpy(dst, &dqstats, sizeof(dqstats));
}
}
 
 
/* Handle requests to old interface */
/* Handle requests to old interface */
static int do_compat_quotactl(struct super_block *sb, int type, int cmd, qid_t id, caddr_t addr)
static int do_compat_quotactl(struct super_block *sb, int type, int cmd, qid_t id, caddr_t addr)
{
{
        int ret;
        int ret;
 
 
        switch (cmd) {
        switch (cmd) {
                case Q_COMP_QUOTAON: {
                case Q_COMP_QUOTAON: {
                        char *pathname;
                        char *pathname;
 
 
                        if (IS_ERR(pathname = getname(addr)))
                        if (IS_ERR(pathname = getname(addr)))
                                return PTR_ERR(pathname);
                                return PTR_ERR(pathname);
                        ret = sb->s_qcop->quota_on(sb, type, QFMT_VFS_OLD, pathname);
                        ret = sb->s_qcop->quota_on(sb, type, QFMT_VFS_OLD, pathname);
                        putname(pathname);
                        putname(pathname);
                        return ret;
                        return ret;
                }
                }
                case Q_COMP_QUOTAOFF:
                case Q_COMP_QUOTAOFF:
                        return sb->s_qcop->quota_off(sb, type);
                        return sb->s_qcop->quota_off(sb, type);
                case Q_COMP_SYNC:
                case Q_COMP_SYNC:
                        if (sb)
                        if (sb)
                                return sb->s_qcop->quota_sync(sb, type);
                                return sb->s_qcop->quota_sync(sb, type);
                        sync_dquots_dev(NODEV, type);
                        sync_dquots_dev(NODEV, type);
                        return 0;
                        return 0;
                case Q_V1_RSQUASH: {
                case Q_V1_RSQUASH: {
                        int flag;
                        int flag;
 
 
                        if (copy_from_user(&flag, addr, sizeof(flag)))
                        if (copy_from_user(&flag, addr, sizeof(flag)))
                                return -EFAULT;
                                return -EFAULT;
                        return v1_set_rsquash(sb, type, flag);
                        return v1_set_rsquash(sb, type, flag);
                }
                }
                case Q_V1_GETQUOTA: {
                case Q_V1_GETQUOTA: {
                        struct v1c_mem_dqblk mdq;
                        struct v1c_mem_dqblk mdq;
 
 
                        if ((ret = v1_get_dqblk(sb, type, id, &mdq)))
                        if ((ret = v1_get_dqblk(sb, type, id, &mdq)))
                                return ret;
                                return ret;
                        if (copy_to_user(addr, &mdq, sizeof(mdq)))
                        if (copy_to_user(addr, &mdq, sizeof(mdq)))
                                return -EFAULT;
                                return -EFAULT;
                        return 0;
                        return 0;
                }
                }
                case Q_V1_SETQLIM:
                case Q_V1_SETQLIM:
                case Q_V1_SETUSE:
                case Q_V1_SETUSE:
                case Q_V1_SETQUOTA: {
                case Q_V1_SETQUOTA: {
                        struct v1c_mem_dqblk mdq;
                        struct v1c_mem_dqblk mdq;
 
 
                        if (copy_from_user(&mdq, addr, sizeof(mdq)))
                        if (copy_from_user(&mdq, addr, sizeof(mdq)))
                                return -EFAULT;
                                return -EFAULT;
                        return v1_set_dqblk(sb, type, cmd, id, &mdq);
                        return v1_set_dqblk(sb, type, cmd, id, &mdq);
                }
                }
                case Q_V1_GETSTATS: {
                case Q_V1_GETSTATS: {
                        struct v1c_dqstats dst;
                        struct v1c_dqstats dst;
 
 
                        v1_get_stats(&dst);
                        v1_get_stats(&dst);
                        if (copy_to_user(addr, &dst, sizeof(dst)))
                        if (copy_to_user(addr, &dst, sizeof(dst)))
                                return -EFAULT;
                                return -EFAULT;
                        return 0;
                        return 0;
                }
                }
        }
        }
        BUG();
        BUG();
        return 0;
        return 0;
}
}
 
 
/* Macros for short-circuiting the compatibility tests */
/* Macros for short-circuiting the compatibility tests */
#define NEW_COMMAND(c) ((c) & (0x80 << 16))
#define NEW_COMMAND(c) ((c) & (0x80 << 16))
#define XQM_COMMAND(c) (((c) & ('X' << 8)) == ('X' << 8))
#define XQM_COMMAND(c) (((c) & ('X' << 8)) == ('X' << 8))
 
 
/*
/*
 * This is the system call interface. This communicates with
 * This is the system call interface. This communicates with
 * the user-level programs. Currently this only supports diskquota
 * the user-level programs. Currently this only supports diskquota
 * calls. Maybe we need to add the process quotas etc. in the future,
 * calls. Maybe we need to add the process quotas etc. in the future,
 * but we probably should use rlimits for that.
 * but we probably should use rlimits for that.
 */
 */
asmlinkage long sys_quotactl(unsigned int cmd, const char *special, qid_t id, caddr_t addr)
asmlinkage long sys_quotactl(unsigned int cmd, const char *special, qid_t id, caddr_t addr)
{
{
        uint cmds, type;
        uint cmds, type;
        struct super_block *sb = NULL;
        struct super_block *sb = NULL;
        int ret = -EINVAL;
        int ret = -EINVAL;
 
 
        lock_kernel();
        lock_kernel();
        cmds = cmd >> SUBCMDSHIFT;
        cmds = cmd >> SUBCMDSHIFT;
        type = cmd & SUBCMDMASK;
        type = cmd & SUBCMDMASK;
 
 
        if (cmds != Q_V1_GETSTATS && cmds != Q_V2_GETSTATS && IS_ERR(sb = resolve_dev(special))) {
        if (cmds != Q_V1_GETSTATS && cmds != Q_V2_GETSTATS && IS_ERR(sb = resolve_dev(special))) {
                ret = PTR_ERR(sb);
                ret = PTR_ERR(sb);
                sb = NULL;
                sb = NULL;
                goto out;
                goto out;
        }
        }
        if (!NEW_COMMAND(cmds) && !XQM_COMMAND(cmds)) {
        if (!NEW_COMMAND(cmds) && !XQM_COMMAND(cmds)) {
                if ((ret = check_compat_quotactl_valid(sb, type, cmds, id)) < 0)
                if ((ret = check_compat_quotactl_valid(sb, type, cmds, id)) < 0)
                        goto out;
                        goto out;
                ret = do_compat_quotactl(sb, type, cmds, id, addr);
                ret = do_compat_quotactl(sb, type, cmds, id, addr);
                goto out;
                goto out;
        }
        }
        if ((ret = check_quotactl_valid(sb, type, cmds, id)) < 0)
        if ((ret = check_quotactl_valid(sb, type, cmds, id)) < 0)
                goto out;
                goto out;
        ret = do_quotactl(sb, type, cmds, id, addr);
        ret = do_quotactl(sb, type, cmds, id, addr);
out:
out:
        if (sb)
        if (sb)
                drop_super(sb);
                drop_super(sb);
        unlock_kernel();
        unlock_kernel();
        return ret;
        return ret;
}
}
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.