diff options
Diffstat (limited to 'fs/ocfs2/stackglue.c')
-rw-r--r-- | fs/ocfs2/stackglue.c | 111 |
1 files changed, 100 insertions, 11 deletions
diff --git a/fs/ocfs2/stackglue.c b/fs/ocfs2/stackglue.c index 76ae4fcebcbd..bf45d9bff8a7 100644 --- a/fs/ocfs2/stackglue.c +++ b/fs/ocfs2/stackglue.c | |||
@@ -27,11 +27,17 @@ | |||
27 | #include <linux/kobject.h> | 27 | #include <linux/kobject.h> |
28 | #include <linux/sysfs.h> | 28 | #include <linux/sysfs.h> |
29 | 29 | ||
30 | #include "ocfs2_fs.h" | ||
31 | |||
30 | #include "stackglue.h" | 32 | #include "stackglue.h" |
31 | 33 | ||
34 | #define OCFS2_STACK_PLUGIN_O2CB "o2cb" | ||
35 | #define OCFS2_STACK_PLUGIN_USER "user" | ||
36 | |||
32 | static struct ocfs2_locking_protocol *lproto; | 37 | static struct ocfs2_locking_protocol *lproto; |
33 | static DEFINE_SPINLOCK(ocfs2_stack_lock); | 38 | static DEFINE_SPINLOCK(ocfs2_stack_lock); |
34 | static LIST_HEAD(ocfs2_stack_list); | 39 | static LIST_HEAD(ocfs2_stack_list); |
40 | static char cluster_stack_name[OCFS2_STACK_LABEL_LEN + 1]; | ||
35 | 41 | ||
36 | /* | 42 | /* |
37 | * The stack currently in use. If not null, active_stack->sp_count > 0, | 43 | * The stack currently in use. If not null, active_stack->sp_count > 0, |
@@ -53,26 +59,36 @@ static struct ocfs2_stack_plugin *ocfs2_stack_lookup(const char *name) | |||
53 | return NULL; | 59 | return NULL; |
54 | } | 60 | } |
55 | 61 | ||
56 | static int ocfs2_stack_driver_request(const char *name) | 62 | static int ocfs2_stack_driver_request(const char *stack_name, |
63 | const char *plugin_name) | ||
57 | { | 64 | { |
58 | int rc; | 65 | int rc; |
59 | struct ocfs2_stack_plugin *p; | 66 | struct ocfs2_stack_plugin *p; |
60 | 67 | ||
61 | spin_lock(&ocfs2_stack_lock); | 68 | spin_lock(&ocfs2_stack_lock); |
62 | 69 | ||
70 | /* | ||
71 | * If the stack passed by the filesystem isn't the selected one, | ||
72 | * we can't continue. | ||
73 | */ | ||
74 | if (strcmp(stack_name, cluster_stack_name)) { | ||
75 | rc = -EBUSY; | ||
76 | goto out; | ||
77 | } | ||
78 | |||
63 | if (active_stack) { | 79 | if (active_stack) { |
64 | /* | 80 | /* |
65 | * If the active stack isn't the one we want, it cannot | 81 | * If the active stack isn't the one we want, it cannot |
66 | * be selected right now. | 82 | * be selected right now. |
67 | */ | 83 | */ |
68 | if (!strcmp(active_stack->sp_name, name)) | 84 | if (!strcmp(active_stack->sp_name, plugin_name)) |
69 | rc = 0; | 85 | rc = 0; |
70 | else | 86 | else |
71 | rc = -EBUSY; | 87 | rc = -EBUSY; |
72 | goto out; | 88 | goto out; |
73 | } | 89 | } |
74 | 90 | ||
75 | p = ocfs2_stack_lookup(name); | 91 | p = ocfs2_stack_lookup(plugin_name); |
76 | if (!p || !try_module_get(p->sp_owner)) { | 92 | if (!p || !try_module_get(p->sp_owner)) { |
77 | rc = -ENOENT; | 93 | rc = -ENOENT; |
78 | goto out; | 94 | goto out; |
@@ -94,23 +110,42 @@ out: | |||
94 | * there is no stack, it tries to load it. It will fail if the stack still | 110 | * there is no stack, it tries to load it. It will fail if the stack still |
95 | * cannot be found. It will also fail if a different stack is in use. | 111 | * cannot be found. It will also fail if a different stack is in use. |
96 | */ | 112 | */ |
97 | static int ocfs2_stack_driver_get(const char *name) | 113 | static int ocfs2_stack_driver_get(const char *stack_name) |
98 | { | 114 | { |
99 | int rc; | 115 | int rc; |
116 | char *plugin_name = OCFS2_STACK_PLUGIN_O2CB; | ||
117 | |||
118 | /* | ||
119 | * Classic stack does not pass in a stack name. This is | ||
120 | * compatible with older tools as well. | ||
121 | */ | ||
122 | if (!stack_name || !*stack_name) | ||
123 | stack_name = OCFS2_STACK_PLUGIN_O2CB; | ||
124 | |||
125 | if (strlen(stack_name) != OCFS2_STACK_LABEL_LEN) { | ||
126 | printk(KERN_ERR | ||
127 | "ocfs2 passed an invalid cluster stack label: \"%s\"\n", | ||
128 | stack_name); | ||
129 | return -EINVAL; | ||
130 | } | ||
100 | 131 | ||
101 | rc = ocfs2_stack_driver_request(name); | 132 | /* Anything that isn't the classic stack is a user stack */ |
133 | if (strcmp(stack_name, OCFS2_STACK_PLUGIN_O2CB)) | ||
134 | plugin_name = OCFS2_STACK_PLUGIN_USER; | ||
135 | |||
136 | rc = ocfs2_stack_driver_request(stack_name, plugin_name); | ||
102 | if (rc == -ENOENT) { | 137 | if (rc == -ENOENT) { |
103 | request_module("ocfs2_stack_%s", name); | 138 | request_module("ocfs2_stack_%s", plugin_name); |
104 | rc = ocfs2_stack_driver_request(name); | 139 | rc = ocfs2_stack_driver_request(stack_name, plugin_name); |
105 | } | 140 | } |
106 | 141 | ||
107 | if (rc == -ENOENT) { | 142 | if (rc == -ENOENT) { |
108 | printk(KERN_ERR | 143 | printk(KERN_ERR |
109 | "ocfs2: Cluster stack driver \"%s\" cannot be found\n", | 144 | "ocfs2: Cluster stack driver \"%s\" cannot be found\n", |
110 | name); | 145 | plugin_name); |
111 | } else if (rc == -EBUSY) { | 146 | } else if (rc == -EBUSY) { |
112 | printk(KERN_ERR | 147 | printk(KERN_ERR |
113 | "ocfs2: A different cluster stack driver is in use\n"); | 148 | "ocfs2: A different cluster stack is in use\n"); |
114 | } | 149 | } |
115 | 150 | ||
116 | return rc; | 151 | return rc; |
@@ -242,7 +277,8 @@ void ocfs2_dlm_dump_lksb(union ocfs2_dlm_lksb *lksb) | |||
242 | } | 277 | } |
243 | EXPORT_SYMBOL_GPL(ocfs2_dlm_dump_lksb); | 278 | EXPORT_SYMBOL_GPL(ocfs2_dlm_dump_lksb); |
244 | 279 | ||
245 | int ocfs2_cluster_connect(const char *group, | 280 | int ocfs2_cluster_connect(const char *stack_name, |
281 | const char *group, | ||
246 | int grouplen, | 282 | int grouplen, |
247 | void (*recovery_handler)(int node_num, | 283 | void (*recovery_handler)(int node_num, |
248 | void *recovery_data), | 284 | void *recovery_data), |
@@ -277,7 +313,7 @@ int ocfs2_cluster_connect(const char *group, | |||
277 | new_conn->cc_version = lproto->lp_max_version; | 313 | new_conn->cc_version = lproto->lp_max_version; |
278 | 314 | ||
279 | /* This will pin the stack driver if successful */ | 315 | /* This will pin the stack driver if successful */ |
280 | rc = ocfs2_stack_driver_get("o2cb"); | 316 | rc = ocfs2_stack_driver_get(stack_name); |
281 | if (rc) | 317 | if (rc) |
282 | goto out_free; | 318 | goto out_free; |
283 | 319 | ||
@@ -416,10 +452,61 @@ static struct kobj_attribute ocfs2_attr_active_cluster_plugin = | |||
416 | __ATTR(active_cluster_plugin, S_IFREG | S_IRUGO, | 452 | __ATTR(active_cluster_plugin, S_IFREG | S_IRUGO, |
417 | ocfs2_active_cluster_plugin_show, NULL); | 453 | ocfs2_active_cluster_plugin_show, NULL); |
418 | 454 | ||
455 | static ssize_t ocfs2_cluster_stack_show(struct kobject *kobj, | ||
456 | struct kobj_attribute *attr, | ||
457 | char *buf) | ||
458 | { | ||
459 | ssize_t ret; | ||
460 | spin_lock(&ocfs2_stack_lock); | ||
461 | ret = snprintf(buf, PAGE_SIZE, "%s\n", cluster_stack_name); | ||
462 | spin_unlock(&ocfs2_stack_lock); | ||
463 | |||
464 | return ret; | ||
465 | } | ||
466 | |||
467 | static ssize_t ocfs2_cluster_stack_store(struct kobject *kobj, | ||
468 | struct kobj_attribute *attr, | ||
469 | const char *buf, size_t count) | ||
470 | { | ||
471 | size_t len = count; | ||
472 | ssize_t ret; | ||
473 | |||
474 | if (len == 0) | ||
475 | return len; | ||
476 | |||
477 | if (buf[len - 1] == '\n') | ||
478 | len--; | ||
479 | |||
480 | if ((len != OCFS2_STACK_LABEL_LEN) || | ||
481 | (strnlen(buf, len) != len)) | ||
482 | return -EINVAL; | ||
483 | |||
484 | spin_lock(&ocfs2_stack_lock); | ||
485 | if (active_stack) { | ||
486 | if (!strncmp(buf, cluster_stack_name, len)) | ||
487 | ret = count; | ||
488 | else | ||
489 | ret = -EBUSY; | ||
490 | } else { | ||
491 | memcpy(cluster_stack_name, buf, len); | ||
492 | ret = count; | ||
493 | } | ||
494 | spin_unlock(&ocfs2_stack_lock); | ||
495 | |||
496 | return ret; | ||
497 | } | ||
498 | |||
499 | |||
500 | static struct kobj_attribute ocfs2_attr_cluster_stack = | ||
501 | __ATTR(cluster_stack, S_IFREG | S_IRUGO | S_IWUSR, | ||
502 | ocfs2_cluster_stack_show, | ||
503 | ocfs2_cluster_stack_store); | ||
504 | |||
419 | static struct attribute *ocfs2_attrs[] = { | 505 | static struct attribute *ocfs2_attrs[] = { |
420 | &ocfs2_attr_max_locking_protocol.attr, | 506 | &ocfs2_attr_max_locking_protocol.attr, |
421 | &ocfs2_attr_loaded_cluster_plugins.attr, | 507 | &ocfs2_attr_loaded_cluster_plugins.attr, |
422 | &ocfs2_attr_active_cluster_plugin.attr, | 508 | &ocfs2_attr_active_cluster_plugin.attr, |
509 | &ocfs2_attr_cluster_stack.attr, | ||
423 | NULL, | 510 | NULL, |
424 | }; | 511 | }; |
425 | 512 | ||
@@ -455,6 +542,8 @@ error: | |||
455 | 542 | ||
456 | static int __init ocfs2_stack_glue_init(void) | 543 | static int __init ocfs2_stack_glue_init(void) |
457 | { | 544 | { |
545 | strcpy(cluster_stack_name, OCFS2_STACK_PLUGIN_O2CB); | ||
546 | |||
458 | return ocfs2_sysfs_init(); | 547 | return ocfs2_sysfs_init(); |
459 | } | 548 | } |
460 | 549 | ||