summaryrefslogtreecommitdiffstats
path: root/fs/dquot.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-03-23 02:25:38 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-03-23 02:25:38 +0000
commit16b5d462f73eb29d1f67fa01cc1ea66afdc72569 (patch)
tree5407bd573f4840e473ea27cbe61e5c7a07131fcd /fs/dquot.c
parentce8a076e11e7e5ee36007f9a3eee5bb3744cb8f6 (diff)
Merge with Linux 2.3.99-pre2.
Diffstat (limited to 'fs/dquot.c')
-rw-r--r--fs/dquot.c230
1 files changed, 110 insertions, 120 deletions
diff --git a/fs/dquot.c b/fs/dquot.c
index 61dcef366..c602697f5 100644
--- a/fs/dquot.c
+++ b/fs/dquot.c
@@ -66,6 +66,11 @@ static char *quotatypes[] = INITQFNAMES;
static kmem_cache_t *dquot_cachep;
+static inline struct quota_mount_options *sb_dqopt(struct super_block *sb)
+{
+ return &sb->s_dquot;
+}
+
/*
* Dquot List Management:
* The quota code uses three lists for dquot management: the inuse_list,
@@ -98,29 +103,20 @@ static DECLARE_WAIT_QUEUE_HEAD(update_wait);
static void dqput(struct dquot *);
static struct dquot *dqduplicate(struct dquot *);
-static inline char is_enabled(struct vfsmount *vfsmnt, short type)
+static inline char is_enabled(struct quota_mount_options *dqopt, short type)
{
switch (type) {
case USRQUOTA:
- return((vfsmnt->mnt_dquot.flags & DQUOT_USR_ENABLED) != 0);
+ return((dqopt->flags & DQUOT_USR_ENABLED) != 0);
case GRPQUOTA:
- return((vfsmnt->mnt_dquot.flags & DQUOT_GRP_ENABLED) != 0);
+ return((dqopt->flags & DQUOT_GRP_ENABLED) != 0);
}
return(0);
}
static inline char sb_has_quota_enabled(struct super_block *sb, short type)
{
- struct vfsmount *vfsmnt;
-
- return((vfsmnt = lookup_vfsmnt(sb->s_dev)) != (struct vfsmount *)NULL && is_enabled(vfsmnt, type));
-}
-
-static inline char dev_has_quota_enabled(kdev_t dev, short type)
-{
- struct vfsmount *vfsmnt;
-
- return((vfsmnt = lookup_vfsmnt(dev)) != (struct vfsmount *)NULL && is_enabled(vfsmnt, type));
+ return is_enabled(sb_dqopt(sb), type);
}
static inline int const hashfn(kdev_t dev, unsigned int id, short type)
@@ -253,15 +249,15 @@ static void write_dquot(struct dquot *dquot)
mm_segment_t fs;
loff_t offset;
ssize_t ret;
- struct semaphore *sem = &dquot->dq_mnt->mnt_dquot.dqio_sem;
+ struct semaphore *sem = &dquot->dq_sb->s_dquot.dqio_sem;
lock_dquot(dquot);
- if (!dquot->dq_mnt) { /* Invalidated quota? */
+ if (!dquot->dq_sb) { /* Invalidated quota? */
unlock_dquot(dquot);
return;
}
down(sem);
- filp = dquot->dq_mnt->mnt_dquot.files[type];
+ filp = dquot->dq_sb->s_dquot.files[type];
offset = dqoff(dquot->dq_id);
fs = get_fs();
set_fs(KERNEL_DS);
@@ -293,20 +289,20 @@ static void read_dquot(struct dquot *dquot)
mm_segment_t fs;
loff_t offset;
- filp = dquot->dq_mnt->mnt_dquot.files[type];
+ filp = dquot->dq_sb->s_dquot.files[type];
if (filp == (struct file *)NULL)
return;
lock_dquot(dquot);
- if (!dquot->dq_mnt) /* Invalidated quota? */
+ if (!dquot->dq_sb) /* Invalidated quota? */
goto out_lock;
/* Now we are sure filp is valid - the dquot isn't invalidated */
- down(&dquot->dq_mnt->mnt_dquot.dqio_sem);
+ 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_mnt->mnt_dquot.dqio_sem);
+ up(&dquot->dq_sb->s_dquot.dqio_sem);
set_fs(fs);
if (dquot->dq_bhardlimit == 0 && dquot->dq_bsoftlimit == 0 &&
@@ -326,7 +322,7 @@ void clear_dquot(struct dquot *dquot)
{
/* unhash it first */
unhash_dquot(dquot);
- dquot->dq_mnt = NULL;
+ dquot->dq_sb = NULL;
dquot->dq_flags = 0;
dquot->dq_referenced = 0;
memset(&dquot->dq_dqb, 0, sizeof(struct dqblk));
@@ -346,7 +342,7 @@ restart:
continue;
if (dquot->dq_type != type)
continue;
- if (!dquot->dq_mnt) /* Already invalidated entry? */
+ if (!dquot->dq_sb) /* Already invalidated entry? */
continue;
if (dquot->dq_flags & DQ_LOCKED) {
__wait_on_dquot(dquot);
@@ -360,7 +356,7 @@ restart:
continue;
if (dquot->dq_type != type)
continue;
- if (!dquot->dq_mnt)
+ if (!dquot->dq_sb)
continue;
}
/*
@@ -368,7 +364,7 @@ restart:
* the quota needn't to be written to disk. So we write it
* ourselves before discarding the data just for sure...
*/
- if (dquot->dq_flags & DQ_MOD && dquot->dq_mnt)
+ if (dquot->dq_flags & DQ_MOD && dquot->dq_sb)
{
write_dquot(dquot);
need_restart = 1; /* We slept on IO */
@@ -397,7 +393,7 @@ restart:
continue;
if (type != -1 && dquot->dq_type != type)
continue;
- if (!dquot->dq_mnt) /* Invalidated? */
+ if (!dquot->dq_sb) /* Invalidated? */
continue;
if (!(dquot->dq_flags & (DQ_LOCKED | DQ_MOD)))
continue;
@@ -435,11 +431,11 @@ static void dqput(struct dquot *dquot)
}
/*
- * If the dq_mnt pointer isn't initialized this entry needs no
+ * If the dq_sb pointer isn't initialized this entry needs no
* checking and doesn't need to be written. It's just an empty
* dquot that is put back on to the freelist.
*/
- if (dquot->dq_mnt)
+ if (dquot->dq_sb)
dqstats.drops++;
we_slept:
if (dquot->dq_count > 1) {
@@ -451,7 +447,7 @@ we_slept:
printk(KERN_ERR "VFS: Locked quota to be put on the free list.\n");
dquot->dq_flags &= ~DQ_LOCKED;
}
- if (dquot->dq_mnt && dquot->dq_flags & DQ_MOD) {
+ if (dquot->dq_sb && dquot->dq_flags & DQ_MOD) {
write_dquot(dquot);
goto we_slept;
}
@@ -571,17 +567,17 @@ pressure:
goto repeat;
}
-struct dquot *dqget(kdev_t dev, unsigned int id, short type)
+static struct dquot *dqget(struct super_block *sb, unsigned int id, short type)
{
- unsigned int hashent = hashfn(dev, id, type);
+ unsigned int hashent = hashfn(sb->s_dev, id, type);
struct dquot *dquot, *empty = NULL;
- struct vfsmount *vfsmnt;
+ struct quota_mount_options *dqopt = sb_dqopt(sb);
- if ((vfsmnt = lookup_vfsmnt(dev)) == (struct vfsmount *)NULL || !is_enabled(vfsmnt, type))
+ if (!is_enabled(dqopt, type))
return(NODQUOT);
we_slept:
- if ((dquot = find_dquot(hashent, dev, id, type)) == NULL) {
+ if ((dquot = find_dquot(hashent, sb->s_dev, id, type)) == NULL) {
if (empty == NULL) {
dquot_updating[hashent]++;
empty = get_empty_dquot();
@@ -592,8 +588,8 @@ we_slept:
dquot = empty;
dquot->dq_id = id;
dquot->dq_type = type;
- dquot->dq_dev = dev;
- dquot->dq_mnt = vfsmnt;
+ dquot->dq_dev = sb->s_dev;
+ dquot->dq_sb = sb;
/* hash it first so it can be found */
hash_dquot(dquot);
read_dquot(dquot);
@@ -610,7 +606,7 @@ we_slept:
while (dquot_updating[hashent])
sleep_on(&update_wait);
- if (!dquot->dq_mnt) { /* Has somebody invalidated entry under us? */
+ if (!dquot->dq_sb) { /* Has somebody invalidated entry under us? */
/*
* Do it as if the quota was invalidated before we started
*/
@@ -625,11 +621,11 @@ we_slept:
static struct dquot *dqduplicate(struct dquot *dquot)
{
- if (dquot == NODQUOT || !dquot->dq_mnt)
+ if (dquot == NODQUOT || !dquot->dq_sb)
return NODQUOT;
dquot->dq_count++;
wait_on_dquot(dquot);
- if (!dquot->dq_mnt) {
+ if (!dquot->dq_sb) {
dquot->dq_count--;
return NODQUOT;
}
@@ -642,13 +638,12 @@ static struct dquot *dqduplicate(struct dquot *dquot)
static inline int is_quotafile(struct inode *inode)
{
int cnt;
- struct vfsmount *vfsmnt;
+ struct quota_mount_options *dqopt = sb_dqopt(inode->i_sb);
struct file **files;
- vfsmnt = lookup_vfsmnt(inode->i_dev);
- if (!vfsmnt)
+ if (!dqopt)
return 0;
- files = vfsmnt->mnt_dquot.files;
+ files = dqopt->files;
for (cnt = 0; cnt < MAXQUOTAS; cnt++)
if (files[cnt] && files[cnt]->f_dentry->d_inode == inode)
return 1;
@@ -671,13 +666,12 @@ static int dqinit_needed(struct inode *inode, short type)
return 0;
}
-static void add_dquot_ref(kdev_t dev, short type)
+static void add_dquot_ref(struct super_block *sb, short type)
{
- struct super_block *sb = get_super(dev);
struct list_head *p;
struct inode *inode;
- if (!sb || !sb->dq_op)
+ if (!sb->dq_op)
return; /* nothing to do */
restart:
@@ -804,7 +798,7 @@ static void print_warning(struct dquot *dquot, int flag, const char *fmtstr)
if (!need_print_warning(dquot, flag))
return;
- root = dquot->dq_mnt->mnt_sb->s_root;
+ root = dquot->dq_sb->s_root;
dget(root);
buffer = (char *) __get_free_page(GFP_KERNEL);
path = buffer ? d_path(root, buffer, PAGE_SIZE) : "?";
@@ -817,7 +811,7 @@ static void print_warning(struct dquot *dquot, int flag, const char *fmtstr)
static inline char ignore_hardlimit(struct dquot *dquot)
{
- return capable(CAP_SYS_RESOURCE) && !dquot->dq_mnt->mnt_dquot.rsquash[dquot->dq_type];
+ return capable(CAP_SYS_RESOURCE) && !dquot->dq_sb->s_dquot.rsquash[dquot->dq_type];
}
static int check_idq(struct dquot *dquot, u_long inodes)
@@ -844,7 +838,7 @@ static int check_idq(struct dquot *dquot, u_long inodes)
(dquot->dq_curinodes + inodes) > dquot->dq_isoftlimit &&
dquot->dq_itime == 0) {
print_warning(dquot, 0, "%s: warning, %s file quota exceeded\n");
- dquot->dq_itime = CURRENT_TIME + dquot->dq_mnt->mnt_dquot.inode_expire[dquot->dq_type];
+ dquot->dq_itime = CURRENT_TIME + dquot->dq_sb->s_dquot.inode_expire[dquot->dq_type];
}
return QUOTA_OK;
@@ -877,7 +871,7 @@ static int check_bdq(struct dquot *dquot, u_long blocks, char prealloc)
dquot->dq_btime == 0) {
if (!prealloc) {
print_warning(dquot, 0, "%s: warning, %s disk quota exceeded\n");
- dquot->dq_btime = CURRENT_TIME + dquot->dq_mnt->mnt_dquot.block_expire[dquot->dq_type];
+ dquot->dq_btime = CURRENT_TIME + dquot->dq_sb->s_dquot.block_expire[dquot->dq_type];
}
else
/*
@@ -894,7 +888,7 @@ static int check_bdq(struct dquot *dquot, u_long blocks, char prealloc)
* Initialize a dquot-struct with new quota info. This is used by the
* system call interface functions.
*/
-static int set_dqblk(kdev_t dev, int id, short type, int flags, struct dqblk *dqblk)
+static int set_dqblk(struct super_block *sb, int id, short type, int flags, struct dqblk *dqblk)
{
struct dquot *dquot;
int error = -EFAULT;
@@ -909,7 +903,7 @@ static int set_dqblk(kdev_t dev, int id, short type, int flags, struct dqblk *dq
} else
memcpy((caddr_t)&dq_dqblk, (caddr_t)dqblk, sizeof(struct dqblk));
- if ((dquot = dqget(dev, id, type)) != NODQUOT) {
+ if (sb && (dquot = dqget(sb, id, type)) != NODQUOT) {
lock_dquot(dquot);
if (id > 0 && ((flags & SET_QUOTA) || (flags & SET_QLIMIT))) {
@@ -923,22 +917,22 @@ static int set_dqblk(kdev_t dev, int id, short type, int flags, struct dqblk *dq
if (dquot->dq_isoftlimit &&
dquot->dq_curinodes < dquot->dq_isoftlimit &&
dq_dqblk.dqb_curinodes >= dquot->dq_isoftlimit)
- dquot->dq_itime = CURRENT_TIME + dquot->dq_mnt->mnt_dquot.inode_expire[type];
+ 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_mnt->mnt_dquot.block_expire[type];
+ 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_mnt->mnt_dquot.block_expire[type] = dquot->dq_btime = dq_dqblk.dqb_btime;
- dquot->dq_mnt->mnt_dquot.inode_expire[type] = dquot->dq_itime = dq_dqblk.dqb_itime;
+ 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 &&
@@ -954,14 +948,14 @@ static int set_dqblk(kdev_t dev, int id, short type, int flags, struct dqblk *dq
return(0);
}
-static int get_quota(kdev_t dev, int id, short type, struct dqblk *dqblk)
+static int get_quota(struct super_block *sb, int id, short type, struct dqblk *dqblk)
{
struct dquot *dquot;
int error = -ESRCH;
- if (!dev_has_quota_enabled(dev, type))
+ if (!sb || !sb_has_quota_enabled(sb, type))
goto out;
- dquot = dqget(dev, id, type);
+ dquot = dqget(sb, id, type);
if (dquot == NODQUOT)
goto out;
@@ -990,17 +984,16 @@ static int get_stats(caddr_t addr)
return error;
}
-static int quota_root_squash(kdev_t dev, short type, int *addr)
+static int quota_root_squash(struct super_block *sb, short type, int *addr)
{
- struct vfsmount *vfsmnt;
int new_value, error;
- if ((vfsmnt = lookup_vfsmnt(dev)) == (struct vfsmount *)NULL)
+ if (!sb)
return(-ENODEV);
error = -EFAULT;
if (!copy_from_user(&new_value, addr, sizeof(int))) {
- vfsmnt->mnt_dquot.rsquash[type] = new_value;
+ sb_dqopt(sb)->rsquash[type] = new_value;
error = 0;
}
return error;
@@ -1063,7 +1056,7 @@ void dquot_initialize(struct inode *inode, short type)
id = inode->i_gid;
break;
}
- dquot = dqget(inode->i_dev, id, cnt);
+ dquot = dqget(inode->i_sb, id, cnt);
if (dquot == NODQUOT)
continue;
if (inode->i_dquot[cnt] != NODQUOT) {
@@ -1219,10 +1212,13 @@ int dquot_transfer(struct dentry *dentry, struct iattr *iattr)
if (!inode)
return -ENOENT;
+ /* Arguably we could consider that as error, but... no fs - no quota */
+ if (!inode->i_sb)
+ return 0;
/*
* Find out if this filesystem uses i_blocks.
*/
- if (!inode->i_sb || !inode->i_sb->s_blocksize)
+ if (!inode->i_sb->s_blocksize)
blocks = isize_to_blocks(inode->i_size, BLOCK_SIZE_BITS);
else
blocks = (inode->i_blocks >> 1);
@@ -1243,14 +1239,14 @@ int dquot_transfer(struct dentry *dentry, struct iattr *iattr)
if (inode->i_uid == iattr->ia_uid)
continue;
/* We can get transfer_from from inode, can't we? */
- transfer_from[cnt] = dqget(inode->i_dev, inode->i_uid, cnt);
- transfer_to[cnt] = dqget(inode->i_dev, iattr->ia_uid, cnt);
+ transfer_from[cnt] = dqget(inode->i_sb, inode->i_uid, cnt);
+ transfer_to[cnt] = dqget(inode->i_sb, iattr->ia_uid, cnt);
break;
case GRPQUOTA:
if (inode->i_gid == iattr->ia_gid)
continue;
- transfer_from[cnt] = dqget(inode->i_dev, inode->i_gid, cnt);
- transfer_to[cnt] = dqget(inode->i_dev, iattr->ia_gid, cnt);
+ transfer_from[cnt] = dqget(inode->i_sb, inode->i_gid, cnt);
+ transfer_to[cnt] = dqget(inode->i_sb, iattr->ia_gid, cnt);
break;
}
@@ -1286,7 +1282,7 @@ int dquot_transfer(struct dentry *dentry, struct iattr *iattr)
* dqget() could block and so the first structure might got
* invalidated or locked...
*/
- if (!transfer_to[cnt]->dq_mnt || !transfer_from[cnt]->dq_mnt ||
+ if (!transfer_to[cnt]->dq_sb || !transfer_from[cnt]->dq_sb ||
check_idq(transfer_to[cnt], 1) == NO_QUOTA ||
check_bdq(transfer_to[cnt], blocks, 0) == NO_QUOTA) {
cnt++;
@@ -1371,26 +1367,26 @@ struct dquot_operations dquot_operations = {
dquot_transfer
};
-static inline void set_enable_flags(struct vfsmount *vfsmnt, short type)
+static inline void set_enable_flags(struct quota_mount_options *dqopt, short type)
{
switch (type) {
case USRQUOTA:
- vfsmnt->mnt_dquot.flags |= DQUOT_USR_ENABLED;
+ dqopt->flags |= DQUOT_USR_ENABLED;
break;
case GRPQUOTA:
- vfsmnt->mnt_dquot.flags |= DQUOT_GRP_ENABLED;
+ dqopt->flags |= DQUOT_GRP_ENABLED;
break;
}
}
-static inline void reset_enable_flags(struct vfsmount *vfsmnt, short type)
+static inline void reset_enable_flags(struct quota_mount_options *dqopt, short type)
{
switch (type) {
case USRQUOTA:
- vfsmnt->mnt_dquot.flags &= ~DQUOT_USR_ENABLED;
+ dqopt->flags &= ~DQUOT_USR_ENABLED;
break;
case GRPQUOTA:
- vfsmnt->mnt_dquot.flags &= ~DQUOT_GRP_ENABLED;
+ dqopt->flags &= ~DQUOT_GRP_ENABLED;
break;
}
}
@@ -1401,38 +1397,36 @@ extern void remove_dquot_ref(kdev_t, short);
/*
* Turn quota off on a device. type == -1 ==> quotaoff for all types (umount)
*/
-int quota_off(kdev_t dev, short type)
+int quota_off(struct super_block *sb, short type)
{
- struct vfsmount *vfsmnt;
struct file *filp;
short cnt;
int enabled = 0;
+ struct quota_mount_options *dqopt = sb_dqopt(sb);
- /* We don't need to search for vfsmnt each time - umount has to wait for us */
- vfsmnt = lookup_vfsmnt(dev);
- if (!vfsmnt || !vfsmnt->mnt_sb)
+ if (!sb)
goto out;
/* We need to serialize quota_off() for device */
- down(&vfsmnt->mnt_dquot.dqoff_sem);
+ down(&dqopt->dqoff_sem);
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
if (type != -1 && cnt != type)
continue;
- if (!is_enabled(vfsmnt, cnt))
+ if (!is_enabled(dqopt, cnt))
continue;
- reset_enable_flags(vfsmnt, cnt);
+ reset_enable_flags(dqopt, cnt);
/* Note: these are blocking operations */
- remove_dquot_ref(dev, cnt);
- invalidate_dquots(dev, cnt);
+ remove_dquot_ref(sb->s_dev, cnt);
+ invalidate_dquots(sb->s_dev, cnt);
/* Wait for any pending IO - remove me as soon as invalidate is more polite */
- down(&vfsmnt->mnt_dquot.dqio_sem);
- filp = vfsmnt->mnt_dquot.files[cnt];
- vfsmnt->mnt_dquot.files[cnt] = (struct file *)NULL;
- vfsmnt->mnt_dquot.inode_expire[cnt] = 0;
- vfsmnt->mnt_dquot.block_expire[cnt] = 0;
- up(&vfsmnt->mnt_dquot.dqio_sem);
+ down(&dqopt->dqio_sem);
+ filp = dqopt->files[cnt];
+ dqopt->files[cnt] = (struct file *)NULL;
+ dqopt->inode_expire[cnt] = 0;
+ dqopt->block_expire[cnt] = 0;
+ up(&dqopt->dqio_sem);
fput(filp);
}
@@ -1441,10 +1435,10 @@ int quota_off(kdev_t dev, short type)
* and if not clear the dq_op pointer.
*/
for (cnt = 0; cnt < MAXQUOTAS; cnt++)
- enabled |= is_enabled(vfsmnt, cnt);
+ enabled |= is_enabled(dqopt, cnt);
if (!enabled)
- vfsmnt->mnt_sb->dq_op = NULL;
- up(&vfsmnt->mnt_dquot.dqoff_sem);
+ sb->dq_op = NULL;
+ up(&dqopt->dqoff_sem);
out:
return(0);
}
@@ -1457,31 +1451,25 @@ static inline int check_quotafile_size(loff_t size)
return !(((blocks % sizeof(struct dqblk)) * BLOCK_SIZE + off % sizeof(struct dqblk)) % sizeof(struct dqblk));
}
-int quota_on(kdev_t dev, short type, char *path)
+static int quota_on(struct super_block *sb, short type, char *path)
{
struct file *f;
- struct vfsmount *vfsmnt;
struct inode *inode;
struct dquot *dquot;
- struct quota_mount_options *mnt_dquot;
+ struct quota_mount_options *dqopt = sb_dqopt(sb);
char *tmp;
int error;
- vfsmnt = lookup_vfsmnt(dev);
- if (vfsmnt == (struct vfsmount *)NULL)
- return -ENODEV;
-
- if (is_enabled(vfsmnt, type))
+ if (is_enabled(dqopt, type))
return -EBUSY;
- mnt_dquot = &vfsmnt->mnt_dquot;
- down(&mnt_dquot->dqoff_sem);
+ down(&dqopt->dqoff_sem);
tmp = getname(path);
error = PTR_ERR(tmp);
if (IS_ERR(tmp))
goto out_lock;
- f = filp_open(tmp, O_RDWR, 0600);
+ f = filp_open(tmp, O_RDWR, 0600, NULL);
putname(tmp);
error = PTR_ERR(f);
@@ -1499,24 +1487,24 @@ int quota_on(kdev_t dev, short type, char *path)
goto out_f;
dquot_drop(inode); /* We don't want quota on quota files */
- set_enable_flags(vfsmnt, type);
- mnt_dquot->files[type] = f;
+ set_enable_flags(dqopt, type);
+ dqopt->files[type] = f;
- dquot = dqget(dev, 0, type);
- mnt_dquot->inode_expire[type] = (dquot != NODQUOT) ? dquot->dq_itime : MAX_IQ_TIME;
- mnt_dquot->block_expire[type] = (dquot != NODQUOT) ? dquot->dq_btime : MAX_DQ_TIME;
+ 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);
- vfsmnt->mnt_sb->dq_op = &dquot_operations;
- add_dquot_ref(dev, type);
+ sb->dq_op = &dquot_operations;
+ add_dquot_ref(sb, type);
- up(&mnt_dquot->dqoff_sem);
+ up(&dqopt->dqoff_sem);
return 0;
out_f:
filp_close(f, NULL);
out_lock:
- up(&mnt_dquot->dqoff_sem);
+ up(&dqopt->dqoff_sem);
return error;
}
@@ -1531,6 +1519,7 @@ asmlinkage long sys_quotactl(int cmd, const char *special, int id, caddr_t addr)
{
int cmds = 0, type = 0, flags = 0;
kdev_t dev;
+ struct super_block *sb = NULL;
int ret = -EINVAL;
lock_kernel();
@@ -1575,18 +1564,19 @@ asmlinkage long sys_quotactl(int cmd, const char *special, int id, caddr_t addr)
ret = -ENOTBLK;
if (!S_ISBLK(mode))
goto out;
+ sb = get_super(dev);
}
ret = -EINVAL;
switch (cmds) {
case Q_QUOTAON:
- ret = quota_on(dev, type, (char *) addr);
+ ret = sb ? quota_on(sb, type, (char *) addr) : -ENODEV;
goto out;
case Q_QUOTAOFF:
- ret = quota_off(dev, type);
+ ret = quota_off(sb, type);
goto out;
case Q_GETQUOTA:
- ret = get_quota(dev, id, type, (struct dqblk *) addr);
+ ret = get_quota(sb, id, type, (struct dqblk *) addr);
goto out;
case Q_SETQUOTA:
flags |= SET_QUOTA;
@@ -1604,7 +1594,7 @@ asmlinkage long sys_quotactl(int cmd, const char *special, int id, caddr_t addr)
ret = get_stats(addr);
goto out;
case Q_RSQUASH:
- ret = quota_root_squash(dev, type, (int *) addr);
+ ret = quota_root_squash(sb, type, (int *) addr);
goto out;
default:
goto out;
@@ -1613,8 +1603,8 @@ asmlinkage long sys_quotactl(int cmd, const char *special, int id, caddr_t addr)
flags |= QUOTA_SYSCALL;
ret = -ESRCH;
- if (dev_has_quota_enabled(dev, type))
- ret = set_dqblk(dev, id, type, flags, (struct dqblk *) addr);
+ if (sb && sb_has_quota_enabled(sb, type))
+ ret = set_dqblk(sb, id, type, flags, (struct dqblk *) addr);
out:
unlock_kernel();
return ret;