Re: Quotactl change

Nathan Scott (nathans@sgi.com)
Tue, 9 Oct 2001 22:21:43 +1000


On Tue, Oct 09, 2001 at 03:03:49AM -0400, Alexander Viro wrote:
>
> Quota side looks sane. fs/super.c one is an overkill...
>

On Tue, Oct 09, 2001 at 09:34:25AM +0200, Jan Kara wrote:
> I see two problems...
>

Thanks - these three issues should be resolved now. I'll
bang on this some more tomorrow, but this should just about
do it, I think.

cheers.

-- 
Nathan

diff -Naur linux-2410ac8/fs/Makefile linux-2410ac8-quota/fs/Makefile --- linux-2410ac8/fs/Makefile Mon Oct 8 13:26:59 2001 +++ linux-2410ac8-quota/fs/Makefile Mon Oct 8 19:45:36 2001 @@ -14,12 +14,10 @@ super.o block_dev.o char_dev.o stat.o exec.o pipe.o namei.o \ fcntl.o ioctl.o readdir.o select.o fifo.o locks.o \ dcache.o inode.o attr.o bad_inode.o file.o iobuf.o dnotify.o \ - filesystems.o jbd-kernel.o namespace.o + filesystems.o jbd-kernel.o namespace.o quota.o ifeq ($(CONFIG_QUOTA),y) obj-y += dquot.o -else -obj-y += noquot.o endif subdir-$(CONFIG_PROC_FS) += proc diff -Naur linux-2410ac8/fs/dquot.c linux-2410ac8-quota/fs/dquot.c --- linux-2410ac8/fs/dquot.c Mon Oct 8 13:26:59 2001 +++ linux-2410ac8-quota/fs/dquot.c Tue Oct 9 20:08:05 2001 @@ -46,9 +46,12 @@ * Jan Kara <jack@suse.cz> 12/2000 * * New quotafile format - * Alocation units changed to bytes + * Allocation units changed to bytes * Jan Kara, <jack@suse.cz>, 2000 * + * Reworked the quotactl interface for filesystem-specific quota + * Nathan Scott <nathans@sgi.com> and Jan Kara <jack@suse.cz>, 2001 + * * (C) Copyright 1994 - 1997 Marco van Wieringen */ @@ -65,6 +68,7 @@ #include <linux/slab.h> #include <linux/smp_lock.h> #include <linux/init.h> +#include <linux/proc_fs.h> #include <asm/uaccess.h> #include <asm/byteorder.h> @@ -73,8 +77,6 @@ #define __DQUOT_NUM_VERSION__ (6*10000+5*100+0) #define __DQUOT_PARANOIA -int nr_dquots, nr_free_dquots; - static const char *quotatypes[] = INITQFNAMES; static const uint quota_magics[] = INITQMAGICS; static const uint quota_versions[] = INITQVERSIONS; @@ -1019,6 +1021,11 @@ return 0; } +static int quota_sync(struct super_block *sb, short type) +{ + return sync_dquots(sb->s_dev, type); +} + /* Free unused dquots from cache */ static void prune_dqcache(int count) { @@ -1477,25 +1484,21 @@ * Initialize a dquot-struct with new quota info. This is used by the * system call interface functions. */ -static int set_dqblk(struct super_block *sb, qid_t id, short type, int flags, struct mem_dqblk *dqblk) +static int set_dqblk(struct super_block *sb, short type, qid_t id, struct mem_dqblk *dqblk, int op) { struct dquot *dquot; - int error = -EFAULT; struct mem_dqblk dq_dqblk; - if (copy_from_user(&dq_dqblk, dqblk, sizeof(struct mem_dqblk))) - return error; - - if (sb && (dquot = dqget(sb, id, type)) != NODQUOT) { + if ((dquot = dqget(sb, id, type)) != NODQUOT) { /* We can't block while changing quota structure... */ - if ((flags & SET_QUOTA) || (flags & SET_QLIMIT)) { + if (op == Q_SETQUOTA || op == Q_SETQLIM) { dquot->dq_bhardlimit = dq_dqblk.dqb_bhardlimit; dquot->dq_bsoftlimit = dq_dqblk.dqb_bsoftlimit; dquot->dq_ihardlimit = dq_dqblk.dqb_ihardlimit; dquot->dq_isoftlimit = dq_dqblk.dqb_isoftlimit; } - if ((flags & SET_QUOTA) || (flags & SET_USE)) { + if (op == Q_SETQUOTA || op == Q_SETUSE) { if (dquot->dq_isoftlimit && dquot->dq_curinodes < dquot->dq_isoftlimit && dq_dqblk.dqb_curinodes >= dquot->dq_isoftlimit) @@ -1529,77 +1532,85 @@ return 0; } -static int get_quota(struct super_block *sb, qid_t id, short type, struct mem_dqblk *dqblk) +static int get_dqblk(struct super_block *sb, short type, qid_t id, struct mem_dqblk *dqblk) { struct dquot *dquot; - struct mem_dqblk data; int error = -ESRCH; - if (!sb || !sb_has_quota_enabled(sb, type)) + if (!sb_has_quota_enabled(sb, type)) goto out; dquot = dqget(sb, id, type); if (dquot == NODQUOT) goto out; - memcpy(&data, &dquot->dq_dqb, sizeof(struct mem_dqblk)); /* We copy data to preserve them from changing */ + memcpy(dqblk, &dquot->dq_dqb, sizeof(struct mem_dqblk)); /* We copy data to preserve them from changing */ dqput(dquot); - error = -EFAULT; - if (dqblk && !copy_to_user(dqblk, &data, sizeof(struct mem_dqblk))) - error = 0; + error = 0; out: return error; } -static int get_stats(caddr_t addr) +#ifdef CONFIG_PROC_FS +static int read_stats(char *buffer, char **start, off_t offset, int count, int *eof, void *data) { - int error = -EFAULT; - struct dqstats stats; + int len; dqstats.allocated_dquots = nr_dquots; dqstats.free_dquots = nr_free_dquots; - /* make a copy, in case we page-fault in user space */ - memcpy(&stats, &dqstats, sizeof(struct dqstats)); - if (!copy_to_user(addr, &stats, sizeof(struct dqstats))) - error = 0; - return error; -} + len = sprintf(buffer, "Version %u\n", dqstats.version); + len += sprintf(buffer + len, "%u %u %u %u %u %u %u %u\n", + dqstats.lookups, dqstats.drops, + dqstats.reads, dqstats.writes, + dqstats.cache_hits, dqstats.allocated_dquots, + dqstats.free_dquots, dqstats.syncs); + + if (offset >= len) { + *start = buffer; + *eof = 1; + return 0; + } + *start = buffer + offset; + if ((len -= offset) > count) + return count; + *eof = 1; + + return len; +} +#define quota_proc_init() \ + create_proc_read_entry("fs/quota", 0, 0, read_stats, NULL); +#else +#define quota_proc_init() do { } while (0) +#endif -static int get_info(struct super_block *sb, short type, struct mem_dqinfo *pinfo) +static int get_info(struct super_block *sb, short type, struct mem_dqinfo *kinfo) { - struct mem_dqinfo kinfo; - - if (!sb || !sb_has_quota_enabled(sb, type)) + if (!sb_has_quota_enabled(sb, type)) return -ESRCH; /* Make our own copy so we can guarantee consistent structure */ - memcpy(&kinfo, sb_dqopt(sb)->info+type, sizeof(struct mem_dqinfo)); - kinfo.dqi_flags &= DQF_MASK; - if (copy_to_user(pinfo, &kinfo, sizeof(struct mem_dqinfo))) - return -EFAULT; + memcpy(kinfo, sb_dqopt(sb)->info+type, sizeof(struct mem_dqinfo)); + kinfo->dqi_flags &= DQF_MASK; return 0; } -static int set_info(int op, struct super_block *sb, short type, struct mem_dqinfo *pinfo) +static int set_info(struct super_block *sb, short type, struct mem_dqinfo *pinfo, int op) { struct mem_dqinfo info; struct quota_info *dqopt = sb_dqopt(sb); - if (!sb || !sb_has_quota_enabled(sb, type)) + if (!sb_has_quota_enabled(sb, type)) return -ESRCH; - if (copy_from_user(&info, pinfo, sizeof(struct mem_dqinfo))) - return -EFAULT; - switch (op) { - case ISET_FLAGS: + case Q_SETFLAGS: dqopt->info[type].dqi_flags = (dqopt->info[type].dqi_flags & ~DQF_MASK) | (info.dqi_flags & DQF_MASK); break; - case ISET_GRACE: + case Q_SETGRACE: dqopt->info[type].dqi_bgrace = info.dqi_bgrace; dqopt->info[type].dqi_igrace = info.dqi_igrace; break; - case ISET_ALL: + case Q_SETINFO: info.dqi_flags &= ~DQF_MASK; memcpy(dqopt->info + type, &info, sizeof(struct mem_dqinfo)); break; @@ -1886,6 +1897,7 @@ INIT_LIST_HEAD(dquot_hash + i); dqstats.version = __DQUOT_NUM_VERSION__; printk(KERN_NOTICE "VFS: Diskquotas version %s initialized\n", __DQUOT_VERSION__); + quota_proc_init(); return 0; } __initcall(dquot_init); @@ -1939,9 +1951,6 @@ short cnt; struct quota_info *dqopt = sb_dqopt(sb); - if (!sb) - goto out; - /* We need to serialize quota_off() for device */ down(&dqopt->dqoff_sem); for (cnt = 0; cnt < MAXQUOTAS; cnt++) { @@ -1963,7 +1972,6 @@ fput(filp); } up(&dqopt->dqoff_sem); -out: return 0; } @@ -2044,114 +2052,14 @@ } /* - * 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. + * Definitions of quota operations accessible through quotactl(2). */ -asmlinkage long sys_quotactl(int cmd, const char *special, qid_t id, __kernel_caddr_t addr) -{ - int cmds = 0, type = 0, flags = 0; - kdev_t dev; - struct super_block *sb = NULL; - int ret = -EINVAL; - - lock_kernel(); - cmds = cmd >> SUBCMDSHIFT; - type = cmd & SUBCMDMASK; - - - if ((uint) type >= MAXQUOTAS || cmds > 0x1100 || cmds < 0x100 || cmds == 0x0300 || - cmds == 0x0400 || cmds == 0x0500 || cmds == 0x1000) - goto out; - - ret = -EPERM; - switch (cmds) { - case Q_SYNC: - case Q_GETSTATS: - case Q_GETINFO: - break; - case Q_GETQUOTA: - if (((type == USRQUOTA && current->euid != id) || - (type == GRPQUOTA && !in_egroup_p(id))) && - !capable(CAP_SYS_ADMIN)) - goto out; - break; - default: - if (!capable(CAP_SYS_ADMIN)) - goto out; - } - - dev = NODEV; - if (special != NULL || (cmds != Q_SYNC && cmds != Q_GETSTATS)) { - mode_t mode; - struct nameidata nd; - - ret = user_path_walk(special, &nd); - if (ret) - goto out; - - dev = nd.dentry->d_inode->i_rdev; - mode = nd.dentry->d_inode->i_mode; - path_release(&nd); - - ret = -ENOTBLK; - if (!S_ISBLK(mode)) - goto out; - ret = -ENODEV; - sb = get_super(dev); - if (!sb) - goto out; - } - - ret = -EINVAL; - switch (cmds) { - case Q_QUOTAON: - ret = quota_on(sb, type, (char *) addr); - goto out; - case Q_QUOTAOFF: - ret = quota_off(sb, type); - goto out; - case Q_GETQUOTA: - ret = get_quota(sb, id, type, (struct mem_dqblk *) addr); - goto out; - case Q_SETQUOTA: - flags |= SET_QUOTA; - break; - case Q_SETUSE: - flags |= SET_USE; - break; - case Q_SETQLIM: - flags |= SET_QLIMIT; - break; - case Q_SYNC: - ret = sync_dquots(dev, type); - goto out; - case Q_GETSTATS: - ret = get_stats(addr); - goto out; - case Q_GETINFO: - ret = get_info(sb, type, (struct mem_dqinfo *) addr); - goto out; - case Q_SETFLAGS: - ret = set_info(ISET_FLAGS, sb, type, (struct mem_dqinfo *)addr); - goto out; - case Q_SETGRACE: - ret = set_info(ISET_GRACE, sb, type, (struct mem_dqinfo *)addr); - goto out; - case Q_SETINFO: - ret = set_info(ISET_ALL, sb, type, (struct mem_dqinfo *)addr); - goto out; - default: - goto out; - } - - ret = -NODEV; - if (sb && sb_has_quota_enabled(sb, type)) - ret = set_dqblk(sb, id, type, flags, (struct mem_dqblk *) addr); -out: - if (sb) - drop_super(sb); - unlock_kernel(); - return ret; -} +struct quota_operations generic_quota_ops = { + quotaon: quota_on, + quotaoff: quota_off, + quotasync: quota_sync, + getinfo: get_info, + setinfo: set_info, + getdqblk: get_dqblk, + setdqblk: set_dqblk, +}; diff -Naur linux-2410ac8/fs/noquot.c linux-2410ac8-quota/fs/noquot.c --- linux-2410ac8/fs/noquot.c Mon Oct 8 13:27:00 2001 +++ linux-2410ac8-quota/fs/noquot.c Thu Jan 1 10:00:00 1970 @@ -1,20 +0,0 @@ -/* noquot.c: Quota stubs necessary for when quotas are not - * compiled into the kernel. - */ - -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/errno.h> - -int nr_dquots, nr_free_dquots; -int max_dquots; - -asmlinkage long sys_quotactl(int cmd, const char *special, int id, caddr_t addr) -{ - return(-ENOSYS); -} - -void shrink_dqcache_memory(int priority, unsigned int gfp_mask) -{ - ; -} diff -Naur linux-2410ac8/fs/quota.c linux-2410ac8-quota/fs/quota.c --- linux-2410ac8/fs/quota.c Thu Jan 1 10:00:00 1970 +++ linux-2410ac8-quota/fs/quota.c Tue Oct 9 20:44:43 2001 @@ -0,0 +1,212 @@ +/* + * Quota code necessary even when VFS quota support is not compiled + * into the kernel. Allows filesystems to implement their own form + * of quota if they wish. The interesting stuff is over in dquot.c, + * living here are symbols for initial quotactl(2) handling, sysctl + * variables, etc - things needed even when quota support disabled. + */ + +#include <linux/fs.h> +#include <asm/current.h> +#include <asm/uaccess.h> +#include <linux/kernel.h> +#include <linux/smp_lock.h> + +int nr_dquots, nr_free_dquots; + +#ifndef CONFIG_QUOTA +void shrink_dqcache_memory(int priority, unsigned int mask) +{ + return; +} +#endif + +static struct super_block * +validate_quotactl(int cmd, int type, const char *special, qid_t id) +{ + int ret; + kdev_t dev; + mode_t mode; + struct nameidata nd; + struct super_block *sb; + + ret = -ENOSYS; + if (cmd == 0x0800 || cmd == 0x1100) /* both were Q_GETSTATS */ + goto error; + + /* version/compatibility stuff - needs to be early on in the piece */ + ret = -EINVAL; + if (cmd == 0x0300 || cmd == 0x0400 || cmd == 0x0500 || cmd == 0x1000 + || cmd < 0x100) + goto error; + if (type >= MAXQUOTAS) + goto error; + + ret = -EPERM; + switch (cmd) { + case Q_SYNC: + case Q_GETINFO: + case Q_XGETQSTAT: + break; + + case Q_GETQUOTA: + case Q_XGETQUOTA: + if (((type == USRQUOTA && current->euid != id) || + (type == GRPQUOTA && !in_egroup_p(id))) && + !capable(CAP_SYS_ADMIN)) + goto error; + + default: + if (!capable(CAP_SYS_ADMIN)) + goto error; + } + + ret = -ENODEV; + if (!special) + goto error; + ret = user_path_walk(special, &nd); + if (ret) + goto error; + + dev = nd.dentry->d_inode->i_rdev; + mode = nd.dentry->d_inode->i_mode; + path_release(&nd); + + ret = -ENOTBLK; + if (!S_ISBLK(mode)) + goto error; + + ret = -ENODEV; + sb = get_super(dev); + if (!sb) + goto error; + + ret = -ENOSYS; + if (!sb->s_qop) { + drop_super(sb); + goto error; + } + + return sb; +error: + return ERR_PTR(ret); +} + +asmlinkage long +sys_quotactl(int cmd, const char *special, qid_t id, __kernel_caddr_t addr) +{ + int ret, cmds, type; + struct super_block *sb; + union { + char *pathname; + unsigned int flags; + struct mem_dqblk mdq; + struct mem_dqinfo info; + struct fs_disk_quota fdq; + struct fs_quota_stat fqs; + } u; /* qualifies valid uses of "addr" */ + + lock_kernel(); + cmds = cmd >> SUBCMDSHIFT; + type = cmd & SUBCMDMASK; + + sb = validate_quotactl(cmds, type, special, id); + if (IS_ERR(sb)) { + unlock_kernel(); + return PTR_ERR(sb); + } + + ret = -EINVAL; + switch (cmds) { + case Q_QUOTAON: + u.pathname = (char *)addr; + if (sb->s_qop->quotaon) + ret = sb->s_qop->quotaon(sb, type, u.pathname); + break; + + case Q_QUOTAOFF: + if (sb->s_qop->quotaoff) + ret = sb->s_qop->quotaoff(sb, type); + break; + + case Q_SYNC: + if (sb->s_qop->quotasync) + ret = sb->s_qop->quotasync(sb, type); + break; + + case Q_GETINFO: + if (sb->s_qop->getinfo) + ret = sb->s_qop->getinfo(sb, type, &u.info); + if (!ret && copy_to_user(addr, &u.info, sizeof(u.info))) + ret = -EFAULT; + break; + + case Q_SETINFO: + case Q_SETFLAGS: + case Q_SETGRACE: + if (!sb->s_qop->setinfo) + break; + ret = -EFAULT; + if (copy_from_user(&u.info, addr, sizeof(u.info))) + break; + ret = sb->s_qop->setinfo(sb, type, &u.info, cmds); + break; + + case Q_GETQUOTA: + if (sb->s_qop->getdqblk) + ret = sb->s_qop->getdqblk(sb, id, type, &u.mdq); + if (!ret && copy_to_user(addr, &u.mdq, sizeof(u.mdq))) + ret = -EFAULT; + break; + + case Q_SETUSE: + case Q_SETQLIM: + case Q_SETQUOTA: + if (!sb->s_qop->setdqblk) + break; + ret = -EFAULT; + if (copy_from_user(&u.mdq, addr, sizeof(u.mdq))) + break; + ret = sb->s_qop->setdqblk(sb, id, type, &u.mdq, cmds); + break; + + case Q_XQUOTAON: + case Q_XQUOTAOFF: + case Q_XQUOTARM: + if (!sb->s_qop->setxstate) + break; + ret = -EFAULT; + if (copy_from_user(&u.flags, addr, sizeof(u.flags))) + break; + ret = sb->s_qop->setxstate(sb, type, u.flags, cmds); + break; + + case Q_XGETQSTAT: + if (sb->s_qop->getxstate) + ret = sb->s_qop->getxstate(sb, type, &u.fqs); + if (!ret && copy_to_user(addr, &u.fqs, sizeof(u.fqs))) + ret = -EFAULT; + break; + + case Q_XSETQLIM: + if (!sb->s_qop->setxquota) + break; + ret = -EFAULT; + if (copy_from_user(&u.fdq, addr, sizeof(u.fdq))) + break; + ret = sb->s_qop->setxquota(sb, type, &u.fdq); + break; + + case Q_XGETQUOTA: + if (sb->s_qop->getxquota) + ret = sb->s_qop->getxquota(sb, type, &u.fdq); + if (!ret && copy_to_user(addr, &u.fqs, sizeof(u.fdq))) + ret = -EFAULT; + break; + + default: + } + drop_super(sb); + unlock_kernel(); + return ret; +} diff -Naur linux-2410ac8/fs/super.c linux-2410ac8-quota/fs/super.c --- linux-2410ac8/fs/super.c Mon Oct 8 13:27:00 2001 +++ linux-2410ac8-quota/fs/super.c Tue Oct 9 21:34:49 2001 @@ -437,6 +437,7 @@ sema_init(&s->s_dquot.dqio_sem, 1); sema_init(&s->s_dquot.dqoff_sem, 1); s->s_maxbytes = MAX_NON_LFS; + s->s_qop = sb_generic_quota_ops; } return s; } diff -Naur linux-2410ac8/include/linux/fs.h linux-2410ac8-quota/include/linux/fs.h --- linux-2410ac8/include/linux/fs.h Mon Oct 8 13:27:00 2001 +++ linux-2410ac8-quota/include/linux/fs.h Tue Oct 9 20:24:42 2001 @@ -376,6 +376,7 @@ /* * Includes for diskquotas and mount structures. */ +#include <linux/xqm.h> #include <linux/quota.h> #include <linux/mount.h> @@ -659,6 +660,20 @@ struct mem_dqinfo info[MAXQUOTAS]; /* Information for each quota type */ }; +struct quota_operations { + int (*quotaon)(struct super_block *, short, char *); + int (*quotaoff)(struct super_block *, short); + int (*quotasync)(struct super_block *, short); + int (*getinfo)(struct super_block *, short, struct mem_dqinfo *); + int (*setinfo)(struct super_block *, short, struct mem_dqinfo *, int); + int (*getdqblk)(struct super_block *, short, qid_t, struct mem_dqblk *); + int (*setdqblk)(struct super_block *, short, qid_t, struct mem_dqblk *, int); + int (*getxstate)(struct super_block *, short, struct fs_quota_stat *); + int (*setxstate)(struct super_block *, short, unsigned int, int); + int (*getxquota)(struct super_block *, short, struct fs_disk_quota *); + int (*setxquota)(struct super_block *, short, struct fs_disk_quota *); +}; + /* * Umount options */ @@ -720,6 +735,7 @@ struct block_device *s_bdev; struct list_head s_instances; struct quota_info s_dquot; /* Diskquota specific options */ + struct quota_operations *s_qop; union { struct minix_sb_info minix_sb; diff -Naur linux-2410ac8/include/linux/quota.h linux-2410ac8-quota/include/linux/quota.h --- linux-2410ac8/include/linux/quota.h Mon Oct 8 15:30:03 2001 +++ linux-2410ac8-quota/include/linux/quota.h Mon Oct 8 18:04:05 2001 @@ -107,7 +107,7 @@ #define Q_SETQUOTA 0x0E00 /* set limits and usage */ #define Q_SETUSE 0x0F00 /* set usage */ /* 0x1000 used by old RSQUASH */ -#define Q_GETSTATS 0x1100 /* get collected stats */ +/* 0x1100 used by GETSTATS v2, since replaced by procfs entry */ /* * The following structure defines the format of the disk quota file @@ -253,13 +253,6 @@ #define dq_bhardlimit dq_dqb.dqb_bhardlimit #define dq_itime dq_dqb.dqb_itime #define dq_btime dq_dqb.dqb_btime - -/* - * Flags used for set_dqblk. - */ -#define SET_QUOTA 0x01 -#define SET_USE 0x02 -#define SET_QLIMIT 0x04 #define QUOTA_OK 0 #define NO_QUOTA 1 diff -Naur linux-2410ac8/include/linux/quotaops.h linux-2410ac8-quota/include/linux/quotaops.h --- linux-2410ac8/include/linux/quotaops.h Mon Oct 8 13:27:00 2001 +++ linux-2410ac8-quota/include/linux/quotaops.h Mon Oct 8 18:26:56 2001 @@ -17,6 +17,9 @@ #include <linux/fs.h> +extern struct quota_operations generic_quota_ops; +#define sb_generic_quota_ops (&generic_quota_ops) + /* * declaration of quota_function calls in kernel. */ @@ -166,6 +169,7 @@ /* * NO-OP when quota not configured. */ +#define sb_generic_quota_ops (NULL) #define DQUOT_INIT(inode) do { } while(0) #define DQUOT_DROP(inode) do { } while(0) #define DQUOT_ALLOC_INODE(inode) (0) diff -Naur linux-2410ac8/include/linux/sysctl.h linux-2410ac8-quota/include/linux/sysctl.h --- linux-2410ac8/include/linux/sysctl.h Mon Oct 8 13:27:00 2001 +++ linux-2410ac8-quota/include/linux/sysctl.h Mon Oct 8 18:04:06 2001 @@ -535,7 +535,7 @@ FS_STATINODE=2, FS_MAXINODE=3, /* int:maximum number of inodes that can be allocated */ FS_NRDQUOT=4, /* int:current number of allocated dquots */ - FS_MAXDQUOT=5, /* int:maximum number of dquots that can be allocated */ + /* was FS_MAXDQUOT */ FS_NRFILE=6, /* int:current number of allocated filedescriptors */ FS_MAXFILE=7, /* int:maximum number of filedescriptors that can be allocated */ FS_DENTRY=8, diff -Naur linux-2410ac8/include/linux/xqm.h linux-2410ac8-quota/include/linux/xqm.h --- linux-2410ac8/include/linux/xqm.h Thu Jan 1 10:00:00 1970 +++ linux-2410ac8-quota/include/linux/xqm.h Mon Oct 8 18:04:05 2001 @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it is + * free of the rightful claim of any third person regarding infringement + * or the like. Any license provided herein, whether implied or + * otherwise, applies only to this software file. Patent licenses, if + * any, provided herein do not apply to combinations of this program with + * other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write the Free Software Foundation, Inc., 59 + * Temple Place - Suite 330, Boston MA 02111-1307, USA. + * + * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, + * Mountain View, CA 94043, or: + * + * http://www.sgi.com + * + * For further information regarding this notice, see: + * + * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ + */ +#ifndef _LINUX_XQM_H +#define _LINUX_XQM_H + +#include <linux/types.h> + +/* + * Disk quota - quotactl(2) commands for the XFS Quota Manager (XQM). + */ + +#define XQM_CMD(x) (('X'<<8)+(x)) /* note: forms first QCMD argument */ +#define Q_XQUOTAON XQM_CMD(0x1) /* enable accounting/enforcement */ +#define Q_XQUOTAOFF XQM_CMD(0x2) /* disable accounting/enforcement */ +#define Q_XGETQUOTA XQM_CMD(0x3) /* get disk limits and usage */ +#define Q_XSETQLIM XQM_CMD(0x4) /* set disk limits */ +#define Q_XGETQSTAT XQM_CMD(0x5) /* get quota subsystem status */ +#define Q_XQUOTARM XQM_CMD(0x6) /* free disk space used by dquots */ + +/* + * fs_disk_quota structure: + * + * This contains the current quota information regarding a user/proj/group. + * It is 64-bit aligned, and all the blk units are in BBs (Basic Blocks) of + * 512 bytes. + */ +#define FS_DQUOT_VERSION 1 /* fs_disk_quota.d_version */ +typedef struct fs_disk_quota { + __s8 d_version; /* version of this structure */ + __s8 d_flags; /* XFS_{USER,PROJ,GROUP}_QUOTA */ + __u16 d_fieldmask; /* field specifier */ + __u32 d_id; /* user, project, or group ID */ + __u64 d_blk_hardlimit;/* absolute limit on disk blks */ + __u64 d_blk_softlimit;/* preferred limit on disk blks */ + __u64 d_ino_hardlimit;/* maximum # allocated inodes */ + __u64 d_ino_softlimit;/* preferred inode limit */ + __u64 d_bcount; /* # disk blocks owned by the user */ + __u64 d_icount; /* # inodes owned by the user */ + __s32 d_itimer; /* zero if within inode limits */ + /* if not, we refuse service */ + __s32 d_btimer; /* similar to above; for disk blocks */ + __u16 d_iwarns; /* # warnings issued wrt num inodes */ + __u16 d_bwarns; /* # warnings issued wrt disk blocks */ + __s32 d_padding2; /* padding2 - for future use */ + __u64 d_rtb_hardlimit;/* absolute limit on realtime blks */ + __u64 d_rtb_softlimit;/* preferred limit on RT disk blks */ + __u64 d_rtbcount; /* # realtime blocks owned */ + __s32 d_rtbtimer; /* similar to above; for RT disk blks */ + __u16 d_rtbwarns; /* # warnings issued wrt RT disk blks */ + __s16 d_padding3; /* padding3 - for future use */ + char d_padding4[8]; /* yet more padding */ +} fs_disk_quota_t; + +/* + * These fields are sent to Q_XSETQLIM to specify fields that need to change. + */ +#define FS_DQ_ISOFT (1<<0) +#define FS_DQ_IHARD (1<<1) +#define FS_DQ_BSOFT (1<<2) +#define FS_DQ_BHARD (1<<3) +#define FS_DQ_RTBSOFT (1<<4) +#define FS_DQ_RTBHARD (1<<5) +#define FS_DQ_LIMIT_MASK (FS_DQ_ISOFT | FS_DQ_IHARD | FS_DQ_BSOFT | \ + FS_DQ_BHARD | FS_DQ_RTBSOFT | FS_DQ_RTBHARD) +/* + * These timers can only be set in super user's dquot. For others, timers are + * automatically started and stopped. Superusers timer values set the limits + * for the rest. In case these values are zero, the DQ_{F,B}TIMELIMIT values + * defined below are used. + * These values also apply only to the d_fieldmask field for Q_XSETQLIM. + */ +#define FS_DQ_BTIMER (1<<6) +#define FS_DQ_ITIMER (1<<7) +#define FS_DQ_RTBTIMER (1<<8) +#define FS_DQ_TIMER_MASK (FS_DQ_BTIMER | FS_DQ_ITIMER | FS_DQ_RTBTIMER) + +/* + * The following constants define the default amount of time given a user + * before the soft limits are treated as hard limits (usually resulting + * in an allocation failure). These may be modified by the quotactl(2) + * system call with the Q_XSETQLIM command. + */ +#define DQ_FTIMELIMIT (7 * 24*60*60) /* 1 week */ +#define DQ_BTIMELIMIT (7 * 24*60*60) /* 1 week */ + +/* + * Various flags related to quotactl(2). Only relevant to XFS filesystems. + */ +#define XFS_QUOTA_UDQ_ACCT (1<<0) /* user quota accounting */ +#define XFS_QUOTA_UDQ_ENFD (1<<1) /* user quota limits enforcement */ +#define XFS_QUOTA_GDQ_ACCT (1<<2) /* group quota accounting */ +#define XFS_QUOTA_GDQ_ENFD (1<<3) /* group quota limits enforcement */ + +#define XFS_USER_QUOTA (1<<0) /* user quota type */ +#define XFS_PROJ_QUOTA (1<<1) /* (IRIX) project quota type */ +#define XFS_GROUP_QUOTA (1<<2) /* group quota type */ + +/* + * fs_quota_stat is the struct returned in Q_XGETQSTAT for a given file system. + * Provides a centralized way to get meta infomation about the quota subsystem. + * eg. space taken up for user and group quotas, number of dquots currently + * incore. + */ +#define FS_QSTAT_VERSION 1 /* fs_quota_stat.qs_version */ + +/* + * Some basic infomation about 'quota files'. + */ +typedef struct fs_qfilestat { + __u64 qfs_ino; /* inode number */ + __u64 qfs_nblks; /* number of BBs 512-byte-blks */ + __u32 qfs_nextents; /* number of extents */ +} fs_qfilestat_t; + +typedef struct fs_quota_stat { + __s8 qs_version; /* version number for future changes */ + __u16 qs_flags; /* XFS_QUOTA_{U,P,G}DQ_{ACCT,ENFD} */ + __s8 qs_pad; /* unused */ + fs_qfilestat_t qs_uquota; /* user quota storage information */ + fs_qfilestat_t qs_gquota; /* group quota storage information */ + __u32 qs_incoredqs; /* number of dquots incore */ + __s32 qs_btimelimit; /* limit for blks timer */ + __s32 qs_itimelimit; /* limit for inodes timer */ + __s32 qs_rtbtimelimit;/* limit for rt blks timer */ + __u16 qs_bwarnlimit; /* limit for num warnings */ + __u16 qs_iwarnlimit; /* limit for num warnings */ +} fs_quota_stat_t; + +#endif /* _LINUX_XQM_H */ - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/