Whamcloud - gitweb
b=22456 Remove files for unsupported kernels
[fs/lustre-release.git] / lustre / kernel_patches / patches / quota-deadlock-on-pagelock-core.patch
diff --git a/lustre/kernel_patches/patches/quota-deadlock-on-pagelock-core.patch b/lustre/kernel_patches/patches/quota-deadlock-on-pagelock-core.patch
deleted file mode 100644 (file)
index 576765c..0000000
+++ /dev/null
@@ -1,1261 +0,0 @@
-From: Jan Kara <jack@suse.cz>
-
-The four patches in this series fix deadlocks with quotas of pagelock (the
-problem was lock inversion on PageLock and transaction start - quota code
-needed to first start a transaction and then write the data which subsequently
-needed acquisition of PageLock while the standard ordering - PageLock first
-and transaction start later - was used e.g.  by pdflush).  They implement a
-new way of quota access to disk: Every filesystem that would like to implement
-quotas now has to provide quota_read() and quota_write() functions.  These
-functions must obey quota lock ordering (in particular they should not take
-PageLock inside a transaction).
-
-The first patch implements the changes in the quota core, the other three
-patches implement needed functions in ext2, ext3 and reiserfs.  The patch for
-reiserfs also fixes several other lock inversion problems (similar as ext3
-had) and implements the journaled quota functionality (which comes almost for
-free after the locking fixes...).
-
-The quota core patch makes quota support in other filesystems (except XFS
-which implements everything on its own ;)) unfunctional (quotaon() will refuse
-to turn on quotas on them).  When the patches get reasonable wide testing and
-it will seem that no major changes will be needed I can make fixes also for
-the other filesystems (JFS, UDF, UFS).
-
-This patch:
-
-The patch implements the new way of quota io in the quota core.  Every
-filesystem wanting to support quotas has to provide functions quota_read()
-and quota_write() obeying quota locking rules.  As the writes and reads
-bypass the pagecache there is some ugly stuff ensuring that userspace can
-see all the data after quotaoff() (or Q_SYNC quotactl).  In future I plan
-to make quota files inaccessible from userspace (with the exception of
-quotacheck(8) which will take care about the cache flushing and such stuff
-itself) so that this synchronization stuff can be removed...
-
-The rewrite of the quota core. Quota uses the filesystem read() and write()
-functions no more to avoid possible deadlocks on PageLock. From now on every
-filesystem supporting quotas must provide functions quota_read() and
-quota_write() which obey the quota locking rules (e.g. they cannot acquire the
-PageLock).
-
-Signed-off-by: Jan Kara <jack@suse.cz>
-Signed-off-by: Andrew Morton <akpm@osdl.org>
----
-
- 25-akpm/fs/dquot.c               |  162 +++++++++++++--------------
- 25-akpm/fs/quota.c               |   45 +++++++
- 25-akpm/fs/quota_v1.c            |   62 ++--------
- 25-akpm/fs/quota_v2.c            |  227 +++++++++++++++++----------------------
- 25-akpm/include/linux/fs.h       |    3 
- 25-akpm/include/linux/quota.h    |    2 
- 25-akpm/include/linux/security.h |    8 -
- 25-akpm/security/dummy.c         |    2 
- 25-akpm/security/selinux/hooks.c |    4 
- 9 files changed, 247 insertions(+), 268 deletions(-)
-
-diff -rup RH_2_6_9_55.orig/fs/dquot.c RH_2_6_9_55/fs/dquot.c
---- RH_2_6_9_55.orig/fs/dquot.c
-+++ RH_2_6_9_55/fs/dquot.c
-@@ -49,7 +49,7 @@
-  *            New SMP locking.
-  *            Jan Kara, <jack@suse.cz>, 10/2002
-  *
-- *            Added journalled quota support
-+ *            Added journalled quota support, fix lock inversion problems
-  *            Jan Kara, <jack@suse.cz>, 2003,2004
-  *
-  * (C) Copyright 1994 - 1997 Marco van Wieringen 
-@@ -75,7 +75,8 @@
- #include <linux/proc_fs.h>
- #include <linux/security.h>
- #include <linux/kmod.h>
--#include <linux/pagemap.h>
-+#include <linux/namei.h>
-+#include <linux/buffer_head.h>
- #include <asm/uaccess.h>
-@@ -114,7 +115,7 @@
-  * operations on dquots don't hold dq_lock as they copy data under dq_data_lock
-  * spinlock to internal buffers before writing.
-  *
-- * Lock ordering (including related VFS locks) is following:
-+ * Lock ordering (including related VFS locks) is the following:
-  *   i_sem > dqonoff_sem > journal_lock > dqptr_sem > dquot->dq_lock > 
-  *   dqio_sem
-  * i_sem on quota files is special (it's below dqio_sem)
-@@ -183,8 +184,7 @@ static void put_quota_format(struct quot
-  * on all three lists, depending on its current state.
-  *
-  * All dquots are placed to the end of inuse_list when first created, and this
-- * list is used for the sync and invalidate operations, which must look
-- * at every dquot.
-+ * list is used for invalidate operation, which must look at every dquot.
-  *
-  * Unused dquots (dq_count == 0) are added to the free_dquots list when freed,
-  * and this list is searched whenever we need an available dquot.  Dquots are
-@@ -1341,10 +1341,12 @@ int vfs_quota_off(struct super_block *sb
- {
-       int cnt;
-       struct quota_info *dqopt = sb_dqopt(sb);
-+      struct inode *toput[MAXQUOTAS];
-       /* We need to serialize quota_off() for device */
-       down(&dqopt->dqonoff_sem);
-       for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
-+              toput[cnt] = NULL;
-               if (type != -1 && cnt != type)
-                       continue;
-               if (!sb_has_quota_enabled(sb, cnt))
-@@ -1364,7 +1366,7 @@ int vfs_quota_off(struct super_block *sb
-                       dqopt->ops[cnt]->free_file_info(sb, cnt);
-               put_quota_format(dqopt->info[cnt].dqi_format);
--              fput(dqopt->files[cnt]);
-+              toput[cnt] = dqopt->files[cnt];
-               dqopt->files[cnt] = NULL;
-               dqopt->info[cnt].dqi_flags = 0;
-               dqopt->info[cnt].dqi_igrace = 0;
-@@ -1372,6 +1374,26 @@ int vfs_quota_off(struct super_block *sb
-               dqopt->ops[cnt] = NULL;
-       }
-       up(&dqopt->dqonoff_sem);
-+      /* Sync the superblock so that buffers with quota data are written to
-+         * disk (and so userspace sees correct data afterwards) */
-+      if (sb->s_op->sync_fs)
-+              sb->s_op->sync_fs(sb, 1);
-+      sync_blockdev(sb->s_bdev);
-+      /* Now the quota files are just ordinary files and we can set the
-+       * inode flags back. Moreover we discard the pagecache so that
-+       * userspace sees the writes we did bypassing the pagecache. We
-+       * must also discard the blockdev buffers so that we see the
-+       * changes done by userspace on the next quotaon() */
-+      for (cnt = 0; cnt < MAXQUOTAS; cnt++)
-+              if (toput[cnt]) {
-+                      down(&toput[cnt]->i_sem);
-+                      toput[cnt]->i_flags &= ~(S_IMMUTABLE | S_NOATIME | S_NOQUOTA);
-+                      truncate_inode_pages(&toput[cnt]->i_data, 0);
-+                      up(&toput[cnt]->i_sem);
-+                      mark_inode_dirty(toput[cnt]);
-+                      iput(toput[cnt]);
-+              }
-+      invalidate_bdev(sb->s_bdev, 0);
-       return 0;
- }
-@@ -1379,68 +1401,56 @@ int vfs_quota_off(struct super_block *sb
-  *    Turn quotas on on a device
-  */
--/* Helper function when we already have file open */
--static int vfs_quota_on_file(struct file *f, int type, int format_id)
-+/* Helper function when we already have the inode */
-+static int vfs_quota_on_inode(struct inode *inode, int type, int format_id)
- {
-       struct quota_format_type *fmt = find_quota_format(format_id);
--      struct inode *inode;
--      struct super_block *sb = f->f_dentry->d_sb;
-+      struct super_block *sb = inode->i_sb;
-       struct quota_info *dqopt = sb_dqopt(sb);
--      struct dquot *to_drop[MAXQUOTAS];
--      int error, cnt;
--      unsigned int oldflags = -1;
-+      int error;
-+      int oldflags = -1;
-       if (!fmt)
-               return -ESRCH;
--      error = -EIO;
--      if (!f->f_op || !f->f_op->read || !f->f_op->write)
-+      if (!S_ISREG(inode->i_mode)) {
-+              error = -EACCES;
-               goto out_fmt;
--      inode = f->f_dentry->d_inode;
--      error = -EACCES;
--      if (!S_ISREG(inode->i_mode))
-+      }
-+      if (IS_RDONLY(inode)) {
-+              error = -EROFS;
-+              goto out_fmt;
-+      }
-+      if (!sb->s_op->quota_write || !sb->s_op->quota_read) {
-+              error = -EINVAL;
-               goto out_fmt;
-+      }
-+      /* As we bypass the pagecache we must now flush the inode so that
-+       * we see all the changes from userspace... */
-+      write_inode_now(inode, 1);
-+      /* And now flush the block cache so that kernel sees the changes */
-+      invalidate_bdev(sb->s_bdev, 0);
-       down(&inode->i_sem);
-       down(&dqopt->dqonoff_sem);
-       if (sb_has_quota_enabled(sb, type)) {
--              up(&inode->i_sem);
-               error = -EBUSY;
-               goto out_lock;
-       }
-       /* We don't want quota and atime on quota files (deadlocks possible)
--       * We also need to set GFP mask differently because we cannot recurse
--       * into filesystem when allocating page for quota inode */
-+       * Also nobody should write to the file - we use special IO operations
-+       * which ignore the immutable bit. */
-       down_write(&dqopt->dqptr_sem);
--      oldflags = inode->i_flags & (S_NOATIME | S_NOQUOTA);
--      inode->i_flags |= S_NOQUOTA | S_NOATIME;
-+      oldflags = inode->i_flags & (S_NOATIME | S_IMMUTABLE | S_NOQUOTA);
-+      inode->i_flags |= S_NOQUOTA | S_NOATIME | S_IMMUTABLE;
-       up_write(&dqopt->dqptr_sem);
--      up(&inode->i_sem);
--      dqopt->files[type] = f;
-+      error = -EIO;
-+      dqopt->files[type] = igrab(inode);
-+      if (!dqopt->files[type])
-+              goto out_lock;
-       error = -EINVAL;
-       if (!fmt->qf_ops->check_quota_file(sb, type))
-               goto out_file_init;
--      /*
--       * We write to quota files deep within filesystem code.  We don't want
--       * the VFS to reenter filesystem code when it tries to allocate a
--       * pagecache page for the quota file write.  So clear __GFP_FS in
--       * the quota file's allocation flags.
--       */
--      mapping_set_gfp_mask(inode->i_mapping,
--              mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS);
--
--      down_write(&dqopt->dqptr_sem);
--      for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
--              to_drop[cnt] = inode->i_dquot[cnt];
--              inode->i_dquot[cnt] = NODQUOT;
--      }
--      up_write(&dqopt->dqptr_sem);
--      /* We must put dquots outside of dqptr_sem because we may need to
--       * start transaction for dquot_release() */
--      for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
--              if (to_drop[cnt])
--                      dqput(to_drop[cnt]);
--      }
-       dqopt->ops[type] = fmt->qf_ops;
-       dqopt->info[type].dqi_format = fmt;
-@@ -1451,6 +1461,7 @@ static int vfs_quota_on_file(struct file
-               goto out_file_init;
-       }
-       up(&dqopt->dqio_sem);
-+      up(&inode->i_sem);
-       set_enable_flags(dqopt, type);
-       add_dquot_ref(sb, type);
-@@ -1460,19 +1471,18 @@ static int vfs_quota_on_file(struct file
- out_file_init:
-       dqopt->files[type] = NULL;
-+      iput(inode);
- out_lock:
-       up(&dqopt->dqonoff_sem);
-       if (oldflags != -1) {
--              down(&inode->i_sem);
-               down_write(&dqopt->dqptr_sem);
--              /* Reset the NOATIME flag back. I know it could change in the
--               * mean time but playing with NOATIME flags on a quota file is
--               * never a good idea */
--              inode->i_flags &= ~(S_NOATIME | S_NOQUOTA);
-+              /* Set the flags back (in the case of accidental quotaon()
-+               * on a wrong file we don't want to mess up the flags) */
-+              inode->i_flags &= ~(S_NOATIME | S_NOQUOTA | S_IMMUTABLE);
-               inode->i_flags |= oldflags;
-               up_write(&dqopt->dqptr_sem);
--              up(&inode->i_sem);
-       }
-+      up(&inode->i_sem);
- out_fmt:
-       put_quota_format(fmt);
-@@ -1482,47 +1492,37 @@ out_fmt:
- /* Actual function called from quotactl() */
- int vfs_quota_on(struct super_block *sb, int type, int format_id, char *path)
- {
--      struct file *f;
-+      struct nameidata nd;
-       int error;
--      f = filp_open(path, O_RDWR, 0600);
--      if (IS_ERR(f))
--              return PTR_ERR(f);
--      error = security_quota_on(f);
-+      error = path_lookup(path, LOOKUP_FOLLOW, &nd);
-+      if (error < 0)
-+              return error;
-+      error = security_quota_on(nd.dentry);
-       if (error)
--              goto out_f;
--      error = vfs_quota_on_file(f, type, format_id);
--      if (!error)
--              return 0;
--out_f:
--      filp_close(f, NULL);
-+              goto out_path;
-+      /* Quota file not on the same filesystem? */
-+      if (nd.mnt->mnt_sb != sb)
-+              error = -EXDEV;
-+      else
-+              error = vfs_quota_on_inode(nd.dentry->d_inode, type, format_id);
-+out_path:
-+      path_release(&nd);
-       return error;
- }
- /*
-- * Function used by filesystems when filp_open() would fail (filesystem is
-- * being mounted now). We will use a private file structure. Caller is
-- * responsible that it's IO functions won't need vfsmnt structure or
-- * some dentry tricks...
-+ * This function is used when filesystem needs to initialize quotas
-+ * during mount time.
-  */
- int vfs_quota_on_mount(int type, int format_id, struct dentry *dentry)
- {
--      struct file *f;
-       int error;
--      dget(dentry);   /* Get a reference for struct file */
--      f = dentry_open(dentry, NULL, O_RDWR);
--      if (IS_ERR(f)) {
--              error = PTR_ERR(f);
--              goto out_dentry;
--      }
--      error = vfs_quota_on_file(f, type, format_id);
--      if (!error)
--              return 0;
--      fput(f);
--out_dentry:
--      dput(dentry);
--      return error;
-+      error = security_quota_on(dentry);
-+      if (error)
-+              return error;
-+      return vfs_quota_on_inode(dentry->d_inode, type, format_id);
- }
- /* Generic routine for getting common part of quota structure */
-diff -rup RH_2_6_9_55.orig/fs/quota.c RH_2_6_9_55/fs/quota.c
---- RH_2_6_9_55.orig/fs/quota.c
-+++ RH_2_6_9_55/fs/quota.c
-@@ -13,6 +13,8 @@
- #include <linux/kernel.h>
- #include <linux/smp_lock.h>
- #include <linux/security.h>
-+#include <linux/syscalls.h>
-+#include <linux/buffer_head.h>
-
- /* Check validity of quotactl */
- static int check_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id)
-@@ -134,16 +136,54 @@ restart:
-       return NULL;
- }
-+void quota_sync_sb(struct super_block *sb, int type)
-+{
-+      int cnt;
-+      struct inode *discard[MAXQUOTAS];
-+
-+      sb->s_qcop->quota_sync(sb, type);
-+      /* This is not very clever (and fast) but currently I don't know about
-+       * any other simple way of getting quota data to disk and we must get
-+       * them there for userspace to be visible... */
-+      if (sb->s_op->sync_fs)
-+              sb->s_op->sync_fs(sb, 1);
-+      sync_blockdev(sb->s_bdev);
-+
-+      /* Now when everything is written we can discard the pagecache so
-+       * that userspace sees the changes. We need i_sem and so we could
-+       * not do it inside dqonoff_sem. Moreover we need to be carefull
-+       * about races with quotaoff() (that is the reason why we have own
-+       * reference to inode). */
-+      down(&sb_dqopt(sb)->dqonoff_sem);
-+      for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
-+              discard[cnt] = NULL;
-+              if (type != -1 && cnt != type)
-+                      continue;
-+              if (!sb_has_quota_enabled(sb, cnt))
-+                      continue;
-+              discard[cnt] = igrab(sb_dqopt(sb)->files[cnt]);
-+      }
-+      up(&sb_dqopt(sb)->dqonoff_sem);
-+      for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
-+              if (discard[cnt]) {
-+                      down(&discard[cnt]->i_sem);
-+                      truncate_inode_pages(&discard[cnt]->i_data, 0);
-+                      up(&discard[cnt]->i_sem);
-+                      iput(discard[cnt]);
-+              }
-+      }
-+}
-+
- void sync_dquots(struct super_block *sb, int type)
- {
-       if (sb) {
-               if (sb->s_qcop->quota_sync)
--                      sb->s_qcop->quota_sync(sb, type);
-+                      quota_sync_sb(sb, type);
-       }
-       else {
--              while ((sb = get_super_to_sync(type)) != 0) {
-+              while ((sb = get_super_to_sync(type)) != NULL) {
-                       if (sb->s_qcop->quota_sync)
--                              sb->s_qcop->quota_sync(sb, type);
-+                              quota_sync_sb(sb, type);
-                       drop_super(sb);
-               }
-       }
-diff -rup RH_2_6_9_55.orig/fs/quota_v1.c RH_2_6_9_55/fs/quota_v1.c
---- RH_2_6_9_55.orig/fs/quota_v1.c
-+++ RH_2_6_9_55/fs/quota_v1.c
-@@ -7,7 +7,6 @@
- #include <linux/init.h>
- #include <linux/module.h>
--#include <asm/uaccess.h>
- #include <asm/byteorder.h>
- MODULE_AUTHOR("Jan Kara");
-@@ -41,23 +40,14 @@ static void v1_mem2disk_dqblk(struct v1_
- 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)
-+      if (!sb_dqopt(dquot->dq_sb)->files[type])
-               return -EINVAL;
--      /* Now we are sure filp is valid */
--      offset = v1_dqoff(dquot->dq_id);
-       /* Set structure to 0s in case read fails/is after end of file */
-       memset(&dqblk, 0, sizeof(struct v1_disk_dqblk));
--      fs = get_fs();
--      set_fs(KERNEL_DS);
--      filp->f_op->read(filp, (char *)&dqblk, sizeof(struct v1_disk_dqblk), &offset);
--      set_fs(fs);
-+      dquot->dq_sb->s_op->quota_read(dquot->dq_sb, type, (char *)&dqblk, sizeof(struct v1_disk_dqblk), v1_dqoff(dquot->dq_id));
-       v1_disk2mem_dqblk(&dquot->dq_dqb, &dqblk);
-       if (dquot->dq_dqb.dqb_bhardlimit == 0 && dquot->dq_dqb.dqb_bsoftlimit == 0 &&
-@@ -71,26 +61,18 @@ static int v1_read_dqblk(struct dquot *d
- 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);
--
-       v1_mem2disk_dqblk(&dqblk, &dquot->dq_dqb);
-       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 (sb_dqopt(dquot->dq_sb)->files[type])
-+              ret = dquot->dq_sb->s_op->quota_write(dquot->dq_sb, type, (char *)&dqblk,
-+                                      sizeof(struct v1_disk_dqblk), v1_dqoff(dquot->dq_id));
-       if (ret != sizeof(struct v1_disk_dqblk)) {
-               printk(KERN_WARNING "VFS: dquota write failed on dev %s\n",
-                       dquot->dq_sb->s_id);
-@@ -101,7 +83,6 @@ static int v1_commit_dqblk(struct dquot 
-       ret = 0;
- out:
--      set_fs(fs);
-       dqstats.writes++;
-       return ret;
-@@ -121,14 +102,11 @@ struct v2_disk_dqheader {
- 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;
-+      struct inode *inode = sb_dqopt(sb)->files[type];
-       ulong blocks;
-       size_t off; 
-       struct v2_disk_dqheader dqhead;
--      mm_segment_t fs;
-       ssize_t size;
--      loff_t offset = 0;
-       loff_t isize;
-       static const uint quota_magics[] = V2_INITQMAGICS;
-@@ -140,10 +118,7 @@ static int v1_check_quota_file(struct su
-       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);
-+      size = sb->s_op->quota_read(sb, type, (char *)&dqhead, sizeof(struct v2_disk_dqheader), 0);
-       if (size != sizeof(struct v2_disk_dqheader))
-               return 1;       /* Probably not new format */
-       if (le32_to_cpu(dqhead.dqh_magic) != quota_magics[type])
-@@ -155,16 +130,10 @@ static int v1_check_quota_file(struct su
- 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;
--      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 = sb->s_op->quota_read(sb, type, (char *)&dqblk, sizeof(struct v1_disk_dqblk), v1_dqoff(0))) != sizeof(struct v1_disk_dqblk)) {
-               if (ret >= 0)
-                       ret = -EIO;
-               goto out;
-@@ -173,38 +142,31 @@ static int v1_read_file_info(struct supe
-       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:
--      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;
-       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 = sb->s_op->quota_read(sb, type, (char *)&dqblk,
-+          sizeof(struct v1_disk_dqblk), v1_dqoff(0))) != 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);
-+      ret = sb->s_op->quota_write(sb, type, (char *)&dqblk,
-+            sizeof(struct v1_disk_dqblk), v1_dqoff(0));
-       if (ret == sizeof(struct v1_disk_dqblk))
-               ret = 0;
-       else if (ret > 0)
-               ret = -EIO;
- out:
--      set_fs(fs);
-       return ret;
- }
-diff -rup RH_2_6_9_55.orig/fs/quota_v2.c RH_2_6_9_55/fs/quota_v2.c
---- RH_2_6_9_55.orig/fs/quota_v2.c
-+++ RH_2_6_9_55/fs/quota_v2.c
-@@ -13,7 +13,6 @@
- #include <linux/slab.h>
- #include <asm/byteorder.h>
--#include <asm/uaccess.h>
- MODULE_AUTHOR("Jan Kara");
- MODULE_DESCRIPTION("Quota format v2 support");
-@@ -30,19 +29,15 @@ typedef char *dqbuf_t;
- static int v2_check_quota_file(struct super_block *sb, int type)
- {
-       struct v2_disk_dqheader dqhead;
--      struct file *f = sb_dqopt(sb)->files[type];
--      mm_segment_t fs;
-       ssize_t size;
--      loff_t offset = 0;
-       static const uint quota_magics[] = V2_INITQMAGICS;
-       static const uint quota_versions[] = V2_INITQVERSIONS;
-  
--      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))
-+      size = sb->s_op->quota_read(sb, type, (char *)&dqhead, sizeof(struct v2_disk_dqheader), 0);
-+      if (size != sizeof(struct v2_disk_dqheader)) {
-+              printk("failed read\n");
-               return 0;
-+      }
-       if (le32_to_cpu(dqhead.dqh_magic) != quota_magics[type] ||
-           le32_to_cpu(dqhead.dqh_version) != quota_versions[type])
-               return 0;
-@@ -52,20 +47,15 @@ static int v2_check_quota_file(struct su
- /* Read information header from quota file */
- static int v2_read_file_info(struct super_block *sb, int type)
- {
--      mm_segment_t fs;
-       struct v2_disk_dqinfo dinfo;
-       struct mem_dqinfo *info = sb_dqopt(sb)->info+type;
--      struct file *f = sb_dqopt(sb)->files[type];
-       ssize_t size;
--      loff_t offset = V2_DQINFOOFF;
--      fs = get_fs();
--      set_fs(KERNEL_DS);
--      size = f->f_op->read(f, (char *)&dinfo, sizeof(struct v2_disk_dqinfo), &offset);
--      set_fs(fs);
-+      size = sb->s_op->quota_read(sb, type, (char *)&dinfo,
-+             sizeof(struct v2_disk_dqinfo), V2_DQINFOOFF);
-       if (size != sizeof(struct v2_disk_dqinfo)) {
-               printk(KERN_WARNING "Can't read info structure on device %s.\n",
--                      f->f_dentry->d_sb->s_id);
-+                      sb->s_id);
-               return -1;
-       }
-       info->dqi_bgrace = le32_to_cpu(dinfo.dqi_bgrace);
-@@ -80,12 +70,9 @@ static int v2_read_file_info(struct supe
- /* Write information header to quota file */
- static int v2_write_file_info(struct super_block *sb, int type)
- {
--      mm_segment_t fs;
-       struct v2_disk_dqinfo dinfo;
-       struct mem_dqinfo *info = sb_dqopt(sb)->info+type;
--      struct file *f = sb_dqopt(sb)->files[type];
-       ssize_t size;
--      loff_t offset = V2_DQINFOOFF;
-       spin_lock(&dq_data_lock);
-       info->dqi_flags &= ~DQF_INFO_DIRTY;
-@@ -96,13 +83,11 @@ static int v2_write_file_info(struct sup
-       dinfo.dqi_blocks = cpu_to_le32(info->u.v2_i.dqi_blocks);
-       dinfo.dqi_free_blk = cpu_to_le32(info->u.v2_i.dqi_free_blk);
-       dinfo.dqi_free_entry = cpu_to_le32(info->u.v2_i.dqi_free_entry);
--      fs = get_fs();
--      set_fs(KERNEL_DS);
--      size = f->f_op->write(f, (char *)&dinfo, sizeof(struct v2_disk_dqinfo), &offset);
--      set_fs(fs);
-+      size = sb->s_op->quota_write(sb, type, (char *)&dinfo,
-+             sizeof(struct v2_disk_dqinfo), V2_DQINFOOFF);
-       if (size != sizeof(struct v2_disk_dqinfo)) {
-               printk(KERN_WARNING "Can't write info structure on device %s.\n",
--                      f->f_dentry->d_sb->s_id);
-+                      sb->s_id);
-               return -1;
-       }
-       return 0;
-@@ -146,39 +131,24 @@ static inline void freedqbuf(dqbuf_t buf
-       kfree(buf);
- }
--static ssize_t read_blk(struct file *filp, uint blk, dqbuf_t buf)
-+static inline ssize_t read_blk(struct super_block *sb, int type, uint blk, dqbuf_t buf)
- {
--      mm_segment_t fs;
--      ssize_t ret;
--      loff_t offset = blk<<V2_DQBLKSIZE_BITS;
--
-       memset(buf, 0, V2_DQBLKSIZE);
--      fs = get_fs();
--      set_fs(KERNEL_DS);
--      ret = filp->f_op->read(filp, (char *)buf, V2_DQBLKSIZE, &offset);
--      set_fs(fs);
--      return ret;
-+      return sb->s_op->quota_read(sb, type, (char *)buf,
-+             V2_DQBLKSIZE, blk << V2_DQBLKSIZE_BITS);
- }
--static ssize_t write_blk(struct file *filp, uint blk, dqbuf_t buf)
-+static inline ssize_t write_blk(struct super_block *sb, int type, uint blk, dqbuf_t buf)
- {
--      mm_segment_t fs;
--      ssize_t ret;
--      loff_t offset = blk<<V2_DQBLKSIZE_BITS;
--
--      fs = get_fs();
--      set_fs(KERNEL_DS);
--      ret = filp->f_op->write(filp, (char *)buf, V2_DQBLKSIZE, &offset);
--      set_fs(fs);
--      return ret;
--
-+      return sb->s_op->quota_write(sb, type, (char *)buf,
-+             V2_DQBLKSIZE, blk << V2_DQBLKSIZE_BITS);
- }
- /* Remove empty block from list and return it */
--static int get_free_dqblk(struct file *filp, int type)
-+static int get_free_dqblk(struct super_block *sb, int type)
- {
-       dqbuf_t buf = getdqbuf();
--      struct mem_dqinfo *info = sb_dqinfo(filp->f_dentry->d_sb, type);
-+      struct mem_dqinfo *info = sb_dqinfo(sb, type);
-       struct v2_disk_dqdbheader *dh = (struct v2_disk_dqdbheader *)buf;
-       int ret, blk;
-@@ -186,17 +156,18 @@ static int get_free_dqblk(struct file *f
-               return -ENOMEM;
-       if (info->u.v2_i.dqi_free_blk) {
-               blk = info->u.v2_i.dqi_free_blk;
--              if ((ret = read_blk(filp, blk, buf)) < 0)
-+              if ((ret = read_blk(sb, type, blk, buf)) < 0)
-                       goto out_buf;
-               info->u.v2_i.dqi_free_blk = le32_to_cpu(dh->dqdh_next_free);
-       }
-       else {
-               memset(buf, 0, V2_DQBLKSIZE);
--              if ((ret = write_blk(filp, info->u.v2_i.dqi_blocks, buf)) < 0)  /* Assure block allocation... */
-+              /* Assure block allocation... */
-+              if ((ret = write_blk(sb, type, info->u.v2_i.dqi_blocks, buf)) < 0)
-                       goto out_buf;
-               blk = info->u.v2_i.dqi_blocks++;
-       }
--      mark_info_dirty(filp->f_dentry->d_sb, type);
-+      mark_info_dirty(sb, type);
-       ret = blk;
- out_buf:
-       freedqbuf(buf);
-@@ -204,9 +175,9 @@ out_buf:
- }
- /* Insert empty block to the list */
--static int put_free_dqblk(struct file *filp, int type, dqbuf_t buf, uint blk)
-+static int put_free_dqblk(struct super_block *sb, int type, dqbuf_t buf, uint blk)
- {
--      struct mem_dqinfo *info = sb_dqinfo(filp->f_dentry->d_sb, type);
-+      struct mem_dqinfo *info = sb_dqinfo(sb, type);
-       struct v2_disk_dqdbheader *dh = (struct v2_disk_dqdbheader *)buf;
-       int err;
-@@ -214,17 +185,18 @@ static int put_free_dqblk(struct file *f
-       dh->dqdh_prev_free = cpu_to_le32(0);
-       dh->dqdh_entries = cpu_to_le16(0);
-       info->u.v2_i.dqi_free_blk = blk;
--      mark_info_dirty(filp->f_dentry->d_sb, type);
--      if ((err = write_blk(filp, blk, buf)) < 0)      /* Some strange block. We had better leave it... */
-+      mark_info_dirty(sb, type);
-+      /* Some strange block. We had better leave it... */
-+      if ((err = write_blk(sb, type, blk, buf)) < 0)
-               return err;
-       return 0;
- }
- /* Remove given block from the list of blocks with free entries */
--static int remove_free_dqentry(struct file *filp, int type, dqbuf_t buf, uint blk)
-+static int remove_free_dqentry(struct super_block *sb, int type, dqbuf_t buf, uint blk)
- {
-       dqbuf_t tmpbuf = getdqbuf();
--      struct mem_dqinfo *info = sb_dqinfo(filp->f_dentry->d_sb, type);
-+      struct mem_dqinfo *info = sb_dqinfo(sb, type);
-       struct v2_disk_dqdbheader *dh = (struct v2_disk_dqdbheader *)buf;
-       uint nextblk = le32_to_cpu(dh->dqdh_next_free), prevblk = le32_to_cpu(dh->dqdh_prev_free);
-       int err;
-@@ -232,26 +204,27 @@ static int remove_free_dqentry(struct fi
-       if (!tmpbuf)
-               return -ENOMEM;
-       if (nextblk) {
--              if ((err = read_blk(filp, nextblk, tmpbuf)) < 0)
-+              if ((err = read_blk(sb, type, nextblk, tmpbuf)) < 0)
-                       goto out_buf;
-               ((struct v2_disk_dqdbheader *)tmpbuf)->dqdh_prev_free = dh->dqdh_prev_free;
--              if ((err = write_blk(filp, nextblk, tmpbuf)) < 0)
-+              if ((err = write_blk(sb, type, nextblk, tmpbuf)) < 0)
-                       goto out_buf;
-       }
-       if (prevblk) {
--              if ((err = read_blk(filp, prevblk, tmpbuf)) < 0)
-+              if ((err = read_blk(sb, type, prevblk, tmpbuf)) < 0)
-                       goto out_buf;
-               ((struct v2_disk_dqdbheader *)tmpbuf)->dqdh_next_free = dh->dqdh_next_free;
--              if ((err = write_blk(filp, prevblk, tmpbuf)) < 0)
-+              if ((err = write_blk(sb, type, prevblk, tmpbuf)) < 0)
-                       goto out_buf;
-       }
-       else {
-               info->u.v2_i.dqi_free_entry = nextblk;
--              mark_info_dirty(filp->f_dentry->d_sb, type);
-+              mark_info_dirty(sb, type);
-       }
-       freedqbuf(tmpbuf);
-       dh->dqdh_next_free = dh->dqdh_prev_free = cpu_to_le32(0);
--      if (write_blk(filp, blk, buf) < 0)      /* No matter whether write succeeds block is out of list */
-+      /* No matter whether write succeeds block is out of list */
-+      if (write_blk(sb, type, blk, buf) < 0)
-               printk(KERN_ERR "VFS: Can't write block (%u) with free entries.\n", blk);
-       return 0;
- out_buf:
-@@ -260,10 +233,10 @@ out_buf:
- }
- /* Insert given block to the beginning of list with free entries */
--static int insert_free_dqentry(struct file *filp, int type, dqbuf_t buf, uint blk)
-+static int insert_free_dqentry(struct super_block *sb, int type, dqbuf_t buf, uint blk)
- {
-       dqbuf_t tmpbuf = getdqbuf();
--      struct mem_dqinfo *info = sb_dqinfo(filp->f_dentry->d_sb, type);
-+      struct mem_dqinfo *info = sb_dqinfo(sb, type);
-       struct v2_disk_dqdbheader *dh = (struct v2_disk_dqdbheader *)buf;
-       int err;
-@@ -271,18 +244,18 @@ static int insert_free_dqentry(struct fi
-               return -ENOMEM;
-       dh->dqdh_next_free = cpu_to_le32(info->u.v2_i.dqi_free_entry);
-       dh->dqdh_prev_free = cpu_to_le32(0);
--      if ((err = write_blk(filp, blk, buf)) < 0)
-+      if ((err = write_blk(sb, type, blk, buf)) < 0)
-               goto out_buf;
-       if (info->u.v2_i.dqi_free_entry) {
--              if ((err = read_blk(filp, info->u.v2_i.dqi_free_entry, tmpbuf)) < 0)
-+              if ((err = read_blk(sb, type, info->u.v2_i.dqi_free_entry, tmpbuf)) < 0)
-                       goto out_buf;
-               ((struct v2_disk_dqdbheader *)tmpbuf)->dqdh_prev_free = cpu_to_le32(blk);
--              if ((err = write_blk(filp, info->u.v2_i.dqi_free_entry, tmpbuf)) < 0)
-+              if ((err = write_blk(sb, type, info->u.v2_i.dqi_free_entry, tmpbuf)) < 0)
-                       goto out_buf;
-       }
-       freedqbuf(tmpbuf);
-       info->u.v2_i.dqi_free_entry = blk;
--      mark_info_dirty(filp->f_dentry->d_sb, type);
-+      mark_info_dirty(sb, type);
-       return 0;
- out_buf:
-       freedqbuf(tmpbuf);
-@@ -292,8 +265,8 @@ out_buf:
- /* Find space for dquot */
- static uint find_free_dqentry(struct dquot *dquot, int *err)
- {
--      struct file *filp = sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];
--      struct mem_dqinfo *info = sb_dqopt(dquot->dq_sb)->info+dquot->dq_type;
-+      struct super_block *sb = dquot->dq_sb;
-+      struct mem_dqinfo *info = sb_dqopt(sb)->info+dquot->dq_type;
-       uint blk, i;
-       struct v2_disk_dqdbheader *dh;
-       struct v2_disk_dqblk *ddquot;
-@@ -309,22 +282,23 @@ static uint find_free_dqentry(struct dqu
-       ddquot = GETENTRIES(buf);
-       if (info->u.v2_i.dqi_free_entry) {
-               blk = info->u.v2_i.dqi_free_entry;
--              if ((*err = read_blk(filp, blk, buf)) < 0)
-+              if ((*err = read_blk(sb, dquot->dq_type, blk, buf)) < 0)
-                       goto out_buf;
-       }
-       else {
--              blk = get_free_dqblk(filp, dquot->dq_type);
-+              blk = get_free_dqblk(sb, dquot->dq_type);
-               if ((int)blk < 0) {
-                       *err = blk;
-                       freedqbuf(buf);
-                       return 0;
-               }
-               memset(buf, 0, V2_DQBLKSIZE);
--              info->u.v2_i.dqi_free_entry = blk;      /* This is enough as block is already zeroed and entry list is empty... */
--              mark_info_dirty(dquot->dq_sb, dquot->dq_type);
-+              /* This is enough as block is already zeroed and entry list is empty... */
-+              info->u.v2_i.dqi_free_entry = blk;
-+              mark_info_dirty(sb, dquot->dq_type);
-       }
-       if (le16_to_cpu(dh->dqdh_entries)+1 >= V2_DQSTRINBLK)   /* Block will be full? */
--              if ((*err = remove_free_dqentry(filp, dquot->dq_type, buf, blk)) < 0) {
-+              if ((*err = remove_free_dqentry(sb, dquot->dq_type, buf, blk)) < 0) {
-                       printk(KERN_ERR "VFS: find_free_dqentry(): Can't remove block (%u) from entry free list.\n", blk);
-                       goto out_buf;
-               }
-@@ -339,7 +313,7 @@ static uint find_free_dqentry(struct dqu
-               goto out_buf;
-       }
- #endif
--      if ((*err = write_blk(filp, blk, buf)) < 0) {
-+      if ((*err = write_blk(sb, dquot->dq_type, blk, buf)) < 0) {
-               printk(KERN_ERR "VFS: find_free_dqentry(): Can't write quota data block %u.\n", blk);
-               goto out_buf;
-       }
-@@ -354,7 +328,7 @@ out_buf:
- /* Insert reference to structure into the trie */
- static int do_insert_tree(struct dquot *dquot, uint *treeblk, int depth)
- {
--      struct file *filp = sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];
-+      struct super_block *sb = dquot->dq_sb;
-       dqbuf_t buf;
-       int ret = 0, newson = 0, newact = 0;
-       __le32 *ref;
-@@ -363,7 +337,7 @@ static int do_insert_tree(struct dquot *
-       if (!(buf = getdqbuf()))
-               return -ENOMEM;
-       if (!*treeblk) {
--              ret = get_free_dqblk(filp, dquot->dq_type);
-+              ret = get_free_dqblk(sb, dquot->dq_type);
-               if (ret < 0)
-                       goto out_buf;
-               *treeblk = ret;
-@@ -371,7 +345,7 @@ static int do_insert_tree(struct dquot *
-               newact = 1;
-       }
-       else {
--              if ((ret = read_blk(filp, *treeblk, buf)) < 0) {
-+              if ((ret = read_blk(sb, dquot->dq_type, *treeblk, buf)) < 0) {
-                       printk(KERN_ERR "VFS: Can't read tree quota block %u.\n", *treeblk);
-                       goto out_buf;
-               }
-@@ -394,10 +368,10 @@ static int do_insert_tree(struct dquot *
-               ret = do_insert_tree(dquot, &newblk, depth+1);
-       if (newson && ret >= 0) {
-               ref[GETIDINDEX(dquot->dq_id, depth)] = cpu_to_le32(newblk);
--              ret = write_blk(filp, *treeblk, buf);
-+              ret = write_blk(sb, dquot->dq_type, *treeblk, buf);
-       }
-       else if (newact && ret < 0)
--              put_free_dqblk(filp, dquot->dq_type, buf, *treeblk);
-+              put_free_dqblk(sb, dquot->dq_type, buf, *treeblk);
- out_buf:
-       freedqbuf(buf);
-       return ret;
-@@ -416,20 +390,15 @@ static inline int dq_insert_tree(struct 
- static int v2_write_dquot(struct dquot *dquot)
- {
-       int type = dquot->dq_type;
--      struct file *filp;
--      mm_segment_t fs;
--      loff_t offset;
-       ssize_t ret;
-       struct v2_disk_dqblk ddquot, empty;
-       /* dq_off is guarded by dqio_sem */
-       if (!dquot->dq_off)
-               if ((ret = dq_insert_tree(dquot)) < 0) {
--                      printk(KERN_ERR "VFS: Error %Zd occurred while creating quota.\n", ret);
-+                      printk(KERN_ERR "VFS: Error %d occurred while creating quota.\n", ret);
-                       return ret;
-               }
--      filp = sb_dqopt(dquot->dq_sb)->files[type];
--      offset = dquot->dq_off;
-       spin_lock(&dq_data_lock);
-       mem2diskdqb(&ddquot, &dquot->dq_dqb, dquot->dq_id);
-       /* Argh... We may need to write structure full of zeroes but that would be
-@@ -439,10 +408,8 @@ static int v2_write_dquot(struct dquot *
-       if (!memcmp(&empty, &ddquot, sizeof(struct v2_disk_dqblk)))
-               ddquot.dqb_itime = cpu_to_le64(1);
-       spin_unlock(&dq_data_lock);
--      fs = get_fs();
--      set_fs(KERNEL_DS);
--      ret = filp->f_op->write(filp, (char *)&ddquot, sizeof(struct v2_disk_dqblk), &offset);
--      set_fs(fs);
-+      ret = dquot->dq_sb->s_op->quota_write(dquot->dq_sb, type,
-+            (char *)&ddquot, sizeof(struct v2_disk_dqblk), dquot->dq_off);
-       if (ret != sizeof(struct v2_disk_dqblk)) {
-               printk(KERN_WARNING "VFS: dquota write failed on dev %s\n", dquot->dq_sb->s_id);
-               if (ret >= 0)
-@@ -458,7 +425,8 @@ static int v2_write_dquot(struct dquot *
- /* Free dquot entry in data block */
- static int free_dqentry(struct dquot *dquot, uint blk)
- {
--      struct file *filp = sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];
-+      struct super_block *sb = dquot->dq_sb;
-+      int type = dquot->dq_type;
-       struct v2_disk_dqdbheader *dh;
-       dqbuf_t buf = getdqbuf();
-       int ret = 0;
-@@ -466,34 +434,39 @@ static int free_dqentry(struct dquot *dq
-       if (!buf)
-               return -ENOMEM;
-       if (dquot->dq_off >> V2_DQBLKSIZE_BITS != blk) {
--              printk(KERN_ERR "VFS: Quota structure has offset to other block (%u) than it should (%u).\n", blk, (uint)(dquot->dq_off >> V2_DQBLKSIZE_BITS));
-+              printk(KERN_ERR "VFS: Quota structure has offset to other "
-+                "block (%u) than it should (%u).\n", blk,
-+                (uint)(dquot->dq_off >> V2_DQBLKSIZE_BITS));
-               goto out_buf;
-       }
--      if ((ret = read_blk(filp, blk, buf)) < 0) {
-+      if ((ret = read_blk(sb, type, blk, buf)) < 0) {
-               printk(KERN_ERR "VFS: Can't read quota data block %u\n", blk);
-               goto out_buf;
-       }
-       dh = (struct v2_disk_dqdbheader *)buf;
-       dh->dqdh_entries = cpu_to_le16(le16_to_cpu(dh->dqdh_entries)-1);
-       if (!le16_to_cpu(dh->dqdh_entries)) {   /* Block got free? */
--              if ((ret = remove_free_dqentry(filp, dquot->dq_type, buf, blk)) < 0 ||
--                  (ret = put_free_dqblk(filp, dquot->dq_type, buf, blk)) < 0) {
--                      printk(KERN_ERR "VFS: Can't move quota data block (%u) to free list.\n", blk);
-+              if ((ret = remove_free_dqentry(sb, type, buf, blk)) < 0 ||
-+                  (ret = put_free_dqblk(sb, type, buf, blk)) < 0) {
-+                      printk(KERN_ERR "VFS: Can't move quota data block (%u) "
-+                        "to free list.\n", blk);
-                       goto out_buf;
-               }
-       }
-       else {
--              memset(buf+(dquot->dq_off & ((1 << V2_DQBLKSIZE_BITS)-1)), 0, sizeof(struct v2_disk_dqblk));
-+              memset(buf+(dquot->dq_off & ((1 << V2_DQBLKSIZE_BITS)-1)), 0,
-+                sizeof(struct v2_disk_dqblk));
-               if (le16_to_cpu(dh->dqdh_entries) == V2_DQSTRINBLK-1) {
-                       /* Insert will write block itself */
--                      if ((ret = insert_free_dqentry(filp, dquot->dq_type, buf, blk)) < 0) {
-+                      if ((ret = insert_free_dqentry(sb, type, buf, blk)) < 0) {
-                               printk(KERN_ERR "VFS: Can't insert quota data block (%u) to free entry list.\n", blk);
-                               goto out_buf;
-                       }
-               }
-               else
--                      if ((ret = write_blk(filp, blk, buf)) < 0) {
--                              printk(KERN_ERR "VFS: Can't write quota data block %u\n", blk);
-+                      if ((ret = write_blk(sb, type, blk, buf)) < 0) {
-+                              printk(KERN_ERR "VFS: Can't write quota data "
-+                                "block %u\n", blk);
-                               goto out_buf;
-                       }
-       }
-@@ -506,7 +479,8 @@ out_buf:
- /* Remove reference to dquot from tree */
- static int remove_tree(struct dquot *dquot, uint *blk, int depth)
- {
--      struct file *filp = sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];
-+      struct super_block *sb = dquot->dq_sb;
-+      int type = dquot->dq_type;
-       dqbuf_t buf = getdqbuf();
-       int ret = 0;
-       uint newblk;
-@@ -514,7 +488,7 @@ static int remove_tree(struct dquot *dqu
-       
-       if (!buf)
-               return -ENOMEM;
--      if ((ret = read_blk(filp, *blk, buf)) < 0) {
-+      if ((ret = read_blk(sb, type, *blk, buf)) < 0) {
-               printk(KERN_ERR "VFS: Can't read quota data block %u\n", *blk);
-               goto out_buf;
-       }
-@@ -530,12 +504,13 @@ static int remove_tree(struct dquot *dqu
-               ref[GETIDINDEX(dquot->dq_id, depth)] = cpu_to_le32(0);
-               for (i = 0; i < V2_DQBLKSIZE && !buf[i]; i++);  /* Block got empty? */
-               if (i == V2_DQBLKSIZE) {
--                      put_free_dqblk(filp, dquot->dq_type, buf, *blk);
-+                      put_free_dqblk(sb, type, buf, *blk);
-                       *blk = 0;
-               }
-               else
--                      if ((ret = write_blk(filp, *blk, buf)) < 0)
--                              printk(KERN_ERR "VFS: Can't write quota tree block %u.\n", *blk);
-+                      if ((ret = write_blk(sb, type, *blk, buf)) < 0)
-+                              printk(KERN_ERR "VFS: Can't write quota tree "
-+                                "block %u.\n", *blk);
-       }
- out_buf:
-       freedqbuf(buf);
-@@ -555,7 +530,6 @@ static int v2_delete_dquot(struct dquot 
- /* Find entry in block */
- static loff_t find_block_dqentry(struct dquot *dquot, uint blk)
- {
--      struct file *filp = sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];
-       dqbuf_t buf = getdqbuf();
-       loff_t ret = 0;
-       int i;
-@@ -563,27 +537,31 @@ static loff_t find_block_dqentry(struct 
-       if (!buf)
-               return -ENOMEM;
--      if ((ret = read_blk(filp, blk, buf)) < 0) {
-+      if ((ret = read_blk(dquot->dq_sb, dquot->dq_type, blk, buf)) < 0) {
-               printk(KERN_ERR "VFS: Can't read quota tree block %u.\n", blk);
-               goto out_buf;
-       }
-       if (dquot->dq_id)
--              for (i = 0; i < V2_DQSTRINBLK && le32_to_cpu(ddquot[i].dqb_id) != dquot->dq_id; i++);
-+              for (i = 0; i < V2_DQSTRINBLK &&
-+                   le32_to_cpu(ddquot[i].dqb_id) != dquot->dq_id; i++);
-       else {  /* ID 0 as a bit more complicated searching... */
-               struct v2_disk_dqblk fakedquot;
-               memset(&fakedquot, 0, sizeof(struct v2_disk_dqblk));
-               for (i = 0; i < V2_DQSTRINBLK; i++)
--                      if (!le32_to_cpu(ddquot[i].dqb_id) && memcmp(&fakedquot, ddquot+i, sizeof(struct v2_disk_dqblk)))
-+                      if (!le32_to_cpu(ddquot[i].dqb_id) &&
-+                          memcmp(&fakedquot, ddquot+i, sizeof(struct v2_disk_dqblk)))
-                               break;
-       }
-       if (i == V2_DQSTRINBLK) {
--              printk(KERN_ERR "VFS: Quota for id %u referenced but not present.\n", dquot->dq_id);
-+              printk(KERN_ERR "VFS: Quota for id %u referenced "
-+                "but not present.\n", dquot->dq_id);
-               ret = -EIO;
-               goto out_buf;
-       }
-       else
--              ret = (blk << V2_DQBLKSIZE_BITS) + sizeof(struct v2_disk_dqdbheader) + i * sizeof(struct v2_disk_dqblk);
-+              ret = (blk << V2_DQBLKSIZE_BITS) + sizeof(struct
-+                v2_disk_dqdbheader) + i * sizeof(struct v2_disk_dqblk);
- out_buf:
-       freedqbuf(buf);
-       return ret;
-@@ -592,14 +570,13 @@ out_buf:
- /* Find entry for given id in the tree */
- static loff_t find_tree_dqentry(struct dquot *dquot, uint blk, int depth)
- {
--      struct file *filp = sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];
-       dqbuf_t buf = getdqbuf();
-       loff_t ret = 0;
-       __le32 *ref = (__le32 *)buf;
-       if (!buf)
-               return -ENOMEM;
--      if ((ret = read_blk(filp, blk, buf)) < 0) {
-+      if ((ret = read_blk(dquot->dq_sb, dquot->dq_type, blk, buf)) < 0) {
-               printk(KERN_ERR "VFS: Can't read quota tree block %u.\n", blk);
-               goto out_buf;
-       }
-@@ -625,16 +602,13 @@ static inline loff_t find_dqentry(struct
- static int v2_read_dquot(struct dquot *dquot)
- {
-       int type = dquot->dq_type;
--      struct file *filp;
--      mm_segment_t fs;
-       loff_t offset;
-       struct v2_disk_dqblk ddquot, empty;
-       int ret = 0;
--      filp = sb_dqopt(dquot->dq_sb)->files[type];
--
- #ifdef __QUOTA_V2_PARANOIA
--      if (!filp || !dquot->dq_sb) {   /* Invalidated quota? */
-+      /* Invalidated quota? */
-+      if (!dquot->dq_sb || !sb_dqopt(dquot->dq_sb)->files[type]) {
-               printk(KERN_ERR "VFS: Quota invalidated while reading!\n");
-               return -EIO;
-       }
-@@ -642,7 +616,8 @@ static int v2_read_dquot(struct dquot *d
-       offset = find_dqentry(dquot);
-       if (offset <= 0) {      /* Entry not present? */
-               if (offset < 0)
--                      printk(KERN_ERR "VFS: Can't read quota structure for id %u.\n", dquot->dq_id);
-+                      printk(KERN_ERR "VFS: Can't read quota "
-+                        "structure for id %u.\n", dquot->dq_id);
-               dquot->dq_off = 0;
-               set_bit(DQ_FAKE_B, &dquot->dq_flags);
-               memset(&dquot->dq_dqb, 0, sizeof(struct mem_dqblk));
-@@ -650,12 +625,13 @@ static int v2_read_dquot(struct dquot *d
-       }
-       else {
-               dquot->dq_off = offset;
--              fs = get_fs();
--              set_fs(KERNEL_DS);
--              if ((ret = filp->f_op->read(filp, (char *)&ddquot, sizeof(struct v2_disk_dqblk), &offset)) != sizeof(struct v2_disk_dqblk)) {
-+              if ((ret = dquot->dq_sb->s_op->quota_read(dquot->dq_sb, type,
-+                  (char *)&ddquot, sizeof(struct v2_disk_dqblk), offset))
-+                  != sizeof(struct v2_disk_dqblk)) {
-                       if (ret >= 0)
-                               ret = -EIO;
--                      printk(KERN_ERR "VFS: Error while reading quota structure for id %u.\n", dquot->dq_id);
-+                      printk(KERN_ERR "VFS: Error while reading quota "
-+                        "structure for id %u.\n", dquot->dq_id);
-                       memset(&ddquot, 0, sizeof(struct v2_disk_dqblk));
-               }
-               else {
-@@ -666,7 +642,6 @@ static int v2_read_dquot(struct dquot *d
-                       if (!memcmp(&empty, &ddquot, sizeof(struct v2_disk_dqblk)))
-                               ddquot.dqb_itime = 0;
-               }
--              set_fs(fs);
-               disk2memdqb(&dquot->dq_dqb, &ddquot);
-               if (!dquot->dq_dqb.dqb_bhardlimit &&
-                       !dquot->dq_dqb.dqb_bsoftlimit &&
-diff -rup RH_2_6_9_55.orig/include/linux/fs.h RH_2_6_9_55/include/linux/fs.h
---- RH_2_6_9_55.orig/include/linux/fs.h
-+++ RH_2_6_9_55/include/linux/fs.h
-@@ -1042,6 +1042,9 @@ struct super_operations {
-       void (*umount_lustre) (struct super_block *);
-
-       int (*show_options)(struct seq_file *, struct vfsmount *);
-+
-+      ssize_t (*quota_read)(struct super_block *, int, char *, size_t, loff_t);
-+      ssize_t (*quota_write)(struct super_block *, int, const char *, size_t, loff_t);
- };
-
- /* Inode state bits.  Protected by inode_lock. */
-diff -rup RH_2_6_9_55.orig/include/linux/quota.h RH_2_6_9_55/include/linux/quota.h
---- RH_2_6_9_55.orig/include/linux/quota.h
-+++ RH_2_6_9_55/include/linux/quota.h
-@@ -285,7 +285,7 @@ struct quota_info {
-       struct semaphore dqio_sem;              /* lock device while I/O in progress */
-       struct semaphore dqonoff_sem;           /* Serialize quotaon & quotaoff */
-       struct rw_semaphore dqptr_sem;          /* serialize ops using quota_info struct, pointers from inode to dquots */
--      struct file *files[MAXQUOTAS];          /* fp's to quotafiles */
-+      struct inode *files[MAXQUOTAS];         /* inodes of quotafiles */
-       struct mem_dqinfo info[MAXQUOTAS];      /* Information for each quota type */
-       struct quota_format_ops *ops[MAXQUOTAS];        /* Operations for each type */
- };
-diff -rup RH_2_6_9_55.orig/include/linux/security.h RH_2_6_9_55/include/linux/security.h
---- RH_2_6_9_55.orig/include/linux/security.h
-+++ RH_2_6_9_55/include/linux/security.h
-@@ -1033,7 +1033,7 @@ struct security_operations {
-       int (*sysctl) (ctl_table * table, int op);
-       int (*capable) (struct task_struct * tsk, int cap);
-       int (*quotactl) (int cmds, int type, int id, struct super_block * sb);
--      int (*quota_on) (struct file * f);
-+      int (*quota_on) (struct dentry * dentry);
-       int (*syslog) (int type);
-       int (*vm_enough_memory) (long pages);
-
-@@ -1281,9 +1281,9 @@ static inline int security_quotactl (int
-       return security_ops->quotactl (cmds, type, id, sb);
- }
--static inline int security_quota_on (struct file * file)
-+static inline int security_quota_on (struct dentry * dentry)
- {
--      return security_ops->quota_on (file);
-+      return security_ops->quota_on (dentry);
- }
- static inline int security_syslog(int type)
-@@ -1953,7 +1953,7 @@ static inline int security_quotactl (int
-       return 0;
- }
--static inline int security_quota_on (struct file * file)
-+static inline int security_quota_on (struct dentry * dentry)
- {
-       return 0;
- }
-diff -rup RH_2_6_9_55.orig/security/dummy.c RH_2_6_9_55/security/dummy.c
---- RH_2_6_9_55.orig/security/dummy.c
-+++ RH_2_6_9_55/security/dummy.c
-@@ -92,7 +92,7 @@ static int dummy_quotactl (int cmds, int
-       return 0;
- }
--static int dummy_quota_on (struct file *f)
-+static int dummy_quota_on (struct dentry *dentry)
- {
-       return 0;
- }
-diff -rup RH_2_6_9_55.orig/security/selinux/hooks.c RH_2_6_9_55/security/selinux/hooks.c
---- RH_2_6_9_55.orig/security/selinux/hooks.c
-+++ RH_2_6_9_55/security/selinux/hooks.c
-@@ -1485,9 +1485,9 @@ static int selinux_quotactl(int cmds, in
-       return rc;
- }
--static int selinux_quota_on(struct file *f)
-+static int selinux_quota_on(struct dentry *dentry)
- {
--      return file_has_perm(current, f, FILE__QUOTAON);
-+      return dentry_has_perm(current, NULL, dentry, FILE__QUOTAON);
- }
- static int selinux_syslog(int type)