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 {