lkml.org 
[lkml]   [2001]   [Oct]   [8]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
SubjectRe: Quotactl change
hi all,

Al - is the attached patch more along the lines of what you
were after?

Jan - I think this is actually alot closer to what you were
talking about when we last discussed this. Can you see any
problems from a VFS quota point of view here? I had to make
small interface changes to a couple of the dquot.c routines
to make this simpler/more uniform in places - could you have
cross-check those for me?

many thanks.


On Sat, Oct 06, 2001 at 02:25:06PM -0400, Alexander Viro wrote:
>
>
> On Sat, 6 Oct 2001, Jan Kara wrote:
>
> > Hello,
> >
> > I'm sending you a change for quotactl interface which Nathan Scott proposed
> > for XFS. Actually it's his patch with just a few changes from me.
> > It allows quotactl() to be overidden by a filesystem and so XFS can do it's
> > tricks with quota without patching dquot.c. Sideeffect of this change is a
> > cleanup in quotactl() interface :).
>
> [snip]
>
> Umm... So you've just given to each fs driver a syscall with
> completely unspecified arguments? I _really_ doubt that it's a good
> idea, especially since each instance will have to copy structures
> to/from userland.
>
> Please, put switch by the first argument and copy_{to,from}_user()
> into the syscall itself. Yes, it means more methods, but it helps to avoid
> large PITA couple of years down the road.
>

--
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 Mon Oct 8 19:53:03 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;
@@ -988,10 +990,11 @@
}
}

-int sync_dquots(kdev_t dev, short type)
+int sync_dquots(struct super_block *sb, short type)
{
struct list_head *head;
struct dquot *dquot;
+ kdev_t dev = sb->s_dev;

restart:
for (head = inuse_list.next; head != &inuse_list; head = head->next) {
@@ -1477,25 +1480,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 +1528,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 +1893,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 +1947,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 +1968,6 @@
fput(filp);
}
up(&dqopt->dqoff_sem);
-out:
return 0;
}

@@ -2044,114 +2048,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,
+ sync: sync_dquots,
+ 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 Mon Oct 8 18:15:41 2001
@@ -0,0 +1,216 @@
+/*
+ * 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 out;
+
+ /* 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 out;
+ if (type >= MAXQUOTAS)
+ goto out;
+
+ 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 out;
+
+ default:
+ if (!capable(CAP_SYS_ADMIN))
+ goto out;
+ }
+
+ ret = -ENODEV;
+ if (!special)
+ goto out;
+ 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 = -ENOSYS;
+ if (!sb->s_qop) {
+ drop_super(sb);
+ goto out;
+ }
+
+ ret = 0;
+out:
+ if (ret)
+ return ERR_PTR(ret);
+ return NULL;
+}
+
+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->sync)
+ ret = sb->s_qop->sync(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);
+ ret = -EFAULT;
+ 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);
+ ret = -EFAULT;
+ 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 Mon Oct 8 13:29:31 2001
@@ -453,6 +453,7 @@
s->s_bdev = bdev;
s->s_flags = flags;
s->s_type = type;
+ s->s_qop = sb_generic_quota_ops;
spin_lock(&sb_lock);
list_add (&s->s_list, super_blocks.prev);
list_add (&s->s_instances, &type->fs_supers);
@@ -473,6 +474,7 @@
s->s_dev = 0;
s->s_bdev = 0;
s->s_type = NULL;
+ s->s_qop = NULL;
unlock_super(s);
spin_lock(&sb_lock);
list_del(&s->s_list);
@@ -604,6 +606,7 @@
s->s_bdev = bdev;
s->s_flags = flags;
s->s_type = fs_type;
+ s->s_qop = sb_generic_quota_ops;
list_add (&s->s_list, super_blocks.prev);
list_add (&s->s_instances, &fs_type->fs_supers);
s->s_count += S_BIAS;
@@ -623,6 +626,7 @@
s->s_dev = 0;
s->s_bdev = 0;
s->s_type = NULL;
+ s->s_qop = NULL;
unlock_super(s);
spin_lock(&sb_lock);
list_del(&s->s_list);
@@ -687,6 +691,7 @@
s->s_dev = dev;
s->s_flags = flags;
s->s_type = fs_type;
+ s->s_qop = sb_generic_quota_ops;
list_add (&s->s_list, super_blocks.prev);
list_add (&s->s_instances, &fs_type->fs_supers);
s->s_count += S_BIAS;
@@ -702,6 +707,7 @@
s->s_dev = 0;
s->s_bdev = 0;
s->s_type = NULL;
+ s->s_qop = NULL;
unlock_super(s);
spin_lock(&sb_lock);
list_del(&s->s_list);
@@ -757,6 +763,7 @@
sb->s_bdev = NULL;
put_filesystem(fs);
sb->s_type = NULL;
+ sb->s_qop = NULL;
unlock_super(sb);
unlock_kernel();
if (bdev)
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 Mon Oct 8 18:19:06 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 (*sync)(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 (*setxstate)(struct super_block *, short, unsigned int, int);
+ int (*getxstate)(struct super_block *, short, struct fs_quota_stat *);
+ int (*setxquota)(struct super_block *, short, struct fs_disk_quota *);
+ int (*getxquota)(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,159 @@
+/*
+ * 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 */
+#define Q_XDEBUG XQM_CMD(0x7) /* do internal consistency checks */
+
+/*
+ * 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 */
\
 
 \ /
  Last update: 2005-03-22 13:04    [W:0.085 / U:1.608 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site