* [Cluster-devel] [PATCH AUTOSEL 5.13 15/59] fs: dlm: fix srcu read lock usage
[not found] <20210705152815.1520546-1-sashal@kernel.org>
@ 2021-07-05 15:27 ` Sasha Levin
2021-07-05 15:27 ` [Cluster-devel] [PATCH AUTOSEL 5.13 16/59] fs: dlm: reconnect if socket error report occurs Sasha Levin
` (4 subsequent siblings)
5 siblings, 0 replies; 6+ messages in thread
From: Sasha Levin @ 2021-07-05 15:27 UTC (permalink / raw)
To: cluster-devel.redhat.com
From: Alexander Aring <aahringo@redhat.com>
[ Upstream commit b38bc9c2b3171f4411d80015ecb876bc6f9bcd26 ]
This patch holds the srcu connection read lock in cases where we lookup
the connections and accessing it. We don't hold the srcu lock in workers
function where the scheduled worker is part of the connection itself.
The connection should not be freed if any worker is scheduled or
pending.
Signed-off-by: Alexander Aring <aahringo@redhat.com>
Signed-off-by: David Teigland <teigland@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
fs/dlm/lowcomms.c | 75 ++++++++++++++++++++++++++++++++---------------
1 file changed, 52 insertions(+), 23 deletions(-)
diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c
index 166e36fcf3e4..47bf99373f3e 100644
--- a/fs/dlm/lowcomms.c
+++ b/fs/dlm/lowcomms.c
@@ -113,6 +113,7 @@ struct writequeue_entry {
int len;
int end;
int users;
+ int idx; /* get()/commit() idx exchange */
struct connection *con;
};
@@ -163,21 +164,14 @@ static inline int nodeid_hash(int nodeid)
return nodeid & (CONN_HASH_SIZE-1);
}
-static struct connection *__find_con(int nodeid)
+static struct connection *__find_con(int nodeid, int r)
{
- int r, idx;
struct connection *con;
- r = nodeid_hash(nodeid);
-
- idx = srcu_read_lock(&connections_srcu);
hlist_for_each_entry_rcu(con, &connection_hash[r], list) {
- if (con->nodeid == nodeid) {
- srcu_read_unlock(&connections_srcu, idx);
+ if (con->nodeid == nodeid)
return con;
- }
}
- srcu_read_unlock(&connections_srcu, idx);
return NULL;
}
@@ -216,7 +210,8 @@ static struct connection *nodeid2con(int nodeid, gfp_t alloc)
struct connection *con, *tmp;
int r, ret;
- con = __find_con(nodeid);
+ r = nodeid_hash(nodeid);
+ con = __find_con(nodeid, r);
if (con || !alloc)
return con;
@@ -230,8 +225,6 @@ static struct connection *nodeid2con(int nodeid, gfp_t alloc)
return NULL;
}
- r = nodeid_hash(nodeid);
-
spin_lock(&connections_lock);
/* Because multiple workqueues/threads calls this function it can
* race on multiple cpu's. Instead of locking hot path __find_con()
@@ -239,7 +232,7 @@ static struct connection *nodeid2con(int nodeid, gfp_t alloc)
* under protection of connections_lock. If this is the case we
* abort our connection creation and return the existing connection.
*/
- tmp = __find_con(nodeid);
+ tmp = __find_con(nodeid, r);
if (tmp) {
spin_unlock(&connections_lock);
kfree(con->rx_buf);
@@ -256,15 +249,13 @@ static struct connection *nodeid2con(int nodeid, gfp_t alloc)
/* Loop round all connections */
static void foreach_conn(void (*conn_func)(struct connection *c))
{
- int i, idx;
+ int i;
struct connection *con;
- idx = srcu_read_lock(&connections_srcu);
for (i = 0; i < CONN_HASH_SIZE; i++) {
hlist_for_each_entry_rcu(con, &connection_hash[i], list)
conn_func(con);
}
- srcu_read_unlock(&connections_srcu, idx);
}
static struct dlm_node_addr *find_node_addr(int nodeid)
@@ -518,14 +509,21 @@ static void lowcomms_state_change(struct sock *sk)
int dlm_lowcomms_connect_node(int nodeid)
{
struct connection *con;
+ int idx;
if (nodeid == dlm_our_nodeid())
return 0;
+ idx = srcu_read_lock(&connections_srcu);
con = nodeid2con(nodeid, GFP_NOFS);
- if (!con)
+ if (!con) {
+ srcu_read_unlock(&connections_srcu, idx);
return -ENOMEM;
+ }
+
lowcomms_connect_sock(con);
+ srcu_read_unlock(&connections_srcu, idx);
+
return 0;
}
@@ -864,7 +862,7 @@ static int accept_from_sock(struct listen_connection *con)
int result;
struct sockaddr_storage peeraddr;
struct socket *newsock;
- int len;
+ int len, idx;
int nodeid;
struct connection *newcon;
struct connection *addcon;
@@ -907,8 +905,10 @@ static int accept_from_sock(struct listen_connection *con)
* the same time and the connections cross on the wire.
* In this case we store the incoming one in "othercon"
*/
+ idx = srcu_read_lock(&connections_srcu);
newcon = nodeid2con(nodeid, GFP_NOFS);
if (!newcon) {
+ srcu_read_unlock(&connections_srcu, idx);
result = -ENOMEM;
goto accept_err;
}
@@ -924,6 +924,7 @@ static int accept_from_sock(struct listen_connection *con)
if (!othercon) {
log_print("failed to allocate incoming socket");
mutex_unlock(&newcon->sock_mutex);
+ srcu_read_unlock(&connections_srcu, idx);
result = -ENOMEM;
goto accept_err;
}
@@ -932,6 +933,7 @@ static int accept_from_sock(struct listen_connection *con)
if (result < 0) {
kfree(othercon);
mutex_unlock(&newcon->sock_mutex);
+ srcu_read_unlock(&connections_srcu, idx);
goto accept_err;
}
@@ -966,6 +968,8 @@ static int accept_from_sock(struct listen_connection *con)
if (!test_and_set_bit(CF_READ_PENDING, &addcon->flags))
queue_work(recv_workqueue, &addcon->rwork);
+ srcu_read_unlock(&connections_srcu, idx);
+
return 0;
accept_err:
@@ -1403,7 +1407,9 @@ static struct writequeue_entry *new_wq_entry(struct connection *con, int len,
void *dlm_lowcomms_get_buffer(int nodeid, int len, gfp_t allocation, char **ppc)
{
+ struct writequeue_entry *e;
struct connection *con;
+ int idx;
if (len > DEFAULT_BUFFER_SIZE ||
len < sizeof(struct dlm_header)) {
@@ -1413,11 +1419,23 @@ void *dlm_lowcomms_get_buffer(int nodeid, int len, gfp_t allocation, char **ppc)
return NULL;
}
+ idx = srcu_read_lock(&connections_srcu);
con = nodeid2con(nodeid, allocation);
- if (!con)
+ if (!con) {
+ srcu_read_unlock(&connections_srcu, idx);
return NULL;
+ }
+
+ e = new_wq_entry(con, len, allocation, ppc);
+ if (!e) {
+ srcu_read_unlock(&connections_srcu, idx);
+ return NULL;
+ }
+
+ /* we assume if successful commit must called */
+ e->idx = idx;
- return new_wq_entry(con, len, allocation, ppc);
+ return e;
}
void dlm_lowcomms_commit_buffer(void *mh)
@@ -1435,10 +1453,12 @@ void dlm_lowcomms_commit_buffer(void *mh)
spin_unlock(&con->writequeue_lock);
queue_work(send_workqueue, &con->swork);
+ srcu_read_unlock(&connections_srcu, e->idx);
return;
out:
spin_unlock(&con->writequeue_lock);
+ srcu_read_unlock(&connections_srcu, e->idx);
return;
}
@@ -1532,8 +1552,10 @@ int dlm_lowcomms_close(int nodeid)
{
struct connection *con;
struct dlm_node_addr *na;
+ int idx;
log_print("closing connection to node %d", nodeid);
+ idx = srcu_read_lock(&connections_srcu);
con = nodeid2con(nodeid, 0);
if (con) {
set_bit(CF_CLOSE, &con->flags);
@@ -1542,6 +1564,7 @@ int dlm_lowcomms_close(int nodeid)
if (con->othercon)
clean_one_writequeue(con->othercon);
}
+ srcu_read_unlock(&connections_srcu, idx);
spin_lock(&dlm_node_addrs_spin);
na = find_node_addr(nodeid);
@@ -1621,6 +1644,8 @@ static void shutdown_conn(struct connection *con)
void dlm_lowcomms_shutdown(void)
{
+ int idx;
+
/* Set all the flags to prevent any
* socket activity.
*/
@@ -1633,7 +1658,9 @@ void dlm_lowcomms_shutdown(void)
dlm_close_sock(&listen_con.sock);
+ idx = srcu_read_lock(&connections_srcu);
foreach_conn(shutdown_conn);
+ srcu_read_unlock(&connections_srcu, idx);
}
static void _stop_conn(struct connection *con, bool and_other)
@@ -1682,7 +1709,7 @@ static void free_conn(struct connection *con)
static void work_flush(void)
{
- int ok, idx;
+ int ok;
int i;
struct connection *con;
@@ -1693,7 +1720,6 @@ static void work_flush(void)
flush_workqueue(recv_workqueue);
if (send_workqueue)
flush_workqueue(send_workqueue);
- idx = srcu_read_lock(&connections_srcu);
for (i = 0; i < CONN_HASH_SIZE && ok; i++) {
hlist_for_each_entry_rcu(con, &connection_hash[i],
list) {
@@ -1707,14 +1733,17 @@ static void work_flush(void)
}
}
}
- srcu_read_unlock(&connections_srcu, idx);
} while (!ok);
}
void dlm_lowcomms_stop(void)
{
+ int idx;
+
+ idx = srcu_read_lock(&connections_srcu);
work_flush();
foreach_conn(free_conn);
+ srcu_read_unlock(&connections_srcu, idx);
work_stop();
deinit_local();
}
--
2.30.2
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [Cluster-devel] [PATCH AUTOSEL 5.13 16/59] fs: dlm: reconnect if socket error report occurs
[not found] <20210705152815.1520546-1-sashal@kernel.org>
2021-07-05 15:27 ` [Cluster-devel] [PATCH AUTOSEL 5.13 15/59] fs: dlm: fix srcu read lock usage Sasha Levin
@ 2021-07-05 15:27 ` Sasha Levin
2021-07-05 15:27 ` [Cluster-devel] [PATCH AUTOSEL 5.13 17/59] fs: dlm: cancel work sync othercon Sasha Levin
` (3 subsequent siblings)
5 siblings, 0 replies; 6+ messages in thread
From: Sasha Levin @ 2021-07-05 15:27 UTC (permalink / raw)
To: cluster-devel.redhat.com
From: Alexander Aring <aahringo@redhat.com>
[ Upstream commit ba868d9deaab2bb1c09e50650127823925154802 ]
This patch will change the reconnect handling that if an error occurs
if a socket error callback is occurred. This will also handle reconnects
in a non blocking connecting case which is currently missing. If error
ECONNREFUSED is reported we delay the reconnect by one second.
Signed-off-by: Alexander Aring <aahringo@redhat.com>
Signed-off-by: David Teigland <teigland@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
fs/dlm/lowcomms.c | 60 ++++++++++++++++++++++++++++++-----------------
1 file changed, 39 insertions(+), 21 deletions(-)
diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c
index 47bf99373f3e..cdc50e9a5ab0 100644
--- a/fs/dlm/lowcomms.c
+++ b/fs/dlm/lowcomms.c
@@ -79,6 +79,8 @@ struct connection {
#define CF_CLOSING 8
#define CF_SHUTDOWN 9
#define CF_CONNECTED 10
+#define CF_RECONNECT 11
+#define CF_DELAY_CONNECT 12
struct list_head writequeue; /* List of outgoing writequeue_entries */
spinlock_t writequeue_lock;
void (*connect_action) (struct connection *); /* What to do to connect */
@@ -87,6 +89,7 @@ struct connection {
#define MAX_CONNECT_RETRIES 3
struct hlist_node list;
struct connection *othercon;
+ struct connection *sendcon;
struct work_struct rwork; /* Receive workqueue */
struct work_struct swork; /* Send workqueue */
wait_queue_head_t shutdown_wait; /* wait for graceful shutdown */
@@ -585,6 +588,22 @@ static void lowcomms_error_report(struct sock *sk)
dlm_config.ci_tcp_port, sk->sk_err,
sk->sk_err_soft);
}
+
+ /* below sendcon only handling */
+ if (test_bit(CF_IS_OTHERCON, &con->flags))
+ con = con->sendcon;
+
+ switch (sk->sk_err) {
+ case ECONNREFUSED:
+ set_bit(CF_DELAY_CONNECT, &con->flags);
+ break;
+ default:
+ break;
+ }
+
+ if (!test_and_set_bit(CF_RECONNECT, &con->flags))
+ queue_work(send_workqueue, &con->swork);
+
out:
read_unlock_bh(&sk->sk_callback_lock);
if (orig_report)
@@ -702,6 +721,8 @@ static void close_connection(struct connection *con, bool and_other,
con->rx_leftover = 0;
con->retries = 0;
clear_bit(CF_CONNECTED, &con->flags);
+ clear_bit(CF_DELAY_CONNECT, &con->flags);
+ clear_bit(CF_RECONNECT, &con->flags);
mutex_unlock(&con->sock_mutex);
clear_bit(CF_CLOSING, &con->flags);
}
@@ -840,18 +861,15 @@ static int receive_from_sock(struct connection *con)
out_close:
mutex_unlock(&con->sock_mutex);
- if (ret != -EAGAIN) {
- /* Reconnect when there is something to send */
+ if (ret == 0) {
close_connection(con, false, true, false);
- if (ret == 0) {
- log_print("connection %p got EOF from %d",
- con, con->nodeid);
- /* handling for tcp shutdown */
- clear_bit(CF_SHUTDOWN, &con->flags);
- wake_up(&con->shutdown_wait);
- /* signal to breaking receive worker */
- ret = -1;
- }
+ log_print("connection %p got EOF from %d",
+ con, con->nodeid);
+ /* handling for tcp shutdown */
+ clear_bit(CF_SHUTDOWN, &con->flags);
+ wake_up(&con->shutdown_wait);
+ /* signal to breaking receive worker */
+ ret = -1;
}
return ret;
}
@@ -939,6 +957,7 @@ static int accept_from_sock(struct listen_connection *con)
lockdep_set_subclass(&othercon->sock_mutex, 1);
newcon->othercon = othercon;
+ othercon->sendcon = newcon;
} else {
/* close other sock con if we have something new */
close_connection(othercon, false, true, false);
@@ -1503,7 +1522,7 @@ static void send_to_sock(struct connection *con)
cond_resched();
goto out;
} else if (ret < 0)
- goto send_error;
+ goto out;
}
/* Don't starve people filling buffers */
@@ -1520,14 +1539,6 @@ static void send_to_sock(struct connection *con)
mutex_unlock(&con->sock_mutex);
return;
-send_error:
- mutex_unlock(&con->sock_mutex);
- close_connection(con, false, false, true);
- /* Requeue the send work. When the work daemon runs again, it will try
- a new connection, then call this function again. */
- queue_work(send_workqueue, &con->swork);
- return;
-
out_connect:
mutex_unlock(&con->sock_mutex);
queue_work(send_workqueue, &con->swork);
@@ -1602,8 +1613,15 @@ static void process_send_sockets(struct work_struct *work)
struct connection *con = container_of(work, struct connection, swork);
clear_bit(CF_WRITE_PENDING, &con->flags);
- if (con->sock == NULL) /* not mutex protected so check it inside too */
+
+ if (test_and_clear_bit(CF_RECONNECT, &con->flags))
+ close_connection(con, false, false, true);
+
+ if (con->sock == NULL) { /* not mutex protected so check it inside too */
+ if (test_and_clear_bit(CF_DELAY_CONNECT, &con->flags))
+ msleep(1000);
con->connect_action(con);
+ }
if (!list_empty(&con->writequeue))
send_to_sock(con);
}
--
2.30.2
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [Cluster-devel] [PATCH AUTOSEL 5.13 17/59] fs: dlm: cancel work sync othercon
[not found] <20210705152815.1520546-1-sashal@kernel.org>
2021-07-05 15:27 ` [Cluster-devel] [PATCH AUTOSEL 5.13 15/59] fs: dlm: fix srcu read lock usage Sasha Levin
2021-07-05 15:27 ` [Cluster-devel] [PATCH AUTOSEL 5.13 16/59] fs: dlm: reconnect if socket error report occurs Sasha Levin
@ 2021-07-05 15:27 ` Sasha Levin
2021-07-05 15:27 ` [Cluster-devel] [PATCH AUTOSEL 5.13 18/59] fs: dlm: fix connection tcp EOF handling Sasha Levin
` (2 subsequent siblings)
5 siblings, 0 replies; 6+ messages in thread
From: Sasha Levin @ 2021-07-05 15:27 UTC (permalink / raw)
To: cluster-devel.redhat.com
From: Alexander Aring <aahringo@redhat.com>
[ Upstream commit c6aa00e3d20c2767ba3f57b64eb862572b9744b3 ]
These rx tx flags arguments are for signaling close_connection() from
which worker they are called. Obviously the receive worker cannot cancel
itself and vice versa for swork. For the othercon the receive worker
should only be used, however to avoid deadlocks we should pass the same
flags as the original close_connection() was called.
Signed-off-by: Alexander Aring <aahringo@redhat.com>
Signed-off-by: David Teigland <teigland@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
fs/dlm/lowcomms.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c
index cdc50e9a5ab0..138e8236ff6e 100644
--- a/fs/dlm/lowcomms.c
+++ b/fs/dlm/lowcomms.c
@@ -715,7 +715,7 @@ static void close_connection(struct connection *con, bool and_other,
if (con->othercon && and_other) {
/* Will only re-enter once. */
- close_connection(con->othercon, false, true, true);
+ close_connection(con->othercon, false, tx, rx);
}
con->rx_leftover = 0;
--
2.30.2
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [Cluster-devel] [PATCH AUTOSEL 5.13 18/59] fs: dlm: fix connection tcp EOF handling
[not found] <20210705152815.1520546-1-sashal@kernel.org>
` (2 preceding siblings ...)
2021-07-05 15:27 ` [Cluster-devel] [PATCH AUTOSEL 5.13 17/59] fs: dlm: cancel work sync othercon Sasha Levin
@ 2021-07-05 15:27 ` Sasha Levin
2021-07-05 15:27 ` [Cluster-devel] [PATCH AUTOSEL 5.13 22/59] fs: dlm: fix lowcomms_start error case Sasha Levin
2021-07-05 15:27 ` [Cluster-devel] [PATCH AUTOSEL 5.13 23/59] fs: dlm: fix memory leak when fenced Sasha Levin
5 siblings, 0 replies; 6+ messages in thread
From: Sasha Levin @ 2021-07-05 15:27 UTC (permalink / raw)
To: cluster-devel.redhat.com
From: Alexander Aring <aahringo@redhat.com>
[ Upstream commit 8aa31cbf20ad168c35dd83476629402aacbf5a44 ]
This patch fixes the EOF handling for TCP that if and EOF is received we
will close the socket next time the writequeue runs empty. This is a
half-closed socket functionality which doesn't exists in SCTP. The
midcomms layer will do a half closed socket functionality on DLM side to
solve this problem for the SCTP case. However there is still the last ack
flying around but other reset functionality will take care of it if it got
lost.
Signed-off-by: Alexander Aring <aahringo@redhat.com>
Signed-off-by: David Teigland <teigland@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
fs/dlm/lowcomms.c | 48 ++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 43 insertions(+), 5 deletions(-)
diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c
index 138e8236ff6e..b1dd850a4699 100644
--- a/fs/dlm/lowcomms.c
+++ b/fs/dlm/lowcomms.c
@@ -81,10 +81,13 @@ struct connection {
#define CF_CONNECTED 10
#define CF_RECONNECT 11
#define CF_DELAY_CONNECT 12
+#define CF_EOF 13
struct list_head writequeue; /* List of outgoing writequeue_entries */
spinlock_t writequeue_lock;
+ atomic_t writequeue_cnt;
void (*connect_action) (struct connection *); /* What to do to connect */
void (*shutdown_action)(struct connection *con); /* What to do to shutdown */
+ bool (*eof_condition)(struct connection *con); /* What to do to eof check */
int retries;
#define MAX_CONNECT_RETRIES 3
struct hlist_node list;
@@ -179,6 +182,11 @@ static struct connection *__find_con(int nodeid, int r)
return NULL;
}
+static bool tcp_eof_condition(struct connection *con)
+{
+ return atomic_read(&con->writequeue_cnt);
+}
+
static int dlm_con_init(struct connection *con, int nodeid)
{
con->rx_buflen = dlm_config.ci_buffer_size;
@@ -190,6 +198,7 @@ static int dlm_con_init(struct connection *con, int nodeid)
mutex_init(&con->sock_mutex);
INIT_LIST_HEAD(&con->writequeue);
spin_lock_init(&con->writequeue_lock);
+ atomic_set(&con->writequeue_cnt, 0);
INIT_WORK(&con->swork, process_send_sockets);
INIT_WORK(&con->rwork, process_recv_sockets);
init_waitqueue_head(&con->shutdown_wait);
@@ -197,6 +206,7 @@ static int dlm_con_init(struct connection *con, int nodeid)
if (dlm_config.ci_protocol == 0) {
con->connect_action = tcp_connect_to_sock;
con->shutdown_action = dlm_tcp_shutdown;
+ con->eof_condition = tcp_eof_condition;
} else {
con->connect_action = sctp_connect_to_sock;
}
@@ -723,6 +733,7 @@ static void close_connection(struct connection *con, bool and_other,
clear_bit(CF_CONNECTED, &con->flags);
clear_bit(CF_DELAY_CONNECT, &con->flags);
clear_bit(CF_RECONNECT, &con->flags);
+ clear_bit(CF_EOF, &con->flags);
mutex_unlock(&con->sock_mutex);
clear_bit(CF_CLOSING, &con->flags);
}
@@ -860,16 +871,26 @@ static int receive_from_sock(struct connection *con)
return -EAGAIN;
out_close:
- mutex_unlock(&con->sock_mutex);
if (ret == 0) {
- close_connection(con, false, true, false);
log_print("connection %p got EOF from %d",
con, con->nodeid);
- /* handling for tcp shutdown */
- clear_bit(CF_SHUTDOWN, &con->flags);
- wake_up(&con->shutdown_wait);
+
+ if (con->eof_condition && con->eof_condition(con)) {
+ set_bit(CF_EOF, &con->flags);
+ mutex_unlock(&con->sock_mutex);
+ } else {
+ mutex_unlock(&con->sock_mutex);
+ close_connection(con, false, true, false);
+
+ /* handling for tcp shutdown */
+ clear_bit(CF_SHUTDOWN, &con->flags);
+ wake_up(&con->shutdown_wait);
+ }
+
/* signal to breaking receive worker */
ret = -1;
+ } else {
+ mutex_unlock(&con->sock_mutex);
}
return ret;
}
@@ -1020,6 +1041,7 @@ static void writequeue_entry_complete(struct writequeue_entry *e, int completed)
if (e->len == 0 && e->users == 0) {
list_del(&e->list);
+ atomic_dec(&e->con->writequeue_cnt);
free_entry(e);
}
}
@@ -1416,6 +1438,7 @@ static struct writequeue_entry *new_wq_entry(struct connection *con, int len,
*ppc = page_address(e->page);
e->end += len;
+ atomic_inc(&con->writequeue_cnt);
spin_lock(&con->writequeue_lock);
list_add_tail(&e->list, &con->writequeue);
@@ -1535,6 +1558,21 @@ static void send_to_sock(struct connection *con)
writequeue_entry_complete(e, ret);
}
spin_unlock(&con->writequeue_lock);
+
+ /* close if we got EOF */
+ if (test_and_clear_bit(CF_EOF, &con->flags)) {
+ mutex_unlock(&con->sock_mutex);
+ close_connection(con, false, false, true);
+
+ /* handling for tcp shutdown */
+ clear_bit(CF_SHUTDOWN, &con->flags);
+ wake_up(&con->shutdown_wait);
+ } else {
+ mutex_unlock(&con->sock_mutex);
+ }
+
+ return;
+
out:
mutex_unlock(&con->sock_mutex);
return;
--
2.30.2
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [Cluster-devel] [PATCH AUTOSEL 5.13 22/59] fs: dlm: fix lowcomms_start error case
[not found] <20210705152815.1520546-1-sashal@kernel.org>
` (3 preceding siblings ...)
2021-07-05 15:27 ` [Cluster-devel] [PATCH AUTOSEL 5.13 18/59] fs: dlm: fix connection tcp EOF handling Sasha Levin
@ 2021-07-05 15:27 ` Sasha Levin
2021-07-05 15:27 ` [Cluster-devel] [PATCH AUTOSEL 5.13 23/59] fs: dlm: fix memory leak when fenced Sasha Levin
5 siblings, 0 replies; 6+ messages in thread
From: Sasha Levin @ 2021-07-05 15:27 UTC (permalink / raw)
To: cluster-devel.redhat.com
From: Alexander Aring <aahringo@redhat.com>
[ Upstream commit fcef0e6c27ce109d2c617aa12f0bfd9f7ff47d38 ]
This patch fixes the error path handling in lowcomms_start(). We need to
cleanup some static allocated data structure and cleanup possible
workqueue if these have started.
Signed-off-by: Alexander Aring <aahringo@redhat.com>
Signed-off-by: David Teigland <teigland@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
fs/dlm/lowcomms.c | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c
index b1dd850a4699..9bf920bee292 100644
--- a/fs/dlm/lowcomms.c
+++ b/fs/dlm/lowcomms.c
@@ -1666,10 +1666,15 @@ static void process_send_sockets(struct work_struct *work)
static void work_stop(void)
{
- if (recv_workqueue)
+ if (recv_workqueue) {
destroy_workqueue(recv_workqueue);
- if (send_workqueue)
+ recv_workqueue = NULL;
+ }
+
+ if (send_workqueue) {
destroy_workqueue(send_workqueue);
+ send_workqueue = NULL;
+ }
}
static int work_start(void)
@@ -1686,6 +1691,7 @@ static int work_start(void)
if (!send_workqueue) {
log_print("can't start dlm_send");
destroy_workqueue(recv_workqueue);
+ recv_workqueue = NULL;
return -ENOMEM;
}
@@ -1823,7 +1829,7 @@ int dlm_lowcomms_start(void)
error = work_start();
if (error)
- goto fail;
+ goto fail_local;
dlm_allow_conn = 1;
@@ -1840,6 +1846,9 @@ int dlm_lowcomms_start(void)
fail_unlisten:
dlm_allow_conn = 0;
dlm_close_sock(&listen_con.sock);
+ work_stop();
+fail_local:
+ deinit_local();
fail:
return error;
}
--
2.30.2
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [Cluster-devel] [PATCH AUTOSEL 5.13 23/59] fs: dlm: fix memory leak when fenced
[not found] <20210705152815.1520546-1-sashal@kernel.org>
` (4 preceding siblings ...)
2021-07-05 15:27 ` [Cluster-devel] [PATCH AUTOSEL 5.13 22/59] fs: dlm: fix lowcomms_start error case Sasha Levin
@ 2021-07-05 15:27 ` Sasha Levin
5 siblings, 0 replies; 6+ messages in thread
From: Sasha Levin @ 2021-07-05 15:27 UTC (permalink / raw)
To: cluster-devel.redhat.com
From: Alexander Aring <aahringo@redhat.com>
[ Upstream commit 700ab1c363c7b54c9ea3222379b33fc00ab02f7b ]
I got some kmemleak report when a node was fenced. The user space tool
dlm_controld will therefore run some rmdir() in dlm configfs which was
triggering some memleaks. This patch stores the sps and cms attributes
which stores some handling for subdirectories of the configfs cluster
entry and free them if they get released as the parent directory gets
freed.
unreferenced object 0xffff88810d9e3e00 (size 192):
comm "dlm_controld", pid 342, jiffies 4294698126 (age 55438.801s)
hex dump (first 32 bytes):
00 00 00 00 00 00 00 00 73 70 61 63 65 73 00 00 ........spaces..
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
backtrace:
[<00000000db8b640b>] make_cluster+0x5d/0x360
[<000000006a571db4>] configfs_mkdir+0x274/0x730
[<00000000b094501c>] vfs_mkdir+0x27e/0x340
[<0000000058b0adaf>] do_mkdirat+0xff/0x1b0
[<00000000d1ffd156>] do_syscall_64+0x40/0x80
[<00000000ab1408c8>] entry_SYSCALL_64_after_hwframe+0x44/0xae
unreferenced object 0xffff88810d9e3a00 (size 192):
comm "dlm_controld", pid 342, jiffies 4294698126 (age 55438.801s)
hex dump (first 32 bytes):
00 00 00 00 00 00 00 00 63 6f 6d 6d 73 00 00 00 ........comms...
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
backtrace:
[<00000000a7ef6ad2>] make_cluster+0x82/0x360
[<000000006a571db4>] configfs_mkdir+0x274/0x730
[<00000000b094501c>] vfs_mkdir+0x27e/0x340
[<0000000058b0adaf>] do_mkdirat+0xff/0x1b0
[<00000000d1ffd156>] do_syscall_64+0x40/0x80
[<00000000ab1408c8>] entry_SYSCALL_64_after_hwframe+0x44/0xae
Signed-off-by: Alexander Aring <aahringo@redhat.com>
Signed-off-by: David Teigland <teigland@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
fs/dlm/config.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/fs/dlm/config.c b/fs/dlm/config.c
index 88d95d96e36c..52bcda64172a 100644
--- a/fs/dlm/config.c
+++ b/fs/dlm/config.c
@@ -79,6 +79,9 @@ struct dlm_cluster {
unsigned int cl_new_rsb_count;
unsigned int cl_recover_callbacks;
char cl_cluster_name[DLM_LOCKSPACE_LEN];
+
+ struct dlm_spaces *sps;
+ struct dlm_comms *cms;
};
static struct dlm_cluster *config_item_to_cluster(struct config_item *i)
@@ -409,6 +412,9 @@ static struct config_group *make_cluster(struct config_group *g,
if (!cl || !sps || !cms)
goto fail;
+ cl->sps = sps;
+ cl->cms = cms;
+
config_group_init_type_name(&cl->group, name, &cluster_type);
config_group_init_type_name(&sps->ss_group, "spaces", &spaces_type);
config_group_init_type_name(&cms->cs_group, "comms", &comms_type);
@@ -458,6 +464,9 @@ static void drop_cluster(struct config_group *g, struct config_item *i)
static void release_cluster(struct config_item *i)
{
struct dlm_cluster *cl = config_item_to_cluster(i);
+
+ kfree(cl->sps);
+ kfree(cl->cms);
kfree(cl);
}
--
2.30.2
^ permalink raw reply related [flat|nested] 6+ messages in thread
end of thread, other threads:[~2021-07-05 15:27 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20210705152815.1520546-1-sashal@kernel.org>
2021-07-05 15:27 ` [Cluster-devel] [PATCH AUTOSEL 5.13 15/59] fs: dlm: fix srcu read lock usage Sasha Levin
2021-07-05 15:27 ` [Cluster-devel] [PATCH AUTOSEL 5.13 16/59] fs: dlm: reconnect if socket error report occurs Sasha Levin
2021-07-05 15:27 ` [Cluster-devel] [PATCH AUTOSEL 5.13 17/59] fs: dlm: cancel work sync othercon Sasha Levin
2021-07-05 15:27 ` [Cluster-devel] [PATCH AUTOSEL 5.13 18/59] fs: dlm: fix connection tcp EOF handling Sasha Levin
2021-07-05 15:27 ` [Cluster-devel] [PATCH AUTOSEL 5.13 22/59] fs: dlm: fix lowcomms_start error case Sasha Levin
2021-07-05 15:27 ` [Cluster-devel] [PATCH AUTOSEL 5.13 23/59] fs: dlm: fix memory leak when fenced Sasha Levin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).