also merged into github tree used by buildbot http://smb3-test-rhel-75.southcentralus.cloudapp.azure.com/#/builders/2/builds/342 On Thu, Apr 2, 2020 at 11:08 PM Steve French <smfrench@xxxxxxxxx> wrote: > > tentatively merged into cifs-2.6.git for-next pending more testing > > On Thu, Apr 2, 2020 at 3:57 PM longli--- via samba-technical > <samba-technical@xxxxxxxxxxxxxxx> wrote: > > > > From: Long Li <longli@xxxxxxxxxxxxx> > > > > When processing errors from ib_post_send(), the transport state needs to be > > rolled back to the condition before the error. > > > > Refactor the old code to make it easy to roll back on IB errors, and fix this. > > > > Signed-off-by: Long Li <longli@xxxxxxxxxxxxx> > > --- > > > > change in v2: rebased > > > > fs/cifs/smbdirect.c | 220 +++++++++++++++++++------------------------- > > 1 file changed, 97 insertions(+), 123 deletions(-) > > > > diff --git a/fs/cifs/smbdirect.c b/fs/cifs/smbdirect.c > > index fa52bf3e0236..dd3e119da296 100644 > > --- a/fs/cifs/smbdirect.c > > +++ b/fs/cifs/smbdirect.c > > @@ -800,41 +800,91 @@ static int manage_keep_alive_before_sending(struct smbd_connection *info) > > return 0; > > } > > > > -/* > > - * Build and prepare the SMBD packet header > > - * This function waits for avaialbe send credits and build a SMBD packet > > - * header. The caller then optional append payload to the packet after > > - * the header > > - * intput values > > - * size: the size of the payload > > - * remaining_data_length: remaining data to send if this is part of a > > - * fragmented packet > > - * output values > > - * request_out: the request allocated from this function > > - * return values: 0 on success, otherwise actual error code returned > > - */ > > -static int smbd_create_header(struct smbd_connection *info, > > - int size, int remaining_data_length, > > - struct smbd_request **request_out) > > +/* Post the send request */ > > +static int smbd_post_send(struct smbd_connection *info, > > + struct smbd_request *request) > > +{ > > + struct ib_send_wr send_wr; > > + int rc, i; > > + > > + for (i = 0; i < request->num_sge; i++) { > > + log_rdma_send(INFO, > > + "rdma_request sge[%d] addr=%llu length=%u\n", > > + i, request->sge[i].addr, request->sge[i].length); > > + ib_dma_sync_single_for_device( > > + info->id->device, > > + request->sge[i].addr, > > + request->sge[i].length, > > + DMA_TO_DEVICE); > > + } > > + > > + request->cqe.done = send_done; > > + > > + send_wr.next = NULL; > > + send_wr.wr_cqe = &request->cqe; > > + send_wr.sg_list = request->sge; > > + send_wr.num_sge = request->num_sge; > > + send_wr.opcode = IB_WR_SEND; > > + send_wr.send_flags = IB_SEND_SIGNALED; > > + > > + rc = ib_post_send(info->id->qp, &send_wr, NULL); > > + if (rc) { > > + log_rdma_send(ERR, "ib_post_send failed rc=%d\n", rc); > > + smbd_disconnect_rdma_connection(info); > > + rc = -EAGAIN; > > + } else > > + /* Reset timer for idle connection after packet is sent */ > > + mod_delayed_work(info->workqueue, &info->idle_timer_work, > > + info->keep_alive_interval*HZ); > > + > > + return rc; > > +} > > + > > +static int smbd_post_send_sgl(struct smbd_connection *info, > > + struct scatterlist *sgl, int data_length, int remaining_data_length) > > { > > + int num_sgs; > > + int i, rc; > > + int header_length; > > struct smbd_request *request; > > struct smbd_data_transfer *packet; > > - int header_length; > > int new_credits; > > - int rc; > > + struct scatterlist *sg; > > > > +wait_credit: > > /* Wait for send credits. A SMBD packet needs one credit */ > > rc = wait_event_interruptible(info->wait_send_queue, > > atomic_read(&info->send_credits) > 0 || > > info->transport_status != SMBD_CONNECTED); > > if (rc) > > - return rc; > > + goto err_wait_credit; > > > > if (info->transport_status != SMBD_CONNECTED) { > > - log_outgoing(ERR, "disconnected not sending\n"); > > - return -EAGAIN; > > + log_outgoing(ERR, "disconnected not sending on wait_credit\n"); > > + rc = -EAGAIN; > > + goto err_wait_credit; > > + } > > + if (unlikely(atomic_dec_return(&info->send_credits) < 0)) { > > + atomic_inc(&info->send_credits); > > + goto wait_credit; > > + } > > + > > +wait_send_queue: > > + wait_event(info->wait_post_send, > > + atomic_read(&info->send_pending) < info->send_credit_target || > > + info->transport_status != SMBD_CONNECTED); > > + > > + if (info->transport_status != SMBD_CONNECTED) { > > + log_outgoing(ERR, "disconnected not sending on wait_send_queue\n"); > > + rc = -EAGAIN; > > + goto err_wait_send_queue; > > + } > > + > > + if (unlikely(atomic_inc_return(&info->send_pending) > > > + info->send_credit_target)) { > > + atomic_dec(&info->send_pending); > > + goto wait_send_queue; > > } > > - atomic_dec(&info->send_credits); > > > > request = mempool_alloc(info->request_mempool, GFP_KERNEL); > > if (!request) { > > @@ -859,11 +909,11 @@ static int smbd_create_header(struct smbd_connection *info, > > packet->flags |= cpu_to_le16(SMB_DIRECT_RESPONSE_REQUESTED); > > > > packet->reserved = 0; > > - if (!size) > > + if (!data_length) > > packet->data_offset = 0; > > else > > packet->data_offset = cpu_to_le32(24); > > - packet->data_length = cpu_to_le32(size); > > + packet->data_length = cpu_to_le32(data_length); > > packet->remaining_data_length = cpu_to_le32(remaining_data_length); > > packet->padding = 0; > > > > @@ -878,7 +928,7 @@ static int smbd_create_header(struct smbd_connection *info, > > /* Map the packet to DMA */ > > header_length = sizeof(struct smbd_data_transfer); > > /* If this is a packet without payload, don't send padding */ > > - if (!size) > > + if (!data_length) > > header_length = offsetof(struct smbd_data_transfer, padding); > > > > request->num_sge = 1; > > @@ -887,107 +937,15 @@ static int smbd_create_header(struct smbd_connection *info, > > header_length, > > DMA_TO_DEVICE); > > if (ib_dma_mapping_error(info->id->device, request->sge[0].addr)) { > > - mempool_free(request, info->request_mempool); > > rc = -EIO; > > + request->sge[0].addr = 0; > > goto err_dma; > > } > > > > request->sge[0].length = header_length; > > request->sge[0].lkey = info->pd->local_dma_lkey; > > > > - *request_out = request; > > - return 0; > > - > > -err_dma: > > - /* roll back receive credits */ > > - spin_lock(&info->lock_new_credits_offered); > > - info->new_credits_offered += new_credits; > > - spin_unlock(&info->lock_new_credits_offered); > > - atomic_sub(new_credits, &info->receive_credits); > > - > > -err_alloc: > > - /* roll back send credits */ > > - atomic_inc(&info->send_credits); > > - > > - return rc; > > -} > > - > > -static void smbd_destroy_header(struct smbd_connection *info, > > - struct smbd_request *request) > > -{ > > - > > - ib_dma_unmap_single(info->id->device, > > - request->sge[0].addr, > > - request->sge[0].length, > > - DMA_TO_DEVICE); > > - mempool_free(request, info->request_mempool); > > - atomic_inc(&info->send_credits); > > -} > > - > > -/* Post the send request */ > > -static int smbd_post_send(struct smbd_connection *info, > > - struct smbd_request *request) > > -{ > > - struct ib_send_wr send_wr; > > - int rc, i; > > - > > - for (i = 0; i < request->num_sge; i++) { > > - log_rdma_send(INFO, > > - "rdma_request sge[%d] addr=%llu length=%u\n", > > - i, request->sge[i].addr, request->sge[i].length); > > - ib_dma_sync_single_for_device( > > - info->id->device, > > - request->sge[i].addr, > > - request->sge[i].length, > > - DMA_TO_DEVICE); > > - } > > - > > - request->cqe.done = send_done; > > - > > - send_wr.next = NULL; > > - send_wr.wr_cqe = &request->cqe; > > - send_wr.sg_list = request->sge; > > - send_wr.num_sge = request->num_sge; > > - send_wr.opcode = IB_WR_SEND; > > - send_wr.send_flags = IB_SEND_SIGNALED; > > - > > -wait_sq: > > - wait_event(info->wait_post_send, > > - atomic_read(&info->send_pending) < info->send_credit_target); > > - if (unlikely(atomic_inc_return(&info->send_pending) > > > - info->send_credit_target)) { > > - atomic_dec(&info->send_pending); > > - goto wait_sq; > > - } > > - > > - rc = ib_post_send(info->id->qp, &send_wr, NULL); > > - if (rc) { > > - log_rdma_send(ERR, "ib_post_send failed rc=%d\n", rc); > > - if (atomic_dec_and_test(&info->send_pending)) > > - wake_up(&info->wait_send_pending); > > - smbd_disconnect_rdma_connection(info); > > - rc = -EAGAIN; > > - } else > > - /* Reset timer for idle connection after packet is sent */ > > - mod_delayed_work(info->workqueue, &info->idle_timer_work, > > - info->keep_alive_interval*HZ); > > - > > - return rc; > > -} > > - > > -static int smbd_post_send_sgl(struct smbd_connection *info, > > - struct scatterlist *sgl, int data_length, int remaining_data_length) > > -{ > > - int num_sgs; > > - int i, rc; > > - struct smbd_request *request; > > - struct scatterlist *sg; > > - > > - rc = smbd_create_header( > > - info, data_length, remaining_data_length, &request); > > - if (rc) > > - return rc; > > - > > + /* Fill in the packet data payload */ > > num_sgs = sgl ? sg_nents(sgl) : 0; > > for_each_sg(sgl, sg, num_sgs, i) { > > request->sge[i+1].addr = > > @@ -997,7 +955,7 @@ static int smbd_post_send_sgl(struct smbd_connection *info, > > info->id->device, request->sge[i+1].addr)) { > > rc = -EIO; > > request->sge[i+1].addr = 0; > > - goto dma_mapping_failure; > > + goto err_dma; > > } > > request->sge[i+1].length = sg->length; > > request->sge[i+1].lkey = info->pd->local_dma_lkey; > > @@ -1008,14 +966,30 @@ static int smbd_post_send_sgl(struct smbd_connection *info, > > if (!rc) > > return 0; > > > > -dma_mapping_failure: > > - for (i = 1; i < request->num_sge; i++) > > +err_dma: > > + for (i = 0; i < request->num_sge; i++) > > if (request->sge[i].addr) > > ib_dma_unmap_single(info->id->device, > > request->sge[i].addr, > > request->sge[i].length, > > DMA_TO_DEVICE); > > - smbd_destroy_header(info, request); > > + mempool_free(request, info->request_mempool); > > + > > + /* roll back receive credits and credits to be offered */ > > + spin_lock(&info->lock_new_credits_offered); > > + info->new_credits_offered += new_credits; > > + spin_unlock(&info->lock_new_credits_offered); > > + atomic_sub(new_credits, &info->receive_credits); > > + > > +err_alloc: > > + if (atomic_dec_and_test(&info->send_pending)) > > + wake_up(&info->wait_send_pending); > > + > > +err_wait_send_queue: > > + /* roll back send credits and pending */ > > + atomic_inc(&info->send_credits); > > + > > +err_wait_credit: > > return rc; > > } > > > > -- > > 2.17.1 > > > > > > > -- > Thanks, > > Steve -- Thanks, Steve