From c740e569281d46dea3c82b9ecb3878c61ffcef10 Mon Sep 17 00:00:00 2001 From: Shuhei Matsumoto Date: Tue, 10 Jul 2018 16:11:20 +0900 Subject: [PATCH] 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 Reviewed-on: https://review.gerrithub.io/417198 Tested-by: SPDK CI Jenkins Chandler-Test-Pool: SPDK Automated Test System Reviewed-by: Changpeng Liu Reviewed-by: Jim Harris Reviewed-by: Ben Walker --- include/spdk/scsi.h | 26 +++++++++++++++++++++++++ lib/scsi/lun.c | 42 ++++++++++++++++++++++++++++++++++++++++ lib/scsi/scsi_internal.h | 13 ++++++++++++- 3 files changed, 80 insertions(+), 1 deletion(-) diff --git a/include/spdk/scsi.h b/include/spdk/scsi.h index 33bada6d7..fc05232e9 100644 --- a/include/spdk/scsi.h +++ b/include/spdk/scsi.h @@ -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 * diff --git a/lib/scsi/lun.c b/lib/scsi/lun.c index 157265c46..8bc90e9f4 100644 --- a/lib/scsi/lun.c +++ b/lib/scsi/lun.c @@ -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) { diff --git a/lib/scsi/scsi_internal.h b/lib/scsi/scsi_internal.h index b28054dbd..b2e63eb2a 100644 --- a/lib/scsi/scsi_internal.h +++ b/lib/scsi/scsi_internal.h @@ -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 {