diff options
Diffstat (limited to 'fs/ocfs2/stackglue.c')
-rw-r--r-- | fs/ocfs2/stackglue.c | 98 |
1 files changed, 63 insertions, 35 deletions
diff --git a/fs/ocfs2/stackglue.c b/fs/ocfs2/stackglue.c index f3df0baa9a48..39abf89697ed 100644 --- a/fs/ocfs2/stackglue.c +++ b/fs/ocfs2/stackglue.c | |||
@@ -36,7 +36,7 @@ | |||
36 | #define OCFS2_STACK_PLUGIN_USER "user" | 36 | #define OCFS2_STACK_PLUGIN_USER "user" |
37 | #define OCFS2_MAX_HB_CTL_PATH 256 | 37 | #define OCFS2_MAX_HB_CTL_PATH 256 |
38 | 38 | ||
39 | static struct ocfs2_locking_protocol *lproto; | 39 | static struct ocfs2_protocol_version locking_max_version; |
40 | static DEFINE_SPINLOCK(ocfs2_stack_lock); | 40 | static DEFINE_SPINLOCK(ocfs2_stack_lock); |
41 | static LIST_HEAD(ocfs2_stack_list); | 41 | static LIST_HEAD(ocfs2_stack_list); |
42 | static char cluster_stack_name[OCFS2_STACK_LABEL_LEN + 1]; | 42 | static char cluster_stack_name[OCFS2_STACK_LABEL_LEN + 1]; |
@@ -176,7 +176,7 @@ int ocfs2_stack_glue_register(struct ocfs2_stack_plugin *plugin) | |||
176 | spin_lock(&ocfs2_stack_lock); | 176 | spin_lock(&ocfs2_stack_lock); |
177 | if (!ocfs2_stack_lookup(plugin->sp_name)) { | 177 | if (!ocfs2_stack_lookup(plugin->sp_name)) { |
178 | plugin->sp_count = 0; | 178 | plugin->sp_count = 0; |
179 | plugin->sp_proto = lproto; | 179 | plugin->sp_max_proto = locking_max_version; |
180 | list_add(&plugin->sp_list, &ocfs2_stack_list); | 180 | list_add(&plugin->sp_list, &ocfs2_stack_list); |
181 | printk(KERN_INFO "ocfs2: Registered cluster interface %s\n", | 181 | printk(KERN_INFO "ocfs2: Registered cluster interface %s\n", |
182 | plugin->sp_name); | 182 | plugin->sp_name); |
@@ -213,77 +213,76 @@ void ocfs2_stack_glue_unregister(struct ocfs2_stack_plugin *plugin) | |||
213 | } | 213 | } |
214 | EXPORT_SYMBOL_GPL(ocfs2_stack_glue_unregister); | 214 | EXPORT_SYMBOL_GPL(ocfs2_stack_glue_unregister); |
215 | 215 | ||
216 | void ocfs2_stack_glue_set_locking_protocol(struct ocfs2_locking_protocol *proto) | 216 | void ocfs2_stack_glue_set_max_proto_version(struct ocfs2_protocol_version *max_proto) |
217 | { | 217 | { |
218 | struct ocfs2_stack_plugin *p; | 218 | struct ocfs2_stack_plugin *p; |
219 | 219 | ||
220 | BUG_ON(proto == NULL); | ||
221 | |||
222 | spin_lock(&ocfs2_stack_lock); | 220 | spin_lock(&ocfs2_stack_lock); |
223 | BUG_ON(active_stack != NULL); | 221 | if (memcmp(max_proto, &locking_max_version, |
222 | sizeof(struct ocfs2_protocol_version))) { | ||
223 | BUG_ON(locking_max_version.pv_major != 0); | ||
224 | 224 | ||
225 | lproto = proto; | 225 | locking_max_version = *max_proto; |
226 | list_for_each_entry(p, &ocfs2_stack_list, sp_list) { | 226 | list_for_each_entry(p, &ocfs2_stack_list, sp_list) { |
227 | p->sp_proto = lproto; | 227 | p->sp_max_proto = locking_max_version; |
228 | } | ||
228 | } | 229 | } |
229 | |||
230 | spin_unlock(&ocfs2_stack_lock); | 230 | spin_unlock(&ocfs2_stack_lock); |
231 | } | 231 | } |
232 | EXPORT_SYMBOL_GPL(ocfs2_stack_glue_set_locking_protocol); | 232 | EXPORT_SYMBOL_GPL(ocfs2_stack_glue_set_max_proto_version); |
233 | 233 | ||
234 | 234 | ||
235 | /* | 235 | /* |
236 | * The ocfs2_dlm_lock() and ocfs2_dlm_unlock() functions take | 236 | * The ocfs2_dlm_lock() and ocfs2_dlm_unlock() functions take no argument |
237 | * "struct ocfs2_lock_res *astarg" instead of "void *astarg" because the | 237 | * for the ast and bast functions. They will pass the lksb to the ast |
238 | * underlying stack plugins need to pilfer the lksb off of the lock_res. | 238 | * and bast. The caller can wrap the lksb with their own structure to |
239 | * If some other structure needs to be passed as an astarg, the plugins | 239 | * get more information. |
240 | * will need to be given a different avenue to the lksb. | ||
241 | */ | 240 | */ |
242 | int ocfs2_dlm_lock(struct ocfs2_cluster_connection *conn, | 241 | int ocfs2_dlm_lock(struct ocfs2_cluster_connection *conn, |
243 | int mode, | 242 | int mode, |
244 | union ocfs2_dlm_lksb *lksb, | 243 | struct ocfs2_dlm_lksb *lksb, |
245 | u32 flags, | 244 | u32 flags, |
246 | void *name, | 245 | void *name, |
247 | unsigned int namelen, | 246 | unsigned int namelen) |
248 | struct ocfs2_lock_res *astarg) | ||
249 | { | 247 | { |
250 | BUG_ON(lproto == NULL); | 248 | if (!lksb->lksb_conn) |
251 | 249 | lksb->lksb_conn = conn; | |
250 | else | ||
251 | BUG_ON(lksb->lksb_conn != conn); | ||
252 | return active_stack->sp_ops->dlm_lock(conn, mode, lksb, flags, | 252 | return active_stack->sp_ops->dlm_lock(conn, mode, lksb, flags, |
253 | name, namelen, astarg); | 253 | name, namelen); |
254 | } | 254 | } |
255 | EXPORT_SYMBOL_GPL(ocfs2_dlm_lock); | 255 | EXPORT_SYMBOL_GPL(ocfs2_dlm_lock); |
256 | 256 | ||
257 | int ocfs2_dlm_unlock(struct ocfs2_cluster_connection *conn, | 257 | int ocfs2_dlm_unlock(struct ocfs2_cluster_connection *conn, |
258 | union ocfs2_dlm_lksb *lksb, | 258 | struct ocfs2_dlm_lksb *lksb, |
259 | u32 flags, | 259 | u32 flags) |
260 | struct ocfs2_lock_res *astarg) | ||
261 | { | 260 | { |
262 | BUG_ON(lproto == NULL); | 261 | BUG_ON(lksb->lksb_conn == NULL); |
263 | 262 | ||
264 | return active_stack->sp_ops->dlm_unlock(conn, lksb, flags, astarg); | 263 | return active_stack->sp_ops->dlm_unlock(conn, lksb, flags); |
265 | } | 264 | } |
266 | EXPORT_SYMBOL_GPL(ocfs2_dlm_unlock); | 265 | EXPORT_SYMBOL_GPL(ocfs2_dlm_unlock); |
267 | 266 | ||
268 | int ocfs2_dlm_lock_status(union ocfs2_dlm_lksb *lksb) | 267 | int ocfs2_dlm_lock_status(struct ocfs2_dlm_lksb *lksb) |
269 | { | 268 | { |
270 | return active_stack->sp_ops->lock_status(lksb); | 269 | return active_stack->sp_ops->lock_status(lksb); |
271 | } | 270 | } |
272 | EXPORT_SYMBOL_GPL(ocfs2_dlm_lock_status); | 271 | EXPORT_SYMBOL_GPL(ocfs2_dlm_lock_status); |
273 | 272 | ||
274 | int ocfs2_dlm_lvb_valid(union ocfs2_dlm_lksb *lksb) | 273 | int ocfs2_dlm_lvb_valid(struct ocfs2_dlm_lksb *lksb) |
275 | { | 274 | { |
276 | return active_stack->sp_ops->lvb_valid(lksb); | 275 | return active_stack->sp_ops->lvb_valid(lksb); |
277 | } | 276 | } |
278 | EXPORT_SYMBOL_GPL(ocfs2_dlm_lvb_valid); | 277 | EXPORT_SYMBOL_GPL(ocfs2_dlm_lvb_valid); |
279 | 278 | ||
280 | void *ocfs2_dlm_lvb(union ocfs2_dlm_lksb *lksb) | 279 | void *ocfs2_dlm_lvb(struct ocfs2_dlm_lksb *lksb) |
281 | { | 280 | { |
282 | return active_stack->sp_ops->lock_lvb(lksb); | 281 | return active_stack->sp_ops->lock_lvb(lksb); |
283 | } | 282 | } |
284 | EXPORT_SYMBOL_GPL(ocfs2_dlm_lvb); | 283 | EXPORT_SYMBOL_GPL(ocfs2_dlm_lvb); |
285 | 284 | ||
286 | void ocfs2_dlm_dump_lksb(union ocfs2_dlm_lksb *lksb) | 285 | void ocfs2_dlm_dump_lksb(struct ocfs2_dlm_lksb *lksb) |
287 | { | 286 | { |
288 | active_stack->sp_ops->dump_lksb(lksb); | 287 | active_stack->sp_ops->dump_lksb(lksb); |
289 | } | 288 | } |
@@ -312,6 +311,7 @@ EXPORT_SYMBOL_GPL(ocfs2_plock); | |||
312 | int ocfs2_cluster_connect(const char *stack_name, | 311 | int ocfs2_cluster_connect(const char *stack_name, |
313 | const char *group, | 312 | const char *group, |
314 | int grouplen, | 313 | int grouplen, |
314 | struct ocfs2_locking_protocol *lproto, | ||
315 | void (*recovery_handler)(int node_num, | 315 | void (*recovery_handler)(int node_num, |
316 | void *recovery_data), | 316 | void *recovery_data), |
317 | void *recovery_data, | 317 | void *recovery_data, |
@@ -329,6 +329,12 @@ int ocfs2_cluster_connect(const char *stack_name, | |||
329 | goto out; | 329 | goto out; |
330 | } | 330 | } |
331 | 331 | ||
332 | if (memcmp(&lproto->lp_max_version, &locking_max_version, | ||
333 | sizeof(struct ocfs2_protocol_version))) { | ||
334 | rc = -EINVAL; | ||
335 | goto out; | ||
336 | } | ||
337 | |||
332 | new_conn = kzalloc(sizeof(struct ocfs2_cluster_connection), | 338 | new_conn = kzalloc(sizeof(struct ocfs2_cluster_connection), |
333 | GFP_KERNEL); | 339 | GFP_KERNEL); |
334 | if (!new_conn) { | 340 | if (!new_conn) { |
@@ -341,6 +347,7 @@ int ocfs2_cluster_connect(const char *stack_name, | |||
341 | new_conn->cc_recovery_handler = recovery_handler; | 347 | new_conn->cc_recovery_handler = recovery_handler; |
342 | new_conn->cc_recovery_data = recovery_data; | 348 | new_conn->cc_recovery_data = recovery_data; |
343 | 349 | ||
350 | new_conn->cc_proto = lproto; | ||
344 | /* Start the new connection at our maximum compatibility level */ | 351 | /* Start the new connection at our maximum compatibility level */ |
345 | new_conn->cc_version = lproto->lp_max_version; | 352 | new_conn->cc_version = lproto->lp_max_version; |
346 | 353 | ||
@@ -366,6 +373,24 @@ out: | |||
366 | } | 373 | } |
367 | EXPORT_SYMBOL_GPL(ocfs2_cluster_connect); | 374 | EXPORT_SYMBOL_GPL(ocfs2_cluster_connect); |
368 | 375 | ||
376 | /* The caller will ensure all nodes have the same cluster stack */ | ||
377 | int ocfs2_cluster_connect_agnostic(const char *group, | ||
378 | int grouplen, | ||
379 | struct ocfs2_locking_protocol *lproto, | ||
380 | void (*recovery_handler)(int node_num, | ||
381 | void *recovery_data), | ||
382 | void *recovery_data, | ||
383 | struct ocfs2_cluster_connection **conn) | ||
384 | { | ||
385 | char *stack_name = NULL; | ||
386 | |||
387 | if (cluster_stack_name[0]) | ||
388 | stack_name = cluster_stack_name; | ||
389 | return ocfs2_cluster_connect(stack_name, group, grouplen, lproto, | ||
390 | recovery_handler, recovery_data, conn); | ||
391 | } | ||
392 | EXPORT_SYMBOL_GPL(ocfs2_cluster_connect_agnostic); | ||
393 | |||
369 | /* If hangup_pending is 0, the stack driver will be dropped */ | 394 | /* If hangup_pending is 0, the stack driver will be dropped */ |
370 | int ocfs2_cluster_disconnect(struct ocfs2_cluster_connection *conn, | 395 | int ocfs2_cluster_disconnect(struct ocfs2_cluster_connection *conn, |
371 | int hangup_pending) | 396 | int hangup_pending) |
@@ -453,10 +478,10 @@ static ssize_t ocfs2_max_locking_protocol_show(struct kobject *kobj, | |||
453 | ssize_t ret = 0; | 478 | ssize_t ret = 0; |
454 | 479 | ||
455 | spin_lock(&ocfs2_stack_lock); | 480 | spin_lock(&ocfs2_stack_lock); |
456 | if (lproto) | 481 | if (locking_max_version.pv_major) |
457 | ret = snprintf(buf, PAGE_SIZE, "%u.%u\n", | 482 | ret = snprintf(buf, PAGE_SIZE, "%u.%u\n", |
458 | lproto->lp_max_version.pv_major, | 483 | locking_max_version.pv_major, |
459 | lproto->lp_max_version.pv_minor); | 484 | locking_max_version.pv_minor); |
460 | spin_unlock(&ocfs2_stack_lock); | 485 | spin_unlock(&ocfs2_stack_lock); |
461 | 486 | ||
462 | return ret; | 487 | return ret; |
@@ -685,7 +710,10 @@ static int __init ocfs2_stack_glue_init(void) | |||
685 | 710 | ||
686 | static void __exit ocfs2_stack_glue_exit(void) | 711 | static void __exit ocfs2_stack_glue_exit(void) |
687 | { | 712 | { |
688 | lproto = NULL; | 713 | memset(&locking_max_version, 0, |
714 | sizeof(struct ocfs2_protocol_version)); | ||
715 | locking_max_version.pv_major = 0; | ||
716 | locking_max_version.pv_minor = 0; | ||
689 | ocfs2_sysfs_exit(); | 717 | ocfs2_sysfs_exit(); |
690 | if (ocfs2_table_header) | 718 | if (ocfs2_table_header) |
691 | unregister_sysctl_table(ocfs2_table_header); | 719 | unregister_sysctl_table(ocfs2_table_header); |