From: Stefan Metzmacher Date: Wed, 27 Aug 2025 13:54:35 +0000 (+0200) Subject: smb: server: make consitent use of spin_lock_irq{save,restore}() in transport_rdma.c X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=8aa23bae607e3bd5ced892afc26bfbe8945f531b;p=thirdparty%2Fkernel%2Fstable.git smb: server: make consitent use of spin_lock_irq{save,restore}() in transport_rdma.c There is a mix of using spin_lock() and spin_lock_irq(), which is confusing as IB_POLL_WORKQUEUE is used and no code would be called from any interrupt. So using spin_lock() or even mutexes would be ok. But we'll soon share common code with the client, which uses IB_POLL_SOFTIRQ. And Documentation/kernel-hacking/locking.rst section "Cheat Sheet For Locking" says: - Otherwise (== data can be touched in an interrupt), use spin_lock_irqsave() and spin_unlock_irqrestore(). So in order to keep it simple and safe we use that version now. It will help merging functions into common code and have consistent locking in all cases. Acked-by: Namjae Jeon Cc: Steve French Cc: Tom Talpey Cc: linux-cifs@vger.kernel.org Cc: samba-technical@lists.samba.org Signed-off-by: Stefan Metzmacher Signed-off-by: Steve French --- diff --git a/fs/smb/server/transport_rdma.c b/fs/smb/server/transport_rdma.c index ba4dfdcb321a3..f9734d7025b43 100644 --- a/fs/smb/server/transport_rdma.c +++ b/fs/smb/server/transport_rdma.c @@ -150,21 +150,24 @@ static struct smbdirect_recv_io *get_free_recvmsg(struct smbdirect_socket *sc) { struct smbdirect_recv_io *recvmsg = NULL; + unsigned long flags; - spin_lock(&sc->recv_io.free.lock); + spin_lock_irqsave(&sc->recv_io.free.lock, flags); if (!list_empty(&sc->recv_io.free.list)) { recvmsg = list_first_entry(&sc->recv_io.free.list, struct smbdirect_recv_io, list); list_del(&recvmsg->list); } - spin_unlock(&sc->recv_io.free.lock); + spin_unlock_irqrestore(&sc->recv_io.free.lock, flags); return recvmsg; } static void put_recvmsg(struct smbdirect_socket *sc, struct smbdirect_recv_io *recvmsg) { + unsigned long flags; + if (likely(recvmsg->sge.length != 0)) { ib_dma_unmap_single(sc->ib.dev, recvmsg->sge.addr, @@ -173,9 +176,9 @@ static void put_recvmsg(struct smbdirect_socket *sc, recvmsg->sge.length = 0; } - spin_lock(&sc->recv_io.free.lock); + spin_lock_irqsave(&sc->recv_io.free.lock, flags); list_add(&recvmsg->list, &sc->recv_io.free.list); - spin_unlock(&sc->recv_io.free.lock); + spin_unlock_irqrestore(&sc->recv_io.free.lock, flags); queue_work(sc->workqueue, &sc->recv_io.posted.refill_work); } @@ -184,7 +187,9 @@ static void enqueue_reassembly(struct smbdirect_socket *sc, struct smbdirect_recv_io *recvmsg, int data_length) { - spin_lock(&sc->recv_io.reassembly.lock); + unsigned long flags; + + spin_lock_irqsave(&sc->recv_io.reassembly.lock, flags); list_add_tail(&recvmsg->list, &sc->recv_io.reassembly.list); sc->recv_io.reassembly.queue_length++; /* @@ -195,7 +200,7 @@ static void enqueue_reassembly(struct smbdirect_socket *sc, */ virt_wmb(); sc->recv_io.reassembly.data_length += data_length; - spin_unlock(&sc->recv_io.reassembly.lock); + spin_unlock_irqrestore(&sc->recv_io.reassembly.lock, flags); } static struct smbdirect_recv_io *get_first_reassembly(struct smbdirect_socket *sc) @@ -468,14 +473,16 @@ static void free_transport(struct smb_direct_transport *t) ksmbd_debug(RDMA, "drain the reassembly queue\n"); do { - spin_lock(&sc->recv_io.reassembly.lock); + unsigned long flags; + + spin_lock_irqsave(&sc->recv_io.reassembly.lock, flags); recvmsg = get_first_reassembly(sc); if (recvmsg) { list_del(&recvmsg->list); - spin_unlock(&sc->recv_io.reassembly.lock); + spin_unlock_irqrestore(&sc->recv_io.reassembly.lock, flags); put_recvmsg(sc, recvmsg); } else { - spin_unlock(&sc->recv_io.reassembly.lock); + spin_unlock_irqrestore(&sc->recv_io.reassembly.lock, flags); } } while (recvmsg); sc->recv_io.reassembly.data_length = 0; @@ -768,6 +775,7 @@ again: if (sc->recv_io.reassembly.data_length >= size) { int queue_length; int queue_removed = 0; + unsigned long flags; /* * Need to make sure reassembly_data_length is read before @@ -823,9 +831,9 @@ again: if (queue_length) { list_del(&recvmsg->list); } else { - spin_lock_irq(&sc->recv_io.reassembly.lock); + spin_lock_irqsave(&sc->recv_io.reassembly.lock, flags); list_del(&recvmsg->list); - spin_unlock_irq(&sc->recv_io.reassembly.lock); + spin_unlock_irqrestore(&sc->recv_io.reassembly.lock, flags); } queue_removed++; put_recvmsg(sc, recvmsg); @@ -838,10 +846,10 @@ again: data_read += to_copy; } - spin_lock_irq(&sc->recv_io.reassembly.lock); + spin_lock_irqsave(&sc->recv_io.reassembly.lock, flags); sc->recv_io.reassembly.data_length -= data_read; sc->recv_io.reassembly.queue_length -= queue_removed; - spin_unlock_irq(&sc->recv_io.reassembly.lock); + spin_unlock_irqrestore(&sc->recv_io.reassembly.lock, flags); sc->recv_io.reassembly.first_entry_offset = offset; ksmbd_debug(RDMA, @@ -2107,6 +2115,7 @@ static int smb_direct_prepare(struct ksmbd_transport *t) struct smbdirect_socket_parameters *sp = &sc->parameters; struct smbdirect_recv_io *recvmsg; struct smbdirect_negotiate_req *req; + unsigned long flags; int ret; /* @@ -2153,10 +2162,10 @@ static int smb_direct_prepare(struct ksmbd_transport *t) ret = smb_direct_send_negotiate_response(sc, ret); out: - spin_lock_irq(&sc->recv_io.reassembly.lock); + spin_lock_irqsave(&sc->recv_io.reassembly.lock, flags); sc->recv_io.reassembly.queue_length--; list_del(&recvmsg->list); - spin_unlock_irq(&sc->recv_io.reassembly.lock); + spin_unlock_irqrestore(&sc->recv_io.reassembly.lock, flags); put_recvmsg(sc, recvmsg); return ret;