aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2
diff options
context:
space:
mode:
authorJoel Becker <joel.becker@oracle.com>2008-02-01 18:03:57 -0500
committerMark Fasheh <mfasheh@suse.com>2008-04-18 11:56:05 -0400
commit286eaa95c5c5915a6b72cc3f0a2534161fd7928b (patch)
treedce03b619389cc5b5e2508b30ca3e1411401cf4e /fs/ocfs2
parente3dad42bf993a0f24eb6e46152356c9b119c15e8 (diff)
ocfs2: Break out stackglue into modules.
We define the ocfs2_stack_plugin structure to represent a stack driver. The o2cb stack code is split into stack_o2cb.c. This becomes the ocfs2_stack_o2cb.ko module. The stackglue generic functions are similarly split into the ocfs2_stackglue.ko module. This module now provides an interface to register drivers. The ocfs2_stack_o2cb driver registers itself. As part of this interface, ocfs2_stackglue can load drivers on demand. This is accomplished in ocfs2_cluster_connect(). ocfs2_cluster_disconnect() is now notified when a _hangup() is pending. If a hangup is pending, it will not release the driver module and will let _hangup() do that. Signed-off-by: Joel Becker <joel.becker@oracle.com>
Diffstat (limited to 'fs/ocfs2')
-rw-r--r--fs/ocfs2/Makefile7
-rw-r--r--fs/ocfs2/dlmglue.c7
-rw-r--r--fs/ocfs2/dlmglue.h2
-rw-r--r--fs/ocfs2/stack_o2cb.c41
-rw-r--r--fs/ocfs2/stackglue.c238
-rw-r--r--fs/ocfs2/stackglue.h36
-rw-r--r--fs/ocfs2/super.c16
7 files changed, 297 insertions, 50 deletions
diff --git a/fs/ocfs2/Makefile b/fs/ocfs2/Makefile
index 8e86195fedbf..b734254329b2 100644
--- a/fs/ocfs2/Makefile
+++ b/fs/ocfs2/Makefile
@@ -2,7 +2,7 @@ EXTRA_CFLAGS += -Ifs/ocfs2
2 2
3EXTRA_CFLAGS += -DCATCH_BH_JBD_RACES 3EXTRA_CFLAGS += -DCATCH_BH_JBD_RACES
4 4
5obj-$(CONFIG_OCFS2_FS) += ocfs2.o 5obj-$(CONFIG_OCFS2_FS) += ocfs2.o ocfs2_stackglue.o ocfs2_stack_o2cb.o
6 6
7ocfs2-objs := \ 7ocfs2-objs := \
8 alloc.o \ 8 alloc.o \
@@ -24,8 +24,6 @@ ocfs2-objs := \
24 namei.o \ 24 namei.o \
25 resize.o \ 25 resize.o \
26 slot_map.o \ 26 slot_map.o \
27 stackglue.o \
28 stack_o2cb.o \
29 suballoc.o \ 27 suballoc.o \
30 super.o \ 28 super.o \
31 symlink.o \ 29 symlink.o \
@@ -33,5 +31,8 @@ ocfs2-objs := \
33 uptodate.o \ 31 uptodate.o \
34 ver.o 32 ver.o
35 33
34ocfs2_stackglue-objs := stackglue.o
35ocfs2_stack_o2cb-objs := stack_o2cb.o
36
36obj-$(CONFIG_OCFS2_FS) += cluster/ 37obj-$(CONFIG_OCFS2_FS) += cluster/
37obj-$(CONFIG_OCFS2_FS) += dlm/ 38obj-$(CONFIG_OCFS2_FS) += dlm/
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c
index 8a9c84909be3..f62a9e4fc315 100644
--- a/fs/ocfs2/dlmglue.c
+++ b/fs/ocfs2/dlmglue.c
@@ -2641,7 +2641,7 @@ int ocfs2_dlm_init(struct ocfs2_super *osb)
2641 mlog_errno(status); 2641 mlog_errno(status);
2642 mlog(ML_ERROR, 2642 mlog(ML_ERROR,
2643 "could not find this host's node number\n"); 2643 "could not find this host's node number\n");
2644 ocfs2_cluster_disconnect(conn); 2644 ocfs2_cluster_disconnect(conn, 0);
2645 goto bail; 2645 goto bail;
2646 } 2646 }
2647 2647
@@ -2663,7 +2663,8 @@ bail:
2663 return status; 2663 return status;
2664} 2664}
2665 2665
2666void ocfs2_dlm_shutdown(struct ocfs2_super *osb) 2666void ocfs2_dlm_shutdown(struct ocfs2_super *osb,
2667 int hangup_pending)
2667{ 2668{
2668 mlog_entry_void(); 2669 mlog_entry_void();
2669 2670
@@ -2683,7 +2684,7 @@ void ocfs2_dlm_shutdown(struct ocfs2_super *osb)
2683 ocfs2_lock_res_free(&osb->osb_super_lockres); 2684 ocfs2_lock_res_free(&osb->osb_super_lockres);
2684 ocfs2_lock_res_free(&osb->osb_rename_lockres); 2685 ocfs2_lock_res_free(&osb->osb_rename_lockres);
2685 2686
2686 ocfs2_cluster_disconnect(osb->cconn); 2687 ocfs2_cluster_disconnect(osb->cconn, hangup_pending);
2687 osb->cconn = NULL; 2688 osb->cconn = NULL;
2688 2689
2689 ocfs2_dlm_shutdown_debug(osb); 2690 ocfs2_dlm_shutdown_debug(osb);
diff --git a/fs/ocfs2/dlmglue.h b/fs/ocfs2/dlmglue.h
index 34b7598a0dc6..2bb01f09c1b1 100644
--- a/fs/ocfs2/dlmglue.h
+++ b/fs/ocfs2/dlmglue.h
@@ -58,7 +58,7 @@ struct ocfs2_meta_lvb {
58#define OCFS2_LOCK_NONBLOCK (0x04) 58#define OCFS2_LOCK_NONBLOCK (0x04)
59 59
60int ocfs2_dlm_init(struct ocfs2_super *osb); 60int ocfs2_dlm_init(struct ocfs2_super *osb);
61void ocfs2_dlm_shutdown(struct ocfs2_super *osb); 61void ocfs2_dlm_shutdown(struct ocfs2_super *osb, int hangup_pending);
62void ocfs2_lock_res_init_once(struct ocfs2_lock_res *res); 62void ocfs2_lock_res_init_once(struct ocfs2_lock_res *res);
63void ocfs2_inode_lock_res_init(struct ocfs2_lock_res *res, 63void ocfs2_inode_lock_res_init(struct ocfs2_lock_res *res,
64 enum ocfs2_lock_type type, 64 enum ocfs2_lock_type type,
diff --git a/fs/ocfs2/stack_o2cb.c b/fs/ocfs2/stack_o2cb.c
index c9bc3541a33f..ac1d74c63bf5 100644
--- a/fs/ocfs2/stack_o2cb.c
+++ b/fs/ocfs2/stack_o2cb.c
@@ -18,7 +18,7 @@
18 */ 18 */
19 19
20#include <linux/crc32.h> 20#include <linux/crc32.h>
21#include <linux/kmod.h> 21#include <linux/module.h>
22 22
23/* Needed for AOP_TRUNCATED_PAGE in mlog_errno() */ 23/* Needed for AOP_TRUNCATED_PAGE in mlog_errno() */
24#include <linux/fs.h> 24#include <linux/fs.h>
@@ -33,6 +33,8 @@ struct o2dlm_private {
33 struct dlm_eviction_cb op_eviction_cb; 33 struct dlm_eviction_cb op_eviction_cb;
34}; 34};
35 35
36static struct ocfs2_stack_plugin o2cb_stack;
37
36/* These should be identical */ 38/* These should be identical */
37#if (DLM_LOCK_IV != LKM_IVMODE) 39#if (DLM_LOCK_IV != LKM_IVMODE)
38# error Lock modes do not match 40# error Lock modes do not match
@@ -158,23 +160,23 @@ static int dlm_status_to_errno(enum dlm_status status)
158 160
159static void o2dlm_lock_ast_wrapper(void *astarg) 161static void o2dlm_lock_ast_wrapper(void *astarg)
160{ 162{
161 BUG_ON(stack_glue_lproto == NULL); 163 BUG_ON(o2cb_stack.sp_proto == NULL);
162 164
163 stack_glue_lproto->lp_lock_ast(astarg); 165 o2cb_stack.sp_proto->lp_lock_ast(astarg);
164} 166}
165 167
166static void o2dlm_blocking_ast_wrapper(void *astarg, int level) 168static void o2dlm_blocking_ast_wrapper(void *astarg, int level)
167{ 169{
168 BUG_ON(stack_glue_lproto == NULL); 170 BUG_ON(o2cb_stack.sp_proto == NULL);
169 171
170 stack_glue_lproto->lp_blocking_ast(astarg, level); 172 o2cb_stack.sp_proto->lp_blocking_ast(astarg, level);
171} 173}
172 174
173static void o2dlm_unlock_ast_wrapper(void *astarg, enum dlm_status status) 175static void o2dlm_unlock_ast_wrapper(void *astarg, enum dlm_status status)
174{ 176{
175 int error = dlm_status_to_errno(status); 177 int error = dlm_status_to_errno(status);
176 178
177 BUG_ON(stack_glue_lproto == NULL); 179 BUG_ON(o2cb_stack.sp_proto == NULL);
178 180
179 /* 181 /*
180 * In o2dlm, you can get both the lock_ast() for the lock being 182 * In o2dlm, you can get both the lock_ast() for the lock being
@@ -190,7 +192,7 @@ static void o2dlm_unlock_ast_wrapper(void *astarg, enum dlm_status status)
190 if (status == DLM_CANCELGRANT) 192 if (status == DLM_CANCELGRANT)
191 return; 193 return;
192 194
193 stack_glue_lproto->lp_unlock_ast(astarg, error); 195 o2cb_stack.sp_proto->lp_unlock_ast(astarg, error);
194} 196}
195 197
196static int o2cb_dlm_lock(struct ocfs2_cluster_connection *conn, 198static int o2cb_dlm_lock(struct ocfs2_cluster_connection *conn,
@@ -267,6 +269,7 @@ static int o2cb_cluster_connect(struct ocfs2_cluster_connection *conn)
267 struct dlm_protocol_version dlm_version; 269 struct dlm_protocol_version dlm_version;
268 270
269 BUG_ON(conn == NULL); 271 BUG_ON(conn == NULL);
272 BUG_ON(o2cb_stack.sp_proto == NULL);
270 273
271 /* for now we only have one cluster/node, make sure we see it 274 /* for now we only have one cluster/node, make sure we see it
272 * in the heartbeat universe */ 275 * in the heartbeat universe */
@@ -314,7 +317,8 @@ out:
314 return rc; 317 return rc;
315} 318}
316 319
317static int o2cb_cluster_disconnect(struct ocfs2_cluster_connection *conn) 320static int o2cb_cluster_disconnect(struct ocfs2_cluster_connection *conn,
321 int hangup_pending)
318{ 322{
319 struct dlm_ctxt *dlm = conn->cc_lockspace; 323 struct dlm_ctxt *dlm = conn->cc_lockspace;
320 struct o2dlm_private *priv = conn->cc_private; 324 struct o2dlm_private *priv = conn->cc_private;
@@ -393,3 +397,24 @@ struct ocfs2_stack_operations o2cb_stack_ops = {
393 .dump_lksb = o2cb_dump_lksb, 397 .dump_lksb = o2cb_dump_lksb,
394}; 398};
395 399
400static struct ocfs2_stack_plugin o2cb_stack = {
401 .sp_name = "o2cb",
402 .sp_ops = &o2cb_stack_ops,
403 .sp_owner = THIS_MODULE,
404};
405
406static int __init o2cb_stack_init(void)
407{
408 return ocfs2_stack_glue_register(&o2cb_stack);
409}
410
411static void __exit o2cb_stack_exit(void)
412{
413 ocfs2_stack_glue_unregister(&o2cb_stack);
414}
415
416MODULE_AUTHOR("Oracle");
417MODULE_DESCRIPTION("ocfs2 driver for the classic o2cb stack");
418MODULE_LICENSE("GPL");
419module_init(o2cb_stack_init);
420module_exit(o2cb_stack_exit);
diff --git a/fs/ocfs2/stackglue.c b/fs/ocfs2/stackglue.c
index e197367b6bd6..1978c9cff0e9 100644
--- a/fs/ocfs2/stackglue.c
+++ b/fs/ocfs2/stackglue.c
@@ -18,17 +18,176 @@
18 * General Public License for more details. 18 * General Public License for more details.
19 */ 19 */
20 20
21#include <linux/list.h>
22#include <linux/spinlock.h>
23#include <linux/module.h>
21#include <linux/slab.h> 24#include <linux/slab.h>
22#include <linux/kmod.h> 25#include <linux/kmod.h>
23 26
24/* Needed for AOP_TRUNCATED_PAGE in mlog_errno() */ 27#include "stackglue.h"
25#include <linux/fs.h>
26 28
27#include "cluster/masklog.h" 29static struct ocfs2_locking_protocol *lproto;
30static DEFINE_SPINLOCK(ocfs2_stack_lock);
31static LIST_HEAD(ocfs2_stack_list);
28 32
29#include "stackglue.h" 33/*
34 * The stack currently in use. If not null, active_stack->sp_count > 0,
35 * the module is pinned, and the locking protocol cannot be changed.
36 */
37static struct ocfs2_stack_plugin *active_stack;
38
39static struct ocfs2_stack_plugin *ocfs2_stack_lookup(const char *name)
40{
41 struct ocfs2_stack_plugin *p;
42
43 assert_spin_locked(&ocfs2_stack_lock);
44
45 list_for_each_entry(p, &ocfs2_stack_list, sp_list) {
46 if (!strcmp(p->sp_name, name))
47 return p;
48 }
49
50 return NULL;
51}
52
53static int ocfs2_stack_driver_request(const char *name)
54{
55 int rc;
56 struct ocfs2_stack_plugin *p;
57
58 spin_lock(&ocfs2_stack_lock);
59
60 if (active_stack) {
61 /*
62 * If the active stack isn't the one we want, it cannot
63 * be selected right now.
64 */
65 if (!strcmp(active_stack->sp_name, name))
66 rc = 0;
67 else
68 rc = -EBUSY;
69 goto out;
70 }
71
72 p = ocfs2_stack_lookup(name);
73 if (!p || !try_module_get(p->sp_owner)) {
74 rc = -ENOENT;
75 goto out;
76 }
77
78 /* Ok, the stack is pinned */
79 p->sp_count++;
80 active_stack = p;
81
82 rc = 0;
83
84out:
85 spin_unlock(&ocfs2_stack_lock);
86 return rc;
87}
88
89/*
90 * This function looks up the appropriate stack and makes it active. If
91 * there is no stack, it tries to load it. It will fail if the stack still
92 * cannot be found. It will also fail if a different stack is in use.
93 */
94static int ocfs2_stack_driver_get(const char *name)
95{
96 int rc;
97
98 rc = ocfs2_stack_driver_request(name);
99 if (rc == -ENOENT) {
100 request_module("ocfs2_stack_%s", name);
101 rc = ocfs2_stack_driver_request(name);
102 }
103
104 if (rc == -ENOENT) {
105 printk(KERN_ERR
106 "ocfs2: Cluster stack driver \"%s\" cannot be found\n",
107 name);
108 } else if (rc == -EBUSY) {
109 printk(KERN_ERR
110 "ocfs2: A different cluster stack driver is in use\n");
111 }
112
113 return rc;
114}
30 115
31struct ocfs2_locking_protocol *stack_glue_lproto; 116static void ocfs2_stack_driver_put(void)
117{
118 spin_lock(&ocfs2_stack_lock);
119 BUG_ON(active_stack == NULL);
120 BUG_ON(active_stack->sp_count == 0);
121
122 active_stack->sp_count--;
123 if (!active_stack->sp_count) {
124 module_put(active_stack->sp_owner);
125 active_stack = NULL;
126 }
127 spin_unlock(&ocfs2_stack_lock);
128}
129
130int ocfs2_stack_glue_register(struct ocfs2_stack_plugin *plugin)
131{
132 int rc;
133
134 spin_lock(&ocfs2_stack_lock);
135 if (!ocfs2_stack_lookup(plugin->sp_name)) {
136 plugin->sp_count = 0;
137 plugin->sp_proto = lproto;
138 list_add(&plugin->sp_list, &ocfs2_stack_list);
139 printk(KERN_INFO "ocfs2: Registered cluster interface %s\n",
140 plugin->sp_name);
141 rc = 0;
142 } else {
143 printk(KERN_ERR "ocfs2: Stack \"%s\" already registered\n",
144 plugin->sp_name);
145 rc = -EEXIST;
146 }
147 spin_unlock(&ocfs2_stack_lock);
148
149 return rc;
150}
151EXPORT_SYMBOL_GPL(ocfs2_stack_glue_register);
152
153void ocfs2_stack_glue_unregister(struct ocfs2_stack_plugin *plugin)
154{
155 struct ocfs2_stack_plugin *p;
156
157 spin_lock(&ocfs2_stack_lock);
158 p = ocfs2_stack_lookup(plugin->sp_name);
159 if (p) {
160 BUG_ON(p != plugin);
161 BUG_ON(plugin == active_stack);
162 BUG_ON(plugin->sp_count != 0);
163 list_del_init(&plugin->sp_list);
164 printk(KERN_INFO "ocfs2: Unregistered cluster interface %s\n",
165 plugin->sp_name);
166 } else {
167 printk(KERN_ERR "Stack \"%s\" is not registered\n",
168 plugin->sp_name);
169 }
170 spin_unlock(&ocfs2_stack_lock);
171}
172EXPORT_SYMBOL_GPL(ocfs2_stack_glue_unregister);
173
174void ocfs2_stack_glue_set_locking_protocol(struct ocfs2_locking_protocol *proto)
175{
176 struct ocfs2_stack_plugin *p;
177
178 BUG_ON(proto == NULL);
179
180 spin_lock(&ocfs2_stack_lock);
181 BUG_ON(active_stack != NULL);
182
183 lproto = proto;
184 list_for_each_entry(p, &ocfs2_stack_list, sp_list) {
185 p->sp_proto = lproto;
186 }
187
188 spin_unlock(&ocfs2_stack_lock);
189}
190EXPORT_SYMBOL_GPL(ocfs2_stack_glue_set_locking_protocol);
32 191
33 192
34int ocfs2_dlm_lock(struct ocfs2_cluster_connection *conn, 193int ocfs2_dlm_lock(struct ocfs2_cluster_connection *conn,
@@ -39,26 +198,29 @@ int ocfs2_dlm_lock(struct ocfs2_cluster_connection *conn,
39 unsigned int namelen, 198 unsigned int namelen,
40 void *astarg) 199 void *astarg)
41{ 200{
42 BUG_ON(stack_glue_lproto == NULL); 201 BUG_ON(lproto == NULL);
43 202
44 return o2cb_stack_ops.dlm_lock(conn, mode, lksb, flags, 203 return active_stack->sp_ops->dlm_lock(conn, mode, lksb, flags,
45 name, namelen, astarg); 204 name, namelen, astarg);
46} 205}
206EXPORT_SYMBOL_GPL(ocfs2_dlm_lock);
47 207
48int ocfs2_dlm_unlock(struct ocfs2_cluster_connection *conn, 208int ocfs2_dlm_unlock(struct ocfs2_cluster_connection *conn,
49 union ocfs2_dlm_lksb *lksb, 209 union ocfs2_dlm_lksb *lksb,
50 u32 flags, 210 u32 flags,
51 void *astarg) 211 void *astarg)
52{ 212{
53 BUG_ON(stack_glue_lproto == NULL); 213 BUG_ON(lproto == NULL);
54 214
55 return o2cb_stack_ops.dlm_unlock(conn, lksb, flags, astarg); 215 return active_stack->sp_ops->dlm_unlock(conn, lksb, flags, astarg);
56} 216}
217EXPORT_SYMBOL_GPL(ocfs2_dlm_unlock);
57 218
58int ocfs2_dlm_lock_status(union ocfs2_dlm_lksb *lksb) 219int ocfs2_dlm_lock_status(union ocfs2_dlm_lksb *lksb)
59{ 220{
60 return o2cb_stack_ops.lock_status(lksb); 221 return active_stack->sp_ops->lock_status(lksb);
61} 222}
223EXPORT_SYMBOL_GPL(ocfs2_dlm_lock_status);
62 224
63/* 225/*
64 * Why don't we cast to ocfs2_meta_lvb? The "clean" answer is that we 226 * Why don't we cast to ocfs2_meta_lvb? The "clean" answer is that we
@@ -67,13 +229,15 @@ int ocfs2_dlm_lock_status(union ocfs2_dlm_lksb *lksb)
67 */ 229 */
68void *ocfs2_dlm_lvb(union ocfs2_dlm_lksb *lksb) 230void *ocfs2_dlm_lvb(union ocfs2_dlm_lksb *lksb)
69{ 231{
70 return o2cb_stack_ops.lock_lvb(lksb); 232 return active_stack->sp_ops->lock_lvb(lksb);
71} 233}
234EXPORT_SYMBOL_GPL(ocfs2_dlm_lvb);
72 235
73void ocfs2_dlm_dump_lksb(union ocfs2_dlm_lksb *lksb) 236void ocfs2_dlm_dump_lksb(union ocfs2_dlm_lksb *lksb)
74{ 237{
75 o2cb_stack_ops.dump_lksb(lksb); 238 active_stack->sp_ops->dump_lksb(lksb);
76} 239}
240EXPORT_SYMBOL_GPL(ocfs2_dlm_dump_lksb);
77 241
78int ocfs2_cluster_connect(const char *group, 242int ocfs2_cluster_connect(const char *group,
79 int grouplen, 243 int grouplen,
@@ -107,11 +271,16 @@ int ocfs2_cluster_connect(const char *group,
107 new_conn->cc_recovery_data = recovery_data; 271 new_conn->cc_recovery_data = recovery_data;
108 272
109 /* Start the new connection at our maximum compatibility level */ 273 /* Start the new connection at our maximum compatibility level */
110 new_conn->cc_version = stack_glue_lproto->lp_max_version; 274 new_conn->cc_version = lproto->lp_max_version;
275
276 /* This will pin the stack driver if successful */
277 rc = ocfs2_stack_driver_get("o2cb");
278 if (rc)
279 goto out_free;
111 280
112 rc = o2cb_stack_ops.connect(new_conn); 281 rc = active_stack->sp_ops->connect(new_conn);
113 if (rc) { 282 if (rc) {
114 mlog_errno(rc); 283 ocfs2_stack_driver_put();
115 goto out_free; 284 goto out_free;
116 } 285 }
117 286
@@ -124,39 +293,60 @@ out_free:
124out: 293out:
125 return rc; 294 return rc;
126} 295}
296EXPORT_SYMBOL_GPL(ocfs2_cluster_connect);
127 297
128int ocfs2_cluster_disconnect(struct ocfs2_cluster_connection *conn) 298/* If hangup_pending is 0, the stack driver will be dropped */
299int ocfs2_cluster_disconnect(struct ocfs2_cluster_connection *conn,
300 int hangup_pending)
129{ 301{
130 int ret; 302 int ret;
131 303
132 BUG_ON(conn == NULL); 304 BUG_ON(conn == NULL);
133 305
134 ret = o2cb_stack_ops.disconnect(conn); 306 ret = active_stack->sp_ops->disconnect(conn, hangup_pending);
135 307
136 /* XXX Should we free it anyway? */ 308 /* XXX Should we free it anyway? */
137 if (!ret) 309 if (!ret) {
138 kfree(conn); 310 kfree(conn);
311 if (!hangup_pending)
312 ocfs2_stack_driver_put();
313 }
139 314
140 return ret; 315 return ret;
141} 316}
317EXPORT_SYMBOL_GPL(ocfs2_cluster_disconnect);
142 318
143void ocfs2_cluster_hangup(const char *group, int grouplen) 319void ocfs2_cluster_hangup(const char *group, int grouplen)
144{ 320{
145 BUG_ON(group == NULL); 321 BUG_ON(group == NULL);
146 BUG_ON(group[grouplen] != '\0'); 322 BUG_ON(group[grouplen] != '\0');
147 323
148 o2cb_stack_ops.hangup(group, grouplen); 324 active_stack->sp_ops->hangup(group, grouplen);
325
326 /* cluster_disconnect() was called with hangup_pending==1 */
327 ocfs2_stack_driver_put();
149} 328}
329EXPORT_SYMBOL_GPL(ocfs2_cluster_hangup);
150 330
151int ocfs2_cluster_this_node(unsigned int *node) 331int ocfs2_cluster_this_node(unsigned int *node)
152{ 332{
153 return o2cb_stack_ops.this_node(node); 333 return active_stack->sp_ops->this_node(node);
154} 334}
335EXPORT_SYMBOL_GPL(ocfs2_cluster_this_node);
155 336
156void ocfs2_stack_glue_set_locking_protocol(struct ocfs2_locking_protocol *proto) 337
338static int __init ocfs2_stack_glue_init(void)
157{ 339{
158 BUG_ON(proto != NULL); 340 return 0;
341}
159 342
160 stack_glue_lproto = proto; 343static void __exit ocfs2_stack_glue_exit(void)
344{
345 lproto = NULL;
161} 346}
162 347
348MODULE_AUTHOR("Oracle");
349MODULE_DESCRIPTION("ocfs2 cluter stack glue layer");
350MODULE_LICENSE("GPL");
351module_init(ocfs2_stack_glue_init);
352module_exit(ocfs2_stack_glue_exit);
diff --git a/fs/ocfs2/stackglue.h b/fs/ocfs2/stackglue.h
index 083632215dc5..c96c8bb76863 100644
--- a/fs/ocfs2/stackglue.h
+++ b/fs/ocfs2/stackglue.h
@@ -119,14 +119,21 @@ struct ocfs2_stack_operations {
119 * Once ->disconnect() has returned, the connection structure will 119 * Once ->disconnect() has returned, the connection structure will
120 * be freed. Thus, a stack must not return from ->disconnect() 120 * be freed. Thus, a stack must not return from ->disconnect()
121 * until it will no longer reference the conn pointer. 121 * until it will no longer reference the conn pointer.
122 *
123 * If hangup_pending is zero, ocfs2_cluster_disconnect() will also
124 * be dropping the reference on the module.
122 */ 125 */
123 int (*disconnect)(struct ocfs2_cluster_connection *conn); 126 int (*disconnect)(struct ocfs2_cluster_connection *conn,
127 int hangup_pending);
124 128
125 /* 129 /*
126 * ocfs2_cluster_hangup() exists for compatibility with older 130 * ocfs2_cluster_hangup() exists for compatibility with older
127 * ocfs2 tools. Only the classic stack really needs it. As such 131 * ocfs2 tools. Only the classic stack really needs it. As such
128 * ->hangup() is not required of all stacks. See the comment by 132 * ->hangup() is not required of all stacks. See the comment by
129 * ocfs2_cluster_hangup() for more details. 133 * ocfs2_cluster_hangup() for more details.
134 *
135 * Note that ocfs2_cluster_hangup() can only be called if
136 * hangup_pending was passed to ocfs2_cluster_disconnect().
130 */ 137 */
131 void (*hangup)(const char *group, int grouplen); 138 void (*hangup)(const char *group, int grouplen);
132 139
@@ -184,13 +191,32 @@ struct ocfs2_stack_operations {
184 void (*dump_lksb)(union ocfs2_dlm_lksb *lksb); 191 void (*dump_lksb)(union ocfs2_dlm_lksb *lksb);
185}; 192};
186 193
194/*
195 * Each stack plugin must describe itself by registering a
196 * ocfs2_stack_plugin structure. This is only seen by stackglue and the
197 * stack driver.
198 */
199struct ocfs2_stack_plugin {
200 char *sp_name;
201 struct ocfs2_stack_operations *sp_ops;
202 struct module *sp_owner;
203
204 /* These are managed by the stackglue code. */
205 struct list_head sp_list;
206 unsigned int sp_count;
207 struct ocfs2_locking_protocol *sp_proto;
208};
209
210
211/* Used by the filesystem */
187int ocfs2_cluster_connect(const char *group, 212int ocfs2_cluster_connect(const char *group,
188 int grouplen, 213 int grouplen,
189 void (*recovery_handler)(int node_num, 214 void (*recovery_handler)(int node_num,
190 void *recovery_data), 215 void *recovery_data),
191 void *recovery_data, 216 void *recovery_data,
192 struct ocfs2_cluster_connection **conn); 217 struct ocfs2_cluster_connection **conn);
193int ocfs2_cluster_disconnect(struct ocfs2_cluster_connection *conn); 218int ocfs2_cluster_disconnect(struct ocfs2_cluster_connection *conn,
219 int hangup_pending);
194void ocfs2_cluster_hangup(const char *group, int grouplen); 220void ocfs2_cluster_hangup(const char *group, int grouplen);
195int ocfs2_cluster_this_node(unsigned int *node); 221int ocfs2_cluster_this_node(unsigned int *node);
196 222
@@ -212,6 +238,8 @@ void ocfs2_dlm_dump_lksb(union ocfs2_dlm_lksb *lksb);
212 238
213void ocfs2_stack_glue_set_locking_protocol(struct ocfs2_locking_protocol *proto); 239void ocfs2_stack_glue_set_locking_protocol(struct ocfs2_locking_protocol *proto);
214 240
215extern struct ocfs2_locking_protocol *stack_glue_lproto; 241
216extern struct ocfs2_stack_operations o2cb_stack_ops; 242/* Used by stack plugins */
243int ocfs2_stack_glue_register(struct ocfs2_stack_plugin *plugin);
244void ocfs2_stack_glue_unregister(struct ocfs2_stack_plugin *plugin);
217#endif /* STACKGLUE_H */ 245#endif /* STACKGLUE_H */
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
index b4a02a00665d..e27a0d47ea2b 100644
--- a/fs/ocfs2/super.c
+++ b/fs/ocfs2/super.c
@@ -1186,7 +1186,7 @@ leave:
1186 1186
1187static void ocfs2_dismount_volume(struct super_block *sb, int mnt_err) 1187static void ocfs2_dismount_volume(struct super_block *sb, int mnt_err)
1188{ 1188{
1189 int tmp; 1189 int tmp, hangup_needed = 0;
1190 struct ocfs2_super *osb = NULL; 1190 struct ocfs2_super *osb = NULL;
1191 char nodestr[8]; 1191 char nodestr[8];
1192 1192
@@ -1225,19 +1225,21 @@ static void ocfs2_dismount_volume(struct super_block *sb, int mnt_err)
1225 1225
1226 ocfs2_release_system_inodes(osb); 1226 ocfs2_release_system_inodes(osb);
1227 1227
1228 if (osb->cconn)
1229 ocfs2_dlm_shutdown(osb);
1230
1231 debugfs_remove(osb->osb_debug_root);
1232
1233 /* 1228 /*
1234 * This is a small hack to move ocfs2_hb_ctl into stackglue.
1235 * If we're dismounting due to mount error, mount.ocfs2 will clean 1229 * If we're dismounting due to mount error, mount.ocfs2 will clean
1236 * up heartbeat. If we're a local mount, there is no heartbeat. 1230 * up heartbeat. If we're a local mount, there is no heartbeat.
1237 * If we failed before we got a uuid_str yet, we can't stop 1231 * If we failed before we got a uuid_str yet, we can't stop
1238 * heartbeat. Otherwise, do it. 1232 * heartbeat. Otherwise, do it.
1239 */ 1233 */
1240 if (!mnt_err && !ocfs2_mount_local(osb) && osb->uuid_str) 1234 if (!mnt_err && !ocfs2_mount_local(osb) && osb->uuid_str)
1235 hangup_needed = 1;
1236
1237 if (osb->cconn)
1238 ocfs2_dlm_shutdown(osb, hangup_needed);
1239
1240 debugfs_remove(osb->osb_debug_root);
1241
1242 if (hangup_needed)
1241 ocfs2_cluster_hangup(osb->uuid_str, strlen(osb->uuid_str)); 1243 ocfs2_cluster_hangup(osb->uuid_str, strlen(osb->uuid_str));
1242 1244
1243 atomic_set(&osb->vol_state, VOLUME_DISMOUNTED); 1245 atomic_set(&osb->vol_state, VOLUME_DISMOUNTED);