2323#include <linux/mutex.h>
2424#include <linux/slab.h>
2525#include <linux/reboot.h>
26+ #include <linux/sched.h>
2627#include <asm/uaccess.h>
2728
2829#include "stackglue.h"
@@ -122,6 +123,7 @@ struct ocfs2_live_connection {
122123 struct dlm_lksb oc_version_lksb ;
123124 char oc_lvb [DLM_LVB_LEN ];
124125 struct completion oc_sync_wait ;
126+ wait_queue_head_t oc_wait ;
125127};
126128
127129struct ocfs2_control_private {
@@ -218,7 +220,7 @@ static int ocfs2_live_connection_attach(struct ocfs2_cluster_connection *conn,
218220 mutex_lock (& ocfs2_control_lock );
219221 c -> oc_conn = conn ;
220222
221- if (atomic_read (& ocfs2_control_opened ))
223+ if (( c -> oc_type == NO_CONTROLD ) || atomic_read (& ocfs2_control_opened ))
222224 list_add (& c -> oc_list , & ocfs2_live_connection_list );
223225 else {
224226 printk (KERN_ERR
@@ -897,6 +899,55 @@ static int version_unlock(struct ocfs2_cluster_connection *conn)
897899 return sync_unlock (conn , & lc -> oc_version_lksb , VERSION_LOCK );
898900}
899901
902+ /* get_protocol_version()
903+ *
904+ * To exchange ocfs2 versioning, we use the LVB of the version dlm lock.
905+ * The algorithm is:
906+ * 1. Attempt to take the lock in EX mode (non-blocking).
907+ * 2. If successful (which means it is the first mount), write the
908+ * version number and downconvert to PR lock.
909+ * 3. If unsuccessful (returns -EAGAIN), read the version from the LVB after
910+ * taking the PR lock.
911+ */
912+
913+ static int get_protocol_version (struct ocfs2_cluster_connection * conn )
914+ {
915+ int ret ;
916+ struct ocfs2_live_connection * lc = conn -> cc_private ;
917+ struct ocfs2_protocol_version pv ;
918+
919+ running_proto .pv_major =
920+ ocfs2_user_plugin .sp_max_proto .pv_major ;
921+ running_proto .pv_minor =
922+ ocfs2_user_plugin .sp_max_proto .pv_minor ;
923+
924+ lc -> oc_version_lksb .sb_lvbptr = lc -> oc_lvb ;
925+ ret = version_lock (conn , DLM_LOCK_EX ,
926+ DLM_LKF_VALBLK |DLM_LKF_NOQUEUE );
927+ if (!ret ) {
928+ conn -> cc_version .pv_major = running_proto .pv_major ;
929+ conn -> cc_version .pv_minor = running_proto .pv_minor ;
930+ version_to_lvb (& running_proto , lc -> oc_lvb );
931+ version_lock (conn , DLM_LOCK_PR , DLM_LKF_CONVERT |DLM_LKF_VALBLK );
932+ } else if (ret == - EAGAIN ) {
933+ ret = version_lock (conn , DLM_LOCK_PR , DLM_LKF_VALBLK );
934+ if (ret )
935+ goto out ;
936+ lvb_to_version (lc -> oc_lvb , & pv );
937+
938+ if ((pv .pv_major != running_proto .pv_major ) ||
939+ (pv .pv_minor > running_proto .pv_minor )) {
940+ ret = - EINVAL ;
941+ goto out ;
942+ }
943+
944+ conn -> cc_version .pv_major = pv .pv_major ;
945+ conn -> cc_version .pv_minor = pv .pv_minor ;
946+ }
947+ out :
948+ return ret ;
949+ }
950+
900951static void user_recover_prep (void * arg )
901952{
902953}
@@ -925,6 +976,7 @@ static void user_recover_done(void *arg, struct dlm_slot *slots,
925976 }
926977
927978 lc -> oc_our_slot = our_slot ;
979+ wake_up (& lc -> oc_wait );
928980}
929981
930982const struct dlm_lockspace_ops ocfs2_ls_ops = {
@@ -933,11 +985,21 @@ const struct dlm_lockspace_ops ocfs2_ls_ops = {
933985 .recover_done = user_recover_done ,
934986};
935987
988+ static int user_cluster_disconnect (struct ocfs2_cluster_connection * conn )
989+ {
990+ version_unlock (conn );
991+ dlm_release_lockspace (conn -> cc_lockspace , 2 );
992+ conn -> cc_lockspace = NULL ;
993+ ocfs2_live_connection_drop (conn -> cc_private );
994+ conn -> cc_private = NULL ;
995+ return 0 ;
996+ }
997+
936998static int user_cluster_connect (struct ocfs2_cluster_connection * conn )
937999{
9381000 dlm_lockspace_t * fsdlm ;
9391001 struct ocfs2_live_connection * lc ;
940- int rc ;
1002+ int rc , ops_rv ;
9411003
9421004 BUG_ON (conn == NULL );
9431005
@@ -947,52 +1009,65 @@ static int user_cluster_connect(struct ocfs2_cluster_connection *conn)
9471009 goto out ;
9481010 }
9491011
950- lc -> oc_type = WITH_CONTROLD ;
1012+ init_waitqueue_head (& lc -> oc_wait );
1013+ init_completion (& lc -> oc_sync_wait );
1014+ atomic_set (& lc -> oc_this_node , 0 );
1015+ conn -> cc_private = lc ;
1016+ lc -> oc_type = NO_CONTROLD ;
1017+
1018+ rc = dlm_new_lockspace (conn -> cc_name , conn -> cc_cluster_name ,
1019+ DLM_LSFL_FS , DLM_LVB_LEN ,
1020+ & ocfs2_ls_ops , conn , & ops_rv , & fsdlm );
1021+ if (rc )
1022+ goto out ;
1023+
1024+ if (ops_rv == - EOPNOTSUPP ) {
1025+ lc -> oc_type = WITH_CONTROLD ;
1026+ printk (KERN_NOTICE "ocfs2: You seem to be using an older "
1027+ "version of dlm_controld and/or ocfs2-tools."
1028+ " Please consider upgrading.\n" );
1029+ } else if (ops_rv ) {
1030+ rc = ops_rv ;
1031+ goto out ;
1032+ }
1033+ conn -> cc_lockspace = fsdlm ;
1034+
9511035 rc = ocfs2_live_connection_attach (conn , lc );
9521036 if (rc )
9531037 goto out ;
9541038
1039+ if (lc -> oc_type == NO_CONTROLD ) {
1040+ rc = get_protocol_version (conn );
1041+ if (rc ) {
1042+ printk (KERN_ERR "ocfs2: Could not determine"
1043+ " locking version\n" );
1044+ user_cluster_disconnect (conn );
1045+ goto out ;
1046+ }
1047+ wait_event (lc -> oc_wait , (atomic_read (& lc -> oc_this_node ) > 0 ));
1048+ }
1049+
9551050 /*
9561051 * running_proto must have been set before we allowed any mounts
9571052 * to proceed.
9581053 */
9591054 if (fs_protocol_compare (& running_proto , & conn -> cc_version )) {
9601055 printk (KERN_ERR
9611056 "Unable to mount with fs locking protocol version "
962- "%u.%u because the userspace control daemon has "
963- "negotiated %u.%u\n" ,
1057+ "%u.%u because negotiated protocol is %u.%u\n" ,
9641058 conn -> cc_version .pv_major , conn -> cc_version .pv_minor ,
9651059 running_proto .pv_major , running_proto .pv_minor );
9661060 rc = - EPROTO ;
9671061 ocfs2_live_connection_drop (lc );
9681062 lc = NULL ;
969- goto out ;
970- }
971-
972- rc = dlm_new_lockspace (conn -> cc_name , NULL , DLM_LSFL_FS , DLM_LVB_LEN ,
973- NULL , NULL , NULL , & fsdlm );
974- if (rc ) {
975- ocfs2_live_connection_drop (lc );
976- lc = NULL ;
977- goto out ;
9781063 }
9791064
980- conn -> cc_private = lc ;
981- conn -> cc_lockspace = fsdlm ;
9821065out :
9831066 if (rc && lc )
9841067 kfree (lc );
9851068 return rc ;
9861069}
9871070
988- static int user_cluster_disconnect (struct ocfs2_cluster_connection * conn )
989- {
990- dlm_release_lockspace (conn -> cc_lockspace , 2 );
991- conn -> cc_lockspace = NULL ;
992- ocfs2_live_connection_drop (conn -> cc_private );
993- conn -> cc_private = NULL ;
994- return 0 ;
995- }
9961071
9971072static int user_cluster_this_node (struct ocfs2_cluster_connection * conn ,
9981073 unsigned int * this_node )
@@ -1002,8 +1077,11 @@ static int user_cluster_this_node(struct ocfs2_cluster_connection *conn,
10021077
10031078 if (lc -> oc_type == WITH_CONTROLD )
10041079 rc = ocfs2_control_get_this_node ();
1080+ else if (lc -> oc_type == NO_CONTROLD )
1081+ rc = atomic_read (& lc -> oc_this_node );
10051082 else
10061083 rc = - EINVAL ;
1084+
10071085 if (rc < 0 )
10081086 return rc ;
10091087
0 commit comments