blob: 76ae4fcebcbdea9564e3d07f9b960f6735edce96 [file] [log] [blame]
Joel Becker24ef1812008-01-29 17:37:32 -08001/* -*- mode: c; c-basic-offset: 8; -*-
2 * vim: noexpandtab sw=8 ts=8 sts=0:
3 *
4 * stackglue.c
5 *
6 * Code which implements an OCFS2 specific interface to underlying
7 * cluster stacks.
8 *
9 * Copyright (C) 2007 Oracle. All rights reserved.
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public
13 * License as published by the Free Software Foundation, version 2.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
19 */
20
Joel Becker286eaa92008-02-01 15:03:57 -080021#include <linux/list.h>
22#include <linux/spinlock.h>
23#include <linux/module.h>
Joel Becker4670c462008-02-01 14:39:35 -080024#include <linux/slab.h>
Joel Becker6953b4c2008-01-29 16:59:56 -080025#include <linux/kmod.h>
Joel Becker74ae4e12008-01-31 23:56:17 -080026#include <linux/fs.h>
27#include <linux/kobject.h>
28#include <linux/sysfs.h>
Joel Becker4670c462008-02-01 14:39:35 -080029
Joel Becker24ef1812008-01-29 17:37:32 -080030#include "stackglue.h"
31
Joel Becker286eaa92008-02-01 15:03:57 -080032static struct ocfs2_locking_protocol *lproto;
33static DEFINE_SPINLOCK(ocfs2_stack_lock);
34static LIST_HEAD(ocfs2_stack_list);
35
36/*
37 * The stack currently in use. If not null, active_stack->sp_count > 0,
38 * the module is pinned, and the locking protocol cannot be changed.
39 */
40static struct ocfs2_stack_plugin *active_stack;
41
42static struct ocfs2_stack_plugin *ocfs2_stack_lookup(const char *name)
43{
44 struct ocfs2_stack_plugin *p;
45
46 assert_spin_locked(&ocfs2_stack_lock);
47
48 list_for_each_entry(p, &ocfs2_stack_list, sp_list) {
49 if (!strcmp(p->sp_name, name))
50 return p;
51 }
52
53 return NULL;
54}
55
56static int ocfs2_stack_driver_request(const char *name)
57{
58 int rc;
59 struct ocfs2_stack_plugin *p;
60
61 spin_lock(&ocfs2_stack_lock);
62
63 if (active_stack) {
64 /*
65 * If the active stack isn't the one we want, it cannot
66 * be selected right now.
67 */
68 if (!strcmp(active_stack->sp_name, name))
69 rc = 0;
70 else
71 rc = -EBUSY;
72 goto out;
73 }
74
75 p = ocfs2_stack_lookup(name);
76 if (!p || !try_module_get(p->sp_owner)) {
77 rc = -ENOENT;
78 goto out;
79 }
80
81 /* Ok, the stack is pinned */
82 p->sp_count++;
83 active_stack = p;
84
85 rc = 0;
86
87out:
88 spin_unlock(&ocfs2_stack_lock);
89 return rc;
90}
91
92/*
93 * This function looks up the appropriate stack and makes it active. If
94 * 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.
96 */
97static int ocfs2_stack_driver_get(const char *name)
98{
99 int rc;
100
101 rc = ocfs2_stack_driver_request(name);
102 if (rc == -ENOENT) {
103 request_module("ocfs2_stack_%s", name);
104 rc = ocfs2_stack_driver_request(name);
105 }
106
107 if (rc == -ENOENT) {
108 printk(KERN_ERR
109 "ocfs2: Cluster stack driver \"%s\" cannot be found\n",
110 name);
111 } else if (rc == -EBUSY) {
112 printk(KERN_ERR
113 "ocfs2: A different cluster stack driver is in use\n");
114 }
115
116 return rc;
117}
118
119static void ocfs2_stack_driver_put(void)
120{
121 spin_lock(&ocfs2_stack_lock);
122 BUG_ON(active_stack == NULL);
123 BUG_ON(active_stack->sp_count == 0);
124
125 active_stack->sp_count--;
126 if (!active_stack->sp_count) {
127 module_put(active_stack->sp_owner);
128 active_stack = NULL;
129 }
130 spin_unlock(&ocfs2_stack_lock);
131}
132
133int ocfs2_stack_glue_register(struct ocfs2_stack_plugin *plugin)
134{
135 int rc;
136
137 spin_lock(&ocfs2_stack_lock);
138 if (!ocfs2_stack_lookup(plugin->sp_name)) {
139 plugin->sp_count = 0;
140 plugin->sp_proto = lproto;
141 list_add(&plugin->sp_list, &ocfs2_stack_list);
142 printk(KERN_INFO "ocfs2: Registered cluster interface %s\n",
143 plugin->sp_name);
144 rc = 0;
145 } else {
146 printk(KERN_ERR "ocfs2: Stack \"%s\" already registered\n",
147 plugin->sp_name);
148 rc = -EEXIST;
149 }
150 spin_unlock(&ocfs2_stack_lock);
151
152 return rc;
153}
154EXPORT_SYMBOL_GPL(ocfs2_stack_glue_register);
155
156void ocfs2_stack_glue_unregister(struct ocfs2_stack_plugin *plugin)
157{
158 struct ocfs2_stack_plugin *p;
159
160 spin_lock(&ocfs2_stack_lock);
161 p = ocfs2_stack_lookup(plugin->sp_name);
162 if (p) {
163 BUG_ON(p != plugin);
164 BUG_ON(plugin == active_stack);
165 BUG_ON(plugin->sp_count != 0);
166 list_del_init(&plugin->sp_list);
167 printk(KERN_INFO "ocfs2: Unregistered cluster interface %s\n",
168 plugin->sp_name);
169 } else {
170 printk(KERN_ERR "Stack \"%s\" is not registered\n",
171 plugin->sp_name);
172 }
173 spin_unlock(&ocfs2_stack_lock);
174}
175EXPORT_SYMBOL_GPL(ocfs2_stack_glue_unregister);
176
177void ocfs2_stack_glue_set_locking_protocol(struct ocfs2_locking_protocol *proto)
178{
179 struct ocfs2_stack_plugin *p;
180
181 BUG_ON(proto == NULL);
182
183 spin_lock(&ocfs2_stack_lock);
184 BUG_ON(active_stack != NULL);
185
186 lproto = proto;
187 list_for_each_entry(p, &ocfs2_stack_list, sp_list) {
188 p->sp_proto = lproto;
189 }
190
191 spin_unlock(&ocfs2_stack_lock);
192}
193EXPORT_SYMBOL_GPL(ocfs2_stack_glue_set_locking_protocol);
Joel Becker24ef1812008-01-29 17:37:32 -0800194
Joel Becker24ef1812008-01-29 17:37:32 -0800195
Joel Becker553aa7e2008-02-01 14:51:03 -0800196int ocfs2_dlm_lock(struct ocfs2_cluster_connection *conn,
197 int mode,
198 union ocfs2_dlm_lksb *lksb,
199 u32 flags,
200 void *name,
201 unsigned int namelen,
202 void *astarg)
203{
Joel Becker286eaa92008-02-01 15:03:57 -0800204 BUG_ON(lproto == NULL);
Joel Becker553aa7e2008-02-01 14:51:03 -0800205
Joel Becker286eaa92008-02-01 15:03:57 -0800206 return active_stack->sp_ops->dlm_lock(conn, mode, lksb, flags,
207 name, namelen, astarg);
Joel Becker24ef1812008-01-29 17:37:32 -0800208}
Joel Becker286eaa92008-02-01 15:03:57 -0800209EXPORT_SYMBOL_GPL(ocfs2_dlm_lock);
Joel Becker24ef1812008-01-29 17:37:32 -0800210
Joel Becker553aa7e2008-02-01 14:51:03 -0800211int ocfs2_dlm_unlock(struct ocfs2_cluster_connection *conn,
212 union ocfs2_dlm_lksb *lksb,
213 u32 flags,
214 void *astarg)
215{
Joel Becker286eaa92008-02-01 15:03:57 -0800216 BUG_ON(lproto == NULL);
Joel Becker553aa7e2008-02-01 14:51:03 -0800217
Joel Becker286eaa92008-02-01 15:03:57 -0800218 return active_stack->sp_ops->dlm_unlock(conn, lksb, flags, astarg);
Joel Becker8f2c9c12008-02-01 12:16:57 -0800219}
Joel Becker286eaa92008-02-01 15:03:57 -0800220EXPORT_SYMBOL_GPL(ocfs2_dlm_unlock);
Joel Becker8f2c9c12008-02-01 12:16:57 -0800221
Joel Becker553aa7e2008-02-01 14:51:03 -0800222int ocfs2_dlm_lock_status(union ocfs2_dlm_lksb *lksb)
223{
Joel Becker286eaa92008-02-01 15:03:57 -0800224 return active_stack->sp_ops->lock_status(lksb);
Joel Becker553aa7e2008-02-01 14:51:03 -0800225}
Joel Becker286eaa92008-02-01 15:03:57 -0800226EXPORT_SYMBOL_GPL(ocfs2_dlm_lock_status);
Joel Becker553aa7e2008-02-01 14:51:03 -0800227
Joel Becker8f2c9c12008-02-01 12:16:57 -0800228/*
229 * Why don't we cast to ocfs2_meta_lvb? The "clean" answer is that we
230 * don't cast at the glue level. The real answer is that the header
231 * ordering is nigh impossible.
232 */
Joel Becker553aa7e2008-02-01 14:51:03 -0800233void *ocfs2_dlm_lvb(union ocfs2_dlm_lksb *lksb)
234{
Joel Becker286eaa92008-02-01 15:03:57 -0800235 return active_stack->sp_ops->lock_lvb(lksb);
Joel Beckercf0acdc2008-01-29 16:59:55 -0800236}
Joel Becker286eaa92008-02-01 15:03:57 -0800237EXPORT_SYMBOL_GPL(ocfs2_dlm_lvb);
Joel Beckercf0acdc2008-01-29 16:59:55 -0800238
Joel Becker553aa7e2008-02-01 14:51:03 -0800239void ocfs2_dlm_dump_lksb(union ocfs2_dlm_lksb *lksb)
240{
Joel Becker286eaa92008-02-01 15:03:57 -0800241 active_stack->sp_ops->dump_lksb(lksb);
Joel Becker553aa7e2008-02-01 14:51:03 -0800242}
Joel Becker286eaa92008-02-01 15:03:57 -0800243EXPORT_SYMBOL_GPL(ocfs2_dlm_dump_lksb);
Joel Becker553aa7e2008-02-01 14:51:03 -0800244
Joel Becker4670c462008-02-01 14:39:35 -0800245int ocfs2_cluster_connect(const char *group,
246 int grouplen,
247 void (*recovery_handler)(int node_num,
248 void *recovery_data),
249 void *recovery_data,
250 struct ocfs2_cluster_connection **conn)
251{
252 int rc = 0;
253 struct ocfs2_cluster_connection *new_conn;
Joel Becker4670c462008-02-01 14:39:35 -0800254
255 BUG_ON(group == NULL);
256 BUG_ON(conn == NULL);
257 BUG_ON(recovery_handler == NULL);
258
259 if (grouplen > GROUP_NAME_MAX) {
260 rc = -EINVAL;
261 goto out;
262 }
263
264 new_conn = kzalloc(sizeof(struct ocfs2_cluster_connection),
265 GFP_KERNEL);
266 if (!new_conn) {
267 rc = -ENOMEM;
268 goto out;
269 }
270
271 memcpy(new_conn->cc_name, group, grouplen);
272 new_conn->cc_namelen = grouplen;
273 new_conn->cc_recovery_handler = recovery_handler;
274 new_conn->cc_recovery_data = recovery_data;
275
276 /* Start the new connection at our maximum compatibility level */
Joel Becker286eaa92008-02-01 15:03:57 -0800277 new_conn->cc_version = lproto->lp_max_version;
Joel Becker4670c462008-02-01 14:39:35 -0800278
Joel Becker286eaa92008-02-01 15:03:57 -0800279 /* This will pin the stack driver if successful */
280 rc = ocfs2_stack_driver_get("o2cb");
281 if (rc)
282 goto out_free;
283
284 rc = active_stack->sp_ops->connect(new_conn);
Joel Becker553aa7e2008-02-01 14:51:03 -0800285 if (rc) {
Joel Becker286eaa92008-02-01 15:03:57 -0800286 ocfs2_stack_driver_put();
Joel Becker4670c462008-02-01 14:39:35 -0800287 goto out_free;
288 }
289
Joel Becker4670c462008-02-01 14:39:35 -0800290 *conn = new_conn;
291
292out_free:
Joel Becker553aa7e2008-02-01 14:51:03 -0800293 if (rc)
Joel Becker4670c462008-02-01 14:39:35 -0800294 kfree(new_conn);
Joel Becker4670c462008-02-01 14:39:35 -0800295
296out:
297 return rc;
298}
Joel Becker286eaa92008-02-01 15:03:57 -0800299EXPORT_SYMBOL_GPL(ocfs2_cluster_connect);
Joel Becker4670c462008-02-01 14:39:35 -0800300
Joel Becker286eaa92008-02-01 15:03:57 -0800301/* If hangup_pending is 0, the stack driver will be dropped */
302int ocfs2_cluster_disconnect(struct ocfs2_cluster_connection *conn,
303 int hangup_pending)
Joel Becker553aa7e2008-02-01 14:51:03 -0800304{
305 int ret;
306
307 BUG_ON(conn == NULL);
308
Joel Becker286eaa92008-02-01 15:03:57 -0800309 ret = active_stack->sp_ops->disconnect(conn, hangup_pending);
Joel Becker553aa7e2008-02-01 14:51:03 -0800310
311 /* XXX Should we free it anyway? */
Joel Becker286eaa92008-02-01 15:03:57 -0800312 if (!ret) {
Joel Becker553aa7e2008-02-01 14:51:03 -0800313 kfree(conn);
Joel Becker286eaa92008-02-01 15:03:57 -0800314 if (!hangup_pending)
315 ocfs2_stack_driver_put();
316 }
Joel Becker553aa7e2008-02-01 14:51:03 -0800317
318 return ret;
319}
Joel Becker286eaa92008-02-01 15:03:57 -0800320EXPORT_SYMBOL_GPL(ocfs2_cluster_disconnect);
Joel Becker553aa7e2008-02-01 14:51:03 -0800321
Joel Becker6953b4c2008-01-29 16:59:56 -0800322void ocfs2_cluster_hangup(const char *group, int grouplen)
323{
324 BUG_ON(group == NULL);
325 BUG_ON(group[grouplen] != '\0');
326
Joel Becker286eaa92008-02-01 15:03:57 -0800327 active_stack->sp_ops->hangup(group, grouplen);
328
329 /* cluster_disconnect() was called with hangup_pending==1 */
330 ocfs2_stack_driver_put();
Joel Becker19fdb622008-01-30 15:38:24 -0800331}
Joel Becker286eaa92008-02-01 15:03:57 -0800332EXPORT_SYMBOL_GPL(ocfs2_cluster_hangup);
Joel Becker19fdb622008-01-30 15:38:24 -0800333
Joel Becker553aa7e2008-02-01 14:51:03 -0800334int ocfs2_cluster_this_node(unsigned int *node)
335{
Joel Becker286eaa92008-02-01 15:03:57 -0800336 return active_stack->sp_ops->this_node(node);
Joel Becker553aa7e2008-02-01 14:51:03 -0800337}
Joel Becker286eaa92008-02-01 15:03:57 -0800338EXPORT_SYMBOL_GPL(ocfs2_cluster_this_node);
Joel Becker553aa7e2008-02-01 14:51:03 -0800339
Joel Becker286eaa92008-02-01 15:03:57 -0800340
Joel Becker74ae4e12008-01-31 23:56:17 -0800341/*
342 * Sysfs bits
343 */
344
345static ssize_t ocfs2_max_locking_protocol_show(struct kobject *kobj,
346 struct kobj_attribute *attr,
347 char *buf)
348{
349 ssize_t ret = 0;
350
351 spin_lock(&ocfs2_stack_lock);
352 if (lproto)
353 ret = snprintf(buf, PAGE_SIZE, "%u.%u\n",
354 lproto->lp_max_version.pv_major,
355 lproto->lp_max_version.pv_minor);
356 spin_unlock(&ocfs2_stack_lock);
357
358 return ret;
359}
360
361static struct kobj_attribute ocfs2_attr_max_locking_protocol =
362 __ATTR(max_locking_protocol, S_IFREG | S_IRUGO,
363 ocfs2_max_locking_protocol_show, NULL);
364
365static ssize_t ocfs2_loaded_cluster_plugins_show(struct kobject *kobj,
366 struct kobj_attribute *attr,
367 char *buf)
368{
369 ssize_t ret = 0, total = 0, remain = PAGE_SIZE;
370 struct ocfs2_stack_plugin *p;
371
372 spin_lock(&ocfs2_stack_lock);
373 list_for_each_entry(p, &ocfs2_stack_list, sp_list) {
374 ret = snprintf(buf, remain, "%s\n",
375 p->sp_name);
376 if (ret < 0) {
377 total = ret;
378 break;
379 }
380 if (ret == remain) {
381 /* snprintf() didn't fit */
382 total = -E2BIG;
383 break;
384 }
385 total += ret;
386 remain -= ret;
387 }
388 spin_unlock(&ocfs2_stack_lock);
389
390 return total;
391}
392
393static struct kobj_attribute ocfs2_attr_loaded_cluster_plugins =
394 __ATTR(loaded_cluster_plugins, S_IFREG | S_IRUGO,
395 ocfs2_loaded_cluster_plugins_show, NULL);
396
397static ssize_t ocfs2_active_cluster_plugin_show(struct kobject *kobj,
398 struct kobj_attribute *attr,
399 char *buf)
400{
401 ssize_t ret = 0;
402
403 spin_lock(&ocfs2_stack_lock);
404 if (active_stack) {
405 ret = snprintf(buf, PAGE_SIZE, "%s\n",
406 active_stack->sp_name);
407 if (ret == PAGE_SIZE)
408 ret = -E2BIG;
409 }
410 spin_unlock(&ocfs2_stack_lock);
411
412 return ret;
413}
414
415static struct kobj_attribute ocfs2_attr_active_cluster_plugin =
416 __ATTR(active_cluster_plugin, S_IFREG | S_IRUGO,
417 ocfs2_active_cluster_plugin_show, NULL);
418
419static struct attribute *ocfs2_attrs[] = {
420 &ocfs2_attr_max_locking_protocol.attr,
421 &ocfs2_attr_loaded_cluster_plugins.attr,
422 &ocfs2_attr_active_cluster_plugin.attr,
423 NULL,
424};
425
426static struct attribute_group ocfs2_attr_group = {
427 .attrs = ocfs2_attrs,
428};
429
430static struct kset *ocfs2_kset;
431
432static void ocfs2_sysfs_exit(void)
433{
434 kset_unregister(ocfs2_kset);
435}
436
437static int ocfs2_sysfs_init(void)
438{
439 int ret;
440
441 ocfs2_kset = kset_create_and_add("ocfs2", NULL, fs_kobj);
442 if (!ocfs2_kset)
443 return -ENOMEM;
444
445 ret = sysfs_create_group(&ocfs2_kset->kobj, &ocfs2_attr_group);
446 if (ret)
447 goto error;
448
449 return 0;
450
451error:
452 kset_unregister(ocfs2_kset);
453 return ret;
454}
455
Joel Becker286eaa92008-02-01 15:03:57 -0800456static int __init ocfs2_stack_glue_init(void)
Joel Becker24ef1812008-01-29 17:37:32 -0800457{
Joel Becker74ae4e12008-01-31 23:56:17 -0800458 return ocfs2_sysfs_init();
Joel Becker24ef1812008-01-29 17:37:32 -0800459}
460
Joel Becker286eaa92008-02-01 15:03:57 -0800461static void __exit ocfs2_stack_glue_exit(void)
462{
463 lproto = NULL;
Joel Becker74ae4e12008-01-31 23:56:17 -0800464 ocfs2_sysfs_exit();
Joel Becker286eaa92008-02-01 15:03:57 -0800465}
466
467MODULE_AUTHOR("Oracle");
468MODULE_DESCRIPTION("ocfs2 cluter stack glue layer");
469MODULE_LICENSE("GPL");
470module_init(ocfs2_stack_glue_init);
471module_exit(ocfs2_stack_glue_exit);