aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2012-03-13 04:52:37 -0400
committerBen Myers <bpm@sgi.com>2012-03-14 13:06:32 -0400
commita05931ceb0160deadbd7798d60d01b17f2d81b09 (patch)
treeca56811415e970149cc99b8b7f6ec9a4677d6025 /fs
parentb84a3a96751f93071c1863f2962273973c8b8f5e (diff)
xfs: remove the global xfs_Gqm structure
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>
Diffstat (limited to 'fs')
-rw-r--r--fs/xfs/xfs_dquot.c35
-rw-r--r--fs/xfs/xfs_qm.c132
-rw-r--r--fs/xfs/xfs_qm.h15
-rw-r--r--fs/xfs/xfs_qm_bhv.c16
-rw-r--r--fs/xfs/xfs_super.c10
-rw-r--r--fs/xfs/xfs_super.h8
-rw-r--r--fs/xfs/xfs_trans_dquot.c4
7 files changed, 46 insertions, 174 deletions
diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c
index 2896ac953ed6..4be16a0cbe5a 100644
--- a/fs/xfs/xfs_dquot.c
+++ b/fs/xfs/xfs_dquot.c
@@ -59,6 +59,9 @@ int xfs_dqreq_num;
59int xfs_dqerror_mod = 33; 59int xfs_dqerror_mod = 33;
60#endif 60#endif
61 61
62struct kmem_zone *xfs_qm_dqtrxzone;
63static struct kmem_zone *xfs_qm_dqzone;
64
62static struct lock_class_key xfs_dquot_other_class; 65static struct lock_class_key xfs_dquot_other_class;
63 66
64/* 67/*
@@ -71,7 +74,7 @@ xfs_qm_dqdestroy(
71 ASSERT(list_empty(&dqp->q_lru)); 74 ASSERT(list_empty(&dqp->q_lru));
72 75
73 mutex_destroy(&dqp->q_qlock); 76 mutex_destroy(&dqp->q_qlock);
74 kmem_zone_free(xfs_Gqm->qm_dqzone, dqp); 77 kmem_zone_free(xfs_qm_dqzone, dqp);
75 78
76 XFS_STATS_DEC(xs_qm_dquot); 79 XFS_STATS_DEC(xs_qm_dquot);
77} 80}
@@ -491,7 +494,7 @@ xfs_qm_dqread(
491 int cancelflags = 0; 494 int cancelflags = 0;
492 495
493 496
494 dqp = kmem_zone_zalloc(xfs_Gqm->qm_dqzone, KM_SLEEP); 497 dqp = kmem_zone_zalloc(xfs_qm_dqzone, KM_SLEEP);
495 498
496 dqp->dq_flags = type; 499 dqp->dq_flags = type;
497 dqp->q_core.d_id = cpu_to_be32(id); 500 dqp->q_core.d_id = cpu_to_be32(id);
@@ -1040,3 +1043,31 @@ xfs_dqflock_pushbuf_wait(
1040out_lock: 1043out_lock:
1041 xfs_dqflock(dqp); 1044 xfs_dqflock(dqp);
1042} 1045}
1046
1047int __init
1048xfs_qm_init(void)
1049{
1050 xfs_qm_dqzone =
1051 kmem_zone_init(sizeof(struct xfs_dquot), "xfs_dquot");
1052 if (!xfs_qm_dqzone)
1053 goto out;
1054
1055 xfs_qm_dqtrxzone =
1056 kmem_zone_init(sizeof(struct xfs_dquot_acct), "xfs_dqtrx");
1057 if (!xfs_qm_dqtrxzone)
1058 goto out_free_dqzone;
1059
1060 return 0;
1061
1062out_free_dqzone:
1063 kmem_zone_destroy(xfs_qm_dqzone);
1064out:
1065 return -ENOMEM;
1066}
1067
1068void __exit
1069xfs_qm_exit(void)
1070{
1071 kmem_zone_destroy(xfs_qm_dqtrxzone);
1072 kmem_zone_destroy(xfs_qm_dqzone);
1073}
diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c
index 2f92d3b0d8a8..55c6afedc879 100644
--- a/fs/xfs/xfs_qm.c
+++ b/fs/xfs/xfs_qm.c
@@ -48,127 +48,11 @@
48 * quota functionality, including maintaining the freelist and hash 48 * quota functionality, including maintaining the freelist and hash
49 * tables of dquots. 49 * tables of dquots.
50 */ 50 */
51struct mutex xfs_Gqm_lock;
52struct xfs_qm *xfs_Gqm;
53
54kmem_zone_t *qm_dqzone;
55kmem_zone_t *qm_dqtrxzone;
56
57STATIC int xfs_qm_init_quotainos(xfs_mount_t *); 51STATIC int xfs_qm_init_quotainos(xfs_mount_t *);
58STATIC int xfs_qm_init_quotainfo(xfs_mount_t *); 52STATIC int xfs_qm_init_quotainfo(xfs_mount_t *);
59STATIC int xfs_qm_shake(struct shrinker *, struct shrink_control *); 53STATIC int xfs_qm_shake(struct shrinker *, struct shrink_control *);
60 54
61/* 55/*
62 * Initialize the XQM structure.
63 * Note that there is not one quota manager per file system.
64 */
65STATIC struct xfs_qm *
66xfs_Gqm_init(void)
67{
68 xfs_qm_t *xqm;
69
70 xqm = kmem_zalloc(sizeof(xfs_qm_t), KM_SLEEP);
71
72 /*
73 * dquot zone. we register our own low-memory callback.
74 */
75 if (!qm_dqzone) {
76 xqm->qm_dqzone = kmem_zone_init(sizeof(xfs_dquot_t),
77 "xfs_dquots");
78 qm_dqzone = xqm->qm_dqzone;
79 } else
80 xqm->qm_dqzone = qm_dqzone;
81
82 /*
83 * The t_dqinfo portion of transactions.
84 */
85 if (!qm_dqtrxzone) {
86 xqm->qm_dqtrxzone = kmem_zone_init(sizeof(xfs_dquot_acct_t),
87 "xfs_dqtrx");
88 qm_dqtrxzone = xqm->qm_dqtrxzone;
89 } else
90 xqm->qm_dqtrxzone = qm_dqtrxzone;
91
92 xqm->qm_nrefs = 0;
93 return xqm;
94}
95
96/*
97 * Destroy the global quota manager when its reference count goes to zero.
98 */
99STATIC void
100xfs_qm_destroy(
101 struct xfs_qm *xqm)
102{
103 ASSERT(xqm != NULL);
104 ASSERT(xqm->qm_nrefs == 0);
105
106 kmem_free(xqm);
107}
108
109/*
110 * Called at mount time to let XQM know that another file system is
111 * starting quotas. This isn't crucial information as the individual mount
112 * structures are pretty independent, but it helps the XQM keep a
113 * global view of what's going on.
114 */
115/* ARGSUSED */
116STATIC int
117xfs_qm_hold_quotafs_ref(
118 struct xfs_mount *mp)
119{
120 /*
121 * Need to lock the xfs_Gqm structure for things like this. For example,
122 * the structure could disappear between the entry to this routine and
123 * a HOLD operation if not locked.
124 */
125 mutex_lock(&xfs_Gqm_lock);
126
127 if (!xfs_Gqm) {
128 xfs_Gqm = xfs_Gqm_init();
129 if (!xfs_Gqm) {
130 mutex_unlock(&xfs_Gqm_lock);
131 return ENOMEM;
132 }
133 }
134
135 /*
136 * We can keep a list of all filesystems with quotas mounted for
137 * debugging and statistical purposes, but ...
138 * Just take a reference and get out.
139 */
140 xfs_Gqm->qm_nrefs++;
141 mutex_unlock(&xfs_Gqm_lock);
142
143 return 0;
144}
145
146
147/*
148 * Release the reference that a filesystem took at mount time,
149 * so that we know when we need to destroy the entire quota manager.
150 */
151/* ARGSUSED */
152STATIC void
153xfs_qm_rele_quotafs_ref(
154 struct xfs_mount *mp)
155{
156 ASSERT(xfs_Gqm);
157 ASSERT(xfs_Gqm->qm_nrefs > 0);
158
159 /*
160 * Destroy the entire XQM. If somebody mounts with quotaon, this'll
161 * be restarted.
162 */
163 mutex_lock(&xfs_Gqm_lock);
164 if (--xfs_Gqm->qm_nrefs == 0) {
165 xfs_qm_destroy(xfs_Gqm);
166 xfs_Gqm = NULL;
167 }
168 mutex_unlock(&xfs_Gqm_lock);
169}
170
171/*
172 * We use the batch lookup interface to iterate over the dquots as it 56 * We use the batch lookup interface to iterate over the dquots as it
173 * currently is the only interface into the radix tree code that allows 57 * currently is the only interface into the radix tree code that allows
174 * fuzzy lookups instead of exact matches. Holding the lock over multiple 58 * fuzzy lookups instead of exact matches. Holding the lock over multiple
@@ -738,13 +622,6 @@ xfs_qm_init_quotainfo(
738 622
739 ASSERT(XFS_IS_QUOTA_RUNNING(mp)); 623 ASSERT(XFS_IS_QUOTA_RUNNING(mp));
740 624
741 /*
742 * Tell XQM that we exist as soon as possible.
743 */
744 if ((error = xfs_qm_hold_quotafs_ref(mp))) {
745 return error;
746 }
747
748 qinf = mp->m_quotainfo = kmem_zalloc(sizeof(xfs_quotainfo_t), KM_SLEEP); 625 qinf = mp->m_quotainfo = kmem_zalloc(sizeof(xfs_quotainfo_t), KM_SLEEP);
749 626
750 /* 627 /*
@@ -850,17 +727,9 @@ xfs_qm_destroy_quotainfo(
850 727
851 qi = mp->m_quotainfo; 728 qi = mp->m_quotainfo;
852 ASSERT(qi != NULL); 729 ASSERT(qi != NULL);
853 ASSERT(xfs_Gqm != NULL);
854 730
855 unregister_shrinker(&qi->qi_shrinker); 731 unregister_shrinker(&qi->qi_shrinker);
856 732
857 /*
858 * Release the reference that XQM kept, so that we know
859 * when the XQM structure should be freed. We cannot assume
860 * that xfs_Gqm is non-null after this point.
861 */
862 xfs_qm_rele_quotafs_ref(mp);
863
864 if (qi->qi_uquotaip) { 733 if (qi->qi_uquotaip) {
865 IRELE(qi->qi_uquotaip); 734 IRELE(qi->qi_uquotaip);
866 qi->qi_uquotaip = NULL; /* paranoia */ 735 qi->qi_uquotaip = NULL; /* paranoia */
@@ -1447,7 +1316,6 @@ xfs_qm_quotacheck(
1447 * We must turn off quotas. 1316 * We must turn off quotas.
1448 */ 1317 */
1449 ASSERT(mp->m_quotainfo != NULL); 1318 ASSERT(mp->m_quotainfo != NULL);
1450 ASSERT(xfs_Gqm != NULL);
1451 xfs_qm_destroy_quotainfo(mp); 1319 xfs_qm_destroy_quotainfo(mp);
1452 if (xfs_mount_reset_sbqflags(mp)) { 1320 if (xfs_mount_reset_sbqflags(mp)) {
1453 xfs_warn(mp, 1321 xfs_warn(mp,
diff --git a/fs/xfs/xfs_qm.h b/fs/xfs/xfs_qm.h
index 76447060cd47..44b858b79d71 100644
--- a/fs/xfs/xfs_qm.h
+++ b/fs/xfs/xfs_qm.h
@@ -22,13 +22,9 @@
22#include "xfs_dquot.h" 22#include "xfs_dquot.h"
23#include "xfs_quota_priv.h" 23#include "xfs_quota_priv.h"
24 24
25struct xfs_qm;
26struct xfs_inode; 25struct xfs_inode;
27 26
28extern struct mutex xfs_Gqm_lock; 27extern struct kmem_zone *xfs_qm_dqtrxzone;
29extern struct xfs_qm *xfs_Gqm;
30extern kmem_zone_t *qm_dqzone;
31extern kmem_zone_t *qm_dqtrxzone;
32 28
33/* 29/*
34 * This defines the unit of allocation of dquots. 30 * This defines the unit of allocation of dquots.
@@ -42,15 +38,6 @@ extern kmem_zone_t *qm_dqtrxzone;
42#define XFS_DQUOT_CLUSTER_SIZE_FSB (xfs_filblks_t)1 38#define XFS_DQUOT_CLUSTER_SIZE_FSB (xfs_filblks_t)1
43 39
44/* 40/*
45 * Quota Manager (global) structure. Lives only in core.
46 */
47typedef struct xfs_qm {
48 uint qm_nrefs; /* file systems with quota on */
49 kmem_zone_t *qm_dqzone; /* dquot mem-alloc zone */
50 kmem_zone_t *qm_dqtrxzone; /* t_dqinfo of transactions */
51} xfs_qm_t;
52
53/*
54 * Various quota information for individual filesystems. 41 * Various quota information for individual filesystems.
55 * The mount structure keeps a pointer to this. 42 * The mount structure keeps a pointer to this.
56 */ 43 */
diff --git a/fs/xfs/xfs_qm_bhv.c b/fs/xfs/xfs_qm_bhv.c
index 809f86857c6d..e6986b5d80d8 100644
--- a/fs/xfs/xfs_qm_bhv.c
+++ b/fs/xfs/xfs_qm_bhv.c
@@ -156,19 +156,3 @@ xfs_qm_newmount(
156 156
157 return 0; 157 return 0;
158} 158}
159
160void __init
161xfs_qm_init(void)
162{
163 printk(KERN_INFO "SGI XFS Quota Management subsystem\n");
164 mutex_init(&xfs_Gqm_lock);
165}
166
167void __exit
168xfs_qm_exit(void)
169{
170 if (qm_dqzone)
171 kmem_zone_destroy(qm_dqzone);
172 if (qm_dqtrxzone)
173 kmem_zone_destroy(qm_dqtrxzone);
174}
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
index e9ad7894648e..06d23b976f4c 100644
--- a/fs/xfs/xfs_super.c
+++ b/fs/xfs/xfs_super.c
@@ -1654,13 +1654,17 @@ init_xfs_fs(void)
1654 if (error) 1654 if (error)
1655 goto out_cleanup_procfs; 1655 goto out_cleanup_procfs;
1656 1656
1657 vfs_initquota(); 1657 error = xfs_qm_init();
1658 if (error)
1659 goto out_sysctl_unregister;
1658 1660
1659 error = register_filesystem(&xfs_fs_type); 1661 error = register_filesystem(&xfs_fs_type);
1660 if (error) 1662 if (error)
1661 goto out_sysctl_unregister; 1663 goto out_qm_exit;
1662 return 0; 1664 return 0;
1663 1665
1666 out_qm_exit:
1667 xfs_qm_exit();
1664 out_sysctl_unregister: 1668 out_sysctl_unregister:
1665 xfs_sysctl_unregister(); 1669 xfs_sysctl_unregister();
1666 out_cleanup_procfs: 1670 out_cleanup_procfs:
@@ -1682,7 +1686,7 @@ init_xfs_fs(void)
1682STATIC void __exit 1686STATIC void __exit
1683exit_xfs_fs(void) 1687exit_xfs_fs(void)
1684{ 1688{
1685 vfs_exitquota(); 1689 xfs_qm_exit();
1686 unregister_filesystem(&xfs_fs_type); 1690 unregister_filesystem(&xfs_fs_type);
1687 xfs_sysctl_unregister(); 1691 xfs_sysctl_unregister();
1688 xfs_cleanup_procfs(); 1692 xfs_cleanup_procfs();
diff --git a/fs/xfs/xfs_super.h b/fs/xfs/xfs_super.h
index 50a3266c999e..09b0c26b2245 100644
--- a/fs/xfs/xfs_super.h
+++ b/fs/xfs/xfs_super.h
@@ -21,13 +21,11 @@
21#include <linux/exportfs.h> 21#include <linux/exportfs.h>
22 22
23#ifdef CONFIG_XFS_QUOTA 23#ifdef CONFIG_XFS_QUOTA
24extern void xfs_qm_init(void); 24extern int xfs_qm_init(void);
25extern void xfs_qm_exit(void); 25extern void xfs_qm_exit(void);
26# define vfs_initquota() xfs_qm_init()
27# define vfs_exitquota() xfs_qm_exit()
28#else 26#else
29# define vfs_initquota() do { } while (0) 27# define xfs_qm_init() (0)
30# define vfs_exitquota() do { } while (0) 28# define xfs_qm_exit() do { } while (0)
31#endif 29#endif
32 30
33#ifdef CONFIG_XFS_POSIX_ACL 31#ifdef CONFIG_XFS_POSIX_ACL
diff --git a/fs/xfs/xfs_trans_dquot.c b/fs/xfs/xfs_trans_dquot.c
index 877fe6367d2d..279099717ed2 100644
--- a/fs/xfs/xfs_trans_dquot.c
+++ b/fs/xfs/xfs_trans_dquot.c
@@ -875,7 +875,7 @@ STATIC void
875xfs_trans_alloc_dqinfo( 875xfs_trans_alloc_dqinfo(
876 xfs_trans_t *tp) 876 xfs_trans_t *tp)
877{ 877{
878 tp->t_dqinfo = kmem_zone_zalloc(xfs_Gqm->qm_dqtrxzone, KM_SLEEP); 878 tp->t_dqinfo = kmem_zone_zalloc(xfs_qm_dqtrxzone, KM_SLEEP);
879} 879}
880 880
881void 881void
@@ -884,6 +884,6 @@ xfs_trans_free_dqinfo(
884{ 884{
885 if (!tp->t_dqinfo) 885 if (!tp->t_dqinfo)
886 return; 886 return;
887 kmem_zone_free(xfs_Gqm->qm_dqtrxzone, tp->t_dqinfo); 887 kmem_zone_free(xfs_qm_dqtrxzone, tp->t_dqinfo);
888 tp->t_dqinfo = NULL; 888 tp->t_dqinfo = NULL;
889} 889}