Commit e20d3ef5 authored by Linus Torvalds's avatar Linus Torvalds

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
  ...
parents 1acd2de5 aa04dae4
...@@ -38,7 +38,7 @@ ...@@ -38,7 +38,7 @@
#define ISER_MAX_CQ_LEN (ISER_MAX_RX_CQ_LEN + ISER_MAX_TX_CQ_LEN + \ #define ISER_MAX_CQ_LEN (ISER_MAX_RX_CQ_LEN + ISER_MAX_TX_CQ_LEN + \
ISERT_MAX_CONN) ISERT_MAX_CONN)
int isert_debug_level = 0; static int isert_debug_level;
module_param_named(debug_level, isert_debug_level, int, 0644); module_param_named(debug_level, isert_debug_level, int, 0644);
MODULE_PARM_DESC(debug_level, "Enable debug tracing if > 0 (default:0)"); 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) ...@@ -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_err("ib_post_recv() failed with ret: %d\n", ret);
isert_conn->post_recv_buf_count -= count; isert_conn->post_recv_buf_count -= count;
} else { } 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; isert_conn->conn_rx_desc_head = rx_head;
} }
return ret; return ret;
...@@ -1351,17 +1351,19 @@ isert_handle_text_cmd(struct isert_conn *isert_conn, struct isert_cmd *isert_cmd ...@@ -1351,17 +1351,19 @@ isert_handle_text_cmd(struct isert_conn *isert_conn, struct isert_cmd *isert_cmd
struct iscsi_conn *conn = isert_conn->conn; struct iscsi_conn *conn = isert_conn->conn;
u32 payload_length = ntoh24(hdr->dlength); u32 payload_length = ntoh24(hdr->dlength);
int rc; int rc;
unsigned char *text_in; unsigned char *text_in = NULL;
rc = iscsit_setup_text_cmd(conn, cmd, hdr); rc = iscsit_setup_text_cmd(conn, cmd, hdr);
if (rc < 0) if (rc < 0)
return rc; return rc;
text_in = kzalloc(payload_length, GFP_KERNEL); if (payload_length) {
if (!text_in) { text_in = kzalloc(payload_length, GFP_KERNEL);
isert_err("Unable to allocate text_in of payload_length: %u\n", if (!text_in) {
payload_length); isert_err("Unable to allocate text_in of payload_length: %u\n",
return -ENOMEM; payload_length);
return -ENOMEM;
}
} }
cmd->text_in_ptr = text_in; cmd->text_in_ptr = text_in;
...@@ -1434,9 +1436,15 @@ isert_rx_opcode(struct isert_conn *isert_conn, struct iser_rx_desc *rx_desc, ...@@ -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); ret = iscsit_handle_logout_cmd(conn, cmd, (unsigned char *)hdr);
break; break;
case ISCSI_OP_TEXT: case ISCSI_OP_TEXT:
cmd = isert_allocate_cmd(conn); if (be32_to_cpu(hdr->ttt) != 0xFFFFFFFF) {
if (!cmd) cmd = iscsit_find_cmd_from_itt(conn, hdr->itt);
break; if (!cmd)
break;
} else {
cmd = isert_allocate_cmd(conn);
if (!cmd)
break;
}
isert_cmd = iscsit_priv_cmd(cmd); isert_cmd = iscsit_priv_cmd(cmd);
ret = isert_handle_text_cmd(isert_conn, isert_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) ...@@ -1658,6 +1666,7 @@ isert_put_cmd(struct isert_cmd *isert_cmd, bool comp_err)
struct isert_conn *isert_conn = isert_cmd->conn; struct isert_conn *isert_conn = isert_cmd->conn;
struct iscsi_conn *conn = isert_conn->conn; struct iscsi_conn *conn = isert_conn->conn;
struct isert_device *device = isert_conn->conn_device; struct isert_device *device = isert_conn->conn_device;
struct iscsi_text_rsp *hdr;
isert_dbg("Cmd %p\n", isert_cmd); isert_dbg("Cmd %p\n", isert_cmd);
...@@ -1698,6 +1707,11 @@ isert_put_cmd(struct isert_cmd *isert_cmd, bool comp_err) ...@@ -1698,6 +1707,11 @@ isert_put_cmd(struct isert_cmd *isert_cmd, bool comp_err)
case ISCSI_OP_REJECT: case ISCSI_OP_REJECT:
case ISCSI_OP_NOOP_OUT: case ISCSI_OP_NOOP_OUT:
case ISCSI_OP_TEXT: 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); spin_lock_bh(&conn->cmd_lock);
if (!list_empty(&cmd->i_conn_node)) if (!list_empty(&cmd->i_conn_node))
list_del_init(&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) ...@@ -1709,8 +1723,7 @@ isert_put_cmd(struct isert_cmd *isert_cmd, bool comp_err)
* associated cmd->se_cmd needs to be released. * associated cmd->se_cmd needs to be released.
*/ */
if (cmd->se_cmd.se_tfo != NULL) { if (cmd->se_cmd.se_tfo != NULL) {
isert_dbg("Calling transport_generic_free_cmd from" isert_dbg("Calling transport_generic_free_cmd for 0x%02x\n",
" isert_put_cmd for 0x%02x\n",
cmd->iscsi_opcode); cmd->iscsi_opcode);
transport_generic_free_cmd(&cmd->se_cmd, 0); transport_generic_free_cmd(&cmd->se_cmd, 0);
break; break;
...@@ -2275,7 +2288,7 @@ isert_put_text_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn) ...@@ -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_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); return isert_post_response(isert_conn, isert_cmd);
} }
...@@ -3136,7 +3149,7 @@ isert_accept_np(struct iscsi_np *np, struct iscsi_conn *conn) ...@@ -3136,7 +3149,7 @@ isert_accept_np(struct iscsi_np *np, struct iscsi_conn *conn)
spin_lock_bh(&np->np_thread_lock); spin_lock_bh(&np->np_thread_lock);
if (np->np_thread_state >= ISCSI_NP_THREAD_RESET) { if (np->np_thread_state >= ISCSI_NP_THREAD_RESET) {
spin_unlock_bh(&np->np_thread_lock); 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); np->np_thread_state);
/** /**
* No point in stalling here when np_thread * No point in stalling here when np_thread
...@@ -3320,7 +3333,8 @@ static int __init isert_init(void) ...@@ -3320,7 +3333,8 @@ static int __init isert_init(void)
{ {
int ret; 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) { if (!isert_comp_wq) {
isert_err("Unable to allocate isert_comp_wq\n"); isert_err("Unable to allocate isert_comp_wq\n");
ret = -ENOMEM; ret = -ENOMEM;
......
...@@ -3518,7 +3518,7 @@ static void srpt_close_session(struct se_session *se_sess) ...@@ -3518,7 +3518,7 @@ static void srpt_close_session(struct se_session *se_sess)
DECLARE_COMPLETION_ONSTACK(release_done); DECLARE_COMPLETION_ONSTACK(release_done);
struct srpt_rdma_ch *ch; struct srpt_rdma_ch *ch;
struct srpt_device *sdev; struct srpt_device *sdev;
int res; unsigned long res;
ch = se_sess->fabric_sess_ptr; ch = se_sess->fabric_sess_ptr;
WARN_ON(ch->sess != se_sess); WARN_ON(ch->sess != se_sess);
...@@ -3533,7 +3533,7 @@ static void srpt_close_session(struct se_session *se_sess) ...@@ -3533,7 +3533,7 @@ static void srpt_close_session(struct se_session *se_sess)
spin_unlock_irq(&sdev->spinlock); spin_unlock_irq(&sdev->spinlock);
res = wait_for_completion_timeout(&release_done, 60 * HZ); 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( ...@@ -1570,9 +1570,7 @@ static int tcm_qla2xxx_check_initiator_node_acl(
* match the format by tcm_qla2xxx explict ConfigFS NodeACLs. * match the format by tcm_qla2xxx explict ConfigFS NodeACLs.
*/ */
memset(&port_name, 0, 36); memset(&port_name, 0, 36);
snprintf(port_name, 36, "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", snprintf(port_name, sizeof(port_name), "%8phC", fc_wwpn);
fc_wwpn[0], fc_wwpn[1], fc_wwpn[2], fc_wwpn[3], fc_wwpn[4],
fc_wwpn[5], fc_wwpn[6], fc_wwpn[7]);
/* /*
* Locate our struct se_node_acl either from an explict NodeACL created * Locate our struct se_node_acl either from an explict NodeACL created
* via ConfigFS, or via running in TPG demo mode. * via ConfigFS, or via running in TPG demo mode.
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
#include <target/target_core_fabric.h> #include <target/target_core_fabric.h>
#include <target/target_core_configfs.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_parameters.h"
#include "iscsi_target_seq_pdu_list.h" #include "iscsi_target_seq_pdu_list.h"
#include "iscsi_target_tq.h" #include "iscsi_target_tq.h"
...@@ -45,7 +45,7 @@ ...@@ -45,7 +45,7 @@
#include "iscsi_target_util.h" #include "iscsi_target_util.h"
#include "iscsi_target.h" #include "iscsi_target.h"
#include "iscsi_target_device.h" #include "iscsi_target_device.h"
#include "iscsi_target_stat.h" #include <target/iscsi/iscsi_target_stat.h>
#include <target/iscsi/iscsi_transport.h> #include <target/iscsi/iscsi_transport.h>
...@@ -968,11 +968,7 @@ int iscsit_setup_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, ...@@ -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; conn->sess->init_task_tag = cmd->init_task_tag = hdr->itt;
if (hdr->flags & ISCSI_FLAG_CMD_READ) { if (hdr->flags & ISCSI_FLAG_CMD_READ) {
spin_lock_bh(&conn->sess->ttt_lock); cmd->targ_xfer_tag = session_get_next_ttt(conn->sess);
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);
} else if (hdr->flags & ISCSI_FLAG_CMD_WRITE) } else if (hdr->flags & ISCSI_FLAG_CMD_WRITE)
cmd->targ_xfer_tag = 0xFFFFFFFF; cmd->targ_xfer_tag = 0xFFFFFFFF;
cmd->cmd_sn = be32_to_cpu(hdr->cmdsn); cmd->cmd_sn = be32_to_cpu(hdr->cmdsn);
...@@ -1998,6 +1994,7 @@ iscsit_setup_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, ...@@ -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->cmd_sn = be32_to_cpu(hdr->cmdsn);
cmd->exp_stat_sn = be32_to_cpu(hdr->exp_statsn); cmd->exp_stat_sn = be32_to_cpu(hdr->exp_statsn);
cmd->data_direction = DMA_NONE; cmd->data_direction = DMA_NONE;
cmd->text_in_ptr = NULL;
return 0; return 0;
} }
...@@ -2011,9 +2008,13 @@ iscsit_process_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, ...@@ -2011,9 +2008,13 @@ iscsit_process_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
int cmdsn_ret; int cmdsn_ret;
if (!text_in) { if (!text_in) {
pr_err("Unable to locate text_in buffer for sendtargets" cmd->targ_xfer_tag = be32_to_cpu(hdr->ttt);
" discovery\n"); if (cmd->targ_xfer_tag == 0xFFFFFFFF) {
goto reject; pr_err("Unable to locate text_in buffer for sendtargets"
" discovery\n");
goto reject;
}
goto empty_sendtargets;
} }
if (strncmp("SendTargets", text_in, 11) != 0) { if (strncmp("SendTargets", text_in, 11) != 0) {
pr_err("Received Text Data that is not" pr_err("Received Text Data that is not"
...@@ -2040,6 +2041,7 @@ iscsit_process_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, ...@@ -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); list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
spin_unlock_bh(&conn->cmd_lock); spin_unlock_bh(&conn->cmd_lock);
empty_sendtargets:
iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn)); iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn));
if (!(hdr->opcode & ISCSI_OP_IMMEDIATE)) { if (!(hdr->opcode & ISCSI_OP_IMMEDIATE)) {
...@@ -3047,11 +3049,7 @@ static int iscsit_send_r2t( ...@@ -3047,11 +3049,7 @@ static int iscsit_send_r2t(
int_to_scsilun(cmd->se_cmd.orig_fe_lun, int_to_scsilun(cmd->se_cmd.orig_fe_lun,
(struct scsi_lun *)&hdr->lun); (struct scsi_lun *)&hdr->lun);
hdr->itt = cmd->init_task_tag; hdr->itt = cmd->init_task_tag;
spin_lock_bh(&conn->sess->ttt_lock); r2t->targ_xfer_tag = session_get_next_ttt(conn->sess);
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);
hdr->ttt = cpu_to_be32(r2t->targ_xfer_tag); hdr->ttt = cpu_to_be32(r2t->targ_xfer_tag);
hdr->statsn = cpu_to_be32(conn->stat_sn); hdr->statsn = cpu_to_be32(conn->stat_sn);
hdr->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_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) ...@@ -3393,7 +3391,8 @@ static bool iscsit_check_inaddr_any(struct iscsi_np *np)
static int static int
iscsit_build_sendtargets_response(struct iscsi_cmd *cmd, 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; char *payload = NULL;
struct iscsi_conn *conn = cmd->conn; struct iscsi_conn *conn = cmd->conn;
...@@ -3405,7 +3404,7 @@ iscsit_build_sendtargets_response(struct iscsi_cmd *cmd, ...@@ -3405,7 +3404,7 @@ iscsit_build_sendtargets_response(struct iscsi_cmd *cmd,
unsigned char buf[ISCSI_IQN_LEN+12]; /* iqn + "TargetName=" + \0 */ unsigned char buf[ISCSI_IQN_LEN+12]; /* iqn + "TargetName=" + \0 */
unsigned char *text_in = cmd->text_in_ptr, *text_ptr = NULL; 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); SENDTARGETS_BUF_LIMIT);
payload = kzalloc(buffer_len, GFP_KERNEL); payload = kzalloc(buffer_len, GFP_KERNEL);
...@@ -3484,9 +3483,16 @@ iscsit_build_sendtargets_response(struct iscsi_cmd *cmd, ...@@ -3484,9 +3483,16 @@ iscsit_build_sendtargets_response(struct iscsi_cmd *cmd,
end_of_buf = 1; end_of_buf = 1;
goto eob; goto eob;
} }
memcpy(payload + payload_len, buf, len);
payload_len += len; if (skip_bytes && len <= skip_bytes) {
target_name_printed = 1; 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=" len = sprintf(buf, "TargetAddress="
...@@ -3502,15 +3508,24 @@ iscsit_build_sendtargets_response(struct iscsi_cmd *cmd, ...@@ -3502,15 +3508,24 @@ iscsit_build_sendtargets_response(struct iscsi_cmd *cmd,
end_of_buf = 1; end_of_buf = 1;
goto eob; goto eob;
} }
memcpy(payload + payload_len, buf, len);
payload_len += len; 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(&tpg->tpg_np_lock);
} }
spin_unlock(&tiqn->tiqn_tpg_lock); spin_unlock(&tiqn->tiqn_tpg_lock);
eob: eob:
if (end_of_buf) if (end_of_buf) {
*completed = false;
break; break;
}
if (cmd->cmd_flags & ICF_SENDTARGETS_SINGLE) if (cmd->cmd_flags & ICF_SENDTARGETS_SINGLE)
break; break;
...@@ -3528,13 +3543,23 @@ iscsit_build_text_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn, ...@@ -3528,13 +3543,23 @@ iscsit_build_text_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
enum iscsit_transport_type network_transport) enum iscsit_transport_type network_transport)
{ {
int text_length, padding; 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) if (text_length < 0)
return text_length; return text_length;
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; hdr->opcode = ISCSI_OP_TEXT_RSP;
hdr->flags |= ISCSI_FLAG_CMD_FINAL;
padding = ((-text_length) & 3); padding = ((-text_length) & 3);
hton24(hdr->dlength, text_length); hton24(hdr->dlength, text_length);
hdr->itt = cmd->init_task_tag; hdr->itt = cmd->init_task_tag;
...@@ -3543,21 +3568,25 @@ iscsit_build_text_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn, ...@@ -3543,21 +3568,25 @@ iscsit_build_text_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
hdr->statsn = cpu_to_be32(cmd->stat_sn); hdr->statsn = cpu_to_be32(cmd->stat_sn);
iscsit_increment_maxcmdsn(cmd, conn->sess); 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->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_sn);
hdr->max_cmdsn = cpu_to_be32(conn->sess->max_cmd_sn); hdr->max_cmdsn = cpu_to_be32(conn->sess->max_cmd_sn);
pr_debug("Built Text Response: ITT: 0x%08x, StatSN: 0x%08x," pr_debug("Built Text Response: ITT: 0x%08x, TTT: 0x%08x, StatSN: 0x%08x,"
" Length: %u, CID: %hu\n", cmd->init_task_tag, cmd->stat_sn, " Length: %u, CID: %hu F: %d C: %d\n", cmd->init_task_tag,
text_length, conn->cid); 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; return text_length + padding;
} }
EXPORT_SYMBOL(iscsit_build_text_rsp); 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( static int iscsit_send_text_rsp(
struct iscsi_cmd *cmd, struct iscsi_cmd *cmd,
struct iscsi_conn *conn) struct iscsi_conn *conn)
...@@ -4021,9 +4050,15 @@ static int iscsi_target_rx_opcode(struct iscsi_conn *conn, unsigned char *buf) ...@@ -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); ret = iscsit_handle_task_mgt_cmd(conn, cmd, buf);
break; break;
case ISCSI_OP_TEXT: case ISCSI_OP_TEXT:
cmd = iscsit_allocate_cmd(conn, TASK_INTERRUPTIBLE); if (hdr->ttt != cpu_to_be32(0xFFFFFFFF)) {
if (!cmd) cmd = iscsit_find_cmd_from_itt(conn, hdr->itt);
goto reject; if (!cmd)
goto reject;
} else {
cmd = iscsit_allocate_cmd(conn, TASK_INTERRUPTIBLE);
if (!cmd)
goto reject;
}
ret = iscsit_handle_text_cmd(conn, cmd, buf); ret = iscsit_handle_text_cmd(conn, cmd, buf);
break; break;
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
#include <linux/err.h> #include <linux/err.h>
#include <linux/scatterlist.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_nego.h"
#include "iscsi_target_auth.h" #include "iscsi_target_auth.h"
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
#include <target/configfs_macros.h> #include <target/configfs_macros.h>
#include <target/iscsi/iscsi_transport.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_parameters.h"
#include "iscsi_target_device.h" #include "iscsi_target_device.h"
#include "iscsi_target_erl0.h" #include "iscsi_target_erl0.h"
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
#include "iscsi_target_tpg.h" #include "iscsi_target_tpg.h"
#include "iscsi_target_util.h" #include "iscsi_target_util.h"
#include "iscsi_target.h" #include "iscsi_target.h"
#include "iscsi_target_stat.h" #include <target/iscsi/iscsi_target_stat.h>
#include "iscsi_target_configfs.h" #include "iscsi_target_configfs.h"
struct target_fabric_configfs *lio_target_fabric_configfs; struct target_fabric_configfs *lio_target_fabric_configfs;
...@@ -674,12 +674,9 @@ static ssize_t lio_target_nacl_show_info( ...@@ -674,12 +674,9 @@ static ssize_t lio_target_nacl_show_info(
rb += sprintf(page+rb, "InitiatorAlias: %s\n", rb += sprintf(page+rb, "InitiatorAlias: %s\n",
sess->sess_ops->InitiatorAlias); sess->sess_ops->InitiatorAlias);
rb += sprintf(page+rb, "LIO Session ID: %u " rb += sprintf(page+rb,
"ISID: 0x%02x %02x %02x %02x %02x %02x " "LIO Session ID: %u ISID: 0x%6ph TSIH: %hu ",
"TSIH: %hu ", sess->sid, sess->sid, sess->isid, sess->tsih);
sess->isid[0], sess->isid[1], sess->isid[2],
sess->isid[3], sess->isid[4], sess->isid[5],
sess->tsih);
rb += sprintf(page+rb, "SessionType: %s\n", rb += sprintf(page+rb, "SessionType: %s\n",
(sess->sess_ops->SessionType) ? (sess->sess_ops->SessionType) ?
"Discovery" : "Normal"); "Discovery" : "Normal");
...@@ -1758,9 +1755,7 @@ static u32 lio_sess_get_initiator_sid( ...@@ -1758,9 +1755,7 @@ static u32 lio_sess_get_initiator_sid(
/* /*
* iSCSI Initiator Session Identifier from RFC-3720. * iSCSI Initiator Session Identifier from RFC-3720.
*/ */
return snprintf(buf, size, "%02x%02x%02x%02x%02x%02x", return snprintf(buf, size, "%6phN", sess->isid);
sess->isid[0], sess->isid[1], sess->isid[2],
sess->isid[3], sess->isid[4], sess->isid[5]);
} }
static int lio_queue_data_in(struct se_cmd *se_cmd) static int lio_queue_data_in(struct se_cmd *se_cmd)
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
#include <scsi/iscsi_proto.h> #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_seq_pdu_list.h"
#include "iscsi_target_erl1.h" #include "iscsi_target_erl1.h"
#include "iscsi_target_util.h" #include "iscsi_target_util.h"
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
#include <target/target_core_base.h> #include <target/target_core_base.h>
#include <target/target_core_fabric.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_device.h"
#include "iscsi_target_tpg.h" #include "iscsi_target_tpg.h"
#include "iscsi_target_util.h" #include "iscsi_target_util.h"
......
...@@ -21,7 +21,8 @@ ...@@ -21,7 +21,8 @@
#include <target/target_core_base.h> #include <target/target_core_base.h>
#include <target/target_core_fabric.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_seq_pdu_list.h"
#include "iscsi_target_tq.h" #include "iscsi_target_tq.h"
#include "iscsi_target_erl0.h" #include "iscsi_target_erl0.h"
...@@ -939,7 +940,8 @@ void iscsit_take_action_for_connection_exit(struct iscsi_conn *conn) ...@@ -939,7 +940,8 @@ void iscsit_take_action_for_connection_exit(struct iscsi_conn *conn)
if (conn->conn_state == TARG_CONN_STATE_IN_LOGOUT) { if (conn->conn_state == TARG_CONN_STATE_IN_LOGOUT) {
spin_unlock_bh(&conn->state_lock); spin_unlock_bh(&conn->state_lock);
iscsit_close_connection(conn); if (conn->conn_transport->transport_type == ISCSI_TCP)
iscsit_close_connection(conn);
return; return;
} }
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
#include <target/target_core_fabric.h> #include <target/target_core_fabric.h>
#include <target/iscsi/iscsi_transport.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_seq_pdu_list.h"
#include "iscsi_target_datain_values.h" #include "iscsi_target_datain_values.h"
#include "iscsi_target_device.h" #include "iscsi_target_device.h"
......
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
#include <target/target_core_base.h> #include <target/target_core_base.h>
#include <target/target_core_fabric.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_datain_values.h"
#include "iscsi_target_util.h" #include "iscsi_target_util.h"
#include "iscsi_target_erl0.h" #include "iscsi_target_erl0.h"
......
...@@ -24,14 +24,14 @@ ...@@ -24,14 +24,14 @@
#include <target/target_core_base.h> #include <target/target_core_base.h>
#include <target/target_core_fabric.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_tq.h"
#include "iscsi_target_device.h" #include "iscsi_target_device.h"
#include "iscsi_target_nego.h" #include "iscsi_target_nego.h"
#include "iscsi_target_erl0.h" #include "iscsi_target_erl0.h"
#include "iscsi_target_erl2.h" #include "iscsi_target_erl2.h"
#include "iscsi_target_login.h" #include "iscsi_target_login.h"
#include "iscsi_target_stat.h"
#include "iscsi_target_tpg.h" #include "iscsi_target_tpg.h"
#include "iscsi_target_util.h" #include "iscsi_target_util.h"
#include "iscsi_target.h" #include "iscsi_target.h"
......
...@@ -22,7 +22,7 @@ ...@@ -22,7 +22,7 @@
#include <target/target_core_fabric.h> #include <target/target_core_fabric.h>
#include <target/iscsi/iscsi_transport.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_parameters.h"
#include "iscsi_target_login.h" #include "iscsi_target_login.h"
#include "iscsi_target_nego.h" #include "iscsi_target_nego.h"
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
#include <target/target_core_base.h> #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_device.h"
#include "iscsi_target_tpg.h" #include "iscsi_target_tpg.h"
#include "iscsi_target_util.h" #include "iscsi_target_util.h"
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include "iscsi_target_core.h" #include <target/iscsi/iscsi_target_core.h>
#include "iscsi_target_util.h" #include "iscsi_target_util.h"
#include "iscsi_target_parameters.h" #include "iscsi_target_parameters.h"
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/random.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_util.h"
#include "iscsi_target_tpg.h" #include "iscsi_target_tpg.h"
#include "iscsi_target_seq_pdu_list.h" #include "iscsi_target_seq_pdu_list.h"
......
...@@ -23,12 +23,12 @@ ...@@ -23,12 +23,12 @@
#include <target/target_core_base.h> #include <target/target_core_base.h>
#include <target/configfs_macros.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_parameters.h"
#include "iscsi_target_device.h" #include "iscsi_target_device.h"
#include "iscsi_target_tpg.h" #include "iscsi_target_tpg.h"
#include "iscsi_target_util.h" #include "iscsi_target_util.h"
#include "iscsi_target_stat.h" #include <target/iscsi/iscsi_target_stat.h>
#ifndef INITIAL_JIFFIES #ifndef INITIAL_JIFFIES
#define INITIAL_JIFFIES ((unsigned long)(unsigned int) (-300*HZ)) #define INITIAL_JIFFIES ((unsigned long)(unsigned int) (-300*HZ))
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
#include <target/target_core_fabric.h> #include <target/target_core_fabric.h>
#include <target/iscsi/iscsi_transport.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_seq_pdu_list.h"
#include "iscsi_target_datain_values.h" #include "iscsi_target_datain_values.h"
#include "iscsi_target_device.h" #include "iscsi_target_device.h"
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
#include <target/target_core_fabric.h> #include <target/target_core_fabric.h>
#include <target/target_core_configfs.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_erl0.h"
#include "iscsi_target_login.h" #include "iscsi_target_login.h"
#include "iscsi_target_nodeattrib.h" #include "iscsi_target_nodeattrib.h"
......
...@@ -20,40 +20,26 @@ ...@@ -20,40 +20,26 @@
#include <linux/list.h> #include <linux/list.h>
#include <linux/bitmap.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_tq.h"
#include "iscsi_target.h" #include "iscsi_target.h"
static LIST_HEAD(active_ts_list);
static LIST_HEAD(inactive_ts_list); static LIST_HEAD(inactive_ts_list);
static DEFINE_SPINLOCK(active_ts_lock);
static DEFINE_SPINLOCK(inactive_ts_lock); static DEFINE_SPINLOCK(inactive_ts_lock);
static DEFINE_SPINLOCK(ts_bitmap_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) 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); spin_lock(&inactive_ts_lock);
list_add_tail(&ts->ts_list, &inactive_ts_list); list_add_tail(&ts->ts_list, &inactive_ts_list);
iscsit_global->inactive_ts++; iscsit_global->inactive_ts++;
spin_unlock(&inactive_ts_lock); 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) static struct iscsi_thread_set *iscsi_get_ts_from_inactive_list(void)
{ {
struct iscsi_thread_set *ts; struct iscsi_thread_set *ts;
...@@ -66,7 +52,7 @@ static struct iscsi_thread_set *iscsi_get_ts_from_inactive_list(void) ...@@ -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); 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--; iscsit_global->inactive_ts--;
spin_unlock(&inactive_ts_lock); spin_unlock(&inactive_ts_lock);
...@@ -204,8 +190,6 @@ static void iscsi_deallocate_extra_thread_sets(void) ...@@ -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) 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); spin_lock_bh(&ts->ts_state_lock);
conn->thread_set = ts; conn->thread_set = ts;
ts->conn = conn; ts->conn = conn;
...@@ -397,7 +381,6 @@ struct iscsi_conn *iscsi_rx_thread_pre_handler(struct iscsi_thread_set *ts) ...@@ -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)) { if (ts->delay_inactive && (--ts->thread_count == 0)) {
spin_unlock_bh(&ts->ts_state_lock); spin_unlock_bh(&ts->ts_state_lock);
iscsi_del_ts_from_active_list(ts);
if (!iscsit_global->in_shutdown) if (!iscsit_global->in_shutdown)
iscsi_deallocate_extra_thread_sets(); iscsi_deallocate_extra_thread_sets();
...@@ -452,7 +435,6 @@ struct iscsi_conn *iscsi_tx_thread_pre_handler(struct iscsi_thread_set *ts) ...@@ -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)) { if (ts->delay_inactive && (--ts->thread_count == 0)) {
spin_unlock_bh(&ts->ts_state_lock); spin_unlock_bh(&ts->ts_state_lock);
iscsi_del_ts_from_active_list(ts);
if (!iscsit_global->in_shutdown) if (!iscsit_global->in_shutdown)
iscsi_deallocate_extra_thread_sets(); iscsi_deallocate_extra_thread_sets();
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
#include <target/target_core_configfs.h> #include <target/target_core_configfs.h>
#include <target/iscsi/iscsi_transport.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_parameters.h"
#include "iscsi_target_seq_pdu_list.h" #include "iscsi_target_seq_pdu_list.h"
#include "iscsi_target_datain_values.h" #include "iscsi_target_datain_values.h"
...@@ -390,6 +390,7 @@ struct iscsi_cmd *iscsit_find_cmd_from_itt( ...@@ -390,6 +390,7 @@ struct iscsi_cmd *iscsit_find_cmd_from_itt(
init_task_tag, conn->cid); init_task_tag, conn->cid);
return NULL; return NULL;
} }
EXPORT_SYMBOL(iscsit_find_cmd_from_itt);
struct iscsi_cmd *iscsit_find_cmd_from_itt_or_dump( struct iscsi_cmd *iscsit_find_cmd_from_itt_or_dump(
struct iscsi_conn *conn, struct iscsi_conn *conn,
...@@ -939,13 +940,8 @@ static int iscsit_add_nopin(struct iscsi_conn *conn, int want_response) ...@@ -939,13 +940,8 @@ static int iscsit_add_nopin(struct iscsi_conn *conn, int want_response)
state = (want_response) ? ISTATE_SEND_NOPIN_WANT_RESPONSE : state = (want_response) ? ISTATE_SEND_NOPIN_WANT_RESPONSE :
ISTATE_SEND_NOPIN_NO_RESPONSE; ISTATE_SEND_NOPIN_NO_RESPONSE;
cmd->init_task_tag = RESERVED_ITT; cmd->init_task_tag = RESERVED_ITT;
spin_lock_bh(&conn->sess->ttt_lock); cmd->targ_xfer_tag = (want_response) ?
cmd->targ_xfer_tag = (want_response) ? conn->sess->targ_xfer_tag++ : session_get_next_ttt(conn->sess) : 0xFFFFFFFF;
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);
spin_lock_bh(&conn->cmd_lock); spin_lock_bh(&conn->cmd_lock);
list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list); list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
spin_unlock_bh(&conn->cmd_lock); spin_unlock_bh(&conn->cmd_lock);
......
...@@ -16,7 +16,6 @@ extern struct iscsi_r2t *iscsit_get_holder_for_r2tsn(struct iscsi_cmd *, u32); ...@@ -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, extern int iscsit_sequence_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
unsigned char * ,__be32 cmdsn); unsigned char * ,__be32 cmdsn);
extern int iscsit_check_unsolicited_dataout(struct iscsi_cmd *, unsigned char *); 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 *, extern struct iscsi_cmd *iscsit_find_cmd_from_itt_or_dump(struct iscsi_conn *,
itt_t, u32); itt_t, u32);
extern struct iscsi_cmd *iscsit_find_cmd_from_ttt(struct iscsi_conn *, 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) ...@@ -494,6 +494,11 @@ fd_execute_write_same(struct se_cmd *cmd)
target_complete_cmd(cmd, SAM_STAT_GOOD); target_complete_cmd(cmd, SAM_STAT_GOOD);
return 0; 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]; sg = &cmd->t_data_sg[0];
if (cmd->t_data_nents > 1 || if (cmd->t_data_nents > 1 ||
......
...@@ -464,6 +464,11 @@ iblock_execute_write_same(struct se_cmd *cmd) ...@@ -464,6 +464,11 @@ iblock_execute_write_same(struct se_cmd *cmd)
sector_t block_lba = cmd->t_task_lba; sector_t block_lba = cmd->t_task_lba;
sector_t sectors = sbc_get_write_same_sectors(cmd); 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]; sg = &cmd->t_data_sg[0];
if (cmd->t_data_nents > 1 || if (cmd->t_data_nents > 1 ||
......
...@@ -1874,8 +1874,8 @@ static int core_scsi3_update_aptpl_buf( ...@@ -1874,8 +1874,8 @@ static int core_scsi3_update_aptpl_buf(
} }
if ((len + strlen(tmp) >= pr_aptpl_buf_len)) { if ((len + strlen(tmp) >= pr_aptpl_buf_len)) {
pr_err("Unable to update renaming" pr_err("Unable to update renaming APTPL metadata,"
" APTPL metadata\n"); " reallocating larger buffer\n");
ret = -EMSGSIZE; ret = -EMSGSIZE;
goto out; goto out;
} }
...@@ -1892,8 +1892,8 @@ static int core_scsi3_update_aptpl_buf( ...@@ -1892,8 +1892,8 @@ static int core_scsi3_update_aptpl_buf(
lun->lun_sep->sep_rtpi, lun->unpacked_lun, reg_count); lun->lun_sep->sep_rtpi, lun->unpacked_lun, reg_count);
if ((len + strlen(tmp) >= pr_aptpl_buf_len)) { if ((len + strlen(tmp) >= pr_aptpl_buf_len)) {
pr_err("Unable to update renaming" pr_err("Unable to update renaming APTPL metadata,"
" APTPL metadata\n"); " reallocating larger buffer\n");
ret = -EMSGSIZE; ret = -EMSGSIZE;
goto out; goto out;
} }
...@@ -1956,7 +1956,7 @@ static int __core_scsi3_write_aptpl_to_file( ...@@ -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) static sense_reason_t core_scsi3_update_and_write_aptpl(struct se_device *dev, bool aptpl)
{ {
unsigned char *buf; unsigned char *buf;
int rc; int rc, len = PR_APTPL_BUF_LEN;
if (!aptpl) { if (!aptpl) {
char *null_buf = "No Registrations or Reservations\n"; 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 ...@@ -1970,25 +1970,26 @@ static sense_reason_t core_scsi3_update_and_write_aptpl(struct se_device *dev, b
return 0; return 0;
} }
retry:
buf = kzalloc(PR_APTPL_BUF_LEN, GFP_KERNEL); buf = vzalloc(len);
if (!buf) if (!buf)
return TCM_OUT_OF_RESOURCES; 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) { if (rc < 0) {
kfree(buf); vfree(buf);
return TCM_OUT_OF_RESOURCES; len *= 2;
goto retry;
} }
rc = __core_scsi3_write_aptpl_to_file(dev, buf); rc = __core_scsi3_write_aptpl_to_file(dev, buf);
if (rc != 0) { if (rc != 0) {
pr_err("SPC-3 PR: Could not update APTPL\n"); pr_err("SPC-3 PR: Could not update APTPL\n");
kfree(buf); vfree(buf);
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
} }
dev->t10_pr.pr_aptpl_active = 1; dev->t10_pr.pr_aptpl_active = 1;
kfree(buf); vfree(buf);
pr_debug("SPC-3 PR: Set APTPL Bit Activated\n"); pr_debug("SPC-3 PR: Set APTPL Bit Activated\n");
return 0; return 0;
} }
......
...@@ -36,6 +36,9 @@ ...@@ -36,6 +36,9 @@
#include "target_core_ua.h" #include "target_core_ua.h"
#include "target_core_alua.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 static sense_reason_t
sbc_emulate_readcapacity(struct se_cmd *cmd) sbc_emulate_readcapacity(struct se_cmd *cmd)
{ {
...@@ -251,7 +254,10 @@ static inline unsigned long long transport_lba_64_ext(unsigned char *cdb) ...@@ -251,7 +254,10 @@ static inline unsigned long long transport_lba_64_ext(unsigned char *cdb)
static sense_reason_t static sense_reason_t
sbc_setup_write_same(struct se_cmd *cmd, unsigned char *flags, struct sbc_ops *ops) 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); unsigned int sectors = sbc_get_write_same_sectors(cmd);
sense_reason_t ret;
if ((flags[0] & 0x04) || (flags[0] & 0x02)) { if ((flags[0] & 0x04) || (flags[0] & 0x02)) {
pr_err("WRITE_SAME PBDATA and LBDATA" 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 ...@@ -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); sectors, cmd->se_dev->dev_attrib.max_write_same_len);
return TCM_INVALID_CDB_FIELD; 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 */ /* We always have ANC_SUP == 0 so setting ANCHOR is always an error */
if (flags[0] & 0x10) { if (flags[0] & 0x10) {
pr_warn("WRITE SAME with ANCHOR not supported\n"); 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 ...@@ -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) if (!ops->execute_write_same_unmap)
return TCM_UNSUPPORTED_SCSI_OPCODE; 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; cmd->execute_cmd = ops->execute_write_same_unmap;
return 0; return 0;
} }
if (!ops->execute_write_same) if (!ops->execute_write_same)
return TCM_UNSUPPORTED_SCSI_OPCODE; 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; cmd->execute_cmd = ops->execute_write_same;
return 0; return 0;
} }
...@@ -614,14 +639,21 @@ sbc_set_prot_op_checks(u8 protect, enum target_prot_type prot_type, ...@@ -614,14 +639,21 @@ sbc_set_prot_op_checks(u8 protect, enum target_prot_type prot_type,
return 0; return 0;
} }
static bool static sense_reason_t
sbc_check_prot(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb, sbc_check_prot(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb,
u32 sectors, bool is_write) u32 sectors, bool is_write)
{ {
u8 protect = cdb[1] >> 5; u8 protect = cdb[1] >> 5;
if ((!cmd->t_prot_sg || !cmd->t_prot_nents) && cmd->prot_pto) if (!cmd->t_prot_sg || !cmd->t_prot_nents) {
return true; 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) { switch (dev->dev_attrib.pi_prot_type) {
case TARGET_DIF_TYPE3_PROT: case TARGET_DIF_TYPE3_PROT:
...@@ -629,7 +661,7 @@ sbc_check_prot(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb, ...@@ -629,7 +661,7 @@ sbc_check_prot(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb,
break; break;
case TARGET_DIF_TYPE2_PROT: case TARGET_DIF_TYPE2_PROT:
if (protect) if (protect)
return false; return TCM_INVALID_CDB_FIELD;
cmd->reftag_seed = cmd->t_task_lba; cmd->reftag_seed = cmd->t_task_lba;
break; break;
...@@ -638,12 +670,12 @@ sbc_check_prot(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb, ...@@ -638,12 +670,12 @@ sbc_check_prot(struct se_device *dev, struct se_cmd *cmd, unsigned char *cdb,
break; break;
case TARGET_DIF_TYPE0_PROT: case TARGET_DIF_TYPE0_PROT:
default: default:
return true; return TCM_NO_SENSE;
} }
if (sbc_set_prot_op_checks(protect, dev->dev_attrib.pi_prot_type, if (sbc_set_prot_op_checks(protect, dev->dev_attrib.pi_prot_type,
is_write, cmd)) is_write, cmd))
return false; return TCM_INVALID_CDB_FIELD;
cmd->prot_type = dev->dev_attrib.pi_prot_type; cmd->prot_type = dev->dev_attrib.pi_prot_type;
cmd->prot_length = dev->prot_length * sectors; 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, ...@@ -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, __func__, cmd->prot_type, cmd->data_length, cmd->prot_length,
cmd->prot_op, cmd->prot_checks); 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 sense_reason_t
...@@ -686,8 +741,12 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) ...@@ -686,8 +741,12 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
sectors = transport_get_sectors_10(cdb); sectors = transport_get_sectors_10(cdb);
cmd->t_task_lba = transport_lba_32(cdb); cmd->t_task_lba = transport_lba_32(cdb);
if (!sbc_check_prot(dev, cmd, cdb, sectors, false)) if (sbc_check_dpofua(dev, cmd, cdb))
return TCM_UNSUPPORTED_SCSI_OPCODE; 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->se_cmd_flags |= SCF_SCSI_DATA_CDB;
cmd->execute_rw = ops->execute_rw; cmd->execute_rw = ops->execute_rw;
...@@ -697,8 +756,12 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) ...@@ -697,8 +756,12 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
sectors = transport_get_sectors_12(cdb); sectors = transport_get_sectors_12(cdb);
cmd->t_task_lba = transport_lba_32(cdb); cmd->t_task_lba = transport_lba_32(cdb);
if (!sbc_check_prot(dev, cmd, cdb, sectors, false)) if (sbc_check_dpofua(dev, cmd, cdb))
return TCM_UNSUPPORTED_SCSI_OPCODE; 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->se_cmd_flags |= SCF_SCSI_DATA_CDB;
cmd->execute_rw = ops->execute_rw; cmd->execute_rw = ops->execute_rw;
...@@ -708,8 +771,12 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) ...@@ -708,8 +771,12 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
sectors = transport_get_sectors_16(cdb); sectors = transport_get_sectors_16(cdb);
cmd->t_task_lba = transport_lba_64(cdb); cmd->t_task_lba = transport_lba_64(cdb);
if (!sbc_check_prot(dev, cmd, cdb, sectors, false)) if (sbc_check_dpofua(dev, cmd, cdb))
return TCM_UNSUPPORTED_SCSI_OPCODE; 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->se_cmd_flags |= SCF_SCSI_DATA_CDB;
cmd->execute_rw = ops->execute_rw; cmd->execute_rw = ops->execute_rw;
...@@ -727,11 +794,13 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) ...@@ -727,11 +794,13 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
sectors = transport_get_sectors_10(cdb); sectors = transport_get_sectors_10(cdb);
cmd->t_task_lba = transport_lba_32(cdb); cmd->t_task_lba = transport_lba_32(cdb);
if (!sbc_check_prot(dev, cmd, cdb, sectors, true)) if (sbc_check_dpofua(dev, cmd, cdb))
return TCM_UNSUPPORTED_SCSI_OPCODE; 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->se_cmd_flags |= SCF_SCSI_DATA_CDB;
cmd->execute_rw = ops->execute_rw; cmd->execute_rw = ops->execute_rw;
cmd->execute_cmd = sbc_execute_rw; cmd->execute_cmd = sbc_execute_rw;
...@@ -740,11 +809,13 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) ...@@ -740,11 +809,13 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
sectors = transport_get_sectors_12(cdb); sectors = transport_get_sectors_12(cdb);
cmd->t_task_lba = transport_lba_32(cdb); cmd->t_task_lba = transport_lba_32(cdb);
if (!sbc_check_prot(dev, cmd, cdb, sectors, true)) if (sbc_check_dpofua(dev, cmd, cdb))
return TCM_UNSUPPORTED_SCSI_OPCODE; 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->se_cmd_flags |= SCF_SCSI_DATA_CDB;
cmd->execute_rw = ops->execute_rw; cmd->execute_rw = ops->execute_rw;
cmd->execute_cmd = sbc_execute_rw; cmd->execute_cmd = sbc_execute_rw;
...@@ -753,11 +824,13 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) ...@@ -753,11 +824,13 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
sectors = transport_get_sectors_16(cdb); sectors = transport_get_sectors_16(cdb);
cmd->t_task_lba = transport_lba_64(cdb); cmd->t_task_lba = transport_lba_64(cdb);
if (!sbc_check_prot(dev, cmd, cdb, sectors, true)) if (sbc_check_dpofua(dev, cmd, cdb))
return TCM_UNSUPPORTED_SCSI_OPCODE; 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->se_cmd_flags |= SCF_SCSI_DATA_CDB;
cmd->execute_rw = ops->execute_rw; cmd->execute_rw = ops->execute_rw;
cmd->execute_cmd = sbc_execute_rw; cmd->execute_cmd = sbc_execute_rw;
...@@ -768,6 +841,9 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) ...@@ -768,6 +841,9 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
return TCM_INVALID_CDB_FIELD; return TCM_INVALID_CDB_FIELD;
sectors = transport_get_sectors_10(cdb); 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->t_task_lba = transport_lba_32(cdb);
cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB; cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
...@@ -777,8 +853,6 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) ...@@ -777,8 +853,6 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
cmd->execute_rw = ops->execute_rw; cmd->execute_rw = ops->execute_rw;
cmd->execute_cmd = sbc_execute_rw; cmd->execute_cmd = sbc_execute_rw;
cmd->transport_complete_callback = &xdreadwrite_callback; cmd->transport_complete_callback = &xdreadwrite_callback;
if (cdb[1] & 0x8)
cmd->se_cmd_flags |= SCF_FUA;
break; break;
case VARIABLE_LENGTH_CMD: case VARIABLE_LENGTH_CMD:
{ {
...@@ -787,6 +861,8 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) ...@@ -787,6 +861,8 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
case XDWRITEREAD_32: case XDWRITEREAD_32:
sectors = transport_get_sectors_32(cdb); 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 * Use WRITE_32 and READ_32 opcodes for the emulated
* XDWRITE_READ_32 logic. * XDWRITE_READ_32 logic.
...@@ -801,8 +877,6 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) ...@@ -801,8 +877,6 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
cmd->execute_rw = ops->execute_rw; cmd->execute_rw = ops->execute_rw;
cmd->execute_cmd = sbc_execute_rw; cmd->execute_cmd = sbc_execute_rw;
cmd->transport_complete_callback = &xdreadwrite_callback; cmd->transport_complete_callback = &xdreadwrite_callback;
if (cdb[1] & 0x8)
cmd->se_cmd_flags |= SCF_FUA;
break; break;
case WRITE_SAME_32: case WRITE_SAME_32:
sectors = transport_get_sectors_32(cdb); sectors = transport_get_sectors_32(cdb);
...@@ -888,6 +962,11 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) ...@@ -888,6 +962,11 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
if (!ops->execute_unmap) if (!ops->execute_unmap)
return TCM_UNSUPPORTED_SCSI_OPCODE; 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]); size = get_unaligned_be16(&cdb[7]);
cmd->execute_cmd = ops->execute_unmap; cmd->execute_cmd = ops->execute_unmap;
break; break;
...@@ -955,7 +1034,8 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) ...@@ -955,7 +1034,8 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
unsigned long long end_lba; unsigned long long end_lba;
check_lba: check_lba:
end_lba = dev->transport->get_blocks(dev) + 1; 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 " pr_err("cmd exceeds last lba %llu "
"(lba %llu, sectors %u)\n", "(lba %llu, sectors %u)\n",
end_lba, cmd->t_task_lba, sectors); end_lba, cmd->t_task_lba, sectors);
......
...@@ -647,7 +647,7 @@ spc_emulate_evpd_b2(struct se_cmd *cmd, unsigned char *buf) ...@@ -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. * support the use of the WRITE SAME (16) command to unmap LBAs.
*/ */
if (dev->dev_attrib.emulate_tpws != 0) if (dev->dev_attrib.emulate_tpws != 0)
buf[5] |= 0x40; buf[5] |= 0x40 | 0x20;
return 0; return 0;
} }
......
This diff is collapsed.
...@@ -880,4 +880,18 @@ struct iscsit_global { ...@@ -880,4 +880,18 @@ struct iscsit_global {
struct iscsi_portal_group *discovery_tpg; 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 */ #endif /* ISCSI_TARGET_CORE_H */
#include <linux/module.h> #include <linux/module.h>
#include <linux/list.h> #include <linux/list.h>
#include "../../../drivers/target/iscsi/iscsi_target_core.h" #include "iscsi_target_core.h"
struct iscsit_transport { struct iscsit_transport {
#define ISCSIT_TRANSPORT_NAME 16 #define ISCSIT_TRANSPORT_NAME 16
......
...@@ -407,7 +407,7 @@ struct t10_reservation { ...@@ -407,7 +407,7 @@ struct t10_reservation {
/* Activate Persistence across Target Power Loss enabled /* Activate Persistence across Target Power Loss enabled
* for SCSI device */ * for SCSI device */
int pr_aptpl_active; int pr_aptpl_active;
#define PR_APTPL_BUF_LEN 8192 #define PR_APTPL_BUF_LEN 262144
u32 pr_generation; u32 pr_generation;
spinlock_t registration_lock; spinlock_t registration_lock;
spinlock_t aptpl_reg_lock; spinlock_t aptpl_reg_lock;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment