xfs: remove the global xfs_Gqm structure
authorChristoph Hellwig <hch@infradead.org>
Tue, 13 Mar 2012 08:52:37 +0000 (08:52 +0000)
committerBen Myers <bpm@sgi.com>
Wed, 14 Mar 2012 17:06:32 +0000 (12:06 -0500)
If we initialize the slab caches for the quota code when XFS is loaded there
is no need for a global and reference counted quota manager structure.  Drop
all this overhead and also fix the error handling during quota initialization.

Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Ben Myers <bpm@sgi.com>
fs/xfs/xfs_dquot.c
fs/xfs/xfs_qm.c
fs/xfs/xfs_qm.h
fs/xfs/xfs_qm_bhv.c
fs/xfs/xfs_super.c
fs/xfs/xfs_super.h
fs/xfs/xfs_trans_dquot.c

index 2896ac9..4be16a0 100644 (file)
@@ -59,6 +59,9 @@ int xfs_dqreq_num;
 int xfs_dqerror_mod = 33;
 #endif
 
+struct kmem_zone               *xfs_qm_dqtrxzone;
+static struct kmem_zone                *xfs_qm_dqzone;
+
 static struct lock_class_key xfs_dquot_other_class;
 
 /*
@@ -71,7 +74,7 @@ xfs_qm_dqdestroy(
        ASSERT(list_empty(&dqp->q_lru));
 
        mutex_destroy(&dqp->q_qlock);
-       kmem_zone_free(xfs_Gqm->qm_dqzone, dqp);
+       kmem_zone_free(xfs_qm_dqzone, dqp);
 
        XFS_STATS_DEC(xs_qm_dquot);
 }
@@ -491,7 +494,7 @@ xfs_qm_dqread(
        int                     cancelflags = 0;
 
 
-       dqp = kmem_zone_zalloc(xfs_Gqm->qm_dqzone, KM_SLEEP);
+       dqp = kmem_zone_zalloc(xfs_qm_dqzone, KM_SLEEP);
 
        dqp->dq_flags = type;
        dqp->q_core.d_id = cpu_to_be32(id);
@@ -1040,3 +1043,31 @@ xfs_dqflock_pushbuf_wait(
 out_lock:
        xfs_dqflock(dqp);
 }
+
+int __init
+xfs_qm_init(void)
+{
+       xfs_qm_dqzone =
+               kmem_zone_init(sizeof(struct xfs_dquot), "xfs_dquot");
+       if (!xfs_qm_dqzone)
+               goto out;
+
+       xfs_qm_dqtrxzone =
+               kmem_zone_init(sizeof(struct xfs_dquot_acct), "xfs_dqtrx");
+       if (!xfs_qm_dqtrxzone)
+               goto out_free_dqzone;
+
+       return 0;
+
+out_free_dqzone:
+       kmem_zone_destroy(xfs_qm_dqzone);
+out:
+       return -ENOMEM;
+}
+
+void __exit
+xfs_qm_exit(void)
+{
+       kmem_zone_destroy(xfs_qm_dqtrxzone);
+       kmem_zone_destroy(xfs_qm_dqzone);
+}
index 2f92d3b..55c6afe 100644 (file)
  * quota functionality, including maintaining the freelist and hash
  * tables of dquots.
  */
-struct mutex   xfs_Gqm_lock;
-struct xfs_qm  *xfs_Gqm;
-
-kmem_zone_t    *qm_dqzone;
-kmem_zone_t    *qm_dqtrxzone;
-
 STATIC int     xfs_qm_init_quotainos(xfs_mount_t *);
 STATIC int     xfs_qm_init_quotainfo(xfs_mount_t *);
 STATIC int     xfs_qm_shake(struct shrinker *, struct shrink_control *);
 
 /*
- * Initialize the XQM structure.
- * Note that there is not one quota manager per file system.
- */
-STATIC struct xfs_qm *
-xfs_Gqm_init(void)
-{
-       xfs_qm_t        *xqm;
-
-       xqm = kmem_zalloc(sizeof(xfs_qm_t), KM_SLEEP);
-
-       /*
-        * dquot zone. we register our own low-memory callback.
-        */
-       if (!qm_dqzone) {
-               xqm->qm_dqzone = kmem_zone_init(sizeof(xfs_dquot_t),
-                                               "xfs_dquots");
-               qm_dqzone = xqm->qm_dqzone;
-       } else
-               xqm->qm_dqzone = qm_dqzone;
-
-       /*
-        * The t_dqinfo portion of transactions.
-        */
-       if (!qm_dqtrxzone) {
-               xqm->qm_dqtrxzone = kmem_zone_init(sizeof(xfs_dquot_acct_t),
-                                                  "xfs_dqtrx");
-               qm_dqtrxzone = xqm->qm_dqtrxzone;
-       } else
-               xqm->qm_dqtrxzone = qm_dqtrxzone;
-
-       xqm->qm_nrefs = 0;
-       return xqm;
-}
-
-/*
- * Destroy the global quota manager when its reference count goes to zero.
- */
-STATIC void
-xfs_qm_destroy(
-       struct xfs_qm   *xqm)
-{
-       ASSERT(xqm != NULL);
-       ASSERT(xqm->qm_nrefs == 0);
-
-       kmem_free(xqm);
-}
-
-/*
- * Called at mount time to let XQM know that another file system is
- * starting quotas. This isn't crucial information as the individual mount
- * structures are pretty independent, but it helps the XQM keep a
- * global view of what's going on.
- */
-/* ARGSUSED */
-STATIC int
-xfs_qm_hold_quotafs_ref(
-       struct xfs_mount *mp)
-{
-       /*
-        * Need to lock the xfs_Gqm structure for things like this. For example,
-        * the structure could disappear between the entry to this routine and
-        * a HOLD operation if not locked.
-        */
-       mutex_lock(&xfs_Gqm_lock);
-
-       if (!xfs_Gqm) {
-               xfs_Gqm = xfs_Gqm_init();
-               if (!xfs_Gqm) {
-                       mutex_unlock(&xfs_Gqm_lock);
-                       return ENOMEM;
-               }
-       }
-
-       /*
-        * We can keep a list of all filesystems with quotas mounted for
-        * debugging and statistical purposes, but ...
-        * Just take a reference and get out.
-        */
-       xfs_Gqm->qm_nrefs++;
-       mutex_unlock(&xfs_Gqm_lock);
-
-       return 0;
-}
-
-
-/*
- * Release the reference that a filesystem took at mount time,
- * so that we know when we need to destroy the entire quota manager.
- */
-/* ARGSUSED */
-STATIC void
-xfs_qm_rele_quotafs_ref(
-       struct xfs_mount *mp)
-{
-       ASSERT(xfs_Gqm);
-       ASSERT(xfs_Gqm->qm_nrefs > 0);
-
-       /*
-        * Destroy the entire XQM. If somebody mounts with quotaon, this'll
-        * be restarted.
-        */
-       mutex_lock(&xfs_Gqm_lock);
-       if (--xfs_Gqm->qm_nrefs == 0) {
-               xfs_qm_destroy(xfs_Gqm);
-               xfs_Gqm = NULL;
-       }
-       mutex_unlock(&xfs_Gqm_lock);
-}
-
-/*
  * We use the batch lookup interface to iterate over the dquots as it
  * currently is the only interface into the radix tree code that allows
  * fuzzy lookups instead of exact matches.  Holding the lock over multiple
@@ -738,13 +622,6 @@ xfs_qm_init_quotainfo(
 
        ASSERT(XFS_IS_QUOTA_RUNNING(mp));
 
-       /*
-        * Tell XQM that we exist as soon as possible.
-        */
-       if ((error = xfs_qm_hold_quotafs_ref(mp))) {
-               return error;
-       }
-
        qinf = mp->m_quotainfo = kmem_zalloc(sizeof(xfs_quotainfo_t), KM_SLEEP);
 
        /*
@@ -850,17 +727,9 @@ xfs_qm_destroy_quotainfo(
 
        qi = mp->m_quotainfo;
        ASSERT(qi != NULL);
-       ASSERT(xfs_Gqm != NULL);
 
        unregister_shrinker(&qi->qi_shrinker);
 
-       /*
-        * Release the reference that XQM kept, so that we know
-        * when the XQM structure should be freed. We cannot assume
-        * that xfs_Gqm is non-null after this point.
-        */
-       xfs_qm_rele_quotafs_ref(mp);
-
        if (qi->qi_uquotaip) {
                IRELE(qi->qi_uquotaip);
                qi->qi_uquotaip = NULL; /* paranoia */
@@ -1447,7 +1316,6 @@ xfs_qm_quotacheck(
                 * We must turn off quotas.
                 */
                ASSERT(mp->m_quotainfo != NULL);
-               ASSERT(xfs_Gqm != NULL);
                xfs_qm_destroy_quotainfo(mp);
                if (xfs_mount_reset_sbqflags(mp)) {
                        xfs_warn(mp,
index 7644706..44b858b 100644 (file)
 #include "xfs_dquot.h"
 #include "xfs_quota_priv.h"
 
-struct xfs_qm;
 struct xfs_inode;
 
-extern struct mutex    xfs_Gqm_lock;
-extern struct xfs_qm   *xfs_Gqm;
-extern kmem_zone_t     *qm_dqzone;
-extern kmem_zone_t     *qm_dqtrxzone;
+extern struct kmem_zone        *xfs_qm_dqtrxzone;
 
 /*
  * This defines the unit of allocation of dquots.
@@ -42,15 +38,6 @@ extern kmem_zone_t   *qm_dqtrxzone;
 #define XFS_DQUOT_CLUSTER_SIZE_FSB     (xfs_filblks_t)1
 
 /*
- * Quota Manager (global) structure. Lives only in core.
- */
-typedef struct xfs_qm {
-       uint             qm_nrefs;       /* file systems with quota on */
-       kmem_zone_t     *qm_dqzone;      /* dquot mem-alloc zone */
-       kmem_zone_t     *qm_dqtrxzone;   /* t_dqinfo of transactions */
-} xfs_qm_t;
-
-/*
  * Various quota information for individual filesystems.
  * The mount structure keeps a pointer to this.
  */
index 809f868..e6986b5 100644 (file)
@@ -156,19 +156,3 @@ xfs_qm_newmount(
 
        return 0;
 }
-
-void __init
-xfs_qm_init(void)
-{
-       printk(KERN_INFO "SGI XFS Quota Management subsystem\n");
-       mutex_init(&xfs_Gqm_lock);
-}
-
-void __exit
-xfs_qm_exit(void)
-{
-       if (qm_dqzone)
-               kmem_zone_destroy(qm_dqzone);
-       if (qm_dqtrxzone)
-               kmem_zone_destroy(qm_dqtrxzone);
-}
index e9ad789..06d23b9 100644 (file)
@@ -1654,13 +1654,17 @@ init_xfs_fs(void)
        if (error)
                goto out_cleanup_procfs;
 
-       vfs_initquota();
+       error = xfs_qm_init();
+       if (error)
+               goto out_sysctl_unregister;
 
        error = register_filesystem(&xfs_fs_type);
        if (error)
-               goto out_sysctl_unregister;
+               goto out_qm_exit;
        return 0;
 
+ out_qm_exit:
+       xfs_qm_exit();
  out_sysctl_unregister:
        xfs_sysctl_unregister();
  out_cleanup_procfs:
@@ -1682,7 +1686,7 @@ init_xfs_fs(void)
 STATIC void __exit
 exit_xfs_fs(void)
 {
-       vfs_exitquota();
+       xfs_qm_exit();
        unregister_filesystem(&xfs_fs_type);
        xfs_sysctl_unregister();
        xfs_cleanup_procfs();
index 50a3266..09b0c26 100644 (file)
 #include <linux/exportfs.h>
 
 #ifdef CONFIG_XFS_QUOTA
-extern void xfs_qm_init(void);
+extern int xfs_qm_init(void);
 extern void xfs_qm_exit(void);
-# define vfs_initquota()       xfs_qm_init()
-# define vfs_exitquota()       xfs_qm_exit()
 #else
-# define vfs_initquota()       do { } while (0)
-# define vfs_exitquota()       do { } while (0)
+# define xfs_qm_init() (0)
+# define xfs_qm_exit() do { } while (0)
 #endif
 
 #ifdef CONFIG_XFS_POSIX_ACL
index 877fe63..2790997 100644 (file)
@@ -875,7 +875,7 @@ STATIC void
 xfs_trans_alloc_dqinfo(
        xfs_trans_t     *tp)
 {
-       tp->t_dqinfo = kmem_zone_zalloc(xfs_Gqm->qm_dqtrxzone, KM_SLEEP);
+       tp->t_dqinfo = kmem_zone_zalloc(xfs_qm_dqtrxzone, KM_SLEEP);
 }
 
 void
@@ -884,6 +884,6 @@ xfs_trans_free_dqinfo(
 {
        if (!tp->t_dqinfo)
                return;
-       kmem_zone_free(xfs_Gqm->qm_dqtrxzone, tp->t_dqinfo);
+       kmem_zone_free(xfs_qm_dqtrxzone, tp->t_dqinfo);
        tp->t_dqinfo = NULL;
 }