diff options
author | Joel Becker <joel.becker@oracle.com> | 2008-02-01 17:39:35 -0500 |
---|---|---|
committer | Mark Fasheh <mfasheh@suse.com> | 2008-04-18 11:56:04 -0400 |
commit | 4670c46ded9a18268d1265417ff4ac72145a7917 (patch) | |
tree | 4f70822ddee389a9c8ed572b215a3355c20db3a1 | |
parent | 8f2c9c1b16bf6ed0903b29c49d56fa0109a390e4 (diff) |
ocfs2: Introduce the new ocfs2_cluster_connect/disconnect() API.
This step introduces a cluster stack agnostic API for initializing and
exiting. fs/ocfs2/dlmglue.c no longer uses o2cb/o2dlm knowledge to
connect to the stack. It is all handled in stackglue.c.
heartbeat.c no longer needs to know how it gets called.
ocfs2_do_node_down() is now a clean recovery trigger.
The big gotcha is the ordering of initializations and de-initializations done
underneath ocfs2_cluster_connect(). ocfs2_dlm_init() used to do all
o2dlm initialization in one block. Thus, the o2dlm functionality of
ocfs2_cluster_connect() is very straightforward. ocfs2_dlm_shutdown(),
however, did a few things between de-registration of the eviction
callback and actually shutting down the domain. Now de-registration and
shutdown of the domain are wrapped within the single
ocfs2_cluster_disconnect() call. I've checked the code paths to make
sure we can safely tear down things in ocfs2_dlm_shutdown() before
calling ocfs2_cluster_disconnect(). The filesystem has already set
itself to ignore the callback.
Signed-off-by: Joel Becker <joel.becker@oracle.com>
Signed-off-by: Mark Fasheh <mfasheh@suse.com>
-rw-r--r-- | fs/ocfs2/dlmglue.c | 97 | ||||
-rw-r--r-- | fs/ocfs2/dlmglue.h | 1 | ||||
-rw-r--r-- | fs/ocfs2/heartbeat.c | 40 | ||||
-rw-r--r-- | fs/ocfs2/heartbeat.h | 2 | ||||
-rw-r--r-- | fs/ocfs2/ocfs2.h | 4 | ||||
-rw-r--r-- | fs/ocfs2/stackglue.c | 131 | ||||
-rw-r--r-- | fs/ocfs2/stackglue.h | 35 | ||||
-rw-r--r-- | fs/ocfs2/super.c | 13 |
8 files changed, 221 insertions, 102 deletions
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index 459037653e5a..6652a48cbe0f 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c | |||
@@ -27,7 +27,6 @@ | |||
27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | #include <linux/highmem.h> | 28 | #include <linux/highmem.h> |
29 | #include <linux/mm.h> | 29 | #include <linux/mm.h> |
30 | #include <linux/crc32.h> | ||
31 | #include <linux/kthread.h> | 30 | #include <linux/kthread.h> |
32 | #include <linux/pagemap.h> | 31 | #include <linux/pagemap.h> |
33 | #include <linux/debugfs.h> | 32 | #include <linux/debugfs.h> |
@@ -259,31 +258,6 @@ static struct ocfs2_lock_res_ops ocfs2_flock_lops = { | |||
259 | .flags = 0, | 258 | .flags = 0, |
260 | }; | 259 | }; |
261 | 260 | ||
262 | /* | ||
263 | * This is the filesystem locking protocol version. | ||
264 | * | ||
265 | * Whenever the filesystem does new things with locks (adds or removes a | ||
266 | * lock, orders them differently, does different things underneath a lock), | ||
267 | * the version must be changed. The protocol is negotiated when joining | ||
268 | * the dlm domain. A node may join the domain if its major version is | ||
269 | * identical to all other nodes and its minor version is greater than | ||
270 | * or equal to all other nodes. When its minor version is greater than | ||
271 | * the other nodes, it will run at the minor version specified by the | ||
272 | * other nodes. | ||
273 | * | ||
274 | * If a locking change is made that will not be compatible with older | ||
275 | * versions, the major number must be increased and the minor version set | ||
276 | * to zero. If a change merely adds a behavior that can be disabled when | ||
277 | * speaking to older versions, the minor version must be increased. If a | ||
278 | * change adds a fully backwards compatible change (eg, LVB changes that | ||
279 | * are just ignored by older versions), the version does not need to be | ||
280 | * updated. | ||
281 | */ | ||
282 | const struct dlm_protocol_version ocfs2_locking_protocol = { | ||
283 | .pv_major = OCFS2_LOCKING_PROTOCOL_MAJOR, | ||
284 | .pv_minor = OCFS2_LOCKING_PROTOCOL_MINOR, | ||
285 | }; | ||
286 | |||
287 | static inline int ocfs2_is_inode_lock(struct ocfs2_lock_res *lockres) | 261 | static inline int ocfs2_is_inode_lock(struct ocfs2_lock_res *lockres) |
288 | { | 262 | { |
289 | return lockres->l_type == OCFS2_LOCK_TYPE_META || | 263 | return lockres->l_type == OCFS2_LOCK_TYPE_META || |
@@ -886,7 +860,7 @@ static int ocfs2_lock_create(struct ocfs2_super *osb, | |||
886 | lockres_or_flags(lockres, OCFS2_LOCK_BUSY); | 860 | lockres_or_flags(lockres, OCFS2_LOCK_BUSY); |
887 | spin_unlock_irqrestore(&lockres->l_lock, flags); | 861 | spin_unlock_irqrestore(&lockres->l_lock, flags); |
888 | 862 | ||
889 | ret = ocfs2_dlm_lock(osb->dlm, | 863 | ret = ocfs2_dlm_lock(osb->cconn, |
890 | level, | 864 | level, |
891 | &lockres->l_lksb, | 865 | &lockres->l_lksb, |
892 | dlm_flags, | 866 | dlm_flags, |
@@ -1085,7 +1059,7 @@ again: | |||
1085 | lockres->l_name, lockres->l_level, level); | 1059 | lockres->l_name, lockres->l_level, level); |
1086 | 1060 | ||
1087 | /* call dlm_lock to upgrade lock now */ | 1061 | /* call dlm_lock to upgrade lock now */ |
1088 | ret = ocfs2_dlm_lock(osb->dlm, | 1062 | ret = ocfs2_dlm_lock(osb->cconn, |
1089 | level, | 1063 | level, |
1090 | &lockres->l_lksb, | 1064 | &lockres->l_lksb, |
1091 | lkm_flags, | 1065 | lkm_flags, |
@@ -1492,7 +1466,7 @@ int ocfs2_file_lock(struct file *file, int ex, int trylock) | |||
1492 | lockres_add_mask_waiter(lockres, &mw, OCFS2_LOCK_BUSY, 0); | 1466 | lockres_add_mask_waiter(lockres, &mw, OCFS2_LOCK_BUSY, 0); |
1493 | spin_unlock_irqrestore(&lockres->l_lock, flags); | 1467 | spin_unlock_irqrestore(&lockres->l_lock, flags); |
1494 | 1468 | ||
1495 | ret = ocfs2_dlm_lock(osb->dlm, level, &lockres->l_lksb, lkm_flags, | 1469 | ret = ocfs2_dlm_lock(osb->cconn, level, &lockres->l_lksb, lkm_flags, |
1496 | lockres->l_name, OCFS2_LOCK_ID_MAX_LEN - 1, | 1470 | lockres->l_name, OCFS2_LOCK_ID_MAX_LEN - 1, |
1497 | lockres); | 1471 | lockres); |
1498 | if (ret) { | 1472 | if (ret) { |
@@ -2485,8 +2459,7 @@ static void ocfs2_dlm_shutdown_debug(struct ocfs2_super *osb) | |||
2485 | int ocfs2_dlm_init(struct ocfs2_super *osb) | 2459 | int ocfs2_dlm_init(struct ocfs2_super *osb) |
2486 | { | 2460 | { |
2487 | int status = 0; | 2461 | int status = 0; |
2488 | u32 dlm_key; | 2462 | struct ocfs2_cluster_connection *conn = NULL; |
2489 | struct dlm_ctxt *dlm = NULL; | ||
2490 | 2463 | ||
2491 | mlog_entry_void(); | 2464 | mlog_entry_void(); |
2492 | 2465 | ||
@@ -2508,26 +2481,21 @@ int ocfs2_dlm_init(struct ocfs2_super *osb) | |||
2508 | goto bail; | 2481 | goto bail; |
2509 | } | 2482 | } |
2510 | 2483 | ||
2511 | /* used by the dlm code to make message headers unique, each | ||
2512 | * node in this domain must agree on this. */ | ||
2513 | dlm_key = crc32_le(0, osb->uuid_str, strlen(osb->uuid_str)); | ||
2514 | |||
2515 | /* for now, uuid == domain */ | 2484 | /* for now, uuid == domain */ |
2516 | dlm = dlm_register_domain(osb->uuid_str, dlm_key, | 2485 | status = ocfs2_cluster_connect(osb->uuid_str, |
2517 | &osb->osb_locking_proto); | 2486 | strlen(osb->uuid_str), |
2518 | if (IS_ERR(dlm)) { | 2487 | ocfs2_do_node_down, osb, |
2519 | status = PTR_ERR(dlm); | 2488 | &conn); |
2489 | if (status) { | ||
2520 | mlog_errno(status); | 2490 | mlog_errno(status); |
2521 | goto bail; | 2491 | goto bail; |
2522 | } | 2492 | } |
2523 | 2493 | ||
2524 | dlm_register_eviction_cb(dlm, &osb->osb_eviction_cb); | ||
2525 | |||
2526 | local: | 2494 | local: |
2527 | ocfs2_super_lock_res_init(&osb->osb_super_lockres, osb); | 2495 | ocfs2_super_lock_res_init(&osb->osb_super_lockres, osb); |
2528 | ocfs2_rename_lock_res_init(&osb->osb_rename_lockres, osb); | 2496 | ocfs2_rename_lock_res_init(&osb->osb_rename_lockres, osb); |
2529 | 2497 | ||
2530 | osb->dlm = dlm; | 2498 | osb->cconn = conn; |
2531 | 2499 | ||
2532 | status = 0; | 2500 | status = 0; |
2533 | bail: | 2501 | bail: |
@@ -2545,10 +2513,14 @@ void ocfs2_dlm_shutdown(struct ocfs2_super *osb) | |||
2545 | { | 2513 | { |
2546 | mlog_entry_void(); | 2514 | mlog_entry_void(); |
2547 | 2515 | ||
2548 | dlm_unregister_eviction_cb(&osb->osb_eviction_cb); | ||
2549 | |||
2550 | ocfs2_drop_osb_locks(osb); | 2516 | ocfs2_drop_osb_locks(osb); |
2551 | 2517 | ||
2518 | /* | ||
2519 | * Now that we have dropped all locks and ocfs2_dismount_volume() | ||
2520 | * has disabled recovery, the DLM won't be talking to us. It's | ||
2521 | * safe to tear things down before disconnecting the cluster. | ||
2522 | */ | ||
2523 | |||
2552 | if (osb->dc_task) { | 2524 | if (osb->dc_task) { |
2553 | kthread_stop(osb->dc_task); | 2525 | kthread_stop(osb->dc_task); |
2554 | osb->dc_task = NULL; | 2526 | osb->dc_task = NULL; |
@@ -2557,8 +2529,8 @@ void ocfs2_dlm_shutdown(struct ocfs2_super *osb) | |||
2557 | ocfs2_lock_res_free(&osb->osb_super_lockres); | 2529 | ocfs2_lock_res_free(&osb->osb_super_lockres); |
2558 | ocfs2_lock_res_free(&osb->osb_rename_lockres); | 2530 | ocfs2_lock_res_free(&osb->osb_rename_lockres); |
2559 | 2531 | ||
2560 | dlm_unregister_domain(osb->dlm); | 2532 | ocfs2_cluster_disconnect(osb->cconn); |
2561 | osb->dlm = NULL; | 2533 | osb->cconn = NULL; |
2562 | 2534 | ||
2563 | ocfs2_dlm_shutdown_debug(osb); | 2535 | ocfs2_dlm_shutdown_debug(osb); |
2564 | 2536 | ||
@@ -2689,7 +2661,7 @@ static int ocfs2_drop_lock(struct ocfs2_super *osb, | |||
2689 | 2661 | ||
2690 | mlog(0, "lock %s\n", lockres->l_name); | 2662 | mlog(0, "lock %s\n", lockres->l_name); |
2691 | 2663 | ||
2692 | ret = ocfs2_dlm_unlock(osb->dlm, &lockres->l_lksb, lkm_flags, | 2664 | ret = ocfs2_dlm_unlock(osb->cconn, &lockres->l_lksb, lkm_flags, |
2693 | lockres); | 2665 | lockres); |
2694 | if (ret) { | 2666 | if (ret) { |
2695 | ocfs2_log_dlm_error("ocfs2_dlm_unlock", ret, lockres); | 2667 | ocfs2_log_dlm_error("ocfs2_dlm_unlock", ret, lockres); |
@@ -2823,7 +2795,7 @@ static int ocfs2_downconvert_lock(struct ocfs2_super *osb, | |||
2823 | if (lvb) | 2795 | if (lvb) |
2824 | dlm_flags |= DLM_LKF_VALBLK; | 2796 | dlm_flags |= DLM_LKF_VALBLK; |
2825 | 2797 | ||
2826 | ret = ocfs2_dlm_lock(osb->dlm, | 2798 | ret = ocfs2_dlm_lock(osb->cconn, |
2827 | new_level, | 2799 | new_level, |
2828 | &lockres->l_lksb, | 2800 | &lockres->l_lksb, |
2829 | dlm_flags, | 2801 | dlm_flags, |
@@ -2882,7 +2854,7 @@ static int ocfs2_cancel_convert(struct ocfs2_super *osb, | |||
2882 | mlog_entry_void(); | 2854 | mlog_entry_void(); |
2883 | mlog(0, "lock %s\n", lockres->l_name); | 2855 | mlog(0, "lock %s\n", lockres->l_name); |
2884 | 2856 | ||
2885 | ret = ocfs2_dlm_unlock(osb->dlm, &lockres->l_lksb, | 2857 | ret = ocfs2_dlm_unlock(osb->cconn, &lockres->l_lksb, |
2886 | DLM_LKF_CANCEL, lockres); | 2858 | DLM_LKF_CANCEL, lockres); |
2887 | if (ret) { | 2859 | if (ret) { |
2888 | ocfs2_log_dlm_error("ocfs2_dlm_unlock", ret, lockres); | 2860 | ocfs2_log_dlm_error("ocfs2_dlm_unlock", ret, lockres); |
@@ -3193,7 +3165,34 @@ static int ocfs2_dentry_convert_worker(struct ocfs2_lock_res *lockres, | |||
3193 | return UNBLOCK_CONTINUE_POST; | 3165 | return UNBLOCK_CONTINUE_POST; |
3194 | } | 3166 | } |
3195 | 3167 | ||
3168 | /* | ||
3169 | * This is the filesystem locking protocol. It provides the lock handling | ||
3170 | * hooks for the underlying DLM. It has a maximum version number. | ||
3171 | * The version number allows interoperability with systems running at | ||
3172 | * the same major number and an equal or smaller minor number. | ||
3173 | * | ||
3174 | * Whenever the filesystem does new things with locks (adds or removes a | ||
3175 | * lock, orders them differently, does different things underneath a lock), | ||
3176 | * the version must be changed. The protocol is negotiated when joining | ||
3177 | * the dlm domain. A node may join the domain if its major version is | ||
3178 | * identical to all other nodes and its minor version is greater than | ||
3179 | * or equal to all other nodes. When its minor version is greater than | ||
3180 | * the other nodes, it will run at the minor version specified by the | ||
3181 | * other nodes. | ||
3182 | * | ||
3183 | * If a locking change is made that will not be compatible with older | ||
3184 | * versions, the major number must be increased and the minor version set | ||
3185 | * to zero. If a change merely adds a behavior that can be disabled when | ||
3186 | * speaking to older versions, the minor version must be increased. If a | ||
3187 | * change adds a fully backwards compatible change (eg, LVB changes that | ||
3188 | * are just ignored by older versions), the version does not need to be | ||
3189 | * updated. | ||
3190 | */ | ||
3196 | static struct ocfs2_locking_protocol lproto = { | 3191 | static struct ocfs2_locking_protocol lproto = { |
3192 | .lp_max_version = { | ||
3193 | .pv_major = OCFS2_LOCKING_PROTOCOL_MAJOR, | ||
3194 | .pv_minor = OCFS2_LOCKING_PROTOCOL_MINOR, | ||
3195 | }, | ||
3197 | .lp_lock_ast = ocfs2_locking_ast, | 3196 | .lp_lock_ast = ocfs2_locking_ast, |
3198 | .lp_blocking_ast = ocfs2_blocking_ast, | 3197 | .lp_blocking_ast = ocfs2_blocking_ast, |
3199 | .lp_unlock_ast = ocfs2_unlock_ast, | 3198 | .lp_unlock_ast = ocfs2_unlock_ast, |
diff --git a/fs/ocfs2/dlmglue.h b/fs/ocfs2/dlmglue.h index 32380439401f..2d0a8a03c431 100644 --- a/fs/ocfs2/dlmglue.h +++ b/fs/ocfs2/dlmglue.h | |||
@@ -117,5 +117,4 @@ void ocfs2_put_dlm_debug(struct ocfs2_dlm_debug *dlm_debug); | |||
117 | void dlmglue_init_stack(void); | 117 | void dlmglue_init_stack(void); |
118 | void dlmglue_exit_stack(void); | 118 | void dlmglue_exit_stack(void); |
119 | 119 | ||
120 | extern const struct dlm_protocol_version ocfs2_locking_protocol; | ||
121 | #endif /* DLMGLUE_H */ | 120 | #endif /* DLMGLUE_H */ |
diff --git a/fs/ocfs2/heartbeat.c b/fs/ocfs2/heartbeat.c index 80de2397c161..dcac1a487288 100644 --- a/fs/ocfs2/heartbeat.c +++ b/fs/ocfs2/heartbeat.c | |||
@@ -30,8 +30,6 @@ | |||
30 | #include <linux/highmem.h> | 30 | #include <linux/highmem.h> |
31 | #include <linux/kmod.h> | 31 | #include <linux/kmod.h> |
32 | 32 | ||
33 | #include <dlm/dlmapi.h> | ||
34 | |||
35 | #define MLOG_MASK_PREFIX ML_SUPER | 33 | #define MLOG_MASK_PREFIX ML_SUPER |
36 | #include <cluster/masklog.h> | 34 | #include <cluster/masklog.h> |
37 | 35 | ||
@@ -64,19 +62,20 @@ void ocfs2_init_node_maps(struct ocfs2_super *osb) | |||
64 | ocfs2_node_map_init(&osb->osb_recovering_orphan_dirs); | 62 | ocfs2_node_map_init(&osb->osb_recovering_orphan_dirs); |
65 | } | 63 | } |
66 | 64 | ||
67 | static void ocfs2_do_node_down(int node_num, | 65 | void ocfs2_do_node_down(int node_num, void *data) |
68 | struct ocfs2_super *osb) | ||
69 | { | 66 | { |
67 | struct ocfs2_super *osb = data; | ||
68 | |||
70 | BUG_ON(osb->node_num == node_num); | 69 | BUG_ON(osb->node_num == node_num); |
71 | 70 | ||
72 | mlog(0, "ocfs2: node down event for %d\n", node_num); | 71 | mlog(0, "ocfs2: node down event for %d\n", node_num); |
73 | 72 | ||
74 | if (!osb->dlm) { | 73 | if (!osb->cconn) { |
75 | /* | 74 | /* |
76 | * No DLM means we're not even ready to participate yet. | 75 | * No cluster connection means we're not even ready to |
77 | * We check the slots after the DLM comes up, so we will | 76 | * participate yet. We check the slots after the cluster |
78 | * notice the node death then. We can safely ignore it | 77 | * comes up, so we will notice the node death then. We |
79 | * here. | 78 | * can safely ignore it here. |
80 | */ | 79 | */ |
81 | return; | 80 | return; |
82 | } | 81 | } |
@@ -84,29 +83,6 @@ static void ocfs2_do_node_down(int node_num, | |||
84 | ocfs2_recovery_thread(osb, node_num); | 83 | ocfs2_recovery_thread(osb, node_num); |
85 | } | 84 | } |
86 | 85 | ||
87 | /* Called from the dlm when it's about to evict a node. We may also | ||
88 | * get a heartbeat callback later. */ | ||
89 | static void ocfs2_dlm_eviction_cb(int node_num, | ||
90 | void *data) | ||
91 | { | ||
92 | struct ocfs2_super *osb = (struct ocfs2_super *) data; | ||
93 | struct super_block *sb = osb->sb; | ||
94 | |||
95 | mlog(ML_NOTICE, "device (%u,%u): dlm has evicted node %d\n", | ||
96 | MAJOR(sb->s_dev), MINOR(sb->s_dev), node_num); | ||
97 | |||
98 | ocfs2_do_node_down(node_num, osb); | ||
99 | } | ||
100 | |||
101 | void ocfs2_setup_hb_callbacks(struct ocfs2_super *osb) | ||
102 | { | ||
103 | /* Not exactly a heartbeat callback, but leads to essentially | ||
104 | * the same path so we set it up here. */ | ||
105 | dlm_setup_eviction_cb(&osb->osb_eviction_cb, | ||
106 | ocfs2_dlm_eviction_cb, | ||
107 | osb); | ||
108 | } | ||
109 | |||
110 | void ocfs2_stop_heartbeat(struct ocfs2_super *osb) | 86 | void ocfs2_stop_heartbeat(struct ocfs2_super *osb) |
111 | { | 87 | { |
112 | int ret; | 88 | int ret; |
diff --git a/fs/ocfs2/heartbeat.h b/fs/ocfs2/heartbeat.h index 98d8ffc995b1..38e2450bf14c 100644 --- a/fs/ocfs2/heartbeat.h +++ b/fs/ocfs2/heartbeat.h | |||
@@ -28,7 +28,7 @@ | |||
28 | 28 | ||
29 | void ocfs2_init_node_maps(struct ocfs2_super *osb); | 29 | void ocfs2_init_node_maps(struct ocfs2_super *osb); |
30 | 30 | ||
31 | void ocfs2_setup_hb_callbacks(struct ocfs2_super *osb); | 31 | void ocfs2_do_node_down(int node_num, void *data); |
32 | void ocfs2_stop_heartbeat(struct ocfs2_super *osb); | 32 | void ocfs2_stop_heartbeat(struct ocfs2_super *osb); |
33 | 33 | ||
34 | /* node map functions - used to keep track of mounted and in-recovery | 34 | /* node map functions - used to keep track of mounted and in-recovery |
diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h index 6d7c6d2d0c23..664e4fe3eab5 100644 --- a/fs/ocfs2/ocfs2.h +++ b/fs/ocfs2/ocfs2.h | |||
@@ -248,12 +248,10 @@ struct ocfs2_super | |||
248 | struct ocfs2_alloc_stats alloc_stats; | 248 | struct ocfs2_alloc_stats alloc_stats; |
249 | char dev_str[20]; /* "major,minor" of the device */ | 249 | char dev_str[20]; /* "major,minor" of the device */ |
250 | 250 | ||
251 | struct dlm_ctxt *dlm; | 251 | struct ocfs2_cluster_connection *cconn; |
252 | struct ocfs2_lock_res osb_super_lockres; | 252 | struct ocfs2_lock_res osb_super_lockres; |
253 | struct ocfs2_lock_res osb_rename_lockres; | 253 | struct ocfs2_lock_res osb_rename_lockres; |
254 | struct dlm_eviction_cb osb_eviction_cb; | ||
255 | struct ocfs2_dlm_debug *osb_dlm_debug; | 254 | struct ocfs2_dlm_debug *osb_dlm_debug; |
256 | struct dlm_protocol_version osb_locking_proto; | ||
257 | 255 | ||
258 | struct dentry *osb_debug_root; | 256 | struct dentry *osb_debug_root; |
259 | 257 | ||
diff --git a/fs/ocfs2/stackglue.c b/fs/ocfs2/stackglue.c index eb88854cb976..f6f309a08344 100644 --- a/fs/ocfs2/stackglue.c +++ b/fs/ocfs2/stackglue.c | |||
@@ -18,11 +18,21 @@ | |||
18 | * General Public License for more details. | 18 | * General Public License for more details. |
19 | */ | 19 | */ |
20 | 20 | ||
21 | #include <linux/slab.h> | ||
22 | #include <linux/crc32.h> | ||
23 | |||
24 | /* Needed for AOP_TRUNCATED_PAGE in mlog_errno() */ | ||
25 | #include <linux/fs.h> | ||
26 | |||
21 | #include "cluster/masklog.h" | 27 | #include "cluster/masklog.h" |
22 | #include "stackglue.h" | 28 | #include "stackglue.h" |
23 | 29 | ||
24 | static struct ocfs2_locking_protocol *lproto; | 30 | static struct ocfs2_locking_protocol *lproto; |
25 | 31 | ||
32 | struct o2dlm_private { | ||
33 | struct dlm_eviction_cb op_eviction_cb; | ||
34 | }; | ||
35 | |||
26 | /* These should be identical */ | 36 | /* These should be identical */ |
27 | #if (DLM_LOCK_IV != LKM_IVMODE) | 37 | #if (DLM_LOCK_IV != LKM_IVMODE) |
28 | # error Lock modes do not match | 38 | # error Lock modes do not match |
@@ -197,7 +207,7 @@ static void o2dlm_unlock_ast_wrapper(void *astarg, enum dlm_status status) | |||
197 | lproto->lp_unlock_ast(astarg, error); | 207 | lproto->lp_unlock_ast(astarg, error); |
198 | } | 208 | } |
199 | 209 | ||
200 | int ocfs2_dlm_lock(struct dlm_ctxt *dlm, | 210 | int ocfs2_dlm_lock(struct ocfs2_cluster_connection *conn, |
201 | int mode, | 211 | int mode, |
202 | union ocfs2_dlm_lksb *lksb, | 212 | union ocfs2_dlm_lksb *lksb, |
203 | u32 flags, | 213 | u32 flags, |
@@ -212,15 +222,15 @@ int ocfs2_dlm_lock(struct dlm_ctxt *dlm, | |||
212 | 222 | ||
213 | BUG_ON(lproto == NULL); | 223 | BUG_ON(lproto == NULL); |
214 | 224 | ||
215 | status = dlmlock(dlm, o2dlm_mode, &lksb->lksb_o2dlm, o2dlm_flags, | 225 | status = dlmlock(conn->cc_lockspace, o2dlm_mode, &lksb->lksb_o2dlm, |
216 | name, namelen, | 226 | o2dlm_flags, name, namelen, |
217 | o2dlm_lock_ast_wrapper, astarg, | 227 | o2dlm_lock_ast_wrapper, astarg, |
218 | o2dlm_blocking_ast_wrapper); | 228 | o2dlm_blocking_ast_wrapper); |
219 | ret = dlm_status_to_errno(status); | 229 | ret = dlm_status_to_errno(status); |
220 | return ret; | 230 | return ret; |
221 | } | 231 | } |
222 | 232 | ||
223 | int ocfs2_dlm_unlock(struct dlm_ctxt *dlm, | 233 | int ocfs2_dlm_unlock(struct ocfs2_cluster_connection *conn, |
224 | union ocfs2_dlm_lksb *lksb, | 234 | union ocfs2_dlm_lksb *lksb, |
225 | u32 flags, | 235 | u32 flags, |
226 | void *astarg) | 236 | void *astarg) |
@@ -231,8 +241,8 @@ int ocfs2_dlm_unlock(struct dlm_ctxt *dlm, | |||
231 | 241 | ||
232 | BUG_ON(lproto == NULL); | 242 | BUG_ON(lproto == NULL); |
233 | 243 | ||
234 | status = dlmunlock(dlm, &lksb->lksb_o2dlm, o2dlm_flags, | 244 | status = dlmunlock(conn->cc_lockspace, &lksb->lksb_o2dlm, |
235 | o2dlm_unlock_ast_wrapper, astarg); | 245 | o2dlm_flags, o2dlm_unlock_ast_wrapper, astarg); |
236 | ret = dlm_status_to_errno(status); | 246 | ret = dlm_status_to_errno(status); |
237 | return ret; | 247 | return ret; |
238 | } | 248 | } |
@@ -252,6 +262,115 @@ void *ocfs2_dlm_lvb(union ocfs2_dlm_lksb *lksb) | |||
252 | return (void *)(lksb->lksb_o2dlm.lvb); | 262 | return (void *)(lksb->lksb_o2dlm.lvb); |
253 | } | 263 | } |
254 | 264 | ||
265 | /* | ||
266 | * Called from the dlm when it's about to evict a node. This is how the | ||
267 | * classic stack signals node death. | ||
268 | */ | ||
269 | static void o2dlm_eviction_cb(int node_num, void *data) | ||
270 | { | ||
271 | struct ocfs2_cluster_connection *conn = data; | ||
272 | |||
273 | mlog(ML_NOTICE, "o2dlm has evicted node %d from group %.*s\n", | ||
274 | node_num, conn->cc_namelen, conn->cc_name); | ||
275 | |||
276 | conn->cc_recovery_handler(node_num, conn->cc_recovery_data); | ||
277 | } | ||
278 | |||
279 | int ocfs2_cluster_connect(const char *group, | ||
280 | int grouplen, | ||
281 | void (*recovery_handler)(int node_num, | ||
282 | void *recovery_data), | ||
283 | void *recovery_data, | ||
284 | struct ocfs2_cluster_connection **conn) | ||
285 | { | ||
286 | int rc = 0; | ||
287 | struct ocfs2_cluster_connection *new_conn; | ||
288 | u32 dlm_key; | ||
289 | struct dlm_ctxt *dlm; | ||
290 | struct o2dlm_private *priv; | ||
291 | struct dlm_protocol_version dlm_version; | ||
292 | |||
293 | BUG_ON(group == NULL); | ||
294 | BUG_ON(conn == NULL); | ||
295 | BUG_ON(recovery_handler == NULL); | ||
296 | |||
297 | if (grouplen > GROUP_NAME_MAX) { | ||
298 | rc = -EINVAL; | ||
299 | goto out; | ||
300 | } | ||
301 | |||
302 | new_conn = kzalloc(sizeof(struct ocfs2_cluster_connection), | ||
303 | GFP_KERNEL); | ||
304 | if (!new_conn) { | ||
305 | rc = -ENOMEM; | ||
306 | goto out; | ||
307 | } | ||
308 | |||
309 | memcpy(new_conn->cc_name, group, grouplen); | ||
310 | new_conn->cc_namelen = grouplen; | ||
311 | new_conn->cc_recovery_handler = recovery_handler; | ||
312 | new_conn->cc_recovery_data = recovery_data; | ||
313 | |||
314 | /* Start the new connection at our maximum compatibility level */ | ||
315 | new_conn->cc_version = lproto->lp_max_version; | ||
316 | |||
317 | priv = kzalloc(sizeof(struct o2dlm_private), GFP_KERNEL); | ||
318 | if (!priv) { | ||
319 | rc = -ENOMEM; | ||
320 | goto out_free; | ||
321 | } | ||
322 | |||
323 | /* This just fills the structure in. It is safe to use new_conn. */ | ||
324 | dlm_setup_eviction_cb(&priv->op_eviction_cb, o2dlm_eviction_cb, | ||
325 | new_conn); | ||
326 | |||
327 | new_conn->cc_private = priv; | ||
328 | |||
329 | /* used by the dlm code to make message headers unique, each | ||
330 | * node in this domain must agree on this. */ | ||
331 | dlm_key = crc32_le(0, group, grouplen); | ||
332 | dlm_version.pv_major = new_conn->cc_version.pv_major; | ||
333 | dlm_version.pv_minor = new_conn->cc_version.pv_minor; | ||
334 | |||
335 | dlm = dlm_register_domain(group, dlm_key, &dlm_version); | ||
336 | if (IS_ERR(dlm)) { | ||
337 | rc = PTR_ERR(dlm); | ||
338 | mlog_errno(rc); | ||
339 | goto out_free; | ||
340 | } | ||
341 | |||
342 | new_conn->cc_version.pv_major = dlm_version.pv_major; | ||
343 | new_conn->cc_version.pv_minor = dlm_version.pv_minor; | ||
344 | new_conn->cc_lockspace = dlm; | ||
345 | |||
346 | dlm_register_eviction_cb(dlm, &priv->op_eviction_cb); | ||
347 | |||
348 | *conn = new_conn; | ||
349 | |||
350 | out_free: | ||
351 | if (rc) { | ||
352 | kfree(new_conn->cc_private); | ||
353 | kfree(new_conn); | ||
354 | } | ||
355 | |||
356 | out: | ||
357 | return rc; | ||
358 | } | ||
359 | |||
360 | int ocfs2_cluster_disconnect(struct ocfs2_cluster_connection *conn) | ||
361 | { | ||
362 | struct dlm_ctxt *dlm = conn->cc_lockspace; | ||
363 | struct o2dlm_private *priv = conn->cc_private; | ||
364 | |||
365 | dlm_unregister_eviction_cb(&priv->op_eviction_cb); | ||
366 | dlm_unregister_domain(dlm); | ||
367 | |||
368 | kfree(priv); | ||
369 | kfree(conn); | ||
370 | |||
371 | return 0; | ||
372 | } | ||
373 | |||
255 | void o2cb_get_stack(struct ocfs2_locking_protocol *proto) | 374 | void o2cb_get_stack(struct ocfs2_locking_protocol *proto) |
256 | { | 375 | { |
257 | BUG_ON(proto == NULL); | 376 | BUG_ON(proto == NULL); |
diff --git a/fs/ocfs2/stackglue.h b/fs/ocfs2/stackglue.h index 3c91e241892b..3900b5c3933c 100644 --- a/fs/ocfs2/stackglue.h +++ b/fs/ocfs2/stackglue.h | |||
@@ -32,9 +32,22 @@ | |||
32 | */ | 32 | */ |
33 | #define DLM_LKF_LOCAL 0x00100000 | 33 | #define DLM_LKF_LOCAL 0x00100000 |
34 | 34 | ||
35 | /* | ||
36 | * This shadows DLM_LOCKSPACE_LEN in fs/dlm/dlm_internal.h. That probably | ||
37 | * wants to be in a public header. | ||
38 | */ | ||
39 | #define GROUP_NAME_MAX 64 | ||
40 | |||
41 | |||
35 | #include "dlm/dlmapi.h" | 42 | #include "dlm/dlmapi.h" |
36 | 43 | ||
44 | struct ocfs2_protocol_version { | ||
45 | u8 pv_major; | ||
46 | u8 pv_minor; | ||
47 | }; | ||
48 | |||
37 | struct ocfs2_locking_protocol { | 49 | struct ocfs2_locking_protocol { |
50 | struct ocfs2_protocol_version lp_max_version; | ||
38 | void (*lp_lock_ast)(void *astarg); | 51 | void (*lp_lock_ast)(void *astarg); |
39 | void (*lp_blocking_ast)(void *astarg, int level); | 52 | void (*lp_blocking_ast)(void *astarg, int level); |
40 | void (*lp_unlock_ast)(void *astarg, int error); | 53 | void (*lp_unlock_ast)(void *astarg, int error); |
@@ -44,14 +57,32 @@ union ocfs2_dlm_lksb { | |||
44 | struct dlm_lockstatus lksb_o2dlm; | 57 | struct dlm_lockstatus lksb_o2dlm; |
45 | }; | 58 | }; |
46 | 59 | ||
47 | int ocfs2_dlm_lock(struct dlm_ctxt *dlm, | 60 | struct ocfs2_cluster_connection { |
61 | char cc_name[GROUP_NAME_MAX]; | ||
62 | int cc_namelen; | ||
63 | struct ocfs2_protocol_version cc_version; | ||
64 | void (*cc_recovery_handler)(int node_num, void *recovery_data); | ||
65 | void *cc_recovery_data; | ||
66 | void *cc_lockspace; | ||
67 | void *cc_private; | ||
68 | }; | ||
69 | |||
70 | int ocfs2_cluster_connect(const char *group, | ||
71 | int grouplen, | ||
72 | void (*recovery_handler)(int node_num, | ||
73 | void *recovery_data), | ||
74 | void *recovery_data, | ||
75 | struct ocfs2_cluster_connection **conn); | ||
76 | int ocfs2_cluster_disconnect(struct ocfs2_cluster_connection *conn); | ||
77 | |||
78 | int ocfs2_dlm_lock(struct ocfs2_cluster_connection *conn, | ||
48 | int mode, | 79 | int mode, |
49 | union ocfs2_dlm_lksb *lksb, | 80 | union ocfs2_dlm_lksb *lksb, |
50 | u32 flags, | 81 | u32 flags, |
51 | void *name, | 82 | void *name, |
52 | unsigned int namelen, | 83 | unsigned int namelen, |
53 | void *astarg); | 84 | void *astarg); |
54 | int ocfs2_dlm_unlock(struct dlm_ctxt *dlm, | 85 | int ocfs2_dlm_unlock(struct ocfs2_cluster_connection *conn, |
55 | union ocfs2_dlm_lksb *lksb, | 86 | union ocfs2_dlm_lksb *lksb, |
56 | u32 flags, | 87 | u32 flags, |
57 | void *astarg); | 88 | void *astarg); |
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index c8675464e299..0ee49757467d 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c | |||
@@ -1251,9 +1251,9 @@ static void ocfs2_dismount_volume(struct super_block *sb, int mnt_err) | |||
1251 | 1251 | ||
1252 | ocfs2_sync_blockdev(sb); | 1252 | ocfs2_sync_blockdev(sb); |
1253 | 1253 | ||
1254 | /* No dlm means we've failed during mount, so skip all the | 1254 | /* No cluster connection means we've failed during mount, so skip |
1255 | * steps which depended on that to complete. */ | 1255 | * all the steps which depended on that to complete. */ |
1256 | if (osb->dlm) { | 1256 | if (osb->cconn) { |
1257 | tmp = ocfs2_super_lock(osb, 1); | 1257 | tmp = ocfs2_super_lock(osb, 1); |
1258 | if (tmp < 0) { | 1258 | if (tmp < 0) { |
1259 | mlog_errno(tmp); | 1259 | mlog_errno(tmp); |
@@ -1264,12 +1264,12 @@ static void ocfs2_dismount_volume(struct super_block *sb, int mnt_err) | |||
1264 | if (osb->slot_num != OCFS2_INVALID_SLOT) | 1264 | if (osb->slot_num != OCFS2_INVALID_SLOT) |
1265 | ocfs2_put_slot(osb); | 1265 | ocfs2_put_slot(osb); |
1266 | 1266 | ||
1267 | if (osb->dlm) | 1267 | if (osb->cconn) |
1268 | ocfs2_super_unlock(osb, 1); | 1268 | ocfs2_super_unlock(osb, 1); |
1269 | 1269 | ||
1270 | ocfs2_release_system_inodes(osb); | 1270 | ocfs2_release_system_inodes(osb); |
1271 | 1271 | ||
1272 | if (osb->dlm) | 1272 | if (osb->cconn) |
1273 | ocfs2_dlm_shutdown(osb); | 1273 | ocfs2_dlm_shutdown(osb); |
1274 | 1274 | ||
1275 | debugfs_remove(osb->osb_debug_root); | 1275 | debugfs_remove(osb->osb_debug_root); |
@@ -1341,7 +1341,6 @@ static int ocfs2_initialize_super(struct super_block *sb, | |||
1341 | sb->s_fs_info = osb; | 1341 | sb->s_fs_info = osb; |
1342 | sb->s_op = &ocfs2_sops; | 1342 | sb->s_op = &ocfs2_sops; |
1343 | sb->s_export_op = &ocfs2_export_ops; | 1343 | sb->s_export_op = &ocfs2_export_ops; |
1344 | osb->osb_locking_proto = ocfs2_locking_protocol; | ||
1345 | sb->s_time_gran = 1; | 1344 | sb->s_time_gran = 1; |
1346 | sb->s_flags |= MS_NOATIME; | 1345 | sb->s_flags |= MS_NOATIME; |
1347 | /* this is needed to support O_LARGEFILE */ | 1346 | /* this is needed to support O_LARGEFILE */ |
@@ -1391,8 +1390,6 @@ static int ocfs2_initialize_super(struct super_block *sb, | |||
1391 | osb->local_alloc_state = OCFS2_LA_UNUSED; | 1390 | osb->local_alloc_state = OCFS2_LA_UNUSED; |
1392 | osb->local_alloc_bh = NULL; | 1391 | osb->local_alloc_bh = NULL; |
1393 | 1392 | ||
1394 | ocfs2_setup_hb_callbacks(osb); | ||
1395 | |||
1396 | init_waitqueue_head(&osb->osb_mount_event); | 1393 | init_waitqueue_head(&osb->osb_mount_event); |
1397 | 1394 | ||
1398 | osb->vol_label = kmalloc(OCFS2_MAX_VOL_LABEL_LEN, GFP_KERNEL); | 1395 | osb->vol_label = kmalloc(OCFS2_MAX_VOL_LABEL_LEN, GFP_KERNEL); |