diff options
author | Joel Becker <joel.becker@oracle.com> | 2010-01-29 20:19:06 -0500 |
---|---|---|
committer | Joel Becker <joel.becker@oracle.com> | 2010-02-26 18:41:17 -0500 |
commit | 553b5eb91abd5f8e679d23ae547b92c589726814 (patch) | |
tree | 99b3e550a11b0d62d45bbc78d73d448acadd138a /fs/ocfs2 | |
parent | e603cfb074e150736814ef093a411df32c02ba9f (diff) |
ocfs2: Pass the locking protocol into ocfs2_cluster_connect().
Inside the stackglue, the locking protocol structure is hanging off of
the ocfs2_cluster_connection. This takes it one further; the locking
protocol is passed into ocfs2_cluster_connect(). Now different cluster
connections can have different locking protocols with distinct asts.
Note that all locking protocols have to keep their maximum protocol
version in lock-step.
With the protocol structure set in ocfs2_cluster_connect(), there is no
need for the stackglue to have a static pointer to a specific protocol
structure. We can change initialization to only pass in the maximum
protocol version.
Signed-off-by: Joel Becker <joel.becker@oracle.com>
Diffstat (limited to 'fs/ocfs2')
-rw-r--r-- | fs/ocfs2/dlmglue.c | 168 | ||||
-rw-r--r-- | fs/ocfs2/stackglue.c | 43 | ||||
-rw-r--r-- | fs/ocfs2/stackglue.h | 3 |
3 files changed, 110 insertions, 104 deletions
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c index 2bb868b7b44f..d009d7744d63 100644 --- a/fs/ocfs2/dlmglue.c +++ b/fs/ocfs2/dlmglue.c | |||
@@ -1045,7 +1045,6 @@ static unsigned int lockres_set_pending(struct ocfs2_lock_res *lockres) | |||
1045 | return lockres->l_pending_gen; | 1045 | return lockres->l_pending_gen; |
1046 | } | 1046 | } |
1047 | 1047 | ||
1048 | |||
1049 | static void ocfs2_blocking_ast(struct ocfs2_dlm_lksb *lksb, int level) | 1048 | static void ocfs2_blocking_ast(struct ocfs2_dlm_lksb *lksb, int level) |
1050 | { | 1049 | { |
1051 | struct ocfs2_lock_res *lockres = ocfs2_lksb_to_lock_res(lksb); | 1050 | struct ocfs2_lock_res *lockres = ocfs2_lksb_to_lock_res(lksb); |
@@ -1139,6 +1138,88 @@ out: | |||
1139 | spin_unlock_irqrestore(&lockres->l_lock, flags); | 1138 | spin_unlock_irqrestore(&lockres->l_lock, flags); |
1140 | } | 1139 | } |
1141 | 1140 | ||
1141 | static void ocfs2_unlock_ast(struct ocfs2_dlm_lksb *lksb, int error) | ||
1142 | { | ||
1143 | struct ocfs2_lock_res *lockres = ocfs2_lksb_to_lock_res(lksb); | ||
1144 | unsigned long flags; | ||
1145 | |||
1146 | mlog_entry_void(); | ||
1147 | |||
1148 | mlog(0, "UNLOCK AST called on lock %s, action = %d\n", lockres->l_name, | ||
1149 | lockres->l_unlock_action); | ||
1150 | |||
1151 | spin_lock_irqsave(&lockres->l_lock, flags); | ||
1152 | if (error) { | ||
1153 | mlog(ML_ERROR, "Dlm passes error %d for lock %s, " | ||
1154 | "unlock_action %d\n", error, lockres->l_name, | ||
1155 | lockres->l_unlock_action); | ||
1156 | spin_unlock_irqrestore(&lockres->l_lock, flags); | ||
1157 | mlog_exit_void(); | ||
1158 | return; | ||
1159 | } | ||
1160 | |||
1161 | switch(lockres->l_unlock_action) { | ||
1162 | case OCFS2_UNLOCK_CANCEL_CONVERT: | ||
1163 | mlog(0, "Cancel convert success for %s\n", lockres->l_name); | ||
1164 | lockres->l_action = OCFS2_AST_INVALID; | ||
1165 | /* Downconvert thread may have requeued this lock, we | ||
1166 | * need to wake it. */ | ||
1167 | if (lockres->l_flags & OCFS2_LOCK_BLOCKED) | ||
1168 | ocfs2_wake_downconvert_thread(ocfs2_get_lockres_osb(lockres)); | ||
1169 | break; | ||
1170 | case OCFS2_UNLOCK_DROP_LOCK: | ||
1171 | lockres->l_level = DLM_LOCK_IV; | ||
1172 | break; | ||
1173 | default: | ||
1174 | BUG(); | ||
1175 | } | ||
1176 | |||
1177 | lockres_clear_flags(lockres, OCFS2_LOCK_BUSY); | ||
1178 | lockres->l_unlock_action = OCFS2_UNLOCK_INVALID; | ||
1179 | wake_up(&lockres->l_event); | ||
1180 | spin_unlock_irqrestore(&lockres->l_lock, flags); | ||
1181 | |||
1182 | mlog_exit_void(); | ||
1183 | } | ||
1184 | |||
1185 | /* | ||
1186 | * This is the filesystem locking protocol. It provides the lock handling | ||
1187 | * hooks for the underlying DLM. It has a maximum version number. | ||
1188 | * The version number allows interoperability with systems running at | ||
1189 | * the same major number and an equal or smaller minor number. | ||
1190 | * | ||
1191 | * Whenever the filesystem does new things with locks (adds or removes a | ||
1192 | * lock, orders them differently, does different things underneath a lock), | ||
1193 | * the version must be changed. The protocol is negotiated when joining | ||
1194 | * the dlm domain. A node may join the domain if its major version is | ||
1195 | * identical to all other nodes and its minor version is greater than | ||
1196 | * or equal to all other nodes. When its minor version is greater than | ||
1197 | * the other nodes, it will run at the minor version specified by the | ||
1198 | * other nodes. | ||
1199 | * | ||
1200 | * If a locking change is made that will not be compatible with older | ||
1201 | * versions, the major number must be increased and the minor version set | ||
1202 | * to zero. If a change merely adds a behavior that can be disabled when | ||
1203 | * speaking to older versions, the minor version must be increased. If a | ||
1204 | * change adds a fully backwards compatible change (eg, LVB changes that | ||
1205 | * are just ignored by older versions), the version does not need to be | ||
1206 | * updated. | ||
1207 | */ | ||
1208 | static struct ocfs2_locking_protocol lproto = { | ||
1209 | .lp_max_version = { | ||
1210 | .pv_major = OCFS2_LOCKING_PROTOCOL_MAJOR, | ||
1211 | .pv_minor = OCFS2_LOCKING_PROTOCOL_MINOR, | ||
1212 | }, | ||
1213 | .lp_lock_ast = ocfs2_locking_ast, | ||
1214 | .lp_blocking_ast = ocfs2_blocking_ast, | ||
1215 | .lp_unlock_ast = ocfs2_unlock_ast, | ||
1216 | }; | ||
1217 | |||
1218 | void ocfs2_set_locking_protocol(void) | ||
1219 | { | ||
1220 | ocfs2_stack_glue_set_max_proto_version(&lproto.lp_max_version); | ||
1221 | } | ||
1222 | |||
1142 | static inline void ocfs2_recover_from_dlm_error(struct ocfs2_lock_res *lockres, | 1223 | static inline void ocfs2_recover_from_dlm_error(struct ocfs2_lock_res *lockres, |
1143 | int convert) | 1224 | int convert) |
1144 | { | 1225 | { |
@@ -2991,7 +3072,7 @@ int ocfs2_dlm_init(struct ocfs2_super *osb) | |||
2991 | status = ocfs2_cluster_connect(osb->osb_cluster_stack, | 3072 | status = ocfs2_cluster_connect(osb->osb_cluster_stack, |
2992 | osb->uuid_str, | 3073 | osb->uuid_str, |
2993 | strlen(osb->uuid_str), | 3074 | strlen(osb->uuid_str), |
2994 | ocfs2_do_node_down, osb, | 3075 | &lproto, ocfs2_do_node_down, osb, |
2995 | &conn); | 3076 | &conn); |
2996 | if (status) { | 3077 | if (status) { |
2997 | mlog_errno(status); | 3078 | mlog_errno(status); |
@@ -3058,50 +3139,6 @@ void ocfs2_dlm_shutdown(struct ocfs2_super *osb, | |||
3058 | mlog_exit_void(); | 3139 | mlog_exit_void(); |
3059 | } | 3140 | } |
3060 | 3141 | ||
3061 | static void ocfs2_unlock_ast(struct ocfs2_dlm_lksb *lksb, int error) | ||
3062 | { | ||
3063 | struct ocfs2_lock_res *lockres = ocfs2_lksb_to_lock_res(lksb); | ||
3064 | unsigned long flags; | ||
3065 | |||
3066 | mlog_entry_void(); | ||
3067 | |||
3068 | mlog(0, "UNLOCK AST called on lock %s, action = %d\n", lockres->l_name, | ||
3069 | lockres->l_unlock_action); | ||
3070 | |||
3071 | spin_lock_irqsave(&lockres->l_lock, flags); | ||
3072 | if (error) { | ||
3073 | mlog(ML_ERROR, "Dlm passes error %d for lock %s, " | ||
3074 | "unlock_action %d\n", error, lockres->l_name, | ||
3075 | lockres->l_unlock_action); | ||
3076 | spin_unlock_irqrestore(&lockres->l_lock, flags); | ||
3077 | mlog_exit_void(); | ||
3078 | return; | ||
3079 | } | ||
3080 | |||
3081 | switch(lockres->l_unlock_action) { | ||
3082 | case OCFS2_UNLOCK_CANCEL_CONVERT: | ||
3083 | mlog(0, "Cancel convert success for %s\n", lockres->l_name); | ||
3084 | lockres->l_action = OCFS2_AST_INVALID; | ||
3085 | /* Downconvert thread may have requeued this lock, we | ||
3086 | * need to wake it. */ | ||
3087 | if (lockres->l_flags & OCFS2_LOCK_BLOCKED) | ||
3088 | ocfs2_wake_downconvert_thread(ocfs2_get_lockres_osb(lockres)); | ||
3089 | break; | ||
3090 | case OCFS2_UNLOCK_DROP_LOCK: | ||
3091 | lockres->l_level = DLM_LOCK_IV; | ||
3092 | break; | ||
3093 | default: | ||
3094 | BUG(); | ||
3095 | } | ||
3096 | |||
3097 | lockres_clear_flags(lockres, OCFS2_LOCK_BUSY); | ||
3098 | lockres->l_unlock_action = OCFS2_UNLOCK_INVALID; | ||
3099 | wake_up(&lockres->l_event); | ||
3100 | spin_unlock_irqrestore(&lockres->l_lock, flags); | ||
3101 | |||
3102 | mlog_exit_void(); | ||
3103 | } | ||
3104 | |||
3105 | static int ocfs2_drop_lock(struct ocfs2_super *osb, | 3142 | static int ocfs2_drop_lock(struct ocfs2_super *osb, |
3106 | struct ocfs2_lock_res *lockres) | 3143 | struct ocfs2_lock_res *lockres) |
3107 | { | 3144 | { |
@@ -3910,45 +3947,6 @@ void ocfs2_refcount_unlock(struct ocfs2_refcount_tree *ref_tree, int ex) | |||
3910 | ocfs2_cluster_unlock(osb, lockres, level); | 3947 | ocfs2_cluster_unlock(osb, lockres, level); |
3911 | } | 3948 | } |
3912 | 3949 | ||
3913 | /* | ||
3914 | * This is the filesystem locking protocol. It provides the lock handling | ||
3915 | * hooks for the underlying DLM. It has a maximum version number. | ||
3916 | * The version number allows interoperability with systems running at | ||
3917 | * the same major number and an equal or smaller minor number. | ||
3918 | * | ||
3919 | * Whenever the filesystem does new things with locks (adds or removes a | ||
3920 | * lock, orders them differently, does different things underneath a lock), | ||
3921 | * the version must be changed. The protocol is negotiated when joining | ||
3922 | * the dlm domain. A node may join the domain if its major version is | ||
3923 | * identical to all other nodes and its minor version is greater than | ||
3924 | * or equal to all other nodes. When its minor version is greater than | ||
3925 | * the other nodes, it will run at the minor version specified by the | ||
3926 | * other nodes. | ||
3927 | * | ||
3928 | * If a locking change is made that will not be compatible with older | ||
3929 | * versions, the major number must be increased and the minor version set | ||
3930 | * to zero. If a change merely adds a behavior that can be disabled when | ||
3931 | * speaking to older versions, the minor version must be increased. If a | ||
3932 | * change adds a fully backwards compatible change (eg, LVB changes that | ||
3933 | * are just ignored by older versions), the version does not need to be | ||
3934 | * updated. | ||
3935 | */ | ||
3936 | static struct ocfs2_locking_protocol lproto = { | ||
3937 | .lp_max_version = { | ||
3938 | .pv_major = OCFS2_LOCKING_PROTOCOL_MAJOR, | ||
3939 | .pv_minor = OCFS2_LOCKING_PROTOCOL_MINOR, | ||
3940 | }, | ||
3941 | .lp_lock_ast = ocfs2_locking_ast, | ||
3942 | .lp_blocking_ast = ocfs2_blocking_ast, | ||
3943 | .lp_unlock_ast = ocfs2_unlock_ast, | ||
3944 | }; | ||
3945 | |||
3946 | void ocfs2_set_locking_protocol(void) | ||
3947 | { | ||
3948 | ocfs2_stack_glue_set_locking_protocol(&lproto); | ||
3949 | } | ||
3950 | |||
3951 | |||
3952 | static void ocfs2_process_blocked_lock(struct ocfs2_super *osb, | 3950 | static void ocfs2_process_blocked_lock(struct ocfs2_super *osb, |
3953 | struct ocfs2_lock_res *lockres) | 3951 | struct ocfs2_lock_res *lockres) |
3954 | { | 3952 | { |
diff --git a/fs/ocfs2/stackglue.c b/fs/ocfs2/stackglue.c index fc184c762700..31db2e87cfd4 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_max_proto = lproto->lp_max_version; | 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,23 +213,23 @@ 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_max_proto = lproto->lp_max_version; | 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 | /* |
@@ -245,8 +245,6 @@ int ocfs2_dlm_lock(struct ocfs2_cluster_connection *conn, | |||
245 | void *name, | 245 | void *name, |
246 | unsigned int namelen) | 246 | unsigned int namelen) |
247 | { | 247 | { |
248 | BUG_ON(lproto == NULL); | ||
249 | |||
250 | if (!lksb->lksb_conn) | 248 | if (!lksb->lksb_conn) |
251 | lksb->lksb_conn = conn; | 249 | lksb->lksb_conn = conn; |
252 | else | 250 | else |
@@ -260,7 +258,6 @@ int ocfs2_dlm_unlock(struct ocfs2_cluster_connection *conn, | |||
260 | struct ocfs2_dlm_lksb *lksb, | 258 | struct ocfs2_dlm_lksb *lksb, |
261 | u32 flags) | 259 | u32 flags) |
262 | { | 260 | { |
263 | BUG_ON(lproto == NULL); | ||
264 | BUG_ON(lksb->lksb_conn == NULL); | 261 | BUG_ON(lksb->lksb_conn == NULL); |
265 | 262 | ||
266 | return active_stack->sp_ops->dlm_unlock(conn, lksb, flags); | 263 | return active_stack->sp_ops->dlm_unlock(conn, lksb, flags); |
@@ -314,6 +311,7 @@ EXPORT_SYMBOL_GPL(ocfs2_plock); | |||
314 | int ocfs2_cluster_connect(const char *stack_name, | 311 | int ocfs2_cluster_connect(const char *stack_name, |
315 | const char *group, | 312 | const char *group, |
316 | int grouplen, | 313 | int grouplen, |
314 | struct ocfs2_locking_protocol *lproto, | ||
317 | void (*recovery_handler)(int node_num, | 315 | void (*recovery_handler)(int node_num, |
318 | void *recovery_data), | 316 | void *recovery_data), |
319 | void *recovery_data, | 317 | void *recovery_data, |
@@ -331,6 +329,12 @@ int ocfs2_cluster_connect(const char *stack_name, | |||
331 | goto out; | 329 | goto out; |
332 | } | 330 | } |
333 | 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 | |||
334 | new_conn = kzalloc(sizeof(struct ocfs2_cluster_connection), | 338 | new_conn = kzalloc(sizeof(struct ocfs2_cluster_connection), |
335 | GFP_KERNEL); | 339 | GFP_KERNEL); |
336 | if (!new_conn) { | 340 | if (!new_conn) { |
@@ -456,10 +460,10 @@ static ssize_t ocfs2_max_locking_protocol_show(struct kobject *kobj, | |||
456 | ssize_t ret = 0; | 460 | ssize_t ret = 0; |
457 | 461 | ||
458 | spin_lock(&ocfs2_stack_lock); | 462 | spin_lock(&ocfs2_stack_lock); |
459 | if (lproto) | 463 | if (locking_max_version.pv_major) |
460 | ret = snprintf(buf, PAGE_SIZE, "%u.%u\n", | 464 | ret = snprintf(buf, PAGE_SIZE, "%u.%u\n", |
461 | lproto->lp_max_version.pv_major, | 465 | locking_max_version.pv_major, |
462 | lproto->lp_max_version.pv_minor); | 466 | locking_max_version.pv_minor); |
463 | spin_unlock(&ocfs2_stack_lock); | 467 | spin_unlock(&ocfs2_stack_lock); |
464 | 468 | ||
465 | return ret; | 469 | return ret; |
@@ -688,7 +692,10 @@ static int __init ocfs2_stack_glue_init(void) | |||
688 | 692 | ||
689 | static void __exit ocfs2_stack_glue_exit(void) | 693 | static void __exit ocfs2_stack_glue_exit(void) |
690 | { | 694 | { |
691 | lproto = NULL; | 695 | memset(&locking_max_version, 0, |
696 | sizeof(struct ocfs2_protocol_version)); | ||
697 | locking_max_version.pv_major = 0; | ||
698 | locking_max_version.pv_minor = 0; | ||
692 | ocfs2_sysfs_exit(); | 699 | ocfs2_sysfs_exit(); |
693 | if (ocfs2_table_header) | 700 | if (ocfs2_table_header) |
694 | unregister_sysctl_table(ocfs2_table_header); | 701 | unregister_sysctl_table(ocfs2_table_header); |
diff --git a/fs/ocfs2/stackglue.h b/fs/ocfs2/stackglue.h index 77a7a9aeba73..b1981ba4c91f 100644 --- a/fs/ocfs2/stackglue.h +++ b/fs/ocfs2/stackglue.h | |||
@@ -241,6 +241,7 @@ struct ocfs2_stack_plugin { | |||
241 | int ocfs2_cluster_connect(const char *stack_name, | 241 | int ocfs2_cluster_connect(const char *stack_name, |
242 | const char *group, | 242 | const char *group, |
243 | int grouplen, | 243 | int grouplen, |
244 | struct ocfs2_locking_protocol *lproto, | ||
244 | void (*recovery_handler)(int node_num, | 245 | void (*recovery_handler)(int node_num, |
245 | void *recovery_data), | 246 | void *recovery_data), |
246 | void *recovery_data, | 247 | void *recovery_data, |
@@ -270,7 +271,7 @@ int ocfs2_stack_supports_plocks(void); | |||
270 | int ocfs2_plock(struct ocfs2_cluster_connection *conn, u64 ino, | 271 | int ocfs2_plock(struct ocfs2_cluster_connection *conn, u64 ino, |
271 | struct file *file, int cmd, struct file_lock *fl); | 272 | struct file *file, int cmd, struct file_lock *fl); |
272 | 273 | ||
273 | void ocfs2_stack_glue_set_locking_protocol(struct ocfs2_locking_protocol *proto); | 274 | void ocfs2_stack_glue_set_max_proto_version(struct ocfs2_protocol_version *max_proto); |
274 | 275 | ||
275 | 276 | ||
276 | /* Used by stack plugins */ | 277 | /* Used by stack plugins */ |