Skip to content

Commit

Permalink
fs: dlm: fix connection tcp EOF handling
Browse files Browse the repository at this point in the history
[ Upstream commit 8aa31cb ]

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>
  • Loading branch information
Alexander Aring authored and gregkh committed Jul 14, 2021
1 parent 38ef638 commit 871166f
Showing 1 changed file with 43 additions and 5 deletions.
48 changes: 43 additions & 5 deletions fs/dlm/lowcomms.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -190,13 +198,15 @@ 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);

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;
}
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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);
}
}
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 871166f

Please sign in to comment.