All of lore.kernel.org
 help / color / mirror / Atom feed
* [Cluster-devel] [PATCH dlm/next 0/9] fs: dlm: fixes and change listen socket handling
@ 2020-10-19 18:59 Alexander Aring
  2020-10-19 18:59 ` [Cluster-devel] [PATCH dlm/next 1/9] fs: dlm: fix proper srcu api call Alexander Aring
                   ` (8 more replies)
  0 siblings, 9 replies; 10+ messages in thread
From: Alexander Aring @ 2020-10-19 18:59 UTC (permalink / raw)
  To: cluster-devel.redhat.com

Hi,

This series fix a issue by using the wrong RCU API for sleepable rcu.

The second patch is something what I discovered by placing a new header
in front of the dlm header. This header encapsulates a dlm message.
The patch will fix issues with the ci_buffer_size and I am not sure for
what the ci_buffer_size setting is exactly used before, there was no
range protection or something else and it is used for transmit and
receive side. As I saw that the previous receive handling was using it
as the receive buffer size for "bigger" dlm messages, I changed it mostly
the same way and allowed even reading more bytes in a recvmsg(). The user
need somehow know before the actual biggest possible dlm message (which is
PAGE_SIZE, because the buffer allocator of lowcomms). The upper layer
protocol should never request a buffer which can be above PAGE_SIZE length,
otherwise we run in a bufferoverlow. With the recent changes of
"ci_buffer_size" it's allowed to be above PAGE_SIZE, the patch should be
sure we use the maximum possible payload to a dlm recovery message and
don't let this configurable.

The rest of this patch-series makes the listen socket handling better
regarding to accept socket. There exists some code path which the listen
socket should never run, but possible when we handle the listen socket as
normal connection inside the connection hash. This patch series contains
patches to prepare and finally handle the listen connection in their own
separate structure. It also do some small cleanup to avoid double close
on the listen socket and be sure we set the sock pointer to NULL if
closed, some parts of the code seems to have this required.

- Alex

Alexander Aring (9):
  fs: dlm: fix proper srcu api call
  fs: dlm: define max send buffer
  fs: dlm: add get buffer error handling
  fs: dlm: flush othercon at close
  fs: dlm: handle non blocked connect event
  fs: dlm: move connect callback in node creation
  fs: dlm: move shutdown action to node creation
  fs: dlm: refactor sctp sock parameter
  fs: dlm: listen socket out of connection hash

 fs/dlm/lockspace.c |   2 +-
 fs/dlm/lowcomms.c  | 225 +++++++++++++++++++++++----------------------
 fs/dlm/lowcomms.h  |   4 +
 fs/dlm/member.c    |   2 +-
 fs/dlm/rcom.c      |   6 +-
 5 files changed, 122 insertions(+), 117 deletions(-)

-- 
2.26.2



^ permalink raw reply	[flat|nested] 10+ messages in thread

* [Cluster-devel] [PATCH dlm/next 1/9] fs: dlm: fix proper srcu api call
  2020-10-19 18:59 [Cluster-devel] [PATCH dlm/next 0/9] fs: dlm: fixes and change listen socket handling Alexander Aring
@ 2020-10-19 18:59 ` Alexander Aring
  2020-10-19 18:59 ` [Cluster-devel] [PATCH dlm/next 2/9] fs: dlm: define max send buffer Alexander Aring
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Alexander Aring @ 2020-10-19 18:59 UTC (permalink / raw)
  To: cluster-devel.redhat.com

This patch will use call_srcu() instead of call_rcu() because the
related datastructure resource are handled under srcu context. I assume
the current code is fine anyway since free_conn() must be called when
the related resource are not in use otherwise. However it will correct
the overall handling in a srcu context.

Signed-off-by: Alexander Aring <aahringo@redhat.com>
---
 fs/dlm/lowcomms.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c
index 79f56f16bc2ce..77382c2ce6da2 100644
--- a/fs/dlm/lowcomms.c
+++ b/fs/dlm/lowcomms.c
@@ -1616,10 +1616,11 @@ static void free_conn(struct connection *con)
 	spin_unlock(&connections_lock);
 	if (con->othercon) {
 		clean_one_writequeue(con->othercon);
-		call_rcu(&con->othercon->rcu, connection_release);
+		call_srcu(&connections_srcu, &con->othercon->rcu,
+			  connection_release);
 	}
 	clean_one_writequeue(con);
-	call_rcu(&con->rcu, connection_release);
+	call_srcu(&connections_srcu, &con->rcu, connection_release);
 }
 
 static void work_flush(void)
-- 
2.26.2



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [Cluster-devel] [PATCH dlm/next 2/9] fs: dlm: define max send buffer
  2020-10-19 18:59 [Cluster-devel] [PATCH dlm/next 0/9] fs: dlm: fixes and change listen socket handling Alexander Aring
  2020-10-19 18:59 ` [Cluster-devel] [PATCH dlm/next 1/9] fs: dlm: fix proper srcu api call Alexander Aring
@ 2020-10-19 18:59 ` Alexander Aring
  2020-10-19 18:59 ` [Cluster-devel] [PATCH dlm/next 3/9] fs: dlm: add get buffer error handling Alexander Aring
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Alexander Aring @ 2020-10-19 18:59 UTC (permalink / raw)
  To: cluster-devel.redhat.com

This patch will set the maximum transmit buffer size for rcom messages
with "names" to PAGE_SIZE. It's a leftover change of
commit 4798cbbfbd00 ("fs: dlm: rework receive handling"). Fact is that we
cannot allocate a contiguous transmit buffer length above of a PAGE_SIZE.
It seems at some places the upper layer protocol will calculate according
to dlm_config.ci_buffer_size the possible payload of a dlm recovery
message. As compiler setting we will use now the maximum possible
message which dlm can send out. Commit 4e192ee68e5af ("fs: dlm: disallow
buffer size below default") disallow a buffer setting smaller than the
PAGE_SIZE and above PAGE_SIZE is definitely wrong because we will then
write out of buffer space as we cannot allocate a contiguous buffer above
PAGE_SIZE. The ci_buffer_size is still there to define the possible
maximum receive buffer size of a recvmsg() which should be at least the
maximum possible dlm message size.

Signed-off-by: Alexander Aring <aahringo@redhat.com>
---
 fs/dlm/lockspace.c | 2 +-
 fs/dlm/lowcomms.h  | 4 ++++
 fs/dlm/member.c    | 2 +-
 fs/dlm/rcom.c      | 6 +++---
 4 files changed, 9 insertions(+), 5 deletions(-)

diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c
index 624617c12250a..561dcad08ad6e 100644
--- a/fs/dlm/lockspace.c
+++ b/fs/dlm/lockspace.c
@@ -572,7 +572,7 @@ static int new_lockspace(const char *name, const char *cluster,
 	mutex_init(&ls->ls_requestqueue_mutex);
 	mutex_init(&ls->ls_clear_proc_locks);
 
-	ls->ls_recover_buf = kmalloc(dlm_config.ci_buffer_size, GFP_NOFS);
+	ls->ls_recover_buf = kmalloc(LOWCOMMS_MAX_TX_BUFFER_LEN, GFP_NOFS);
 	if (!ls->ls_recover_buf)
 		goto out_lkbidr;
 
diff --git a/fs/dlm/lowcomms.h b/fs/dlm/lowcomms.h
index 687b2894e469a..f68d361b6e8c7 100644
--- a/fs/dlm/lowcomms.h
+++ b/fs/dlm/lowcomms.h
@@ -12,6 +12,10 @@
 #ifndef __LOWCOMMS_DOT_H__
 #define __LOWCOMMS_DOT_H__
 
+#include <asm/page.h>
+
+#define LOWCOMMS_MAX_TX_BUFFER_LEN	PAGE_SIZE
+
 int dlm_lowcomms_start(void);
 void dlm_lowcomms_stop(void);
 void dlm_lowcomms_exit(void);
diff --git a/fs/dlm/member.c b/fs/dlm/member.c
index 7ad83deb45053..ceef3f2074ffd 100644
--- a/fs/dlm/member.c
+++ b/fs/dlm/member.c
@@ -270,7 +270,7 @@ int dlm_slots_assign(struct dlm_ls *ls, int *num_slots, int *slots_size,
 
 	log_slots(ls, gen, num, NULL, array, array_size);
 
-	max_slots = (dlm_config.ci_buffer_size - sizeof(struct dlm_rcom) -
+	max_slots = (LOWCOMMS_MAX_TX_BUFFER_LEN - sizeof(struct dlm_rcom) -
 		     sizeof(struct rcom_config)) / sizeof(struct rcom_slot);
 
 	if (num > max_slots) {
diff --git a/fs/dlm/rcom.c b/fs/dlm/rcom.c
index 4daf5dc2b51c0..73ddee5159d79 100644
--- a/fs/dlm/rcom.c
+++ b/fs/dlm/rcom.c
@@ -162,7 +162,7 @@ int dlm_rcom_status(struct dlm_ls *ls, int nodeid, uint32_t status_flags)
 	set_rcom_status(ls, (struct rcom_status *)rc->rc_buf, status_flags);
 
 	allow_sync_reply(ls, &rc->rc_id);
-	memset(ls->ls_recover_buf, 0, dlm_config.ci_buffer_size);
+	memset(ls->ls_recover_buf, 0, LOWCOMMS_MAX_TX_BUFFER_LEN);
 
 	send_rcom(ls, mh, rc);
 
@@ -284,7 +284,7 @@ int dlm_rcom_names(struct dlm_ls *ls, int nodeid, char *last_name, int last_len)
 	memcpy(rc->rc_buf, last_name, last_len);
 
 	allow_sync_reply(ls, &rc->rc_id);
-	memset(ls->ls_recover_buf, 0, dlm_config.ci_buffer_size);
+	memset(ls->ls_recover_buf, 0, LOWCOMMS_MAX_TX_BUFFER_LEN);
 
 	send_rcom(ls, mh, rc);
 
@@ -304,7 +304,7 @@ static void receive_rcom_names(struct dlm_ls *ls, struct dlm_rcom *rc_in)
 
 	nodeid = rc_in->rc_header.h_nodeid;
 	inlen = rc_in->rc_header.h_length - sizeof(struct dlm_rcom);
-	outlen = dlm_config.ci_buffer_size - sizeof(struct dlm_rcom);
+	outlen = LOWCOMMS_MAX_TX_BUFFER_LEN - sizeof(struct dlm_rcom);
 
 	error = create_rcom(ls, nodeid, DLM_RCOM_NAMES_REPLY, outlen, &rc, &mh);
 	if (error)
-- 
2.26.2



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [Cluster-devel] [PATCH dlm/next 3/9] fs: dlm: add get buffer error handling
  2020-10-19 18:59 [Cluster-devel] [PATCH dlm/next 0/9] fs: dlm: fixes and change listen socket handling Alexander Aring
  2020-10-19 18:59 ` [Cluster-devel] [PATCH dlm/next 1/9] fs: dlm: fix proper srcu api call Alexander Aring
  2020-10-19 18:59 ` [Cluster-devel] [PATCH dlm/next 2/9] fs: dlm: define max send buffer Alexander Aring
@ 2020-10-19 18:59 ` Alexander Aring
  2020-10-19 18:59 ` [Cluster-devel] [PATCH dlm/next 4/9] fs: dlm: flush othercon at close Alexander Aring
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Alexander Aring @ 2020-10-19 18:59 UTC (permalink / raw)
  To: cluster-devel.redhat.com

This patch adds an error handling to the get buffer functionality if the
user is requesting a buffer length which is more than possible of
the internal buffer allocator. This should never happen because specific
handling decided by compile time, but will warn if somebody forget about
to handle this limitation right.

Signed-off-by: Alexander Aring <aahringo@redhat.com>
---
 fs/dlm/lowcomms.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c
index 77382c2ce6da2..0e29242620136 100644
--- a/fs/dlm/lowcomms.c
+++ b/fs/dlm/lowcomms.c
@@ -1352,6 +1352,11 @@ void *dlm_lowcomms_get_buffer(int nodeid, int len, gfp_t allocation, char **ppc)
 	struct writequeue_entry *e;
 	int offset = 0;
 
+	if (len > PAGE_SIZE) {
+		log_print("failed to allocate a buffer of size %d", len);
+		return NULL;
+	}
+
 	con = nodeid2con(nodeid, allocation);
 	if (!con)
 		return NULL;
-- 
2.26.2



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [Cluster-devel] [PATCH dlm/next 4/9] fs: dlm: flush othercon at close
  2020-10-19 18:59 [Cluster-devel] [PATCH dlm/next 0/9] fs: dlm: fixes and change listen socket handling Alexander Aring
                   ` (2 preceding siblings ...)
  2020-10-19 18:59 ` [Cluster-devel] [PATCH dlm/next 3/9] fs: dlm: add get buffer error handling Alexander Aring
@ 2020-10-19 18:59 ` Alexander Aring
  2020-10-19 18:59 ` [Cluster-devel] [PATCH dlm/next 5/9] fs: dlm: handle non blocked connect event Alexander Aring
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Alexander Aring @ 2020-10-19 18:59 UTC (permalink / raw)
  To: cluster-devel.redhat.com

This patch ensures we also flush the othercon writequeue when a lowcomms
close occurs.

Signed-off-by: Alexander Aring <aahringo@redhat.com>
---
 fs/dlm/lowcomms.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c
index 0e29242620136..7a60bb0d6f704 100644
--- a/fs/dlm/lowcomms.c
+++ b/fs/dlm/lowcomms.c
@@ -1511,6 +1511,8 @@ int dlm_lowcomms_close(int nodeid)
 		set_bit(CF_CLOSE, &con->flags);
 		close_connection(con, true, true, true);
 		clean_one_writequeue(con);
+		if (con->othercon)
+			clean_one_writequeue(con->othercon);
 	}
 
 	spin_lock(&dlm_node_addrs_spin);
-- 
2.26.2



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [Cluster-devel] [PATCH dlm/next 5/9] fs: dlm: handle non blocked connect event
  2020-10-19 18:59 [Cluster-devel] [PATCH dlm/next 0/9] fs: dlm: fixes and change listen socket handling Alexander Aring
                   ` (3 preceding siblings ...)
  2020-10-19 18:59 ` [Cluster-devel] [PATCH dlm/next 4/9] fs: dlm: flush othercon at close Alexander Aring
@ 2020-10-19 18:59 ` Alexander Aring
  2020-10-19 18:59 ` [Cluster-devel] [PATCH dlm/next 6/9] fs: dlm: move connect callback in node creation Alexander Aring
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Alexander Aring @ 2020-10-19 18:59 UTC (permalink / raw)
  To: cluster-devel.redhat.com

The manpage of connect shows that in non blocked mode a writeability
indicates successful connection event. This patch is handling this event
inside the writeability callback. In case of SCTP we use blocking
connect functionality which indicates a successful connect when the
function returns with a successful return value.

Signed-off-by: Alexander Aring <aahringo@redhat.com>
---
 fs/dlm/lowcomms.c | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c
index 7a60bb0d6f704..70a216a20dbb9 100644
--- a/fs/dlm/lowcomms.c
+++ b/fs/dlm/lowcomms.c
@@ -78,6 +78,7 @@ struct connection {
 #define CF_APP_LIMITED 7
 #define CF_CLOSING 8
 #define CF_SHUTDOWN 9
+#define CF_CONNECTED 10
 	struct list_head writequeue;  /* List of outgoing writequeue_entries */
 	spinlock_t writequeue_lock;
 	int (*rx_action) (struct connection *);	/* What to do when active */
@@ -419,6 +420,12 @@ static void lowcomms_write_space(struct sock *sk)
 	if (!con)
 		goto out;
 
+	if (!test_and_set_bit(CF_CONNECTED, &con->flags)) {
+		log_print("successful connected to node %d", con->nodeid);
+		queue_work(send_workqueue, &con->swork);
+		goto out;
+	}
+
 	clear_bit(SOCK_NOSPACE, &con->sock->flags);
 
 	if (test_and_clear_bit(CF_APP_LIMITED, &con->flags)) {
@@ -604,6 +611,7 @@ static void close_connection(struct connection *con, bool and_other,
 
 	con->rx_leftover = 0;
 	con->retries = 0;
+	clear_bit(CF_CONNECTED, &con->flags);
 	mutex_unlock(&con->sock_mutex);
 	clear_bit(CF_CLOSING, &con->flags);
 }
@@ -1027,8 +1035,11 @@ static void sctp_connect_to_sock(struct connection *con)
 
 	if (result == -EINPROGRESS)
 		result = 0;
-	if (result == 0)
+	if (result == 0) {
+		if (!test_and_set_bit(CF_CONNECTED, &con->flags))
+			log_print("successful connected to node %d", con->nodeid);
 		goto out;
+	}
 
 bind_err:
 	con->sock = NULL;
-- 
2.26.2



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [Cluster-devel] [PATCH dlm/next 6/9] fs: dlm: move connect callback in node creation
  2020-10-19 18:59 [Cluster-devel] [PATCH dlm/next 0/9] fs: dlm: fixes and change listen socket handling Alexander Aring
                   ` (4 preceding siblings ...)
  2020-10-19 18:59 ` [Cluster-devel] [PATCH dlm/next 5/9] fs: dlm: handle non blocked connect event Alexander Aring
@ 2020-10-19 18:59 ` Alexander Aring
  2020-10-19 18:59 ` [Cluster-devel] [PATCH dlm/next 7/9] fs: dlm: move shutdown action to " Alexander Aring
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 10+ messages in thread
From: Alexander Aring @ 2020-10-19 18:59 UTC (permalink / raw)
  To: cluster-devel.redhat.com

This patch moves the assignment for the connect callback to the node
creation instead of assign some dummy functionality. The assignment
which connect functionality will be used will be detected according to
the configfs setting.

Signed-off-by: Alexander Aring <aahringo@redhat.com>
---
 fs/dlm/lowcomms.c | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c
index 70a216a20dbb9..e8657ae023654 100644
--- a/fs/dlm/lowcomms.c
+++ b/fs/dlm/lowcomms.c
@@ -142,6 +142,8 @@ DEFINE_STATIC_SRCU(connections_srcu);
 static void process_recv_sockets(struct work_struct *work);
 static void process_send_sockets(struct work_struct *work);
 
+static void sctp_connect_to_sock(struct connection *con);
+static void tcp_connect_to_sock(struct connection *con);
 
 /* This is deliberately very simple because most clusters have simple
    sequential nodeids, so we should be able to go straight to a connection
@@ -206,11 +208,15 @@ static struct connection *nodeid2con(int nodeid, gfp_t alloc)
 	if (con->nodeid) {
 		struct connection *zerocon = __find_con(0);
 
-		con->connect_action = zerocon->connect_action;
 		if (!con->rx_action)
 			con->rx_action = zerocon->rx_action;
 	}
 
+	if (dlm_config.ci_protocol == 0)
+		con->connect_action = tcp_connect_to_sock;
+	else
+		con->connect_action = sctp_connect_to_sock;
+
 	r = nodeid_hash(nodeid);
 
 	spin_lock(&connections_lock);
@@ -1009,7 +1015,6 @@ static void sctp_connect_to_sock(struct connection *con)
 	sock_set_mark(sock->sk, mark);
 
 	con->rx_action = receive_from_sock;
-	con->connect_action = sctp_connect_to_sock;
 	add_sock(sock, con);
 
 	/* Bind to all addresses. */
@@ -1107,7 +1112,6 @@ static void tcp_connect_to_sock(struct connection *con)
 	}
 
 	con->rx_action = receive_from_sock;
-	con->connect_action = tcp_connect_to_sock;
 	con->shutdown_action = dlm_tcp_shutdown;
 	add_sock(sock, con);
 
@@ -1195,7 +1199,6 @@ static struct socket *tcp_create_listen_sock(struct connection *con,
 	sock->sk->sk_user_data = con;
 	save_listen_callbacks(sock);
 	con->rx_action = accept_from_sock;
-	con->connect_action = tcp_connect_to_sock;
 	write_unlock_bh(&sock->sk->sk_callback_lock);
 
 	/* Bind to our port */
@@ -1278,7 +1281,6 @@ static int sctp_listen_for_all(void)
 	con->sock = sock;
 	con->sock->sk->sk_data_ready = lowcomms_data_ready;
 	con->rx_action = accept_from_sock;
-	con->connect_action = sctp_connect_to_sock;
 
 	write_unlock_bh(&sock->sk->sk_callback_lock);
 
-- 
2.26.2



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [Cluster-devel] [PATCH dlm/next 7/9] fs: dlm: move shutdown action to node creation
  2020-10-19 18:59 [Cluster-devel] [PATCH dlm/next 0/9] fs: dlm: fixes and change listen socket handling Alexander Aring
                   ` (5 preceding siblings ...)
  2020-10-19 18:59 ` [Cluster-devel] [PATCH dlm/next 6/9] fs: dlm: move connect callback in node creation Alexander Aring
@ 2020-10-19 18:59 ` Alexander Aring
  2020-10-19 18:59 ` [Cluster-devel] [PATCH dlm/next 8/9] fs: dlm: refactor sctp sock parameter Alexander Aring
  2020-10-19 18:59 ` [Cluster-devel] [PATCH dlm/next 9/9] fs: dlm: listen socket out of connection hash Alexander Aring
  8 siblings, 0 replies; 10+ messages in thread
From: Alexander Aring @ 2020-10-19 18:59 UTC (permalink / raw)
  To: cluster-devel.redhat.com

This patch move the assignment for the shutdown action callback to the
node creation functionality.

Signed-off-by: Alexander Aring <aahringo@redhat.com>
---
 fs/dlm/lowcomms.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c
index e8657ae023654..bae4125c22deb 100644
--- a/fs/dlm/lowcomms.c
+++ b/fs/dlm/lowcomms.c
@@ -144,6 +144,7 @@ static void process_send_sockets(struct work_struct *work);
 
 static void sctp_connect_to_sock(struct connection *con);
 static void tcp_connect_to_sock(struct connection *con);
+static void dlm_tcp_shutdown(struct connection *con);
 
 /* This is deliberately very simple because most clusters have simple
    sequential nodeids, so we should be able to go straight to a connection
@@ -212,10 +213,12 @@ static struct connection *nodeid2con(int nodeid, gfp_t alloc)
 			con->rx_action = zerocon->rx_action;
 	}
 
-	if (dlm_config.ci_protocol == 0)
+	if (dlm_config.ci_protocol == 0) {
 		con->connect_action = tcp_connect_to_sock;
-	else
+		con->shutdown_action = dlm_tcp_shutdown;
+	} else {
 		con->connect_action = sctp_connect_to_sock;
+	}
 
 	r = nodeid_hash(nodeid);
 
@@ -1112,7 +1115,6 @@ static void tcp_connect_to_sock(struct connection *con)
 	}
 
 	con->rx_action = receive_from_sock;
-	con->shutdown_action = dlm_tcp_shutdown;
 	add_sock(sock, con);
 
 	/* Bind to our cluster-known address connecting to avoid
-- 
2.26.2



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [Cluster-devel] [PATCH dlm/next 8/9] fs: dlm: refactor sctp sock parameter
  2020-10-19 18:59 [Cluster-devel] [PATCH dlm/next 0/9] fs: dlm: fixes and change listen socket handling Alexander Aring
                   ` (6 preceding siblings ...)
  2020-10-19 18:59 ` [Cluster-devel] [PATCH dlm/next 7/9] fs: dlm: move shutdown action to " Alexander Aring
@ 2020-10-19 18:59 ` Alexander Aring
  2020-10-19 18:59 ` [Cluster-devel] [PATCH dlm/next 9/9] fs: dlm: listen socket out of connection hash Alexander Aring
  8 siblings, 0 replies; 10+ messages in thread
From: Alexander Aring @ 2020-10-19 18:59 UTC (permalink / raw)
  To: cluster-devel.redhat.com

This patch refactors sctp_bind_addrs() to work with a socket parameter
instead of a connection parameter.

Signed-off-by: Alexander Aring <aahringo@redhat.com>
---
 fs/dlm/lowcomms.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c
index bae4125c22deb..f18d40ba42f97 100644
--- a/fs/dlm/lowcomms.c
+++ b/fs/dlm/lowcomms.c
@@ -947,7 +947,7 @@ static void writequeue_entry_complete(struct writequeue_entry *e, int completed)
 /*
  * sctp_bind_addrs - bind a SCTP socket to all our addresses
  */
-static int sctp_bind_addrs(struct connection *con, uint16_t port)
+static int sctp_bind_addrs(struct socket *sock, uint16_t port)
 {
 	struct sockaddr_storage localaddr;
 	struct sockaddr *addr = (struct sockaddr *)&localaddr;
@@ -958,9 +958,9 @@ static int sctp_bind_addrs(struct connection *con, uint16_t port)
 		make_sockaddr(&localaddr, port, &addr_len);
 
 		if (!i)
-			result = kernel_bind(con->sock, addr, addr_len);
+			result = kernel_bind(sock, addr, addr_len);
 		else
-			result = sock_bind_add(con->sock->sk, addr, addr_len);
+			result = sock_bind_add(sock->sk, addr, addr_len);
 
 		if (result < 0) {
 			log_print("Can't bind to %d addr number %d, %d.\n",
@@ -1021,7 +1021,7 @@ static void sctp_connect_to_sock(struct connection *con)
 	add_sock(sock, con);
 
 	/* Bind to all addresses. */
-	if (sctp_bind_addrs(con, 0))
+	if (sctp_bind_addrs(con->sock, 0))
 		goto bind_err;
 
 	make_sockaddr(&daddr, dlm_config.ci_tcp_port, &addr_len);
@@ -1287,7 +1287,7 @@ static int sctp_listen_for_all(void)
 	write_unlock_bh(&sock->sk->sk_callback_lock);
 
 	/* Bind to all addresses. */
-	if (sctp_bind_addrs(con, dlm_config.ci_tcp_port))
+	if (sctp_bind_addrs(con->sock, dlm_config.ci_tcp_port))
 		goto create_delsock;
 
 	result = sock->ops->listen(sock, 5);
-- 
2.26.2



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [Cluster-devel] [PATCH dlm/next 9/9] fs: dlm: listen socket out of connection hash
  2020-10-19 18:59 [Cluster-devel] [PATCH dlm/next 0/9] fs: dlm: fixes and change listen socket handling Alexander Aring
                   ` (7 preceding siblings ...)
  2020-10-19 18:59 ` [Cluster-devel] [PATCH dlm/next 8/9] fs: dlm: refactor sctp sock parameter Alexander Aring
@ 2020-10-19 18:59 ` Alexander Aring
  8 siblings, 0 replies; 10+ messages in thread
From: Alexander Aring @ 2020-10-19 18:59 UTC (permalink / raw)
  To: cluster-devel.redhat.com

This patch introduces a own connection structure for the listen socket
handling instead of handling the listen socket as normal connection
structure in the connection hash. We can remove some nodeid equals zero
validation checks, because this nodeid should not exists anymore inside
the node hash. This patch also removes the sock mutex in
accept_from_sock() function because this function can't occur in another
parallel context if it's scheduled on only one workqueue.

Signed-off-by: Alexander Aring <aahringo@redhat.com>
---
 fs/dlm/lowcomms.c | 180 ++++++++++++++++++++--------------------------
 1 file changed, 79 insertions(+), 101 deletions(-)

diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c
index f18d40ba42f97..11e5e92148fda 100644
--- a/fs/dlm/lowcomms.c
+++ b/fs/dlm/lowcomms.c
@@ -81,7 +81,6 @@ struct connection {
 #define CF_CONNECTED 10
 	struct list_head writequeue;  /* List of outgoing writequeue_entries */
 	spinlock_t writequeue_lock;
-	int (*rx_action) (struct connection *);	/* What to do when active */
 	void (*connect_action) (struct connection *);	/* What to do to connect */
 	void (*shutdown_action)(struct connection *con); /* What to do to shutdown */
 	int retries;
@@ -98,6 +97,11 @@ struct connection {
 };
 #define sock2con(x) ((struct connection *)(x)->sk_user_data)
 
+struct listen_connection {
+	struct socket *sock;
+	struct work_struct rwork;
+};
+
 /* An entry waiting to be sent */
 struct writequeue_entry {
 	struct list_head list;
@@ -127,6 +131,7 @@ static struct listen_sock_callbacks {
 static LIST_HEAD(dlm_node_addrs);
 static DEFINE_SPINLOCK(dlm_node_addrs_spin);
 
+static struct listen_connection listen_con;
 static struct sockaddr_storage *dlm_local_addr[DLM_MAX_ADDR_COUNT];
 static int dlm_local_count;
 static int dlm_allow_conn;
@@ -182,6 +187,11 @@ static struct connection *nodeid2con(int nodeid, gfp_t alloc)
 	struct connection *con, *tmp;
 	int r;
 
+	if (nodeid == 0) {
+		log_print("Invalid nodeid used for lookup\n");
+		return NULL;
+	}
+
 	con = __find_con(nodeid);
 	if (con || !alloc)
 		return con;
@@ -205,14 +215,6 @@ static struct connection *nodeid2con(int nodeid, gfp_t alloc)
 	INIT_WORK(&con->rwork, process_recv_sockets);
 	init_waitqueue_head(&con->shutdown_wait);
 
-	/* Setup action pointers for child sockets */
-	if (con->nodeid) {
-		struct connection *zerocon = __find_con(0);
-
-		if (!con->rx_action)
-			con->rx_action = zerocon->rx_action;
-	}
-
 	if (dlm_config.ci_protocol == 0) {
 		con->connect_action = tcp_connect_to_sock;
 		con->shutdown_action = dlm_tcp_shutdown;
@@ -420,6 +422,11 @@ static void lowcomms_data_ready(struct sock *sk)
 	read_unlock_bh(&sk->sk_callback_lock);
 }
 
+static void lowcomms_listen_data_ready(struct sock *sk)
+{
+	queue_work(recv_workqueue, &listen_con.rwork);
+}
+
 static void lowcomms_write_space(struct sock *sk)
 {
 	struct connection *con;
@@ -555,6 +562,21 @@ static void restore_callbacks(struct socket *sock)
 	write_unlock_bh(&sk->sk_callback_lock);
 }
 
+static void add_listen_sock(struct socket *sock, struct listen_connection *con)
+{
+	struct sock *sk = sock->sk;
+
+	write_lock_bh(&sk->sk_callback_lock);
+	save_listen_callbacks(sock);
+	con->sock = sock;
+
+	sk->sk_user_data = con;
+	sk->sk_allocation = GFP_NOFS;
+	/* Install a data_ready callback */
+	sk->sk_data_ready = lowcomms_listen_data_ready;
+	write_unlock_bh(&sk->sk_callback_lock);
+}
+
 /* Make a socket active */
 static void add_sock(struct socket *sock, struct connection *con)
 {
@@ -592,6 +614,15 @@ static void make_sockaddr(struct sockaddr_storage *saddr, uint16_t port,
 	memset((char *)saddr + *addr_len, 0, sizeof(struct sockaddr_storage) - *addr_len);
 }
 
+static void dlm_close_sock(struct socket **sock)
+{
+	if (*sock) {
+		restore_callbacks(*sock);
+		sock_release(*sock);
+		*sock = NULL;
+	}
+}
+
 /* Close a remote connection and tidy up */
 static void close_connection(struct connection *con, bool and_other,
 			     bool tx, bool rx)
@@ -608,11 +639,8 @@ static void close_connection(struct connection *con, bool and_other,
 	}
 
 	mutex_lock(&con->sock_mutex);
-	if (con->sock) {
-		restore_callbacks(con->sock);
-		sock_release(con->sock);
-		con->sock = NULL;
-	}
+	dlm_close_sock(&con->sock);
+
 	if (con->othercon && and_other) {
 		/* Will only re-enter once. */
 		close_connection(con->othercon, false, true, true);
@@ -708,11 +736,6 @@ static int receive_from_sock(struct connection *con)
 		goto out_close;
 	}
 
-	if (con->nodeid == 0) {
-		ret = -EINVAL;
-		goto out_close;
-	}
-
 	/* realloc if we get new buffer size to read out */
 	buflen = dlm_config.ci_buffer_size;
 	if (con->rx_buflen != buflen && con->rx_leftover <= buflen) {
@@ -784,7 +807,7 @@ static int receive_from_sock(struct connection *con)
 }
 
 /* Listening socket is busy, accept a connection */
-static int accept_from_sock(struct connection *con)
+static int accept_from_sock(struct listen_connection *con)
 {
 	int result;
 	struct sockaddr_storage peeraddr;
@@ -799,12 +822,8 @@ static int accept_from_sock(struct connection *con)
 		return -1;
 	}
 
-	mutex_lock_nested(&con->sock_mutex, 0);
-
-	if (!con->sock) {
-		mutex_unlock(&con->sock_mutex);
+	if (!con->sock)
 		return -ENOTCONN;
-	}
 
 	result = kernel_accept(con->sock, &newsock, O_NONBLOCK);
 	if (result < 0)
@@ -826,7 +845,6 @@ static int accept_from_sock(struct connection *con)
 		print_hex_dump_bytes("ss: ", DUMP_PREFIX_NONE, 
 				     b, sizeof(struct sockaddr_storage));
 		sock_release(newsock);
-		mutex_unlock(&con->sock_mutex);
 		return -1;
 	}
 
@@ -845,7 +863,8 @@ static int accept_from_sock(struct connection *con)
 		result = -ENOMEM;
 		goto accept_err;
 	}
-	mutex_lock_nested(&newcon->sock_mutex, 1);
+
+	mutex_lock(&newcon->sock_mutex);
 	if (newcon->sock) {
 		struct connection *othercon = newcon->othercon;
 
@@ -869,7 +888,6 @@ static int accept_from_sock(struct connection *con)
 			}
 
 			othercon->nodeid = nodeid;
-			othercon->rx_action = receive_from_sock;
 			mutex_init(&othercon->sock_mutex);
 			INIT_LIST_HEAD(&othercon->writequeue);
 			spin_lock_init(&othercon->writequeue_lock);
@@ -882,14 +900,13 @@ static int accept_from_sock(struct connection *con)
 			close_connection(othercon, false, true, false);
 		}
 
-		mutex_lock_nested(&othercon->sock_mutex, 2);
+		mutex_lock_nested(&othercon->sock_mutex, 1);
 		newcon->othercon = othercon;
 		add_sock(newsock, othercon);
 		addcon = othercon;
 		mutex_unlock(&othercon->sock_mutex);
 	}
 	else {
-		newcon->rx_action = receive_from_sock;
 		/* accept copies the sk after we've saved the callbacks, so we
 		   don't want to save them a second time or comm errors will
 		   result in calling sk_error_report recursively. */
@@ -906,12 +923,10 @@ static int accept_from_sock(struct connection *con)
 	 */
 	if (!test_and_set_bit(CF_READ_PENDING, &addcon->flags))
 		queue_work(recv_workqueue, &addcon->rwork);
-	mutex_unlock(&con->sock_mutex);
 
 	return 0;
 
 accept_err:
-	mutex_unlock(&con->sock_mutex);
 	if (newsock)
 		sock_release(newsock);
 
@@ -984,11 +999,6 @@ static void sctp_connect_to_sock(struct connection *con)
 	struct socket *sock;
 	unsigned int mark;
 
-	if (con->nodeid == 0) {
-		log_print("attempt to connect sock 0 foiled");
-		return;
-	}
-
 	dlm_comm_mark(con->nodeid, &mark);
 
 	mutex_lock(&con->sock_mutex);
@@ -1017,7 +1027,6 @@ static void sctp_connect_to_sock(struct connection *con)
 
 	sock_set_mark(sock->sk, mark);
 
-	con->rx_action = receive_from_sock;
 	add_sock(sock, con);
 
 	/* Bind to all addresses. */
@@ -1084,11 +1093,6 @@ static void tcp_connect_to_sock(struct connection *con)
 	unsigned int mark;
 	int result;
 
-	if (con->nodeid == 0) {
-		log_print("attempt to connect sock 0 foiled");
-		return;
-	}
-
 	dlm_comm_mark(con->nodeid, &mark);
 
 	mutex_lock(&con->sock_mutex);
@@ -1114,7 +1118,6 @@ static void tcp_connect_to_sock(struct connection *con)
 		goto out_err;
 	}
 
-	con->rx_action = receive_from_sock;
 	add_sock(sock, con);
 
 	/* Bind to our cluster-known address connecting to avoid
@@ -1170,8 +1173,11 @@ static void tcp_connect_to_sock(struct connection *con)
 	return;
 }
 
-static struct socket *tcp_create_listen_sock(struct connection *con,
-					     struct sockaddr_storage *saddr)
+/* On error caller must run dlm_close_sock() for the
+ * listen connection socket.
+ */
+static int tcp_create_listen_sock(struct listen_connection *con,
+				  struct sockaddr_storage *saddr)
 {
 	struct socket *sock = NULL;
 	int result = 0;
@@ -1197,20 +1203,13 @@ static struct socket *tcp_create_listen_sock(struct connection *con,
 
 	sock_set_reuseaddr(sock->sk);
 
-	write_lock_bh(&sock->sk->sk_callback_lock);
-	sock->sk->sk_user_data = con;
-	save_listen_callbacks(sock);
-	con->rx_action = accept_from_sock;
-	write_unlock_bh(&sock->sk->sk_callback_lock);
+	add_listen_sock(sock, con);
 
 	/* Bind to our port */
 	make_sockaddr(saddr, dlm_config.ci_tcp_port, &addr_len);
 	result = sock->ops->bind(sock, (struct sockaddr *) saddr, addr_len);
 	if (result < 0) {
 		log_print("Can't bind to port %d", dlm_config.ci_tcp_port);
-		sock_release(sock);
-		sock = NULL;
-		con->sock = NULL;
 		goto create_out;
 	}
 	sock_set_keepalive(sock->sk);
@@ -1218,13 +1217,13 @@ static struct socket *tcp_create_listen_sock(struct connection *con,
 	result = sock->ops->listen(sock, 5);
 	if (result < 0) {
 		log_print("Can't listen on port %d", dlm_config.ci_tcp_port);
-		sock_release(sock);
-		sock = NULL;
 		goto create_out;
 	}
 
+	return 0;
+
 create_out:
-	return sock;
+	return result;
 }
 
 /* Get local addresses */
@@ -1253,15 +1252,14 @@ static void deinit_local(void)
 		kfree(dlm_local_addr[i]);
 }
 
-/* Initialise SCTP socket and bind to all interfaces */
-static int sctp_listen_for_all(void)
+/* Initialise SCTP socket and bind to all interfaces
+ * On error caller must run dlm_close_sock() for the
+ * listen connection socket.
+ */
+static int sctp_listen_for_all(struct listen_connection *con)
 {
 	struct socket *sock = NULL;
 	int result = -EINVAL;
-	struct connection *con = nodeid2con(0, GFP_NOFS);
-
-	if (!con)
-		return -ENOMEM;
 
 	log_print("Using SCTP for communications");
 
@@ -1276,44 +1274,27 @@ static int sctp_listen_for_all(void)
 	sock_set_mark(sock->sk, dlm_config.ci_mark);
 	sctp_sock_set_nodelay(sock->sk);
 
-	write_lock_bh(&sock->sk->sk_callback_lock);
-	/* Init con struct */
-	sock->sk->sk_user_data = con;
-	save_listen_callbacks(sock);
-	con->sock = sock;
-	con->sock->sk->sk_data_ready = lowcomms_data_ready;
-	con->rx_action = accept_from_sock;
-
-	write_unlock_bh(&sock->sk->sk_callback_lock);
+	add_listen_sock(sock, con);
 
 	/* Bind to all addresses. */
-	if (sctp_bind_addrs(con->sock, dlm_config.ci_tcp_port))
-		goto create_delsock;
+	result = sctp_bind_addrs(con->sock, dlm_config.ci_tcp_port);
+	if (result < 0)
+		goto out;
 
 	result = sock->ops->listen(sock, 5);
 	if (result < 0) {
 		log_print("Can't set socket listening");
-		goto create_delsock;
+		goto out;
 	}
 
 	return 0;
 
-create_delsock:
-	sock_release(sock);
-	con->sock = NULL;
 out:
 	return result;
 }
 
 static int tcp_listen_for_all(void)
 {
-	struct socket *sock = NULL;
-	struct connection *con = nodeid2con(0, GFP_NOFS);
-	int result = -EINVAL;
-
-	if (!con)
-		return -ENOMEM;
-
 	/* We don't support multi-homed hosts */
 	if (dlm_local_addr[1] != NULL) {
 		log_print("TCP protocol can't handle multi-homed hosts, "
@@ -1323,16 +1304,7 @@ static int tcp_listen_for_all(void)
 
 	log_print("Using TCP for communications");
 
-	sock = tcp_create_listen_sock(con, dlm_local_addr[0]);
-	if (sock) {
-		add_sock(sock, con);
-		result = 0;
-	}
-	else {
-		result = -EADDRINUSE;
-	}
-
-	return result;
+	return tcp_create_listen_sock(&listen_con, dlm_local_addr[0]);
 }
 
 
@@ -1551,10 +1523,15 @@ static void process_recv_sockets(struct work_struct *work)
 
 	clear_bit(CF_READ_PENDING, &con->flags);
 	do {
-		err = con->rx_action(con);
+		err = receive_from_sock(con);
 	} while (!err);
 }
 
+static void process_listen_recv_socket(struct work_struct *work)
+{
+	accept_from_sock(&listen_con);
+}
+
 /* Send workqueue function */
 static void process_send_sockets(struct work_struct *work)
 {
@@ -1688,6 +1665,8 @@ void dlm_lowcomms_stop(void)
 	if (send_workqueue)
 		flush_workqueue(send_workqueue);
 
+	dlm_close_sock(&listen_con.sock);
+
 	foreach_conn(shutdown_conn);
 	work_flush();
 	foreach_conn(free_conn);
@@ -1698,7 +1677,6 @@ void dlm_lowcomms_stop(void)
 int dlm_lowcomms_start(void)
 {
 	int error = -EINVAL;
-	struct connection *con;
 	int i;
 
 	for (i = 0; i < CONN_HASH_SIZE; i++)
@@ -1711,6 +1689,8 @@ int dlm_lowcomms_start(void)
 		goto fail;
 	}
 
+	INIT_WORK(&listen_con.rwork, process_listen_recv_socket);
+
 	error = work_start();
 	if (error)
 		goto fail;
@@ -1721,7 +1701,7 @@ int dlm_lowcomms_start(void)
 	if (dlm_config.ci_protocol == 0)
 		error = tcp_listen_for_all();
 	else
-		error = sctp_listen_for_all();
+		error = sctp_listen_for_all(&listen_con);
 	if (error)
 		goto fail_unlisten;
 
@@ -1729,9 +1709,7 @@ int dlm_lowcomms_start(void)
 
 fail_unlisten:
 	dlm_allow_conn = 0;
-	con = nodeid2con(0,0);
-	if (con)
-		free_conn(con);
+	dlm_close_sock(&listen_con.sock);
 fail:
 	return error;
 }
-- 
2.26.2



^ permalink raw reply related	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2020-10-19 18:59 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-10-19 18:59 [Cluster-devel] [PATCH dlm/next 0/9] fs: dlm: fixes and change listen socket handling Alexander Aring
2020-10-19 18:59 ` [Cluster-devel] [PATCH dlm/next 1/9] fs: dlm: fix proper srcu api call Alexander Aring
2020-10-19 18:59 ` [Cluster-devel] [PATCH dlm/next 2/9] fs: dlm: define max send buffer Alexander Aring
2020-10-19 18:59 ` [Cluster-devel] [PATCH dlm/next 3/9] fs: dlm: add get buffer error handling Alexander Aring
2020-10-19 18:59 ` [Cluster-devel] [PATCH dlm/next 4/9] fs: dlm: flush othercon at close Alexander Aring
2020-10-19 18:59 ` [Cluster-devel] [PATCH dlm/next 5/9] fs: dlm: handle non blocked connect event Alexander Aring
2020-10-19 18:59 ` [Cluster-devel] [PATCH dlm/next 6/9] fs: dlm: move connect callback in node creation Alexander Aring
2020-10-19 18:59 ` [Cluster-devel] [PATCH dlm/next 7/9] fs: dlm: move shutdown action to " Alexander Aring
2020-10-19 18:59 ` [Cluster-devel] [PATCH dlm/next 8/9] fs: dlm: refactor sctp sock parameter Alexander Aring
2020-10-19 18:59 ` [Cluster-devel] [PATCH dlm/next 9/9] fs: dlm: listen socket out of connection hash Alexander Aring

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.