[PATCH 6/7 v2] nvme-fabrics: Add target FC transport support

Christoph Hellwig hch at infradead.org
Wed Oct 12 02:42:03 PDT 2016


> +nvmet_fc_getqueueid(u64 connectionid)
> +{
> +	return (u16)((connectionid) & NVMET_FC_QUEUEID_MASK);

Nitpick: superflous inner braces.

> +static LIST_HEAD(nvmet_fc_target_list);
> +static u32 nvmet_fc_tgtport_cnt;

Use an ida allocator instead?

> +	queue->assoc = assoc;
> +	queue->port = assoc->tgtport->port;
> +	INIT_LIST_HEAD(&queue->fod_list);
> +	atomic_set(&queue->connected, 0);
> +	atomic_set(&queue->sqtail, 0);
> +	atomic_set(&queue->rsn, 1);
> +	atomic_set(&queue->zrspcnt, 0);
> +	kref_init(&queue->ref);
> +
> +	nvmet_fc_tgt_a_get(assoc);

You need to check the return value here.  Also for the I/O queue
it needs to be innvmet_fc_find_target_assoc to be under tgtport->lock.

> +	/*
> +	 * beware: nvmet layer hangs waiting for a completion if
> +	 * connect command failed
> +	 */
> +	flush_workqueue(queue->work_q);

Can you elaborate on what the issue?

> +static struct nvmet_fc_tgt_queue *
> +nvmet_fc_find_target_queue(struct nvmet_fc_tgtport *tgtport,
> +				u64 connection_id)
> +{
> +	struct nvmet_fc_tgt_assoc *assoc;
> +	struct nvmet_fc_tgt_queue *queue;
> +	u64 association_id = nvmet_fc_getassociationid(connection_id);
> +	u16 qid = nvmet_fc_getqueueid(connection_id);
> +	unsigned long flags;
> +
> +	spin_lock_irqsave(&tgtport->lock, flags);
> +	list_for_each_entry(assoc, &tgtport->assoc_list, a_list) {
> +		if (association_id == assoc->association_id) {
> +			queue = assoc->queues[qid];
> +			spin_unlock_irqrestore(&tgtport->lock, flags);
> +			if (queue && !atomic_read(&queue->connected))
> +				queue = NULL;
> +			return queue;

This needs a nvmet_fc_tgt_q_get inside the lock.

> +static struct nvmet_fc_tgt_assoc *
> +nvmet_fc_alloc_target_assoc(struct nvmet_fc_tgtport *tgtport)
> +{
> +	struct nvmet_fc_tgt_assoc *assoc;
> +	unsigned long flags;
> +
> +	assoc = kzalloc(sizeof(*assoc), GFP_KERNEL);
> +	if (!assoc)
> +		return NULL;
> +
> +	assoc->tgtport = tgtport;
> +	assoc->association_id = cpu_to_le64(nvmet_fc_makeconnid(assoc, 0));
> +	INIT_LIST_HEAD(&assoc->a_list);
> +	kref_init(&assoc->ref);
> +
> +	nvmet_fc_tgtport_get(tgtport);

Needs to check the return value (At all callers)

> +	get_device(newrec->dev);

Check the return value.

> +	/*
> +	 * TODO: handle fused cmds back-to-back
> +	 */

Do you also plan to implement fused command support in the core?

> +	if (!list_empty(&nvmet_fc_target_list))
> +		pr_warn("%s: targetport list not empty\n", __func__);

WARN_ON?




More information about the Linux-nvme mailing list