forked from Minki/linux
Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending
Pull SCSI target updates from Nicholas Bellinger: "The highlights this round include: - Update vhost-scsi to support F_ANY_LAYOUT using mm/iov_iter.c logic, and signal VERSION_1 support (MST + Viro + nab) - Fix iscsi/iser-target to remove problematic active_ts_set usage (Gavin Guo) - Update iscsi/iser-target to support multi-sequence sendtargets (Sagi) - Fix original PR_APTPL_BUF_LEN 8k size limitation (Martin Svec) - Add missing WRITE_SAME end-of-device sanity check (Bart) - Check for LBA + sectors wrap-around in sbc_parse_cdb() (nab) - Other various minor SPC/SBC compliance fixes based upon Ronnie Sahlberg test suite (nab)" * 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending: (32 commits) target: Set LBPWS10 bit in Logical Block Provisioning EVPD target: Fail UNMAP when emulate_tpu=0 target: Fail WRITE_SAME w/ UNMAP=1 when emulate_tpws=0 target: Add sanity checks for DPO/FUA bit usage target: Perform PROTECT sanity checks for WRITE_SAME target: Fail I/O with PROTECT bit when protection is unsupported target: Check for LBA + sectors wrap-around in sbc_parse_cdb target: Add missing WRITE_SAME end-of-device sanity check iscsi-target: Avoid IN_LOGOUT failure case for iser-target target: Fix PR_APTPL_BUF_LEN buffer size limitation iscsi-target: Drop problematic active_ts_list usage iscsi/iser-target: Support multi-sequence sendtargets text response iser-target: Remove duplicate function names vhost/scsi: potential memory corruption vhost/scsi: Global tcm_vhost -> vhost_scsi rename vhost/scsi: Drop left-over scsi_tcq.h include vhost/scsi: Set VIRTIO_F_ANY_LAYOUT + VIRTIO_F_VERSION_1 feature bits vhost/scsi: Add ANY_LAYOUT support in vhost_scsi_handle_vq vhost/scsi: Add ANY_LAYOUT iov -> sgl mapping prerequisites vhost/scsi: Change vhost_scsi_map_to_sgl to accept iov ptr + len ...
This commit is contained in:
commit
e20d3ef540
@ -38,7 +38,7 @@
|
||||
#define ISER_MAX_CQ_LEN (ISER_MAX_RX_CQ_LEN + ISER_MAX_TX_CQ_LEN + \
|
||||
ISERT_MAX_CONN)
|
||||
|
||||
int isert_debug_level = 0;
|
||||
static int isert_debug_level;
|
||||
module_param_named(debug_level, isert_debug_level, int, 0644);
|
||||
MODULE_PARM_DESC(debug_level, "Enable debug tracing if > 0 (default:0)");
|
||||
|
||||
@ -949,7 +949,7 @@ isert_post_recv(struct isert_conn *isert_conn, u32 count)
|
||||
isert_err("ib_post_recv() failed with ret: %d\n", ret);
|
||||
isert_conn->post_recv_buf_count -= count;
|
||||
} else {
|
||||
isert_dbg("isert_post_recv(): Posted %d RX buffers\n", count);
|
||||
isert_dbg("Posted %d RX buffers\n", count);
|
||||
isert_conn->conn_rx_desc_head = rx_head;
|
||||
}
|
||||
return ret;
|
||||
@ -1351,18 +1351,20 @@ isert_handle_text_cmd(struct isert_conn *isert_conn, struct isert_cmd *isert_cmd
|
||||
struct iscsi_conn *conn = isert_conn->conn;
|
||||
u32 payload_length = ntoh24(hdr->dlength);
|
||||
int rc;
|
||||
unsigned char *text_in;
|
||||
unsigned char *text_in = NULL;
|
||||
|
||||
rc = iscsit_setup_text_cmd(conn, cmd, hdr);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
if (payload_length) {
|
||||
text_in = kzalloc(payload_length, GFP_KERNEL);
|
||||
if (!text_in) {
|
||||
isert_err("Unable to allocate text_in of payload_length: %u\n",
|
||||
payload_length);
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
cmd->text_in_ptr = text_in;
|
||||
|
||||
memcpy(cmd->text_in_ptr, &rx_desc->data[0], payload_length);
|
||||
@ -1434,9 +1436,15 @@ isert_rx_opcode(struct isert_conn *isert_conn, struct iser_rx_desc *rx_desc,
|
||||
ret = iscsit_handle_logout_cmd(conn, cmd, (unsigned char *)hdr);
|
||||
break;
|
||||
case ISCSI_OP_TEXT:
|
||||
if (be32_to_cpu(hdr->ttt) != 0xFFFFFFFF) {
|
||||
cmd = iscsit_find_cmd_from_itt(conn, hdr->itt);
|
||||
if (!cmd)
|
||||
break;
|
||||
} else {
|
||||
cmd = isert_allocate_cmd(conn);
|
||||
if (!cmd)
|
||||
break;
|
||||
}
|
||||
|
||||
isert_cmd = iscsit_priv_cmd(cmd);
|
||||
ret = isert_handle_text_cmd(isert_conn, isert_cmd, cmd,
|
||||
@ -1658,6 +1666,7 @@ isert_put_cmd(struct isert_cmd *isert_cmd, bool comp_err)
|
||||
struct isert_conn *isert_conn = isert_cmd->conn;
|
||||
struct iscsi_conn *conn = isert_conn->conn;
|
||||
struct isert_device *device = isert_conn->conn_device;
|
||||
struct iscsi_text_rsp *hdr;
|
||||
|
||||
isert_dbg("Cmd %p\n", isert_cmd);
|
||||
|
||||
@ -1698,6 +1707,11 @@ isert_put_cmd(struct isert_cmd *isert_cmd, bool comp_err)
|
||||
case ISCSI_OP_REJECT:
|
||||
case ISCSI_OP_NOOP_OUT:
|
||||
case ISCSI_OP_TEXT:
|
||||
hdr = (struct iscsi_text_rsp *)&isert_cmd->tx_desc.iscsi_header;
|
||||
/* If the continue bit is on, keep the command alive */
|
||||
if (hdr->flags & ISCSI_FLAG_TEXT_CONTINUE)
|
||||
break;
|
||||
|
||||
spin_lock_bh(&conn->cmd_lock);
|
||||
if (!list_empty(&cmd->i_conn_node))
|
||||
list_del_init(&cmd->i_conn_node);
|
||||
@ -1709,8 +1723,7 @@ isert_put_cmd(struct isert_cmd *isert_cmd, bool comp_err)
|
||||
* associated cmd->se_cmd needs to be released.
|
||||
*/
|
||||
if (cmd->se_cmd.se_tfo != NULL) {
|
||||
isert_dbg("Calling transport_generic_free_cmd from"
|
||||
" isert_put_cmd for 0x%02x\n",
|
||||
isert_dbg("Calling transport_generic_free_cmd for 0x%02x\n",
|
||||
cmd->iscsi_opcode);
|
||||
transport_generic_free_cmd(&cmd->se_cmd, 0);
|
||||
break;
|
||||
@ -2275,7 +2288,7 @@ isert_put_text_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn)
|
||||
}
|
||||
isert_init_send_wr(isert_conn, isert_cmd, send_wr);
|
||||
|
||||
isert_dbg("conn %p Text Reject\n", isert_conn);
|
||||
isert_dbg("conn %p Text Response\n", isert_conn);
|
||||
|
||||
return isert_post_response(isert_conn, isert_cmd);
|
||||
}
|
||||
@ -3136,7 +3149,7 @@ accept_wait:
|
||||
spin_lock_bh(&np->np_thread_lock);
|
||||
if (np->np_thread_state >= ISCSI_NP_THREAD_RESET) {
|
||||
spin_unlock_bh(&np->np_thread_lock);
|
||||
isert_dbg("np_thread_state %d for isert_accept_np\n",
|
||||
isert_dbg("np_thread_state %d\n",
|
||||
np->np_thread_state);
|
||||
/**
|
||||
* No point in stalling here when np_thread
|
||||
@ -3320,7 +3333,8 @@ static int __init isert_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
isert_comp_wq = alloc_workqueue("isert_comp_wq", 0, 0);
|
||||
isert_comp_wq = alloc_workqueue("isert_comp_wq",
|
||||
WQ_UNBOUND | WQ_HIGHPRI, 0);
|
||||
if (!isert_comp_wq) {
|
||||
isert_err("Unable to allocate isert_comp_wq\n");
|
||||
ret = -ENOMEM;
|
||||
|
@ -3518,7 +3518,7 @@ static void srpt_close_session(struct se_session *se_sess)
|
||||
DECLARE_COMPLETION_ONSTACK(release_done);
|
||||
struct srpt_rdma_ch *ch;
|
||||
struct srpt_device *sdev;
|
||||
int res;
|
||||
unsigned long res;
|
||||
|
||||
ch = se_sess->fabric_sess_ptr;
|
||||
WARN_ON(ch->sess != se_sess);
|
||||
@ -3533,7 +3533,7 @@ static void srpt_close_session(struct se_session *se_sess)
|
||||
spin_unlock_irq(&sdev->spinlock);
|
||||
|
||||
res = wait_for_completion_timeout(&release_done, 60 * HZ);
|
||||
WARN_ON(res <= 0);
|
||||
WARN_ON(res == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1570,9 +1570,7 @@ static int tcm_qla2xxx_check_initiator_node_acl(
|
||||
* match the format by tcm_qla2xxx explict ConfigFS NodeACLs.
|
||||
*/
|
||||
memset(&port_name, 0, 36);
|
||||
snprintf(port_name, 36, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
fc_wwpn[0], fc_wwpn[1], fc_wwpn[2], fc_wwpn[3], fc_wwpn[4],
|
||||
fc_wwpn[5], fc_wwpn[6], fc_wwpn[7]);
|
||||
snprintf(port_name, sizeof(port_name), "%8phC", fc_wwpn);
|
||||
/*
|
||||
* Locate our struct se_node_acl either from an explict NodeACL created
|
||||
* via ConfigFS, or via running in TPG demo mode.
|
||||
|
@ -30,7 +30,7 @@
|
||||
#include <target/target_core_fabric.h>
|
||||
#include <target/target_core_configfs.h>
|
||||
|
||||
#include "iscsi_target_core.h"
|
||||
#include <target/iscsi/iscsi_target_core.h>
|
||||
#include "iscsi_target_parameters.h"
|
||||
#include "iscsi_target_seq_pdu_list.h"
|
||||
#include "iscsi_target_tq.h"
|
||||
@ -45,7 +45,7 @@
|
||||
#include "iscsi_target_util.h"
|
||||
#include "iscsi_target.h"
|
||||
#include "iscsi_target_device.h"
|
||||
#include "iscsi_target_stat.h"
|
||||
#include <target/iscsi/iscsi_target_stat.h>
|
||||
|
||||
#include <target/iscsi/iscsi_transport.h>
|
||||
|
||||
@ -968,11 +968,7 @@ int iscsit_setup_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
|
||||
|
||||
conn->sess->init_task_tag = cmd->init_task_tag = hdr->itt;
|
||||
if (hdr->flags & ISCSI_FLAG_CMD_READ) {
|
||||
spin_lock_bh(&conn->sess->ttt_lock);
|
||||
cmd->targ_xfer_tag = conn->sess->targ_xfer_tag++;
|
||||
if (cmd->targ_xfer_tag == 0xFFFFFFFF)
|
||||
cmd->targ_xfer_tag = conn->sess->targ_xfer_tag++;
|
||||
spin_unlock_bh(&conn->sess->ttt_lock);
|
||||
cmd->targ_xfer_tag = session_get_next_ttt(conn->sess);
|
||||
} else if (hdr->flags & ISCSI_FLAG_CMD_WRITE)
|
||||
cmd->targ_xfer_tag = 0xFFFFFFFF;
|
||||
cmd->cmd_sn = be32_to_cpu(hdr->cmdsn);
|
||||
@ -1998,6 +1994,7 @@ iscsit_setup_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
|
||||
cmd->cmd_sn = be32_to_cpu(hdr->cmdsn);
|
||||
cmd->exp_stat_sn = be32_to_cpu(hdr->exp_statsn);
|
||||
cmd->data_direction = DMA_NONE;
|
||||
cmd->text_in_ptr = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -2011,10 +2008,14 @@ iscsit_process_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
|
||||
int cmdsn_ret;
|
||||
|
||||
if (!text_in) {
|
||||
cmd->targ_xfer_tag = be32_to_cpu(hdr->ttt);
|
||||
if (cmd->targ_xfer_tag == 0xFFFFFFFF) {
|
||||
pr_err("Unable to locate text_in buffer for sendtargets"
|
||||
" discovery\n");
|
||||
goto reject;
|
||||
}
|
||||
goto empty_sendtargets;
|
||||
}
|
||||
if (strncmp("SendTargets", text_in, 11) != 0) {
|
||||
pr_err("Received Text Data that is not"
|
||||
" SendTargets, cannot continue.\n");
|
||||
@ -2040,6 +2041,7 @@ iscsit_process_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
|
||||
list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
|
||||
spin_unlock_bh(&conn->cmd_lock);
|
||||
|
||||
empty_sendtargets:
|
||||
iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn));
|
||||
|
||||
if (!(hdr->opcode & ISCSI_OP_IMMEDIATE)) {
|
||||
@ -3047,11 +3049,7 @@ static int iscsit_send_r2t(
|
||||
int_to_scsilun(cmd->se_cmd.orig_fe_lun,
|
||||
(struct scsi_lun *)&hdr->lun);
|
||||
hdr->itt = cmd->init_task_tag;
|
||||
spin_lock_bh(&conn->sess->ttt_lock);
|
||||
r2t->targ_xfer_tag = conn->sess->targ_xfer_tag++;
|
||||
if (r2t->targ_xfer_tag == 0xFFFFFFFF)
|
||||
r2t->targ_xfer_tag = conn->sess->targ_xfer_tag++;
|
||||
spin_unlock_bh(&conn->sess->ttt_lock);
|
||||
r2t->targ_xfer_tag = session_get_next_ttt(conn->sess);
|
||||
hdr->ttt = cpu_to_be32(r2t->targ_xfer_tag);
|
||||
hdr->statsn = cpu_to_be32(conn->stat_sn);
|
||||
hdr->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_sn);
|
||||
@ -3393,7 +3391,8 @@ static bool iscsit_check_inaddr_any(struct iscsi_np *np)
|
||||
|
||||
static int
|
||||
iscsit_build_sendtargets_response(struct iscsi_cmd *cmd,
|
||||
enum iscsit_transport_type network_transport)
|
||||
enum iscsit_transport_type network_transport,
|
||||
int skip_bytes, bool *completed)
|
||||
{
|
||||
char *payload = NULL;
|
||||
struct iscsi_conn *conn = cmd->conn;
|
||||
@ -3405,7 +3404,7 @@ iscsit_build_sendtargets_response(struct iscsi_cmd *cmd,
|
||||
unsigned char buf[ISCSI_IQN_LEN+12]; /* iqn + "TargetName=" + \0 */
|
||||
unsigned char *text_in = cmd->text_in_ptr, *text_ptr = NULL;
|
||||
|
||||
buffer_len = max(conn->conn_ops->MaxRecvDataSegmentLength,
|
||||
buffer_len = min(conn->conn_ops->MaxRecvDataSegmentLength,
|
||||
SENDTARGETS_BUF_LIMIT);
|
||||
|
||||
payload = kzalloc(buffer_len, GFP_KERNEL);
|
||||
@ -3484,9 +3483,16 @@ iscsit_build_sendtargets_response(struct iscsi_cmd *cmd,
|
||||
end_of_buf = 1;
|
||||
goto eob;
|
||||
}
|
||||
|
||||
if (skip_bytes && len <= skip_bytes) {
|
||||
skip_bytes -= len;
|
||||
} else {
|
||||
memcpy(payload + payload_len, buf, len);
|
||||
payload_len += len;
|
||||
target_name_printed = 1;
|
||||
if (len > skip_bytes)
|
||||
skip_bytes = 0;
|
||||
}
|
||||
}
|
||||
|
||||
len = sprintf(buf, "TargetAddress="
|
||||
@ -3502,15 +3508,24 @@ iscsit_build_sendtargets_response(struct iscsi_cmd *cmd,
|
||||
end_of_buf = 1;
|
||||
goto eob;
|
||||
}
|
||||
|
||||
if (skip_bytes && len <= skip_bytes) {
|
||||
skip_bytes -= len;
|
||||
} else {
|
||||
memcpy(payload + payload_len, buf, len);
|
||||
payload_len += len;
|
||||
if (len > skip_bytes)
|
||||
skip_bytes = 0;
|
||||
}
|
||||
}
|
||||
spin_unlock(&tpg->tpg_np_lock);
|
||||
}
|
||||
spin_unlock(&tiqn->tiqn_tpg_lock);
|
||||
eob:
|
||||
if (end_of_buf)
|
||||
if (end_of_buf) {
|
||||
*completed = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (cmd->cmd_flags & ICF_SENDTARGETS_SINGLE)
|
||||
break;
|
||||
@ -3528,13 +3543,23 @@ iscsit_build_text_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
|
||||
enum iscsit_transport_type network_transport)
|
||||
{
|
||||
int text_length, padding;
|
||||
bool completed = true;
|
||||
|
||||
text_length = iscsit_build_sendtargets_response(cmd, network_transport);
|
||||
text_length = iscsit_build_sendtargets_response(cmd, network_transport,
|
||||
cmd->read_data_done,
|
||||
&completed);
|
||||
if (text_length < 0)
|
||||
return text_length;
|
||||
|
||||
hdr->opcode = ISCSI_OP_TEXT_RSP;
|
||||
if (completed) {
|
||||
hdr->flags |= ISCSI_FLAG_CMD_FINAL;
|
||||
} else {
|
||||
hdr->flags |= ISCSI_FLAG_TEXT_CONTINUE;
|
||||
cmd->read_data_done += text_length;
|
||||
if (cmd->targ_xfer_tag == 0xFFFFFFFF)
|
||||
cmd->targ_xfer_tag = session_get_next_ttt(conn->sess);
|
||||
}
|
||||
hdr->opcode = ISCSI_OP_TEXT_RSP;
|
||||
padding = ((-text_length) & 3);
|
||||
hton24(hdr->dlength, text_length);
|
||||
hdr->itt = cmd->init_task_tag;
|
||||
@ -3543,21 +3568,25 @@ iscsit_build_text_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
|
||||
hdr->statsn = cpu_to_be32(cmd->stat_sn);
|
||||
|
||||
iscsit_increment_maxcmdsn(cmd, conn->sess);
|
||||
/*
|
||||
* Reset maxcmdsn_inc in multi-part text payload exchanges to
|
||||
* correctly increment MaxCmdSN for each response answering a
|
||||
* non immediate text request with a valid CmdSN.
|
||||
*/
|
||||
cmd->maxcmdsn_inc = 0;
|
||||
hdr->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_sn);
|
||||
hdr->max_cmdsn = cpu_to_be32(conn->sess->max_cmd_sn);
|
||||
|
||||
pr_debug("Built Text Response: ITT: 0x%08x, StatSN: 0x%08x,"
|
||||
" Length: %u, CID: %hu\n", cmd->init_task_tag, cmd->stat_sn,
|
||||
text_length, conn->cid);
|
||||
pr_debug("Built Text Response: ITT: 0x%08x, TTT: 0x%08x, StatSN: 0x%08x,"
|
||||
" Length: %u, CID: %hu F: %d C: %d\n", cmd->init_task_tag,
|
||||
cmd->targ_xfer_tag, cmd->stat_sn, text_length, conn->cid,
|
||||
!!(hdr->flags & ISCSI_FLAG_CMD_FINAL),
|
||||
!!(hdr->flags & ISCSI_FLAG_TEXT_CONTINUE));
|
||||
|
||||
return text_length + padding;
|
||||
}
|
||||
EXPORT_SYMBOL(iscsit_build_text_rsp);
|
||||
|
||||
/*
|
||||
* FIXME: Add support for F_BIT and C_BIT when the length is longer than
|
||||
* MaxRecvDataSegmentLength.
|
||||
*/
|
||||
static int iscsit_send_text_rsp(
|
||||
struct iscsi_cmd *cmd,
|
||||
struct iscsi_conn *conn)
|
||||
@ -4021,9 +4050,15 @@ static int iscsi_target_rx_opcode(struct iscsi_conn *conn, unsigned char *buf)
|
||||
ret = iscsit_handle_task_mgt_cmd(conn, cmd, buf);
|
||||
break;
|
||||
case ISCSI_OP_TEXT:
|
||||
if (hdr->ttt != cpu_to_be32(0xFFFFFFFF)) {
|
||||
cmd = iscsit_find_cmd_from_itt(conn, hdr->itt);
|
||||
if (!cmd)
|
||||
goto reject;
|
||||
} else {
|
||||
cmd = iscsit_allocate_cmd(conn, TASK_INTERRUPTIBLE);
|
||||
if (!cmd)
|
||||
goto reject;
|
||||
}
|
||||
|
||||
ret = iscsit_handle_text_cmd(conn, cmd, buf);
|
||||
break;
|
||||
|
@ -22,7 +22,7 @@
|
||||
#include <linux/err.h>
|
||||
#include <linux/scatterlist.h>
|
||||
|
||||
#include "iscsi_target_core.h"
|
||||
#include <target/iscsi/iscsi_target_core.h>
|
||||
#include "iscsi_target_nego.h"
|
||||
#include "iscsi_target_auth.h"
|
||||
|
||||
|
@ -28,7 +28,7 @@
|
||||
#include <target/configfs_macros.h>
|
||||
#include <target/iscsi/iscsi_transport.h>
|
||||
|
||||
#include "iscsi_target_core.h"
|
||||
#include <target/iscsi/iscsi_target_core.h>
|
||||
#include "iscsi_target_parameters.h"
|
||||
#include "iscsi_target_device.h"
|
||||
#include "iscsi_target_erl0.h"
|
||||
@ -36,7 +36,7 @@
|
||||
#include "iscsi_target_tpg.h"
|
||||
#include "iscsi_target_util.h"
|
||||
#include "iscsi_target.h"
|
||||
#include "iscsi_target_stat.h"
|
||||
#include <target/iscsi/iscsi_target_stat.h>
|
||||
#include "iscsi_target_configfs.h"
|
||||
|
||||
struct target_fabric_configfs *lio_target_fabric_configfs;
|
||||
@ -674,12 +674,9 @@ static ssize_t lio_target_nacl_show_info(
|
||||
rb += sprintf(page+rb, "InitiatorAlias: %s\n",
|
||||
sess->sess_ops->InitiatorAlias);
|
||||
|
||||
rb += sprintf(page+rb, "LIO Session ID: %u "
|
||||
"ISID: 0x%02x %02x %02x %02x %02x %02x "
|
||||
"TSIH: %hu ", sess->sid,
|
||||
sess->isid[0], sess->isid[1], sess->isid[2],
|
||||
sess->isid[3], sess->isid[4], sess->isid[5],
|
||||
sess->tsih);
|
||||
rb += sprintf(page+rb,
|
||||
"LIO Session ID: %u ISID: 0x%6ph TSIH: %hu ",
|
||||
sess->sid, sess->isid, sess->tsih);
|
||||
rb += sprintf(page+rb, "SessionType: %s\n",
|
||||
(sess->sess_ops->SessionType) ?
|
||||
"Discovery" : "Normal");
|
||||
@ -1758,9 +1755,7 @@ static u32 lio_sess_get_initiator_sid(
|
||||
/*
|
||||
* iSCSI Initiator Session Identifier from RFC-3720.
|
||||
*/
|
||||
return snprintf(buf, size, "%02x%02x%02x%02x%02x%02x",
|
||||
sess->isid[0], sess->isid[1], sess->isid[2],
|
||||
sess->isid[3], sess->isid[4], sess->isid[5]);
|
||||
return snprintf(buf, size, "%6phN", sess->isid);
|
||||
}
|
||||
|
||||
static int lio_queue_data_in(struct se_cmd *se_cmd)
|
||||
|
@ -18,7 +18,7 @@
|
||||
|
||||
#include <scsi/iscsi_proto.h>
|
||||
|
||||
#include "iscsi_target_core.h"
|
||||
#include <target/iscsi/iscsi_target_core.h>
|
||||
#include "iscsi_target_seq_pdu_list.h"
|
||||
#include "iscsi_target_erl1.h"
|
||||
#include "iscsi_target_util.h"
|
||||
|
@ -21,7 +21,7 @@
|
||||
#include <target/target_core_base.h>
|
||||
#include <target/target_core_fabric.h>
|
||||
|
||||
#include "iscsi_target_core.h"
|
||||
#include <target/iscsi/iscsi_target_core.h>
|
||||
#include "iscsi_target_device.h"
|
||||
#include "iscsi_target_tpg.h"
|
||||
#include "iscsi_target_util.h"
|
||||
|
@ -21,7 +21,8 @@
|
||||
#include <target/target_core_base.h>
|
||||
#include <target/target_core_fabric.h>
|
||||
|
||||
#include "iscsi_target_core.h"
|
||||
#include <target/iscsi/iscsi_target_core.h>
|
||||
#include <target/iscsi/iscsi_transport.h>
|
||||
#include "iscsi_target_seq_pdu_list.h"
|
||||
#include "iscsi_target_tq.h"
|
||||
#include "iscsi_target_erl0.h"
|
||||
@ -939,6 +940,7 @@ void iscsit_take_action_for_connection_exit(struct iscsi_conn *conn)
|
||||
|
||||
if (conn->conn_state == TARG_CONN_STATE_IN_LOGOUT) {
|
||||
spin_unlock_bh(&conn->state_lock);
|
||||
if (conn->conn_transport->transport_type == ISCSI_TCP)
|
||||
iscsit_close_connection(conn);
|
||||
return;
|
||||
}
|
||||
|
@ -22,7 +22,7 @@
|
||||
#include <target/target_core_fabric.h>
|
||||
#include <target/iscsi/iscsi_transport.h>
|
||||
|
||||
#include "iscsi_target_core.h"
|
||||
#include <target/iscsi/iscsi_target_core.h>
|
||||
#include "iscsi_target_seq_pdu_list.h"
|
||||
#include "iscsi_target_datain_values.h"
|
||||
#include "iscsi_target_device.h"
|
||||
|
@ -21,7 +21,7 @@
|
||||
#include <target/target_core_base.h>
|
||||
#include <target/target_core_fabric.h>
|
||||
|
||||
#include "iscsi_target_core.h"
|
||||
#include <target/iscsi/iscsi_target_core.h>
|
||||
#include "iscsi_target_datain_values.h"
|
||||
#include "iscsi_target_util.h"
|
||||
#include "iscsi_target_erl0.h"
|
||||
|
@ -24,14 +24,14 @@
|
||||
#include <target/target_core_base.h>
|
||||
#include <target/target_core_fabric.h>
|
||||
|
||||
#include "iscsi_target_core.h"
|
||||
#include <target/iscsi/iscsi_target_core.h>
|
||||
#include <target/iscsi/iscsi_target_stat.h>
|
||||
#include "iscsi_target_tq.h"
|
||||
#include "iscsi_target_device.h"
|
||||
#include "iscsi_target_nego.h"
|
||||
#include "iscsi_target_erl0.h"
|
||||
#include "iscsi_target_erl2.h"
|
||||
#include "iscsi_target_login.h"
|
||||
#include "iscsi_target_stat.h"
|
||||
#include "iscsi_target_tpg.h"
|
||||
#include "iscsi_target_util.h"
|
||||
#include "iscsi_target.h"
|
||||
|
@ -22,7 +22,7 @@
|
||||
#include <target/target_core_fabric.h>
|
||||
#include <target/iscsi/iscsi_transport.h>
|
||||
|
||||
#include "iscsi_target_core.h"
|
||||
#include <target/iscsi/iscsi_target_core.h>
|
||||
#include "iscsi_target_parameters.h"
|
||||
#include "iscsi_target_login.h"
|
||||
#include "iscsi_target_nego.h"
|
||||
|
@ -18,7 +18,7 @@
|
||||
|
||||
#include <target/target_core_base.h>
|
||||
|
||||
#include "iscsi_target_core.h"
|
||||
#include <target/iscsi/iscsi_target_core.h>
|
||||
#include "iscsi_target_device.h"
|
||||
#include "iscsi_target_tpg.h"
|
||||
#include "iscsi_target_util.h"
|
||||
|
@ -18,7 +18,7 @@
|
||||
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "iscsi_target_core.h"
|
||||
#include <target/iscsi/iscsi_target_core.h>
|
||||
#include "iscsi_target_util.h"
|
||||
#include "iscsi_target_parameters.h"
|
||||
|
||||
|
@ -20,7 +20,7 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/random.h>
|
||||
|
||||
#include "iscsi_target_core.h"
|
||||
#include <target/iscsi/iscsi_target_core.h>
|
||||
#include "iscsi_target_util.h"
|
||||
#include "iscsi_target_tpg.h"
|
||||
#include "iscsi_target_seq_pdu_list.h"
|
||||
|
@ -23,12 +23,12 @@
|
||||
#include <target/target_core_base.h>
|
||||
#include <target/configfs_macros.h>
|
||||
|
||||
#include "iscsi_target_core.h"
|
||||
#include <target/iscsi/iscsi_target_core.h>
|
||||
#include "iscsi_target_parameters.h"
|
||||
#include "iscsi_target_device.h"
|
||||
#include "iscsi_target_tpg.h"
|
||||
#include "iscsi_target_util.h"
|
||||
#include "iscsi_target_stat.h"
|
||||
#include <target/iscsi/iscsi_target_stat.h>
|
||||
|
||||
#ifndef INITIAL_JIFFIES
|
||||
#define INITIAL_JIFFIES ((unsigned long)(unsigned int) (-300*HZ))
|
||||
|
@ -23,7 +23,7 @@
|
||||
#include <target/target_core_fabric.h>
|
||||
#include <target/iscsi/iscsi_transport.h>
|
||||
|
||||
#include "iscsi_target_core.h"
|
||||
#include <target/iscsi/iscsi_target_core.h>
|
||||
#include "iscsi_target_seq_pdu_list.h"
|
||||
#include "iscsi_target_datain_values.h"
|
||||
#include "iscsi_target_device.h"
|
||||
|
@ -20,7 +20,7 @@
|
||||
#include <target/target_core_fabric.h>
|
||||
#include <target/target_core_configfs.h>
|
||||
|
||||
#include "iscsi_target_core.h"
|
||||
#include <target/iscsi/iscsi_target_core.h>
|
||||
#include "iscsi_target_erl0.h"
|
||||
#include "iscsi_target_login.h"
|
||||
#include "iscsi_target_nodeattrib.h"
|
||||
|
@ -20,40 +20,26 @@
|
||||
#include <linux/list.h>
|
||||
#include <linux/bitmap.h>
|
||||
|
||||
#include "iscsi_target_core.h"
|
||||
#include <target/iscsi/iscsi_target_core.h>
|
||||
#include "iscsi_target_tq.h"
|
||||
#include "iscsi_target.h"
|
||||
|
||||
static LIST_HEAD(active_ts_list);
|
||||
static LIST_HEAD(inactive_ts_list);
|
||||
static DEFINE_SPINLOCK(active_ts_lock);
|
||||
static DEFINE_SPINLOCK(inactive_ts_lock);
|
||||
static DEFINE_SPINLOCK(ts_bitmap_lock);
|
||||
|
||||
static void iscsi_add_ts_to_active_list(struct iscsi_thread_set *ts)
|
||||
{
|
||||
spin_lock(&active_ts_lock);
|
||||
list_add_tail(&ts->ts_list, &active_ts_list);
|
||||
iscsit_global->active_ts++;
|
||||
spin_unlock(&active_ts_lock);
|
||||
}
|
||||
|
||||
static void iscsi_add_ts_to_inactive_list(struct iscsi_thread_set *ts)
|
||||
{
|
||||
if (!list_empty(&ts->ts_list)) {
|
||||
WARN_ON(1);
|
||||
return;
|
||||
}
|
||||
spin_lock(&inactive_ts_lock);
|
||||
list_add_tail(&ts->ts_list, &inactive_ts_list);
|
||||
iscsit_global->inactive_ts++;
|
||||
spin_unlock(&inactive_ts_lock);
|
||||
}
|
||||
|
||||
static void iscsi_del_ts_from_active_list(struct iscsi_thread_set *ts)
|
||||
{
|
||||
spin_lock(&active_ts_lock);
|
||||
list_del(&ts->ts_list);
|
||||
iscsit_global->active_ts--;
|
||||
spin_unlock(&active_ts_lock);
|
||||
}
|
||||
|
||||
static struct iscsi_thread_set *iscsi_get_ts_from_inactive_list(void)
|
||||
{
|
||||
struct iscsi_thread_set *ts;
|
||||
@ -66,7 +52,7 @@ static struct iscsi_thread_set *iscsi_get_ts_from_inactive_list(void)
|
||||
|
||||
ts = list_first_entry(&inactive_ts_list, struct iscsi_thread_set, ts_list);
|
||||
|
||||
list_del(&ts->ts_list);
|
||||
list_del_init(&ts->ts_list);
|
||||
iscsit_global->inactive_ts--;
|
||||
spin_unlock(&inactive_ts_lock);
|
||||
|
||||
@ -204,8 +190,6 @@ static void iscsi_deallocate_extra_thread_sets(void)
|
||||
|
||||
void iscsi_activate_thread_set(struct iscsi_conn *conn, struct iscsi_thread_set *ts)
|
||||
{
|
||||
iscsi_add_ts_to_active_list(ts);
|
||||
|
||||
spin_lock_bh(&ts->ts_state_lock);
|
||||
conn->thread_set = ts;
|
||||
ts->conn = conn;
|
||||
@ -397,7 +381,6 @@ struct iscsi_conn *iscsi_rx_thread_pre_handler(struct iscsi_thread_set *ts)
|
||||
|
||||
if (ts->delay_inactive && (--ts->thread_count == 0)) {
|
||||
spin_unlock_bh(&ts->ts_state_lock);
|
||||
iscsi_del_ts_from_active_list(ts);
|
||||
|
||||
if (!iscsit_global->in_shutdown)
|
||||
iscsi_deallocate_extra_thread_sets();
|
||||
@ -452,7 +435,6 @@ struct iscsi_conn *iscsi_tx_thread_pre_handler(struct iscsi_thread_set *ts)
|
||||
|
||||
if (ts->delay_inactive && (--ts->thread_count == 0)) {
|
||||
spin_unlock_bh(&ts->ts_state_lock);
|
||||
iscsi_del_ts_from_active_list(ts);
|
||||
|
||||
if (!iscsit_global->in_shutdown)
|
||||
iscsi_deallocate_extra_thread_sets();
|
||||
|
@ -25,7 +25,7 @@
|
||||
#include <target/target_core_configfs.h>
|
||||
#include <target/iscsi/iscsi_transport.h>
|
||||
|
||||
#include "iscsi_target_core.h"
|
||||
#include <target/iscsi/iscsi_target_core.h>
|
||||
#include "iscsi_target_parameters.h"
|
||||
#include "iscsi_target_seq_pdu_list.h"
|
||||
#include "iscsi_target_datain_values.h"
|
||||
@ -390,6 +390,7 @@ struct iscsi_cmd *iscsit_find_cmd_from_itt(
|
||||
init_task_tag, conn->cid);
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(iscsit_find_cmd_from_itt);
|
||||
|
||||
struct iscsi_cmd *iscsit_find_cmd_from_itt_or_dump(
|
||||
struct iscsi_conn *conn,
|
||||
@ -939,13 +940,8 @@ static int iscsit_add_nopin(struct iscsi_conn *conn, int want_response)
|
||||
state = (want_response) ? ISTATE_SEND_NOPIN_WANT_RESPONSE :
|
||||
ISTATE_SEND_NOPIN_NO_RESPONSE;
|
||||
cmd->init_task_tag = RESERVED_ITT;
|
||||
spin_lock_bh(&conn->sess->ttt_lock);
|
||||
cmd->targ_xfer_tag = (want_response) ? conn->sess->targ_xfer_tag++ :
|
||||
0xFFFFFFFF;
|
||||
if (want_response && (cmd->targ_xfer_tag == 0xFFFFFFFF))
|
||||
cmd->targ_xfer_tag = conn->sess->targ_xfer_tag++;
|
||||
spin_unlock_bh(&conn->sess->ttt_lock);
|
||||
|
||||
cmd->targ_xfer_tag = (want_response) ?
|
||||
session_get_next_ttt(conn->sess) : 0xFFFFFFFF;
|
||||
spin_lock_bh(&conn->cmd_lock);
|
||||
list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
|
||||
spin_unlock_bh(&conn->cmd_lock);
|
||||
|
@ -16,7 +16,6 @@ extern struct iscsi_r2t *iscsit_get_holder_for_r2tsn(struct iscsi_cmd *, u32);
|
||||
extern int iscsit_sequence_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
|
||||
unsigned char * ,__be32 cmdsn);
|
||||
extern int iscsit_check_unsolicited_dataout(struct iscsi_cmd *, unsigned char *);
|
||||
extern struct iscsi_cmd *iscsit_find_cmd_from_itt(struct iscsi_conn *, itt_t);
|
||||
extern struct iscsi_cmd *iscsit_find_cmd_from_itt_or_dump(struct iscsi_conn *,
|
||||
itt_t, u32);
|
||||
extern struct iscsi_cmd *iscsit_find_cmd_from_ttt(struct iscsi_conn *, u32);
|
||||
|
@ -494,6 +494,11 @@ fd_execute_write_same(struct se_cmd *cmd)
|
||||
target_complete_cmd(cmd, SAM_STAT_GOOD);
|
||||
return 0;
|
||||
}
|
||||
if (cmd->prot_op) {
|
||||
pr_err("WRITE_SAME: Protection information with FILEIO"
|
||||
" backends not supported\n");
|
||||
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
||||
}
|
||||
sg = &cmd->t_data_sg[0];
|
||||
|
||||
if (cmd->t_data_nents > 1 ||
|
||||
|
@ -464,6 +464,11 @@ iblock_execute_write_same(struct se_cmd *cmd)
|
||||
sector_t block_lba = cmd->t_task_lba;
|
||||
sector_t sectors = sbc_get_write_same_sectors(cmd);
|
||||
|
||||
if (cmd->prot_op) {
|
||||
pr_err("WRITE_SAME: Protection information with IBLOCK"
|
||||
" backends not supported\n");
|
||||
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
||||
}
|
||||
sg = &cmd->t_data_sg[0];
|
||||
|
||||
if (cmd->t_data_nents > 1 ||
|
||||
|
@ -1874,8 +1874,8 @@ static int core_scsi3_update_aptpl_buf(
|
||||
}
|
||||
|
||||
if ((len + strlen(tmp) >= pr_aptpl_buf_len)) {
|
||||
pr_err("Unable to update renaming"
|
||||
" APTPL metadata\n");
|
||||
pr_err("Unable to update renaming APTPL metadata,"
|
||||
" reallocating larger buffer\n");
|
||||
ret = -EMSGSIZE;
|
||||
goto out;
|
||||
}
|
||||
@ -1892,8 +1892,8 @@ static int core_scsi3_update_aptpl_buf(
|
||||
lun->lun_sep->sep_rtpi, lun->unpacked_lun, reg_count);
|
||||
|
||||
if ((len + strlen(tmp) >= pr_aptpl_buf_len)) {
|
||||
pr_err("Unable to update renaming"
|
||||
" APTPL metadata\n");
|
||||
pr_err("Unable to update renaming APTPL metadata,"
|
||||
" reallocating larger buffer\n");
|
||||
ret = -EMSGSIZE;
|
||||
goto out;
|
||||
}
|
||||
@ -1956,7 +1956,7 @@ static int __core_scsi3_write_aptpl_to_file(
|
||||
static sense_reason_t core_scsi3_update_and_write_aptpl(struct se_device *dev, bool aptpl)
|
||||
{
|
||||
unsigned char *buf;
|
||||
int rc;
|
||||
int rc, len = PR_APTPL_BUF_LEN;
|
||||
|
||||
if (!aptpl) {
|
||||
char *null_buf = "No Registrations or Reservations\n";
|
||||
@ -1970,25 +1970,26 @@ static sense_reason_t core_scsi3_update_and_write_aptpl(struct se_device *dev, b
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
buf = kzalloc(PR_APTPL_BUF_LEN, GFP_KERNEL);
|
||||
retry:
|
||||
buf = vzalloc(len);
|
||||
if (!buf)
|
||||
return TCM_OUT_OF_RESOURCES;
|
||||
|
||||
rc = core_scsi3_update_aptpl_buf(dev, buf, PR_APTPL_BUF_LEN);
|
||||
rc = core_scsi3_update_aptpl_buf(dev, buf, len);
|
||||
if (rc < 0) {
|
||||
kfree(buf);
|
||||
return TCM_OUT_OF_RESOURCES;
|
||||
vfree(buf);
|
||||
len *= 2;
|
||||
goto retry;
|
||||
}
|
||||
|
||||
rc = __core_scsi3_write_aptpl_to_file(dev, buf);
|
||||
if (rc != 0) {
|
||||
pr_err("SPC-3 PR: Could not update APTPL\n");
|
||||
kfree(buf);
|
||||
vfree(buf);
|
||||
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
||||
}
|
||||
dev->t10_pr.pr_aptpl_active = 1;
|
||||
kfree(buf);
|
||||
vfree(buf);
|
||||
pr_debug("SPC-3 PR: Set APTPL Bit Activated\n");
|
||||
return 0;
|
||||
}
|
||||
|
@ -36,6 +36,9 @@
|
||||
#include "target_core_ua.h"
|
||||
#include "target_core_alua.h"
|
||||
|
||||
static sense_reason_t
|
||||
sbc_check_prot(struct se_device *, struct se_cmd *, unsigned char *, u32, bool);
|
||||
|
||||
static sense_reason_t
|
||||
sbc_emulate_readcapacity(struct se_cmd *cmd)
|
||||
{
|
||||
@ -251,7 +254,10 @@ static inline unsigned long long transport_lba_64_ext(unsigned char *cdb)
|
||||
static sense_reason_t
|
||||
sbc_setup_write_same(struct se_cmd *cmd, unsigned char *flags, struct sbc_ops *ops)
|
||||
{
|
||||
struct se_device *dev = cmd->se_dev;
|
||||
sector_t end_lba = dev->transport->get_blocks(dev) + 1;
|
||||
unsigned int sectors = sbc_get_write_same_sectors(cmd);
|
||||
sense_reason_t ret;
|
||||
|
||||
if ((flags[0] & 0x04) || (flags[0] & 0x02)) {
|
||||
pr_err("WRITE_SAME PBDATA and LBDATA"
|
||||
@ -264,6 +270,16 @@ sbc_setup_write_same(struct se_cmd *cmd, unsigned char *flags, struct sbc_ops *o
|
||||
sectors, cmd->se_dev->dev_attrib.max_write_same_len);
|
||||
return TCM_INVALID_CDB_FIELD;
|
||||
}
|
||||
/*
|
||||
* Sanity check for LBA wrap and request past end of device.
|
||||
*/
|
||||
if (((cmd->t_task_lba + sectors) < cmd->t_task_lba) ||
|
||||
((cmd->t_task_lba + sectors) > end_lba)) {
|
||||
pr_err("WRITE_SAME exceeds last lba %llu (lba %llu, sectors %u)\n",
|
||||
(unsigned long long)end_lba, cmd->t_task_lba, sectors);
|
||||
return TCM_ADDRESS_OUT_OF_RANGE;
|
||||
}
|
||||
|
||||
/* We always have ANC_SUP == 0 so setting ANCHOR is always an error */
|
||||
if (flags[0] & 0x10) {
|
||||
pr_warn("WRITE SAME with ANCHOR not supported\n");
|
||||
@ -277,12 +293,21 @@ sbc_setup_write_same(struct se_cmd *cmd, unsigned char *flags, struct sbc_ops *o
|
||||
if (!ops->execute_write_same_unmap)
|
||||
return TCM_UNSUPPORTED_SCSI_OPCODE;
|
||||
|
||||
if (!dev->dev_attrib.emulate_tpws) {
|
||||
pr_err("Got WRITE_SAME w/ UNMAP=1, but backend device"
|
||||
" has emulate_tpws disabled\n");
|
||||
return TCM_UNSUPPORTED_SCSI_OPCODE;
|
||||
}
|
||||
cmd->execute_cmd = ops->execute_write_same_unmap;
|
||||
return 0;
|
||||
}
|
||||
if (!ops->execute_write_same)
|
||||
return TCM_UNSUPPORTED_SCSI_OPCODE;
|
||||
|
||||
ret = sbc_check_prot(dev, cmd, &cmd->t_task_cdb[0], sectors, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
cmd->execute_cmd = ops->execute_write_same;
|
||||
return 0;
|
||||
}
|
||||
@ -614,14 +639,21 @@ sbc_set_prot_op_checks(u8 protect, enum target_prot_type prot_type,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
static sense_reason_t
|
||||
sbc_check_prot(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb,
|
||||
u32 sectors, bool is_write)
|
||||
{
|
||||
u8 protect = cdb[1] >> 5;
|
||||
|
||||
if ((!cmd->t_prot_sg || !cmd->t_prot_nents) && cmd->prot_pto)
|
||||
return true;
|
||||
if (!cmd->t_prot_sg || !cmd->t_prot_nents) {
|
||||
if (protect && !dev->dev_attrib.pi_prot_type) {
|
||||
pr_err("CDB contains protect bit, but device does not"
|
||||
" advertise PROTECT=1 feature bit\n");
|
||||
return TCM_INVALID_CDB_FIELD;
|
||||
}
|
||||
if (cmd->prot_pto)
|
||||
return TCM_NO_SENSE;
|
||||
}
|
||||
|
||||
switch (dev->dev_attrib.pi_prot_type) {
|
||||
case TARGET_DIF_TYPE3_PROT:
|
||||
@ -629,7 +661,7 @@ sbc_check_prot(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb,
|
||||
break;
|
||||
case TARGET_DIF_TYPE2_PROT:
|
||||
if (protect)
|
||||
return false;
|
||||
return TCM_INVALID_CDB_FIELD;
|
||||
|
||||
cmd->reftag_seed = cmd->t_task_lba;
|
||||
break;
|
||||
@ -638,12 +670,12 @@ sbc_check_prot(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb,
|
||||
break;
|
||||
case TARGET_DIF_TYPE0_PROT:
|
||||
default:
|
||||
return true;
|
||||
return TCM_NO_SENSE;
|
||||
}
|
||||
|
||||
if (sbc_set_prot_op_checks(protect, dev->dev_attrib.pi_prot_type,
|
||||
is_write, cmd))
|
||||
return false;
|
||||
return TCM_INVALID_CDB_FIELD;
|
||||
|
||||
cmd->prot_type = dev->dev_attrib.pi_prot_type;
|
||||
cmd->prot_length = dev->prot_length * sectors;
|
||||
@ -662,7 +694,30 @@ sbc_check_prot(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb,
|
||||
__func__, cmd->prot_type, cmd->data_length, cmd->prot_length,
|
||||
cmd->prot_op, cmd->prot_checks);
|
||||
|
||||
return true;
|
||||
return TCM_NO_SENSE;
|
||||
}
|
||||
|
||||
static int
|
||||
sbc_check_dpofua(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb)
|
||||
{
|
||||
if (cdb[1] & 0x10) {
|
||||
if (!dev->dev_attrib.emulate_dpo) {
|
||||
pr_err("Got CDB: 0x%02x with DPO bit set, but device"
|
||||
" does not advertise support for DPO\n", cdb[0]);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
if (cdb[1] & 0x8) {
|
||||
if (!dev->dev_attrib.emulate_fua_write ||
|
||||
!dev->dev_attrib.emulate_write_cache) {
|
||||
pr_err("Got CDB: 0x%02x with FUA bit set, but device"
|
||||
" does not advertise support for FUA write\n",
|
||||
cdb[0]);
|
||||
return -EINVAL;
|
||||
}
|
||||
cmd->se_cmd_flags |= SCF_FUA;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
sense_reason_t
|
||||
@ -686,8 +741,12 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
|
||||
sectors = transport_get_sectors_10(cdb);
|
||||
cmd->t_task_lba = transport_lba_32(cdb);
|
||||
|
||||
if (!sbc_check_prot(dev, cmd, cdb, sectors, false))
|
||||
return TCM_UNSUPPORTED_SCSI_OPCODE;
|
||||
if (sbc_check_dpofua(dev, cmd, cdb))
|
||||
return TCM_INVALID_CDB_FIELD;
|
||||
|
||||
ret = sbc_check_prot(dev, cmd, cdb, sectors, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
|
||||
cmd->execute_rw = ops->execute_rw;
|
||||
@ -697,8 +756,12 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
|
||||
sectors = transport_get_sectors_12(cdb);
|
||||
cmd->t_task_lba = transport_lba_32(cdb);
|
||||
|
||||
if (!sbc_check_prot(dev, cmd, cdb, sectors, false))
|
||||
return TCM_UNSUPPORTED_SCSI_OPCODE;
|
||||
if (sbc_check_dpofua(dev, cmd, cdb))
|
||||
return TCM_INVALID_CDB_FIELD;
|
||||
|
||||
ret = sbc_check_prot(dev, cmd, cdb, sectors, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
|
||||
cmd->execute_rw = ops->execute_rw;
|
||||
@ -708,8 +771,12 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
|
||||
sectors = transport_get_sectors_16(cdb);
|
||||
cmd->t_task_lba = transport_lba_64(cdb);
|
||||
|
||||
if (!sbc_check_prot(dev, cmd, cdb, sectors, false))
|
||||
return TCM_UNSUPPORTED_SCSI_OPCODE;
|
||||
if (sbc_check_dpofua(dev, cmd, cdb))
|
||||
return TCM_INVALID_CDB_FIELD;
|
||||
|
||||
ret = sbc_check_prot(dev, cmd, cdb, sectors, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
|
||||
cmd->execute_rw = ops->execute_rw;
|
||||
@ -727,11 +794,13 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
|
||||
sectors = transport_get_sectors_10(cdb);
|
||||
cmd->t_task_lba = transport_lba_32(cdb);
|
||||
|
||||
if (!sbc_check_prot(dev, cmd, cdb, sectors, true))
|
||||
return TCM_UNSUPPORTED_SCSI_OPCODE;
|
||||
if (sbc_check_dpofua(dev, cmd, cdb))
|
||||
return TCM_INVALID_CDB_FIELD;
|
||||
|
||||
ret = sbc_check_prot(dev, cmd, cdb, sectors, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (cdb[1] & 0x8)
|
||||
cmd->se_cmd_flags |= SCF_FUA;
|
||||
cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
|
||||
cmd->execute_rw = ops->execute_rw;
|
||||
cmd->execute_cmd = sbc_execute_rw;
|
||||
@ -740,11 +809,13 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
|
||||
sectors = transport_get_sectors_12(cdb);
|
||||
cmd->t_task_lba = transport_lba_32(cdb);
|
||||
|
||||
if (!sbc_check_prot(dev, cmd, cdb, sectors, true))
|
||||
return TCM_UNSUPPORTED_SCSI_OPCODE;
|
||||
if (sbc_check_dpofua(dev, cmd, cdb))
|
||||
return TCM_INVALID_CDB_FIELD;
|
||||
|
||||
ret = sbc_check_prot(dev, cmd, cdb, sectors, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (cdb[1] & 0x8)
|
||||
cmd->se_cmd_flags |= SCF_FUA;
|
||||
cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
|
||||
cmd->execute_rw = ops->execute_rw;
|
||||
cmd->execute_cmd = sbc_execute_rw;
|
||||
@ -753,11 +824,13 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
|
||||
sectors = transport_get_sectors_16(cdb);
|
||||
cmd->t_task_lba = transport_lba_64(cdb);
|
||||
|
||||
if (!sbc_check_prot(dev, cmd, cdb, sectors, true))
|
||||
return TCM_UNSUPPORTED_SCSI_OPCODE;
|
||||
if (sbc_check_dpofua(dev, cmd, cdb))
|
||||
return TCM_INVALID_CDB_FIELD;
|
||||
|
||||
ret = sbc_check_prot(dev, cmd, cdb, sectors, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (cdb[1] & 0x8)
|
||||
cmd->se_cmd_flags |= SCF_FUA;
|
||||
cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
|
||||
cmd->execute_rw = ops->execute_rw;
|
||||
cmd->execute_cmd = sbc_execute_rw;
|
||||
@ -768,6 +841,9 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
|
||||
return TCM_INVALID_CDB_FIELD;
|
||||
sectors = transport_get_sectors_10(cdb);
|
||||
|
||||
if (sbc_check_dpofua(dev, cmd, cdb))
|
||||
return TCM_INVALID_CDB_FIELD;
|
||||
|
||||
cmd->t_task_lba = transport_lba_32(cdb);
|
||||
cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
|
||||
|
||||
@ -777,8 +853,6 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
|
||||
cmd->execute_rw = ops->execute_rw;
|
||||
cmd->execute_cmd = sbc_execute_rw;
|
||||
cmd->transport_complete_callback = &xdreadwrite_callback;
|
||||
if (cdb[1] & 0x8)
|
||||
cmd->se_cmd_flags |= SCF_FUA;
|
||||
break;
|
||||
case VARIABLE_LENGTH_CMD:
|
||||
{
|
||||
@ -787,6 +861,8 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
|
||||
case XDWRITEREAD_32:
|
||||
sectors = transport_get_sectors_32(cdb);
|
||||
|
||||
if (sbc_check_dpofua(dev, cmd, cdb))
|
||||
return TCM_INVALID_CDB_FIELD;
|
||||
/*
|
||||
* Use WRITE_32 and READ_32 opcodes for the emulated
|
||||
* XDWRITE_READ_32 logic.
|
||||
@ -801,8 +877,6 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
|
||||
cmd->execute_rw = ops->execute_rw;
|
||||
cmd->execute_cmd = sbc_execute_rw;
|
||||
cmd->transport_complete_callback = &xdreadwrite_callback;
|
||||
if (cdb[1] & 0x8)
|
||||
cmd->se_cmd_flags |= SCF_FUA;
|
||||
break;
|
||||
case WRITE_SAME_32:
|
||||
sectors = transport_get_sectors_32(cdb);
|
||||
@ -888,6 +962,11 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
|
||||
if (!ops->execute_unmap)
|
||||
return TCM_UNSUPPORTED_SCSI_OPCODE;
|
||||
|
||||
if (!dev->dev_attrib.emulate_tpu) {
|
||||
pr_err("Got UNMAP, but backend device has"
|
||||
" emulate_tpu disabled\n");
|
||||
return TCM_UNSUPPORTED_SCSI_OPCODE;
|
||||
}
|
||||
size = get_unaligned_be16(&cdb[7]);
|
||||
cmd->execute_cmd = ops->execute_unmap;
|
||||
break;
|
||||
@ -955,7 +1034,8 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
|
||||
unsigned long long end_lba;
|
||||
check_lba:
|
||||
end_lba = dev->transport->get_blocks(dev) + 1;
|
||||
if (cmd->t_task_lba + sectors > end_lba) {
|
||||
if (((cmd->t_task_lba + sectors) < cmd->t_task_lba) ||
|
||||
((cmd->t_task_lba + sectors) > end_lba)) {
|
||||
pr_err("cmd exceeds last lba %llu "
|
||||
"(lba %llu, sectors %u)\n",
|
||||
end_lba, cmd->t_task_lba, sectors);
|
||||
|
@ -647,7 +647,7 @@ spc_emulate_evpd_b2(struct se_cmd *cmd, unsigned char *buf)
|
||||
* support the use of the WRITE SAME (16) command to unmap LBAs.
|
||||
*/
|
||||
if (dev->dev_attrib.emulate_tpws != 0)
|
||||
buf[5] |= 0x40;
|
||||
buf[5] |= 0x40 | 0x20;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
1050
drivers/vhost/scsi.c
1050
drivers/vhost/scsi.c
File diff suppressed because it is too large
Load Diff
@ -880,4 +880,18 @@ struct iscsit_global {
|
||||
struct iscsi_portal_group *discovery_tpg;
|
||||
};
|
||||
|
||||
static inline u32 session_get_next_ttt(struct iscsi_session *session)
|
||||
{
|
||||
u32 ttt;
|
||||
|
||||
spin_lock_bh(&session->ttt_lock);
|
||||
ttt = session->targ_xfer_tag++;
|
||||
if (ttt == 0xFFFFFFFF)
|
||||
ttt = session->targ_xfer_tag++;
|
||||
spin_unlock_bh(&session->ttt_lock);
|
||||
|
||||
return ttt;
|
||||
}
|
||||
|
||||
extern struct iscsi_cmd *iscsit_find_cmd_from_itt(struct iscsi_conn *, itt_t);
|
||||
#endif /* ISCSI_TARGET_CORE_H */
|
@ -1,6 +1,6 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/list.h>
|
||||
#include "../../../drivers/target/iscsi/iscsi_target_core.h"
|
||||
#include "iscsi_target_core.h"
|
||||
|
||||
struct iscsit_transport {
|
||||
#define ISCSIT_TRANSPORT_NAME 16
|
||||
|
@ -407,7 +407,7 @@ struct t10_reservation {
|
||||
/* Activate Persistence across Target Power Loss enabled
|
||||
* for SCSI device */
|
||||
int pr_aptpl_active;
|
||||
#define PR_APTPL_BUF_LEN 8192
|
||||
#define PR_APTPL_BUF_LEN 262144
|
||||
u32 pr_generation;
|
||||
spinlock_t registration_lock;
|
||||
spinlock_t aptpl_reg_lock;
|
||||
|
Loading…
Reference in New Issue
Block a user