Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
[safe/jmp/linux-2.6] / fs / xfs / quota / xfs_qm.c
index e15ee7c..7a2beb6 100644 (file)
@@ -20,7 +20,6 @@
 #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"
@@ -192,8 +191,8 @@ xfs_qm_destroy(
                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;
@@ -201,7 +200,7 @@ xfs_qm_destroy(
 #ifdef DEBUG
        mutex_destroy(&qcheck_lock);
 #endif
-       kmem_free(xqm, sizeof(xfs_qm_t));
+       kmem_free(xqm);
 }
 
 /*
@@ -310,8 +309,7 @@ xfs_qm_unmount_quotadestroy(
  */
 void
 xfs_qm_mount_quotas(
-       xfs_mount_t     *mp,
-       int             mfsi_flags)
+       xfs_mount_t     *mp)
 {
        int             error = 0;
        uint            sbf;
@@ -346,8 +344,7 @@ 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 (XFS_QM_NEED_QUOTACHECK(mp)) {
                error = xfs_qm_quotacheck(mp);
                if (error) {
                        /* Quotacheck failed and disabled quotas. */
@@ -398,13 +395,10 @@ xfs_qm_mount_quotas(
 /*
  * 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.
@@ -417,43 +411,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);
 }
 
 /*
@@ -484,7 +453,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
@@ -631,7 +600,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);
@@ -670,7 +639,7 @@ xfs_qm_dqattach_one(
        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
@@ -874,7 +843,7 @@ xfs_qm_dqattach(
                return 0;
 
        ASSERT((flags & XFS_QMOPT_ILOCKED) == 0 ||
-              XFS_ISLOCKED_INODE_EXCL(ip));
+              xfs_isilocked(ip, XFS_ILOCK_EXCL));
 
        if (! (flags & XFS_QMOPT_ILOCKED))
                xfs_ilock(ip, XFS_ILOCK_EXCL);
@@ -888,7 +857,8 @@ xfs_qm_dqattach(
                        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,
@@ -913,7 +883,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);
 
@@ -956,7 +926,7 @@ xfs_qm_dqattach(
 
 #ifdef QUOTADEBUG
        else
-               ASSERT(XFS_ISLOCKED_INODE_EXCL(ip));
+               ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
 #endif
        return error;
 }
@@ -988,14 +958,10 @@ 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,
@@ -1061,7 +1027,7 @@ 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;
@@ -1104,6 +1070,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
@@ -1133,13 +1106,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;
        }
 
-       spin_lock_init(&qinf->qi_pinlock);
        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 */
@@ -1235,19 +1209,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;
 }
 
@@ -1291,7 +1264,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,8 +1365,8 @@ 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.
@@ -1622,7 +1595,7 @@ xfs_qm_dqiterate(
                        break;
        } while (nmaps > 0);
 
-       kmem_free(map, XFS_DQITER_MAP_SIZE * sizeof(*map));
+       kmem_free(map);
 
        return error;
 }
@@ -1737,12 +1710,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
@@ -1927,7 +1894,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);
        }
@@ -2081,7 +2051,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;
@@ -2259,7 +2229,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;
                }
@@ -2389,9 +2359,9 @@ xfs_qm_write_sb_changes(
        }
 
        xfs_mod_sb(tp, flags);
-       (void) xfs_trans_commit(tp, 0);
+       error = xfs_trans_commit(tp, 0);
 
-       return 0;
+       return error;
 }
 
 
@@ -2560,7 +2530,7 @@ 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 */
@@ -2604,7 +2574,7 @@ xfs_qm_vop_chown_reserve(
        uint            delblks, blkflags, prjflags = 0;
        xfs_dquot_t     *unresudq, *unresgdq, *delblksudq, *delblksgdq;
 
-       ASSERT(XFS_ISLOCKED_INODE(ip));
+       ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL|XFS_ILOCK_SHARED));
        mp = ip->i_mount;
        ASSERT(XFS_IS_QUOTA_RUNNING(mp));
 
@@ -2714,7 +2684,7 @@ xfs_qm_vop_dqattach_and_dqmod_newinode(
        if (!XFS_IS_QUOTA_ON(tp->t_mountp))
                return;
 
-       ASSERT(XFS_ISLOCKED_INODE_EXCL(ip));
+       ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
        ASSERT(XFS_IS_QUOTA_RUNNING(tp->t_mountp));
 
        if (udqp) {