2022-11-01 20:26:26 +00:00
|
|
|
/* SPDX-License-Identifier: BSD-3-Clause
|
2022-11-01 21:45:50 +00:00
|
|
|
* Copyright (C) 2016 Intel Corporation
|
2022-11-01 20:26:26 +00:00
|
|
|
* All rights reserved.
|
|
|
|
*/
|
|
|
|
|
2016-08-16 21:42:15 +00:00
|
|
|
#include "iscsi/task.h"
|
|
|
|
#include "iscsi/iscsi.h"
|
|
|
|
#include "iscsi/conn.h"
|
2016-11-07 22:10:28 +00:00
|
|
|
|
2017-03-27 19:59:40 +00:00
|
|
|
#include "spdk/env.h"
|
2018-02-07 19:58:14 +00:00
|
|
|
#include "spdk/sock.h"
|
2018-08-29 22:28:21 +00:00
|
|
|
#include "spdk_cunit.h"
|
2016-08-16 21:42:15 +00:00
|
|
|
|
2020-10-06 16:16:26 +00:00
|
|
|
#include "spdk/log.h"
|
2018-12-10 00:58:26 +00:00
|
|
|
#include "spdk_internal/mock.h"
|
2016-11-07 22:10:28 +00:00
|
|
|
|
2017-05-03 19:41:55 +00:00
|
|
|
#include "scsi/scsi_internal.h"
|
|
|
|
|
2020-09-04 11:27:29 +00:00
|
|
|
SPDK_LOG_REGISTER_COMPONENT(iscsi)
|
2016-08-16 21:42:15 +00:00
|
|
|
|
2019-10-22 00:52:30 +00:00
|
|
|
TAILQ_HEAD(, spdk_iscsi_pdu) g_write_pdu_list = TAILQ_HEAD_INITIALIZER(g_write_pdu_list);
|
2018-01-18 06:34:47 +00:00
|
|
|
|
2019-10-24 01:05:06 +00:00
|
|
|
static bool g_task_pool_is_empty = false;
|
|
|
|
static bool g_pdu_pool_is_empty = false;
|
2021-03-01 13:05:05 +00:00
|
|
|
static uint32_t g_conn_read_len;
|
2021-10-21 06:29:34 +00:00
|
|
|
static bool g_conn_read_data_digest = false;
|
|
|
|
static uint32_t g_data_digest;
|
2019-10-24 01:05:06 +00:00
|
|
|
|
2016-08-16 21:42:15 +00:00
|
|
|
struct spdk_iscsi_task *
|
2020-04-15 20:30:47 +00:00
|
|
|
iscsi_task_get(struct spdk_iscsi_conn *conn,
|
|
|
|
struct spdk_iscsi_task *parent,
|
|
|
|
spdk_scsi_task_cpl cpl_fn)
|
2016-08-16 21:42:15 +00:00
|
|
|
{
|
|
|
|
struct spdk_iscsi_task *task;
|
|
|
|
|
2019-10-24 01:05:06 +00:00
|
|
|
if (g_task_pool_is_empty) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2016-08-16 21:42:15 +00:00
|
|
|
task = calloc(1, sizeof(*task));
|
2018-12-09 23:12:11 +00:00
|
|
|
if (!task) {
|
|
|
|
return NULL;
|
|
|
|
}
|
2019-11-11 21:50:52 +00:00
|
|
|
|
|
|
|
task->conn = conn;
|
|
|
|
task->scsi.cpl_fn = cpl_fn;
|
|
|
|
if (parent) {
|
|
|
|
parent->scsi.ref++;
|
|
|
|
task->parent = parent;
|
|
|
|
task->tag = parent->tag;
|
|
|
|
task->lun_id = parent->lun_id;
|
|
|
|
task->scsi.dxfer_dir = parent->scsi.dxfer_dir;
|
|
|
|
task->scsi.transfer_len = parent->scsi.transfer_len;
|
|
|
|
task->scsi.lun = parent->scsi.lun;
|
|
|
|
task->scsi.cdb = parent->scsi.cdb;
|
|
|
|
task->scsi.target_port = parent->scsi.target_port;
|
|
|
|
task->scsi.initiator_port = parent->scsi.initiator_port;
|
2019-11-18 15:32:35 +00:00
|
|
|
if (conn && (task->scsi.dxfer_dir == SPDK_SCSI_DIR_FROM_DEV)) {
|
|
|
|
conn->data_in_cnt++;
|
|
|
|
}
|
2019-11-11 21:50:52 +00:00
|
|
|
}
|
|
|
|
|
2018-12-09 23:12:11 +00:00
|
|
|
task->scsi.iovs = &task->scsi.iov;
|
2016-08-16 21:42:15 +00:00
|
|
|
return task;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2016-09-28 06:49:06 +00:00
|
|
|
spdk_scsi_task_put(struct spdk_scsi_task *task)
|
2016-08-16 21:42:15 +00:00
|
|
|
{
|
|
|
|
free(task);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-04-16 02:10:57 +00:00
|
|
|
iscsi_put_pdu(struct spdk_iscsi_pdu *pdu)
|
2016-08-16 21:42:15 +00:00
|
|
|
{
|
2017-12-07 23:23:48 +00:00
|
|
|
if (!pdu) {
|
2016-08-16 21:42:15 +00:00
|
|
|
return;
|
2017-12-07 23:23:48 +00:00
|
|
|
}
|
2016-08-16 21:42:15 +00:00
|
|
|
|
2017-06-08 05:11:02 +00:00
|
|
|
pdu->ref--;
|
2016-08-16 21:42:15 +00:00
|
|
|
if (pdu->ref < 0) {
|
|
|
|
CU_FAIL("negative ref count");
|
|
|
|
pdu->ref = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pdu->ref == 0) {
|
2016-10-09 04:31:06 +00:00
|
|
|
if (pdu->data && !pdu->data_from_mempool) {
|
2016-08-16 21:42:15 +00:00
|
|
|
free(pdu->data);
|
|
|
|
}
|
|
|
|
free(pdu);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct spdk_iscsi_pdu *
|
2020-04-16 02:10:57 +00:00
|
|
|
iscsi_get_pdu(struct spdk_iscsi_conn *conn)
|
2016-08-16 21:42:15 +00:00
|
|
|
{
|
|
|
|
struct spdk_iscsi_pdu *pdu;
|
|
|
|
|
2020-01-15 17:20:21 +00:00
|
|
|
assert(conn != NULL);
|
2019-10-24 01:05:06 +00:00
|
|
|
if (g_pdu_pool_is_empty) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2016-08-16 21:42:15 +00:00
|
|
|
pdu = malloc(sizeof(*pdu));
|
|
|
|
if (!pdu) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2017-07-13 00:50:19 +00:00
|
|
|
memset(pdu, 0, offsetof(struct spdk_iscsi_pdu, ahs));
|
2016-08-16 21:42:15 +00:00
|
|
|
pdu->ref = 1;
|
2020-01-15 17:20:21 +00:00
|
|
|
pdu->conn = conn;
|
2016-08-16 21:42:15 +00:00
|
|
|
|
|
|
|
return pdu;
|
|
|
|
}
|
|
|
|
|
2018-12-10 00:58:26 +00:00
|
|
|
DEFINE_STUB_V(spdk_scsi_task_process_null_lun, (struct spdk_scsi_task *task));
|
2017-02-26 12:41:06 +00:00
|
|
|
|
2018-12-10 00:58:26 +00:00
|
|
|
DEFINE_STUB_V(spdk_scsi_task_process_abort, (struct spdk_scsi_task *task));
|
2018-12-09 23:12:11 +00:00
|
|
|
|
2021-02-25 19:34:01 +00:00
|
|
|
void
|
|
|
|
spdk_scsi_dev_queue_task(struct spdk_scsi_dev *dev, struct spdk_scsi_task *task)
|
|
|
|
{
|
2021-09-25 03:52:02 +00:00
|
|
|
struct spdk_scsi_lun *lun;
|
2021-02-25 19:34:01 +00:00
|
|
|
|
2021-09-25 03:52:02 +00:00
|
|
|
lun = TAILQ_FIRST(&dev->luns);
|
|
|
|
SPDK_CU_ASSERT_FATAL(lun != NULL);
|
|
|
|
|
|
|
|
TAILQ_INSERT_TAIL(&lun->tasks, task, scsi_link);
|
2021-02-25 19:34:01 +00:00
|
|
|
}
|
2016-08-16 21:42:15 +00:00
|
|
|
|
2018-12-10 00:58:26 +00:00
|
|
|
DEFINE_STUB(spdk_scsi_dev_find_port_by_id, struct spdk_scsi_port *,
|
|
|
|
(struct spdk_scsi_dev *dev, uint64_t id), NULL);
|
2016-08-16 21:42:15 +00:00
|
|
|
|
2018-12-10 00:58:26 +00:00
|
|
|
DEFINE_STUB_V(spdk_scsi_dev_queue_mgmt_task,
|
|
|
|
(struct spdk_scsi_dev *dev, struct spdk_scsi_task *task));
|
2016-08-16 21:42:15 +00:00
|
|
|
|
2017-12-05 06:42:37 +00:00
|
|
|
const char *
|
|
|
|
spdk_scsi_dev_get_name(const struct spdk_scsi_dev *dev)
|
|
|
|
{
|
|
|
|
if (dev != NULL) {
|
|
|
|
return dev->name;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2018-12-10 00:58:26 +00:00
|
|
|
DEFINE_STUB(spdk_scsi_dev_construct, struct spdk_scsi_dev *,
|
|
|
|
(const char *name, const char **bdev_name_list,
|
|
|
|
int *lun_id_list, int num_luns, uint8_t protocol_id,
|
|
|
|
void (*hotremove_cb)(const struct spdk_scsi_lun *, void *),
|
|
|
|
void *hotremove_ctx),
|
|
|
|
NULL);
|
2016-08-16 21:42:15 +00:00
|
|
|
|
2019-04-11 09:10:47 +00:00
|
|
|
DEFINE_STUB_V(spdk_scsi_dev_destruct,
|
|
|
|
(struct spdk_scsi_dev *dev, spdk_scsi_dev_destruct_cb_t cb_fn, void *cb_arg));
|
2016-08-16 21:42:15 +00:00
|
|
|
|
2018-12-10 00:58:26 +00:00
|
|
|
DEFINE_STUB(spdk_scsi_dev_add_port, int,
|
|
|
|
(struct spdk_scsi_dev *dev, uint64_t id, const char *name), 0);
|
2016-08-16 21:42:15 +00:00
|
|
|
|
2020-04-15 22:28:10 +00:00
|
|
|
DEFINE_STUB(iscsi_drop_conns, int,
|
2018-12-10 00:58:26 +00:00
|
|
|
(struct spdk_iscsi_conn *conn, const char *conn_match, int drop_all),
|
|
|
|
0);
|
2016-08-16 21:42:15 +00:00
|
|
|
|
2018-12-10 00:58:26 +00:00
|
|
|
DEFINE_STUB(spdk_scsi_dev_delete_port, int,
|
|
|
|
(struct spdk_scsi_dev *dev, uint64_t id), 0);
|
2017-12-05 06:42:37 +00:00
|
|
|
|
2020-04-15 22:28:10 +00:00
|
|
|
DEFINE_STUB_V(shutdown_iscsi_conns, (void));
|
2016-08-16 21:42:15 +00:00
|
|
|
|
2020-07-05 08:43:02 +00:00
|
|
|
DEFINE_STUB_V(iscsi_conns_request_logout, (struct spdk_iscsi_tgt_node *target, int pg_tag));
|
2019-04-10 08:01:43 +00:00
|
|
|
|
2020-04-15 22:28:10 +00:00
|
|
|
DEFINE_STUB(iscsi_get_active_conns, int, (struct spdk_iscsi_tgt_node *target), 0);
|
2019-04-10 08:01:43 +00:00
|
|
|
|
2016-08-16 21:42:15 +00:00
|
|
|
void
|
2020-04-15 22:28:10 +00:00
|
|
|
iscsi_task_cpl(struct spdk_scsi_task *scsi_task)
|
2016-08-16 21:42:15 +00:00
|
|
|
{
|
2018-12-09 23:12:11 +00:00
|
|
|
struct spdk_iscsi_task *iscsi_task;
|
2017-06-08 20:45:41 +00:00
|
|
|
|
2018-12-09 23:12:11 +00:00
|
|
|
if (scsi_task != NULL) {
|
2020-04-15 20:30:47 +00:00
|
|
|
iscsi_task = iscsi_task_from_scsi_task(scsi_task);
|
2019-11-11 21:50:52 +00:00
|
|
|
if (iscsi_task->parent && (iscsi_task->scsi.dxfer_dir == SPDK_SCSI_DIR_FROM_DEV)) {
|
|
|
|
assert(iscsi_task->conn->data_in_cnt > 0);
|
|
|
|
iscsi_task->conn->data_in_cnt--;
|
|
|
|
}
|
|
|
|
|
2018-12-09 23:12:11 +00:00
|
|
|
free(iscsi_task);
|
|
|
|
}
|
2016-08-16 21:42:15 +00:00
|
|
|
}
|
|
|
|
|
2020-04-15 22:28:10 +00:00
|
|
|
DEFINE_STUB_V(iscsi_task_mgmt_cpl, (struct spdk_scsi_task *scsi_task));
|
2017-06-08 20:45:41 +00:00
|
|
|
|
2021-10-21 06:29:34 +00:00
|
|
|
#define MAKE_DIGEST_WORD(BUF, CRC32C) \
|
|
|
|
( ((*((uint8_t *)(BUF)+0)) = (uint8_t)((uint32_t)(CRC32C) >> 0)), \
|
|
|
|
((*((uint8_t *)(BUF)+1)) = (uint8_t)((uint32_t)(CRC32C) >> 8)), \
|
|
|
|
((*((uint8_t *)(BUF)+2)) = (uint8_t)((uint32_t)(CRC32C) >> 16)), \
|
|
|
|
((*((uint8_t *)(BUF)+3)) = (uint8_t)((uint32_t)(CRC32C) >> 24)))
|
|
|
|
|
2021-03-01 13:05:05 +00:00
|
|
|
int
|
|
|
|
iscsi_conn_read_data(struct spdk_iscsi_conn *conn, int bytes, void *buf)
|
|
|
|
{
|
|
|
|
uint32_t *data = buf;
|
|
|
|
int i;
|
|
|
|
|
2021-10-21 06:29:34 +00:00
|
|
|
if (g_conn_read_data_digest) {
|
|
|
|
MAKE_DIGEST_WORD(buf, g_data_digest);
|
|
|
|
return ISCSI_DIGEST_LEN;
|
|
|
|
}
|
|
|
|
|
2021-03-01 13:05:05 +00:00
|
|
|
/* Limit the length to 4 bytes multiples. */
|
|
|
|
SPDK_CU_ASSERT_FATAL((bytes % 4) == 0);
|
|
|
|
|
|
|
|
for (i = 0; i < bytes; i += 4) {
|
|
|
|
data[i / 4] = g_conn_read_len + i;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_conn_read_len += bytes;
|
|
|
|
|
|
|
|
return bytes;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
iscsi_conn_readv_data(struct spdk_iscsi_conn *conn, struct iovec *iov, int iovcnt)
|
|
|
|
{
|
|
|
|
int i, len = 0;
|
2016-08-16 21:42:15 +00:00
|
|
|
|
2021-03-01 13:05:05 +00:00
|
|
|
for (i = 0; i < iovcnt; i++) {
|
|
|
|
len += iov[i].iov_len;
|
|
|
|
}
|
|
|
|
|
|
|
|
return len;
|
|
|
|
}
|
2019-02-27 02:06:25 +00:00
|
|
|
|
2018-01-18 06:34:47 +00:00
|
|
|
void
|
2020-04-15 22:28:10 +00:00
|
|
|
iscsi_conn_write_pdu(struct spdk_iscsi_conn *conn, struct spdk_iscsi_pdu *pdu,
|
|
|
|
iscsi_conn_xfer_complete_cb cb_fn, void *cb_arg)
|
2018-01-18 06:34:47 +00:00
|
|
|
{
|
|
|
|
TAILQ_INSERT_TAIL(&g_write_pdu_list, pdu, tailq);
|
|
|
|
}
|
|
|
|
|
2020-04-15 22:28:10 +00:00
|
|
|
DEFINE_STUB_V(iscsi_conn_logout, (struct spdk_iscsi_conn *conn));
|
2016-08-16 21:42:15 +00:00
|
|
|
|
2018-12-10 00:58:26 +00:00
|
|
|
DEFINE_STUB_V(spdk_scsi_task_set_status,
|
|
|
|
(struct spdk_scsi_task *task, int sc, int sk, int asc, int ascq));
|
2016-11-22 19:47:04 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
spdk_scsi_task_set_data(struct spdk_scsi_task *task, void *data, uint32_t len)
|
|
|
|
{
|
2018-08-29 22:28:21 +00:00
|
|
|
SPDK_CU_ASSERT_FATAL(task->iovs != NULL);
|
2016-11-22 19:47:04 +00:00
|
|
|
task->iovs[0].iov_base = data;
|
|
|
|
task->iovs[0].iov_len = len;
|
|
|
|
}
|