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/dlmglue.c | |
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/dlmglue.c')
-rw-r--r-- | fs/ocfs2/dlmglue.c | 168 |
1 files changed, 83 insertions, 85 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 | { |