xfs: kill xfs_qmops
[safe/jmp/linux-2.6] / fs / xfs / quota / xfs_qm.c
index 53a00fb..aa5d821 100644 (file)
 #include "xfs_bit.h"
 #include "xfs_log.h"
 #include "xfs_inum.h"
-#include "xfs_clnt.h"
 #include "xfs_trans.h"
 #include "xfs_sb.h"
 #include "xfs_ag.h"
-#include "xfs_dir.h"
 #include "xfs_dir2.h"
 #include "xfs_alloc.h"
 #include "xfs_dmapi.h"
@@ -33,7 +31,6 @@
 #include "xfs_bmap_btree.h"
 #include "xfs_alloc_btree.h"
 #include "xfs_ialloc_btree.h"
-#include "xfs_dir_sf.h"
 #include "xfs_dir2_sf.h"
 #include "xfs_attr_sf.h"
 #include "xfs_dinode.h"
@@ -46,8 +43,6 @@
 #include "xfs_bmap.h"
 #include "xfs_rw.h"
 #include "xfs_acl.h"
-#include "xfs_cap.h"
-#include "xfs_mac.h"
 #include "xfs_attr.h"
 #include "xfs_buf_item.h"
 #include "xfs_trans_space.h"
  * quota functionality, including maintaining the freelist and hash
  * tables of dquots.
  */
-mutex_t                xfs_Gqm_lock;
+struct mutex   xfs_Gqm_lock;
 struct xfs_qm  *xfs_Gqm;
 uint           ndquot;
 
 kmem_zone_t    *qm_dqzone;
 kmem_zone_t    *qm_dqtrxzone;
-STATIC kmem_shaker_t   xfs_qm_shaker;
+
+static cred_t  xfs_zerocr;
 
 STATIC void    xfs_qm_list_init(xfs_dqlist_t *, char *, int);
 STATIC void    xfs_qm_list_destroy(xfs_dqlist_t *);
 
 STATIC void    xfs_qm_freelist_init(xfs_frlist_t *);
 STATIC void    xfs_qm_freelist_destroy(xfs_frlist_t *);
-STATIC int     xfs_qm_mplist_nowait(xfs_mount_t *);
-STATIC int     xfs_qm_dqhashlock_nowait(xfs_dquot_t *);
 
 STATIC int     xfs_qm_init_quotainos(xfs_mount_t *);
 STATIC int     xfs_qm_init_quotainfo(xfs_mount_t *);
 STATIC int     xfs_qm_shake(int, gfp_t);
 
+static struct shrinker xfs_qm_shaker = {
+       .shrink = xfs_qm_shake,
+       .seeks = DEFAULT_SEEKS,
+};
+
 #ifdef DEBUG
-extern mutex_t qcheck_lock;
+extern struct mutex    qcheck_lock;
 #endif
 
 #ifdef QUOTADEBUG
@@ -111,17 +110,18 @@ xfs_Gqm_init(void)
 {
        xfs_dqhash_t    *udqhash, *gdqhash;
        xfs_qm_t        *xqm;
-       uint            i, hsize, flags = KM_SLEEP | KM_MAYFAIL;
+       size_t          hsize;
+       uint            i;
 
        /*
         * Initialize the dquot hash tables.
         */
-       hsize = XFS_QM_HASHSIZE_HIGH;
-       while (!(udqhash = kmem_zalloc(hsize * sizeof(xfs_dqhash_t), flags))) {
-               if ((hsize >>= 1) <= XFS_QM_HASHSIZE_LOW)
-                       flags = KM_SLEEP;
-       }
-       gdqhash = kmem_zalloc(hsize * sizeof(xfs_dqhash_t), KM_SLEEP);
+       udqhash = kmem_zalloc_greedy(&hsize,
+                                    XFS_QM_HASHSIZE_LOW * sizeof(xfs_dqhash_t),
+                                    XFS_QM_HASHSIZE_HIGH * sizeof(xfs_dqhash_t),
+                                    KM_SLEEP | KM_MAYFAIL | KM_LARGE);
+       gdqhash = kmem_zalloc(hsize, KM_SLEEP | KM_LARGE);
+       hsize /= sizeof(xfs_dqhash_t);
        ndquot = hsize << 8;
 
        xqm = kmem_zalloc(sizeof(xfs_qm_t), KM_SLEEP);
@@ -151,7 +151,7 @@ xfs_Gqm_init(void)
        } else
                xqm->qm_dqzone = qm_dqzone;
 
-       xfs_qm_shaker = kmem_shake_register(xfs_qm_shake);
+       register_shrinker(&xfs_qm_shaker);
 
        /*
         * The t_dqinfo portion of transactions.
@@ -183,14 +183,14 @@ xfs_qm_destroy(
 
        ASSERT(xqm != NULL);
        ASSERT(xqm->qm_nrefs == 0);
-       kmem_shake_deregister(xfs_qm_shaker);
+       unregister_shrinker(&xfs_qm_shaker);
        hsize = xqm->qm_dqhashmask + 1;
        for (i = 0; i < hsize; i++) {
                xfs_qm_list_destroy(&(xqm->qm_usr_dqhtable[i]));
                xfs_qm_list_destroy(&(xqm->qm_grp_dqhtable[i]));
        }
-       kmem_free(xqm->qm_usr_dqhtable, hsize * sizeof(xfs_dqhash_t));
-       kmem_free(xqm->qm_grp_dqhtable, hsize * sizeof(xfs_dqhash_t));
+       kmem_free(xqm->qm_usr_dqhtable);
+       kmem_free(xqm->qm_grp_dqhtable);
        xqm->qm_usr_dqhtable = NULL;
        xqm->qm_grp_dqhtable = NULL;
        xqm->qm_dqhashmask = 0;
@@ -198,7 +198,7 @@ xfs_qm_destroy(
 #ifdef DEBUG
        mutex_destroy(&qcheck_lock);
 #endif
-       kmem_free(xqm, sizeof(xfs_qm_t));
+       kmem_free(xqm);
 }
 
 /*
@@ -217,7 +217,7 @@ xfs_qm_hold_quotafs_ref(
         * the structure could disappear between the entry to this routine and
         * a HOLD operation if not locked.
         */
-       XFS_QM_LOCK(xfs_Gqm);
+       mutex_lock(&xfs_Gqm_lock);
 
        if (xfs_Gqm == NULL)
                xfs_Gqm = xfs_Gqm_init();
@@ -226,8 +226,8 @@ xfs_qm_hold_quotafs_ref(
         * debugging and statistical purposes, but ...
         * Just take a reference and get out.
         */
-       XFS_QM_HOLD(xfs_Gqm);
-       XFS_QM_UNLOCK(xfs_Gqm);
+       xfs_Gqm->qm_nrefs++;
+       mutex_unlock(&xfs_Gqm_lock);
 
        return 0;
 }
@@ -275,63 +275,25 @@ xfs_qm_rele_quotafs_ref(
         * Destroy the entire XQM. If somebody mounts with quotaon, this'll
         * be restarted.
         */
-       XFS_QM_LOCK(xfs_Gqm);
-       XFS_QM_RELE(xfs_Gqm);
-       if (xfs_Gqm->qm_nrefs == 0) {
+       mutex_lock(&xfs_Gqm_lock);
+       if (--xfs_Gqm->qm_nrefs == 0) {
                xfs_qm_destroy(xfs_Gqm);
                xfs_Gqm = NULL;
        }
-       XFS_QM_UNLOCK(xfs_Gqm);
-}
-
-/*
- * This is called at mount time from xfs_mountfs to initialize the quotainfo
- * structure and start the global quotamanager (xfs_Gqm) if it hasn't done
- * so already. Note that the superblock has not been read in yet.
- */
-void
-xfs_qm_mount_quotainit(
-       xfs_mount_t     *mp,
-       uint            flags)
-{
-       /*
-        * User, projects or group quotas has to be on.
-        */
-       ASSERT(flags & (XFSMNT_UQUOTA | XFSMNT_PQUOTA | XFSMNT_GQUOTA));
-
-       /*
-        * Initialize the flags in the mount structure. From this point
-        * onwards we look at m_qflags to figure out if quotas's ON/OFF, etc.
-        * Note that we enforce nothing if accounting is off.
-        * ie.  XFSMNT_*QUOTA must be ON for XFSMNT_*QUOTAENF.
-        * It isn't necessary to take the quotaoff lock to do this; this is
-        * called from mount.
-        */
-       if (flags & XFSMNT_UQUOTA) {
-               mp->m_qflags |= (XFS_UQUOTA_ACCT | XFS_UQUOTA_ACTIVE);
-               if (flags & XFSMNT_UQUOTAENF)
-                       mp->m_qflags |= XFS_UQUOTA_ENFD;
-       }
-       if (flags & XFSMNT_GQUOTA) {
-               mp->m_qflags |= (XFS_GQUOTA_ACCT | XFS_GQUOTA_ACTIVE);
-               if (flags & XFSMNT_GQUOTAENF)
-                       mp->m_qflags |= XFS_OQUOTA_ENFD;
-       } else if (flags & XFSMNT_PQUOTA) {
-               mp->m_qflags |= (XFS_PQUOTA_ACCT | XFS_PQUOTA_ACTIVE);
-               if (flags & XFSMNT_PQUOTAENF)
-                       mp->m_qflags |= XFS_OQUOTA_ENFD;
-       }
+       mutex_unlock(&xfs_Gqm_lock);
 }
 
 /*
  * Just destroy the quotainfo structure.
  */
 void
-xfs_qm_unmount_quotadestroy(
-       xfs_mount_t     *mp)
+xfs_qm_unmount(
+       struct xfs_mount        *mp)
 {
-       if (mp->m_quotainfo)
+       if (mp->m_quotainfo) {
+               xfs_qm_dqpurge_all(mp, XFS_QMOPT_QUOTALL | XFS_QMOPT_UMOUNTING);
                xfs_qm_destroy_quotainfo(mp);
+       }
 }
 
 
@@ -340,17 +302,17 @@ xfs_qm_unmount_quotadestroy(
  * necessary data structures like quotainfo.  This is also responsible for
  * running a quotacheck as necessary.  We are guaranteed that the superblock
  * is consistently read in at this point.
+ *
+ * If we fail here, the mount will continue with quota turned off. We don't
+ * need to inidicate success or failure at all.
  */
-int
+void
 xfs_qm_mount_quotas(
-       xfs_mount_t     *mp,
-       int             mfsi_flags)
+       xfs_mount_t     *mp)
 {
-       unsigned long   s;
        int             error = 0;
        uint            sbf;
 
-
        /*
         * If quotas on realtime volumes is not supported, we disable
         * quotas immediately.
@@ -369,7 +331,8 @@ xfs_qm_mount_quotas(
         * Allocate the quotainfo structure inside the mount struct, and
         * create quotainode(s), and change/rev superblock if necessary.
         */
-       if ((error = xfs_qm_init_quotainfo(mp))) {
+       error = xfs_qm_init_quotainfo(mp);
+       if (error) {
                /*
                 * We must turn off quotas.
                 */
@@ -380,25 +343,32 @@ xfs_qm_mount_quotas(
        /*
         * If any of the quotas are not consistent, do a quotacheck.
         */
-       if (XFS_QM_NEED_QUOTACHECK(mp) &&
-               !(mfsi_flags & XFS_MFSI_NO_QUOTACHECK)) {
-               if ((error = xfs_qm_quotacheck(mp))) {
-                       /* Quotacheck has failed and quotas have
-                        * been disabled.
-                        */
-                       return XFS_ERROR(error);
+       if (XFS_QM_NEED_QUOTACHECK(mp)) {
+               error = xfs_qm_quotacheck(mp);
+               if (error) {
+                       /* Quotacheck failed and disabled quotas. */
+                       return;
                }
        }
+       /* 
+        * If one type of quotas is off, then it will lose its
+        * quotachecked status, since we won't be doing accounting for
+        * that type anymore.
+        */
+       if (!XFS_IS_UQUOTA_ON(mp))
+               mp->m_qflags &= ~XFS_UQUOTA_CHKD;
+       if (!(XFS_IS_GQUOTA_ON(mp) || XFS_IS_PQUOTA_ON(mp)))
+               mp->m_qflags &= ~XFS_OQUOTA_CHKD;
 
  write_changes:
        /*
-        * We actually don't have to acquire the SB_LOCK at all.
+        * We actually don't have to acquire the m_sb_lock at all.
         * This can only be called from mount, and that's single threaded. XXX
         */
-       s = XFS_SB_LOCK(mp);
+       spin_lock(&mp->m_sb_lock);
        sbf = mp->m_sb.sb_qflags;
        mp->m_sb.sb_qflags = mp->m_qflags & XFS_MOUNT_QUOTA_ALL;
-       XFS_SB_UNLOCK(mp, s);
+       spin_unlock(&mp->m_sb_lock);
 
        if (sbf != (mp->m_qflags & XFS_MOUNT_QUOTA_ALL)) {
                if (xfs_qm_write_sb_changes(mp, XFS_SB_QFLAGS)) {
@@ -417,20 +387,22 @@ xfs_qm_mount_quotas(
        if (error) {
                xfs_fs_cmn_err(CE_WARN, mp,
                        "Failed to initialize disk quotas.");
+               return;
        }
-       return XFS_ERROR(error);
+
+#ifdef QUOTADEBUG
+       if (XFS_IS_QUOTA_ON(mp))
+               xfs_qm_internalqcheck(mp);
+#endif
 }
 
 /*
  * Called from the vfsops layer.
  */
-int
+void
 xfs_qm_unmount_quotas(
        xfs_mount_t     *mp)
 {
-       xfs_inode_t     *uqp, *gqp;
-       int             error = 0;
-
        /*
         * Release the dquots that root inode, et al might be holding,
         * before we flush quotas and blow away the quotainfo structure.
@@ -443,43 +415,18 @@ xfs_qm_unmount_quotas(
                xfs_qm_dqdetach(mp->m_rsumip);
 
        /*
-        * Flush out the quota inodes.
+        * Release the quota inodes.
         */
-       uqp = gqp = NULL;
        if (mp->m_quotainfo) {
-               if ((uqp = mp->m_quotainfo->qi_uquotaip) != NULL) {
-                       xfs_ilock(uqp, XFS_ILOCK_EXCL);
-                       xfs_iflock(uqp);
-                       error = xfs_iflush(uqp, XFS_IFLUSH_SYNC);
-                       xfs_iunlock(uqp, XFS_ILOCK_EXCL);
-                       if (unlikely(error == EFSCORRUPTED)) {
-                               XFS_ERROR_REPORT("xfs_qm_unmount_quotas(1)",
-                                                XFS_ERRLEVEL_LOW, mp);
-                               goto out;
-                       }
+               if (mp->m_quotainfo->qi_uquotaip) {
+                       IRELE(mp->m_quotainfo->qi_uquotaip);
+                       mp->m_quotainfo->qi_uquotaip = NULL;
                }
-               if ((gqp = mp->m_quotainfo->qi_gquotaip) != NULL) {
-                       xfs_ilock(gqp, XFS_ILOCK_EXCL);
-                       xfs_iflock(gqp);
-                       error = xfs_iflush(gqp, XFS_IFLUSH_SYNC);
-                       xfs_iunlock(gqp, XFS_ILOCK_EXCL);
-                       if (unlikely(error == EFSCORRUPTED)) {
-                               XFS_ERROR_REPORT("xfs_qm_unmount_quotas(2)",
-                                                XFS_ERRLEVEL_LOW, mp);
-                               goto out;
-                       }
+               if (mp->m_quotainfo->qi_gquotaip) {
+                       IRELE(mp->m_quotainfo->qi_gquotaip);
+                       mp->m_quotainfo->qi_gquotaip = NULL;
                }
        }
-       if (uqp) {
-                XFS_PURGE_INODE(uqp);
-                mp->m_quotainfo->qi_uquotaip = NULL;
-       }
-       if (gqp) {
-               XFS_PURGE_INODE(gqp);
-               mp->m_quotainfo->qi_gquotaip = NULL;
-       }
-out:
-       return XFS_ERROR(error);
 }
 
 /*
@@ -510,7 +457,7 @@ again:
                xfs_dqtrace_entry(dqp, "FLUSHALL: DQDIRTY");
                /* XXX a sentinel would be better */
                recl = XFS_QI_MPLRECLAIMS(mp);
-               if (! xfs_qm_dqflock_nowait(dqp)) {
+               if (!xfs_dqflock_nowait(dqp)) {
                        /*
                         * If we can't grab the flush lock then check
                         * to see if the dquot has been flushed delayed
@@ -634,10 +581,10 @@ xfs_qm_dqpurge_int(
                        continue;
                }
 
-               if (! xfs_qm_dqhashlock_nowait(dqp)) {
+               if (!mutex_trylock(&dqp->q_hash->qh_lock)) {
                        nrecl = XFS_QI_MPLRECLAIMS(mp);
                        xfs_qm_mplist_unlock(mp);
-                       XFS_DQ_HASH_LOCK(dqp->q_hash);
+                       mutex_lock(&dqp->q_hash->qh_lock);
                        xfs_qm_mplist_lock(mp);
 
                        /*
@@ -647,7 +594,7 @@ xfs_qm_dqpurge_int(
                         * this point, but somebody might be taking things off.
                         */
                        if (nrecl != XFS_QI_MPLRECLAIMS(mp)) {
-                               XFS_DQ_HASH_UNLOCK(dqp->q_hash);
+                               mutex_unlock(&dqp->q_hash->qh_lock);
                                goto again;
                        }
                }
@@ -657,7 +604,7 @@ xfs_qm_dqpurge_int(
                 * freelist in INACTIVE state.
                 */
                nextdqp = dqp->MPL_NEXT;
-               nmisses += xfs_qm_dqpurge(dqp, flags);
+               nmisses += xfs_qm_dqpurge(dqp);
                dqp = nextdqp;
        }
        xfs_qm_mplist_unlock(mp);
@@ -689,25 +636,24 @@ xfs_qm_dqattach_one(
        xfs_dqid_t      id,
        uint            type,
        uint            doalloc,
-       uint            dolock,
        xfs_dquot_t     *udqhint, /* hint */
        xfs_dquot_t     **IO_idqpp)
 {
        xfs_dquot_t     *dqp;
        int             error;
 
-       ASSERT(XFS_ISLOCKED_INODE_EXCL(ip));
+       ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
        error = 0;
+
        /*
         * See if we already have it in the inode itself. IO_idqpp is
         * &i_udquot or &i_gdquot. This made the code look weird, but
         * made the logic a lot simpler.
         */
-       if ((dqp = *IO_idqpp)) {
-               if (dolock)
-                       xfs_dqlock(dqp);
+       dqp = *IO_idqpp;
+       if (dqp) {
                xfs_dqtrace_entry(dqp, "DQATTACH: found in ip");
-               goto done;
+               return 0;
        }
 
        /*
@@ -716,38 +662,38 @@ xfs_qm_dqattach_one(
         * lookup by dqid (xfs_qm_dqget) by caching a group dquot inside
         * the user dquot.
         */
-       ASSERT(!udqhint || type == XFS_DQ_GROUP || type == XFS_DQ_PROJ);
-       if (udqhint && !dolock)
+       if (udqhint) {
+               ASSERT(type == XFS_DQ_GROUP || type == XFS_DQ_PROJ);
                xfs_dqlock(udqhint);
 
-       /*
-        * No need to take dqlock to look at the id.
-        * The ID can't change until it gets reclaimed, and it won't
-        * be reclaimed as long as we have a ref from inode and we hold
-        * the ilock.
-        */
-       if (udqhint &&
-           (dqp = udqhint->q_gdquot) &&
-           (be32_to_cpu(dqp->q_core.d_id) == id)) {
-               ASSERT(XFS_DQ_IS_LOCKED(udqhint));
-               xfs_dqlock(dqp);
-               XFS_DQHOLD(dqp);
-               ASSERT(*IO_idqpp == NULL);
-               *IO_idqpp = dqp;
-               if (!dolock) {
+               /*
+                * No need to take dqlock to look at the id.
+                *
+                * The ID can't change until it gets reclaimed, and it won't
+                * be reclaimed as long as we have a ref from inode and we
+                * hold the ilock.
+                */
+               dqp = udqhint->q_gdquot;
+               if (dqp && be32_to_cpu(dqp->q_core.d_id) == id) {
+                       xfs_dqlock(dqp);
+                       XFS_DQHOLD(dqp);
+                       ASSERT(*IO_idqpp == NULL);
+                       *IO_idqpp = dqp;
+
                        xfs_dqunlock(dqp);
                        xfs_dqunlock(udqhint);
+                       return 0;
                }
-               goto done;
-       }
-       /*
-        * We can't hold a dquot lock when we call the dqget code.
-        * We'll deadlock in no time, because of (not conforming to)
-        * lock ordering - the inodelock comes before any dquot lock,
-        * and we may drop and reacquire the ilock in xfs_qm_dqget().
-        */
-       if (udqhint)
+
+               /*
+                * We can't hold a dquot lock when we call the dqget code.
+                * We'll deadlock in no time, because of (not conforming to)
+                * lock ordering - the inodelock comes before any dquot lock,
+                * and we may drop and reacquire the ilock in xfs_qm_dqget().
+                */
                xfs_dqunlock(udqhint);
+       }
+
        /*
         * Find the dquot from somewhere. This bumps the
         * reference count of dquot and returns it locked.
@@ -755,48 +701,19 @@ xfs_qm_dqattach_one(
         * disk and we didn't ask it to allocate;
         * ESRCH if quotas got turned off suddenly.
         */
-       if ((error = xfs_qm_dqget(ip->i_mount, ip, id, type,
-                                doalloc|XFS_QMOPT_DOWARN, &dqp))) {
-               if (udqhint && dolock)
-                       xfs_dqlock(udqhint);
-               goto done;
-       }
+       error = xfs_qm_dqget(ip->i_mount, ip, id, type, XFS_QMOPT_DOWARN, &dqp);
+       if (error)
+               return error;
 
        xfs_dqtrace_entry(dqp, "DQATTACH: found by dqget");
+
        /*
         * dqget may have dropped and re-acquired the ilock, but it guarantees
         * that the dquot returned is the one that should go in the inode.
         */
        *IO_idqpp = dqp;
-       ASSERT(dqp);
-       ASSERT(XFS_DQ_IS_LOCKED(dqp));
-       if (! dolock) {
-               xfs_dqunlock(dqp);
-               goto done;
-       }
-       if (! udqhint)
-               goto done;
-
-       ASSERT(udqhint);
-       ASSERT(dolock);
-       ASSERT(XFS_DQ_IS_LOCKED(dqp));
-       if (! xfs_qm_dqlock_nowait(udqhint)) {
-               xfs_dqunlock(dqp);
-               xfs_dqlock(udqhint);
-               xfs_dqlock(dqp);
-       }
-      done:
-#ifdef QUOTADEBUG
-       if (udqhint) {
-               if (dolock)
-                       ASSERT(XFS_DQ_IS_LOCKED(udqhint));
-       }
-       if (! error) {
-               if (dolock)
-                       ASSERT(XFS_DQ_IS_LOCKED(dqp));
-       }
-#endif
-       return error;
+       xfs_dqunlock(dqp);
+       return 0;
 }
 
 
@@ -804,31 +721,22 @@ xfs_qm_dqattach_one(
  * Given a udquot and gdquot, attach a ptr to the group dquot in the
  * udquot as a hint for future lookups. The idea sounds simple, but the
  * execution isn't, because the udquot might have a group dquot attached
- * already and getting rid of that gets us into lock ordering contraints.
+ * already and getting rid of that gets us into lock ordering constraints.
  * The process is complicated more by the fact that the dquots may or may not
  * be locked on entry.
  */
 STATIC void
 xfs_qm_dqattach_grouphint(
        xfs_dquot_t     *udq,
-       xfs_dquot_t     *gdq,
-       uint            locked)
+       xfs_dquot_t     *gdq)
 {
        xfs_dquot_t     *tmp;
 
-#ifdef QUOTADEBUG
-       if (locked) {
-               ASSERT(XFS_DQ_IS_LOCKED(udq));
-               ASSERT(XFS_DQ_IS_LOCKED(gdq));
-       }
-#endif
-       if (! locked)
-               xfs_dqlock(udq);
+       xfs_dqlock(udq);
 
        if ((tmp = udq->q_gdquot)) {
                if (tmp == gdq) {
-                       if (! locked)
-                               xfs_dqunlock(udq);
+                       xfs_dqunlock(udq);
                        return;
                }
 
@@ -838,8 +746,6 @@ xfs_qm_dqattach_grouphint(
                 * because the freelist lock comes before dqlocks.
                 */
                xfs_dqunlock(udq);
-               if (locked)
-                       xfs_dqunlock(gdq);
                /*
                 * we took a hard reference once upon a time in dqget,
                 * so give it back when the udquot no longer points at it
@@ -852,9 +758,7 @@ xfs_qm_dqattach_grouphint(
 
        } else {
                ASSERT(XFS_DQ_IS_LOCKED(udq));
-               if (! locked) {
-                       xfs_dqlock(gdq);
-               }
+               xfs_dqlock(gdq);
        }
 
        ASSERT(XFS_DQ_IS_LOCKED(udq));
@@ -867,10 +771,9 @@ xfs_qm_dqattach_grouphint(
                XFS_DQHOLD(gdq);
                udq->q_gdquot = gdq;
        }
-       if (! locked) {
-               xfs_dqunlock(gdq);
-               xfs_dqunlock(udq);
-       }
+
+       xfs_dqunlock(gdq);
+       xfs_dqunlock(udq);
 }
 
 
@@ -878,14 +781,11 @@ xfs_qm_dqattach_grouphint(
  * Given a locked inode, attach dquot(s) to it, taking U/G/P-QUOTAON
  * into account.
  * If XFS_QMOPT_DQALLOC, the dquot(s) will be allocated if needed.
- * If XFS_QMOPT_DQLOCK, the dquot(s) will be returned locked. This option pretty
- * much made this code a complete mess, but it has been pretty useful.
- * If XFS_QMOPT_ILOCKED, then inode sent is already locked EXCL.
  * Inode may get unlocked and relocked in here, and the caller must deal with
  * the consequences.
  */
 int
-xfs_qm_dqattach(
+xfs_qm_dqattach_locked(
        xfs_inode_t     *ip,
        uint            flags)
 {
@@ -893,37 +793,32 @@ xfs_qm_dqattach(
        uint            nquotas = 0;
        int             error = 0;
 
-       if ((! XFS_IS_QUOTA_ON(mp)) ||
-           (! XFS_NOT_DQATTACHED(mp, ip)) ||
-           (ip->i_ino == mp->m_sb.sb_uquotino) ||
-           (ip->i_ino == mp->m_sb.sb_gquotino))
+       if (!XFS_IS_QUOTA_RUNNING(mp) ||
+           !XFS_IS_QUOTA_ON(mp) ||
+           !XFS_NOT_DQATTACHED(mp, ip) ||
+           ip->i_ino == mp->m_sb.sb_uquotino ||
+           ip->i_ino == mp->m_sb.sb_gquotino)
                return 0;
 
-       ASSERT((flags & XFS_QMOPT_ILOCKED) == 0 ||
-              XFS_ISLOCKED_INODE_EXCL(ip));
-
-       if (! (flags & XFS_QMOPT_ILOCKED))
-               xfs_ilock(ip, XFS_ILOCK_EXCL);
+       ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
 
        if (XFS_IS_UQUOTA_ON(mp)) {
                error = xfs_qm_dqattach_one(ip, ip->i_d.di_uid, XFS_DQ_USER,
                                                flags & XFS_QMOPT_DQALLOC,
-                                               flags & XFS_QMOPT_DQLOCK,
                                                NULL, &ip->i_udquot);
                if (error)
                        goto done;
                nquotas++;
        }
-       ASSERT(XFS_ISLOCKED_INODE_EXCL(ip));
+
+       ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
        if (XFS_IS_OQUOTA_ON(mp)) {
                error = XFS_IS_GQUOTA_ON(mp) ?
                        xfs_qm_dqattach_one(ip, ip->i_d.di_gid, XFS_DQ_GROUP,
                                                flags & XFS_QMOPT_DQALLOC,
-                                               flags & XFS_QMOPT_DQLOCK,
                                                ip->i_udquot, &ip->i_gdquot) :
                        xfs_qm_dqattach_one(ip, ip->i_d.di_projid, XFS_DQ_PROJ,
                                                flags & XFS_QMOPT_DQALLOC,
-                                               flags & XFS_QMOPT_DQLOCK,
                                                ip->i_udquot, &ip->i_gdquot);
                /*
                 * Don't worry about the udquot that we may have
@@ -939,7 +834,7 @@ xfs_qm_dqattach(
         * This WON'T, in general, result in a thrash.
         */
        if (nquotas == 2) {
-               ASSERT(XFS_ISLOCKED_INODE_EXCL(ip));
+               ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
                ASSERT(ip->i_udquot);
                ASSERT(ip->i_gdquot);
 
@@ -954,36 +849,33 @@ xfs_qm_dqattach(
                /*
                 * Attach i_gdquot to the gdquot hint inside the i_udquot.
                 */
-               xfs_qm_dqattach_grouphint(ip->i_udquot, ip->i_gdquot,
-                                        flags & XFS_QMOPT_DQLOCK);
+               xfs_qm_dqattach_grouphint(ip->i_udquot, ip->i_gdquot);
        }
 
-      done:
-
+ done:
 #ifdef QUOTADEBUG
        if (! error) {
-               if (ip->i_udquot) {
-                       if (flags & XFS_QMOPT_DQLOCK)
-                               ASSERT(XFS_DQ_IS_LOCKED(ip->i_udquot));
-               }
-               if (ip->i_gdquot) {
-                       if (flags & XFS_QMOPT_DQLOCK)
-                               ASSERT(XFS_DQ_IS_LOCKED(ip->i_gdquot));
-               }
                if (XFS_IS_UQUOTA_ON(mp))
                        ASSERT(ip->i_udquot);
                if (XFS_IS_OQUOTA_ON(mp))
                        ASSERT(ip->i_gdquot);
        }
+       ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
 #endif
+       return error;
+}
 
-       if (! (flags & XFS_QMOPT_ILOCKED))
-               xfs_iunlock(ip, XFS_ILOCK_EXCL);
+int
+xfs_qm_dqattach(
+       struct xfs_inode        *ip,
+       uint                    flags)
+{
+       int                     error;
+
+       xfs_ilock(ip, XFS_ILOCK_EXCL);
+       error = xfs_qm_dqattach_locked(ip, flags);
+       xfs_iunlock(ip, XFS_ILOCK_EXCL);
 
-#ifdef QUOTADEBUG
-       else
-               ASSERT(XFS_ISLOCKED_INODE_EXCL(ip));
-#endif
        return error;
 }
 
@@ -1014,18 +906,14 @@ xfs_qm_dqdetach(
 }
 
 /*
- * This is called by VFS_SYNC and flags arg determines the caller,
- * and its motives, as done in xfs_sync.
- *
- * vfs_sync: SYNC_FSDATA|SYNC_ATTR|SYNC_BDFLUSH 0x31
- * syscall sync: SYNC_FSDATA|SYNC_ATTR|SYNC_DELWRI 0x25
- * umountroot : SYNC_WAIT | SYNC_CLOSE | SYNC_ATTR | SYNC_FSDATA
+ * This is called to sync quotas. We can be told to use non-blocking
+ * semantics by either the SYNC_BDFLUSH flag or the absence of the
+ * SYNC_WAIT flag.
  */
-
 int
 xfs_qm_sync(
        xfs_mount_t     *mp,
-       short           flags)
+       int             flags)
 {
        int             recl, restarts;
        xfs_dquot_t     *dqp;
@@ -1033,6 +921,9 @@ xfs_qm_sync(
        boolean_t       nowait;
        int             error;
 
+       if (!XFS_IS_QUOTA_RUNNING(mp) || !XFS_IS_QUOTA_ON(mp))
+               return 0;
+
        restarts = 0;
        /*
         * We won't block unless we are asked to.
@@ -1084,17 +975,17 @@ xfs_qm_sync(
 
                /* XXX a sentinel would be better */
                recl = XFS_QI_MPLRECLAIMS(mp);
-               if (! xfs_qm_dqflock_nowait(dqp)) {
+               if (!xfs_dqflock_nowait(dqp)) {
                        if (nowait) {
                                xfs_dqunlock(dqp);
                                continue;
                        }
                        /*
                         * If we can't grab the flush lock then if the caller
-                        * really wanted us to give this our best shot,
+                        * really wanted us to give this our best shot, so
                         * see if we can give a push to the buffer before we wait
                         * on the flush lock. At this point, we know that
-                        * eventhough the dquot is being flushed,
+                        * even though the dquot is being flushed,
                         * it has (new) dirty data.
                         */
                        xfs_qm_dqflock_pushbuf_wait(dqp);
@@ -1127,6 +1018,13 @@ xfs_qm_sync(
        return 0;
 }
 
+/*
+ * The hash chains and the mplist use the same xfs_dqhash structure as
+ * their list head, but we can take the mplist qh_lock and one of the
+ * hash qh_locks at the same time without any problem as they aren't
+ * related.
+ */
+static struct lock_class_key xfs_quota_mplist_class;
 
 /*
  * This initializes all the quota information that's kept in the
@@ -1156,13 +1054,14 @@ xfs_qm_init_quotainfo(
         * and change the superblock accordingly.
         */
        if ((error = xfs_qm_init_quotainos(mp))) {
-               kmem_free(qinf, sizeof(xfs_quotainfo_t));
+               kmem_free(qinf);
                mp->m_quotainfo = NULL;
                return error;
        }
 
-       spinlock_init(&qinf->qi_pinlock, "xfs_qinf_pin");
        xfs_qm_list_init(&qinf->qi_dqlist, "mpdqlist", 0);
+       lockdep_set_class(&qinf->qi_dqlist.qh_lock, &xfs_quota_mplist_class);
+
        qinf->qi_dqreclaims = 0;
 
        /* mutex used to serialize quotaoffs */
@@ -1258,19 +1157,18 @@ xfs_qm_destroy_quotainfo(
         */
        xfs_qm_rele_quotafs_ref(mp);
 
-       spinlock_destroy(&qi->qi_pinlock);
        xfs_qm_list_destroy(&qi->qi_dqlist);
 
        if (qi->qi_uquotaip) {
-               XFS_PURGE_INODE(qi->qi_uquotaip);
+               IRELE(qi->qi_uquotaip);
                qi->qi_uquotaip = NULL; /* paranoia */
        }
        if (qi->qi_gquotaip) {
-               XFS_PURGE_INODE(qi->qi_gquotaip);
+               IRELE(qi->qi_gquotaip);
                qi->qi_gquotaip = NULL;
        }
        mutex_destroy(&qi->qi_quotaofflock);
-       kmem_free(qi, sizeof(xfs_quotainfo_t));
+       kmem_free(qi);
        mp->m_quotainfo = NULL;
 }
 
@@ -1314,7 +1212,7 @@ xfs_qm_dqget_noattach(
        xfs_mount_t     *mp;
        xfs_dquot_t     *udqp, *gdqp;
 
-       ASSERT(XFS_ISLOCKED_INODE_EXCL(ip));
+       ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
        mp = ip->i_mount;
        udqp = NULL;
        gdqp = NULL;
@@ -1392,9 +1290,6 @@ xfs_qm_qino_alloc(
 {
        xfs_trans_t     *tp;
        int             error;
-       unsigned long   s;
-       cred_t          zerocr;
-       xfs_inode_t     zeroino;
        int             committed;
 
        tp = xfs_trans_alloc(mp, XFS_TRANS_QM_QINOCREATE);
@@ -1406,11 +1301,9 @@ xfs_qm_qino_alloc(
                xfs_trans_cancel(tp, 0);
                return error;
        }
-       memset(&zerocr, 0, sizeof(zerocr));
-       memset(&zeroino, 0, sizeof(zeroino));
 
-       if ((error = xfs_dir_ialloc(&tp, &zeroino, S_IFREG, 1, 0,
-                                  &zerocr, 0, 1, ip, &committed))) {
+       if ((error = xfs_dir_ialloc(&tp, NULL, S_IFREG, 1, 0,
+                                  &xfs_zerocr, 0, 1, ip, &committed))) {
                xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES |
                                 XFS_TRANS_ABORT);
                return error;
@@ -1420,26 +1313,26 @@ xfs_qm_qino_alloc(
         * Keep an extra reference to this quota inode. This inode is
         * locked exclusively and joined to the transaction already.
         */
-       ASSERT(XFS_ISLOCKED_INODE_EXCL(*ip));
-       VN_HOLD(XFS_ITOV((*ip)));
+       ASSERT(xfs_isilocked(*ip, XFS_ILOCK_EXCL));
+       IHOLD(*ip);
 
        /*
         * Make the changes in the superblock, and log those too.
         * sbfields arg may contain fields other than *QUOTINO;
         * VERSIONNUM for example.
         */
-       s = XFS_SB_LOCK(mp);
+       spin_lock(&mp->m_sb_lock);
        if (flags & XFS_QMOPT_SBVERSION) {
 #if defined(DEBUG) && defined(XFS_LOUD_RECOVERY)
                unsigned oldv = mp->m_sb.sb_versionnum;
 #endif
-               ASSERT(!XFS_SB_VERSION_HASQUOTA(&mp->m_sb));
+               ASSERT(!xfs_sb_version_hasquota(&mp->m_sb));
                ASSERT((sbfields & (XFS_SB_VERSIONNUM | XFS_SB_UQUOTINO |
                                   XFS_SB_GQUOTINO | XFS_SB_QFLAGS)) ==
                       (XFS_SB_VERSIONNUM | XFS_SB_UQUOTINO |
                        XFS_SB_GQUOTINO | XFS_SB_QFLAGS));
 
-               XFS_SB_VERSION_ADDQUOTA(&mp->m_sb);
+               xfs_sb_version_addquota(&mp->m_sb);
                mp->m_sb.sb_uquotino = NULLFSINO;
                mp->m_sb.sb_gquotino = NULLFSINO;
 
@@ -1455,11 +1348,10 @@ xfs_qm_qino_alloc(
                mp->m_sb.sb_uquotino = (*ip)->i_ino;
        else
                mp->m_sb.sb_gquotino = (*ip)->i_ino;
-       XFS_SB_UNLOCK(mp, s);
+       spin_unlock(&mp->m_sb_lock);
        xfs_mod_sb(tp, sbfields);
 
-       if ((error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES,
-                                    NULL))) {
+       if ((error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES))) {
                xfs_fs_cmn_err(CE_ALERT, mp, "XFS qino_alloc failed!");
                return error;
        }
@@ -1467,7 +1359,7 @@ xfs_qm_qino_alloc(
 }
 
 
-STATIC int
+STATIC void
 xfs_qm_reset_dqcounts(
        xfs_mount_t     *mp,
        xfs_buf_t       *bp,
@@ -1492,7 +1384,7 @@ xfs_qm_reset_dqcounts(
                /*
                 * Do a sanity check, and if needed, repair the dqblk. Don't
                 * output any warnings because it's perfectly possible to
-                * find unitialized dquot blks. See comment in xfs_qm_dqcheck.
+                * find uninitialised dquot blks. See comment in xfs_qm_dqcheck.
                 */
                (void) xfs_qm_dqcheck(ddq, id+j, type, XFS_QMOPT_DQREPAIR,
                                      "xfs_quotacheck");
@@ -1507,8 +1399,6 @@ xfs_qm_reset_dqcounts(
                ddq->d_rtbwarns = 0;
                ddq = (xfs_disk_dquot_t *) ((xfs_dqblk_t *)ddq + 1);
        }
-
-       return 0;
 }
 
 STATIC int
@@ -1549,7 +1439,7 @@ xfs_qm_dqiter_bufs(
                if (error)
                        break;
 
-               (void) xfs_qm_reset_dqcounts(mp, bp, firstid, type);
+               xfs_qm_reset_dqcounts(mp, bp, firstid, type);
                xfs_bdwrite(mp, bp);
                /*
                 * goto the next block.
@@ -1581,7 +1471,7 @@ xfs_qm_dqiterate(
 
        error = 0;
        /*
-        * This looks racey, but we can't keep an inode lock across a
+        * This looks racy, but we can't keep an inode lock across a
         * trans_reserve. But, this gets called during quotacheck, and that
         * happens only at mount time which is single threaded.
         */
@@ -1604,7 +1494,7 @@ xfs_qm_dqiterate(
                                  maxlblkcnt - lblkno,
                                  XFS_BMAPI_METADATA,
                                  NULL,
-                                 0, map, &nmaps, NULL);
+                                 0, map, &nmaps, NULL, NULL);
                xfs_iunlock(qip, XFS_ILOCK_SHARED);
                if (error)
                        break;
@@ -1653,7 +1543,7 @@ xfs_qm_dqiterate(
                        break;
        } while (nmaps > 0);
 
-       kmem_free(map, XFS_DQITER_MAP_SIZE * sizeof(*map));
+       kmem_free(map);
 
        return error;
 }
@@ -1677,14 +1567,14 @@ xfs_qm_quotacheck_dqadjust(
         * Adjust the inode count and the block count to reflect this inode's
         * resource usage.
         */
-       be64_add(&dqp->q_core.d_icount, 1);
+       be64_add_cpu(&dqp->q_core.d_icount, 1);
        dqp->q_res_icount++;
        if (nblks) {
-               be64_add(&dqp->q_core.d_bcount, nblks);
+               be64_add_cpu(&dqp->q_core.d_bcount, nblks);
                dqp->q_res_bcount += nblks;
        }
        if (rtblks) {
-               be64_add(&dqp->q_core.d_rtbcount, rtblks);
+               be64_add_cpu(&dqp->q_core.d_rtbcount, rtblks);
                dqp->q_res_rtbcount += rtblks;
        }
 
@@ -1705,10 +1595,9 @@ xfs_qm_get_rtblks(
        xfs_qcnt_t      *O_rtblks)
 {
        xfs_filblks_t   rtblks;                 /* total rt blks */
+       xfs_extnum_t    idx;                    /* extent record index */
        xfs_ifork_t     *ifp;                   /* inode fork pointer */
        xfs_extnum_t    nextents;               /* number of extent entries */
-       xfs_bmbt_rec_t  *base;                  /* base of extent array */
-       xfs_bmbt_rec_t  *ep;                    /* pointer to an extent entry */
        int             error;
 
        ASSERT(XFS_IS_REALTIME_INODE(ip));
@@ -1718,10 +1607,9 @@ xfs_qm_get_rtblks(
                        return error;
        }
        rtblks = 0;
-       nextents = ifp->if_bytes / sizeof(xfs_bmbt_rec_t);
-       base = &ifp->if_u1.if_extents[0];
-       for (ep = base; ep < &base[nextents]; ep++)
-               rtblks += xfs_bmbt_get_blockcount(ep);
+       nextents = ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t);
+       for (idx = 0; idx < nextents; idx++)
+               rtblks += xfs_bmbt_get_blockcount(xfs_iext_get_ext(ifp, idx));
        *O_rtblks = (xfs_qcnt_t)rtblks;
        return 0;
 }
@@ -1770,12 +1658,6 @@ xfs_qm_dqusage_adjust(
                return error;
        }
 
-       if (ip->i_d.di_mode == 0) {
-               xfs_iput_new(ip, XFS_ILOCK_EXCL);
-               *res = BULKSTAT_RV_NOTHING;
-               return XFS_ERROR(ENOENT);
-       }
-
        /*
         * Obtain the locked dquots. In case of an error (eg. allocation
         * fails for ENOSPC), we return the negative of the error number
@@ -1824,7 +1706,7 @@ xfs_qm_dqusage_adjust(
         * we have to start from the beginning anyway.
         * Once we're done, we'll log all the dquot bufs.
         *
-        * The *QUOTA_ON checks below may look pretty racey, but quotachecks
+        * The *QUOTA_ON checks below may look pretty racy, but quotachecks
         * and quotaoffs don't race. (Quotachecks happen at mount time only).
         */
        if (XFS_IS_UQUOTA_ON(mp)) {
@@ -1841,7 +1723,7 @@ xfs_qm_dqusage_adjust(
         * Now release the inode. This will send it to 'inactive', and
         * possibly even free blocks.
         */
-       VN_RELE(XFS_ITOV(ip));
+       IRELE(ip);
 
        /*
         * Goto next inode.
@@ -1905,14 +1787,20 @@ xfs_qm_quotacheck(
                 */
                if ((error = xfs_bulkstat(mp, &lastino, &count,
                                     xfs_qm_dqusage_adjust, NULL,
-                                    structsz, NULL,
-                                    BULKSTAT_FG_IGET|BULKSTAT_FG_VFSLOCKED,
-                                    &done)))
+                                    structsz, NULL, BULKSTAT_FG_IGET, &done)))
                        break;
 
        } while (! done);
 
        /*
+        * We've made all the changes that we need to make incore.
+        * Flush them down to disk buffers if everything was updated
+        * successfully.
+        */
+       if (!error)
+               error = xfs_qm_dqflush_all(mp, XFS_QMOPT_DELWRI);
+
+       /*
         * We can get this error if we couldn't do a dquot allocation inside
         * xfs_qm_dqusage_adjust (via bulkstat). We don't care about the
         * dirty dquots that might be cached, we just want to get rid of them
@@ -1923,11 +1811,6 @@ xfs_qm_quotacheck(
                xfs_qm_dqpurge_all(mp, XFS_QMOPT_QUOTALL | XFS_QMOPT_QUOTAOFF);
                goto error_return;
        }
-       /*
-        * We've made all the changes that we need to make incore.
-        * Now flush_them down to disk buffers.
-        */
-       xfs_qm_dqflush_all(mp, XFS_QMOPT_DELWRI);
 
        /*
         * We didn't log anything, because if we crashed, we'll have to
@@ -1959,7 +1842,10 @@ xfs_qm_quotacheck(
                ASSERT(mp->m_quotainfo != NULL);
                ASSERT(xfs_Gqm != NULL);
                xfs_qm_destroy_quotainfo(mp);
-               (void)xfs_mount_reset_sbqflags(mp);
+               if (xfs_mount_reset_sbqflags(mp)) {
+                       cmn_err(CE_WARN, "XFS quotacheck %s: "
+                               "Failed to reset quota flags.", mp->m_fsname);
+               }
        } else {
                cmn_err(CE_NOTE, "XFS quotacheck %s: Done.", mp->m_fsname);
        }
@@ -1987,7 +1873,7 @@ xfs_qm_init_quotainos(
        /*
         * Get the uquota and gquota inodes
         */
-       if (XFS_SB_VERSION_HASQUOTA(&mp->m_sb)) {
+       if (xfs_sb_version_hasquota(&mp->m_sb)) {
                if (XFS_IS_UQUOTA_ON(mp) &&
                    mp->m_sb.sb_uquotino != NULLFSINO) {
                        ASSERT(mp->m_sb.sb_uquotino > 0);
@@ -2001,7 +1887,7 @@ xfs_qm_init_quotainos(
                        if ((error = xfs_iget(mp, NULL, mp->m_sb.sb_gquotino,
                                             0, 0, &gip, 0))) {
                                if (uip)
-                                       VN_RELE(XFS_ITOV(uip));
+                                       IRELE(uip);
                                return XFS_ERROR(error);
                        }
                }
@@ -2032,7 +1918,7 @@ xfs_qm_init_quotainos(
                                          sbflags | XFS_SB_GQUOTINO, flags);
                if (error) {
                        if (uip)
-                               VN_RELE(XFS_ITOV(uip));
+                               IRELE(uip);
 
                        return XFS_ERROR(error);
                }
@@ -2113,7 +1999,7 @@ xfs_qm_shake_freelist(
                 * Try to grab the flush lock. If this dquot is in the process of
                 * getting flushed to disk, we don't want to reclaim it.
                 */
-               if (! xfs_qm_dqflock_nowait(dqp)) {
+               if (!xfs_dqflock_nowait(dqp)) {
                        xfs_dqunlock(dqp);
                        dqp = dqp->dq_flnext;
                        continue;
@@ -2126,12 +2012,17 @@ xfs_qm_shake_freelist(
                 * dirty dquots.
                 */
                if (XFS_DQ_IS_DIRTY(dqp)) {
+                       int     error;
                        xfs_dqtrace_entry(dqp, "DQSHAKE: DQDIRTY");
                        /*
                         * We flush it delayed write, so don't bother
                         * releasing the mplock.
                         */
-                       (void) xfs_qm_dqflush(dqp, XFS_QMOPT_DELWRI);
+                       error = xfs_qm_dqflush(dqp, XFS_QMOPT_DELWRI);
+                       if (error) {
+                               xfs_fs_cmn_err(CE_WARN, dqp->q_mount,
+                       "xfs_qm_dqflush_all: dquot %p flush failed", dqp);
+                       }
                        xfs_dqunlock(dqp); /* dqflush unlocks dqflock */
                        dqp = dqp->dq_flnext;
                        continue;
@@ -2143,7 +2034,7 @@ xfs_qm_shake_freelist(
                 * a dqlookup process that holds the hashlock that is
                 * waiting for the freelist lock.
                 */
-               if (! xfs_qm_dqhashlock_nowait(dqp)) {
+               if (!mutex_trylock(&dqp->q_hash->qh_lock)) {
                        xfs_dqfunlock(dqp);
                        xfs_dqunlock(dqp);
                        dqp = dqp->dq_flnext;
@@ -2160,7 +2051,7 @@ xfs_qm_shake_freelist(
                        /* XXX put a sentinel so that we can come back here */
                        xfs_dqfunlock(dqp);
                        xfs_dqunlock(dqp);
-                       XFS_DQ_HASH_UNLOCK(hash);
+                       mutex_unlock(&hash->qh_lock);
                        xfs_qm_freelist_unlock(xfs_Gqm);
                        if (++restarts >= XFS_QM_RECLAIM_MAX_RESTARTS)
                                return nreclaimed;
@@ -2177,7 +2068,7 @@ xfs_qm_shake_freelist(
                XQM_HASHLIST_REMOVE(hash, dqp);
                xfs_dqfunlock(dqp);
                xfs_qm_mplist_unlock(dqp->q_mount);
-               XFS_DQ_HASH_UNLOCK(hash);
+               mutex_unlock(&hash->qh_lock);
 
  off_freelist:
                XQM_FREELIST_REMOVE(dqp);
@@ -2286,7 +2177,7 @@ xfs_qm_dqreclaim_one(void)
                 * Try to grab the flush lock. If this dquot is in the process of
                 * getting flushed to disk, we don't want to reclaim it.
                 */
-               if (! xfs_qm_dqflock_nowait(dqp)) {
+               if (!xfs_dqflock_nowait(dqp)) {
                        xfs_dqunlock(dqp);
                        continue;
                }
@@ -2298,12 +2189,17 @@ xfs_qm_dqreclaim_one(void)
                 * dirty dquots.
                 */
                if (XFS_DQ_IS_DIRTY(dqp)) {
+                       int     error;
                        xfs_dqtrace_entry(dqp, "DQRECLAIM: DQDIRTY");
                        /*
                         * We flush it delayed write, so don't bother
                         * releasing the freelist lock.
                         */
-                       (void) xfs_qm_dqflush(dqp, XFS_QMOPT_DELWRI);
+                       error = xfs_qm_dqflush(dqp, XFS_QMOPT_DELWRI);
+                       if (error) {
+                               xfs_fs_cmn_err(CE_WARN, dqp->q_mount,
+                       "xfs_qm_dqreclaim: dquot %p flush failed", dqp);
+                       }
                        xfs_dqunlock(dqp); /* dqflush unlocks dqflock */
                        continue;
                }
@@ -2314,7 +2210,7 @@ xfs_qm_dqreclaim_one(void)
                        continue;
                }
 
-               if (! xfs_qm_dqhashlock_nowait(dqp))
+               if (!mutex_trylock(&dqp->q_hash->qh_lock))
                        goto mplistunlock;
 
                ASSERT(dqp->q_nrefs == 0);
@@ -2323,7 +2219,7 @@ xfs_qm_dqreclaim_one(void)
                XQM_HASHLIST_REMOVE(dqp->q_hash, dqp);
                XQM_FREELIST_REMOVE(dqp);
                dqpout = dqp;
-               XFS_DQ_HASH_UNLOCK(dqp->q_hash);
+               mutex_unlock(&dqp->q_hash->qh_lock);
  mplistunlock:
                xfs_qm_mplist_unlock(dqp->q_mount);
                xfs_dqfunlock(dqp);
@@ -2411,9 +2307,9 @@ xfs_qm_write_sb_changes(
        }
 
        xfs_mod_sb(tp, flags);
-       (void) xfs_trans_commit(tp, 0, NULL);
+       error = xfs_trans_commit(tp, 0);
 
-       return 0;
+       return error;
 }
 
 
@@ -2432,27 +2328,26 @@ xfs_qm_write_sb_changes(
  */
 int
 xfs_qm_vop_dqalloc(
-       xfs_mount_t     *mp,
-       xfs_inode_t     *ip,
-       uid_t           uid,
-       gid_t           gid,
-       prid_t          prid,
-       uint            flags,
-       xfs_dquot_t     **O_udqpp,
-       xfs_dquot_t     **O_gdqpp)
+       struct xfs_inode        *ip,
+       uid_t                   uid,
+       gid_t                   gid,
+       prid_t                  prid,
+       uint                    flags,
+       struct xfs_dquot        **O_udqpp,
+       struct xfs_dquot        **O_gdqpp)
 {
-       int             error;
-       xfs_dquot_t     *uq, *gq;
-       uint            lockflags;
+       struct xfs_mount        *mp = ip->i_mount;
+       struct xfs_dquot        *uq, *gq;
+       int                     error;
+       uint                    lockflags;
 
-       if (!XFS_IS_QUOTA_ON(mp))
+       if (!XFS_IS_QUOTA_RUNNING(mp) || !XFS_IS_QUOTA_ON(mp))
                return 0;
 
        lockflags = XFS_ILOCK_EXCL;
        xfs_ilock(ip, lockflags);
 
-       if ((flags & XFS_QMOPT_INHERIT) &&
-           XFS_INHERIT_GID(ip, XFS_MTOVFS(mp)))
+       if ((flags & XFS_QMOPT_INHERIT) && XFS_INHERIT_GID(ip))
                gid = ip->i_d.di_gid;
 
        /*
@@ -2460,8 +2355,8 @@ xfs_qm_vop_dqalloc(
         * if necessary. The dquot(s) will not be locked.
         */
        if (XFS_NOT_DQATTACHED(mp, ip)) {
-               if ((error = xfs_qm_dqattach(ip, XFS_QMOPT_DQALLOC |
-                                           XFS_QMOPT_ILOCKED))) {
+               error = xfs_qm_dqattach_locked(ip, XFS_QMOPT_DQALLOC);
+               if (error) {
                        xfs_iunlock(ip, lockflags);
                        return error;
                }
@@ -2583,7 +2478,8 @@ xfs_qm_vop_chown(
        uint            bfield = XFS_IS_REALTIME_INODE(ip) ?
                                 XFS_TRANS_DQ_RTBCOUNT : XFS_TRANS_DQ_BCOUNT;
 
-       ASSERT(XFS_ISLOCKED_INODE_EXCL(ip));
+
+       ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
        ASSERT(XFS_IS_QUOTA_RUNNING(ip->i_mount));
 
        /* old dquot */
@@ -2622,13 +2518,13 @@ xfs_qm_vop_chown_reserve(
        xfs_dquot_t     *gdqp,
        uint            flags)
 {
-       int             error;
-       xfs_mount_t     *mp;
-       uint            delblks, blkflags;
+       xfs_mount_t     *mp = ip->i_mount;
+       uint            delblks, blkflags, prjflags = 0;
        xfs_dquot_t     *unresudq, *unresgdq, *delblksudq, *delblksgdq;
+       int             error;
 
-       ASSERT(XFS_ISLOCKED_INODE(ip));
-       mp = ip->i_mount;
+
+       ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED));
        ASSERT(XFS_IS_QUOTA_RUNNING(mp));
 
        delblks = ip->i_delayed_blks;
@@ -2650,10 +2546,13 @@ xfs_qm_vop_chown_reserve(
                }
        }
        if (XFS_IS_OQUOTA_ON(ip->i_mount) && gdqp) {
-               if ((XFS_IS_GQUOTA_ON(ip->i_mount) &&
-                    ip->i_d.di_gid != be32_to_cpu(gdqp->q_core.d_id)) ||
-                   (XFS_IS_PQUOTA_ON(ip->i_mount) &&
-                    ip->i_d.di_projid != be32_to_cpu(gdqp->q_core.d_id))) {
+               if (XFS_IS_PQUOTA_ON(ip->i_mount) &&
+                    ip->i_d.di_projid != be32_to_cpu(gdqp->q_core.d_id))
+                       prjflags = XFS_QMOPT_ENOSPC;
+
+               if (prjflags ||
+                   (XFS_IS_GQUOTA_ON(ip->i_mount) &&
+                    ip->i_d.di_gid != be32_to_cpu(gdqp->q_core.d_id))) {
                        delblksgdq = gdqp;
                        if (delblks) {
                                ASSERT(ip->i_gdquot);
@@ -2664,7 +2563,7 @@ xfs_qm_vop_chown_reserve(
 
        if ((error = xfs_trans_reserve_quota_bydquots(tp, ip->i_mount,
                                delblksudq, delblksgdq, ip->i_d.di_nblocks, 1,
-                               flags | blkflags)))
+                               flags | blkflags | prjflags)))
                return (error);
 
        /*
@@ -2681,7 +2580,7 @@ xfs_qm_vop_chown_reserve(
                ASSERT(unresudq || unresgdq);
                if ((error = xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount,
                                delblksudq, delblksgdq, (xfs_qcnt_t)delblks, 0,
-                               flags | blkflags)))
+                               flags | blkflags | prjflags)))
                        return (error);
                xfs_trans_reserve_quota_bydquots(NULL, ip->i_mount,
                                unresudq, unresgdq, -((xfs_qcnt_t)delblks), 0,
@@ -2693,28 +2592,23 @@ xfs_qm_vop_chown_reserve(
 
 int
 xfs_qm_vop_rename_dqattach(
-       xfs_inode_t     **i_tab)
+       struct xfs_inode        **i_tab)
 {
-       xfs_inode_t     *ip;
-       int             i;
-       int             error;
-
-       ip = i_tab[0];
+       struct xfs_mount        *mp = i_tab[0]->i_mount;
+       int                     i;
 
-       if (! XFS_IS_QUOTA_ON(ip->i_mount))
+       if (!XFS_IS_QUOTA_RUNNING(mp) || !XFS_IS_QUOTA_ON(mp))
                return 0;
 
-       if (XFS_NOT_DQATTACHED(ip->i_mount, ip)) {
-               error = xfs_qm_dqattach(ip, 0);
-               if (error)
-                       return error;
-       }
-       for (i = 1; (i < 4 && i_tab[i]); i++) {
+       for (i = 0; (i < 4 && i_tab[i]); i++) {
+               struct xfs_inode        *ip = i_tab[i];
+               int                     error;
+
                /*
                 * Watch out for duplicate entries in the table.
                 */
-               if ((ip = i_tab[i]) != i_tab[i-1]) {
-                       if (XFS_NOT_DQATTACHED(ip->i_mount, ip)) {
+               if (i == 0 || ip != i_tab[i-1]) {
+                       if (XFS_NOT_DQATTACHED(mp, ip)) {
                                error = xfs_qm_dqattach(ip, 0);
                                if (error)
                                        return error;
@@ -2725,17 +2619,19 @@ xfs_qm_vop_rename_dqattach(
 }
 
 void
-xfs_qm_vop_dqattach_and_dqmod_newinode(
-       xfs_trans_t     *tp,
-       xfs_inode_t     *ip,
-       xfs_dquot_t     *udqp,
-       xfs_dquot_t     *gdqp)
+xfs_qm_vop_create_dqattach(
+       struct xfs_trans        *tp,
+       struct xfs_inode        *ip,
+       struct xfs_dquot        *udqp,
+       struct xfs_dquot        *gdqp)
 {
-       if (!XFS_IS_QUOTA_ON(tp->t_mountp))
+       struct xfs_mount        *mp = tp->t_mountp;
+
+       if (!XFS_IS_QUOTA_RUNNING(mp) || !XFS_IS_QUOTA_ON(mp))
                return;
 
-       ASSERT(XFS_ISLOCKED_INODE_EXCL(ip));
-       ASSERT(XFS_IS_QUOTA_RUNNING(tp->t_mountp));
+       ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
+       ASSERT(XFS_IS_QUOTA_RUNNING(mp));
 
        if (udqp) {
                xfs_dqlock(udqp);
@@ -2743,7 +2639,7 @@ xfs_qm_vop_dqattach_and_dqmod_newinode(
                xfs_dqunlock(udqp);
                ASSERT(ip->i_udquot == NULL);
                ip->i_udquot = udqp;
-               ASSERT(XFS_IS_UQUOTA_ON(tp->t_mountp));
+               ASSERT(XFS_IS_UQUOTA_ON(mp));
                ASSERT(ip->i_d.di_uid == be32_to_cpu(udqp->q_core.d_id));
                xfs_trans_mod_dquot(tp, udqp, XFS_TRANS_DQ_ICOUNT, 1);
        }
@@ -2753,8 +2649,8 @@ xfs_qm_vop_dqattach_and_dqmod_newinode(
                xfs_dqunlock(gdqp);
                ASSERT(ip->i_gdquot == NULL);
                ip->i_gdquot = gdqp;
-               ASSERT(XFS_IS_OQUOTA_ON(tp->t_mountp));
-               ASSERT((XFS_IS_GQUOTA_ON(tp->t_mountp) ?
+               ASSERT(XFS_IS_OQUOTA_ON(mp));
+               ASSERT((XFS_IS_GQUOTA_ON(mp) ?
                        ip->i_d.di_gid : ip->i_d.di_projid) ==
                                be32_to_cpu(gdqp->q_core.d_id));
                xfs_trans_mod_dquot(tp, gdqp, XFS_TRANS_DQ_ICOUNT, 1);
@@ -2789,9 +2685,7 @@ xfs_qm_freelist_destroy(xfs_frlist_t *ql)
                xfs_qm_dqdestroy(dqp);
                dqp = nextdqp;
        }
-       /*
-        * Don't bother about unlocking.
-        */
+       mutex_unlock(&ql->qh_lock);
        mutex_destroy(&ql->qh_lock);
 
        ASSERT(ql->qh_nelems == 0);
@@ -2826,34 +2720,3 @@ xfs_qm_freelist_append(xfs_frlist_t *ql, xfs_dquot_t *dq)
 {
        xfs_qm_freelist_insert((xfs_frlist_t *)ql->qh_prev, dq);
 }
-
-STATIC int
-xfs_qm_dqhashlock_nowait(
-       xfs_dquot_t *dqp)
-{
-       int locked;
-
-       locked = mutex_trylock(&((dqp)->q_hash->qh_lock));
-       return locked;
-}
-
-int
-xfs_qm_freelist_lock_nowait(
-       xfs_qm_t *xqm)
-{
-       int locked;
-
-       locked = mutex_trylock(&(xqm->qm_dqfreelist.qh_lock));
-       return locked;
-}
-
-STATIC int
-xfs_qm_mplist_nowait(
-       xfs_mount_t     *mp)
-{
-       int locked;
-
-       ASSERT(mp->m_quotainfo);
-       locked = mutex_trylock(&(XFS_QI_MPLLOCK(mp)));
-       return locked;
-}