diff options
author | Christoph Hellwig <hch@infradead.org> | 2012-03-13 04:52:37 -0400 |
---|---|---|
committer | Ben Myers <bpm@sgi.com> | 2012-03-14 13:06:32 -0400 |
commit | a05931ceb0160deadbd7798d60d01b17f2d81b09 (patch) | |
tree | ca56811415e970149cc99b8b7f6ec9a4677d6025 /fs | |
parent | b84a3a96751f93071c1863f2962273973c8b8f5e (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.c | 35 | ||||
-rw-r--r-- | fs/xfs/xfs_qm.c | 132 | ||||
-rw-r--r-- | fs/xfs/xfs_qm.h | 15 | ||||
-rw-r--r-- | fs/xfs/xfs_qm_bhv.c | 16 | ||||
-rw-r--r-- | fs/xfs/xfs_super.c | 10 | ||||
-rw-r--r-- | fs/xfs/xfs_super.h | 8 | ||||
-rw-r--r-- | fs/xfs/xfs_trans_dquot.c | 4 |
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; | |||
59 | int xfs_dqerror_mod = 33; | 59 | int xfs_dqerror_mod = 33; |
60 | #endif | 60 | #endif |
61 | 61 | ||
62 | struct kmem_zone *xfs_qm_dqtrxzone; | ||
63 | static struct kmem_zone *xfs_qm_dqzone; | ||
64 | |||
62 | static struct lock_class_key xfs_dquot_other_class; | 65 | static 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( | |||
1040 | out_lock: | 1043 | out_lock: |
1041 | xfs_dqflock(dqp); | 1044 | xfs_dqflock(dqp); |
1042 | } | 1045 | } |
1046 | |||
1047 | int __init | ||
1048 | xfs_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 | |||
1062 | out_free_dqzone: | ||
1063 | kmem_zone_destroy(xfs_qm_dqzone); | ||
1064 | out: | ||
1065 | return -ENOMEM; | ||
1066 | } | ||
1067 | |||
1068 | void __exit | ||
1069 | xfs_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 | */ |
51 | struct mutex xfs_Gqm_lock; | ||
52 | struct xfs_qm *xfs_Gqm; | ||
53 | |||
54 | kmem_zone_t *qm_dqzone; | ||
55 | kmem_zone_t *qm_dqtrxzone; | ||
56 | |||
57 | STATIC int xfs_qm_init_quotainos(xfs_mount_t *); | 51 | STATIC int xfs_qm_init_quotainos(xfs_mount_t *); |
58 | STATIC int xfs_qm_init_quotainfo(xfs_mount_t *); | 52 | STATIC int xfs_qm_init_quotainfo(xfs_mount_t *); |
59 | STATIC int xfs_qm_shake(struct shrinker *, struct shrink_control *); | 53 | STATIC 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 | */ | ||
65 | STATIC struct xfs_qm * | ||
66 | xfs_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 | */ | ||
99 | STATIC void | ||
100 | xfs_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 */ | ||
116 | STATIC int | ||
117 | xfs_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 */ | ||
152 | STATIC void | ||
153 | xfs_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 | ||
25 | struct xfs_qm; | ||
26 | struct xfs_inode; | 25 | struct xfs_inode; |
27 | 26 | ||
28 | extern struct mutex xfs_Gqm_lock; | 27 | extern struct kmem_zone *xfs_qm_dqtrxzone; |
29 | extern struct xfs_qm *xfs_Gqm; | ||
30 | extern kmem_zone_t *qm_dqzone; | ||
31 | extern 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 | */ | ||
47 | typedef 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 | |||
160 | void __init | ||
161 | xfs_qm_init(void) | ||
162 | { | ||
163 | printk(KERN_INFO "SGI XFS Quota Management subsystem\n"); | ||
164 | mutex_init(&xfs_Gqm_lock); | ||
165 | } | ||
166 | |||
167 | void __exit | ||
168 | xfs_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) | |||
1682 | STATIC void __exit | 1686 | STATIC void __exit |
1683 | exit_xfs_fs(void) | 1687 | exit_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 |
24 | extern void xfs_qm_init(void); | 24 | extern int xfs_qm_init(void); |
25 | extern void xfs_qm_exit(void); | 25 | extern 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 | |||
875 | xfs_trans_alloc_dqinfo( | 875 | xfs_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 | ||
881 | void | 881 | void |
@@ -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 | } |