patch-2.3.99-pre2 linux/fs/dquot.c

Next file: linux/fs/exec.c
Previous file: linux/fs/buffer.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.99-pre1/linux/fs/dquot.c linux/fs/dquot.c
@@ -66,6 +66,11 @@
 
 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 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 @@
 	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 @@
 	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 @@
 {
 	/* 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 @@
 			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 @@
 				continue;
 			if (dquot->dq_type != type)
 				continue;
-			if (!dquot->dq_mnt)
+			if (!dquot->dq_sb)
 				continue;
 		}
 		/*
@@ -368,7 +364,7 @@
 		 *  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 @@
 			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 @@
 	}
 
 	/*
-	 * 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 @@
 		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 @@
 	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 @@
 		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 @@
 	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 @@
 
 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 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 @@
 	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 @@
 
 	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 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 @@
 	   (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 @@
 	    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 @@
  * 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 @@
 	} 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 @@
 			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 @@
 	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 @@
 	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 @@
 						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 @@
 
 	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 @@
 				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 @@
 		 * 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 @@
 	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 @@
 /*
  * 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 @@
 	 * 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 @@
 	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 @@
 		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 @@
 {
 	int cmds = 0, type = 0, flags = 0;
 	kdev_t dev;
+	struct super_block *sb = NULL;
 	int ret = -EINVAL;
 
 	lock_kernel();
@@ -1575,18 +1564,19 @@
 		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 @@
 			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 @@
 	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;

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)