aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ocfs2/stack_user.c
diff options
context:
space:
mode:
authorGoldwyn Rodrigues <rgoldwyn@suse.de>2014-01-21 18:48:32 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-01-21 19:19:42 -0500
commitc994c2ebdbbc391a42f177c8eb7882ebf3f142d8 (patch)
tree0f0240ae61f86140b0660ce224b1eff26d89ce3c /fs/ocfs2/stack_user.c
parent415036303319c0a46caf9059711710bfa34e3bf3 (diff)
ocfs2: use the new DLM operation callbacks while requesting new lockspace
Attempt to use the new DLM operations. If it is not supported, use the traditional ocfs2_controld. To exchange ocfs2 versioning, we use the LVB of the version dlm lock. It first attempts to take the lock in EX mode (non-blocking). If successful (which means it is the first mount), it writes the version number and downconverts to PR lock. If it is unsuccessful, it reads the version from the lock. If this becomes the standard (with o2cb as well), it could simplify userspace tools to check if the filesystem is mounted on other nodes. Dan: Since ocfs2_protocol_version are two u8 values, the additional checks with LONG* don't make sense. Signed-off-by: Goldwyn Rodrigues <rgoldwyn@suse.com> Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com> Reviewed-by: Mark Fasheh <mfasheh@suse.de> Cc: Joel Becker <jlbec@evilplan.org> Cc: Dan Carpenter <dan.carpenter@oracle.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/ocfs2/stack_user.c')
-rw-r--r--fs/ocfs2/stack_user.c126
1 files changed, 102 insertions, 24 deletions
diff --git a/fs/ocfs2/stack_user.c b/fs/ocfs2/stack_user.c
index d3867100aca8..673ab40eb81b 100644
--- a/fs/ocfs2/stack_user.c
+++ b/fs/ocfs2/stack_user.c
@@ -23,6 +23,7 @@
23#include <linux/mutex.h> 23#include <linux/mutex.h>
24#include <linux/slab.h> 24#include <linux/slab.h>
25#include <linux/reboot.h> 25#include <linux/reboot.h>
26#include <linux/sched.h>
26#include <asm/uaccess.h> 27#include <asm/uaccess.h>
27 28
28#include "stackglue.h" 29#include "stackglue.h"
@@ -122,6 +123,7 @@ struct ocfs2_live_connection {
122 struct dlm_lksb oc_version_lksb; 123 struct dlm_lksb oc_version_lksb;
123 char oc_lvb[DLM_LVB_LEN]; 124 char oc_lvb[DLM_LVB_LEN];
124 struct completion oc_sync_wait; 125 struct completion oc_sync_wait;
126 wait_queue_head_t oc_wait;
125}; 127};
126 128
127struct ocfs2_control_private { 129struct ocfs2_control_private {
@@ -218,7 +220,7 @@ static int ocfs2_live_connection_attach(struct ocfs2_cluster_connection *conn,
218 mutex_lock(&ocfs2_control_lock); 220 mutex_lock(&ocfs2_control_lock);
219 c->oc_conn = conn; 221 c->oc_conn = conn;
220 222
221 if (atomic_read(&ocfs2_control_opened)) 223 if ((c->oc_type == NO_CONTROLD) || atomic_read(&ocfs2_control_opened))
222 list_add(&c->oc_list, &ocfs2_live_connection_list); 224 list_add(&c->oc_list, &ocfs2_live_connection_list);
223 else { 225 else {
224 printk(KERN_ERR 226 printk(KERN_ERR
@@ -897,6 +899,55 @@ static int version_unlock(struct ocfs2_cluster_connection *conn)
897 return sync_unlock(conn, &lc->oc_version_lksb, VERSION_LOCK); 899 return sync_unlock(conn, &lc->oc_version_lksb, VERSION_LOCK);
898} 900}
899 901
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
913static 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 }
947out:
948 return ret;
949}
950
900static void user_recover_prep(void *arg) 951static void user_recover_prep(void *arg)
901{ 952{
902} 953}
@@ -925,6 +976,7 @@ static void user_recover_done(void *arg, struct dlm_slot *slots,
925 } 976 }
926 977
927 lc->oc_our_slot = our_slot; 978 lc->oc_our_slot = our_slot;
979 wake_up(&lc->oc_wait);
928} 980}
929 981
930const struct dlm_lockspace_ops ocfs2_ls_ops = { 982const struct dlm_lockspace_ops ocfs2_ls_ops = {
@@ -933,11 +985,21 @@ const struct dlm_lockspace_ops ocfs2_ls_ops = {
933 .recover_done = user_recover_done, 985 .recover_done = user_recover_done,
934}; 986};
935 987
988static 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
936static int user_cluster_connect(struct ocfs2_cluster_connection *conn) 998static int user_cluster_connect(struct ocfs2_cluster_connection *conn)
937{ 999{
938 dlm_lockspace_t *fsdlm; 1000 dlm_lockspace_t *fsdlm;
939 struct ocfs2_live_connection *lc; 1001 struct ocfs2_live_connection *lc;
940 int rc; 1002 int rc, ops_rv;
941 1003
942 BUG_ON(conn == NULL); 1004 BUG_ON(conn == NULL);
943 1005
@@ -947,11 +1009,44 @@ static int user_cluster_connect(struct ocfs2_cluster_connection *conn)
947 goto out; 1009 goto out;
948 } 1010 }
949 1011
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
951 rc = ocfs2_live_connection_attach(conn, lc); 1035 rc = ocfs2_live_connection_attach(conn, lc);
952 if (rc) 1036 if (rc)
953 goto out; 1037 goto out;
954 1038
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
955 /* 1050 /*
956 * running_proto must have been set before we allowed any mounts 1051 * running_proto must have been set before we allowed any mounts
957 * to proceed. 1052 * to proceed.
@@ -959,40 +1054,20 @@ static int user_cluster_connect(struct ocfs2_cluster_connection *conn)
959 if (fs_protocol_compare(&running_proto, &conn->cc_version)) { 1054 if (fs_protocol_compare(&running_proto, &conn->cc_version)) {
960 printk(KERN_ERR 1055 printk(KERN_ERR
961 "Unable to mount with fs locking protocol version " 1056 "Unable to mount with fs locking protocol version "
962 "%u.%u because the userspace control daemon has " 1057 "%u.%u because negotiated protocol is %u.%u\n",
963 "negotiated %u.%u\n",
964 conn->cc_version.pv_major, conn->cc_version.pv_minor, 1058 conn->cc_version.pv_major, conn->cc_version.pv_minor,
965 running_proto.pv_major, running_proto.pv_minor); 1059 running_proto.pv_major, running_proto.pv_minor);
966 rc = -EPROTO; 1060 rc = -EPROTO;
967 ocfs2_live_connection_drop(lc); 1061 ocfs2_live_connection_drop(lc);
968 lc = NULL; 1062 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;
978 } 1063 }
979 1064
980 conn->cc_private = lc;
981 conn->cc_lockspace = fsdlm;
982out: 1065out:
983 if (rc && lc) 1066 if (rc && lc)
984 kfree(lc); 1067 kfree(lc);
985 return rc; 1068 return rc;
986} 1069}
987 1070
988static 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}
996 1071
997static int user_cluster_this_node(struct ocfs2_cluster_connection *conn, 1072static int user_cluster_this_node(struct ocfs2_cluster_connection *conn,
998 unsigned int *this_node) 1073 unsigned int *this_node)
@@ -1002,8 +1077,11 @@ static int user_cluster_this_node(struct ocfs2_cluster_connection *conn,
1002 1077
1003 if (lc->oc_type == WITH_CONTROLD) 1078 if (lc->oc_type == WITH_CONTROLD)
1004 rc = ocfs2_control_get_this_node(); 1079 rc = ocfs2_control_get_this_node();
1080 else if (lc->oc_type == NO_CONTROLD)
1081 rc = atomic_read(&lc->oc_this_node);
1005 else 1082 else
1006 rc = -EINVAL; 1083 rc = -EINVAL;
1084
1007 if (rc < 0) 1085 if (rc < 0)
1008 return rc; 1086 return rc;
1009 1087