Commit c740e569 authored by Shuhei Matsumoto's avatar Shuhei Matsumoto Committed by Ben Walker
Browse files

scsi: Open/close a LUN to remove it safely for iSCSI multi connections



To remove a LUN safely for iSCSI multiple connections, each connection
must return I/O channel after checking completion of all tasks.

Open/close mechanism provides a way to register callback to do it.

Registered callback will be called after checking completion of
outstanding tasks.

Making the close LUN function public is necessary to support hot removal.

Change-Id: I06d50d016b0b7aba0d081da226f5b2e0c911629e
Signed-off-by: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-on: https://review.gerrithub.io/417198


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Chandler-Test-Pool: SPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: default avatarChangpeng Liu <changpeng.liu@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
parent 767202e3
Loading
Loading
Loading
Loading
+26 −0
Original line number Diff line number Diff line
@@ -147,6 +147,9 @@ struct spdk_scsi_task {
struct spdk_scsi_port;
struct spdk_scsi_dev;
struct spdk_scsi_lun;
struct spdk_scsi_desc;

typedef void (*spdk_scsi_remove_cb_t)(struct spdk_scsi_lun *, void *);

/**
 * Initialize SCSI layer.
@@ -459,6 +462,29 @@ void spdk_scsi_task_copy_status(struct spdk_scsi_task *dst, struct spdk_scsi_tas
 */
void spdk_scsi_task_process_null_lun(struct spdk_scsi_task *task);

/**
 * Open a logical unit for I/O operations.
 *
 * The registered callback function must get all tasks from the upper layer
 *  (e.g. iSCSI) to the LUN done, free the IO channel of the LUN if allocated,
 *  and then close the LUN.
 *
 * \param lun Logical unit to open.
 * \param hotremove_cb Callback function for hot removal of the logical unit.
 * \param hotremove_ctx Param for hot removal callback function.
 * \param desc Output parameter for the descriptor when operation is successful.
 * \return 0 if operation is successful, suitable errno value otherwise
 */
int spdk_scsi_lun_open(struct spdk_scsi_lun *lun, spdk_scsi_remove_cb_t hotremove_cb,
		       void *hotremove_ctx, struct spdk_scsi_desc **desc);

/**
 * Close an opened logical unit.
 *
 * \param desc Descriptor of the logical unit.
 */
void spdk_scsi_lun_close(struct spdk_scsi_desc *desc);

/**
 * Allocate I/O channel for the LUN
 *
+42 −0
Original line number Diff line number Diff line
@@ -207,10 +207,20 @@ spdk_scsi_lun_check_io_channel(void *arg)
static void
spdk_scsi_lun_notify_hot_remove(struct spdk_scsi_lun *lun)
{
	struct spdk_scsi_desc *desc, *tmp;

	if (lun->hotremove_cb) {
		lun->hotremove_cb(lun, lun->hotremove_ctx);
	}

	TAILQ_FOREACH_SAFE(desc, &lun->open_descs, link, tmp) {
		if (desc->hotremove_cb) {
			desc->hotremove_cb(lun, desc->hotremove_ctx);
		} else {
			spdk_scsi_lun_close(desc);
		}
	}

	if (lun->io_channel) {
		lun->hotremove_poller = spdk_poller_register(spdk_scsi_lun_check_io_channel,
					lun, 10);
@@ -311,6 +321,7 @@ spdk_scsi_lun_construct(struct spdk_bdev *bdev,
	lun->io_channel = NULL;
	lun->hotremove_cb = hotremove_cb;
	lun->hotremove_ctx = hotremove_ctx;
	TAILQ_INIT(&lun->open_descs);

	return lun;
}
@@ -321,6 +332,37 @@ spdk_scsi_lun_destruct(struct spdk_scsi_lun *lun)
	spdk_scsi_lun_hot_remove(lun);
}

int
spdk_scsi_lun_open(struct spdk_scsi_lun *lun, spdk_scsi_remove_cb_t hotremove_cb,
		   void *hotremove_ctx, struct spdk_scsi_desc **_desc)
{
	struct spdk_scsi_desc *desc;

	desc = calloc(1, sizeof(*desc));
	if (desc == NULL) {
		SPDK_ERRLOG("calloc() failed for LUN descriptor.\n");
		return -ENOMEM;
	}

	TAILQ_INSERT_TAIL(&lun->open_descs, desc, link);

	desc->lun = lun;
	desc->hotremove_cb = hotremove_cb;
	desc->hotremove_ctx = hotremove_ctx;
	*_desc = desc;

	return 0;
}

void
spdk_scsi_lun_close(struct spdk_scsi_desc *desc)
{
	struct spdk_scsi_lun *lun = desc->lun;

	TAILQ_REMOVE(&lun->open_descs, desc, link);
	free(desc);
}

int spdk_scsi_lun_allocate_io_channel(struct spdk_scsi_lun *lun)
{
	if (lun->io_channel != NULL) {
+12 −1
Original line number Diff line number Diff line
@@ -72,6 +72,13 @@ struct spdk_scsi_dev {
	uint8_t			protocol_id;
};

struct spdk_scsi_desc {
	struct spdk_scsi_lun		*lun;
	spdk_scsi_remove_cb_t		hotremove_cb;
	void				*hotremove_ctx;
	TAILQ_ENTRY(spdk_scsi_desc)	link;
};

struct spdk_scsi_lun {
	/** LUN id for this logical unit. */
	int id;
@@ -103,7 +110,11 @@ struct spdk_scsi_lun {
	/** Argument for hotremove_cb */
	void *hotremove_ctx;

	TAILQ_HEAD(tasks, spdk_scsi_task) tasks;			/* pending tasks */
	/** List of open descriptors for this LUN. */
	TAILQ_HEAD(, spdk_scsi_desc) open_descs;

	/** pending tasks */
	TAILQ_HEAD(tasks, spdk_scsi_task) tasks;
};

struct spdk_lun_db_entry {