[PATCH 4/5] nvme-fabrics: Add target FC transport support
James Smart
james.smart at broadcom.com
Mon Aug 22 09:56:41 PDT 2016
On 8/1/2016 9:37 PM, J Freyensee wrote:
>
>> +static void
>> +nvmet_fc_free_target_queue(struct nvmet_fc_tgt_queue *queue)
>> +{
>> + struct nvmet_fc_tgtport *tgtport = queue->assoc->tgtport;
>> + unsigned long flags;
>> +
>> + /*
>> + * beware: nvmet layer hangs waiting for a completion if
>> + * connect command failed
>> + */
>> + flush_workqueue(queue->work_q);
>> + if (queue->connected)
>> + nvmet_sq_destroy(&queue->nvme_sq);
> I was wondering if there is any way for this fc target layer to fake
> send an NVMe completion to the nvmet layer to prevent a nvmet layer
> hang (because I'm assuming the nvmet layer hangs because it never
> receives a connect completion upon failure here), then send a signal to
> tear down the sq.
>
> Or alternatively call nvmet_ctrl_fatal_error() if connect fails as a
> trial/alternative to having the nvmet layer hang?
I haven't tried to fix the bugs in the other layers - enough to do in FC
already. Agree to look into this.
>> +
>> +/**
>> + * nvme_fc_register_targetport - transport entry point called by an
>> + * LLDD to register the existence of a
>> local
>> + * NVME subystem FC port.
>> + * @pinfo: pointer to information about the port to be
>> registered
>> + * @template: LLDD entrypoints and operational parameters for the
>> port
>> + * @dev: physical hardware device node port corresponds to.
>> Will be
>> + * used for DMA mappings
>> + * @tgtport_p: pointer to a local port pointer. Upon success, the
>
> looks like the variable tgtport_p does not exist (or it's now called
> portptr)?
Yeah - comment not in sync with the code's name.
>
>> +/*
>> + * Actual processing routine for received FC-NVME LS Requests from
>> the LLD
>> + */
>> +void
>> +nvmet_fc_handle_ls_rqst(struct nvmet_fc_tgtport *tgtport,
>> + struct nvmet_fc_ls_iod *iod)
>> +{
>> + struct fcnvme_ls_rqst_w0 *w0 =
>> + (struct fcnvme_ls_rqst_w0 *)iod->rqstbuf;
>> +
>> + iod->lsreq->nvmet_fc_private = iod;
>> + iod->lsreq->rspbuf = iod->rspbuf;
>> + iod->lsreq->rspdma = iod->rspdma;
>> + iod->lsreq->done = nvmet_fc_xmt_ls_rsp_done;
>> + /* Be preventative. handlers will later set to valid length
>> */
>> + iod->lsreq->rsplen = 0;
>> +
>> + iod->assoc = NULL;
>> +
>> + /*
>> + * handlers:
>> + * parse request input, set up nvmet req (cmd, rsp,
>> execute)
>> + * and format the LS response
>> + * if non-zero returned, then no futher action taken on the
>> LS
>> + * if zero:
>> + * valid to call nvmet layer if execute routine set
>> + * iod->rspbuf contains ls response
>> + */
>> + switch (w0->ls_cmd) {
>> + case FCNVME_LS_CREATE_ASSOCIATION:
>> + /* Creates Association and initial Admin
>> Queue/Connection */
>> + nvmet_fc_ls_create_association(tgtport, iod);
>> + break;
>> + case FCNVME_LS_CREATE_CONNECTION:
>> + /* Creates an IO Queue/Connection */
>> + nvmet_fc_ls_create_connection(tgtport, iod);
>> + break;
>> + case FCNVME_LS_DISCONNECT:
>> + /* Terminate a Queue/Connection or the Association
>> */
>> + nvmet_fc_ls_disconnect(tgtport, iod);
>> + break;
>> + default:
>> + iod->lsreq->rsplen = nvmet_fc_format_rjt(iod
>> ->rspbuf,
>> + NVME_FC_MAX_LS_BUFFER_SIZE, w0
>> ->ls_cmd,
>> + LSRJT_REASON_INVALID_ELS_CODE,
>> + LSRJT_EXPL_NO_EXPLANATION, 0);
>> + }
>> +
>> + nvmet_fc_xmt_ls_rsp(tgtport, iod);
>> +}
> All the functions in the case() (nvmet_fc_ls_disconnect(),
> nvmet_fc_ls_create_association(), etc) have internal return values
> (errors and certain values), I'm curious why you wouldn't want to
> bubble up those values through the function calling chain? Especially
> since there is a comment in the function above that says "if non-zero
> returned, then no futher action taken on the LS".
just style. they all generate a response payload that is then always
sent, so returning a code didn't really mean much. The comment is old.
They used to return the value, but as you can see, they don't now. Will
clean it up.
>
> .
>> +
>> +static int __init nvmet_fc_init_module(void)
>> +{
>> + /* ensure NVMET_NR_QUEUES is a power of 2 - required for our
>> masks */
>> + if (!is_power_of_2((unsigned long)NVMET_NR_QUEUES)) {
>> + pr_err("%s: NVMET_NR_QUEUES required to be power of
>> 2\n",
>> + __func__);
> If this is so important that NVMET_NR_QUEUES always be a power of two
> for this FC driver, I'd have the function print out the value in the
> error message for easier diagnosis.
no problem.
>
> And why mask the sign of NVMET_NR_QUEUES? Yes, it would have to be a
> really careless programmer error that would be caught very quick if the
> #define became negative, but masking out the sign of a #define value
> that seems to be pretty important for FC transport functionality makes
> me a tad nervous.
I'll look at it. I believe I did the type redef to make the calling
sequence happy. I'll see if there's a better way.
> Good stuff James,
> J
>
>
Thanks
-- james
More information about the Linux-nvme
mailing list