Commit 43a3a37b authored by Linus Torvalds's avatar Linus Torvalds

Merge quota update from Jan Kara

parents 6033f024 ad447df3
......@@ -3669,7 +3669,11 @@ getname32 (const char *filename)
return result;
}
struct dqblk32 {
extern asmlinkage long sys_quotactl(int cmd, const char *special, int id, caddr_t addr);
#ifdef CONFIG_QIFACE_COMPAT
#ifdef CONFIG_QIFACE_V1
struct user_dqblk32 {
__u32 dqb_bhardlimit;
__u32 dqb_bsoftlimit;
__u32 dqb_curblocks;
......@@ -3679,49 +3683,82 @@ struct dqblk32 {
__kernel_time_t32 dqb_btime;
__kernel_time_t32 dqb_itime;
};
typedef struct v1c_mem_dqblk comp_dqblk_t;
asmlinkage long
sys32_quotactl (int cmd, unsigned int special, int id, struct dqblk32 *addr)
#define Q_COMP_GETQUOTA Q_V1_GETQUOTA
#define Q_COMP_SETQUOTA Q_V1_SETQUOTA
#define Q_COMP_SETQLIM Q_V1_SETQLIM
#define Q_COMP_SETUSE Q_V1_SETUSE
#else
struct user_dqblk32 {
__u32 dqb_ihardlimit;
__u32 dqb_isoftlimit;
__u32 dqb_curinodes;
__u32 dqb_bhardlimit;
__u32 dqb_bsoftlimit;
__u64 dqb_curspace;
__kernel_time_t32 dqb_btime;
__kernel_time_t32 dqb_itime;
};
typedef struct v2c_mem_dqblk comp_dqblk_t;
#define Q_COMP_GETQUOTA Q_V2_GETQUOTA
#define Q_COMP_SETQUOTA Q_V2_SETQUOTA
#define Q_COMP_SETQLIM Q_V2_SETQLIM
#define Q_COMP_SETUSE Q_V2_SETUSE
#endif
asmlinkage long sys32_quotactl(int cmd, const char *special, int id, caddr_t addr)
{
extern asmlinkage long sys_quotactl (int, const char *, int, caddr_t);
int cmds = cmd >> SUBCMDSHIFT;
long err;
comp_dqblk_t d;
mm_segment_t old_fs;
struct dqblk d;
char *spec;
long err;
switch (cmds) {
case Q_GETQUOTA:
case Q_COMP_GETQUOTA:
break;
case Q_SETQUOTA:
case Q_SETUSE:
case Q_SETQLIM:
if (copy_from_user (&d, addr, sizeof(struct dqblk32)))
case Q_COMP_SETQUOTA:
case Q_COMP_SETUSE:
case Q_COMP_SETQLIM:
if (copy_from_user(&d, (struct user_dqblk32 *)addr,
sizeof (struct user_dqblk32)))
return -EFAULT;
d.dqb_itime = ((struct dqblk32 *)&d)->dqb_itime;
d.dqb_btime = ((struct dqblk32 *)&d)->dqb_btime;
d.dqb_itime = ((struct user_dqblk32 *)&d)->dqb_itime;
d.dqb_btime = ((struct user_dqblk32 *)&d)->dqb_btime;
break;
default:
return sys_quotactl(cmd, (void *) A(special), id, (caddr_t) addr);
return sys_quotactl(cmd, special, id, (__kernel_caddr_t)addr);
}
spec = getname32((void *) A(special));
spec = getname (special);
err = PTR_ERR(spec);
if (IS_ERR(spec))
if (IS_ERR(spec)) return err;
old_fs = get_fs();
set_fs (KERNEL_DS);
err = sys_quotactl(cmd, (const char *)spec, id, (__kernel_caddr_t)&d);
set_fs (old_fs);
putname (spec);
if (err)
return err;
old_fs = get_fs ();
set_fs(KERNEL_DS);
err = sys_quotactl(cmd, (const char *)spec, id, (caddr_t)&d);
set_fs(old_fs);
putname(spec);
if (cmds == Q_GETQUOTA) {
if (cmds == Q_COMP_GETQUOTA) {
__kernel_time_t b = d.dqb_btime, i = d.dqb_itime;
((struct dqblk32 *)&d)->dqb_itime = i;
((struct dqblk32 *)&d)->dqb_btime = b;
if (copy_to_user(addr, &d, sizeof(struct dqblk32)))
((struct user_dqblk32 *)&d)->dqb_itime = i;
((struct user_dqblk32 *)&d)->dqb_btime = b;
if (copy_to_user ((struct user_dqblk32 *)addr, &d,
sizeof (struct user_dqblk32)))
return -EFAULT;
}
return err;
return 0;
}
#else
/* No conversion needed for new interface */
asmlinkage long sys32_quotactl(int cmd, const char *special, int id, caddr_t addr)
{
return sys_quotactl(cmd, special, id, addr);
}
#endif
asmlinkage long
sys32_sched_rr_get_interval (pid_t pid, struct timespec32 *interval)
......
......@@ -897,7 +897,28 @@ asmlinkage long sys32_fcntl64(unsigned int fd, unsigned int cmd, unsigned long a
return sys32_fcntl(fd, cmd, arg);
}
struct mem_dqblk32 {
extern asmlinkage int sys_quotactl(int cmd, const char *special, int id, caddr_t addr);
#ifdef CONFIG_QIFACE_COMPAT
#ifdef CONFIG_QIFACE_V1
struct user_dqblk32 {
__u32 dqb_bhardlimit;
__u32 dqb_bsoftlimit;
__u32 dqb_curblocks;
__u32 dqb_ihardlimit;
__u32 dqb_isoftlimit;
__u32 dqb_curinodes;
__kernel_time_t32 dqb_btime;
__kernel_time_t32 dqb_itime;
};
typedef struct v1c_mem_dqblk comp_dqblk_t;
#define Q_COMP_GETQUOTA Q_V1_GETQUOTA
#define Q_COMP_SETQUOTA Q_V1_SETQUOTA
#define Q_COMP_SETQLIM Q_V1_SETQLIM
#define Q_COMP_SETUSE Q_V1_SETUSE
#else
struct user_dqblk32 {
__u32 dqb_ihardlimit;
__u32 dqb_isoftlimit;
__u32 dqb_curinodes;
......@@ -907,54 +928,66 @@ struct mem_dqblk32 {
__kernel_time_t32 dqb_btime;
__kernel_time_t32 dqb_itime;
};
typedef struct v2c_mem_dqblk comp_dqblk_t;
extern asmlinkage long sys_quotactl(int cmd, const char *special, int id, __kernel_caddr_t addr);
#define Q_COMP_GETQUOTA Q_V2_GETQUOTA
#define Q_COMP_SETQUOTA Q_V2_SETQUOTA
#define Q_COMP_SETQLIM Q_V2_SETQLIM
#define Q_COMP_SETUSE Q_V2_SETUSE
#endif
asmlinkage int sys32_quotactl(int cmd, const char *special, int id, unsigned long addr)
asmlinkage int sys32_quotactl(int cmd, const char *special, int id, caddr_t addr)
{
int cmds = cmd >> SUBCMDSHIFT;
int err;
struct mem_dqblk d;
comp_dqblk_t d;
mm_segment_t old_fs;
char *spec;
switch (cmds) {
case Q_GETQUOTA:
case Q_COMP_GETQUOTA:
break;
case Q_SETQUOTA:
case Q_SETUSE:
case Q_SETQLIM:
if (copy_from_user (&d, (struct mem_dqblk32 *)addr,
sizeof (struct mem_dqblk32)))
case Q_COMP_SETQUOTA:
case Q_COMP_SETUSE:
case Q_COMP_SETQLIM:
if (copy_from_user(&d, (struct user_dqblk32 *)addr,
sizeof (struct user_dqblk32)))
return -EFAULT;
d.dqb_itime = ((struct mem_dqblk32 *)&d)->dqb_itime;
d.dqb_btime = ((struct mem_dqblk32 *)&d)->dqb_btime;
d.dqb_itime = ((struct user_dqblk32 *)&d)->dqb_itime;
d.dqb_btime = ((struct user_dqblk32 *)&d)->dqb_btime;
break;
default:
return sys_quotactl(cmd, special,
id, (__kernel_caddr_t)addr);
return sys_quotactl(cmd, special, id, (__kernel_caddr_t)addr);
}
spec = getname (special);
err = PTR_ERR(spec);
if (IS_ERR(spec)) return err;
old_fs = get_fs ();
old_fs = get_fs();
set_fs (KERNEL_DS);
err = sys_quotactl(cmd, (const char *)spec, id, (__kernel_caddr_t)&d);
set_fs (old_fs);
putname (spec);
if (err)
return err;
if (cmds == Q_GETQUOTA) {
if (cmds == Q_COMP_GETQUOTA) {
__kernel_time_t b = d.dqb_btime, i = d.dqb_itime;
((struct mem_dqblk32 *)&d)->dqb_itime = i;
((struct mem_dqblk32 *)&d)->dqb_btime = b;
if (copy_to_user ((struct mem_dqblk32 *)addr, &d,
sizeof (struct mem_dqblk32)))
((struct user_dqblk32 *)&d)->dqb_itime = i;
((struct user_dqblk32 *)&d)->dqb_btime = b;
if (copy_to_user ((struct user_dqblk32 *)addr, &d,
sizeof (struct user_dqblk32)))
return -EFAULT;
}
return 0;
}
#else
/* No conversion needed for new interface */
asmlinkage int sys32_quotactl(int cmd, const char *special, int id, caddr_t addr)
{
return sys_quotactl(cmd, special, id, addr);
}
#endif
static inline int put_statfs (struct statfs32 *ubuf, struct statfs *kbuf)
{
int err;
......
......@@ -889,7 +889,11 @@ asmlinkage long sys32_fcntl64(unsigned int fd, unsigned int cmd, unsigned long a
return sys32_fcntl(fd, cmd, arg);
}
struct dqblk32 {
extern asmlinkage int sys_quotactl(int cmd, const char *special, int id, caddr_t addr);
#ifdef CONFIG_QIFACE_COMPAT
#ifdef CONFIG_QIFACE_V1
struct user_dqblk32 {
__u32 dqb_bhardlimit;
__u32 dqb_bsoftlimit;
__u32 dqb_curblocks;
......@@ -899,52 +903,83 @@ struct dqblk32 {
__kernel_time_t32 dqb_btime;
__kernel_time_t32 dqb_itime;
};
typedef struct v1c_mem_dqblk comp_dqblk_t;
#define Q_COMP_GETQUOTA Q_V1_GETQUOTA
#define Q_COMP_SETQUOTA Q_V1_SETQUOTA
#define Q_COMP_SETQLIM Q_V1_SETQLIM
#define Q_COMP_SETUSE Q_V1_SETUSE
#else
struct user_dqblk32 {
__u32 dqb_ihardlimit;
__u32 dqb_isoftlimit;
__u32 dqb_curinodes;
__u32 dqb_bhardlimit;
__u32 dqb_bsoftlimit;
__u64 dqb_curspace;
__kernel_time_t32 dqb_btime;
__kernel_time_t32 dqb_itime;
};
typedef struct v2c_mem_dqblk comp_dqblk_t;
extern asmlinkage int sys_quotactl(int cmd, const char *special, int id, caddr_t addr);
#define Q_COMP_GETQUOTA Q_V2_GETQUOTA
#define Q_COMP_SETQUOTA Q_V2_SETQUOTA
#define Q_COMP_SETQLIM Q_V2_SETQLIM
#define Q_COMP_SETUSE Q_V2_SETUSE
#endif
asmlinkage int sys32_quotactl(int cmd, const char *special, int id, unsigned long addr)
asmlinkage int sys32_quotactl(int cmd, const char *special, int id, caddr_t addr)
{
int cmds = cmd >> SUBCMDSHIFT;
int err;
struct dqblk d;
comp_dqblk_t d;
mm_segment_t old_fs;
char *spec;
switch (cmds) {
case Q_GETQUOTA:
case Q_COMP_GETQUOTA:
break;
case Q_SETQUOTA:
case Q_SETUSE:
case Q_SETQLIM:
if (copy_from_user (&d, (struct dqblk32 *)addr,
sizeof (struct dqblk32)))
case Q_COMP_SETQUOTA:
case Q_COMP_SETUSE:
case Q_COMP_SETQLIM:
if (copy_from_user(&d, (struct user_dqblk32 *)addr,
sizeof (struct user_dqblk32)))
return -EFAULT;
d.dqb_itime = ((struct dqblk32 *)&d)->dqb_itime;
d.dqb_btime = ((struct dqblk32 *)&d)->dqb_btime;
d.dqb_itime = ((struct user_dqblk32 *)&d)->dqb_itime;
d.dqb_btime = ((struct user_dqblk32 *)&d)->dqb_btime;
break;
default:
return sys_quotactl(cmd, special,
id, (caddr_t)addr);
return sys_quotactl(cmd, special, id, (__kernel_caddr_t)addr);
}
spec = getname (special);
err = PTR_ERR(spec);
if (IS_ERR(spec)) return err;
old_fs = get_fs ();
old_fs = get_fs();
set_fs (KERNEL_DS);
err = sys_quotactl(cmd, (const char *)spec, id, (caddr_t)&d);
err = sys_quotactl(cmd, (const char *)spec, id, (__kernel_caddr_t)&d);
set_fs (old_fs);
putname (spec);
if (cmds == Q_GETQUOTA) {
if (err)
return err;
if (cmds == Q_COMP_GETQUOTA) {
__kernel_time_t b = d.dqb_btime, i = d.dqb_itime;
((struct dqblk32 *)&d)->dqb_itime = i;
((struct dqblk32 *)&d)->dqb_btime = b;
if (copy_to_user ((struct dqblk32 *)addr, &d,
sizeof (struct dqblk32)))
((struct user_dqblk32 *)&d)->dqb_itime = i;
((struct user_dqblk32 *)&d)->dqb_btime = b;
if (copy_to_user ((struct user_dqblk32 *)addr, &d,
sizeof (struct user_dqblk32)))
return -EFAULT;
}
return err;
return 0;
}
#else
/* No conversion needed for new interface */
asmlinkage int sys32_quotactl(int cmd, const char *special, int id, caddr_t addr)
{
return sys_quotactl(cmd, special, id, addr);
}
#endif
static inline int put_statfs (struct statfs32 *ubuf, struct statfs *kbuf)
{
int err;
......
......@@ -194,7 +194,7 @@ sunos_sys_table:
.word sunos_getdirentries, sys32_statfs, sys32_fstatfs
.word sys_oldumount, sunos_nosys, sunos_nosys
.word sys_getdomainname, sys_setdomainname
.word sunos_nosys, sys32_quotactl, sunos_nosys
.word sunos_nosys, sys_quotactl, sunos_nosys
.word sunos_mount, sys_ustat, sunos_semsys
.word sunos_nosys, sunos_shmsys, sunos_audit
.word sunos_nosys, sunos_getdents, sys_setsid
......
CONFIG_QUOTA
If you say Y here, you will be able to set per user limits for disk
usage (also called disk quotas). Currently, it works only for the
ext2 file system. You need additional software in order to use quota
support; for details, read the Quota mini-HOWTO, available from
usage (also called disk quotas). Currently, it works for the
ext2, ext3, and reiserfs file system. You need additional software
in order to use quota support (you can download sources from
<http://www.sf.net/projects/linuxquota/>). For further details, read
the Quota mini-HOWTO, available from
<http://www.linuxdoc.org/docs.html#howto>. Probably the quota
support is only useful for multi user systems. If unsure, say N.
CONFIG_QFMT_V1
This quota format was (is) used by kernels earlier than 2.4.??. If
you have quota working and you don't want to convert to new quota
format say Y here.
CONFIG_QFMT_V2
This quota format allows using quotas with 32-bit UIDs/GIDs. If you
need this functionality say Y here. Note that you will need latest
quota utilities for new quota format with this kernel.
CONFIG_QIFACE_COMPAT
This option will enable old quota interface in kernel.
If you have old quota tools (version <= 3.04) and you don't want to
upgrade them say Y here.
CONFIG_QIFACE_V1
This is the oldest quota interface. It was used for old quota format.
If you have old quota tools and you use old quota format choose this
interface (if unsure, this interface is the best one to choose).
CONFIG_QIFACE_V2
This quota interface was used by VFS v0 quota format. If you need
support for VFS v0 quota format (eg. you're using quota on ReiserFS)
and you don't want to upgrade quota tools, choose this interface.
CONFIG_MINIX_FS
Minix is a simple operating system used in many classes about OS's.
The minix file system (method to organize files on a hard disk
......
......@@ -5,6 +5,14 @@ mainmenu_option next_comment
comment 'File systems'
bool 'Quota support' CONFIG_QUOTA
dep_tristate ' Old quota format support' CONFIG_QFMT_V1 $CONFIG_QUOTA
dep_tristate ' VFS v0 quota format support' CONFIG_QFMT_V2 $CONFIG_QUOTA
dep_mbool ' Compatible quota interfaces' CONFIG_QIFACE_COMPAT $CONFIG_QUOTA
if [ "$CONFIG_QUOTA" = "y" -a "$CONFIG_QIFACE_COMPAT" = "y" ]; then
choice ' Compatible quota interfaces' \
"Original CONFIG_QIFACE_V1 \
VFSv0 CONFIG_QIFACE_V2" Original
fi
tristate 'Kernel automounter support' CONFIG_AUTOFS_FS
tristate 'Kernel automounter version 4 support (also supports v3)' CONFIG_AUTOFS4_FS
......
......@@ -7,7 +7,7 @@
O_TARGET := fs.o
export-objs := filesystems.o open.o dcache.o buffer.o bio.o inode.o
export-objs := filesystems.o open.o dcache.o buffer.o bio.o inode.o dquot.o
mod-subdirs := nls
obj-y := open.o read_write.o devices.o file_table.o buffer.o \
......@@ -15,7 +15,7 @@ obj-y := open.o read_write.o devices.o file_table.o buffer.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 namespace.o seq_file.o xattr.o libfs.o \
fs-writeback.o
fs-writeback.o quota.o
ifneq ($(CONFIG_NFSD),n)
ifneq ($(CONFIG_NFSD),)
......@@ -82,6 +82,8 @@ obj-y += binfmt_script.o
obj-$(CONFIG_BINFMT_ELF) += binfmt_elf.o
obj-$(CONFIG_QUOTA) += dquot.o
obj-$(CONFIG_QFMT_V1) += quota_v1.o
obj-$(CONFIG_QFMT_V2) += quota_v2.o
# persistent filesystems
obj-y += $(join $(subdir-y),$(subdir-y:%=/%.o))
......
This diff is collapsed.
......@@ -99,6 +99,7 @@ static struct inode *alloc_inode(struct super_block *sb)
atomic_set(&inode->i_writecount, 0);
inode->i_size = 0;
inode->i_blocks = 0;
inode->i_bytes = 0;
inode->i_generation = 0;
memset(&inode->i_dquot, 0, sizeof(inode->i_dquot));
inode->i_pipe = NULL;
......@@ -978,9 +979,9 @@ void update_atime (struct inode *inode)
/* Functions back in dquot.c */
void put_dquot_list(struct list_head *);
int remove_inode_dquot_ref(struct inode *, short, struct list_head *);
int remove_inode_dquot_ref(struct inode *, int, struct list_head *);
void remove_dquot_ref(struct super_block *sb, short type)
void remove_dquot_ref(struct super_block *sb, int type)
{
struct inode *inode;
struct list_head *act_head;
......
......@@ -102,6 +102,16 @@ asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
filp->f_flags &= ~FASYNC;
break;
case FIOQSIZE:
if (S_ISDIR(filp->f_dentry->d_inode->i_mode) ||
S_ISREG(filp->f_dentry->d_inode->i_mode) ||
S_ISLNK(filp->f_dentry->d_inode->i_mode)) {
loff_t res = inode_get_bytes(filp->f_dentry->d_inode);
error = copy_to_user((loff_t *)arg, &res, sizeof(res)) ? -EFAULT : 0;
}
else
error = -ENOTTY;
break;
default:
error = -ENOTTY;
if (S_ISREG(filp->f_dentry->d_inode->i_mode))
......
This diff is collapsed.
#include <linux/errno.h>
#include <linux/fs.h>
#include <linux/quota.h>
#include <linux/dqblk_v1.h>
#include <linux/quotaio_v1.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <asm/uaccess.h>
#include <asm/byteorder.h>
static void v1_disk2mem_dqblk(struct mem_dqblk *m, struct v1_disk_dqblk *d)
{
m->dqb_ihardlimit = d->dqb_ihardlimit;
m->dqb_isoftlimit = d->dqb_isoftlimit;
m->dqb_curinodes = d->dqb_curinodes;
m->dqb_bhardlimit = d->dqb_bhardlimit;
m->dqb_bsoftlimit = d->dqb_bsoftlimit;
m->dqb_curspace = d->dqb_curblocks << QUOTABLOCK_BITS;
m->dqb_itime = d->dqb_itime;
m->dqb_btime = d->dqb_btime;
}
static void v1_mem2disk_dqblk(struct v1_disk_dqblk *d, struct mem_dqblk *m)
{
d->dqb_ihardlimit = m->dqb_ihardlimit;
d->dqb_isoftlimit = m->dqb_isoftlimit;
d->dqb_curinodes = m->dqb_curinodes;
d->dqb_bhardlimit = m->dqb_bhardlimit;
d->dqb_bsoftlimit = m->dqb_bsoftlimit;
d->dqb_curblocks = toqb(m->dqb_curspace);
d->dqb_itime = m->dqb_itime;
d->dqb_btime = m->dqb_btime;
}
static int v1_read_dqblk(struct dquot *dquot)
{
int type = dquot->dq_type;
struct file *filp;
mm_segment_t fs;
loff_t offset;
struct v1_disk_dqblk dqblk;
filp = sb_dqopt(dquot->dq_sb)->files[type];
if (filp == (struct file *)NULL)
return -EINVAL;
/* Now we are sure filp is valid */
offset = v1_dqoff(dquot->dq_id);
fs = get_fs();
set_fs(KERNEL_DS);
filp->f_op->read(filp, (char *)&dqblk, sizeof(struct v1_disk_dqblk), &offset);
set_fs(fs);
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)
dquot->dq_flags |= DQ_FAKE;
dqstats.reads++;
return 0;
}
static int v1_commit_dqblk(struct dquot *dquot)
{
short type = dquot->dq_type;
struct file *filp;
mm_segment_t fs;
loff_t offset;
ssize_t ret;
struct v1_disk_dqblk dqblk;
filp = sb_dqopt(dquot->dq_sb)->files[type];
offset = v1_dqoff(dquot->dq_id);
fs = get_fs();
set_fs(KERNEL_DS);
/*
* Note: clear the DQ_MOD flag unconditionally,
* so we don't loop forever on failure.
*/
v1_mem2disk_dqblk(&dqblk, &dquot->dq_dqb);
dquot->dq_flags &= ~DQ_MOD;
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 (filp)
ret = filp->f_op->write(filp, (char *)&dqblk,
sizeof(struct v1_disk_dqblk), &offset);
if (ret != sizeof(struct v1_disk_dqblk)) {
printk(KERN_WARNING "VFS: dquota write failed on dev %s\n",
kdevname(dquot->dq_sb->s_dev));
if (ret >= 0)
ret = -EIO;
goto out;
}
ret = 0;
out:
set_fs(fs);
dqstats.writes++;
return ret;
}
/* Magics of new quota format */
#define V2_INITQMAGICS {\
0xd9c01f11, /* USRQUOTA */\
0xd9c01927 /* GRPQUOTA */\
}
/* Header of new quota format */
struct v2_disk_dqheader {
__u32 dqh_magic; /* Magic number identifying file */
__u32 dqh_version; /* File version */
};
static int v1_check_quota_file(struct super_block *sb, int type)
{
struct file *f = sb_dqopt(sb)->files[type];
struct inode *inode = f->f_dentry->d_inode;
ulong blocks;
size_t off;
struct v2_disk_dqheader dqhead;
mm_segment_t fs;
ssize_t size;
loff_t offset = 0;
static const uint quota_magics[] = V2_INITQMAGICS;
if (!inode->i_size)
return 0;
blocks = inode->i_size >> BLOCK_SIZE_BITS;
off = inode->i_size & (BLOCK_SIZE - 1);
if ((blocks % sizeof(struct v1_disk_dqblk) * BLOCK_SIZE + off) % sizeof(struct v1_disk_dqblk))
return 0;
/* Doublecheck whether we didn't get file with new format - with old quotactl() this could happen */
fs = get_fs();
set_fs(KERNEL_DS);
size = f->f_op->read(f, (char *)&dqhead, sizeof(struct v2_disk_dqheader), &offset);
set_fs(fs);
if (size != sizeof(struct v2_disk_dqheader))
return 1; /* Probably not new format */
if (le32_to_cpu(dqhead.dqh_magic) != quota_magics[type])
return 1; /* Definitely not new format */
printk(KERN_INFO "VFS: %s: Refusing to turn on old quota format on given file. It probably contains newer quota format.\n", kdevname(sb->s_dev));
return 0; /* Seems like a new format file -> refuse it */
}
static int v1_read_file_info(struct super_block *sb, int type)
{
struct quota_info *dqopt = sb_dqopt(sb);
mm_segment_t fs;
loff_t offset;
struct file *filp = dqopt->files[type];
struct v1_disk_dqblk dqblk;
int ret;
down(&dqopt->dqio_sem);
offset = v1_dqoff(0);
fs = get_fs();
set_fs(KERNEL_DS);
if ((ret = filp->f_op->read(filp, (char *)&dqblk, sizeof(struct v1_disk_dqblk), &offset)) != sizeof(struct v1_disk_dqblk)) {
if (ret >= 0)
ret = -EIO;
goto out;
}
ret = 0;
dqopt->info[type].dqi_igrace = dqblk.dqb_itime ? dqblk.dqb_itime : MAX_IQ_TIME;
dqopt->info[type].dqi_bgrace = dqblk.dqb_btime ? dqblk.dqb_btime : MAX_DQ_TIME;
out:
up(&dqopt->dqio_sem);
set_fs(fs);
return ret;
}
static int v1_write_file_info(struct super_block *sb, int type)
{
struct quota_info *dqopt = sb_dqopt(sb);
mm_segment_t fs;
struct file *filp = dqopt->files[type];
struct v1_disk_dqblk dqblk;
loff_t offset;
int ret;
down(&dqopt->dqio_sem);
dqopt->info[type].dqi_flags &= ~DQF_INFO_DIRTY;
offset = v1_dqoff(0);
fs = get_fs();
set_fs(KERNEL_DS);
if ((ret = filp->f_op->read(filp, (char *)&dqblk, sizeof(struct v1_disk_dqblk), &offset)) != sizeof(struct v1_disk_dqblk)) {
if (ret >= 0)
ret = -EIO;
goto out;
}
dqblk.dqb_itime = dqopt->info[type].dqi_igrace;
dqblk.dqb_btime = dqopt->info[type].dqi_bgrace;
offset = v1_dqoff(0);
ret = filp->f_op->write(filp, (char *)&dqblk, sizeof(struct v1_disk_dqblk), &offset);
if (ret == sizeof(struct v1_disk_dqblk))
ret = 0;
else if (ret > 0)
ret = -EIO;
out:
up(&dqopt->dqio_sem);
set_fs(fs);
return ret;
}
static struct quota_format_ops v1_format_ops = {
check_quota_file: v1_check_quota_file,
read_file_info: v1_read_file_info,
write_file_info: v1_write_file_info,
free_file_info: NULL,
read_dqblk: v1_read_dqblk,
commit_dqblk: v1_commit_dqblk,
};
static struct quota_format_type v1_quota_format = {
qf_fmt_id: QFMT_VFS_OLD,
qf_ops: &v1_format_ops,
qf_owner: THIS_MODULE
};
static int __init init_v1_quota_format(void)
{
return register_quota_format(&v1_quota_format);
}
static void __exit exit_v1_quota_format(void)
{
unregister_quota_format(&v1_quota_format);
}
EXPORT_NO_SYMBOLS;
module_init(init_v1_quota_format);
module_exit(exit_v1_quota_format);
This diff is collapsed.
......@@ -27,6 +27,7 @@
#include <linux/devfs_fs_kernel.h>
#include <linux/acct.h>
#include <linux/blkdev.h>
#include <linux/quotaops.h>
#include <asm/uaccess.h>
void get_filesystem(struct file_system_type *fs);
......@@ -62,6 +63,8 @@ static struct super_block *alloc_super(void)
sema_init(&s->s_dquot.dqio_sem, 1);
sema_init(&s->s_dquot.dqoff_sem, 1);
s->s_maxbytes = MAX_NON_LFS;
s->dq_op = sb_dquot_ops;
s->s_qcop = sb_quotactl_ops;
}
return s;
}
......
......@@ -9,6 +9,7 @@
#define FIONBIO _IOW('f', 126, int)
#define FIONREAD _IOR('f', 127, int)
#define TIOCINQ FIONREAD
#define FIOQSIZE _IOR('f', 128, loff_t)
#define TIOCGETP _IOR('t', 8, struct sgttyb)
#define TIOCSETP _IOW('t', 9, struct sgttyb)
......
......@@ -69,6 +69,7 @@
#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
#define TIOCGHAYESESP 0x545E /* Get Hayes ESP configuration */
#define TIOCSHAYESESP 0x545F /* Set Hayes ESP configuration */
#define FIOQSIZE 0x5460
/* Used for packet mode */
#define TIOCPKT_DATA 0
......
......@@ -67,6 +67,7 @@
#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
#define TIOCGHAYESESP 0x545E /* Get Hayes ESP configuration */
#define TIOCSHAYESESP 0x545F /* Set Hayes ESP configuration */
#define FIOQSIZE 0x5460
/* Used for packet mode */
#define TIOCPKT_DATA 0
......
......@@ -72,6 +72,7 @@
#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
#define TIOCGHAYESESP 0x545E /* Get Hayes ESP configuration */
#define TIOCSHAYESESP 0x545F /* Set Hayes ESP configuration */
#define FIOQSIZE 0x5460
/* Used for packet mode */
#define TIOCPKT_DATA 0
......
......@@ -65,6 +65,7 @@
#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */
#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
#define FIOQSIZE 0x545E
/* Used for packet mode */
#define TIOCPKT_DATA 0
......
......@@ -67,6 +67,7 @@
#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
#define TIOCGHAYESESP 0x545E /* Get Hayes ESP configuration */
#define TIOCSHAYESESP 0x545F /* Set Hayes ESP configuration */
#define FIOQSIZE 0x5460 /* Get exact space used by quota */
/* Used for packet mode */
#define TIOCPKT_DATA 0
......
......@@ -9,6 +9,7 @@
#define FIONBIO _IOW('f', 126, int)
#define FIONREAD _IOR('f', 127, int)
#define TIOCINQ FIONREAD
#define FIOQSIZE _IOR('f', 128, loff_t)
#define TCGETS 0x5401
#define TCSETS 0x5402
......
......@@ -86,6 +86,7 @@
#define FIONBIO _IOW('f', 126, int)
#define FIONREAD _IOR('f', 127, int)
#define TIOCINQ FIONREAD
#define FIOQSIZE _IOR('f', 128, loff_t)
/* SCARY Rutgers local SunOS kernel hackery, perhaps I will support it
* someday. This is completely bogus, I know...
......
......@@ -87,6 +87,7 @@
#define FIONBIO _IOW('f', 126, int)
#define FIONREAD _IOR('f', 127, int)
#define TIOCINQ FIONREAD
#define FIOQSIZE _IOR('f', 128, loff_t)
/* SCARY Rutgers local SunOS kernel hackery, perhaps I will support it
* someday. This is completely bogus, I know...
......
/*
* File with in-memory structures of old quota format
*/
#ifndef _LINUX_DQBLK_V1_H
#define _LINUX_DQBLK_V1_H
/* Id of quota format */
#define QFMT_VFS_OLD 1
/* Root squash turned on */
#define V1_DQF_RSQUASH 1
/* Special information about quotafile */
struct v1_mem_dqinfo {
};
#endif /* _LINUX_DQBLK_V1_H */
/*
* Definitions of structures for vfsv0 quota format
*/
#ifndef _LINUX_DQBLK_V2_H
#define _LINUX_DQBLK_V2_H
#include <linux/types.h>
/* id numbers of quota format */
#define QFMT_VFS_V0 2
/* Inmemory copy of version specific information */
struct v2_mem_dqinfo {
unsigned int dqi_blocks;
unsigned int dqi_free_blk;
unsigned int dqi_free_entry;
};
#endif /* _LINUX_DQBLK_V2_H */
......@@ -368,6 +368,7 @@ struct inode {
unsigned long i_blksize;
unsigned long i_blocks;
unsigned long i_version;
unsigned short i_bytes;
struct semaphore i_sem;
struct inode_operations *i_op;
struct file_operations *i_fop; /* former ->i_op->default_file_ops */
......@@ -425,6 +426,39 @@ struct fown_struct {
int signum; /* posix.1b rt signal to be delivered on IO */
};
static inline void inode_add_bytes(struct inode *inode, loff_t bytes)
{
inode->i_blocks += bytes >> 9;
bytes &= 511;
inode->i_bytes += bytes;
if (inode->i_bytes >= 512) {
inode->i_blocks++;
inode->i_bytes -= 512;
}
}
static inline void inode_sub_bytes(struct inode *inode, loff_t bytes)
{
inode->i_blocks -= bytes >> 9;
bytes &= 511;
if (inode->i_bytes < bytes) {
inode->i_blocks--;
inode->i_bytes += 512;
}
inode->i_bytes -= bytes;
}
static inline loff_t inode_get_bytes(struct inode *inode)
{
return (((loff_t)inode->i_blocks) << 9) + inode->i_bytes;
}
static inline void inode_set_bytes(struct inode *inode, loff_t bytes)
{
inode->i_blocks = bytes >> 9;
inode->i_bytes = bytes & 511;
}
/*
* Track a single file's readahead state
*/
......@@ -581,20 +615,6 @@ struct nameidata {
struct vfsmount *old_mnt;
};
#define DQUOT_USR_ENABLED 0x01 /* User diskquotas enabled */
#define DQUOT_GRP_ENABLED 0x02 /* Group diskquotas enabled */
struct quota_mount_options
{
unsigned int flags; /* Flags for diskquotas on this device */
struct semaphore dqio_sem; /* lock device while I/O in progress */
struct semaphore dqoff_sem; /* serialize quota_off() and quota_on() on device */
struct file *files[MAXQUOTAS]; /* fp's to quotafiles */
time_t inode_expire[MAXQUOTAS]; /* expiretime for inode-quota */
time_t block_expire[MAXQUOTAS]; /* expiretime for block-quota */
char rsquash[MAXQUOTAS]; /* for quotas threat root as any other user */
};
/*
* Umount options
*/
......@@ -624,6 +644,7 @@ struct super_block {
struct file_system_type *s_type;
struct super_operations *s_op;
struct dquot_operations *dq_op;
struct quotactl_ops *s_qcop;
struct export_operations *s_export_op;
unsigned long s_flags;
unsigned long s_magic;
......@@ -642,7 +663,7 @@ struct super_block {
struct block_device *s_bdev;
struct list_head s_instances;
struct quota_mount_options s_dquot; /* Diskquota specific options */
struct quota_info s_dquot; /* Diskquota specific options */
char s_id[32]; /* Informational name */
......@@ -809,16 +830,6 @@ static inline void mark_inode_dirty_sync(struct inode *inode)
__mark_inode_dirty(inode, I_DIRTY_SYNC);
}
struct dquot_operations {
void (*initialize) (struct inode *, short);
void (*drop) (struct inode *);
int (*alloc_block) (struct inode *, unsigned long, char);
int (*alloc_inode) (const struct inode *, unsigned long);
void (*free_block) (struct inode *, unsigned long);
void (*free_inode) (const struct inode *, unsigned long);
int (*transfer) (struct inode *, struct iattr *);
};
/**
* &export_operations - for nfsd to communicate with file systems
......
This diff is collapsed.
/*
* Definition of symbols used for backward compatible interface
*/
#ifndef _LINUX_QUOTACOMPAT_
#define _LINUX_QUOTACOMPAT_
#include <linux/types.h>
#include <linux/quota.h>
struct v1c_mem_dqblk {
__u32 dqb_bhardlimit; /* absolute limit on disk blks alloc */
__u32 dqb_bsoftlimit; /* preferred limit on disk blks */
__u32 dqb_curblocks; /* current block count */
__u32 dqb_ihardlimit; /* maximum # allocated inodes */
__u32 dqb_isoftlimit; /* preferred inode limit */
__u32 dqb_curinodes; /* current # allocated inodes */
time_t dqb_btime; /* time limit for excessive disk use */
time_t dqb_itime; /* time limit for excessive files */
};
struct v1c_dqstats {
__u32 lookups;
__u32 drops;
__u32 reads;
__u32 writes;
__u32 cache_hits;
__u32 allocated_dquots;
__u32 free_dquots;
__u32 syncs;
};
struct v2c_mem_dqblk {
unsigned int dqb_ihardlimit;
unsigned int dqb_isoftlimit;
unsigned int dqb_curinodes;
unsigned int dqb_bhardlimit;
unsigned int dqb_bsoftlimit;
qsize_t dqb_curspace;
__kernel_time_t dqb_btime;
__kernel_time_t dqb_itime;
};
struct v2c_mem_dqinfo {
unsigned int dqi_bgrace;
unsigned int dqi_igrace;
unsigned int dqi_flags;
unsigned int dqi_blocks;
unsigned int dqi_free_blk;
unsigned int dqi_free_entry;
};
struct v2c_dqstats {
__u32 lookups;
__u32 drops;
__u32 reads;
__u32 writes;
__u32 cache_hits;
__u32 allocated_dquots;
__u32 free_dquots;
__u32 syncs;
__u32 version;
};
#define Q_COMP_QUOTAON 0x0100 /* enable quotas */
#define Q_COMP_QUOTAOFF 0x0200 /* disable quotas */
#define Q_COMP_SYNC 0x0600 /* sync disk copy of a filesystems quotas */
#define Q_V1_GETQUOTA 0x0300 /* get limits and usage */
#define Q_V1_SETQUOTA 0x0400 /* set limits and usage */
#define Q_V1_SETUSE 0x0500 /* set usage */
#define Q_V1_SETQLIM 0x0700 /* set limits */
#define Q_V1_GETSTATS 0x0800 /* get collected stats */
#define Q_V1_RSQUASH 0x1000 /* set root_squash option */
#define Q_V2_SETQLIM 0x0700 /* set limits */
#define Q_V2_GETINFO 0x0900 /* get info about quotas - graces, flags... */
#define Q_V2_SETINFO 0x0A00 /* set info about quotas */
#define Q_V2_SETGRACE 0x0B00 /* set inode and block grace */
#define Q_V2_SETFLAGS 0x0C00 /* set flags for quota */
#define Q_V2_GETQUOTA 0x0D00 /* get limits and usage */
#define Q_V2_SETQUOTA 0x0E00 /* set limits and usage */
#define Q_V2_SETUSE 0x0F00 /* set usage */
#define Q_V2_GETSTATS 0x1100 /* get collected stats */
#endif
#ifndef _LINUX_QUOTAIO_V1_H
#define _LINUX_QUOTAIO_V1_H
#include <linux/types.h>
/*
* The following constants define the amount of time given a user
* before the soft limits are treated as hard limits (usually resulting
* in an allocation failure). The timer is started when the user crosses
* their soft limit, it is reset when they go below their soft limit.
*/
#define MAX_IQ_TIME 604800 /* (7*24*60*60) 1 week */
#define MAX_DQ_TIME 604800 /* (7*24*60*60) 1 week */
/*
* The following structure defines the format of the disk quota file
* (as it appears on disk) - the file is an array of these structures
* indexed by user or group number.
*/
struct v1_disk_dqblk {
__u32 dqb_bhardlimit; /* absolute limit on disk blks alloc */
__u32 dqb_bsoftlimit; /* preferred limit on disk blks */
__u32 dqb_curblocks; /* current block count */
__u32 dqb_ihardlimit; /* absolute limit on allocated inodes */
__u32 dqb_isoftlimit; /* preferred inode limit */
__u32 dqb_curinodes; /* current # allocated inodes */
time_t dqb_btime; /* time limit for excessive disk use */
time_t dqb_itime; /* time limit for excessive inode use */
};
#define v1_dqoff(UID) ((loff_t)((UID) * sizeof (struct v1_disk_dqblk)))
#endif /* _LINUX_QUOTAIO_V1_H */
/*
* Definitions of structures for vfsv0 quota format
*/
#ifndef _LINUX_QUOTAIO_V2_H
#define _LINUX_QUOTAIO_V2_H
#include <linux/types.h>
#include <linux/quota.h>
/*
* Definitions of magics and versions of current quota files
*/
#define V2_INITQMAGICS {\
0xd9c01f11, /* USRQUOTA */\
0xd9c01927 /* GRPQUOTA */\
}
#define V2_INITQVERSIONS {\
0, /* USRQUOTA */\
0 /* GRPQUOTA */\
}
/*
* The following structure defines the format of the disk quota file
* (as it appears on disk) - the file is a radix tree whose leaves point
* to blocks of these structures.
*/
struct v2_disk_dqblk {
__u32 dqb_id; /* id this quota applies to */
__u32 dqb_ihardlimit; /* absolute limit on allocated inodes */
__u32 dqb_isoftlimit; /* preferred inode limit */
__u32 dqb_curinodes; /* current # allocated inodes */
__u32 dqb_bhardlimit; /* absolute limit on disk space (in QUOTABLOCK_SIZE) */
__u32 dqb_bsoftlimit; /* preferred limit on disk space (in QUOTABLOCK_SIZE) */
__u64 dqb_curspace; /* current space occupied (in bytes) */
__u64 dqb_btime; /* time limit for excessive disk use */
__u64 dqb_itime; /* time limit for excessive inode use */
};
/*
* Here are header structures as written on disk and their in-memory copies
*/
/* First generic header */
struct v2_disk_dqheader {
__u32 dqh_magic; /* Magic number identifying file */
__u32 dqh_version; /* File version */
};
/* Header with type and version specific information */
struct v2_disk_dqinfo {
__u32 dqi_bgrace; /* Time before block soft limit becomes hard limit */
__u32 dqi_igrace; /* Time before inode soft limit becomes hard limit */
__u32 dqi_flags; /* Flags for quotafile (DQF_*) */
__u32 dqi_blocks; /* Number of blocks in file */
__u32 dqi_free_blk; /* Number of first free block in the list */
__u32 dqi_free_entry; /* Number of block with at least one free entry */
};
/*
* Structure of header of block with quota structures. It is padded to 16 bytes so
* there will be space for exactly 18 quota-entries in a block
*/
struct v2_disk_dqdbheader {
__u32 dqdh_next_free; /* Number of next block with free entry */
__u32 dqdh_prev_free; /* Number of previous block with free entry */
__u16 dqdh_entries; /* Number of valid entries in block */
__u16 dqdh_pad1;
__u32 dqdh_pad2;
};
#define V2_DQINFOOFF sizeof(struct v2_disk_dqheader) /* Offset of info header in file */
#define V2_DQBLKSIZE_BITS 10
#define V2_DQBLKSIZE (1 << V2_DQBLKSIZE_BITS) /* Size of block with quota structures */
#define V2_DQTREEOFF 1 /* Offset of tree in file in blocks */
#define V2_DQTREEDEPTH 4 /* Depth of quota tree */
#define V2_DQSTRINBLK ((V2_DQBLKSIZE - sizeof(struct v2_disk_dqdbheader)) / sizeof(struct v2_disk_dqblk)) /* Number of entries in one blocks */
#endif /* _LINUX_QUOTAIO_V2_H */
......@@ -20,15 +20,15 @@
/*
* declaration of quota_function calls in kernel.
*/
extern void dquot_initialize(struct inode *inode, short type);
extern void sync_dquots(struct super_block *sb, int type);
extern void dquot_initialize(struct inode *inode, int type);
extern void dquot_drop(struct inode *inode);
extern int quota_off(struct super_block *sb, short type);
extern int sync_dquots(struct super_block *sb, short type);
extern int dquot_alloc_block(struct inode *inode, unsigned long number, char prealloc);
extern int dquot_alloc_space(struct inode *inode, qsize_t number, int prealloc);
extern int dquot_alloc_inode(const struct inode *inode, unsigned long number);
extern void dquot_free_block(struct inode *inode, unsigned long number);
extern void dquot_free_space(struct inode *inode, qsize_t number);
extern void dquot_free_inode(const struct inode *inode, unsigned long number);
extern int dquot_transfer(struct inode *inode, struct iattr *iattr);
......@@ -36,7 +36,11 @@ extern int dquot_transfer(struct inode *inode, struct iattr *iattr);
/*
* Operations supported for diskquotas.
*/
#define sb_any_quota_enabled(sb) ((sb)->s_dquot.flags & (DQUOT_USR_ENABLED | DQUOT_GRP_ENABLED))
extern struct dquot_operations dquot_operations;
extern struct quotactl_ops vfs_quotactl_ops;
#define sb_dquot_ops (&dquot_operations)
#define sb_quotactl_ops (&vfs_quotactl_ops)
static __inline__ void DQUOT_INIT(struct inode *inode)
{
......@@ -59,50 +63,50 @@ static __inline__ void DQUOT_DROP(struct inode *inode)
unlock_kernel();
}
static __inline__ int DQUOT_PREALLOC_BLOCK_NODIRTY(struct inode *inode, int nr)
static __inline__ int DQUOT_PREALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr)
{
lock_kernel();
if (sb_any_quota_enabled(inode->i_sb)) {
/* Number of used blocks is updated in alloc_block() */
if (inode->i_sb->dq_op->alloc_block(inode, fs_to_dq_blocks(nr, inode->i_sb->s_blocksize), 1) == NO_QUOTA) {
/* Used space is updated in alloc_space() */
if (inode->i_sb->dq_op->alloc_space(inode, nr, 1) == NO_QUOTA) {
unlock_kernel();
return 1;
}
}
else
inode->i_blocks += nr << (inode->i_sb->s_blocksize_bits - 9);
inode_add_bytes(inode, nr);
unlock_kernel();
return 0;
}
static __inline__ int DQUOT_PREALLOC_BLOCK(struct inode *inode, int nr)
static __inline__ int DQUOT_PREALLOC_SPACE(struct inode *inode, qsize_t nr)
{
int ret;
if (!(ret = DQUOT_PREALLOC_BLOCK_NODIRTY(inode, nr)))
if (!(ret = DQUOT_PREALLOC_SPACE_NODIRTY(inode, nr)))
mark_inode_dirty(inode);
return ret;
}
static __inline__ int DQUOT_ALLOC_BLOCK_NODIRTY(struct inode *inode, int nr)
static __inline__ int DQUOT_ALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr)
{
lock_kernel();
if (sb_any_quota_enabled(inode->i_sb)) {
/* Number of used blocks is updated in alloc_block() */
if (inode->i_sb->dq_op->alloc_block(inode, fs_to_dq_blocks(nr, inode->i_sb->s_blocksize), 0) == NO_QUOTA) {
/* Used space is updated in alloc_space() */
if (inode->i_sb->dq_op->alloc_space(inode, nr, 0) == NO_QUOTA) {
unlock_kernel();
return 1;
}
}
else
inode->i_blocks += nr << (inode->i_sb->s_blocksize_bits - 9);
inode_add_bytes(inode, nr);
unlock_kernel();
return 0;
}
static __inline__ int DQUOT_ALLOC_BLOCK(struct inode *inode, int nr)
static __inline__ int DQUOT_ALLOC_SPACE(struct inode *inode, qsize_t nr)
{
int ret;
if (!(ret = DQUOT_ALLOC_BLOCK_NODIRTY(inode, nr)))
if (!(ret = DQUOT_ALLOC_SPACE_NODIRTY(inode, nr)))
mark_inode_dirty(inode);
return ret;
}
......@@ -121,19 +125,19 @@ static __inline__ int DQUOT_ALLOC_INODE(struct inode *inode)
return 0;
}
static __inline__ void DQUOT_FREE_BLOCK_NODIRTY(struct inode *inode, int nr)
static __inline__ void DQUOT_FREE_SPACE_NODIRTY(struct inode *inode, qsize_t nr)
{
lock_kernel();
if (sb_any_quota_enabled(inode->i_sb))
inode->i_sb->dq_op->free_block(inode, fs_to_dq_blocks(nr, inode->i_sb->s_blocksize));
inode->i_sb->dq_op->free_space(inode, nr);
else
inode->i_blocks -= nr << (inode->i_sb->s_blocksize_bits - 9);
inode_sub_bytes(inode, nr);
unlock_kernel();
}
static __inline__ void DQUOT_FREE_BLOCK(struct inode *inode, int nr)
static __inline__ void DQUOT_FREE_SPACE(struct inode *inode, qsize_t nr)
{
DQUOT_FREE_BLOCK_NODIRTY(inode, nr);
DQUOT_FREE_SPACE_NODIRTY(inode, nr);
mark_inode_dirty(inode);
}
......@@ -160,13 +164,25 @@ static __inline__ int DQUOT_TRANSFER(struct inode *inode, struct iattr *iattr)
}
#define DQUOT_SYNC(sb) sync_dquots(sb, -1)
#define DQUOT_OFF(sb) quota_off(sb, -1)
static __inline__ int DQUOT_OFF(struct super_block *sb)
{
int ret = -ENOSYS;
lock_kernel();
if (sb->s_qcop && sb->s_qcop->quota_off)
ret = sb->s_qcop->quota_off(sb, -1);
unlock_kernel();
return ret;
}
#else
/*
* NO-OP when quota not configured.
*/
#define sb_dquot_ops (NULL)
#define sb_quotactl_ops (NULL)
#define DQUOT_INIT(inode) do { } while(0)
#define DQUOT_DROP(inode) do { } while(0)
#define DQUOT_ALLOC_INODE(inode) (0)
......@@ -174,48 +190,56 @@ static __inline__ int DQUOT_TRANSFER(struct inode *inode, struct iattr *iattr)
#define DQUOT_SYNC(sb) do { } while(0)
#define DQUOT_OFF(sb) do { } while(0)
#define DQUOT_TRANSFER(inode, iattr) (0)
extern __inline__ int DQUOT_PREALLOC_BLOCK_NODIRTY(struct inode *inode, int nr)
extern __inline__ int DQUOT_PREALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr)
{
lock_kernel();
inode->i_blocks += nr << (inode->i_sb->s_blocksize_bits - 9);
inode_add_bytes(inode, nr);
unlock_kernel();
return 0;
}
extern __inline__ int DQUOT_PREALLOC_BLOCK(struct inode *inode, int nr)
extern __inline__ int DQUOT_PREALLOC_SPACE(struct inode *inode, qsize_t nr)
{
DQUOT_PREALLOC_BLOCK_NODIRTY(inode, nr);
DQUOT_PREALLOC_SPACE_NODIRTY(inode, nr);
mark_inode_dirty(inode);
return 0;
}
extern __inline__ int DQUOT_ALLOC_BLOCK_NODIRTY(struct inode *inode, int nr)
extern __inline__ int DQUOT_ALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr)
{
lock_kernel();
inode->i_blocks += nr << (inode->i_sb->s_blocksize_bits - 9);
inode_add_bytes(inode, nr);
unlock_kernel();
return 0;
}
extern __inline__ int DQUOT_ALLOC_BLOCK(struct inode *inode, int nr)
extern __inline__ int DQUOT_ALLOC_SPACE(struct inode *inode, qsize_t nr)
{
DQUOT_ALLOC_BLOCK_NODIRTY(inode, nr);
DQUOT_ALLOC_SPACE_NODIRTY(inode, nr);
mark_inode_dirty(inode);
return 0;
}
extern __inline__ void DQUOT_FREE_BLOCK_NODIRTY(struct inode *inode, int nr)
extern __inline__ void DQUOT_FREE_SPACE_NODIRTY(struct inode *inode, qsize_t nr)
{
lock_kernel();
inode->i_blocks -= nr << (inode->i_sb->s_blocksize_bits - 9);
inode_sub_bytes(inode, nr);
unlock_kernel();
}
extern __inline__ void DQUOT_FREE_BLOCK(struct inode *inode, int nr)
extern __inline__ void DQUOT_FREE_SPACE(struct inode *inode, qsize_t nr)
{
DQUOT_FREE_BLOCK_NODIRTY(inode, nr);
DQUOT_FREE_SPACE_NODIRTY(inode, nr);
mark_inode_dirty(inode);
}
#endif /* CONFIG_QUOTA */
#define DQUOT_PREALLOC_BLOCK_NODIRTY(inode, nr) DQUOT_PREALLOC_SPACE_NODIRTY(inode, ((qsize_t)(nr)) << (inode)->i_sb->s_blocksize_bits)
#define DQUOT_PREALLOC_BLOCK(inode, nr) DQUOT_PREALLOC_SPACE(inode, ((qsize_t)(nr)) << (inode)->i_sb->s_blocksize_bits)
#define DQUOT_ALLOC_BLOCK_NODIRTY(inode, nr) DQUOT_ALLOC_SPACE_NODIRTY(inode, ((qsize_t)(nr)) << (inode)->i_sb->s_blocksize_bits)
#define DQUOT_ALLOC_BLOCK(inode, nr) DQUOT_ALLOC_SPACE(inode, ((qsize_t)(nr)) << (inode)->i_sb->s_blocksize_bits)
#define DQUOT_FREE_BLOCK_NODIRTY(inode, nr) DQUOT_FREE_SPACE_NODIRTY(inode, ((qsize_t)(nr)) << (inode)->i_sb->s_blocksize_bits)
#define DQUOT_FREE_BLOCK(inode, nr) DQUOT_FREE_SPACE(inode, ((qsize_t)(nr)) << (inode)->i_sb->s_blocksize_bits)
#endif /* _LINUX_QUOTAOPS_ */
/*
* Copyright (c) 1995-2001 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.1 of the GNU Lesser 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 Lesser 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 */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment