mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-11-24 20:20:50 +07:00
Merge branch '3.3-rc-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending
This series contains pending target bug-fixes and cleanups for v3.3-rc3 that have been addressed the past weeks in lio-core.git. Some of the highlights include: - Fix handling for control CDBs with data greater than PAGE_SIZE (andy) - Use IP_FREEBIND for iscsi-target to address network portal creation issues with systemd (dax) - Allow PERSISTENT RESERVE IN for non-reservation holder (marco) - Fix iblock se_dev_attrib.unmap_granularity (marco) - Fix unsupported WRITE_SAME sense payload handling (martin) - Add workaround for zero-length control CDB handling (nab) - Fix discovery with INADDR_ANY and IN6ADDR_ANY_INIT (nab) - Fix target_submit_cmd() exception handling (nab) - Return correct ASC for unimplemented VPD pages (roland) - Don't zero pages used for data buffers (roland) - Fix return code of core_tpg_.*_lun (sebastian) * '3.3-rc-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending: (26 commits) target: Fix unsupported WRITE_SAME sense payload iscsi: use IP_FREEBIND socket option iblock: fix handling of large requests target: handle empty string writes in sysfs iscsi_target: in_aton needs linux/inet.h target: Fix iblock se_dev_attrib.unmap_granularity target: Fix target_submit_cmd() exception handling target: Change target_submit_cmd() to return void target: accept REQUEST_SENSE with 18bytes target: Fail INQUIRY commands with EVPD==0 but PAGE CODE!=0 target: Return correct ASC for unimplemented VPD pages iscsi-target: Fix discovery with INADDR_ANY and IN6ADDR_ANY_INIT target: Allow control CDBs with data > 1 page iscsi-target: Fix up a few assignments iscsi-target: make one-bit bitfields unsigned iscsi-target: Fix double list_add with iscsit_alloc_buffs reject iscsi-target: Fix reject release handling in iscsit_free_cmd() target: fix return code of core_tpg_.*_lun target: use save/restore lock primitive in core_dec_lacl_count() target: avoid multiple outputs in scsi_dump_inquiry() ...
This commit is contained in:
commit
19e75ed46f
@ -1061,7 +1061,7 @@ static int iscsit_handle_scsi_cmd(
|
||||
if (ret < 0)
|
||||
return iscsit_add_reject_from_cmd(
|
||||
ISCSI_REASON_BOOKMARK_NO_RESOURCES,
|
||||
1, 1, buf, cmd);
|
||||
1, 0, buf, cmd);
|
||||
/*
|
||||
* Check the CmdSN against ExpCmdSN/MaxCmdSN here if
|
||||
* the Immediate Bit is not set, and no Immediate
|
||||
@ -3164,6 +3164,30 @@ static int iscsit_send_task_mgt_rsp(
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool iscsit_check_inaddr_any(struct iscsi_np *np)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
if (np->np_sockaddr.ss_family == AF_INET6) {
|
||||
const struct sockaddr_in6 sin6 = {
|
||||
.sin6_addr = IN6ADDR_ANY_INIT };
|
||||
struct sockaddr_in6 *sock_in6 =
|
||||
(struct sockaddr_in6 *)&np->np_sockaddr;
|
||||
|
||||
if (!memcmp(sock_in6->sin6_addr.s6_addr,
|
||||
sin6.sin6_addr.s6_addr, 16))
|
||||
ret = true;
|
||||
} else {
|
||||
struct sockaddr_in * sock_in =
|
||||
(struct sockaddr_in *)&np->np_sockaddr;
|
||||
|
||||
if (sock_in->sin_addr.s_addr == INADDR_ANY)
|
||||
ret = true;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int iscsit_build_sendtargets_response(struct iscsi_cmd *cmd)
|
||||
{
|
||||
char *payload = NULL;
|
||||
@ -3213,12 +3237,17 @@ static int iscsit_build_sendtargets_response(struct iscsi_cmd *cmd)
|
||||
spin_lock(&tpg->tpg_np_lock);
|
||||
list_for_each_entry(tpg_np, &tpg->tpg_gnp_list,
|
||||
tpg_np_list) {
|
||||
struct iscsi_np *np = tpg_np->tpg_np;
|
||||
bool inaddr_any = iscsit_check_inaddr_any(np);
|
||||
|
||||
len = sprintf(buf, "TargetAddress="
|
||||
"%s%s%s:%hu,%hu",
|
||||
(tpg_np->tpg_np->np_sockaddr.ss_family == AF_INET6) ?
|
||||
"[" : "", tpg_np->tpg_np->np_ip,
|
||||
(tpg_np->tpg_np->np_sockaddr.ss_family == AF_INET6) ?
|
||||
"]" : "", tpg_np->tpg_np->np_port,
|
||||
(np->np_sockaddr.ss_family == AF_INET6) ?
|
||||
"[" : "", (inaddr_any == false) ?
|
||||
np->np_ip : conn->local_ip,
|
||||
(np->np_sockaddr.ss_family == AF_INET6) ?
|
||||
"]" : "", (inaddr_any == false) ?
|
||||
np->np_port : conn->local_port,
|
||||
tpg->tpgt);
|
||||
len += 1;
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
#include <linux/configfs.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/inet.h>
|
||||
#include <target/target_core_base.h>
|
||||
#include <target/target_core_fabric.h>
|
||||
#include <target/target_core_fabric_configfs.h>
|
||||
|
@ -508,6 +508,7 @@ struct iscsi_conn {
|
||||
u16 cid;
|
||||
/* Remote TCP Port */
|
||||
u16 login_port;
|
||||
u16 local_port;
|
||||
int net_size;
|
||||
u32 auth_id;
|
||||
#define CONNFLAG_SCTP_STRUCT_FILE 0x01
|
||||
@ -527,6 +528,7 @@ struct iscsi_conn {
|
||||
unsigned char bad_hdr[ISCSI_HDR_LEN];
|
||||
#define IPV6_ADDRESS_SPACE 48
|
||||
unsigned char login_ip[IPV6_ADDRESS_SPACE];
|
||||
unsigned char local_ip[IPV6_ADDRESS_SPACE];
|
||||
int conn_usage_count;
|
||||
int conn_waiting_on_uc;
|
||||
atomic_t check_immediate_queue;
|
||||
@ -561,8 +563,8 @@ struct iscsi_conn {
|
||||
struct hash_desc conn_tx_hash;
|
||||
/* Used for scheduling TX and RX connection kthreads */
|
||||
cpumask_var_t conn_cpumask;
|
||||
int conn_rx_reset_cpumask:1;
|
||||
int conn_tx_reset_cpumask:1;
|
||||
unsigned int conn_rx_reset_cpumask:1;
|
||||
unsigned int conn_tx_reset_cpumask:1;
|
||||
/* list_head of struct iscsi_cmd for this connection */
|
||||
struct list_head conn_cmd_list;
|
||||
struct list_head immed_queue_list;
|
||||
|
@ -1238,7 +1238,7 @@ void iscsit_mod_dataout_timer(struct iscsi_cmd *cmd)
|
||||
{
|
||||
struct iscsi_conn *conn = cmd->conn;
|
||||
struct iscsi_session *sess = conn->sess;
|
||||
struct iscsi_node_attrib *na = na = iscsit_tpg_get_node_attrib(sess);
|
||||
struct iscsi_node_attrib *na = iscsit_tpg_get_node_attrib(sess);
|
||||
|
||||
spin_lock_bh(&cmd->dataout_timeout_lock);
|
||||
if (!(cmd->dataout_timer_flags & ISCSI_TF_RUNNING)) {
|
||||
@ -1261,7 +1261,7 @@ void iscsit_start_dataout_timer(
|
||||
struct iscsi_conn *conn)
|
||||
{
|
||||
struct iscsi_session *sess = conn->sess;
|
||||
struct iscsi_node_attrib *na = na = iscsit_tpg_get_node_attrib(sess);
|
||||
struct iscsi_node_attrib *na = iscsit_tpg_get_node_attrib(sess);
|
||||
|
||||
if (cmd->dataout_timer_flags & ISCSI_TF_RUNNING)
|
||||
return;
|
||||
|
@ -615,8 +615,8 @@ static int iscsi_post_login_handler(
|
||||
}
|
||||
|
||||
pr_debug("iSCSI Login successful on CID: %hu from %s to"
|
||||
" %s:%hu,%hu\n", conn->cid, conn->login_ip, np->np_ip,
|
||||
np->np_port, tpg->tpgt);
|
||||
" %s:%hu,%hu\n", conn->cid, conn->login_ip,
|
||||
conn->local_ip, conn->local_port, tpg->tpgt);
|
||||
|
||||
list_add_tail(&conn->conn_list, &sess->sess_conn_list);
|
||||
atomic_inc(&sess->nconn);
|
||||
@ -658,7 +658,8 @@ static int iscsi_post_login_handler(
|
||||
sess->session_state = TARG_SESS_STATE_LOGGED_IN;
|
||||
|
||||
pr_debug("iSCSI Login successful on CID: %hu from %s to %s:%hu,%hu\n",
|
||||
conn->cid, conn->login_ip, np->np_ip, np->np_port, tpg->tpgt);
|
||||
conn->cid, conn->login_ip, conn->local_ip, conn->local_port,
|
||||
tpg->tpgt);
|
||||
|
||||
spin_lock_bh(&sess->conn_lock);
|
||||
list_add_tail(&conn->conn_list, &sess->sess_conn_list);
|
||||
@ -841,6 +842,14 @@ int iscsi_target_setup_login_socket(
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = kernel_setsockopt(sock, IPPROTO_IP, IP_FREEBIND,
|
||||
(char *)&opt, sizeof(opt));
|
||||
if (ret < 0) {
|
||||
pr_err("kernel_setsockopt() for IP_FREEBIND"
|
||||
" failed\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ret = kernel_bind(sock, (struct sockaddr *)&np->np_sockaddr, len);
|
||||
if (ret < 0) {
|
||||
pr_err("kernel_bind() failed: %d\n", ret);
|
||||
@ -1020,6 +1029,18 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
|
||||
snprintf(conn->login_ip, sizeof(conn->login_ip), "%pI6c",
|
||||
&sock_in6.sin6_addr.in6_u);
|
||||
conn->login_port = ntohs(sock_in6.sin6_port);
|
||||
|
||||
if (conn->sock->ops->getname(conn->sock,
|
||||
(struct sockaddr *)&sock_in6, &err, 0) < 0) {
|
||||
pr_err("sock_ops->getname() failed.\n");
|
||||
iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
|
||||
ISCSI_LOGIN_STATUS_TARGET_ERROR);
|
||||
goto new_sess_out;
|
||||
}
|
||||
snprintf(conn->local_ip, sizeof(conn->local_ip), "%pI6c",
|
||||
&sock_in6.sin6_addr.in6_u);
|
||||
conn->local_port = ntohs(sock_in6.sin6_port);
|
||||
|
||||
} else {
|
||||
memset(&sock_in, 0, sizeof(struct sockaddr_in));
|
||||
|
||||
@ -1032,6 +1053,16 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
|
||||
}
|
||||
sprintf(conn->login_ip, "%pI4", &sock_in.sin_addr.s_addr);
|
||||
conn->login_port = ntohs(sock_in.sin_port);
|
||||
|
||||
if (conn->sock->ops->getname(conn->sock,
|
||||
(struct sockaddr *)&sock_in, &err, 0) < 0) {
|
||||
pr_err("sock_ops->getname() failed.\n");
|
||||
iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
|
||||
ISCSI_LOGIN_STATUS_TARGET_ERROR);
|
||||
goto new_sess_out;
|
||||
}
|
||||
sprintf(conn->local_ip, "%pI4", &sock_in.sin_addr.s_addr);
|
||||
conn->local_port = ntohs(sock_in.sin_port);
|
||||
}
|
||||
|
||||
conn->network_transport = np->np_network_transport;
|
||||
@ -1039,7 +1070,7 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
|
||||
pr_debug("Received iSCSI login request from %s on %s Network"
|
||||
" Portal %s:%hu\n", conn->login_ip,
|
||||
(conn->network_transport == ISCSI_TCP) ? "TCP" : "SCTP",
|
||||
np->np_ip, np->np_port);
|
||||
conn->local_ip, conn->local_port);
|
||||
|
||||
pr_debug("Moving to TARG_CONN_STATE_IN_LOGIN.\n");
|
||||
conn->conn_state = TARG_CONN_STATE_IN_LOGIN;
|
||||
|
@ -849,6 +849,17 @@ void iscsit_free_cmd(struct iscsi_cmd *cmd)
|
||||
case ISCSI_OP_SCSI_TMFUNC:
|
||||
transport_generic_free_cmd(&cmd->se_cmd, 1);
|
||||
break;
|
||||
case ISCSI_OP_REJECT:
|
||||
/*
|
||||
* Handle special case for REJECT when iscsi_add_reject*() has
|
||||
* overwritten the original iscsi_opcode assignment, and the
|
||||
* associated cmd->se_cmd needs to be released.
|
||||
*/
|
||||
if (cmd->se_cmd.se_tfo != NULL) {
|
||||
transport_generic_free_cmd(&cmd->se_cmd, 1);
|
||||
break;
|
||||
}
|
||||
/* Fall-through */
|
||||
default:
|
||||
iscsit_release_cmd(cmd);
|
||||
break;
|
||||
|
@ -78,7 +78,7 @@ int target_emulate_report_target_port_groups(struct se_task *task)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
buf = transport_kmap_first_data_page(cmd);
|
||||
buf = transport_kmap_data_sg(cmd);
|
||||
|
||||
spin_lock(&su_dev->t10_alua.tg_pt_gps_lock);
|
||||
list_for_each_entry(tg_pt_gp, &su_dev->t10_alua.tg_pt_gps_list,
|
||||
@ -163,7 +163,7 @@ int target_emulate_report_target_port_groups(struct se_task *task)
|
||||
buf[2] = ((rd_len >> 8) & 0xff);
|
||||
buf[3] = (rd_len & 0xff);
|
||||
|
||||
transport_kunmap_first_data_page(cmd);
|
||||
transport_kunmap_data_sg(cmd);
|
||||
|
||||
task->task_scsi_status = GOOD;
|
||||
transport_complete_task(task, 1);
|
||||
@ -194,7 +194,7 @@ int target_emulate_set_target_port_groups(struct se_task *task)
|
||||
cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
||||
return -EINVAL;
|
||||
}
|
||||
buf = transport_kmap_first_data_page(cmd);
|
||||
buf = transport_kmap_data_sg(cmd);
|
||||
|
||||
/*
|
||||
* Determine if explict ALUA via SET_TARGET_PORT_GROUPS is allowed
|
||||
@ -351,7 +351,7 @@ int target_emulate_set_target_port_groups(struct se_task *task)
|
||||
}
|
||||
|
||||
out:
|
||||
transport_kunmap_first_data_page(cmd);
|
||||
transport_kunmap_data_sg(cmd);
|
||||
task->task_scsi_status = GOOD;
|
||||
transport_complete_task(task, 1);
|
||||
return 0;
|
||||
|
@ -83,7 +83,7 @@ target_emulate_inquiry_std(struct se_cmd *cmd)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
buf = transport_kmap_first_data_page(cmd);
|
||||
buf = transport_kmap_data_sg(cmd);
|
||||
|
||||
if (dev == tpg->tpg_virt_lun0.lun_se_dev) {
|
||||
buf[0] = 0x3f; /* Not connected */
|
||||
@ -134,7 +134,7 @@ target_emulate_inquiry_std(struct se_cmd *cmd)
|
||||
buf[4] = 31; /* Set additional length to 31 */
|
||||
|
||||
out:
|
||||
transport_kunmap_first_data_page(cmd);
|
||||
transport_kunmap_data_sg(cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -698,6 +698,13 @@ int target_emulate_inquiry(struct se_task *task)
|
||||
int p, ret;
|
||||
|
||||
if (!(cdb[1] & 0x1)) {
|
||||
if (cdb[2]) {
|
||||
pr_err("INQUIRY with EVPD==0 but PAGE CODE=%02x\n",
|
||||
cdb[2]);
|
||||
cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = target_emulate_inquiry_std(cmd);
|
||||
goto out;
|
||||
}
|
||||
@ -716,7 +723,7 @@ int target_emulate_inquiry(struct se_task *task)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
buf = transport_kmap_first_data_page(cmd);
|
||||
buf = transport_kmap_data_sg(cmd);
|
||||
|
||||
buf[0] = dev->transport->get_device_type(dev);
|
||||
|
||||
@ -729,11 +736,11 @@ int target_emulate_inquiry(struct se_task *task)
|
||||
}
|
||||
|
||||
pr_err("Unknown VPD Code: 0x%02x\n", cdb[2]);
|
||||
cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE;
|
||||
cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
|
||||
ret = -EINVAL;
|
||||
|
||||
out_unmap:
|
||||
transport_kunmap_first_data_page(cmd);
|
||||
transport_kunmap_data_sg(cmd);
|
||||
out:
|
||||
if (!ret) {
|
||||
task->task_scsi_status = GOOD;
|
||||
@ -755,7 +762,7 @@ int target_emulate_readcapacity(struct se_task *task)
|
||||
else
|
||||
blocks = (u32)blocks_long;
|
||||
|
||||
buf = transport_kmap_first_data_page(cmd);
|
||||
buf = transport_kmap_data_sg(cmd);
|
||||
|
||||
buf[0] = (blocks >> 24) & 0xff;
|
||||
buf[1] = (blocks >> 16) & 0xff;
|
||||
@ -771,7 +778,7 @@ int target_emulate_readcapacity(struct se_task *task)
|
||||
if (dev->se_sub_dev->se_dev_attrib.emulate_tpu || dev->se_sub_dev->se_dev_attrib.emulate_tpws)
|
||||
put_unaligned_be32(0xFFFFFFFF, &buf[0]);
|
||||
|
||||
transport_kunmap_first_data_page(cmd);
|
||||
transport_kunmap_data_sg(cmd);
|
||||
|
||||
task->task_scsi_status = GOOD;
|
||||
transport_complete_task(task, 1);
|
||||
@ -785,7 +792,7 @@ int target_emulate_readcapacity_16(struct se_task *task)
|
||||
unsigned char *buf;
|
||||
unsigned long long blocks = dev->transport->get_blocks(dev);
|
||||
|
||||
buf = transport_kmap_first_data_page(cmd);
|
||||
buf = transport_kmap_data_sg(cmd);
|
||||
|
||||
buf[0] = (blocks >> 56) & 0xff;
|
||||
buf[1] = (blocks >> 48) & 0xff;
|
||||
@ -806,7 +813,7 @@ int target_emulate_readcapacity_16(struct se_task *task)
|
||||
if (dev->se_sub_dev->se_dev_attrib.emulate_tpu || dev->se_sub_dev->se_dev_attrib.emulate_tpws)
|
||||
buf[14] = 0x80;
|
||||
|
||||
transport_kunmap_first_data_page(cmd);
|
||||
transport_kunmap_data_sg(cmd);
|
||||
|
||||
task->task_scsi_status = GOOD;
|
||||
transport_complete_task(task, 1);
|
||||
@ -1019,9 +1026,9 @@ int target_emulate_modesense(struct se_task *task)
|
||||
offset = cmd->data_length;
|
||||
}
|
||||
|
||||
rbuf = transport_kmap_first_data_page(cmd);
|
||||
rbuf = transport_kmap_data_sg(cmd);
|
||||
memcpy(rbuf, buf, offset);
|
||||
transport_kunmap_first_data_page(cmd);
|
||||
transport_kunmap_data_sg(cmd);
|
||||
|
||||
task->task_scsi_status = GOOD;
|
||||
transport_complete_task(task, 1);
|
||||
@ -1043,7 +1050,7 @@ int target_emulate_request_sense(struct se_task *task)
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
buf = transport_kmap_first_data_page(cmd);
|
||||
buf = transport_kmap_data_sg(cmd);
|
||||
|
||||
if (!core_scsi3_ua_clear_for_request_sense(cmd, &ua_asc, &ua_ascq)) {
|
||||
/*
|
||||
@ -1051,11 +1058,8 @@ int target_emulate_request_sense(struct se_task *task)
|
||||
*/
|
||||
buf[0] = 0x70;
|
||||
buf[SPC_SENSE_KEY_OFFSET] = UNIT_ATTENTION;
|
||||
/*
|
||||
* Make sure request data length is enough for additional
|
||||
* sense data.
|
||||
*/
|
||||
if (cmd->data_length <= 18) {
|
||||
|
||||
if (cmd->data_length < 18) {
|
||||
buf[7] = 0x00;
|
||||
err = -EINVAL;
|
||||
goto end;
|
||||
@ -1072,11 +1076,8 @@ int target_emulate_request_sense(struct se_task *task)
|
||||
*/
|
||||
buf[0] = 0x70;
|
||||
buf[SPC_SENSE_KEY_OFFSET] = NO_SENSE;
|
||||
/*
|
||||
* Make sure request data length is enough for additional
|
||||
* sense data.
|
||||
*/
|
||||
if (cmd->data_length <= 18) {
|
||||
|
||||
if (cmd->data_length < 18) {
|
||||
buf[7] = 0x00;
|
||||
err = -EINVAL;
|
||||
goto end;
|
||||
@ -1089,7 +1090,7 @@ int target_emulate_request_sense(struct se_task *task)
|
||||
}
|
||||
|
||||
end:
|
||||
transport_kunmap_first_data_page(cmd);
|
||||
transport_kunmap_data_sg(cmd);
|
||||
task->task_scsi_status = GOOD;
|
||||
transport_complete_task(task, 1);
|
||||
return 0;
|
||||
@ -1123,7 +1124,7 @@ int target_emulate_unmap(struct se_task *task)
|
||||
dl = get_unaligned_be16(&cdb[0]);
|
||||
bd_dl = get_unaligned_be16(&cdb[2]);
|
||||
|
||||
buf = transport_kmap_first_data_page(cmd);
|
||||
buf = transport_kmap_data_sg(cmd);
|
||||
|
||||
ptr = &buf[offset];
|
||||
pr_debug("UNMAP: Sub: %s Using dl: %hu bd_dl: %hu size: %hu"
|
||||
@ -1147,7 +1148,7 @@ int target_emulate_unmap(struct se_task *task)
|
||||
}
|
||||
|
||||
err:
|
||||
transport_kunmap_first_data_page(cmd);
|
||||
transport_kunmap_data_sg(cmd);
|
||||
if (!ret) {
|
||||
task->task_scsi_status = GOOD;
|
||||
transport_complete_task(task, 1);
|
||||
|
@ -1704,13 +1704,15 @@ static ssize_t target_core_store_dev_alias(
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
se_dev->su_dev_flags |= SDF_USING_ALIAS;
|
||||
read_bytes = snprintf(&se_dev->se_dev_alias[0], SE_DEV_ALIAS_LEN,
|
||||
"%s", page);
|
||||
|
||||
if (!read_bytes)
|
||||
return -EINVAL;
|
||||
if (se_dev->se_dev_alias[read_bytes - 1] == '\n')
|
||||
se_dev->se_dev_alias[read_bytes - 1] = '\0';
|
||||
|
||||
se_dev->su_dev_flags |= SDF_USING_ALIAS;
|
||||
|
||||
pr_debug("Target_Core_ConfigFS: %s/%s set alias: %s\n",
|
||||
config_item_name(&hba->hba_group.cg_item),
|
||||
config_item_name(&se_dev->se_dev_group.cg_item),
|
||||
@ -1753,13 +1755,15 @@ static ssize_t target_core_store_dev_udev_path(
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
se_dev->su_dev_flags |= SDF_USING_UDEV_PATH;
|
||||
read_bytes = snprintf(&se_dev->se_dev_udev_path[0], SE_UDEV_PATH_LEN,
|
||||
"%s", page);
|
||||
|
||||
if (!read_bytes)
|
||||
return -EINVAL;
|
||||
if (se_dev->se_dev_udev_path[read_bytes - 1] == '\n')
|
||||
se_dev->se_dev_udev_path[read_bytes - 1] = '\0';
|
||||
|
||||
se_dev->su_dev_flags |= SDF_USING_UDEV_PATH;
|
||||
|
||||
pr_debug("Target_Core_ConfigFS: %s/%s set udev_path: %s\n",
|
||||
config_item_name(&hba->hba_group.cg_item),
|
||||
config_item_name(&se_dev->se_dev_group.cg_item),
|
||||
|
@ -320,11 +320,12 @@ int core_free_device_list_for_node(
|
||||
void core_dec_lacl_count(struct se_node_acl *se_nacl, struct se_cmd *se_cmd)
|
||||
{
|
||||
struct se_dev_entry *deve;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irq(&se_nacl->device_list_lock);
|
||||
spin_lock_irqsave(&se_nacl->device_list_lock, flags);
|
||||
deve = &se_nacl->device_list[se_cmd->orig_fe_lun];
|
||||
deve->deve_cmds--;
|
||||
spin_unlock_irq(&se_nacl->device_list_lock);
|
||||
spin_unlock_irqrestore(&se_nacl->device_list_lock, flags);
|
||||
}
|
||||
|
||||
void core_update_device_list_access(
|
||||
@ -656,7 +657,7 @@ int target_report_luns(struct se_task *se_task)
|
||||
unsigned char *buf;
|
||||
u32 cdb_offset = 0, lun_count = 0, offset = 8, i;
|
||||
|
||||
buf = transport_kmap_first_data_page(se_cmd);
|
||||
buf = (unsigned char *) transport_kmap_data_sg(se_cmd);
|
||||
|
||||
/*
|
||||
* If no struct se_session pointer is present, this struct se_cmd is
|
||||
@ -694,7 +695,7 @@ int target_report_luns(struct se_task *se_task)
|
||||
* See SPC3 r07, page 159.
|
||||
*/
|
||||
done:
|
||||
transport_kunmap_first_data_page(se_cmd);
|
||||
transport_kunmap_data_sg(se_cmd);
|
||||
lun_count *= 8;
|
||||
buf[0] = ((lun_count >> 24) & 0xff);
|
||||
buf[1] = ((lun_count >> 16) & 0xff);
|
||||
@ -1294,24 +1295,26 @@ struct se_lun *core_dev_add_lun(
|
||||
{
|
||||
struct se_lun *lun_p;
|
||||
u32 lun_access = 0;
|
||||
int rc;
|
||||
|
||||
if (atomic_read(&dev->dev_access_obj.obj_access_count) != 0) {
|
||||
pr_err("Unable to export struct se_device while dev_access_obj: %d\n",
|
||||
atomic_read(&dev->dev_access_obj.obj_access_count));
|
||||
return NULL;
|
||||
return ERR_PTR(-EACCES);
|
||||
}
|
||||
|
||||
lun_p = core_tpg_pre_addlun(tpg, lun);
|
||||
if ((IS_ERR(lun_p)) || !lun_p)
|
||||
return NULL;
|
||||
if (IS_ERR(lun_p))
|
||||
return lun_p;
|
||||
|
||||
if (dev->dev_flags & DF_READ_ONLY)
|
||||
lun_access = TRANSPORT_LUNFLAGS_READ_ONLY;
|
||||
else
|
||||
lun_access = TRANSPORT_LUNFLAGS_READ_WRITE;
|
||||
|
||||
if (core_tpg_post_addlun(tpg, lun_p, lun_access, dev) < 0)
|
||||
return NULL;
|
||||
rc = core_tpg_post_addlun(tpg, lun_p, lun_access, dev);
|
||||
if (rc < 0)
|
||||
return ERR_PTR(rc);
|
||||
|
||||
pr_debug("%s_TPG[%u]_LUN[%u] - Activated %s Logical Unit from"
|
||||
" CORE HBA: %u\n", tpg->se_tpg_tfo->get_fabric_name(),
|
||||
@ -1348,11 +1351,10 @@ int core_dev_del_lun(
|
||||
u32 unpacked_lun)
|
||||
{
|
||||
struct se_lun *lun;
|
||||
int ret = 0;
|
||||
|
||||
lun = core_tpg_pre_dellun(tpg, unpacked_lun, &ret);
|
||||
if (!lun)
|
||||
return ret;
|
||||
lun = core_tpg_pre_dellun(tpg, unpacked_lun);
|
||||
if (IS_ERR(lun))
|
||||
return PTR_ERR(lun);
|
||||
|
||||
core_tpg_post_dellun(tpg, lun);
|
||||
|
||||
|
@ -766,9 +766,9 @@ static int target_fabric_port_link(
|
||||
|
||||
lun_p = core_dev_add_lun(se_tpg, dev->se_hba, dev,
|
||||
lun->unpacked_lun);
|
||||
if (IS_ERR(lun_p) || !lun_p) {
|
||||
if (IS_ERR(lun_p)) {
|
||||
pr_err("core_dev_add_lun() failed\n");
|
||||
ret = -EINVAL;
|
||||
ret = PTR_ERR(lun_p);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -129,7 +129,7 @@ static struct se_device *iblock_create_virtdevice(
|
||||
/*
|
||||
* These settings need to be made tunable..
|
||||
*/
|
||||
ib_dev->ibd_bio_set = bioset_create(32, 64);
|
||||
ib_dev->ibd_bio_set = bioset_create(32, 0);
|
||||
if (!ib_dev->ibd_bio_set) {
|
||||
pr_err("IBLOCK: Unable to create bioset()\n");
|
||||
return ERR_PTR(-ENOMEM);
|
||||
@ -181,7 +181,7 @@ static struct se_device *iblock_create_virtdevice(
|
||||
*/
|
||||
dev->se_sub_dev->se_dev_attrib.max_unmap_block_desc_count = 1;
|
||||
dev->se_sub_dev->se_dev_attrib.unmap_granularity =
|
||||
q->limits.discard_granularity;
|
||||
q->limits.discard_granularity >> 9;
|
||||
dev->se_sub_dev->se_dev_attrib.unmap_granularity_alignment =
|
||||
q->limits.discard_alignment;
|
||||
|
||||
@ -488,6 +488,13 @@ iblock_get_bio(struct se_task *task, sector_t lba, u32 sg_num)
|
||||
struct iblock_req *ib_req = IBLOCK_REQ(task);
|
||||
struct bio *bio;
|
||||
|
||||
/*
|
||||
* Only allocate as many vector entries as the bio code allows us to,
|
||||
* we'll loop later on until we have handled the whole request.
|
||||
*/
|
||||
if (sg_num > BIO_MAX_PAGES)
|
||||
sg_num = BIO_MAX_PAGES;
|
||||
|
||||
bio = bio_alloc_bioset(GFP_NOIO, sg_num, ib_dev->ibd_bio_set);
|
||||
if (!bio) {
|
||||
pr_err("Unable to allocate memory for bio\n");
|
||||
|
@ -90,7 +90,7 @@ void core_tpg_wait_for_nacl_pr_ref(struct se_node_acl *);
|
||||
struct se_lun *core_tpg_pre_addlun(struct se_portal_group *, u32);
|
||||
int core_tpg_post_addlun(struct se_portal_group *, struct se_lun *,
|
||||
u32, void *);
|
||||
struct se_lun *core_tpg_pre_dellun(struct se_portal_group *, u32, int *);
|
||||
struct se_lun *core_tpg_pre_dellun(struct se_portal_group *, u32 unpacked_lun);
|
||||
int core_tpg_post_dellun(struct se_portal_group *, struct se_lun *);
|
||||
|
||||
/* target_core_transport.c */
|
||||
|
@ -478,6 +478,7 @@ static int core_scsi3_pr_seq_non_holder(
|
||||
case READ_MEDIA_SERIAL_NUMBER:
|
||||
case REPORT_LUNS:
|
||||
case REQUEST_SENSE:
|
||||
case PERSISTENT_RESERVE_IN:
|
||||
ret = 0; /*/ Allowed CDBs */
|
||||
break;
|
||||
default:
|
||||
@ -1534,7 +1535,7 @@ static int core_scsi3_decode_spec_i_port(
|
||||
tidh_new->dest_local_nexus = 1;
|
||||
list_add_tail(&tidh_new->dest_list, &tid_dest_list);
|
||||
|
||||
buf = transport_kmap_first_data_page(cmd);
|
||||
buf = transport_kmap_data_sg(cmd);
|
||||
/*
|
||||
* For a PERSISTENT RESERVE OUT specify initiator ports payload,
|
||||
* first extract TransportID Parameter Data Length, and make sure
|
||||
@ -1785,7 +1786,7 @@ static int core_scsi3_decode_spec_i_port(
|
||||
|
||||
}
|
||||
|
||||
transport_kunmap_first_data_page(cmd);
|
||||
transport_kunmap_data_sg(cmd);
|
||||
|
||||
/*
|
||||
* Go ahead and create a registrations from tid_dest_list for the
|
||||
@ -1833,7 +1834,7 @@ static int core_scsi3_decode_spec_i_port(
|
||||
|
||||
return 0;
|
||||
out:
|
||||
transport_kunmap_first_data_page(cmd);
|
||||
transport_kunmap_data_sg(cmd);
|
||||
/*
|
||||
* For the failure case, release everything from tid_dest_list
|
||||
* including *dest_pr_reg and the configfs dependances..
|
||||
@ -3120,7 +3121,7 @@ static int core_scsi3_pro_preempt(
|
||||
if (!calling_it_nexus)
|
||||
core_scsi3_ua_allocate(pr_reg_nacl,
|
||||
pr_res_mapped_lun, 0x2A,
|
||||
ASCQ_2AH_RESERVATIONS_PREEMPTED);
|
||||
ASCQ_2AH_REGISTRATIONS_PREEMPTED);
|
||||
}
|
||||
spin_unlock(&pr_tmpl->registration_lock);
|
||||
/*
|
||||
@ -3233,7 +3234,7 @@ static int core_scsi3_pro_preempt(
|
||||
* additional sense code set to REGISTRATIONS PREEMPTED;
|
||||
*/
|
||||
core_scsi3_ua_allocate(pr_reg_nacl, pr_res_mapped_lun, 0x2A,
|
||||
ASCQ_2AH_RESERVATIONS_PREEMPTED);
|
||||
ASCQ_2AH_REGISTRATIONS_PREEMPTED);
|
||||
}
|
||||
spin_unlock(&pr_tmpl->registration_lock);
|
||||
/*
|
||||
@ -3410,14 +3411,14 @@ static int core_scsi3_emulate_pro_register_and_move(
|
||||
* will be moved to for the TransportID containing SCSI initiator WWN
|
||||
* information.
|
||||
*/
|
||||
buf = transport_kmap_first_data_page(cmd);
|
||||
buf = transport_kmap_data_sg(cmd);
|
||||
rtpi = (buf[18] & 0xff) << 8;
|
||||
rtpi |= buf[19] & 0xff;
|
||||
tid_len = (buf[20] & 0xff) << 24;
|
||||
tid_len |= (buf[21] & 0xff) << 16;
|
||||
tid_len |= (buf[22] & 0xff) << 8;
|
||||
tid_len |= buf[23] & 0xff;
|
||||
transport_kunmap_first_data_page(cmd);
|
||||
transport_kunmap_data_sg(cmd);
|
||||
buf = NULL;
|
||||
|
||||
if ((tid_len + 24) != cmd->data_length) {
|
||||
@ -3469,7 +3470,7 @@ static int core_scsi3_emulate_pro_register_and_move(
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
buf = transport_kmap_first_data_page(cmd);
|
||||
buf = transport_kmap_data_sg(cmd);
|
||||
proto_ident = (buf[24] & 0x0f);
|
||||
#if 0
|
||||
pr_debug("SPC-3 PR REGISTER_AND_MOVE: Extracted Protocol Identifier:"
|
||||
@ -3503,7 +3504,7 @@ static int core_scsi3_emulate_pro_register_and_move(
|
||||
goto out;
|
||||
}
|
||||
|
||||
transport_kunmap_first_data_page(cmd);
|
||||
transport_kunmap_data_sg(cmd);
|
||||
buf = NULL;
|
||||
|
||||
pr_debug("SPC-3 PR [%s] Extracted initiator %s identifier: %s"
|
||||
@ -3768,13 +3769,13 @@ static int core_scsi3_emulate_pro_register_and_move(
|
||||
" REGISTER_AND_MOVE\n");
|
||||
}
|
||||
|
||||
transport_kunmap_first_data_page(cmd);
|
||||
transport_kunmap_data_sg(cmd);
|
||||
|
||||
core_scsi3_put_pr_reg(dest_pr_reg);
|
||||
return 0;
|
||||
out:
|
||||
if (buf)
|
||||
transport_kunmap_first_data_page(cmd);
|
||||
transport_kunmap_data_sg(cmd);
|
||||
if (dest_se_deve)
|
||||
core_scsi3_lunacl_undepend_item(dest_se_deve);
|
||||
if (dest_node_acl)
|
||||
@ -3848,7 +3849,7 @@ int target_scsi3_emulate_pr_out(struct se_task *task)
|
||||
scope = (cdb[2] & 0xf0);
|
||||
type = (cdb[2] & 0x0f);
|
||||
|
||||
buf = transport_kmap_first_data_page(cmd);
|
||||
buf = transport_kmap_data_sg(cmd);
|
||||
/*
|
||||
* From PERSISTENT_RESERVE_OUT parameter list (payload)
|
||||
*/
|
||||
@ -3866,7 +3867,7 @@ int target_scsi3_emulate_pr_out(struct se_task *task)
|
||||
aptpl = (buf[17] & 0x01);
|
||||
unreg = (buf[17] & 0x02);
|
||||
}
|
||||
transport_kunmap_first_data_page(cmd);
|
||||
transport_kunmap_data_sg(cmd);
|
||||
buf = NULL;
|
||||
|
||||
/*
|
||||
@ -3966,7 +3967,7 @@ static int core_scsi3_pri_read_keys(struct se_cmd *cmd)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
buf = transport_kmap_first_data_page(cmd);
|
||||
buf = transport_kmap_data_sg(cmd);
|
||||
buf[0] = ((su_dev->t10_pr.pr_generation >> 24) & 0xff);
|
||||
buf[1] = ((su_dev->t10_pr.pr_generation >> 16) & 0xff);
|
||||
buf[2] = ((su_dev->t10_pr.pr_generation >> 8) & 0xff);
|
||||
@ -4000,7 +4001,7 @@ static int core_scsi3_pri_read_keys(struct se_cmd *cmd)
|
||||
buf[6] = ((add_len >> 8) & 0xff);
|
||||
buf[7] = (add_len & 0xff);
|
||||
|
||||
transport_kunmap_first_data_page(cmd);
|
||||
transport_kunmap_data_sg(cmd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -4026,7 +4027,7 @@ static int core_scsi3_pri_read_reservation(struct se_cmd *cmd)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
buf = transport_kmap_first_data_page(cmd);
|
||||
buf = transport_kmap_data_sg(cmd);
|
||||
buf[0] = ((su_dev->t10_pr.pr_generation >> 24) & 0xff);
|
||||
buf[1] = ((su_dev->t10_pr.pr_generation >> 16) & 0xff);
|
||||
buf[2] = ((su_dev->t10_pr.pr_generation >> 8) & 0xff);
|
||||
@ -4085,7 +4086,7 @@ static int core_scsi3_pri_read_reservation(struct se_cmd *cmd)
|
||||
|
||||
err:
|
||||
spin_unlock(&se_dev->dev_reservation_lock);
|
||||
transport_kunmap_first_data_page(cmd);
|
||||
transport_kunmap_data_sg(cmd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -4109,7 +4110,7 @@ static int core_scsi3_pri_report_capabilities(struct se_cmd *cmd)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
buf = transport_kmap_first_data_page(cmd);
|
||||
buf = transport_kmap_data_sg(cmd);
|
||||
|
||||
buf[0] = ((add_len << 8) & 0xff);
|
||||
buf[1] = (add_len & 0xff);
|
||||
@ -4141,7 +4142,7 @@ static int core_scsi3_pri_report_capabilities(struct se_cmd *cmd)
|
||||
buf[4] |= 0x02; /* PR_TYPE_WRITE_EXCLUSIVE */
|
||||
buf[5] |= 0x01; /* PR_TYPE_EXCLUSIVE_ACCESS_ALLREG */
|
||||
|
||||
transport_kunmap_first_data_page(cmd);
|
||||
transport_kunmap_data_sg(cmd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -4171,7 +4172,7 @@ static int core_scsi3_pri_read_full_status(struct se_cmd *cmd)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
buf = transport_kmap_first_data_page(cmd);
|
||||
buf = transport_kmap_data_sg(cmd);
|
||||
|
||||
buf[0] = ((su_dev->t10_pr.pr_generation >> 24) & 0xff);
|
||||
buf[1] = ((su_dev->t10_pr.pr_generation >> 16) & 0xff);
|
||||
@ -4292,7 +4293,7 @@ static int core_scsi3_pri_read_full_status(struct se_cmd *cmd)
|
||||
buf[6] = ((add_len >> 8) & 0xff);
|
||||
buf[7] = (add_len & 0xff);
|
||||
|
||||
transport_kunmap_first_data_page(cmd);
|
||||
transport_kunmap_data_sg(cmd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -693,7 +693,7 @@ static int pscsi_transport_complete(struct se_task *task)
|
||||
|
||||
if (task->task_se_cmd->se_deve->lun_flags &
|
||||
TRANSPORT_LUNFLAGS_READ_ONLY) {
|
||||
unsigned char *buf = transport_kmap_first_data_page(task->task_se_cmd);
|
||||
unsigned char *buf = transport_kmap_data_sg(task->task_se_cmd);
|
||||
|
||||
if (cdb[0] == MODE_SENSE_10) {
|
||||
if (!(buf[3] & 0x80))
|
||||
@ -703,7 +703,7 @@ static int pscsi_transport_complete(struct se_task *task)
|
||||
buf[2] |= 0x80;
|
||||
}
|
||||
|
||||
transport_kunmap_first_data_page(task->task_se_cmd);
|
||||
transport_kunmap_data_sg(task->task_se_cmd);
|
||||
}
|
||||
}
|
||||
after_mode_sense:
|
||||
|
@ -807,8 +807,7 @@ static void core_tpg_shutdown_lun(
|
||||
|
||||
struct se_lun *core_tpg_pre_dellun(
|
||||
struct se_portal_group *tpg,
|
||||
u32 unpacked_lun,
|
||||
int *ret)
|
||||
u32 unpacked_lun)
|
||||
{
|
||||
struct se_lun *lun;
|
||||
|
||||
|
@ -1255,32 +1255,34 @@ static void core_setup_task_attr_emulation(struct se_device *dev)
|
||||
static void scsi_dump_inquiry(struct se_device *dev)
|
||||
{
|
||||
struct t10_wwn *wwn = &dev->se_sub_dev->t10_wwn;
|
||||
char buf[17];
|
||||
int i, device_type;
|
||||
/*
|
||||
* Print Linux/SCSI style INQUIRY formatting to the kernel ring buffer
|
||||
*/
|
||||
pr_debug(" Vendor: ");
|
||||
for (i = 0; i < 8; i++)
|
||||
if (wwn->vendor[i] >= 0x20)
|
||||
pr_debug("%c", wwn->vendor[i]);
|
||||
buf[i] = wwn->vendor[i];
|
||||
else
|
||||
pr_debug(" ");
|
||||
buf[i] = ' ';
|
||||
buf[i] = '\0';
|
||||
pr_debug(" Vendor: %s\n", buf);
|
||||
|
||||
pr_debug(" Model: ");
|
||||
for (i = 0; i < 16; i++)
|
||||
if (wwn->model[i] >= 0x20)
|
||||
pr_debug("%c", wwn->model[i]);
|
||||
buf[i] = wwn->model[i];
|
||||
else
|
||||
pr_debug(" ");
|
||||
buf[i] = ' ';
|
||||
buf[i] = '\0';
|
||||
pr_debug(" Model: %s\n", buf);
|
||||
|
||||
pr_debug(" Revision: ");
|
||||
for (i = 0; i < 4; i++)
|
||||
if (wwn->revision[i] >= 0x20)
|
||||
pr_debug("%c", wwn->revision[i]);
|
||||
buf[i] = wwn->revision[i];
|
||||
else
|
||||
pr_debug(" ");
|
||||
|
||||
pr_debug("\n");
|
||||
buf[i] = ' ';
|
||||
buf[i] = '\0';
|
||||
pr_debug(" Revision: %s\n", buf);
|
||||
|
||||
device_type = dev->transport->get_device_type(dev);
|
||||
pr_debug(" Type: %s ", scsi_device_type(device_type));
|
||||
@ -1655,7 +1657,7 @@ EXPORT_SYMBOL(transport_handle_cdb_direct);
|
||||
* This may only be called from process context, and also currently
|
||||
* assumes internal allocation of fabric payload buffer by target-core.
|
||||
**/
|
||||
int target_submit_cmd(struct se_cmd *se_cmd, struct se_session *se_sess,
|
||||
void target_submit_cmd(struct se_cmd *se_cmd, struct se_session *se_sess,
|
||||
unsigned char *cdb, unsigned char *sense, u32 unpacked_lun,
|
||||
u32 data_length, int task_attr, int data_dir, int flags)
|
||||
{
|
||||
@ -1688,15 +1690,21 @@ int target_submit_cmd(struct se_cmd *se_cmd, struct se_session *se_sess,
|
||||
/*
|
||||
* Locate se_lun pointer and attach it to struct se_cmd
|
||||
*/
|
||||
if (transport_lookup_cmd_lun(se_cmd, unpacked_lun) < 0)
|
||||
goto out_check_cond;
|
||||
if (transport_lookup_cmd_lun(se_cmd, unpacked_lun) < 0) {
|
||||
transport_send_check_condition_and_sense(se_cmd,
|
||||
se_cmd->scsi_sense_reason, 0);
|
||||
target_put_sess_cmd(se_sess, se_cmd);
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* Sanitize CDBs via transport_generic_cmd_sequencer() and
|
||||
* allocate the necessary tasks to complete the received CDB+data
|
||||
*/
|
||||
rc = transport_generic_allocate_tasks(se_cmd, cdb);
|
||||
if (rc != 0)
|
||||
goto out_check_cond;
|
||||
if (rc != 0) {
|
||||
transport_generic_request_failure(se_cmd);
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* Dispatch se_cmd descriptor to se_lun->lun_se_dev backend
|
||||
* for immediate execution of READs, otherwise wait for
|
||||
@ -1704,12 +1712,7 @@ int target_submit_cmd(struct se_cmd *se_cmd, struct se_session *se_sess,
|
||||
* when fabric has filled the incoming buffer.
|
||||
*/
|
||||
transport_handle_cdb_direct(se_cmd);
|
||||
return 0;
|
||||
|
||||
out_check_cond:
|
||||
transport_send_check_condition_and_sense(se_cmd,
|
||||
se_cmd->scsi_sense_reason, 0);
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
EXPORT_SYMBOL(target_submit_cmd);
|
||||
|
||||
@ -2694,7 +2697,7 @@ static int transport_generic_cmd_sequencer(
|
||||
cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
|
||||
|
||||
if (target_check_write_same_discard(&cdb[10], dev) < 0)
|
||||
goto out_invalid_cdb_field;
|
||||
goto out_unsupported_cdb;
|
||||
if (!passthrough)
|
||||
cmd->execute_task = target_emulate_write_same;
|
||||
break;
|
||||
@ -2977,7 +2980,7 @@ static int transport_generic_cmd_sequencer(
|
||||
cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
|
||||
|
||||
if (target_check_write_same_discard(&cdb[1], dev) < 0)
|
||||
goto out_invalid_cdb_field;
|
||||
goto out_unsupported_cdb;
|
||||
if (!passthrough)
|
||||
cmd->execute_task = target_emulate_write_same;
|
||||
break;
|
||||
@ -3000,7 +3003,7 @@ static int transport_generic_cmd_sequencer(
|
||||
* of byte 1 bit 3 UNMAP instead of original reserved field
|
||||
*/
|
||||
if (target_check_write_same_discard(&cdb[1], dev) < 0)
|
||||
goto out_invalid_cdb_field;
|
||||
goto out_unsupported_cdb;
|
||||
if (!passthrough)
|
||||
cmd->execute_task = target_emulate_write_same;
|
||||
break;
|
||||
@ -3082,11 +3085,6 @@ static int transport_generic_cmd_sequencer(
|
||||
(cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB)))
|
||||
goto out_unsupported_cdb;
|
||||
|
||||
/* Let's limit control cdbs to a page, for simplicity's sake. */
|
||||
if ((cmd->se_cmd_flags & SCF_SCSI_CONTROL_SG_IO_CDB) &&
|
||||
size > PAGE_SIZE)
|
||||
goto out_invalid_cdb_field;
|
||||
|
||||
transport_set_supported_SAM_opcode(cmd);
|
||||
return ret;
|
||||
|
||||
@ -3490,9 +3488,11 @@ int transport_generic_map_mem_to_cmd(
|
||||
}
|
||||
EXPORT_SYMBOL(transport_generic_map_mem_to_cmd);
|
||||
|
||||
void *transport_kmap_first_data_page(struct se_cmd *cmd)
|
||||
void *transport_kmap_data_sg(struct se_cmd *cmd)
|
||||
{
|
||||
struct scatterlist *sg = cmd->t_data_sg;
|
||||
struct page **pages;
|
||||
int i;
|
||||
|
||||
BUG_ON(!sg);
|
||||
/*
|
||||
@ -3500,15 +3500,41 @@ void *transport_kmap_first_data_page(struct se_cmd *cmd)
|
||||
* tcm_loop who may be using a contig buffer from the SCSI midlayer for
|
||||
* control CDBs passed as SGLs via transport_generic_map_mem_to_cmd()
|
||||
*/
|
||||
return kmap(sg_page(sg)) + sg->offset;
|
||||
}
|
||||
EXPORT_SYMBOL(transport_kmap_first_data_page);
|
||||
if (!cmd->t_data_nents)
|
||||
return NULL;
|
||||
else if (cmd->t_data_nents == 1)
|
||||
return kmap(sg_page(sg)) + sg->offset;
|
||||
|
||||
void transport_kunmap_first_data_page(struct se_cmd *cmd)
|
||||
{
|
||||
kunmap(sg_page(cmd->t_data_sg));
|
||||
/* >1 page. use vmap */
|
||||
pages = kmalloc(sizeof(*pages) * cmd->t_data_nents, GFP_KERNEL);
|
||||
if (!pages)
|
||||
return NULL;
|
||||
|
||||
/* convert sg[] to pages[] */
|
||||
for_each_sg(cmd->t_data_sg, sg, cmd->t_data_nents, i) {
|
||||
pages[i] = sg_page(sg);
|
||||
}
|
||||
|
||||
cmd->t_data_vmap = vmap(pages, cmd->t_data_nents, VM_MAP, PAGE_KERNEL);
|
||||
kfree(pages);
|
||||
if (!cmd->t_data_vmap)
|
||||
return NULL;
|
||||
|
||||
return cmd->t_data_vmap + cmd->t_data_sg[0].offset;
|
||||
}
|
||||
EXPORT_SYMBOL(transport_kunmap_first_data_page);
|
||||
EXPORT_SYMBOL(transport_kmap_data_sg);
|
||||
|
||||
void transport_kunmap_data_sg(struct se_cmd *cmd)
|
||||
{
|
||||
if (!cmd->t_data_nents)
|
||||
return;
|
||||
else if (cmd->t_data_nents == 1)
|
||||
kunmap(sg_page(cmd->t_data_sg));
|
||||
|
||||
vunmap(cmd->t_data_vmap);
|
||||
cmd->t_data_vmap = NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(transport_kunmap_data_sg);
|
||||
|
||||
static int
|
||||
transport_generic_get_mem(struct se_cmd *cmd)
|
||||
@ -3516,6 +3542,7 @@ transport_generic_get_mem(struct se_cmd *cmd)
|
||||
u32 length = cmd->data_length;
|
||||
unsigned int nents;
|
||||
struct page *page;
|
||||
gfp_t zero_flag;
|
||||
int i = 0;
|
||||
|
||||
nents = DIV_ROUND_UP(length, PAGE_SIZE);
|
||||
@ -3526,9 +3553,11 @@ transport_generic_get_mem(struct se_cmd *cmd)
|
||||
cmd->t_data_nents = nents;
|
||||
sg_init_table(cmd->t_data_sg, nents);
|
||||
|
||||
zero_flag = cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB ? 0 : __GFP_ZERO;
|
||||
|
||||
while (length) {
|
||||
u32 page_len = min_t(u32, length, PAGE_SIZE);
|
||||
page = alloc_page(GFP_KERNEL | __GFP_ZERO);
|
||||
page = alloc_page(GFP_KERNEL | zero_flag);
|
||||
if (!page)
|
||||
goto out;
|
||||
|
||||
@ -3756,6 +3785,11 @@ transport_allocate_control_task(struct se_cmd *cmd)
|
||||
struct se_task *task;
|
||||
unsigned long flags;
|
||||
|
||||
/* Workaround for handling zero-length control CDBs */
|
||||
if ((cmd->se_cmd_flags & SCF_SCSI_CONTROL_SG_IO_CDB) &&
|
||||
!cmd->data_length)
|
||||
return 0;
|
||||
|
||||
task = transport_generic_get_task(cmd, cmd->data_direction);
|
||||
if (!task)
|
||||
return -ENOMEM;
|
||||
@ -3827,6 +3861,14 @@ int transport_generic_new_cmd(struct se_cmd *cmd)
|
||||
else if (!task_cdbs && (cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB)) {
|
||||
cmd->t_state = TRANSPORT_COMPLETE;
|
||||
atomic_set(&cmd->t_transport_active, 1);
|
||||
|
||||
if (cmd->t_task_cdb[0] == REQUEST_SENSE) {
|
||||
u8 ua_asc = 0, ua_ascq = 0;
|
||||
|
||||
core_scsi3_ua_clear_for_request_sense(cmd,
|
||||
&ua_asc, &ua_ascq);
|
||||
}
|
||||
|
||||
INIT_WORK(&cmd->work, target_complete_ok_work);
|
||||
queue_work(target_completion_wq, &cmd->work);
|
||||
return 0;
|
||||
@ -4448,8 +4490,8 @@ int transport_send_check_condition_and_sense(
|
||||
/* CURRENT ERROR */
|
||||
buffer[offset] = 0x70;
|
||||
buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
|
||||
/* ABORTED COMMAND */
|
||||
buffer[offset+SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND;
|
||||
/* ILLEGAL REQUEST */
|
||||
buffer[offset+SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
|
||||
/* INVALID FIELD IN CDB */
|
||||
buffer[offset+SPC_ASC_KEY_OFFSET] = 0x24;
|
||||
break;
|
||||
@ -4457,8 +4499,8 @@ int transport_send_check_condition_and_sense(
|
||||
/* CURRENT ERROR */
|
||||
buffer[offset] = 0x70;
|
||||
buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
|
||||
/* ABORTED COMMAND */
|
||||
buffer[offset+SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND;
|
||||
/* ILLEGAL REQUEST */
|
||||
buffer[offset+SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
|
||||
/* INVALID FIELD IN PARAMETER LIST */
|
||||
buffer[offset+SPC_ASC_KEY_OFFSET] = 0x26;
|
||||
break;
|
||||
|
@ -540,7 +540,6 @@ static void ft_send_work(struct work_struct *work)
|
||||
int data_dir = 0;
|
||||
u32 data_len;
|
||||
int task_attr;
|
||||
int ret;
|
||||
|
||||
fcp = fc_frame_payload_get(cmd->req_frame, sizeof(*fcp));
|
||||
if (!fcp)
|
||||
@ -603,14 +602,10 @@ static void ft_send_work(struct work_struct *work)
|
||||
* Use a single se_cmd->cmd_kref as we expect to release se_cmd
|
||||
* directly from ft_check_stop_free callback in response path.
|
||||
*/
|
||||
ret = target_submit_cmd(&cmd->se_cmd, cmd->sess->se_sess, cmd->cdb,
|
||||
target_submit_cmd(&cmd->se_cmd, cmd->sess->se_sess, cmd->cdb,
|
||||
&cmd->ft_sense_buffer[0], cmd->lun, data_len,
|
||||
task_attr, data_dir, 0);
|
||||
pr_debug("r_ctl %x alloc target_submit_cmd %d\n", fh->fh_r_ctl, ret);
|
||||
if (ret < 0) {
|
||||
ft_dump_cmd(cmd, __func__);
|
||||
return;
|
||||
}
|
||||
pr_debug("r_ctl %x alloc target_submit_cmd\n", fh->fh_r_ctl);
|
||||
return;
|
||||
|
||||
err:
|
||||
|
@ -59,7 +59,7 @@ int transport_set_vpd_ident_type(struct t10_vpd *, unsigned char *);
|
||||
int transport_set_vpd_ident(struct t10_vpd *, unsigned char *);
|
||||
|
||||
/* core helpers also used by command snooping in pscsi */
|
||||
void *transport_kmap_first_data_page(struct se_cmd *);
|
||||
void transport_kunmap_first_data_page(struct se_cmd *);
|
||||
void *transport_kmap_data_sg(struct se_cmd *);
|
||||
void transport_kunmap_data_sg(struct se_cmd *);
|
||||
|
||||
#endif /* TARGET_CORE_BACKEND_H */
|
||||
|
@ -582,6 +582,7 @@ struct se_cmd {
|
||||
|
||||
struct scatterlist *t_data_sg;
|
||||
unsigned int t_data_nents;
|
||||
void *t_data_vmap;
|
||||
struct scatterlist *t_bidi_data_sg;
|
||||
unsigned int t_bidi_data_nents;
|
||||
|
||||
|
@ -114,7 +114,7 @@ void transport_init_se_cmd(struct se_cmd *, struct target_core_fabric_ops *,
|
||||
struct se_session *, u32, int, int, unsigned char *);
|
||||
int transport_lookup_cmd_lun(struct se_cmd *, u32);
|
||||
int transport_generic_allocate_tasks(struct se_cmd *, unsigned char *);
|
||||
int target_submit_cmd(struct se_cmd *, struct se_session *, unsigned char *,
|
||||
void target_submit_cmd(struct se_cmd *, struct se_session *, unsigned char *,
|
||||
unsigned char *, u32, u32, int, int, int);
|
||||
int transport_handle_cdb_direct(struct se_cmd *);
|
||||
int transport_generic_handle_cdb_map(struct se_cmd *);
|
||||
|
Loading…
Reference in New Issue
Block a user