2016-07-27 09:32:00 -07:00
|
|
|
/*-
|
|
|
|
* BSD LICENSE
|
|
|
|
*
|
|
|
|
* Copyright (C) 2008-2012 Daisuke Aoyama <aoyama@peach.ne.jp>.
|
|
|
|
* Copyright (c) Intel Corporation.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
*
|
|
|
|
* * Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* * Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in
|
|
|
|
* the documentation and/or other materials provided with the
|
|
|
|
* distribution.
|
|
|
|
* * Neither the name of Intel Corporation nor the names of its
|
|
|
|
* contributors may be used to endorse or promote products derived
|
|
|
|
* from this software without specific prior written permission.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
|
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
|
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
|
|
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
|
|
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
|
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
|
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "scsi_internal.h"
|
2016-08-02 10:43:00 -07:00
|
|
|
#include "spdk/endian.h"
|
2017-03-27 12:59:40 -07:00
|
|
|
#include "spdk/env.h"
|
2018-06-11 13:32:15 -07:00
|
|
|
#include "spdk/thread.h"
|
2017-01-16 21:18:12 +08:00
|
|
|
#include "spdk/event.h"
|
2017-05-01 13:42:29 -07:00
|
|
|
#include "spdk/util.h"
|
2018-11-29 10:18:50 +09:00
|
|
|
#include "spdk/likely.h"
|
2016-07-27 09:32:00 -07:00
|
|
|
|
|
|
|
void
|
|
|
|
spdk_scsi_lun_complete_task(struct spdk_scsi_lun *lun, struct spdk_scsi_task *task)
|
|
|
|
{
|
|
|
|
if (lun) {
|
2017-05-12 17:31:46 -07:00
|
|
|
TAILQ_REMOVE(&lun->tasks, task, scsi_link);
|
2016-07-27 09:32:00 -07:00
|
|
|
spdk_trace_record(TRACE_SCSI_TASK_DONE, lun->dev->id, 0, (uintptr_t)task, 0);
|
|
|
|
}
|
2017-06-08 13:45:41 -07:00
|
|
|
task->cpl_fn(task);
|
2016-07-27 09:32:00 -07:00
|
|
|
}
|
|
|
|
|
2018-11-28 09:47:45 +09:00
|
|
|
static void
|
|
|
|
spdk_scsi_lun_complete_mgmt_task(struct spdk_scsi_lun *lun, struct spdk_scsi_task *task)
|
|
|
|
{
|
|
|
|
TAILQ_REMOVE(&lun->mgmt_tasks, task, scsi_link);
|
|
|
|
|
|
|
|
task->cpl_fn(task);
|
|
|
|
|
|
|
|
/* Try to execute the first pending mgmt task if it exists. */
|
|
|
|
spdk_scsi_lun_execute_mgmt_task(lun);
|
|
|
|
}
|
|
|
|
|
2018-11-29 10:23:07 +09:00
|
|
|
static bool
|
|
|
|
spdk_scsi_lun_has_outstanding_tasks(struct spdk_scsi_lun *lun)
|
|
|
|
{
|
|
|
|
return !TAILQ_EMPTY(&lun->tasks);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Reset task have to wait until all prior outstanding tasks complete. */
|
|
|
|
static int
|
|
|
|
spdk_scsi_lun_reset_check_outstanding_tasks(void *arg)
|
|
|
|
{
|
|
|
|
struct spdk_scsi_task *task = (struct spdk_scsi_task *)arg;
|
|
|
|
struct spdk_scsi_lun *lun = task->lun;
|
|
|
|
|
|
|
|
if (spdk_scsi_lun_has_outstanding_tasks(lun)) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
spdk_poller_unregister(&lun->reset_poller);
|
|
|
|
|
|
|
|
spdk_scsi_lun_complete_mgmt_task(lun, task);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2017-11-15 12:37:24 +08:00
|
|
|
void
|
2018-11-26 12:03:38 +09:00
|
|
|
spdk_scsi_lun_complete_reset_task(struct spdk_scsi_lun *lun, struct spdk_scsi_task *task)
|
2017-11-15 12:37:24 +08:00
|
|
|
{
|
2018-11-26 12:03:38 +09:00
|
|
|
if (task->status == SPDK_SCSI_STATUS_GOOD) {
|
2018-11-29 10:23:07 +09:00
|
|
|
if (spdk_scsi_lun_has_outstanding_tasks(lun)) {
|
|
|
|
lun->reset_poller =
|
|
|
|
spdk_poller_register(spdk_scsi_lun_reset_check_outstanding_tasks,
|
|
|
|
task, 10);
|
|
|
|
return;
|
2017-11-15 12:37:24 +08:00
|
|
|
}
|
2016-07-27 09:32:00 -07:00
|
|
|
}
|
2018-11-26 12:03:38 +09:00
|
|
|
|
2018-11-28 09:47:45 +09:00
|
|
|
spdk_scsi_lun_complete_mgmt_task(lun, task);
|
2018-11-26 12:03:38 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2018-11-28 09:47:45 +09:00
|
|
|
_spdk_scsi_lun_execute_mgmt_task(struct spdk_scsi_lun *lun,
|
|
|
|
struct spdk_scsi_task *task)
|
2018-11-26 12:03:38 +09:00
|
|
|
{
|
2018-11-28 09:47:45 +09:00
|
|
|
TAILQ_INSERT_TAIL(&lun->mgmt_tasks, task, scsi_link);
|
2017-05-23 13:11:49 -07:00
|
|
|
|
2018-11-26 11:05:21 +09:00
|
|
|
switch (task->function) {
|
2016-07-27 09:32:00 -07:00
|
|
|
case SPDK_SCSI_TASK_FUNC_ABORT_TASK:
|
2017-05-23 13:11:49 -07:00
|
|
|
task->response = SPDK_SCSI_TASK_MGMT_RESP_REJECT_FUNC_NOT_SUPPORTED;
|
|
|
|
SPDK_ERRLOG("ABORT_TASK failed\n");
|
2016-07-27 09:32:00 -07:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SPDK_SCSI_TASK_FUNC_ABORT_TASK_SET:
|
2017-05-23 13:11:49 -07:00
|
|
|
task->response = SPDK_SCSI_TASK_MGMT_RESP_REJECT_FUNC_NOT_SUPPORTED;
|
|
|
|
SPDK_ERRLOG("ABORT_TASK_SET failed\n");
|
2016-07-27 09:32:00 -07:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SPDK_SCSI_TASK_FUNC_LUN_RESET:
|
2018-01-04 15:45:01 -07:00
|
|
|
spdk_bdev_scsi_reset(task);
|
2018-11-28 09:47:45 +09:00
|
|
|
return;
|
2016-07-27 09:32:00 -07:00
|
|
|
|
|
|
|
default:
|
|
|
|
SPDK_ERRLOG("Unknown Task Management Function!\n");
|
|
|
|
/*
|
|
|
|
* Task management functions other than those above should never
|
|
|
|
* reach this point having been filtered by the frontend. Reject
|
|
|
|
* the task as being unsupported.
|
|
|
|
*/
|
|
|
|
task->response = SPDK_SCSI_TASK_MGMT_RESP_REJECT_FUNC_NOT_SUPPORTED;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2018-11-28 09:47:45 +09:00
|
|
|
spdk_scsi_lun_complete_mgmt_task(lun, task);
|
|
|
|
}
|
2016-07-27 09:32:00 -07:00
|
|
|
|
2018-11-28 09:47:45 +09:00
|
|
|
void
|
|
|
|
spdk_scsi_lun_append_mgmt_task(struct spdk_scsi_lun *lun,
|
|
|
|
struct spdk_scsi_task *task)
|
|
|
|
{
|
|
|
|
TAILQ_INSERT_TAIL(&lun->pending_mgmt_tasks, task, scsi_link);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
spdk_scsi_lun_execute_mgmt_task(struct spdk_scsi_lun *lun)
|
|
|
|
{
|
|
|
|
struct spdk_scsi_task *task;
|
|
|
|
|
|
|
|
if (!TAILQ_EMPTY(&lun->mgmt_tasks)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
task = TAILQ_FIRST(&lun->pending_mgmt_tasks);
|
2018-11-29 10:18:50 +09:00
|
|
|
if (spdk_likely(task == NULL)) {
|
|
|
|
/* Try to execute all pending tasks */
|
|
|
|
spdk_scsi_lun_execute_tasks(lun);
|
2018-11-28 09:47:45 +09:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
TAILQ_REMOVE(&lun->pending_mgmt_tasks, task, scsi_link);
|
|
|
|
|
|
|
|
_spdk_scsi_lun_execute_mgmt_task(lun, task);
|
2016-07-27 09:32:00 -07:00
|
|
|
}
|
|
|
|
|
2018-11-29 10:18:50 +09:00
|
|
|
static void
|
|
|
|
_spdk_scsi_lun_execute_task(struct spdk_scsi_lun *lun, struct spdk_scsi_task *task)
|
2016-07-27 09:32:00 -07:00
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
|
2018-01-08 12:20:57 +01:00
|
|
|
task->status = SPDK_SCSI_STATUS_GOOD;
|
|
|
|
spdk_trace_record(TRACE_SCSI_TASK_START, lun->dev->id, task->length, (uintptr_t)task, 0);
|
|
|
|
TAILQ_INSERT_TAIL(&lun->tasks, task, scsi_link);
|
|
|
|
if (!lun->removed) {
|
|
|
|
rc = spdk_bdev_scsi_execute(task);
|
|
|
|
} else {
|
2018-12-04 22:24:34 +09:00
|
|
|
spdk_scsi_task_process_abort(task);
|
2018-01-08 12:20:57 +01:00
|
|
|
rc = SPDK_SCSI_TASK_COMPLETE;
|
|
|
|
}
|
2016-07-27 09:32:00 -07:00
|
|
|
|
2018-01-08 12:20:57 +01:00
|
|
|
switch (rc) {
|
|
|
|
case SPDK_SCSI_TASK_PENDING:
|
|
|
|
break;
|
2016-07-27 09:32:00 -07:00
|
|
|
|
2018-01-08 12:20:57 +01:00
|
|
|
case SPDK_SCSI_TASK_COMPLETE:
|
|
|
|
spdk_scsi_lun_complete_task(lun, task);
|
|
|
|
break;
|
2016-07-27 09:32:00 -07:00
|
|
|
|
2018-01-08 12:20:57 +01:00
|
|
|
default:
|
|
|
|
abort();
|
2016-07-27 09:32:00 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-29 10:18:50 +09:00
|
|
|
void
|
|
|
|
spdk_scsi_lun_append_task(struct spdk_scsi_lun *lun, struct spdk_scsi_task *task)
|
|
|
|
{
|
|
|
|
TAILQ_INSERT_TAIL(&lun->pending_tasks, task, scsi_link);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
spdk_scsi_lun_execute_tasks(struct spdk_scsi_lun *lun)
|
|
|
|
{
|
|
|
|
struct spdk_scsi_task *task, *task_tmp;
|
|
|
|
|
|
|
|
if (spdk_scsi_lun_has_pending_mgmt_tasks(lun)) {
|
|
|
|
/* Pending IO tasks will wait for completion of existing mgmt tasks.
|
|
|
|
*/
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
TAILQ_FOREACH_SAFE(task, &lun->pending_tasks, scsi_link, task_tmp) {
|
|
|
|
TAILQ_REMOVE(&lun->pending_tasks, task, scsi_link);
|
|
|
|
_spdk_scsi_lun_execute_task(lun, task);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-08 14:43:07 +09:00
|
|
|
static void
|
|
|
|
spdk_scsi_lun_remove(struct spdk_scsi_lun *lun)
|
|
|
|
{
|
|
|
|
spdk_bdev_close(lun->bdev_desc);
|
|
|
|
|
|
|
|
spdk_scsi_dev_delete_lun(lun->dev, lun);
|
|
|
|
free(lun);
|
|
|
|
}
|
|
|
|
|
2018-03-12 17:16:47 -07:00
|
|
|
static int
|
2018-06-28 10:56:06 +09:00
|
|
|
spdk_scsi_lun_check_io_channel(void *arg)
|
2017-01-16 21:18:12 +08:00
|
|
|
{
|
|
|
|
struct spdk_scsi_lun *lun = (struct spdk_scsi_lun *)arg;
|
|
|
|
|
2018-06-28 10:56:06 +09:00
|
|
|
if (lun->io_channel) {
|
2018-06-21 13:37:31 +09:00
|
|
|
return -1;
|
2017-01-16 21:18:12 +08:00
|
|
|
}
|
2018-06-21 13:37:31 +09:00
|
|
|
spdk_poller_unregister(&lun->hotremove_poller);
|
|
|
|
|
2018-06-28 10:56:06 +09:00
|
|
|
spdk_scsi_lun_remove(lun);
|
2018-03-12 17:16:47 -07:00
|
|
|
return -1;
|
2017-01-16 21:18:12 +08:00
|
|
|
}
|
|
|
|
|
2017-06-28 12:21:21 +02:00
|
|
|
static void
|
2018-06-28 10:56:06 +09:00
|
|
|
spdk_scsi_lun_notify_hot_remove(struct spdk_scsi_lun *lun)
|
2017-01-16 21:18:12 +08:00
|
|
|
{
|
2018-07-10 16:11:20 +09:00
|
|
|
struct spdk_scsi_desc *desc, *tmp;
|
|
|
|
|
2017-06-28 12:21:21 +02:00
|
|
|
if (lun->hotremove_cb) {
|
|
|
|
lun->hotremove_cb(lun, lun->hotremove_ctx);
|
|
|
|
}
|
|
|
|
|
2018-07-10 16:11:20 +09:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-28 10:56:06 +09:00
|
|
|
if (lun->io_channel) {
|
|
|
|
lun->hotremove_poller = spdk_poller_register(spdk_scsi_lun_check_io_channel,
|
2018-06-08 14:43:07 +09:00
|
|
|
lun, 10);
|
2018-01-04 21:09:02 +01:00
|
|
|
} else {
|
2018-06-08 14:43:07 +09:00
|
|
|
spdk_scsi_lun_remove(lun);
|
2018-01-04 21:09:02 +01:00
|
|
|
}
|
2017-01-16 21:18:12 +08:00
|
|
|
}
|
|
|
|
|
2018-06-28 10:56:06 +09:00
|
|
|
static int
|
|
|
|
spdk_scsi_lun_check_pending_tasks(void *arg)
|
|
|
|
{
|
|
|
|
struct spdk_scsi_lun *lun = (struct spdk_scsi_lun *)arg;
|
|
|
|
|
2018-11-28 09:47:45 +09:00
|
|
|
if (spdk_scsi_lun_has_pending_tasks(lun) ||
|
|
|
|
spdk_scsi_lun_has_pending_mgmt_tasks(lun)) {
|
2018-06-28 10:56:06 +09:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
spdk_poller_unregister(&lun->hotremove_poller);
|
|
|
|
|
|
|
|
spdk_scsi_lun_notify_hot_remove(lun);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_spdk_scsi_lun_hot_remove(void *arg1)
|
|
|
|
{
|
|
|
|
struct spdk_scsi_lun *lun = arg1;
|
|
|
|
|
2018-11-28 09:47:45 +09:00
|
|
|
if (spdk_scsi_lun_has_pending_tasks(lun) ||
|
|
|
|
spdk_scsi_lun_has_pending_mgmt_tasks(lun)) {
|
2018-06-28 10:56:06 +09:00
|
|
|
lun->hotremove_poller = spdk_poller_register(spdk_scsi_lun_check_pending_tasks,
|
|
|
|
lun, 10);
|
|
|
|
} else {
|
|
|
|
spdk_scsi_lun_notify_hot_remove(lun);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-14 14:02:02 -07:00
|
|
|
static void
|
|
|
|
spdk_scsi_lun_hot_remove(void *remove_ctx)
|
|
|
|
{
|
|
|
|
struct spdk_scsi_lun *lun = (struct spdk_scsi_lun *)remove_ctx;
|
2017-07-31 13:34:00 +02:00
|
|
|
struct spdk_thread *thread;
|
2017-11-14 14:02:02 -07:00
|
|
|
|
2018-01-04 21:09:02 +01:00
|
|
|
if (lun->removed) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
lun->removed = true;
|
2017-07-31 13:34:00 +02:00
|
|
|
if (lun->io_channel == NULL) {
|
|
|
|
_spdk_scsi_lun_hot_remove(lun);
|
|
|
|
return;
|
|
|
|
}
|
2017-11-14 14:02:02 -07:00
|
|
|
|
2017-07-31 13:34:00 +02:00
|
|
|
thread = spdk_io_channel_get_thread(lun->io_channel);
|
|
|
|
if (thread != spdk_get_thread()) {
|
|
|
|
spdk_thread_send_msg(thread, _spdk_scsi_lun_hot_remove, lun);
|
2017-11-14 14:02:02 -07:00
|
|
|
} else {
|
2017-07-31 13:34:00 +02:00
|
|
|
_spdk_scsi_lun_hot_remove(lun);
|
2017-11-14 14:02:02 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-04-24 11:14:41 -07:00
|
|
|
/**
|
2017-04-25 10:35:22 -07:00
|
|
|
* \brief Constructs a new spdk_scsi_lun object based on the provided parameters.
|
|
|
|
*
|
2017-07-12 21:08:53 -07:00
|
|
|
* \param bdev bdev associated with this LUN
|
2017-04-25 10:35:22 -07:00
|
|
|
*
|
2017-07-12 21:08:53 -07:00
|
|
|
* \return NULL if bdev == NULL
|
2017-04-25 10:35:22 -07:00
|
|
|
* \return pointer to the new spdk_scsi_lun object otherwise
|
|
|
|
*/
|
2016-07-27 09:32:00 -07:00
|
|
|
_spdk_scsi_lun *
|
2018-01-10 14:55:53 +09:00
|
|
|
spdk_scsi_lun_construct(struct spdk_bdev *bdev,
|
|
|
|
void (*hotremove_cb)(const struct spdk_scsi_lun *, void *),
|
|
|
|
void *hotremove_ctx)
|
2016-07-27 09:32:00 -07:00
|
|
|
{
|
|
|
|
struct spdk_scsi_lun *lun;
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
if (bdev == NULL) {
|
2017-07-12 21:08:53 -07:00
|
|
|
SPDK_ERRLOG("bdev must be non-NULL\n");
|
2016-07-27 09:32:00 -07:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
lun = calloc(1, sizeof(*lun));
|
|
|
|
if (lun == NULL) {
|
|
|
|
SPDK_ERRLOG("could not allocate lun\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2017-06-29 11:23:50 -07:00
|
|
|
rc = spdk_bdev_open(bdev, true, spdk_scsi_lun_hot_remove, lun, &lun->bdev_desc);
|
|
|
|
|
|
|
|
if (rc != 0) {
|
2018-01-10 14:55:53 +09:00
|
|
|
SPDK_ERRLOG("bdev %s cannot be opened, error=%d\n", spdk_bdev_get_name(bdev), rc);
|
2017-01-10 09:54:23 -07:00
|
|
|
free(lun);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2016-07-27 09:32:00 -07:00
|
|
|
TAILQ_INIT(&lun->tasks);
|
2018-11-29 10:18:50 +09:00
|
|
|
TAILQ_INIT(&lun->pending_tasks);
|
2018-11-28 09:47:45 +09:00
|
|
|
TAILQ_INIT(&lun->mgmt_tasks);
|
|
|
|
TAILQ_INIT(&lun->pending_mgmt_tasks);
|
2016-07-27 09:32:00 -07:00
|
|
|
|
|
|
|
lun->bdev = bdev;
|
2017-07-31 13:34:00 +02:00
|
|
|
lun->io_channel = NULL;
|
2017-06-28 12:21:21 +02:00
|
|
|
lun->hotremove_cb = hotremove_cb;
|
|
|
|
lun->hotremove_ctx = hotremove_ctx;
|
2018-07-10 16:11:20 +09:00
|
|
|
TAILQ_INIT(&lun->open_descs);
|
2016-07-27 09:32:00 -07:00
|
|
|
|
|
|
|
return lun;
|
|
|
|
}
|
|
|
|
|
2018-01-04 21:09:02 +01:00
|
|
|
void
|
2016-07-27 09:32:00 -07:00
|
|
|
spdk_scsi_lun_destruct(struct spdk_scsi_lun *lun)
|
|
|
|
{
|
2018-01-04 21:09:02 +01:00
|
|
|
spdk_scsi_lun_hot_remove(lun);
|
2016-07-27 09:32:00 -07:00
|
|
|
}
|
2016-09-20 12:46:28 -07:00
|
|
|
|
2018-07-10 16:11:20 +09:00
|
|
|
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);
|
2018-07-10 16:17:34 +09:00
|
|
|
|
|
|
|
assert(!TAILQ_EMPTY(&lun->open_descs) || lun->io_channel == NULL);
|
2018-07-10 16:11:20 +09:00
|
|
|
}
|
|
|
|
|
2018-07-10 16:17:34 +09:00
|
|
|
int
|
|
|
|
_spdk_scsi_lun_allocate_io_channel(struct spdk_scsi_lun *lun)
|
2016-09-20 12:46:28 -07:00
|
|
|
{
|
|
|
|
if (lun->io_channel != NULL) {
|
2018-06-22 10:32:03 +09:00
|
|
|
if (spdk_get_thread() == spdk_io_channel_get_thread(lun->io_channel)) {
|
2017-09-25 09:23:57 -07:00
|
|
|
lun->ref++;
|
|
|
|
return 0;
|
|
|
|
}
|
2018-01-10 14:55:53 +09:00
|
|
|
SPDK_ERRLOG("io_channel already allocated for lun %s\n",
|
|
|
|
spdk_bdev_get_name(lun->bdev));
|
2017-09-25 09:23:57 -07:00
|
|
|
return -1;
|
2016-09-20 12:46:28 -07:00
|
|
|
}
|
|
|
|
|
2017-06-29 11:23:50 -07:00
|
|
|
lun->io_channel = spdk_bdev_get_io_channel(lun->bdev_desc);
|
2016-09-20 12:46:28 -07:00
|
|
|
if (lun->io_channel == NULL) {
|
|
|
|
return -1;
|
|
|
|
}
|
2017-09-25 09:23:57 -07:00
|
|
|
lun->ref = 1;
|
2016-09-20 12:46:28 -07:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-07-10 16:17:34 +09:00
|
|
|
void
|
|
|
|
_spdk_scsi_lun_free_io_channel(struct spdk_scsi_lun *lun)
|
2016-09-20 12:46:28 -07:00
|
|
|
{
|
2018-06-22 10:32:03 +09:00
|
|
|
if (lun->io_channel == NULL) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (spdk_get_thread() != spdk_io_channel_get_thread(lun->io_channel)) {
|
|
|
|
SPDK_ERRLOG("io_channel was freed by different thread\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
lun->ref--;
|
|
|
|
if (lun->ref == 0) {
|
|
|
|
spdk_put_io_channel(lun->io_channel);
|
|
|
|
lun->io_channel = NULL;
|
2016-09-20 12:46:28 -07:00
|
|
|
}
|
|
|
|
}
|
2017-05-01 13:32:34 -07:00
|
|
|
|
2018-07-10 16:17:34 +09:00
|
|
|
int
|
|
|
|
spdk_scsi_lun_allocate_io_channel(struct spdk_scsi_desc *desc)
|
|
|
|
{
|
|
|
|
struct spdk_scsi_lun *lun = desc->lun;
|
|
|
|
|
|
|
|
return _spdk_scsi_lun_allocate_io_channel(lun);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
spdk_scsi_lun_free_io_channel(struct spdk_scsi_desc *desc)
|
|
|
|
{
|
|
|
|
struct spdk_scsi_lun *lun = desc->lun;
|
|
|
|
|
|
|
|
_spdk_scsi_lun_free_io_channel(lun);
|
|
|
|
}
|
|
|
|
|
2017-05-01 13:32:34 -07:00
|
|
|
int
|
|
|
|
spdk_scsi_lun_get_id(const struct spdk_scsi_lun *lun)
|
|
|
|
{
|
|
|
|
return lun->id;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *
|
2018-01-10 14:55:53 +09:00
|
|
|
spdk_scsi_lun_get_bdev_name(const struct spdk_scsi_lun *lun)
|
2017-05-01 13:32:34 -07:00
|
|
|
{
|
2018-01-10 14:55:53 +09:00
|
|
|
return spdk_bdev_get_name(lun->bdev);
|
2017-05-01 13:32:34 -07:00
|
|
|
}
|
2017-06-28 12:21:21 +02:00
|
|
|
|
|
|
|
const struct spdk_scsi_dev *
|
|
|
|
spdk_scsi_lun_get_dev(const struct spdk_scsi_lun *lun)
|
|
|
|
{
|
|
|
|
return lun->dev;
|
|
|
|
}
|
2017-06-22 16:44:49 +02:00
|
|
|
|
2018-11-28 09:47:45 +09:00
|
|
|
bool
|
|
|
|
spdk_scsi_lun_has_pending_mgmt_tasks(const struct spdk_scsi_lun *lun)
|
|
|
|
{
|
|
|
|
return !TAILQ_EMPTY(&lun->pending_mgmt_tasks) ||
|
|
|
|
!TAILQ_EMPTY(&lun->mgmt_tasks);
|
|
|
|
}
|
|
|
|
|
2018-11-29 10:18:50 +09:00
|
|
|
/* This check includes both pending and submitted (outstanding) tasks. */
|
2017-06-22 16:44:49 +02:00
|
|
|
bool
|
|
|
|
spdk_scsi_lun_has_pending_tasks(const struct spdk_scsi_lun *lun)
|
|
|
|
{
|
2018-11-29 10:18:50 +09:00
|
|
|
return !TAILQ_EMPTY(&lun->pending_tasks) ||
|
|
|
|
!TAILQ_EMPTY(&lun->tasks);
|
2017-06-22 16:44:49 +02:00
|
|
|
}
|
2018-07-04 14:23:55 +09:00
|
|
|
|
|
|
|
bool
|
|
|
|
spdk_scsi_lun_is_removing(const struct spdk_scsi_lun *lun)
|
|
|
|
{
|
|
|
|
return lun->removed;
|
|
|
|
}
|