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); |
