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: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-on: https://review.gerrithub.io/417198
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Chandler-Test-Pool: SPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: Changpeng Liu <changpeng.liu@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
This commit is contained in:
Shuhei Matsumoto 2018-07-10 16:11:20 +09:00 committed by Ben Walker
parent 767202e3ac
commit c740e56928
3 changed files with 80 additions and 1 deletions

View File

@ -147,6 +147,9 @@ struct spdk_scsi_task {
struct spdk_scsi_port; struct spdk_scsi_port;
struct spdk_scsi_dev; struct spdk_scsi_dev;
struct spdk_scsi_lun; struct spdk_scsi_lun;
struct spdk_scsi_desc;
typedef void (*spdk_scsi_remove_cb_t)(struct spdk_scsi_lun *, void *);
/** /**
* Initialize SCSI layer. * 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); 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 * Allocate I/O channel for the LUN
* *

View File

@ -207,10 +207,20 @@ spdk_scsi_lun_check_io_channel(void *arg)
static void static void
spdk_scsi_lun_notify_hot_remove(struct spdk_scsi_lun *lun) spdk_scsi_lun_notify_hot_remove(struct spdk_scsi_lun *lun)
{ {
struct spdk_scsi_desc *desc, *tmp;
if (lun->hotremove_cb) { if (lun->hotremove_cb) {
lun->hotremove_cb(lun, lun->hotremove_ctx); 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) { if (lun->io_channel) {
lun->hotremove_poller = spdk_poller_register(spdk_scsi_lun_check_io_channel, lun->hotremove_poller = spdk_poller_register(spdk_scsi_lun_check_io_channel,
lun, 10); lun, 10);
@ -311,6 +321,7 @@ spdk_scsi_lun_construct(struct spdk_bdev *bdev,
lun->io_channel = NULL; lun->io_channel = NULL;
lun->hotremove_cb = hotremove_cb; lun->hotremove_cb = hotremove_cb;
lun->hotremove_ctx = hotremove_ctx; lun->hotremove_ctx = hotremove_ctx;
TAILQ_INIT(&lun->open_descs);
return lun; return lun;
} }
@ -321,6 +332,37 @@ spdk_scsi_lun_destruct(struct spdk_scsi_lun *lun)
spdk_scsi_lun_hot_remove(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) int spdk_scsi_lun_allocate_io_channel(struct spdk_scsi_lun *lun)
{ {
if (lun->io_channel != NULL) { if (lun->io_channel != NULL) {

View File

@ -72,6 +72,13 @@ struct spdk_scsi_dev {
uint8_t protocol_id; 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 { struct spdk_scsi_lun {
/** LUN id for this logical unit. */ /** LUN id for this logical unit. */
int id; int id;
@ -103,7 +110,11 @@ struct spdk_scsi_lun {
/** Argument for hotremove_cb */ /** Argument for hotremove_cb */
void *hotremove_ctx; 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 { struct spdk_lun_db_entry {