Skip to content

Commit c994c2e

Browse files
Goldwyn Rodriguestorvalds
authored andcommitted
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>
1 parent 4150363 commit c994c2e

File tree

1 file changed

+102
-24
lines changed

1 file changed

+102
-24
lines changed

fs/ocfs2/stack_user.c

Lines changed: 102 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
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

127129
struct 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+
900951
static 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

930982
const 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+
936998
static 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;
9821065
out:
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

9971072
static 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

Comments
 (0)