]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
smb: client: let smbd_post_send_iter() call ib_dma_map_single() for the header first
authorStefan Metzmacher <metze@samba.org>
Sun, 14 Sep 2025 22:55:31 +0000 (00:55 +0200)
committerSteve French <stfrench@microsoft.com>
Sun, 28 Sep 2025 23:29:51 +0000 (18:29 -0500)
This will simplify further changes, the important part is that
request->num_sge >= 1 is only set if request->sge[0].* is valid.

Note that ib_dma_sync_single_for_device() is called in
smbd_post_send() for each sge, so the device will still
see the packet header even if it's modified after calling
ib_dma_map_single().

Cc: Steve French <smfrench@gmail.com>
Cc: Tom Talpey <tom@talpey.com>
Cc: Long Li <longli@microsoft.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Cc: linux-cifs@vger.kernel.org
Cc: samba-technical@lists.samba.org
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
fs/smb/client/smbdirect.c

index 1d81ead875d0aaef2f699a700319621d81dbe1b2..316f398c70f4b541a71dd8d97886bdce34a34496 100644 (file)
@@ -1158,10 +1158,30 @@ wait_send_queue:
        request->socket = sc;
        memset(request->sge, 0, sizeof(request->sge));
 
+       /* Map the packet to DMA */
+       header_length = sizeof(struct smbdirect_data_transfer);
+       /* If this is a packet without payload, don't send padding */
+       if (!iter)
+               header_length = offsetof(struct smbdirect_data_transfer, padding);
+
+       packet = smbdirect_send_io_payload(request);
+       request->sge[0].addr = ib_dma_map_single(sc->ib.dev,
+                                                (void *)packet,
+                                                header_length,
+                                                DMA_TO_DEVICE);
+       if (ib_dma_mapping_error(sc->ib.dev, request->sge[0].addr)) {
+               rc = -EIO;
+               goto err_dma;
+       }
+
+       request->sge[0].length = header_length;
+       request->sge[0].lkey = sc->ib.pd->local_dma_lkey;
+       request->num_sge = 1;
+
        /* Fill in the data payload to find out how much data we can add */
        if (iter) {
                struct smb_extract_to_rdma extract = {
-                       .nr_sge         = 1,
+                       .nr_sge         = request->num_sge,
                        .max_sge        = SMBDIRECT_SEND_IO_MAX_SGE,
                        .sge            = request->sge,
                        .device         = sc->ib.dev,
@@ -1180,11 +1200,9 @@ wait_send_queue:
                *_remaining_data_length -= data_length;
        } else {
                data_length = 0;
-               request->num_sge = 1;
        }
 
        /* Fill in the packet header */
-       packet = smbdirect_send_io_payload(request);
        packet->credits_requested = cpu_to_le16(sp->send_credit_target);
 
        new_credits = manage_credits_prior_sending(sc);
@@ -1211,25 +1229,6 @@ wait_send_queue:
                     le32_to_cpu(packet->data_length),
                     le32_to_cpu(packet->remaining_data_length));
 
-       /* Map the packet to DMA */
-       header_length = sizeof(struct smbdirect_data_transfer);
-       /* If this is a packet without payload, don't send padding */
-       if (!data_length)
-               header_length = offsetof(struct smbdirect_data_transfer, padding);
-
-       request->sge[0].addr = ib_dma_map_single(sc->ib.dev,
-                                                (void *)packet,
-                                                header_length,
-                                                DMA_TO_DEVICE);
-       if (ib_dma_mapping_error(sc->ib.dev, request->sge[0].addr)) {
-               rc = -EIO;
-               request->sge[0].addr = 0;
-               goto err_dma;
-       }
-
-       request->sge[0].length = header_length;
-       request->sge[0].lkey = sc->ib.pd->local_dma_lkey;
-
        rc = smbd_post_send(sc, request);
        if (!rc)
                return 0;