Commit b80d2549 authored by Jan Kara's avatar Jan Kara Committed by Linus Torvalds

[PATCH] [2/13] quota-2-formats

This patch removes most format dependent code from dquot.c and quota.h
and puts calls of callback functions instead.
parent 61d681d6
...@@ -71,7 +71,7 @@ int nr_dquots, nr_free_dquots; ...@@ -71,7 +71,7 @@ int nr_dquots, nr_free_dquots;
static char *quotatypes[] = INITQFNAMES; static char *quotatypes[] = INITQFNAMES;
static inline struct quota_mount_options *sb_dqopt(struct super_block *sb) static inline struct quota_info *sb_dqopt(struct super_block *sb)
{ {
return &sb->s_dquot; return &sb->s_dquot;
} }
...@@ -121,7 +121,7 @@ static struct dqstats dqstats; ...@@ -121,7 +121,7 @@ static struct dqstats dqstats;
static void dqput(struct dquot *); static void dqput(struct dquot *);
static struct dquot *dqduplicate(struct dquot *); static struct dquot *dqduplicate(struct dquot *);
static inline char is_enabled(struct quota_mount_options *dqopt, short type) static inline char is_enabled(struct quota_info *dqopt, short type)
{ {
switch (type) { switch (type) {
case USRQUOTA: case USRQUOTA:
...@@ -296,73 +296,28 @@ static void __wait_dup_drop(struct dquot *dquot) ...@@ -296,73 +296,28 @@ static void __wait_dup_drop(struct dquot *dquot)
current->state = TASK_RUNNING; current->state = TASK_RUNNING;
} }
/* static int read_dqblk(struct dquot *dquot)
* We don't have to be afraid of deadlocks as we never have quotas on quota files...
*/
static void write_dquot(struct dquot *dquot)
{ {
short type = dquot->dq_type; int ret;
struct file *filp; struct quota_info *dqopt = sb_dqopt(dquot->dq_sb);
mm_segment_t fs;
loff_t offset;
ssize_t ret;
struct semaphore *sem = &dquot->dq_sb->s_dquot.dqio_sem;
struct dqblk dqbuf;
down(sem);
filp = dquot->dq_sb->s_dquot.files[type];
offset = dqoff(dquot->dq_id);
fs = get_fs();
set_fs(KERNEL_DS);
/* lock_dquot(dquot);
* Note: clear the DQ_MOD flag unconditionally, down(&dqopt->dqio_sem);
* so we don't loop forever on failure. ret = dqopt->ops[dquot->dq_type]->read_dqblk(dquot);
*/ up(&dqopt->dqio_sem);
memcpy(&dqbuf, &dquot->dq_dqb, sizeof(struct dqblk)); unlock_dquot(dquot);
dquot->dq_flags &= ~DQ_MOD; return ret;
ret = 0;
if (filp)
ret = filp->f_op->write(filp, (char *)&dqbuf,
sizeof(struct dqblk), &offset);
if (ret != sizeof(struct dqblk))
printk(KERN_WARNING "VFS: dquota write failed on dev %s\n",
dquot->dq_sb->s_id);
set_fs(fs);
up(sem);
dqstats.writes++;
} }
static void read_dquot(struct dquot *dquot) static int commit_dqblk(struct dquot *dquot)
{ {
short type = dquot->dq_type; int ret;
struct file *filp; struct quota_info *dqopt = sb_dqopt(dquot->dq_sb);
mm_segment_t fs;
loff_t offset;
filp = dquot->dq_sb->s_dquot.files[type]; down(&dqopt->dqio_sem);
if (filp == (struct file *)NULL) ret = dqopt->ops[dquot->dq_type]->commit_dqblk(dquot);
return; up(&dqopt->dqio_sem);
return ret;
lock_dquot(dquot);
if (!dquot->dq_sb) /* Invalidated quota? */
goto out_lock;
/* Now we are sure filp is valid - the dquot isn't invalidated */
down(&dquot->dq_sb->s_dquot.dqio_sem);
offset = dqoff(dquot->dq_id);
fs = get_fs();
set_fs(KERNEL_DS);
filp->f_op->read(filp, (char *)&dquot->dq_dqb, sizeof(struct dqblk), &offset);
up(&dquot->dq_sb->s_dquot.dqio_sem);
set_fs(fs);
if (dquot->dq_bhardlimit == 0 && dquot->dq_bsoftlimit == 0 &&
dquot->dq_ihardlimit == 0 && dquot->dq_isoftlimit == 0)
dquot->dq_flags |= DQ_FAKE;
dqstats.reads++;
out_lock:
unlock_dquot(dquot);
} }
/* Invalidate all dquots on the list, wait for all users. Note that this function is called /* Invalidate all dquots on the list, wait for all users. Note that this function is called
...@@ -412,7 +367,7 @@ int sync_dquots(struct super_block *sb, short type) ...@@ -412,7 +367,7 @@ int sync_dquots(struct super_block *sb, short type)
continue; continue;
if (!dquot->dq_sb) /* Invalidated? */ if (!dquot->dq_sb) /* Invalidated? */
continue; continue;
if (!(dquot->dq_flags & (DQ_MOD | DQ_LOCKED))) if (!dquot_dirty(dquot) && !(dquot->dq_flags & DQ_LOCKED))
continue; continue;
/* Get reference to quota so it won't be invalidated. get_dquot_ref() /* Get reference to quota so it won't be invalidated. get_dquot_ref()
* is enough since if dquot is locked/modified it can't be * is enough since if dquot is locked/modified it can't be
...@@ -420,8 +375,8 @@ int sync_dquots(struct super_block *sb, short type) ...@@ -420,8 +375,8 @@ int sync_dquots(struct super_block *sb, short type)
get_dquot_ref(dquot); get_dquot_ref(dquot);
if (dquot->dq_flags & DQ_LOCKED) if (dquot->dq_flags & DQ_LOCKED)
wait_on_dquot(dquot); wait_on_dquot(dquot);
if (dquot->dq_flags & DQ_MOD) if (dquot_dirty(dquot))
write_dquot(dquot); commit_dqblk(dquot);
dqput(dquot); dqput(dquot);
goto restart; goto restart;
} }
...@@ -502,8 +457,8 @@ static void dqput(struct dquot *dquot) ...@@ -502,8 +457,8 @@ static void dqput(struct dquot *dquot)
put_dquot_ref(dquot); put_dquot_ref(dquot);
return; return;
} }
if (dquot->dq_flags & DQ_MOD) { if (dquot_dirty(dquot)) {
write_dquot(dquot); commit_dqblk(dquot);
goto we_slept; goto we_slept;
} }
...@@ -520,7 +475,7 @@ static void dqput(struct dquot *dquot) ...@@ -520,7 +475,7 @@ static void dqput(struct dquot *dquot)
wake_up(&dquot->dq_wait_free); wake_up(&dquot->dq_wait_free);
} }
static struct dquot *get_empty_dquot(void) static struct dquot *get_empty_dquot(struct super_block *sb, int type)
{ {
struct dquot *dquot; struct dquot *dquot;
...@@ -534,6 +489,8 @@ static struct dquot *get_empty_dquot(void) ...@@ -534,6 +489,8 @@ static struct dquot *get_empty_dquot(void)
INIT_LIST_HEAD(&dquot->dq_free); INIT_LIST_HEAD(&dquot->dq_free);
INIT_LIST_HEAD(&dquot->dq_inuse); INIT_LIST_HEAD(&dquot->dq_inuse);
INIT_LIST_HEAD(&dquot->dq_hash); INIT_LIST_HEAD(&dquot->dq_hash);
dquot->dq_sb = sb;
dquot->dq_type = type;
dquot->dq_count = 1; dquot->dq_count = 1;
/* all dquots go on the inuse_list */ /* all dquots go on the inuse_list */
put_inuse(dquot); put_inuse(dquot);
...@@ -545,7 +502,7 @@ static struct dquot *dqget(struct super_block *sb, unsigned int id, short type) ...@@ -545,7 +502,7 @@ static struct dquot *dqget(struct super_block *sb, unsigned int id, short type)
{ {
unsigned int hashent = hashfn(sb, id, type); unsigned int hashent = hashfn(sb, id, type);
struct dquot *dquot, *empty = NODQUOT; struct dquot *dquot, *empty = NODQUOT;
struct quota_mount_options *dqopt = sb_dqopt(sb); struct quota_info *dqopt = sb_dqopt(sb);
we_slept: we_slept:
if (!is_enabled(dqopt, type)) { if (!is_enabled(dqopt, type)) {
...@@ -556,17 +513,15 @@ static struct dquot *dqget(struct super_block *sb, unsigned int id, short type) ...@@ -556,17 +513,15 @@ static struct dquot *dqget(struct super_block *sb, unsigned int id, short type)
if ((dquot = find_dquot(hashent, sb, id, type)) == NODQUOT) { if ((dquot = find_dquot(hashent, sb, id, type)) == NODQUOT) {
if (empty == NODQUOT) { if (empty == NODQUOT) {
if ((empty = get_empty_dquot()) == NODQUOT) if ((empty = get_empty_dquot(sb, type)) == NODQUOT)
schedule(); /* Try to wait for a moment... */ schedule(); /* Try to wait for a moment... */
goto we_slept; goto we_slept;
} }
dquot = empty; dquot = empty;
dquot->dq_id = id; dquot->dq_id = id;
dquot->dq_type = type;
dquot->dq_sb = sb;
/* hash it first so it can be found */ /* hash it first so it can be found */
insert_dquot_hash(dquot); insert_dquot_hash(dquot);
read_dquot(dquot); read_dqblk(dquot);
} else { } else {
if (!dquot->dq_count) if (!dquot->dq_count)
remove_free_dquot(dquot); remove_free_dquot(dquot);
...@@ -720,13 +675,13 @@ void put_dquot_list(struct list_head *tofree_head) ...@@ -720,13 +675,13 @@ void put_dquot_list(struct list_head *tofree_head)
static inline void dquot_incr_inodes(struct dquot *dquot, unsigned long number) static inline void dquot_incr_inodes(struct dquot *dquot, unsigned long number)
{ {
dquot->dq_curinodes += number; dquot->dq_curinodes += number;
dquot->dq_flags |= DQ_MOD; mark_dquot_dirty(dquot);
} }
static inline void dquot_incr_blocks(struct dquot *dquot, unsigned long number) static inline void dquot_incr_blocks(struct dquot *dquot, unsigned long number)
{ {
dquot->dq_curblocks += number; dquot->dq_curblocks += number;
dquot->dq_flags |= DQ_MOD; mark_dquot_dirty(dquot);
} }
static inline void dquot_decr_inodes(struct dquot *dquot, unsigned long number) static inline void dquot_decr_inodes(struct dquot *dquot, unsigned long number)
...@@ -738,7 +693,7 @@ static inline void dquot_decr_inodes(struct dquot *dquot, unsigned long number) ...@@ -738,7 +693,7 @@ static inline void dquot_decr_inodes(struct dquot *dquot, unsigned long number)
if (dquot->dq_curinodes < dquot->dq_isoftlimit) if (dquot->dq_curinodes < dquot->dq_isoftlimit)
dquot->dq_itime = (time_t) 0; dquot->dq_itime = (time_t) 0;
dquot->dq_flags &= ~DQ_INODES; dquot->dq_flags &= ~DQ_INODES;
dquot->dq_flags |= DQ_MOD; mark_dquot_dirty(dquot);
} }
static inline void dquot_decr_blocks(struct dquot *dquot, unsigned long number) static inline void dquot_decr_blocks(struct dquot *dquot, unsigned long number)
...@@ -750,7 +705,7 @@ static inline void dquot_decr_blocks(struct dquot *dquot, unsigned long number) ...@@ -750,7 +705,7 @@ static inline void dquot_decr_blocks(struct dquot *dquot, unsigned long number)
if (dquot->dq_curblocks < dquot->dq_bsoftlimit) if (dquot->dq_curblocks < dquot->dq_bsoftlimit)
dquot->dq_btime = (time_t) 0; dquot->dq_btime = (time_t) 0;
dquot->dq_flags &= ~DQ_BLKS; dquot->dq_flags &= ~DQ_BLKS;
dquot->dq_flags |= DQ_MOD; mark_dquot_dirty(dquot);
} }
static inline int need_print_warning(struct dquot *dquot, int flag) static inline int need_print_warning(struct dquot *dquot, int flag)
...@@ -823,7 +778,7 @@ static inline void flush_warnings(struct dquot **dquots, char *warntype) ...@@ -823,7 +778,7 @@ static inline void flush_warnings(struct dquot **dquots, char *warntype)
static inline char ignore_hardlimit(struct dquot *dquot) static inline char ignore_hardlimit(struct dquot *dquot)
{ {
return capable(CAP_SYS_RESOURCE) && !dquot->dq_sb->s_dquot.rsquash[dquot->dq_type]; return capable(CAP_SYS_RESOURCE);
} }
static int check_idq(struct dquot *dquot, ulong inodes, char *warntype) static int check_idq(struct dquot *dquot, ulong inodes, char *warntype)
...@@ -851,7 +806,7 @@ static int check_idq(struct dquot *dquot, ulong inodes, char *warntype) ...@@ -851,7 +806,7 @@ static int check_idq(struct dquot *dquot, ulong inodes, char *warntype)
(dquot->dq_curinodes + inodes) > dquot->dq_isoftlimit && (dquot->dq_curinodes + inodes) > dquot->dq_isoftlimit &&
dquot->dq_itime == 0) { dquot->dq_itime == 0) {
*warntype = ISOFTWARN; *warntype = ISOFTWARN;
dquot->dq_itime = CURRENT_TIME + dquot->dq_sb->s_dquot.inode_expire[dquot->dq_type]; dquot->dq_itime = CURRENT_TIME + sb_dqopt(dquot->dq_sb)->info[dquot->dq_type].dqi_igrace;
} }
return QUOTA_OK; return QUOTA_OK;
...@@ -885,7 +840,7 @@ static int check_bdq(struct dquot *dquot, ulong blocks, char prealloc, char *war ...@@ -885,7 +840,7 @@ static int check_bdq(struct dquot *dquot, ulong blocks, char prealloc, char *war
dquot->dq_btime == 0) { dquot->dq_btime == 0) {
if (!prealloc) { if (!prealloc) {
*warntype = BSOFTWARN; *warntype = BSOFTWARN;
dquot->dq_btime = CURRENT_TIME + dquot->dq_sb->s_dquot.block_expire[dquot->dq_type]; dquot->dq_btime = CURRENT_TIME + sb_dqopt(dquot->dq_sb)->info[dquot->dq_type].dqi_bgrace;
} }
else else
/* /*
...@@ -898,83 +853,6 @@ static int check_bdq(struct dquot *dquot, ulong blocks, char prealloc, char *war ...@@ -898,83 +853,6 @@ static int check_bdq(struct dquot *dquot, ulong blocks, char prealloc, char *war
return QUOTA_OK; return QUOTA_OK;
} }
/*
* 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, int id, short type, int flags, struct dqblk *dqblk)
{
struct dquot *dquot;
int error = -EFAULT;
struct dqblk dq_dqblk;
if (copy_from_user(&dq_dqblk, dqblk, sizeof(struct dqblk)))
return error;
if (sb && (dquot = dqget(sb, id, type)) != NODQUOT) {
/* We can't block while changing quota structure... */
if (id > 0 && ((flags & SET_QUOTA) || (flags & SET_QLIMIT))) {
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 (dquot->dq_isoftlimit &&
dquot->dq_curinodes < dquot->dq_isoftlimit &&
dq_dqblk.dqb_curinodes >= dquot->dq_isoftlimit)
dquot->dq_itime = CURRENT_TIME + dquot->dq_sb->s_dquot.inode_expire[type];
dquot->dq_curinodes = dq_dqblk.dqb_curinodes;
if (dquot->dq_curinodes < dquot->dq_isoftlimit)
dquot->dq_flags &= ~DQ_INODES;
if (dquot->dq_bsoftlimit &&
dquot->dq_curblocks < dquot->dq_bsoftlimit &&
dq_dqblk.dqb_curblocks >= dquot->dq_bsoftlimit)
dquot->dq_btime = CURRENT_TIME + dquot->dq_sb->s_dquot.block_expire[type];
dquot->dq_curblocks = dq_dqblk.dqb_curblocks;
if (dquot->dq_curblocks < dquot->dq_bsoftlimit)
dquot->dq_flags &= ~DQ_BLKS;
}
if (id == 0) {
dquot->dq_sb->s_dquot.block_expire[type] = dquot->dq_btime = dq_dqblk.dqb_btime;
dquot->dq_sb->s_dquot.inode_expire[type] = dquot->dq_itime = dq_dqblk.dqb_itime;
}
if (dq_dqblk.dqb_bhardlimit == 0 && dq_dqblk.dqb_bsoftlimit == 0 &&
dq_dqblk.dqb_ihardlimit == 0 && dq_dqblk.dqb_isoftlimit == 0)
dquot->dq_flags |= DQ_FAKE;
else
dquot->dq_flags &= ~DQ_FAKE;
dquot->dq_flags |= DQ_MOD;
dqput(dquot);
}
return 0;
}
static int get_quota(struct super_block *sb, int id, short type, struct dqblk *dqblk)
{
struct dquot *dquot;
struct dqblk data;
int error = -ESRCH;
if (!sb || !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 dqblk)); /* We copy data to preserve them from changing */
dqput(dquot);
error = -EFAULT;
if (dqblk && !copy_to_user(dqblk, &data, sizeof(struct dqblk)))
error = 0;
out:
return error;
}
static int get_stats(caddr_t addr) static int get_stats(caddr_t addr)
{ {
int error = -EFAULT; int error = -EFAULT;
...@@ -990,47 +868,6 @@ static int get_stats(caddr_t addr) ...@@ -990,47 +868,6 @@ static int get_stats(caddr_t addr)
return error; return error;
} }
static int quota_root_squash(struct super_block *sb, short type, int *addr)
{
int new_value, error;
if (!sb)
return(-ENODEV);
error = -EFAULT;
if (!copy_from_user(&new_value, addr, sizeof(int))) {
sb_dqopt(sb)->rsquash[type] = new_value;
error = 0;
}
return error;
}
#if 0 /* We are not going to support filesystems without i_blocks... */
/*
* This is a simple algorithm that calculates the size of a file in blocks.
* This is only used on filesystems that do not have an i_blocks count.
*/
static u_long isize_to_blocks(loff_t isize, size_t blksize_bits)
{
u_long blocks;
u_long indirect;
if (!blksize_bits)
blksize_bits = BLOCK_SIZE_BITS;
blocks = (isize >> blksize_bits) + ((isize & ~((1 << blksize_bits)-1)) ? 1 : 0);
if (blocks > 10) {
indirect = ((blocks - 11) >> 8) + 1; /* single indirect blocks */
if (blocks > (10 + 256)) {
indirect += ((blocks - 267) >> 16) + 1; /* double indirect blocks */
if (blocks > (10 + 256 + (256 << 8)))
indirect++; /* triple indirect blocks */
}
blocks += indirect;
}
return blocks;
}
#endif
/* /*
* Externally referenced functions through dquot_operations in inode. * Externally referenced functions through dquot_operations in inode.
* *
...@@ -1346,7 +1183,7 @@ struct dquot_operations dquot_operations = { ...@@ -1346,7 +1183,7 @@ struct dquot_operations dquot_operations = {
transfer: dquot_transfer transfer: dquot_transfer
}; };
static inline void set_enable_flags(struct quota_mount_options *dqopt, short type) static inline void set_enable_flags(struct quota_info *dqopt, short type)
{ {
switch (type) { switch (type) {
case USRQUOTA: case USRQUOTA:
...@@ -1358,7 +1195,7 @@ static inline void set_enable_flags(struct quota_mount_options *dqopt, short typ ...@@ -1358,7 +1195,7 @@ static inline void set_enable_flags(struct quota_mount_options *dqopt, short typ
} }
} }
static inline void reset_enable_flags(struct quota_mount_options *dqopt, short type) static inline void reset_enable_flags(struct quota_info *dqopt, short type)
{ {
switch (type) { switch (type) {
case USRQUOTA: case USRQUOTA:
...@@ -1380,7 +1217,7 @@ int quota_off(struct super_block *sb, short type) ...@@ -1380,7 +1217,7 @@ int quota_off(struct super_block *sb, short type)
{ {
struct file *filp; struct file *filp;
short cnt; short cnt;
struct quota_mount_options *dqopt = sb_dqopt(sb); struct quota_info *dqopt = sb_dqopt(sb);
lock_kernel(); lock_kernel();
if (!sb) if (!sb)
...@@ -1398,11 +1235,15 @@ int quota_off(struct super_block *sb, short type) ...@@ -1398,11 +1235,15 @@ int quota_off(struct super_block *sb, short type)
/* Note: these are blocking operations */ /* Note: these are blocking operations */
remove_dquot_ref(sb, cnt); remove_dquot_ref(sb, cnt);
invalidate_dquots(sb, cnt); invalidate_dquots(sb, cnt);
if (info_dirty(&dqopt->info[cnt]))
dqopt->ops[cnt]->write_file_info(sb, cnt);
filp = dqopt->files[cnt]; filp = dqopt->files[cnt];
dqopt->files[cnt] = (struct file *)NULL; dqopt->files[cnt] = (struct file *)NULL;
dqopt->inode_expire[cnt] = 0; dqopt->info[cnt].dqi_flags = 0;
dqopt->block_expire[cnt] = 0; dqopt->info[cnt].dqi_igrace = 0;
dqopt->info[cnt].dqi_bgrace = 0;
dqopt->ops[cnt] = NULL;
fput(filp); fput(filp);
} }
up(&dqopt->dqoff_sem); up(&dqopt->dqoff_sem);
...@@ -1411,20 +1252,12 @@ int quota_off(struct super_block *sb, short type) ...@@ -1411,20 +1252,12 @@ int quota_off(struct super_block *sb, short type)
return 0; return 0;
} }
static inline int check_quotafile_size(loff_t size)
{
ulong blocks = size >> BLOCK_SIZE_BITS;
size_t off = size & (BLOCK_SIZE - 1);
return !(((blocks % sizeof(struct dqblk)) * BLOCK_SIZE + off % sizeof(struct dqblk)) % sizeof(struct dqblk));
}
static int quota_on(struct super_block *sb, short type, char *path) static int quota_on(struct super_block *sb, short type, char *path)
{ {
struct file *f; struct file *f;
struct inode *inode; struct inode *inode;
struct dquot *dquot; struct dquot *dquot;
struct quota_mount_options *dqopt = sb_dqopt(sb); struct quota_info *dqopt = sb_dqopt(sb);
char *tmp; char *tmp;
int error; int error;
...@@ -1451,7 +1284,7 @@ static int quota_on(struct super_block *sb, short type, char *path) ...@@ -1451,7 +1284,7 @@ static int quota_on(struct super_block *sb, short type, char *path)
if (!S_ISREG(inode->i_mode)) if (!S_ISREG(inode->i_mode))
goto out_f; goto out_f;
error = -EINVAL; error = -EINVAL;
if (inode->i_size == 0 || !check_quotafile_size(inode->i_size)) if (!check_quota_file(sb, type))
goto out_f; goto out_f;
/* We don't want quota on quota files */ /* We don't want quota on quota files */
dquot_drop(inode); dquot_drop(inode);
...@@ -1461,11 +1294,6 @@ static int quota_on(struct super_block *sb, short type, char *path) ...@@ -1461,11 +1294,6 @@ static int quota_on(struct super_block *sb, short type, char *path)
sb->dq_op = &dquot_operations; sb->dq_op = &dquot_operations;
set_enable_flags(dqopt, type); set_enable_flags(dqopt, type);
dquot = dqget(sb, 0, type);
dqopt->inode_expire[type] = (dquot != NODQUOT) ? dquot->dq_itime : MAX_IQ_TIME;
dqopt->block_expire[type] = (dquot != NODQUOT) ? dquot->dq_btime : MAX_DQ_TIME;
dqput(dquot);
add_dquot_ref(sb, type); add_dquot_ref(sb, type);
up(&dqopt->dqoff_sem); up(&dqopt->dqoff_sem);
......
...@@ -586,15 +586,13 @@ struct nameidata { ...@@ -586,15 +586,13 @@ struct nameidata {
#define DQUOT_USR_ENABLED 0x01 /* User diskquotas enabled */ #define DQUOT_USR_ENABLED 0x01 /* User diskquotas enabled */
#define DQUOT_GRP_ENABLED 0x02 /* Group diskquotas enabled */ #define DQUOT_GRP_ENABLED 0x02 /* Group diskquotas enabled */
struct quota_mount_options struct quota_info {
{
unsigned int flags; /* Flags for diskquotas on this device */ unsigned int flags; /* Flags for diskquotas on this device */
struct semaphore dqio_sem; /* lock device while I/O in progress */ struct semaphore dqio_sem; /* lock device while I/O in progress */
struct semaphore dqoff_sem; /* serialize quota_off() and quota_on() on device */ struct semaphore dqoff_sem; /* serialize quota_off() and quota_on() on device */
struct file *files[MAXQUOTAS]; /* fp's to quotafiles */ struct file *files[MAXQUOTAS]; /* fp's to quotafiles */
time_t inode_expire[MAXQUOTAS]; /* expiretime for inode-quota */ struct mem_dqinfo info[MAXQUOTAS]; /* Information for each quota type */
time_t block_expire[MAXQUOTAS]; /* expiretime for block-quota */ struct quota_format_ops *ops[MAXQUOTAS]; /* Operations for each format */
char rsquash[MAXQUOTAS]; /* for quotas threat root as any other user */
}; };
/* /*
...@@ -643,7 +641,7 @@ struct super_block { ...@@ -643,7 +641,7 @@ struct super_block {
struct block_device *s_bdev; struct block_device *s_bdev;
struct list_head s_instances; 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 */ char s_id[32]; /* Informational name */
......
...@@ -40,10 +40,13 @@ ...@@ -40,10 +40,13 @@
#define _LINUX_QUOTA_ #define _LINUX_QUOTA_
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/types.h>
#define __DQUOT_VERSION__ "dquot_6.5.1" #define __DQUOT_VERSION__ "dquot_6.5.1"
#define __DQUOT_NUM_VERSION__ 6*10000+5*100+1 #define __DQUOT_NUM_VERSION__ 6*10000+5*100+1
typedef __kernel_uid32_t qid_t; /* Type in which we store ids in memory */
/* /*
* Convert diskblocks to blocks and the other way around. * Convert diskblocks to blocks and the other way around.
*/ */
...@@ -94,32 +97,49 @@ ...@@ -94,32 +97,49 @@
#define SUBCMDSHIFT 8 #define SUBCMDSHIFT 8
#define QCMD(cmd, type) (((cmd) << SUBCMDSHIFT) | ((type) & SUBCMDMASK)) #define QCMD(cmd, type) (((cmd) << SUBCMDSHIFT) | ((type) & SUBCMDMASK))
#define Q_QUOTAON 0x0100 /* enable quotas */
#define Q_QUOTAOFF 0x0200 /* disable quotas */
#define Q_GETQUOTA 0x0300 /* get limits and usage */
#define Q_SETQUOTA 0x0400 /* set limits and usage */
#define Q_SETUSE 0x0500 /* set usage */
#define Q_SYNC 0x0600 /* sync disk copy of a filesystems quotas */ #define Q_SYNC 0x0600 /* sync disk copy of a filesystems quotas */
#define Q_SETQLIM 0x0700 /* set limits */
#define Q_GETSTATS 0x0800 /* get collected stats */
#define Q_RSQUASH 0x1000 /* set root_squash option */
/* /*
* The following structure defines the format of the disk quota file * Data for one user/group kept in memory
* (as it appears on disk) - the file is an array of these structures
* indexed by user or group number.
*/ */
struct dqblk { struct mem_dqblk {
__u32 dqb_bhardlimit; /* absolute limit on disk blks alloc */ __u32 dqb_bhardlimit; /* absolute limit on disk blks alloc */
__u32 dqb_bsoftlimit; /* preferred limit on disk blks */ __u32 dqb_bsoftlimit; /* preferred limit on disk blks */
__u32 dqb_curblocks; /* current block count */ __u32 dqb_curblocks; /* current block count */
__u32 dqb_ihardlimit; /* absolute limit on allocated inodes */ __u32 dqb_ihardlimit; /* absolute limit on allocated inodes */
__u32 dqb_isoftlimit; /* preferred inode limit */ __u32 dqb_isoftlimit; /* preferred inode limit */
__u32 dqb_curinodes; /* current # allocated inodes */ __u32 dqb_curinodes; /* current # allocated inodes */
time_t dqb_btime; /* time limit for excessive disk use */ time_t dqb_btime; /* time limit for excessive disk use */
time_t dqb_itime; /* time limit for excessive inode use */ time_t dqb_itime; /* time limit for excessive inode use */
}; };
/*
* Data for one quotafile kept in memory
*/
struct mem_dqinfo {
int dqi_flags;
unsigned int dqi_bgrace;
unsigned int dqi_igrace;
union {
} u;
};
#ifdef __KERNEL__
#define DQF_MASK 0xffff /* Mask for format specific flags */
#define DQF_INFO_DIRTY 0x10000 /* Is info dirty? */
extern inline void mark_info_dirty(struct mem_dqinfo *info)
{
info->dqi_flags |= DQF_INFO_DIRTY;
}
#define info_dirty(info) ((info)->dqi_flags & DQF_INFO_DIRTY)
#define sb_dqopt(sb) (&(sb)->s_dquot)
#endif /* __KERNEL__ */
/* /*
* Shorthand notation. * Shorthand notation.
*/ */
...@@ -134,6 +154,11 @@ struct dqblk { ...@@ -134,6 +154,11 @@ struct dqblk {
#define dqoff(UID) ((loff_t)((UID) * sizeof (struct dqblk))) #define dqoff(UID) ((loff_t)((UID) * sizeof (struct dqblk)))
#ifdef __KERNEL__
extern int nr_dquots, nr_free_dquots;
extern int dquot_root_squash;
struct dqstats { struct dqstats {
__u32 lookups; __u32 lookups;
__u32 drops; __u32 drops;
...@@ -145,10 +170,6 @@ struct dqstats { ...@@ -145,10 +170,6 @@ struct dqstats {
__u32 syncs; __u32 syncs;
}; };
#ifdef __KERNEL__
extern int dquot_root_squash;
#define NR_DQHASH 43 /* Just an arbitrary number */ #define NR_DQHASH 43 /* Just an arbitrary number */
#define DQ_LOCKED 0x01 /* dquot under IO */ #define DQ_LOCKED 0x01 /* dquot under IO */
...@@ -174,21 +195,31 @@ struct dquot { ...@@ -174,21 +195,31 @@ struct dquot {
short dq_flags; /* See DQ_* */ short dq_flags; /* See DQ_* */
unsigned long dq_referenced; /* Number of times this dquot was unsigned long dq_referenced; /* Number of times this dquot was
referenced during its lifetime */ referenced during its lifetime */
struct dqblk dq_dqb; /* Diskquota usage */ struct mem_dqblk dq_dqb; /* Diskquota usage */
}; };
#define NODQUOT (struct dquot *)NULL extern inline void mark_dquot_dirty(struct dquot *dquot)
{
dquot->dq_flags |= DQ_MOD;
}
/* #define dquot_dirty(dquot) ((dquot)->dq_flags & DQ_MOD)
* Flags used for set_dqblk.
*/ #define NODQUOT (struct dquot *)NULL
#define SET_QUOTA 0x02
#define SET_USE 0x04
#define SET_QLIMIT 0x08
#define QUOTA_OK 0 #define QUOTA_OK 0
#define NO_QUOTA 1 #define NO_QUOTA 1
/* Operations which must be implemented by each quota format */
struct quota_format_ops {
int (*check_quota_file)(struct super_block *sb, int type); /* Detect whether file is in our format */
int (*read_file_info)(struct super_block *sb, int type); /* Read main info about file */
int (*write_file_info)(struct super_block *sb, int type); /* Write main info about file */
int (*free_file_info)(struct super_block *sb, int type); /* Called on quotaoff() */
int (*read_dqblk)(struct dquot *dquot); /* Read structure for one user */
int (*commit_dqblk)(struct dquot *dquot); /* Write (or delete) structure for one user */
};
#else #else
# /* nodep */ include <sys/cdefs.h> # /* nodep */ include <sys/cdefs.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