diff options
author | Joel Becker <joel.becker@oracle.com> | 2008-02-01 18:03:57 -0500 |
---|---|---|
committer | Mark Fasheh <mfasheh@suse.com> | 2008-04-18 11:56:05 -0400 |
commit | 286eaa95c5c5915a6b72cc3f0a2534161fd7928b (patch) | |
tree | dce03b619389cc5b5e2508b30ca3e1411401cf4e /fs/ocfs2 | |
parent | e3dad42bf993a0f24eb6e46152356c9b119c15e8 (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/Makefile | 7 | ||||
-rw-r--r-- | fs/ocfs2/dlmglue.c | 7 | ||||
-rw-r--r-- | fs/ocfs2/dlmglue.h | 2 | ||||
-rw-r--r-- | fs/ocfs2/stack_o2cb.c | 41 | ||||
-rw-r--r-- | fs/ocfs2/stackglue.c | 238 | ||||
-rw-r--r-- | fs/ocfs2/stackglue.h | 36 | ||||
-rw-r--r-- | fs/ocfs2/super.c | 16 |
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 | ||
3 | EXTRA_CFLAGS += -DCATCH_BH_JBD_RACES | 3 | EXTRA_CFLAGS += -DCATCH_BH_JBD_RACES |
4 | 4 | ||
5 | obj-$(CONFIG_OCFS2_FS) += ocfs2.o | 5 | obj-$(CONFIG_OCFS2_FS) += ocfs2.o ocfs2_stackglue.o ocfs2_stack_o2cb.o |
6 | 6 | ||
7 | ocfs2-objs := \ | 7 | ocfs2-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 | ||
34 | ocfs2_stackglue-objs := stackglue.o | ||
35 | ocfs2_stack_o2cb-objs := stack_o2cb.o | ||
36 | |||
36 | obj-$(CONFIG_OCFS2_FS) += cluster/ | 37 | obj-$(CONFIG_OCFS2_FS) += cluster/ |
37 | obj-$(CONFIG_OCFS2_FS) += dlm/ | 38 | obj-$(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 | ||
2666 | void ocfs2_dlm_shutdown(struct ocfs2_super *osb) | 2666 | void 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 | ||
60 | int ocfs2_dlm_init(struct ocfs2_super *osb); | 60 | int ocfs2_dlm_init(struct ocfs2_super *osb); |
61 | void ocfs2_dlm_shutdown(struct ocfs2_super *osb); | 61 | void ocfs2_dlm_shutdown(struct ocfs2_super *osb, int hangup_pending); |
62 | void ocfs2_lock_res_init_once(struct ocfs2_lock_res *res); | 62 | void ocfs2_lock_res_init_once(struct ocfs2_lock_res *res); |
63 | void ocfs2_inode_lock_res_init(struct ocfs2_lock_res *res, | 63 | void 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 | ||
36 | static 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 | ||
159 | static void o2dlm_lock_ast_wrapper(void *astarg) | 161 | static 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 | ||
166 | static void o2dlm_blocking_ast_wrapper(void *astarg, int level) | 168 | static 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 | ||
173 | static void o2dlm_unlock_ast_wrapper(void *astarg, enum dlm_status status) | 175 | static 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 | ||
196 | static int o2cb_dlm_lock(struct ocfs2_cluster_connection *conn, | 198 | static 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 | ||
317 | static int o2cb_cluster_disconnect(struct ocfs2_cluster_connection *conn) | 320 | static 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 | ||
400 | static struct ocfs2_stack_plugin o2cb_stack = { | ||
401 | .sp_name = "o2cb", | ||
402 | .sp_ops = &o2cb_stack_ops, | ||
403 | .sp_owner = THIS_MODULE, | ||
404 | }; | ||
405 | |||
406 | static int __init o2cb_stack_init(void) | ||
407 | { | ||
408 | return ocfs2_stack_glue_register(&o2cb_stack); | ||
409 | } | ||
410 | |||
411 | static void __exit o2cb_stack_exit(void) | ||
412 | { | ||
413 | ocfs2_stack_glue_unregister(&o2cb_stack); | ||
414 | } | ||
415 | |||
416 | MODULE_AUTHOR("Oracle"); | ||
417 | MODULE_DESCRIPTION("ocfs2 driver for the classic o2cb stack"); | ||
418 | MODULE_LICENSE("GPL"); | ||
419 | module_init(o2cb_stack_init); | ||
420 | module_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" | 29 | static struct ocfs2_locking_protocol *lproto; |
30 | static DEFINE_SPINLOCK(ocfs2_stack_lock); | ||
31 | static 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 | */ | ||
37 | static struct ocfs2_stack_plugin *active_stack; | ||
38 | |||
39 | static 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 | |||
53 | static 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 | |||
84 | out: | ||
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 | */ | ||
94 | static 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 | ||
31 | struct ocfs2_locking_protocol *stack_glue_lproto; | 116 | static 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 | |||
130 | int 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 | } | ||
151 | EXPORT_SYMBOL_GPL(ocfs2_stack_glue_register); | ||
152 | |||
153 | void 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 | } | ||
172 | EXPORT_SYMBOL_GPL(ocfs2_stack_glue_unregister); | ||
173 | |||
174 | void 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 | } | ||
190 | EXPORT_SYMBOL_GPL(ocfs2_stack_glue_set_locking_protocol); | ||
32 | 191 | ||
33 | 192 | ||
34 | int ocfs2_dlm_lock(struct ocfs2_cluster_connection *conn, | 193 | int 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 | } |
206 | EXPORT_SYMBOL_GPL(ocfs2_dlm_lock); | ||
47 | 207 | ||
48 | int ocfs2_dlm_unlock(struct ocfs2_cluster_connection *conn, | 208 | int 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 | } |
217 | EXPORT_SYMBOL_GPL(ocfs2_dlm_unlock); | ||
57 | 218 | ||
58 | int ocfs2_dlm_lock_status(union ocfs2_dlm_lksb *lksb) | 219 | int 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 | } |
223 | EXPORT_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 | */ |
68 | void *ocfs2_dlm_lvb(union ocfs2_dlm_lksb *lksb) | 230 | void *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 | } |
234 | EXPORT_SYMBOL_GPL(ocfs2_dlm_lvb); | ||
72 | 235 | ||
73 | void ocfs2_dlm_dump_lksb(union ocfs2_dlm_lksb *lksb) | 236 | void 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 | } |
240 | EXPORT_SYMBOL_GPL(ocfs2_dlm_dump_lksb); | ||
77 | 241 | ||
78 | int ocfs2_cluster_connect(const char *group, | 242 | int 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: | |||
124 | out: | 293 | out: |
125 | return rc; | 294 | return rc; |
126 | } | 295 | } |
296 | EXPORT_SYMBOL_GPL(ocfs2_cluster_connect); | ||
127 | 297 | ||
128 | int ocfs2_cluster_disconnect(struct ocfs2_cluster_connection *conn) | 298 | /* If hangup_pending is 0, the stack driver will be dropped */ |
299 | int 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 | } |
317 | EXPORT_SYMBOL_GPL(ocfs2_cluster_disconnect); | ||
142 | 318 | ||
143 | void ocfs2_cluster_hangup(const char *group, int grouplen) | 319 | void 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 | } |
329 | EXPORT_SYMBOL_GPL(ocfs2_cluster_hangup); | ||
150 | 330 | ||
151 | int ocfs2_cluster_this_node(unsigned int *node) | 331 | int 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 | } |
335 | EXPORT_SYMBOL_GPL(ocfs2_cluster_this_node); | ||
155 | 336 | ||
156 | void ocfs2_stack_glue_set_locking_protocol(struct ocfs2_locking_protocol *proto) | 337 | |
338 | static 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; | 343 | static void __exit ocfs2_stack_glue_exit(void) |
344 | { | ||
345 | lproto = NULL; | ||
161 | } | 346 | } |
162 | 347 | ||
348 | MODULE_AUTHOR("Oracle"); | ||
349 | MODULE_DESCRIPTION("ocfs2 cluter stack glue layer"); | ||
350 | MODULE_LICENSE("GPL"); | ||
351 | module_init(ocfs2_stack_glue_init); | ||
352 | module_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 | */ | ||
199 | struct 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 */ | ||
187 | int ocfs2_cluster_connect(const char *group, | 212 | int 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); |
193 | int ocfs2_cluster_disconnect(struct ocfs2_cluster_connection *conn); | 218 | int ocfs2_cluster_disconnect(struct ocfs2_cluster_connection *conn, |
219 | int hangup_pending); | ||
194 | void ocfs2_cluster_hangup(const char *group, int grouplen); | 220 | void ocfs2_cluster_hangup(const char *group, int grouplen); |
195 | int ocfs2_cluster_this_node(unsigned int *node); | 221 | int 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 | ||
213 | void ocfs2_stack_glue_set_locking_protocol(struct ocfs2_locking_protocol *proto); | 239 | void ocfs2_stack_glue_set_locking_protocol(struct ocfs2_locking_protocol *proto); |
214 | 240 | ||
215 | extern struct ocfs2_locking_protocol *stack_glue_lproto; | 241 | |
216 | extern struct ocfs2_stack_operations o2cb_stack_ops; | 242 | /* Used by stack plugins */ |
243 | int ocfs2_stack_glue_register(struct ocfs2_stack_plugin *plugin); | ||
244 | void 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 | ||
1187 | static void ocfs2_dismount_volume(struct super_block *sb, int mnt_err) | 1187 | static 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); |