]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
dlm: use SHUT_RDWR for SCTP shutdown
authorAlexander Aring <aahringo@redhat.com>
Tue, 29 Apr 2025 20:29:11 +0000 (16:29 -0400)
committerDavid Teigland <teigland@redhat.com>
Wed, 30 Apr 2025 14:26:34 +0000 (09:26 -0500)
Currently SCTP shutdown() call gets stuck because there is no incoming
EOF indicator on its socket. On the peer side the EOF indicator as
recvmsg() returns 0 will be triggered as mechanism to flush the socket
queue on the receive side. In SCTP recvmsg() function sctp_recvmsg() we
can see that only if sk_shutdown has the bit RCV_SHUTDOWN set SCTP will
recvmsg() will return EOF. The RCV_SHUTDOWN bit will only be set when
shutdown with SHUT_RD is called. We use now SHUT_RDWR to also get a EOF
indicator from recvmsg() call on the shutdown() initiator.

SCTP does not support half closed sockets and the semantic of SHUT_WR is
different here, it seems that calling SHUT_WR on sctp sockets keeps the
socket open to have the possibility to do some specific SCTP operations on
it that we don't do here.

There exists still a difference in the limitations of TCP vs SCTP in
case if we are required to have a half closed socket functionality. This
was tried to archieve with DLM protocol changes in the past and
hopefully we really don't require half closed socket functionality.

Signed-off-by: Alexander Aring <aahringo@redhat.com>
Tested-by: Heming zhao <heming.zhao@suse.com>
Reviewed-by: Heming zhao <heming.zhao@suse.com>
Signed-off-by: David Teigland <teigland@redhat.com>
fs/dlm/lowcomms.c

index 50c42b368c839a9e43450ee30aab8e2d512f033d..e4373bce1bc2390882dd5a85243c305e939d20bd 100644 (file)
@@ -160,6 +160,7 @@ struct dlm_proto_ops {
        bool try_new_addr;
        const char *name;
        int proto;
+       int how;
 
        void (*sockopts)(struct socket *sock);
        int (*bind)(struct socket *sock);
@@ -810,7 +811,7 @@ static void shutdown_connection(struct connection *con, bool and_other)
                return;
        }
 
-       ret = kernel_sock_shutdown(con->sock, SHUT_WR);
+       ret = kernel_sock_shutdown(con->sock, dlm_proto_ops->how);
        up_read(&con->sock_lock);
        if (ret) {
                log_print("Connection %p failed to shutdown: %d will force close",
@@ -1858,6 +1859,7 @@ static int dlm_tcp_listen_bind(struct socket *sock)
 static const struct dlm_proto_ops dlm_tcp_ops = {
        .name = "TCP",
        .proto = IPPROTO_TCP,
+       .how = SHUT_WR,
        .sockopts = dlm_tcp_sockopts,
        .bind = dlm_tcp_bind,
        .listen_validate = dlm_tcp_listen_validate,
@@ -1896,6 +1898,7 @@ static void dlm_sctp_sockopts(struct socket *sock)
 static const struct dlm_proto_ops dlm_sctp_ops = {
        .name = "SCTP",
        .proto = IPPROTO_SCTP,
+       .how = SHUT_RDWR,
        .try_new_addr = true,
        .sockopts = dlm_sctp_sockopts,
        .bind = dlm_sctp_bind,