diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-03-23 02:25:38 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-03-23 02:25:38 +0000 |
commit | 16b5d462f73eb29d1f67fa01cc1ea66afdc72569 (patch) | |
tree | 5407bd573f4840e473ea27cbe61e5c7a07131fcd /fs/dquot.c | |
parent | ce8a076e11e7e5ee36007f9a3eee5bb3744cb8f6 (diff) |
Merge with Linux 2.3.99-pre2.
Diffstat (limited to 'fs/dquot.c')
-rw-r--r-- | fs/dquot.c | 230 |
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; |