Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending
Pull SCSI target updates from Nicholas Bellinger: "Here are the outstanding target-pending updates for v4.3-rc1. Mostly bug-fixes and minor changes this round. The fallout from the big v4.2-rc1 RCU conversion have (thus far) been minimal. The highlights this round include: - Move sense handling routines into scsi_common code (Sagi) - Return ABORTED_COMMAND sense key for PI errors (Sagi) - Add tpg_enabled_sendtargets attribute for disabled iscsi-target discovery (David) - Shrink target struct se_cmd by rearranging fields (Roland) - Drop iSCSI use of mutex around max_cmd_sn increment (Roland) - Replace iSCSI __kernel_sockaddr_storage with sockaddr_storage (Andy + Chris) - Honor fabric max_data_sg_nents I/O transfer limit (Arun + Himanshu + nab) - Fix EXTENDED_COPY >= v4.1 regression OOPsen (Alex + nab)" * 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending: (37 commits) target: use stringify.h instead of own definition target/user: Fix UFLAG_UNKNOWN_OP handling target: Remove no-op conditional target/user: Remove unused variable target: Fix max_cmd_sn increment w/o cmdsn mutex regressions target: Attach EXTENDED_COPY local I/O descriptors to xcopy_pt_sess target/qla2xxx: Honor max_data_sg_nents I/O transfer limit target/iscsi: Replace __kernel_sockaddr_storage with sockaddr_storage target/iscsi: Replace conn->login_ip with login_sockaddr target/iscsi: Keep local_ip as the actual sockaddr target/iscsi: Fix np_ip bracket issue by removing np_ip target: Drop iSCSI use of mutex around max_cmd_sn increment qla2xxx: Update tcm_qla2xxx module description to 24xx+ iscsi-target: Add tpg_enabled_sendtargets for disabled discovery drivers: target: Drop unlikely before IS_ERR(_OR_NULL) target: check DPO/FUA usage for COMPARE AND WRITE target: Shrink struct se_cmd by rearranging fields target: Remove cmd->se_ordered_id (unused except debug log lines) target: add support for START_STOP_UNIT SCSI opcode target: improve unsupported opcode message ...
This commit is contained in:
commit
05c78081d2
@ -3095,7 +3095,7 @@ out:
|
||||
|
||||
static int
|
||||
isert_setup_np(struct iscsi_np *np,
|
||||
struct __kernel_sockaddr_storage *ksockaddr)
|
||||
struct sockaddr_storage *ksockaddr)
|
||||
{
|
||||
struct isert_np *isert_np;
|
||||
struct rdma_cm_id *isert_lid;
|
||||
@ -3117,7 +3117,7 @@ isert_setup_np(struct iscsi_np *np,
|
||||
* in iscsi_target_configfs.c code..
|
||||
*/
|
||||
memcpy(&np->np_sockaddr, ksockaddr,
|
||||
sizeof(struct __kernel_sockaddr_storage));
|
||||
sizeof(struct sockaddr_storage));
|
||||
|
||||
isert_lid = isert_setup_id(isert_np);
|
||||
if (IS_ERR(isert_lid)) {
|
||||
@ -3199,32 +3199,11 @@ isert_set_conn_info(struct iscsi_np *np, struct iscsi_conn *conn,
|
||||
{
|
||||
struct rdma_cm_id *cm_id = isert_conn->cm_id;
|
||||
struct rdma_route *cm_route = &cm_id->route;
|
||||
struct sockaddr_in *sock_in;
|
||||
struct sockaddr_in6 *sock_in6;
|
||||
|
||||
conn->login_family = np->np_sockaddr.ss_family;
|
||||
|
||||
if (np->np_sockaddr.ss_family == AF_INET6) {
|
||||
sock_in6 = (struct sockaddr_in6 *)&cm_route->addr.dst_addr;
|
||||
snprintf(conn->login_ip, sizeof(conn->login_ip), "%pI6c",
|
||||
&sock_in6->sin6_addr.in6_u);
|
||||
conn->login_port = ntohs(sock_in6->sin6_port);
|
||||
|
||||
sock_in6 = (struct sockaddr_in6 *)&cm_route->addr.src_addr;
|
||||
snprintf(conn->local_ip, sizeof(conn->local_ip), "%pI6c",
|
||||
&sock_in6->sin6_addr.in6_u);
|
||||
conn->local_port = ntohs(sock_in6->sin6_port);
|
||||
} else {
|
||||
sock_in = (struct sockaddr_in *)&cm_route->addr.dst_addr;
|
||||
sprintf(conn->login_ip, "%pI4",
|
||||
&sock_in->sin_addr.s_addr);
|
||||
conn->login_port = ntohs(sock_in->sin_port);
|
||||
|
||||
sock_in = (struct sockaddr_in *)&cm_route->addr.src_addr;
|
||||
sprintf(conn->local_ip, "%pI4",
|
||||
&sock_in->sin_addr.s_addr);
|
||||
conn->local_port = ntohs(sock_in->sin_port);
|
||||
}
|
||||
conn->login_sockaddr = cm_route->addr.dst_addr;
|
||||
conn->local_sockaddr = cm_route->addr.src_addr;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -853,12 +853,9 @@ static void iscsi_scsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
|
||||
SAM_STAT_CHECK_CONDITION;
|
||||
scsi_build_sense_buffer(1, sc->sense_buffer,
|
||||
ILLEGAL_REQUEST, 0x10, ascq);
|
||||
sc->sense_buffer[7] = 0xc; /* Additional sense length */
|
||||
sc->sense_buffer[8] = 0; /* Information desc type */
|
||||
sc->sense_buffer[9] = 0xa; /* Additional desc length */
|
||||
sc->sense_buffer[10] = 0x80; /* Validity bit */
|
||||
|
||||
put_unaligned_be64(sector, &sc->sense_buffer[12]);
|
||||
scsi_set_sense_information(sc->sense_buffer,
|
||||
SCSI_SENSE_BUFFERSIZE,
|
||||
sector);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
@ -32,10 +32,10 @@ config SCSI_QLA_FC
|
||||
They are also included in the linux-firmware tree as well.
|
||||
|
||||
config TCM_QLA2XXX
|
||||
tristate "TCM_QLA2XXX fabric module for Qlogic 2xxx series target mode HBAs"
|
||||
tristate "TCM_QLA2XXX fabric module for QLogic 24xx+ series target mode HBAs"
|
||||
depends on SCSI_QLA_FC && TARGET_CORE
|
||||
depends on LIBFC
|
||||
select BTREE
|
||||
default n
|
||||
---help---
|
||||
Say Y here to enable the TCM_QLA2XXX fabric module for Qlogic 2xxx series target mode HBAs
|
||||
Say Y here to enable the TCM_QLA2XXX fabric module for QLogic 24xx+ series target mode HBAs
|
||||
|
@ -1359,9 +1359,7 @@ static void tcm_qla2xxx_free_session(struct qla_tgt_sess *sess)
|
||||
struct qla_hw_data *ha = tgt->ha;
|
||||
scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
|
||||
struct se_session *se_sess;
|
||||
struct se_node_acl *se_nacl;
|
||||
struct tcm_qla2xxx_lport *lport;
|
||||
struct tcm_qla2xxx_nacl *nacl;
|
||||
|
||||
BUG_ON(in_interrupt());
|
||||
|
||||
@ -1371,8 +1369,6 @@ static void tcm_qla2xxx_free_session(struct qla_tgt_sess *sess)
|
||||
dump_stack();
|
||||
return;
|
||||
}
|
||||
se_nacl = se_sess->se_node_acl;
|
||||
nacl = container_of(se_nacl, struct tcm_qla2xxx_nacl, se_node_acl);
|
||||
|
||||
lport = vha->vha_tgt.target_lport_ptr;
|
||||
if (!lport) {
|
||||
@ -1680,7 +1676,6 @@ static int tcm_qla2xxx_lport_register_npiv_cb(struct scsi_qla_host *base_vha,
|
||||
(struct tcm_qla2xxx_lport *)target_lport_ptr;
|
||||
struct tcm_qla2xxx_lport *base_lport =
|
||||
(struct tcm_qla2xxx_lport *)base_vha->vha_tgt.target_lport_ptr;
|
||||
struct tcm_qla2xxx_tpg *base_tpg;
|
||||
struct fc_vport_identifiers vport_id;
|
||||
|
||||
if (!qla_tgt_mode_enabled(base_vha)) {
|
||||
@ -1693,7 +1688,6 @@ static int tcm_qla2xxx_lport_register_npiv_cb(struct scsi_qla_host *base_vha,
|
||||
pr_err("qla2xxx base_lport or tpg_1 not available\n");
|
||||
return -EPERM;
|
||||
}
|
||||
base_tpg = base_lport->tpg_1;
|
||||
|
||||
memset(&vport_id, 0, sizeof(vport_id));
|
||||
vport_id.port_name = npiv_wwpn;
|
||||
@ -1810,6 +1804,11 @@ static const struct target_core_fabric_ops tcm_qla2xxx_ops = {
|
||||
.module = THIS_MODULE,
|
||||
.name = "qla2xxx",
|
||||
.node_acl_size = sizeof(struct tcm_qla2xxx_nacl),
|
||||
/*
|
||||
* XXX: Limit assumes single page per scatter-gather-list entry.
|
||||
* Current maximum is ~4.9 MB per se_cmd->t_data_sg with PAGE_SIZE=4096
|
||||
*/
|
||||
.max_data_sg_nents = 1200,
|
||||
.get_fabric_name = tcm_qla2xxx_get_fabric_name,
|
||||
.tpg_get_wwn = tcm_qla2xxx_get_fabric_wwn,
|
||||
.tpg_get_tag = tcm_qla2xxx_get_tag,
|
||||
@ -1958,7 +1957,7 @@ static void __exit tcm_qla2xxx_exit(void)
|
||||
tcm_qla2xxx_deregister_configfs();
|
||||
}
|
||||
|
||||
MODULE_DESCRIPTION("TCM QLA2XXX series NPIV enabled fabric driver");
|
||||
MODULE_DESCRIPTION("TCM QLA24XX+ series NPIV enabled fabric driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
module_init(tcm_qla2xxx_init);
|
||||
module_exit(tcm_qla2xxx_exit);
|
||||
|
@ -5,6 +5,8 @@
|
||||
#include <linux/bug.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/errno.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include <scsi/scsi_common.h>
|
||||
|
||||
/* NB: These are exposed through /proc/scsi/scsi and form part of the ABI.
|
||||
@ -176,3 +178,110 @@ bool scsi_normalize_sense(const u8 *sense_buffer, int sb_len,
|
||||
return true;
|
||||
}
|
||||
EXPORT_SYMBOL(scsi_normalize_sense);
|
||||
|
||||
/**
|
||||
* scsi_sense_desc_find - search for a given descriptor type in descriptor sense data format.
|
||||
* @sense_buffer: byte array of descriptor format sense data
|
||||
* @sb_len: number of valid bytes in sense_buffer
|
||||
* @desc_type: value of descriptor type to find
|
||||
* (e.g. 0 -> information)
|
||||
*
|
||||
* Notes:
|
||||
* only valid when sense data is in descriptor format
|
||||
*
|
||||
* Return value:
|
||||
* pointer to start of (first) descriptor if found else NULL
|
||||
*/
|
||||
const u8 * scsi_sense_desc_find(const u8 * sense_buffer, int sb_len,
|
||||
int desc_type)
|
||||
{
|
||||
int add_sen_len, add_len, desc_len, k;
|
||||
const u8 * descp;
|
||||
|
||||
if ((sb_len < 8) || (0 == (add_sen_len = sense_buffer[7])))
|
||||
return NULL;
|
||||
if ((sense_buffer[0] < 0x72) || (sense_buffer[0] > 0x73))
|
||||
return NULL;
|
||||
add_sen_len = (add_sen_len < (sb_len - 8)) ?
|
||||
add_sen_len : (sb_len - 8);
|
||||
descp = &sense_buffer[8];
|
||||
for (desc_len = 0, k = 0; k < add_sen_len; k += desc_len) {
|
||||
descp += desc_len;
|
||||
add_len = (k < (add_sen_len - 1)) ? descp[1]: -1;
|
||||
desc_len = add_len + 2;
|
||||
if (descp[0] == desc_type)
|
||||
return descp;
|
||||
if (add_len < 0) // short descriptor ??
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(scsi_sense_desc_find);
|
||||
|
||||
/**
|
||||
* scsi_build_sense_buffer - build sense data in a buffer
|
||||
* @desc: Sense format (non zero == descriptor format,
|
||||
* 0 == fixed format)
|
||||
* @buf: Where to build sense data
|
||||
* @key: Sense key
|
||||
* @asc: Additional sense code
|
||||
* @ascq: Additional sense code qualifier
|
||||
*
|
||||
**/
|
||||
void scsi_build_sense_buffer(int desc, u8 *buf, u8 key, u8 asc, u8 ascq)
|
||||
{
|
||||
if (desc) {
|
||||
buf[0] = 0x72; /* descriptor, current */
|
||||
buf[1] = key;
|
||||
buf[2] = asc;
|
||||
buf[3] = ascq;
|
||||
buf[7] = 0;
|
||||
} else {
|
||||
buf[0] = 0x70; /* fixed, current */
|
||||
buf[2] = key;
|
||||
buf[7] = 0xa;
|
||||
buf[12] = asc;
|
||||
buf[13] = ascq;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(scsi_build_sense_buffer);
|
||||
|
||||
/**
|
||||
* scsi_set_sense_information - set the information field in a
|
||||
* formatted sense data buffer
|
||||
* @buf: Where to build sense data
|
||||
* @buf_len: buffer length
|
||||
* @info: 64-bit information value to be set
|
||||
*
|
||||
* Return value:
|
||||
* 0 on success or EINVAL for invalid sense buffer length
|
||||
**/
|
||||
int scsi_set_sense_information(u8 *buf, int buf_len, u64 info)
|
||||
{
|
||||
if ((buf[0] & 0x7f) == 0x72) {
|
||||
u8 *ucp, len;
|
||||
|
||||
len = buf[7];
|
||||
ucp = (char *)scsi_sense_desc_find(buf, len + 8, 0);
|
||||
if (!ucp) {
|
||||
buf[7] = len + 0xc;
|
||||
ucp = buf + 8 + len;
|
||||
}
|
||||
|
||||
if (buf_len < len + 0xc)
|
||||
/* Not enough room for info */
|
||||
return -EINVAL;
|
||||
|
||||
ucp[0] = 0;
|
||||
ucp[1] = 0xa;
|
||||
ucp[2] = 0x80; /* Valid bit */
|
||||
ucp[3] = 0;
|
||||
put_unaligned_be64(info, &ucp[4]);
|
||||
} else if ((buf[0] & 0x7f) == 0x70) {
|
||||
buf[0] |= 0x80;
|
||||
put_unaligned_be64(info, &buf[3]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(scsi_set_sense_information);
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include <scsi/scsi_device.h>
|
||||
#include <scsi/scsi_driver.h>
|
||||
#include <scsi/scsi_eh.h>
|
||||
#include <scsi/scsi_common.h>
|
||||
#include <scsi/scsi_transport.h>
|
||||
#include <scsi/scsi_host.h>
|
||||
#include <scsi/scsi_ioctl.h>
|
||||
@ -2424,45 +2425,6 @@ bool scsi_command_normalize_sense(const struct scsi_cmnd *cmd,
|
||||
}
|
||||
EXPORT_SYMBOL(scsi_command_normalize_sense);
|
||||
|
||||
/**
|
||||
* scsi_sense_desc_find - search for a given descriptor type in descriptor sense data format.
|
||||
* @sense_buffer: byte array of descriptor format sense data
|
||||
* @sb_len: number of valid bytes in sense_buffer
|
||||
* @desc_type: value of descriptor type to find
|
||||
* (e.g. 0 -> information)
|
||||
*
|
||||
* Notes:
|
||||
* only valid when sense data is in descriptor format
|
||||
*
|
||||
* Return value:
|
||||
* pointer to start of (first) descriptor if found else NULL
|
||||
*/
|
||||
const u8 * scsi_sense_desc_find(const u8 * sense_buffer, int sb_len,
|
||||
int desc_type)
|
||||
{
|
||||
int add_sen_len, add_len, desc_len, k;
|
||||
const u8 * descp;
|
||||
|
||||
if ((sb_len < 8) || (0 == (add_sen_len = sense_buffer[7])))
|
||||
return NULL;
|
||||
if ((sense_buffer[0] < 0x72) || (sense_buffer[0] > 0x73))
|
||||
return NULL;
|
||||
add_sen_len = (add_sen_len < (sb_len - 8)) ?
|
||||
add_sen_len : (sb_len - 8);
|
||||
descp = &sense_buffer[8];
|
||||
for (desc_len = 0, k = 0; k < add_sen_len; k += desc_len) {
|
||||
descp += desc_len;
|
||||
add_len = (k < (add_sen_len - 1)) ? descp[1]: -1;
|
||||
desc_len = add_len + 2;
|
||||
if (descp[0] == desc_type)
|
||||
return descp;
|
||||
if (add_len < 0) // short descriptor ??
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(scsi_sense_desc_find);
|
||||
|
||||
/**
|
||||
* scsi_get_sense_info_fld - get information field from sense data (either fixed or descriptor format)
|
||||
* @sense_buffer: byte array of sense data
|
||||
@ -2512,31 +2474,3 @@ int scsi_get_sense_info_fld(const u8 * sense_buffer, int sb_len,
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(scsi_get_sense_info_fld);
|
||||
|
||||
/**
|
||||
* scsi_build_sense_buffer - build sense data in a buffer
|
||||
* @desc: Sense format (non zero == descriptor format,
|
||||
* 0 == fixed format)
|
||||
* @buf: Where to build sense data
|
||||
* @key: Sense key
|
||||
* @asc: Additional sense code
|
||||
* @ascq: Additional sense code qualifier
|
||||
*
|
||||
**/
|
||||
void scsi_build_sense_buffer(int desc, u8 *buf, u8 key, u8 asc, u8 ascq)
|
||||
{
|
||||
if (desc) {
|
||||
buf[0] = 0x72; /* descriptor, current */
|
||||
buf[1] = key;
|
||||
buf[2] = asc;
|
||||
buf[3] = ascq;
|
||||
buf[7] = 0;
|
||||
} else {
|
||||
buf[0] = 0x70; /* fixed, current */
|
||||
buf[2] = key;
|
||||
buf[7] = 0xa;
|
||||
buf[12] = asc;
|
||||
buf[13] = ascq;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(scsi_build_sense_buffer);
|
||||
|
@ -269,14 +269,14 @@ int iscsit_deaccess_np(struct iscsi_np *np, struct iscsi_portal_group *tpg,
|
||||
}
|
||||
|
||||
bool iscsit_check_np_match(
|
||||
struct __kernel_sockaddr_storage *sockaddr,
|
||||
struct sockaddr_storage *sockaddr,
|
||||
struct iscsi_np *np,
|
||||
int network_transport)
|
||||
{
|
||||
struct sockaddr_in *sock_in, *sock_in_e;
|
||||
struct sockaddr_in6 *sock_in6, *sock_in6_e;
|
||||
bool ip_match = false;
|
||||
u16 port;
|
||||
u16 port, port_e;
|
||||
|
||||
if (sockaddr->ss_family == AF_INET6) {
|
||||
sock_in6 = (struct sockaddr_in6 *)sockaddr;
|
||||
@ -288,6 +288,7 @@ bool iscsit_check_np_match(
|
||||
ip_match = true;
|
||||
|
||||
port = ntohs(sock_in6->sin6_port);
|
||||
port_e = ntohs(sock_in6_e->sin6_port);
|
||||
} else {
|
||||
sock_in = (struct sockaddr_in *)sockaddr;
|
||||
sock_in_e = (struct sockaddr_in *)&np->np_sockaddr;
|
||||
@ -296,9 +297,10 @@ bool iscsit_check_np_match(
|
||||
ip_match = true;
|
||||
|
||||
port = ntohs(sock_in->sin_port);
|
||||
port_e = ntohs(sock_in_e->sin_port);
|
||||
}
|
||||
|
||||
if (ip_match && (np->np_port == port) &&
|
||||
if (ip_match && (port_e == port) &&
|
||||
(np->np_network_transport == network_transport))
|
||||
return true;
|
||||
|
||||
@ -309,7 +311,7 @@ bool iscsit_check_np_match(
|
||||
* Called with mutex np_lock held
|
||||
*/
|
||||
static struct iscsi_np *iscsit_get_np(
|
||||
struct __kernel_sockaddr_storage *sockaddr,
|
||||
struct sockaddr_storage *sockaddr,
|
||||
int network_transport)
|
||||
{
|
||||
struct iscsi_np *np;
|
||||
@ -340,12 +342,9 @@ static struct iscsi_np *iscsit_get_np(
|
||||
}
|
||||
|
||||
struct iscsi_np *iscsit_add_np(
|
||||
struct __kernel_sockaddr_storage *sockaddr,
|
||||
char *ip_str,
|
||||
struct sockaddr_storage *sockaddr,
|
||||
int network_transport)
|
||||
{
|
||||
struct sockaddr_in *sock_in;
|
||||
struct sockaddr_in6 *sock_in6;
|
||||
struct iscsi_np *np;
|
||||
int ret;
|
||||
|
||||
@ -368,16 +367,6 @@ struct iscsi_np *iscsit_add_np(
|
||||
}
|
||||
|
||||
np->np_flags |= NPF_IP_NETWORK;
|
||||
if (sockaddr->ss_family == AF_INET6) {
|
||||
sock_in6 = (struct sockaddr_in6 *)sockaddr;
|
||||
snprintf(np->np_ip, IPV6_ADDRESS_SPACE, "%s", ip_str);
|
||||
np->np_port = ntohs(sock_in6->sin6_port);
|
||||
} else {
|
||||
sock_in = (struct sockaddr_in *)sockaddr;
|
||||
sprintf(np->np_ip, "%s", ip_str);
|
||||
np->np_port = ntohs(sock_in->sin_port);
|
||||
}
|
||||
|
||||
np->np_network_transport = network_transport;
|
||||
spin_lock_init(&np->np_thread_lock);
|
||||
init_completion(&np->np_restart_comp);
|
||||
@ -411,8 +400,8 @@ struct iscsi_np *iscsit_add_np(
|
||||
list_add_tail(&np->np_list, &g_np_list);
|
||||
mutex_unlock(&np_lock);
|
||||
|
||||
pr_debug("CORE[0] - Added Network Portal: %s:%hu on %s\n",
|
||||
np->np_ip, np->np_port, np->np_transport->name);
|
||||
pr_debug("CORE[0] - Added Network Portal: %pISpc on %s\n",
|
||||
&np->np_sockaddr, np->np_transport->name);
|
||||
|
||||
return np;
|
||||
}
|
||||
@ -481,8 +470,8 @@ int iscsit_del_np(struct iscsi_np *np)
|
||||
list_del(&np->np_list);
|
||||
mutex_unlock(&np_lock);
|
||||
|
||||
pr_debug("CORE[0] - Removed Network Portal: %s:%hu on %s\n",
|
||||
np->np_ip, np->np_port, np->np_transport->name);
|
||||
pr_debug("CORE[0] - Removed Network Portal: %pISpc on %s\n",
|
||||
&np->np_sockaddr, np->np_transport->name);
|
||||
|
||||
iscsit_put_transport(np->np_transport);
|
||||
kfree(np);
|
||||
@ -1209,7 +1198,6 @@ static u32 iscsit_do_crypto_hash_sg(
|
||||
u8 *pad_bytes)
|
||||
{
|
||||
u32 data_crc;
|
||||
u32 i;
|
||||
struct scatterlist *sg;
|
||||
unsigned int page_off;
|
||||
|
||||
@ -1218,15 +1206,15 @@ static u32 iscsit_do_crypto_hash_sg(
|
||||
sg = cmd->first_data_sg;
|
||||
page_off = cmd->first_data_sg_off;
|
||||
|
||||
i = 0;
|
||||
while (data_length) {
|
||||
u32 cur_len = min_t(u32, data_length, (sg[i].length - page_off));
|
||||
u32 cur_len = min_t(u32, data_length, (sg->length - page_off));
|
||||
|
||||
crypto_hash_update(hash, &sg[i], cur_len);
|
||||
crypto_hash_update(hash, sg, cur_len);
|
||||
|
||||
data_length -= cur_len;
|
||||
page_off = 0;
|
||||
i++;
|
||||
/* iscsit_map_iovec has already checked for invalid sg pointers */
|
||||
sg = sg_next(sg);
|
||||
}
|
||||
|
||||
if (padding) {
|
||||
@ -2556,7 +2544,7 @@ static int iscsit_send_conn_drop_async_message(
|
||||
cmd->stat_sn = conn->stat_sn++;
|
||||
hdr->statsn = cpu_to_be32(cmd->stat_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((u32) atomic_read(&conn->sess->max_cmd_sn));
|
||||
hdr->async_event = ISCSI_ASYNC_MSG_DROPPING_CONNECTION;
|
||||
hdr->param1 = cpu_to_be16(cmd->logout_cid);
|
||||
hdr->param2 = cpu_to_be16(conn->sess->sess_ops->DefaultTime2Wait);
|
||||
@ -2628,7 +2616,7 @@ iscsit_build_datain_pdu(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
|
||||
hdr->statsn = cpu_to_be32(0xFFFFFFFF);
|
||||
|
||||
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((u32) atomic_read(&conn->sess->max_cmd_sn));
|
||||
hdr->datasn = cpu_to_be32(datain->data_sn);
|
||||
hdr->offset = cpu_to_be32(datain->offset);
|
||||
|
||||
@ -2839,7 +2827,7 @@ iscsit_build_logout_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
|
||||
|
||||
iscsit_increment_maxcmdsn(cmd, conn->sess);
|
||||
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((u32) atomic_read(&conn->sess->max_cmd_sn));
|
||||
|
||||
pr_debug("Built Logout Response ITT: 0x%08x StatSN:"
|
||||
" 0x%08x Response: 0x%02x CID: %hu on CID: %hu\n",
|
||||
@ -2902,7 +2890,7 @@ iscsit_build_nopin_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
|
||||
iscsit_increment_maxcmdsn(cmd, conn->sess);
|
||||
|
||||
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((u32) atomic_read(&conn->sess->max_cmd_sn));
|
||||
|
||||
pr_debug("Built NOPIN %s Response ITT: 0x%08x, TTT: 0x%08x,"
|
||||
" StatSN: 0x%08x, Length %u\n", (nopout_response) ?
|
||||
@ -3049,7 +3037,7 @@ static int iscsit_send_r2t(
|
||||
hdr->ttt = cpu_to_be32(r2t->targ_xfer_tag);
|
||||
hdr->statsn = cpu_to_be32(conn->stat_sn);
|
||||
hdr->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_sn);
|
||||
hdr->max_cmdsn = cpu_to_be32(conn->sess->max_cmd_sn);
|
||||
hdr->max_cmdsn = cpu_to_be32((u32) atomic_read(&conn->sess->max_cmd_sn));
|
||||
hdr->r2tsn = cpu_to_be32(r2t->r2t_sn);
|
||||
hdr->data_offset = cpu_to_be32(r2t->offset);
|
||||
hdr->data_length = cpu_to_be32(r2t->xfer_len);
|
||||
@ -3202,7 +3190,7 @@ void iscsit_build_rsp_pdu(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
|
||||
|
||||
iscsit_increment_maxcmdsn(cmd, conn->sess);
|
||||
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((u32) atomic_read(&conn->sess->max_cmd_sn));
|
||||
|
||||
pr_debug("Built SCSI Response, ITT: 0x%08x, StatSN: 0x%08x,"
|
||||
" Response: 0x%02x, SAM Status: 0x%02x, CID: %hu\n",
|
||||
@ -3321,7 +3309,7 @@ iscsit_build_task_mgt_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
|
||||
|
||||
iscsit_increment_maxcmdsn(cmd, conn->sess);
|
||||
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((u32) atomic_read(&conn->sess->max_cmd_sn));
|
||||
|
||||
pr_debug("Built Task Management Response ITT: 0x%08x,"
|
||||
" StatSN: 0x%08x, Response: 0x%02x, CID: %hu\n",
|
||||
@ -3399,6 +3387,7 @@ iscsit_build_sendtargets_response(struct iscsi_cmd *cmd,
|
||||
int target_name_printed;
|
||||
unsigned char buf[ISCSI_IQN_LEN+12]; /* iqn + "TargetName=" + \0 */
|
||||
unsigned char *text_in = cmd->text_in_ptr, *text_ptr = NULL;
|
||||
bool active;
|
||||
|
||||
buffer_len = min(conn->conn_ops->MaxRecvDataSegmentLength,
|
||||
SENDTARGETS_BUF_LIMIT);
|
||||
@ -3452,19 +3441,18 @@ iscsit_build_sendtargets_response(struct iscsi_cmd *cmd,
|
||||
}
|
||||
|
||||
spin_lock(&tpg->tpg_state_lock);
|
||||
if ((tpg->tpg_state == TPG_STATE_FREE) ||
|
||||
(tpg->tpg_state == TPG_STATE_INACTIVE)) {
|
||||
spin_unlock(&tpg->tpg_state_lock);
|
||||
continue;
|
||||
}
|
||||
active = (tpg->tpg_state == TPG_STATE_ACTIVE);
|
||||
spin_unlock(&tpg->tpg_state_lock);
|
||||
|
||||
if (!active && tpg->tpg_attrib.tpg_enabled_sendtargets)
|
||||
continue;
|
||||
|
||||
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);
|
||||
char *fmt_str;
|
||||
struct sockaddr_storage *sockaddr;
|
||||
|
||||
if (np->np_network_transport != network_transport)
|
||||
continue;
|
||||
@ -3492,15 +3480,15 @@ iscsit_build_sendtargets_response(struct iscsi_cmd *cmd,
|
||||
}
|
||||
}
|
||||
|
||||
if (np->np_sockaddr.ss_family == AF_INET6)
|
||||
fmt_str = "TargetAddress=[%s]:%hu,%hu";
|
||||
if (inaddr_any)
|
||||
sockaddr = &conn->local_sockaddr;
|
||||
else
|
||||
fmt_str = "TargetAddress=%s:%hu,%hu";
|
||||
sockaddr = &np->np_sockaddr;
|
||||
|
||||
len = sprintf(buf, fmt_str,
|
||||
inaddr_any ? conn->local_ip : np->np_ip,
|
||||
np->np_port,
|
||||
tpg->tpgt);
|
||||
len = sprintf(buf, "TargetAddress="
|
||||
"%pISpc,%hu",
|
||||
sockaddr,
|
||||
tpg->tpgt);
|
||||
len += 1;
|
||||
|
||||
if ((len + payload_len) > buffer_len) {
|
||||
@ -3576,7 +3564,7 @@ iscsit_build_text_rsp(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
|
||||
*/
|
||||
cmd->maxcmdsn_inc = 0;
|
||||
hdr->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_sn);
|
||||
hdr->max_cmdsn = cpu_to_be32(conn->sess->max_cmd_sn);
|
||||
hdr->max_cmdsn = cpu_to_be32((u32) atomic_read(&conn->sess->max_cmd_sn));
|
||||
|
||||
pr_debug("Built Text Response: ITT: 0x%08x, TTT: 0x%08x, StatSN: 0x%08x,"
|
||||
" Length: %u, CID: %hu F: %d C: %d\n", cmd->init_task_tag,
|
||||
@ -3654,7 +3642,7 @@ iscsit_build_reject(struct iscsi_cmd *cmd, struct iscsi_conn *conn,
|
||||
cmd->stat_sn = conn->stat_sn++;
|
||||
hdr->statsn = cpu_to_be32(cmd->stat_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((u32) atomic_read(&conn->sess->max_cmd_sn));
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL(iscsit_build_reject);
|
||||
|
@ -10,10 +10,10 @@ extern int iscsit_access_np(struct iscsi_np *, struct iscsi_portal_group *);
|
||||
extern void iscsit_login_kref_put(struct kref *);
|
||||
extern int iscsit_deaccess_np(struct iscsi_np *, struct iscsi_portal_group *,
|
||||
struct iscsi_tpg_np *);
|
||||
extern bool iscsit_check_np_match(struct __kernel_sockaddr_storage *,
|
||||
extern bool iscsit_check_np_match(struct sockaddr_storage *,
|
||||
struct iscsi_np *, int);
|
||||
extern struct iscsi_np *iscsit_add_np(struct __kernel_sockaddr_storage *,
|
||||
char *, int);
|
||||
extern struct iscsi_np *iscsit_add_np(struct sockaddr_storage *,
|
||||
int);
|
||||
extern int iscsit_reset_np_thread(struct iscsi_np *, struct iscsi_tpg_np *,
|
||||
struct iscsi_portal_group *, bool);
|
||||
extern int iscsit_del_np(struct iscsi_np *);
|
||||
|
@ -99,7 +99,7 @@ static ssize_t lio_target_np_store_sctp(
|
||||
* Use existing np->np_sockaddr for SCTP network portal reference
|
||||
*/
|
||||
tpg_np_sctp = iscsit_tpg_add_network_portal(tpg, &np->np_sockaddr,
|
||||
np->np_ip, tpg_np, ISCSI_SCTP_TCP);
|
||||
tpg_np, ISCSI_SCTP_TCP);
|
||||
if (!tpg_np_sctp || IS_ERR(tpg_np_sctp))
|
||||
goto out;
|
||||
} else {
|
||||
@ -177,7 +177,7 @@ static ssize_t lio_target_np_store_iser(
|
||||
}
|
||||
|
||||
tpg_np_iser = iscsit_tpg_add_network_portal(tpg, &np->np_sockaddr,
|
||||
np->np_ip, tpg_np, ISCSI_INFINIBAND);
|
||||
tpg_np, ISCSI_INFINIBAND);
|
||||
if (IS_ERR(tpg_np_iser)) {
|
||||
rc = PTR_ERR(tpg_np_iser);
|
||||
goto out;
|
||||
@ -220,7 +220,7 @@ static struct se_tpg_np *lio_target_call_addnptotpg(
|
||||
struct iscsi_portal_group *tpg;
|
||||
struct iscsi_tpg_np *tpg_np;
|
||||
char *str, *str2, *ip_str, *port_str;
|
||||
struct __kernel_sockaddr_storage sockaddr;
|
||||
struct sockaddr_storage sockaddr;
|
||||
struct sockaddr_in *sock_in;
|
||||
struct sockaddr_in6 *sock_in6;
|
||||
unsigned long port;
|
||||
@ -235,7 +235,7 @@ static struct se_tpg_np *lio_target_call_addnptotpg(
|
||||
memset(buf, 0, MAX_PORTAL_LEN + 1);
|
||||
snprintf(buf, MAX_PORTAL_LEN + 1, "%s", name);
|
||||
|
||||
memset(&sockaddr, 0, sizeof(struct __kernel_sockaddr_storage));
|
||||
memset(&sockaddr, 0, sizeof(struct sockaddr_storage));
|
||||
|
||||
str = strstr(buf, "[");
|
||||
if (str) {
|
||||
@ -248,8 +248,8 @@ static struct se_tpg_np *lio_target_call_addnptotpg(
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
str++; /* Skip over leading "[" */
|
||||
*str2 = '\0'; /* Terminate the IPv6 address */
|
||||
str2++; /* Skip over the "]" */
|
||||
*str2 = '\0'; /* Terminate the unbracketed IPv6 address */
|
||||
str2++; /* Skip over the \0 */
|
||||
port_str = strstr(str2, ":");
|
||||
if (!port_str) {
|
||||
pr_err("Unable to locate \":port\""
|
||||
@ -267,7 +267,7 @@ static struct se_tpg_np *lio_target_call_addnptotpg(
|
||||
sock_in6 = (struct sockaddr_in6 *)&sockaddr;
|
||||
sock_in6->sin6_family = AF_INET6;
|
||||
sock_in6->sin6_port = htons((unsigned short)port);
|
||||
ret = in6_pton(str, IPV6_ADDRESS_SPACE,
|
||||
ret = in6_pton(str, -1,
|
||||
(void *)&sock_in6->sin6_addr.in6_u, -1, &end);
|
||||
if (ret <= 0) {
|
||||
pr_err("in6_pton returned: %d\n", ret);
|
||||
@ -316,7 +316,7 @@ static struct se_tpg_np *lio_target_call_addnptotpg(
|
||||
* sys/kernel/config/iscsi/$IQN/$TPG/np/$IP:$PORT/
|
||||
*
|
||||
*/
|
||||
tpg_np = iscsit_tpg_add_network_portal(tpg, &sockaddr, str, NULL,
|
||||
tpg_np = iscsit_tpg_add_network_portal(tpg, &sockaddr, NULL,
|
||||
ISCSI_TCP);
|
||||
if (IS_ERR(tpg_np)) {
|
||||
iscsit_put_tpg(tpg);
|
||||
@ -344,8 +344,8 @@ static void lio_target_call_delnpfromtpg(
|
||||
|
||||
se_tpg = &tpg->tpg_se_tpg;
|
||||
pr_debug("LIO_Target_ConfigFS: DEREGISTER -> %s TPGT: %hu"
|
||||
" PORTAL: %s:%hu\n", config_item_name(&se_tpg->se_tpg_wwn->wwn_group.cg_item),
|
||||
tpg->tpgt, tpg_np->tpg_np->np_ip, tpg_np->tpg_np->np_port);
|
||||
" PORTAL: %pISpc\n", config_item_name(&se_tpg->se_tpg_wwn->wwn_group.cg_item),
|
||||
tpg->tpgt, &tpg_np->tpg_np->np_sockaddr);
|
||||
|
||||
ret = iscsit_tpg_del_network_portal(tpg, tpg_np);
|
||||
if (ret < 0)
|
||||
@ -656,6 +656,7 @@ static ssize_t lio_target_nacl_show_info(
|
||||
struct iscsi_conn *conn;
|
||||
struct se_session *se_sess;
|
||||
ssize_t rb = 0;
|
||||
u32 max_cmd_sn;
|
||||
|
||||
spin_lock_bh(&se_nacl->nacl_sess_lock);
|
||||
se_sess = se_nacl->nacl_sess;
|
||||
@ -703,11 +704,12 @@ static ssize_t lio_target_nacl_show_info(
|
||||
" Values]-----------------------\n");
|
||||
rb += sprintf(page+rb, " CmdSN/WR : CmdSN/WC : ExpCmdSN"
|
||||
" : MaxCmdSN : ITT : TTT\n");
|
||||
max_cmd_sn = (u32) atomic_read(&sess->max_cmd_sn);
|
||||
rb += sprintf(page+rb, " 0x%08x 0x%08x 0x%08x 0x%08x"
|
||||
" 0x%08x 0x%08x\n",
|
||||
sess->cmdsn_window,
|
||||
(sess->max_cmd_sn - sess->exp_cmd_sn) + 1,
|
||||
sess->exp_cmd_sn, sess->max_cmd_sn,
|
||||
(max_cmd_sn - sess->exp_cmd_sn) + 1,
|
||||
sess->exp_cmd_sn, max_cmd_sn,
|
||||
sess->init_task_tag, sess->targ_xfer_tag);
|
||||
rb += sprintf(page+rb, "----------------------[iSCSI"
|
||||
" Connections]-------------------------\n");
|
||||
@ -751,7 +753,7 @@ static ssize_t lio_target_nacl_show_info(
|
||||
break;
|
||||
}
|
||||
|
||||
rb += sprintf(page+rb, " Address %s %s", conn->login_ip,
|
||||
rb += sprintf(page+rb, " Address %pISc %s", &conn->login_sockaddr,
|
||||
(conn->network_transport == ISCSI_TCP) ?
|
||||
"TCP" : "SCTP");
|
||||
rb += sprintf(page+rb, " StatSN: 0x%08x\n",
|
||||
@ -1010,6 +1012,11 @@ TPG_ATTR(t10_pi, S_IRUGO | S_IWUSR);
|
||||
*/
|
||||
DEF_TPG_ATTRIB(fabric_prot_type);
|
||||
TPG_ATTR(fabric_prot_type, S_IRUGO | S_IWUSR);
|
||||
/*
|
||||
* Define iscsi_tpg_attrib_s_tpg_enabled_sendtargets
|
||||
*/
|
||||
DEF_TPG_ATTRIB(tpg_enabled_sendtargets);
|
||||
TPG_ATTR(tpg_enabled_sendtargets, S_IRUGO | S_IWUSR);
|
||||
|
||||
static struct configfs_attribute *lio_target_tpg_attrib_attrs[] = {
|
||||
&iscsi_tpg_attrib_authentication.attr,
|
||||
@ -1024,6 +1031,7 @@ static struct configfs_attribute *lio_target_tpg_attrib_attrs[] = {
|
||||
&iscsi_tpg_attrib_default_erl.attr,
|
||||
&iscsi_tpg_attrib_t10_pi.attr,
|
||||
&iscsi_tpg_attrib_fabric_prot_type.attr,
|
||||
&iscsi_tpg_attrib_tpg_enabled_sendtargets.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
@ -47,19 +47,19 @@ void iscsit_determine_maxcmdsn(struct iscsi_session *sess)
|
||||
* core_set_queue_depth_for_node().
|
||||
*/
|
||||
sess->cmdsn_window = se_nacl->queue_depth;
|
||||
sess->max_cmd_sn = (sess->max_cmd_sn + se_nacl->queue_depth) - 1;
|
||||
atomic_add(se_nacl->queue_depth - 1, &sess->max_cmd_sn);
|
||||
}
|
||||
|
||||
void iscsit_increment_maxcmdsn(struct iscsi_cmd *cmd, struct iscsi_session *sess)
|
||||
{
|
||||
u32 max_cmd_sn;
|
||||
|
||||
if (cmd->immediate_cmd || cmd->maxcmdsn_inc)
|
||||
return;
|
||||
|
||||
cmd->maxcmdsn_inc = 1;
|
||||
|
||||
mutex_lock(&sess->cmdsn_mutex);
|
||||
sess->max_cmd_sn += 1;
|
||||
pr_debug("Updated MaxCmdSN to 0x%08x\n", sess->max_cmd_sn);
|
||||
mutex_unlock(&sess->cmdsn_mutex);
|
||||
max_cmd_sn = atomic_inc_return(&sess->max_cmd_sn);
|
||||
pr_debug("Updated MaxCmdSN to 0x%08x\n", max_cmd_sn);
|
||||
}
|
||||
EXPORT_SYMBOL(iscsit_increment_maxcmdsn);
|
||||
|
@ -331,7 +331,7 @@ static int iscsi_login_zero_tsih_s1(
|
||||
* The FFP CmdSN window values will be allocated from the TPG's
|
||||
* Initiator Node's ACL once the login has been successfully completed.
|
||||
*/
|
||||
sess->max_cmd_sn = be32_to_cpu(pdu->cmdsn);
|
||||
atomic_set(&sess->max_cmd_sn, be32_to_cpu(pdu->cmdsn));
|
||||
|
||||
sess->sess_ops = kzalloc(sizeof(struct iscsi_sess_ops), GFP_KERNEL);
|
||||
if (!sess->sess_ops) {
|
||||
@ -729,9 +729,9 @@ void iscsi_post_login_handler(
|
||||
stop_timer = 1;
|
||||
}
|
||||
|
||||
pr_debug("iSCSI Login successful on CID: %hu from %s to"
|
||||
" %s:%hu,%hu\n", conn->cid, conn->login_ip,
|
||||
conn->local_ip, conn->local_port, tpg->tpgt);
|
||||
pr_debug("iSCSI Login successful on CID: %hu from %pISpc to"
|
||||
" %pISpc,%hu\n", conn->cid, &conn->login_sockaddr,
|
||||
&conn->local_sockaddr, tpg->tpgt);
|
||||
|
||||
list_add_tail(&conn->conn_list, &sess->sess_conn_list);
|
||||
atomic_inc(&sess->nconn);
|
||||
@ -776,8 +776,8 @@ void iscsi_post_login_handler(
|
||||
pr_debug("Moving to TARG_SESS_STATE_LOGGED_IN.\n");
|
||||
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, conn->local_ip, conn->local_port,
|
||||
pr_debug("iSCSI Login successful on CID: %hu from %pISpc to %pISpc,%hu\n",
|
||||
conn->cid, &conn->login_sockaddr, &conn->local_sockaddr,
|
||||
tpg->tpgt);
|
||||
|
||||
spin_lock_bh(&sess->conn_lock);
|
||||
@ -823,8 +823,8 @@ static void iscsi_handle_login_thread_timeout(unsigned long data)
|
||||
struct iscsi_np *np = (struct iscsi_np *) data;
|
||||
|
||||
spin_lock_bh(&np->np_thread_lock);
|
||||
pr_err("iSCSI Login timeout on Network Portal %s:%hu\n",
|
||||
np->np_ip, np->np_port);
|
||||
pr_err("iSCSI Login timeout on Network Portal %pISpc\n",
|
||||
&np->np_sockaddr);
|
||||
|
||||
if (np->np_login_timer_flags & ISCSI_TF_STOP) {
|
||||
spin_unlock_bh(&np->np_thread_lock);
|
||||
@ -877,7 +877,7 @@ static void iscsi_stop_login_thread_timer(struct iscsi_np *np)
|
||||
|
||||
int iscsit_setup_np(
|
||||
struct iscsi_np *np,
|
||||
struct __kernel_sockaddr_storage *sockaddr)
|
||||
struct sockaddr_storage *sockaddr)
|
||||
{
|
||||
struct socket *sock = NULL;
|
||||
int backlog = ISCSIT_TCP_BACKLOG, ret, opt = 0, len;
|
||||
@ -916,7 +916,7 @@ int iscsit_setup_np(
|
||||
* in iscsi_target_configfs.c code..
|
||||
*/
|
||||
memcpy(&np->np_sockaddr, sockaddr,
|
||||
sizeof(struct __kernel_sockaddr_storage));
|
||||
sizeof(struct sockaddr_storage));
|
||||
|
||||
if (sockaddr->ss_family == AF_INET6)
|
||||
len = sizeof(struct sockaddr_in6);
|
||||
@ -975,7 +975,7 @@ fail:
|
||||
|
||||
int iscsi_target_setup_login_socket(
|
||||
struct iscsi_np *np,
|
||||
struct __kernel_sockaddr_storage *sockaddr)
|
||||
struct sockaddr_storage *sockaddr)
|
||||
{
|
||||
struct iscsit_transport *t;
|
||||
int rc;
|
||||
@ -1015,44 +1015,42 @@ int iscsit_accept_np(struct iscsi_np *np, struct iscsi_conn *conn)
|
||||
rc = conn->sock->ops->getname(conn->sock,
|
||||
(struct sockaddr *)&sock_in6, &err, 1);
|
||||
if (!rc) {
|
||||
if (!ipv6_addr_v4mapped(&sock_in6.sin6_addr))
|
||||
snprintf(conn->login_ip, sizeof(conn->login_ip), "[%pI6c]",
|
||||
&sock_in6.sin6_addr.in6_u);
|
||||
else
|
||||
snprintf(conn->login_ip, sizeof(conn->login_ip), "%pI4",
|
||||
&sock_in6.sin6_addr.s6_addr32[3]);
|
||||
conn->login_port = ntohs(sock_in6.sin6_port);
|
||||
if (!ipv6_addr_v4mapped(&sock_in6.sin6_addr)) {
|
||||
memcpy(&conn->login_sockaddr, &sock_in6, sizeof(sock_in6));
|
||||
} else {
|
||||
/* Pretend to be an ipv4 socket */
|
||||
sock_in.sin_family = AF_INET;
|
||||
sock_in.sin_port = sock_in6.sin6_port;
|
||||
memcpy(&sock_in.sin_addr, &sock_in6.sin6_addr.s6_addr32[3], 4);
|
||||
memcpy(&conn->login_sockaddr, &sock_in, sizeof(sock_in));
|
||||
}
|
||||
}
|
||||
|
||||
rc = conn->sock->ops->getname(conn->sock,
|
||||
(struct sockaddr *)&sock_in6, &err, 0);
|
||||
if (!rc) {
|
||||
if (!ipv6_addr_v4mapped(&sock_in6.sin6_addr))
|
||||
snprintf(conn->local_ip, sizeof(conn->local_ip), "[%pI6c]",
|
||||
&sock_in6.sin6_addr.in6_u);
|
||||
else
|
||||
snprintf(conn->local_ip, sizeof(conn->local_ip), "%pI4",
|
||||
&sock_in6.sin6_addr.s6_addr32[3]);
|
||||
conn->local_port = ntohs(sock_in6.sin6_port);
|
||||
if (!ipv6_addr_v4mapped(&sock_in6.sin6_addr)) {
|
||||
memcpy(&conn->local_sockaddr, &sock_in6, sizeof(sock_in6));
|
||||
} else {
|
||||
/* Pretend to be an ipv4 socket */
|
||||
sock_in.sin_family = AF_INET;
|
||||
sock_in.sin_port = sock_in6.sin6_port;
|
||||
memcpy(&sock_in.sin_addr, &sock_in6.sin6_addr.s6_addr32[3], 4);
|
||||
memcpy(&conn->local_sockaddr, &sock_in, sizeof(sock_in));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
memset(&sock_in, 0, sizeof(struct sockaddr_in));
|
||||
|
||||
rc = conn->sock->ops->getname(conn->sock,
|
||||
(struct sockaddr *)&sock_in, &err, 1);
|
||||
if (!rc) {
|
||||
sprintf(conn->login_ip, "%pI4",
|
||||
&sock_in.sin_addr.s_addr);
|
||||
conn->login_port = ntohs(sock_in.sin_port);
|
||||
}
|
||||
if (!rc)
|
||||
memcpy(&conn->login_sockaddr, &sock_in, sizeof(sock_in));
|
||||
|
||||
rc = conn->sock->ops->getname(conn->sock,
|
||||
(struct sockaddr *)&sock_in, &err, 0);
|
||||
if (!rc) {
|
||||
sprintf(conn->local_ip, "%pI4",
|
||||
&sock_in.sin_addr.s_addr);
|
||||
conn->local_port = ntohs(sock_in.sin_port);
|
||||
}
|
||||
if (!rc)
|
||||
memcpy(&conn->local_sockaddr, &sock_in, sizeof(sock_in));
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -1302,8 +1300,8 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
|
||||
spin_lock_bh(&np->np_thread_lock);
|
||||
if (np->np_thread_state != ISCSI_NP_THREAD_ACTIVE) {
|
||||
spin_unlock_bh(&np->np_thread_lock);
|
||||
pr_err("iSCSI Network Portal on %s:%hu currently not"
|
||||
" active.\n", np->np_ip, np->np_port);
|
||||
pr_err("iSCSI Network Portal on %pISpc currently not"
|
||||
" active.\n", &np->np_sockaddr);
|
||||
iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
|
||||
ISCSI_LOGIN_STATUS_SVC_UNAVAILABLE);
|
||||
goto new_sess_out;
|
||||
@ -1312,9 +1310,9 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
|
||||
|
||||
conn->network_transport = np->np_network_transport;
|
||||
|
||||
pr_debug("Received iSCSI login request from %s on %s Network"
|
||||
" Portal %s:%hu\n", conn->login_ip, np->np_transport->name,
|
||||
conn->local_ip, conn->local_port);
|
||||
pr_debug("Received iSCSI login request from %pISpc on %s Network"
|
||||
" Portal %pISpc\n", &conn->login_sockaddr, np->np_transport->name,
|
||||
&conn->local_sockaddr);
|
||||
|
||||
pr_debug("Moving to TARG_CONN_STATE_IN_LOGIN.\n");
|
||||
conn->conn_state = TARG_CONN_STATE_IN_LOGIN;
|
||||
|
@ -5,9 +5,9 @@ extern int iscsi_login_setup_crypto(struct iscsi_conn *);
|
||||
extern int iscsi_check_for_session_reinstatement(struct iscsi_conn *);
|
||||
extern int iscsi_login_post_auth_non_zero_tsih(struct iscsi_conn *, u16, u32);
|
||||
extern int iscsit_setup_np(struct iscsi_np *,
|
||||
struct __kernel_sockaddr_storage *);
|
||||
struct sockaddr_storage *);
|
||||
extern int iscsi_target_setup_login_socket(struct iscsi_np *,
|
||||
struct __kernel_sockaddr_storage *);
|
||||
struct sockaddr_storage *);
|
||||
extern int iscsit_accept_np(struct iscsi_np *, struct iscsi_conn *);
|
||||
extern int iscsit_get_login_rx(struct iscsi_conn *, struct iscsi_login *);
|
||||
extern int iscsit_put_login_tx(struct iscsi_conn *, struct iscsi_login *, u32);
|
||||
|
@ -341,7 +341,6 @@ static int iscsi_target_check_first_request(
|
||||
static int iscsi_target_do_tx_login_io(struct iscsi_conn *conn, struct iscsi_login *login)
|
||||
{
|
||||
u32 padding = 0;
|
||||
struct iscsi_session *sess = conn->sess;
|
||||
struct iscsi_login_rsp *login_rsp;
|
||||
|
||||
login_rsp = (struct iscsi_login_rsp *) login->rsp;
|
||||
@ -353,7 +352,7 @@ static int iscsi_target_do_tx_login_io(struct iscsi_conn *conn, struct iscsi_log
|
||||
login_rsp->itt = login->init_task_tag;
|
||||
login_rsp->statsn = cpu_to_be32(conn->stat_sn++);
|
||||
login_rsp->exp_cmdsn = cpu_to_be32(conn->sess->exp_cmd_sn);
|
||||
login_rsp->max_cmdsn = cpu_to_be32(conn->sess->max_cmd_sn);
|
||||
login_rsp->max_cmdsn = cpu_to_be32((u32) atomic_read(&conn->sess->max_cmd_sn));
|
||||
|
||||
pr_debug("Sending Login Response, Flags: 0x%02x, ITT: 0x%08x,"
|
||||
" ExpCmdSN; 0x%08x, MaxCmdSN: 0x%08x, StatSN: 0x%08x, Length:"
|
||||
@ -382,10 +381,6 @@ static int iscsi_target_do_tx_login_io(struct iscsi_conn *conn, struct iscsi_log
|
||||
goto err;
|
||||
|
||||
login->rsp_length = 0;
|
||||
mutex_lock(&sess->cmdsn_mutex);
|
||||
login_rsp->exp_cmdsn = cpu_to_be32(sess->exp_cmd_sn);
|
||||
login_rsp->max_cmdsn = cpu_to_be32(sess->max_cmd_sn);
|
||||
mutex_unlock(&sess->cmdsn_mutex);
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -430,7 +430,7 @@ static ssize_t iscsi_stat_tgt_attr_show_attr_fail_intr_addr(
|
||||
int ret;
|
||||
|
||||
spin_lock(&lstat->lock);
|
||||
ret = snprintf(page, PAGE_SIZE, "%s\n", lstat->last_intr_fail_ip_addr);
|
||||
ret = snprintf(page, PAGE_SIZE, "%pISc\n", &lstat->last_intr_fail_sockaddr);
|
||||
spin_unlock(&lstat->lock);
|
||||
|
||||
return ret;
|
||||
|
@ -50,7 +50,7 @@ u8 iscsit_tmr_abort_task(
|
||||
pr_err("Unable to locate RefTaskTag: 0x%08x on CID:"
|
||||
" %hu.\n", hdr->rtt, conn->cid);
|
||||
return (iscsi_sna_gte(be32_to_cpu(hdr->refcmdsn), conn->sess->exp_cmd_sn) &&
|
||||
iscsi_sna_lte(be32_to_cpu(hdr->refcmdsn), conn->sess->max_cmd_sn)) ?
|
||||
iscsi_sna_lte(be32_to_cpu(hdr->refcmdsn), (u32) atomic_read(&conn->sess->max_cmd_sn))) ?
|
||||
ISCSI_TMF_RSP_COMPLETE : ISCSI_TMF_RSP_NO_TASK;
|
||||
}
|
||||
if (ref_cmd->cmd_sn != be32_to_cpu(hdr->refcmdsn)) {
|
||||
|
@ -226,6 +226,7 @@ static void iscsit_set_default_tpg_attribs(struct iscsi_portal_group *tpg)
|
||||
a->default_erl = TA_DEFAULT_ERL;
|
||||
a->t10_pi = TA_DEFAULT_T10_PI;
|
||||
a->fabric_prot_type = TA_DEFAULT_FABRIC_PROT_TYPE;
|
||||
a->tpg_enabled_sendtargets = TA_DEFAULT_TPG_ENABLED_SENDTARGETS;
|
||||
}
|
||||
|
||||
int iscsit_tpg_add_portal_group(struct iscsi_tiqn *tiqn, struct iscsi_portal_group *tpg)
|
||||
@ -430,7 +431,7 @@ struct iscsi_tpg_np *iscsit_tpg_locate_child_np(
|
||||
|
||||
static bool iscsit_tpg_check_network_portal(
|
||||
struct iscsi_tiqn *tiqn,
|
||||
struct __kernel_sockaddr_storage *sockaddr,
|
||||
struct sockaddr_storage *sockaddr,
|
||||
int network_transport)
|
||||
{
|
||||
struct iscsi_portal_group *tpg;
|
||||
@ -459,8 +460,7 @@ static bool iscsit_tpg_check_network_portal(
|
||||
|
||||
struct iscsi_tpg_np *iscsit_tpg_add_network_portal(
|
||||
struct iscsi_portal_group *tpg,
|
||||
struct __kernel_sockaddr_storage *sockaddr,
|
||||
char *ip_str,
|
||||
struct sockaddr_storage *sockaddr,
|
||||
struct iscsi_tpg_np *tpg_np_parent,
|
||||
int network_transport)
|
||||
{
|
||||
@ -470,8 +470,8 @@ struct iscsi_tpg_np *iscsit_tpg_add_network_portal(
|
||||
if (!tpg_np_parent) {
|
||||
if (iscsit_tpg_check_network_portal(tpg->tpg_tiqn, sockaddr,
|
||||
network_transport)) {
|
||||
pr_err("Network Portal: %s already exists on a"
|
||||
" different TPG on %s\n", ip_str,
|
||||
pr_err("Network Portal: %pISc already exists on a"
|
||||
" different TPG on %s\n", sockaddr,
|
||||
tpg->tpg_tiqn->tiqn);
|
||||
return ERR_PTR(-EEXIST);
|
||||
}
|
||||
@ -484,7 +484,7 @@ struct iscsi_tpg_np *iscsit_tpg_add_network_portal(
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
np = iscsit_add_np(sockaddr, ip_str, network_transport);
|
||||
np = iscsit_add_np(sockaddr, network_transport);
|
||||
if (IS_ERR(np)) {
|
||||
kfree(tpg_np);
|
||||
return ERR_CAST(np);
|
||||
@ -514,8 +514,8 @@ struct iscsi_tpg_np *iscsit_tpg_add_network_portal(
|
||||
spin_unlock(&tpg_np_parent->tpg_np_parent_lock);
|
||||
}
|
||||
|
||||
pr_debug("CORE[%s] - Added Network Portal: %s:%hu,%hu on %s\n",
|
||||
tpg->tpg_tiqn->tiqn, np->np_ip, np->np_port, tpg->tpgt,
|
||||
pr_debug("CORE[%s] - Added Network Portal: %pISpc,%hu on %s\n",
|
||||
tpg->tpg_tiqn->tiqn, &np->np_sockaddr, tpg->tpgt,
|
||||
np->np_transport->name);
|
||||
|
||||
return tpg_np;
|
||||
@ -528,8 +528,8 @@ static int iscsit_tpg_release_np(
|
||||
{
|
||||
iscsit_clear_tpg_np_login_thread(tpg_np, tpg, true);
|
||||
|
||||
pr_debug("CORE[%s] - Removed Network Portal: %s:%hu,%hu on %s\n",
|
||||
tpg->tpg_tiqn->tiqn, np->np_ip, np->np_port, tpg->tpgt,
|
||||
pr_debug("CORE[%s] - Removed Network Portal: %pISpc,%hu on %s\n",
|
||||
tpg->tpg_tiqn->tiqn, &np->np_sockaddr, tpg->tpgt,
|
||||
np->np_transport->name);
|
||||
|
||||
tpg_np->tpg_np = NULL;
|
||||
@ -892,3 +892,21 @@ int iscsit_ta_fabric_prot_type(
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int iscsit_ta_tpg_enabled_sendtargets(
|
||||
struct iscsi_portal_group *tpg,
|
||||
u32 flag)
|
||||
{
|
||||
struct iscsi_tpg_attrib *a = &tpg->tpg_attrib;
|
||||
|
||||
if ((flag != 0) && (flag != 1)) {
|
||||
pr_err("Illegal value %d\n", flag);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
a->tpg_enabled_sendtargets = flag;
|
||||
pr_debug("iSCSI_TPG[%hu] - TPG enabled bit required for SendTargets:"
|
||||
" %s\n", tpg->tpgt, (a->tpg_enabled_sendtargets) ? "ON" : "OFF");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ extern struct iscsi_node_attrib *iscsit_tpg_get_node_attrib(struct iscsi_session
|
||||
extern void iscsit_tpg_del_external_nps(struct iscsi_tpg_np *);
|
||||
extern struct iscsi_tpg_np *iscsit_tpg_locate_child_np(struct iscsi_tpg_np *, int);
|
||||
extern struct iscsi_tpg_np *iscsit_tpg_add_network_portal(struct iscsi_portal_group *,
|
||||
struct __kernel_sockaddr_storage *, char *, struct iscsi_tpg_np *,
|
||||
struct sockaddr_storage *, struct iscsi_tpg_np *,
|
||||
int);
|
||||
extern int iscsit_tpg_del_network_portal(struct iscsi_portal_group *,
|
||||
struct iscsi_tpg_np *);
|
||||
@ -40,5 +40,6 @@ extern int iscsit_ta_demo_mode_discovery(struct iscsi_portal_group *, u32);
|
||||
extern int iscsit_ta_default_erl(struct iscsi_portal_group *, u32);
|
||||
extern int iscsit_ta_t10_pi(struct iscsi_portal_group *, u32);
|
||||
extern int iscsit_ta_fabric_prot_type(struct iscsi_portal_group *, u32);
|
||||
extern int iscsit_ta_tpg_enabled_sendtargets(struct iscsi_portal_group *, u32);
|
||||
|
||||
#endif /* ISCSI_TARGET_TPG_H */
|
||||
|
@ -233,6 +233,7 @@ struct iscsi_r2t *iscsit_get_holder_for_r2tsn(
|
||||
|
||||
static inline int iscsit_check_received_cmdsn(struct iscsi_session *sess, u32 cmdsn)
|
||||
{
|
||||
u32 max_cmdsn;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
@ -241,10 +242,10 @@ static inline int iscsit_check_received_cmdsn(struct iscsi_session *sess, u32 cm
|
||||
* or order CmdSNs due to multiple connection sessions and/or
|
||||
* CRC failures.
|
||||
*/
|
||||
if (iscsi_sna_gt(cmdsn, sess->max_cmd_sn)) {
|
||||
max_cmdsn = atomic_read(&sess->max_cmd_sn);
|
||||
if (iscsi_sna_gt(cmdsn, max_cmdsn)) {
|
||||
pr_err("Received CmdSN: 0x%08x is greater than"
|
||||
" MaxCmdSN: 0x%08x, ignoring.\n", cmdsn,
|
||||
sess->max_cmd_sn);
|
||||
" MaxCmdSN: 0x%08x, ignoring.\n", cmdsn, max_cmdsn);
|
||||
ret = CMDSN_MAXCMDSN_OVERRUN;
|
||||
|
||||
} else if (cmdsn == sess->exp_cmd_sn) {
|
||||
@ -1371,6 +1372,33 @@ int tx_data(
|
||||
return iscsit_do_tx_data(conn, &c);
|
||||
}
|
||||
|
||||
static bool sockaddr_equal(struct sockaddr_storage *x, struct sockaddr_storage *y)
|
||||
{
|
||||
switch (x->ss_family) {
|
||||
case AF_INET: {
|
||||
struct sockaddr_in *sinx = (struct sockaddr_in *)x;
|
||||
struct sockaddr_in *siny = (struct sockaddr_in *)y;
|
||||
if (sinx->sin_addr.s_addr != siny->sin_addr.s_addr)
|
||||
return false;
|
||||
if (sinx->sin_port != siny->sin_port)
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case AF_INET6: {
|
||||
struct sockaddr_in6 *sinx = (struct sockaddr_in6 *)x;
|
||||
struct sockaddr_in6 *siny = (struct sockaddr_in6 *)y;
|
||||
if (!ipv6_addr_equal(&sinx->sin6_addr, &siny->sin6_addr))
|
||||
return false;
|
||||
if (sinx->sin6_port != siny->sin6_port)
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void iscsit_collect_login_stats(
|
||||
struct iscsi_conn *conn,
|
||||
u8 status_class,
|
||||
@ -1387,7 +1415,7 @@ void iscsit_collect_login_stats(
|
||||
ls = &tiqn->login_stats;
|
||||
|
||||
spin_lock(&ls->lock);
|
||||
if (!strcmp(conn->login_ip, ls->last_intr_fail_ip_addr) &&
|
||||
if (sockaddr_equal(&conn->login_sockaddr, &ls->last_intr_fail_sockaddr) &&
|
||||
((get_jiffies_64() - ls->last_fail_time) < 10)) {
|
||||
/* We already have the failure info for this login */
|
||||
spin_unlock(&ls->lock);
|
||||
@ -1427,8 +1455,7 @@ void iscsit_collect_login_stats(
|
||||
|
||||
ls->last_intr_fail_ip_family = conn->login_family;
|
||||
|
||||
snprintf(ls->last_intr_fail_ip_addr, IPV6_ADDRESS_SPACE,
|
||||
"%s", conn->login_ip);
|
||||
ls->last_intr_fail_sockaddr = conn->login_sockaddr;
|
||||
ls->last_fail_time = get_jiffies_64();
|
||||
}
|
||||
|
||||
|
@ -526,7 +526,7 @@ static inline struct tcm_loop_tpg *tl_tpg(struct se_portal_group *se_tpg)
|
||||
static char *tcm_loop_get_endpoint_wwn(struct se_portal_group *se_tpg)
|
||||
{
|
||||
/*
|
||||
* Return the passed NAA identifier for the SAS Target Port
|
||||
* Return the passed NAA identifier for the Target Port
|
||||
*/
|
||||
return &tl_tpg(se_tpg)->tl_hba->tl_wwn_address[0];
|
||||
}
|
||||
@ -845,7 +845,7 @@ static int tcm_loop_make_nexus(
|
||||
transport_free_session(tl_nexus->se_sess);
|
||||
goto out;
|
||||
}
|
||||
/* Now, register the SAS I_T Nexus as active. */
|
||||
/* Now, register the I_T Nexus as active. */
|
||||
transport_register_session(se_tpg, tl_nexus->se_sess->se_node_acl,
|
||||
tl_nexus->se_sess, tl_nexus);
|
||||
tl_tpg->tl_nexus = tl_nexus;
|
||||
@ -884,7 +884,7 @@ static int tcm_loop_drop_nexus(
|
||||
" %s Initiator Port: %s\n", tcm_loop_dump_proto_id(tpg->tl_hba),
|
||||
tl_nexus->se_sess->se_node_acl->initiatorname);
|
||||
/*
|
||||
* Release the SCSI I_T Nexus to the emulated SAS Target Port
|
||||
* Release the SCSI I_T Nexus to the emulated Target Port
|
||||
*/
|
||||
transport_deregister_session(tl_nexus->se_sess);
|
||||
tpg->tl_nexus = NULL;
|
||||
@ -1034,6 +1034,11 @@ static ssize_t tcm_loop_tpg_store_transport_status(
|
||||
}
|
||||
if (!strncmp(page, "offline", 7)) {
|
||||
tl_tpg->tl_transport_status = TCM_TRANSPORT_OFFLINE;
|
||||
if (tl_tpg->tl_nexus) {
|
||||
struct se_session *tl_sess = tl_tpg->tl_nexus->se_sess;
|
||||
|
||||
core_allocate_nexus_loss_ua(tl_sess->se_node_acl);
|
||||
}
|
||||
return count;
|
||||
}
|
||||
return -EINVAL;
|
||||
@ -1077,7 +1082,7 @@ static struct se_portal_group *tcm_loop_make_naa_tpg(
|
||||
tl_tpg->tl_hba = tl_hba;
|
||||
tl_tpg->tl_tpgt = tpgt;
|
||||
/*
|
||||
* Register the tl_tpg as a emulated SAS TCM Target Endpoint
|
||||
* Register the tl_tpg as a emulated TCM Target Endpoint
|
||||
*/
|
||||
ret = core_tpg_register(wwn, &tl_tpg->tl_se_tpg, tl_hba->tl_proto_id);
|
||||
if (ret < 0)
|
||||
@ -1102,11 +1107,11 @@ static void tcm_loop_drop_naa_tpg(
|
||||
tl_hba = tl_tpg->tl_hba;
|
||||
tpgt = tl_tpg->tl_tpgt;
|
||||
/*
|
||||
* Release the I_T Nexus for the Virtual SAS link if present
|
||||
* Release the I_T Nexus for the Virtual target link if present
|
||||
*/
|
||||
tcm_loop_drop_nexus(tl_tpg);
|
||||
/*
|
||||
* Deregister the tl_tpg as a emulated SAS TCM Target Endpoint
|
||||
* Deregister the tl_tpg as a emulated TCM Target Endpoint
|
||||
*/
|
||||
core_tpg_deregister(se_tpg);
|
||||
|
||||
@ -1199,8 +1204,9 @@ static void tcm_loop_drop_scsi_hba(
|
||||
struct tcm_loop_hba, tl_hba_wwn);
|
||||
|
||||
pr_debug("TCM_Loop_ConfigFS: Deallocating emulated Target"
|
||||
" SAS Address: %s at Linux/SCSI Host ID: %d\n",
|
||||
tl_hba->tl_wwn_address, tl_hba->sh->host_no);
|
||||
" %s Address: %s at Linux/SCSI Host ID: %d\n",
|
||||
tcm_loop_dump_proto_id(tl_hba), tl_hba->tl_wwn_address,
|
||||
tl_hba->sh->host_no);
|
||||
/*
|
||||
* Call device_unregister() on the original tl_hba->dev.
|
||||
* tcm_loop_fabric_scsi.c:tcm_loop_release_adapter() will
|
||||
|
@ -620,8 +620,6 @@ struct se_lun_acl *core_dev_init_initiator_node_lun_acl(
|
||||
|
||||
lacl->mapped_lun = mapped_lun;
|
||||
lacl->se_lun_nacl = nacl;
|
||||
snprintf(lacl->initiatorname, TRANSPORT_IQN_LEN, "%s",
|
||||
nacl->initiatorname);
|
||||
|
||||
return lacl;
|
||||
}
|
||||
@ -656,7 +654,7 @@ int core_dev_add_initiator_node_lun_acl(
|
||||
" InitiatorNode: %s\n", tpg->se_tpg_tfo->get_fabric_name(),
|
||||
tpg->se_tpg_tfo->tpg_get_tag(tpg), lun->unpacked_lun, lacl->mapped_lun,
|
||||
(lun_access & TRANSPORT_LUNFLAGS_READ_WRITE) ? "RW" : "RO",
|
||||
lacl->initiatorname);
|
||||
nacl->initiatorname);
|
||||
/*
|
||||
* Check to see if there are any existing persistent reservation APTPL
|
||||
* pre-registrations that need to be enabled for this LUN ACL..
|
||||
@ -688,7 +686,7 @@ int core_dev_del_initiator_node_lun_acl(
|
||||
" InitiatorNode: %s Mapped LUN: %llu\n",
|
||||
tpg->se_tpg_tfo->get_fabric_name(),
|
||||
tpg->se_tpg_tfo->tpg_get_tag(tpg), lun->unpacked_lun,
|
||||
lacl->initiatorname, lacl->mapped_lun);
|
||||
nacl->initiatorname, lacl->mapped_lun);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -701,7 +699,7 @@ void core_dev_free_initiator_node_lun_acl(
|
||||
" Mapped LUN: %llu\n", tpg->se_tpg_tfo->get_fabric_name(),
|
||||
tpg->se_tpg_tfo->tpg_get_tag(tpg),
|
||||
tpg->se_tpg_tfo->get_fabric_name(),
|
||||
lacl->initiatorname, lacl->mapped_lun);
|
||||
lacl->se_lun_nacl->initiatorname, lacl->mapped_lun);
|
||||
|
||||
kfree(lacl);
|
||||
}
|
||||
@ -754,7 +752,7 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name)
|
||||
dev->dev_link_magic = SE_DEV_LINK_MAGIC;
|
||||
dev->se_hba = hba;
|
||||
dev->transport = hba->backend->ops;
|
||||
dev->prot_length = sizeof(struct se_dif_v1_tuple);
|
||||
dev->prot_length = sizeof(struct t10_pi_tuple);
|
||||
dev->hba_index = hba->hba_index;
|
||||
|
||||
INIT_LIST_HEAD(&dev->dev_list);
|
||||
@ -771,7 +769,6 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name)
|
||||
spin_lock_init(&dev->se_tmr_lock);
|
||||
spin_lock_init(&dev->qf_cmd_lock);
|
||||
sema_init(&dev->caw_sem, 1);
|
||||
atomic_set(&dev->dev_ordered_id, 0);
|
||||
INIT_LIST_HEAD(&dev->t10_wwn.t10_vpd_list);
|
||||
spin_lock_init(&dev->t10_wwn.t10_vpd_lock);
|
||||
INIT_LIST_HEAD(&dev->t10_pr.registration_list);
|
||||
|
@ -203,7 +203,7 @@ static ssize_t target_fabric_mappedlun_store_write_protect(
|
||||
pr_debug("%s_ConfigFS: Changed Initiator ACL: %s"
|
||||
" Mapped LUN: %llu Write Protect bit to %s\n",
|
||||
se_tpg->se_tpg_tfo->get_fabric_name(),
|
||||
lacl->initiatorname, lacl->mapped_lun, (op) ? "ON" : "OFF");
|
||||
se_nacl->initiatorname, lacl->mapped_lun, (op) ? "ON" : "OFF");
|
||||
|
||||
return count;
|
||||
|
||||
|
@ -184,3 +184,8 @@ core_delete_hba(struct se_hba *hba)
|
||||
kfree(hba);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool target_sense_desc_format(struct se_device *dev)
|
||||
{
|
||||
return dev->transport->get_blocks(dev) > U32_MAX;
|
||||
}
|
||||
|
@ -154,6 +154,38 @@ sbc_emulate_readcapacity_16(struct se_cmd *cmd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static sense_reason_t
|
||||
sbc_emulate_startstop(struct se_cmd *cmd)
|
||||
{
|
||||
unsigned char *cdb = cmd->t_task_cdb;
|
||||
|
||||
/*
|
||||
* See sbc3r36 section 5.25
|
||||
* Immediate bit should be set since there is nothing to complete
|
||||
* POWER CONDITION MODIFIER 0h
|
||||
*/
|
||||
if (!(cdb[1] & 1) || cdb[2] || cdb[3])
|
||||
return TCM_INVALID_CDB_FIELD;
|
||||
|
||||
/*
|
||||
* See sbc3r36 section 5.25
|
||||
* POWER CONDITION 0h START_VALID - process START and LOEJ
|
||||
*/
|
||||
if (cdb[4] >> 4 & 0xf)
|
||||
return TCM_INVALID_CDB_FIELD;
|
||||
|
||||
/*
|
||||
* See sbc3r36 section 5.25
|
||||
* LOEJ 0h - nothing to load or unload
|
||||
* START 1h - we are ready
|
||||
*/
|
||||
if (!(cdb[4] & 1) || (cdb[4] & 2) || (cdb[4] & 4))
|
||||
return TCM_INVALID_CDB_FIELD;
|
||||
|
||||
target_complete_cmd(cmd, SAM_STAT_GOOD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
sector_t sbc_get_write_same_sectors(struct se_cmd *cmd)
|
||||
{
|
||||
u32 num_blocks;
|
||||
@ -960,6 +992,9 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
|
||||
" than 1\n", sectors);
|
||||
return TCM_INVALID_CDB_FIELD;
|
||||
}
|
||||
if (sbc_check_dpofua(dev, cmd, cdb))
|
||||
return TCM_INVALID_CDB_FIELD;
|
||||
|
||||
/*
|
||||
* Double size because we have two buffers, note that
|
||||
* zero is not an error..
|
||||
@ -1069,6 +1104,10 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
|
||||
size = 0;
|
||||
cmd->execute_cmd = sbc_emulate_noop;
|
||||
break;
|
||||
case START_STOP:
|
||||
size = 0;
|
||||
cmd->execute_cmd = sbc_emulate_startstop;
|
||||
break;
|
||||
default:
|
||||
ret = spc_parse_cdb(cmd, &size);
|
||||
if (ret)
|
||||
@ -1191,7 +1230,7 @@ void
|
||||
sbc_dif_generate(struct se_cmd *cmd)
|
||||
{
|
||||
struct se_device *dev = cmd->se_dev;
|
||||
struct se_dif_v1_tuple *sdt;
|
||||
struct t10_pi_tuple *sdt;
|
||||
struct scatterlist *dsg = cmd->t_data_sg, *psg;
|
||||
sector_t sector = cmd->t_task_lba;
|
||||
void *daddr, *paddr;
|
||||
@ -1203,7 +1242,7 @@ sbc_dif_generate(struct se_cmd *cmd)
|
||||
daddr = kmap_atomic(sg_page(dsg)) + dsg->offset;
|
||||
|
||||
for (j = 0; j < psg->length;
|
||||
j += sizeof(struct se_dif_v1_tuple)) {
|
||||
j += sizeof(*sdt)) {
|
||||
__u16 crc;
|
||||
unsigned int avail;
|
||||
|
||||
@ -1256,7 +1295,7 @@ sbc_dif_generate(struct se_cmd *cmd)
|
||||
}
|
||||
|
||||
static sense_reason_t
|
||||
sbc_dif_v1_verify(struct se_cmd *cmd, struct se_dif_v1_tuple *sdt,
|
||||
sbc_dif_v1_verify(struct se_cmd *cmd, struct t10_pi_tuple *sdt,
|
||||
__u16 crc, sector_t sector, unsigned int ei_lba)
|
||||
{
|
||||
__be16 csum;
|
||||
@ -1346,7 +1385,7 @@ sbc_dif_verify(struct se_cmd *cmd, sector_t start, unsigned int sectors,
|
||||
unsigned int ei_lba, struct scatterlist *psg, int psg_off)
|
||||
{
|
||||
struct se_device *dev = cmd->se_dev;
|
||||
struct se_dif_v1_tuple *sdt;
|
||||
struct t10_pi_tuple *sdt;
|
||||
struct scatterlist *dsg = cmd->t_data_sg;
|
||||
sector_t sector = start;
|
||||
void *daddr, *paddr;
|
||||
@ -1361,7 +1400,7 @@ sbc_dif_verify(struct se_cmd *cmd, sector_t start, unsigned int sectors,
|
||||
|
||||
for (i = psg_off; i < psg->length &&
|
||||
sector < start + sectors;
|
||||
i += sizeof(struct se_dif_v1_tuple)) {
|
||||
i += sizeof(*sdt)) {
|
||||
__u16 crc;
|
||||
unsigned int avail;
|
||||
|
||||
|
@ -484,8 +484,8 @@ static sense_reason_t
|
||||
spc_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf)
|
||||
{
|
||||
struct se_device *dev = cmd->se_dev;
|
||||
int have_tp = 0;
|
||||
int opt, min;
|
||||
u32 mtl = 0;
|
||||
int have_tp = 0, opt, min;
|
||||
|
||||
/*
|
||||
* Following spc3r22 section 6.5.3 Block Limits VPD page, when
|
||||
@ -516,8 +516,15 @@ spc_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf)
|
||||
|
||||
/*
|
||||
* Set MAXIMUM TRANSFER LENGTH
|
||||
*
|
||||
* XXX: Currently assumes single PAGE_SIZE per scatterlist for fabrics
|
||||
* enforcing maximum HW scatter-gather-list entry limit
|
||||
*/
|
||||
put_unaligned_be32(dev->dev_attrib.hw_max_sectors, &buf[8]);
|
||||
if (cmd->se_tfo->max_data_sg_nents) {
|
||||
mtl = (cmd->se_tfo->max_data_sg_nents * PAGE_SIZE) /
|
||||
dev->dev_attrib.block_size;
|
||||
}
|
||||
put_unaligned_be32(min_not_zero(mtl, dev->dev_attrib.hw_max_sectors), &buf[8]);
|
||||
|
||||
/*
|
||||
* Set OPTIMAL TRANSFER LENGTH
|
||||
@ -768,7 +775,12 @@ static int spc_modesense_control(struct se_cmd *cmd, u8 pc, u8 *p)
|
||||
if (pc == 1)
|
||||
goto out;
|
||||
|
||||
p[2] = 2;
|
||||
/* GLTSD: No implicit save of log parameters */
|
||||
p[2] = (1 << 1);
|
||||
if (target_sense_desc_format(dev))
|
||||
/* D_SENSE: Descriptor format sense data for 64bit sectors */
|
||||
p[2] |= (1 << 2);
|
||||
|
||||
/*
|
||||
* From spc4r23, 7.4.7 Control mode page
|
||||
*
|
||||
@ -1151,6 +1163,7 @@ static sense_reason_t spc_emulate_request_sense(struct se_cmd *cmd)
|
||||
unsigned char *rbuf;
|
||||
u8 ua_asc = 0, ua_ascq = 0;
|
||||
unsigned char buf[SE_SENSE_BUF];
|
||||
bool desc_format = target_sense_desc_format(cmd->se_dev);
|
||||
|
||||
memset(buf, 0, SE_SENSE_BUF);
|
||||
|
||||
@ -1164,32 +1177,11 @@ static sense_reason_t spc_emulate_request_sense(struct se_cmd *cmd)
|
||||
if (!rbuf)
|
||||
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
||||
|
||||
if (!core_scsi3_ua_clear_for_request_sense(cmd, &ua_asc, &ua_ascq)) {
|
||||
/*
|
||||
* CURRENT ERROR, UNIT ATTENTION
|
||||
*/
|
||||
buf[0] = 0x70;
|
||||
buf[SPC_SENSE_KEY_OFFSET] = UNIT_ATTENTION;
|
||||
|
||||
/*
|
||||
* The Additional Sense Code (ASC) from the UNIT ATTENTION
|
||||
*/
|
||||
buf[SPC_ASC_KEY_OFFSET] = ua_asc;
|
||||
buf[SPC_ASCQ_KEY_OFFSET] = ua_ascq;
|
||||
buf[7] = 0x0A;
|
||||
} else {
|
||||
/*
|
||||
* CURRENT ERROR, NO SENSE
|
||||
*/
|
||||
buf[0] = 0x70;
|
||||
buf[SPC_SENSE_KEY_OFFSET] = NO_SENSE;
|
||||
|
||||
/*
|
||||
* NO ADDITIONAL SENSE INFORMATION
|
||||
*/
|
||||
buf[SPC_ASC_KEY_OFFSET] = 0x00;
|
||||
buf[7] = 0x0A;
|
||||
}
|
||||
if (!core_scsi3_ua_clear_for_request_sense(cmd, &ua_asc, &ua_ascq))
|
||||
scsi_build_sense_buffer(desc_format, buf, UNIT_ATTENTION,
|
||||
ua_asc, ua_ascq);
|
||||
else
|
||||
scsi_build_sense_buffer(desc_format, buf, NO_SENSE, 0x0, 0x0);
|
||||
|
||||
memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length));
|
||||
transport_kunmap_data_sg(cmd);
|
||||
@ -1418,9 +1410,6 @@ spc_parse_cdb(struct se_cmd *cmd, unsigned int *size)
|
||||
}
|
||||
break;
|
||||
default:
|
||||
pr_warn("TARGET_CORE[%s]: Unsupported SCSI Opcode"
|
||||
" 0x%02x, sending CHECK_CONDITION.\n",
|
||||
cmd->se_tfo->get_fabric_name(), cdb[0]);
|
||||
return TCM_UNSUPPORTED_SCSI_OPCODE;
|
||||
}
|
||||
|
||||
|
@ -41,6 +41,7 @@
|
||||
#include "target_core_internal.h"
|
||||
#include "target_core_alua.h"
|
||||
#include "target_core_pr.h"
|
||||
#include "target_core_ua.h"
|
||||
|
||||
extern struct se_device *g_lun0_dev;
|
||||
|
||||
@ -83,6 +84,22 @@ struct se_node_acl *core_tpg_get_initiator_node_acl(
|
||||
}
|
||||
EXPORT_SYMBOL(core_tpg_get_initiator_node_acl);
|
||||
|
||||
void core_allocate_nexus_loss_ua(
|
||||
struct se_node_acl *nacl)
|
||||
{
|
||||
struct se_dev_entry *deve;
|
||||
|
||||
if (!nacl)
|
||||
return;
|
||||
|
||||
rcu_read_lock();
|
||||
hlist_for_each_entry_rcu(deve, &nacl->lun_entry_hlist, link)
|
||||
core_scsi3_ua_allocate(deve, 0x29,
|
||||
ASCQ_29H_NEXUS_LOSS_OCCURRED);
|
||||
rcu_read_unlock();
|
||||
}
|
||||
EXPORT_SYMBOL(core_allocate_nexus_loss_ua);
|
||||
|
||||
/* core_tpg_add_node_to_devs():
|
||||
*
|
||||
*
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include <net/sock.h>
|
||||
#include <net/tcp.h>
|
||||
#include <scsi/scsi_proto.h>
|
||||
#include <scsi/scsi_common.h>
|
||||
|
||||
#include <target/target_core_base.h>
|
||||
#include <target/target_core_backend.h>
|
||||
@ -1074,6 +1075,55 @@ transport_set_vpd_ident(struct t10_vpd *vpd, unsigned char *page_83)
|
||||
}
|
||||
EXPORT_SYMBOL(transport_set_vpd_ident);
|
||||
|
||||
static sense_reason_t
|
||||
target_check_max_data_sg_nents(struct se_cmd *cmd, struct se_device *dev,
|
||||
unsigned int size)
|
||||
{
|
||||
u32 mtl;
|
||||
|
||||
if (!cmd->se_tfo->max_data_sg_nents)
|
||||
return TCM_NO_SENSE;
|
||||
/*
|
||||
* Check if fabric enforced maximum SGL entries per I/O descriptor
|
||||
* exceeds se_cmd->data_length. If true, set SCF_UNDERFLOW_BIT +
|
||||
* residual_count and reduce original cmd->data_length to maximum
|
||||
* length based on single PAGE_SIZE entry scatter-lists.
|
||||
*/
|
||||
mtl = (cmd->se_tfo->max_data_sg_nents * PAGE_SIZE);
|
||||
if (cmd->data_length > mtl) {
|
||||
/*
|
||||
* If an existing CDB overflow is present, calculate new residual
|
||||
* based on CDB size minus fabric maximum transfer length.
|
||||
*
|
||||
* If an existing CDB underflow is present, calculate new residual
|
||||
* based on original cmd->data_length minus fabric maximum transfer
|
||||
* length.
|
||||
*
|
||||
* Otherwise, set the underflow residual based on cmd->data_length
|
||||
* minus fabric maximum transfer length.
|
||||
*/
|
||||
if (cmd->se_cmd_flags & SCF_OVERFLOW_BIT) {
|
||||
cmd->residual_count = (size - mtl);
|
||||
} else if (cmd->se_cmd_flags & SCF_UNDERFLOW_BIT) {
|
||||
u32 orig_dl = size + cmd->residual_count;
|
||||
cmd->residual_count = (orig_dl - mtl);
|
||||
} else {
|
||||
cmd->se_cmd_flags |= SCF_UNDERFLOW_BIT;
|
||||
cmd->residual_count = (cmd->data_length - mtl);
|
||||
}
|
||||
cmd->data_length = mtl;
|
||||
/*
|
||||
* Reset sbc_check_prot() calculated protection payload
|
||||
* length based upon the new smaller MTL.
|
||||
*/
|
||||
if (cmd->prot_length) {
|
||||
u32 sectors = (mtl / dev->dev_attrib.block_size);
|
||||
cmd->prot_length = dev->prot_length * sectors;
|
||||
}
|
||||
}
|
||||
return TCM_NO_SENSE;
|
||||
}
|
||||
|
||||
sense_reason_t
|
||||
target_cmd_size_check(struct se_cmd *cmd, unsigned int size)
|
||||
{
|
||||
@ -1087,9 +1137,9 @@ target_cmd_size_check(struct se_cmd *cmd, unsigned int size)
|
||||
" 0x%02x\n", cmd->se_tfo->get_fabric_name(),
|
||||
cmd->data_length, size, cmd->t_task_cdb[0]);
|
||||
|
||||
if (cmd->data_direction == DMA_TO_DEVICE) {
|
||||
pr_err("Rejecting underflow/overflow"
|
||||
" WRITE data\n");
|
||||
if (cmd->data_direction == DMA_TO_DEVICE &&
|
||||
cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) {
|
||||
pr_err("Rejecting underflow/overflow WRITE data\n");
|
||||
return TCM_INVALID_CDB_FIELD;
|
||||
}
|
||||
/*
|
||||
@ -1119,7 +1169,7 @@ target_cmd_size_check(struct se_cmd *cmd, unsigned int size)
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return target_check_max_data_sg_nents(cmd, dev, size);
|
||||
|
||||
}
|
||||
|
||||
@ -1177,14 +1227,7 @@ transport_check_alloc_task_attr(struct se_cmd *cmd)
|
||||
" emulation is not supported\n");
|
||||
return TCM_INVALID_CDB_FIELD;
|
||||
}
|
||||
/*
|
||||
* Used to determine when ORDERED commands should go from
|
||||
* Dormant to Active status.
|
||||
*/
|
||||
cmd->se_ordered_id = atomic_inc_return(&dev->dev_ordered_id);
|
||||
pr_debug("Allocated se_ordered_id: %u for Task Attr: 0x%02x on %s\n",
|
||||
cmd->se_ordered_id, cmd->sam_task_attr,
|
||||
dev->transport->name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1246,6 +1289,11 @@ target_setup_cmd_from_cdb(struct se_cmd *cmd, unsigned char *cdb)
|
||||
}
|
||||
|
||||
ret = dev->transport->parse_cdb(cmd);
|
||||
if (ret == TCM_UNSUPPORTED_SCSI_OPCODE)
|
||||
pr_warn_ratelimited("%s/%s: Unsupported SCSI Opcode 0x%02x, sending CHECK_CONDITION.\n",
|
||||
cmd->se_tfo->get_fabric_name(),
|
||||
cmd->se_sess->se_node_acl->initiatorname,
|
||||
cmd->t_task_cdb[0]);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@ -1693,8 +1741,7 @@ void transport_generic_request_failure(struct se_cmd *cmd,
|
||||
|
||||
check_stop:
|
||||
transport_lun_remove_cmd(cmd);
|
||||
if (!transport_cmd_check_stop_to_fabric(cmd))
|
||||
;
|
||||
transport_cmd_check_stop_to_fabric(cmd);
|
||||
return;
|
||||
|
||||
queue_full:
|
||||
@ -1767,16 +1814,14 @@ static bool target_handle_task_attr(struct se_cmd *cmd)
|
||||
*/
|
||||
switch (cmd->sam_task_attr) {
|
||||
case TCM_HEAD_TAG:
|
||||
pr_debug("Added HEAD_OF_QUEUE for CDB: 0x%02x, "
|
||||
"se_ordered_id: %u\n",
|
||||
cmd->t_task_cdb[0], cmd->se_ordered_id);
|
||||
pr_debug("Added HEAD_OF_QUEUE for CDB: 0x%02x\n",
|
||||
cmd->t_task_cdb[0]);
|
||||
return false;
|
||||
case TCM_ORDERED_TAG:
|
||||
atomic_inc_mb(&dev->dev_ordered_sync);
|
||||
|
||||
pr_debug("Added ORDERED for CDB: 0x%02x to ordered list, "
|
||||
" se_ordered_id: %u\n",
|
||||
cmd->t_task_cdb[0], cmd->se_ordered_id);
|
||||
pr_debug("Added ORDERED for CDB: 0x%02x to ordered list\n",
|
||||
cmd->t_task_cdb[0]);
|
||||
|
||||
/*
|
||||
* Execute an ORDERED command if no other older commands
|
||||
@ -1800,10 +1845,8 @@ static bool target_handle_task_attr(struct se_cmd *cmd)
|
||||
list_add_tail(&cmd->se_delayed_node, &dev->delayed_cmd_list);
|
||||
spin_unlock(&dev->delayed_cmd_lock);
|
||||
|
||||
pr_debug("Added CDB: 0x%02x Task Attr: 0x%02x to"
|
||||
" delayed CMD list, se_ordered_id: %u\n",
|
||||
cmd->t_task_cdb[0], cmd->sam_task_attr,
|
||||
cmd->se_ordered_id);
|
||||
pr_debug("Added CDB: 0x%02x Task Attr: 0x%02x to delayed CMD listn",
|
||||
cmd->t_task_cdb[0], cmd->sam_task_attr);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1888,20 +1931,18 @@ static void transport_complete_task_attr(struct se_cmd *cmd)
|
||||
if (cmd->sam_task_attr == TCM_SIMPLE_TAG) {
|
||||
atomic_dec_mb(&dev->simple_cmds);
|
||||
dev->dev_cur_ordered_id++;
|
||||
pr_debug("Incremented dev->dev_cur_ordered_id: %u for"
|
||||
" SIMPLE: %u\n", dev->dev_cur_ordered_id,
|
||||
cmd->se_ordered_id);
|
||||
pr_debug("Incremented dev->dev_cur_ordered_id: %u for SIMPLE\n",
|
||||
dev->dev_cur_ordered_id);
|
||||
} else if (cmd->sam_task_attr == TCM_HEAD_TAG) {
|
||||
dev->dev_cur_ordered_id++;
|
||||
pr_debug("Incremented dev_cur_ordered_id: %u for"
|
||||
" HEAD_OF_QUEUE: %u\n", dev->dev_cur_ordered_id,
|
||||
cmd->se_ordered_id);
|
||||
pr_debug("Incremented dev_cur_ordered_id: %u for HEAD_OF_QUEUE\n",
|
||||
dev->dev_cur_ordered_id);
|
||||
} else if (cmd->sam_task_attr == TCM_ORDERED_TAG) {
|
||||
atomic_dec_mb(&dev->dev_ordered_sync);
|
||||
|
||||
dev->dev_cur_ordered_id++;
|
||||
pr_debug("Incremented dev_cur_ordered_id: %u for ORDERED:"
|
||||
" %u\n", dev->dev_cur_ordered_id, cmd->se_ordered_id);
|
||||
pr_debug("Incremented dev_cur_ordered_id: %u for ORDERED\n",
|
||||
dev->dev_cur_ordered_id);
|
||||
}
|
||||
|
||||
target_restart_delayed_cmds(dev);
|
||||
@ -2615,37 +2656,159 @@ bool transport_wait_for_tasks(struct se_cmd *cmd)
|
||||
}
|
||||
EXPORT_SYMBOL(transport_wait_for_tasks);
|
||||
|
||||
static int transport_get_sense_codes(
|
||||
struct se_cmd *cmd,
|
||||
u8 *asc,
|
||||
u8 *ascq)
|
||||
struct sense_info {
|
||||
u8 key;
|
||||
u8 asc;
|
||||
u8 ascq;
|
||||
bool add_sector_info;
|
||||
};
|
||||
|
||||
static const struct sense_info sense_info_table[] = {
|
||||
[TCM_NO_SENSE] = {
|
||||
.key = NOT_READY
|
||||
},
|
||||
[TCM_NON_EXISTENT_LUN] = {
|
||||
.key = ILLEGAL_REQUEST,
|
||||
.asc = 0x25 /* LOGICAL UNIT NOT SUPPORTED */
|
||||
},
|
||||
[TCM_UNSUPPORTED_SCSI_OPCODE] = {
|
||||
.key = ILLEGAL_REQUEST,
|
||||
.asc = 0x20, /* INVALID COMMAND OPERATION CODE */
|
||||
},
|
||||
[TCM_SECTOR_COUNT_TOO_MANY] = {
|
||||
.key = ILLEGAL_REQUEST,
|
||||
.asc = 0x20, /* INVALID COMMAND OPERATION CODE */
|
||||
},
|
||||
[TCM_UNKNOWN_MODE_PAGE] = {
|
||||
.key = ILLEGAL_REQUEST,
|
||||
.asc = 0x24, /* INVALID FIELD IN CDB */
|
||||
},
|
||||
[TCM_CHECK_CONDITION_ABORT_CMD] = {
|
||||
.key = ABORTED_COMMAND,
|
||||
.asc = 0x29, /* BUS DEVICE RESET FUNCTION OCCURRED */
|
||||
.ascq = 0x03,
|
||||
},
|
||||
[TCM_INCORRECT_AMOUNT_OF_DATA] = {
|
||||
.key = ABORTED_COMMAND,
|
||||
.asc = 0x0c, /* WRITE ERROR */
|
||||
.ascq = 0x0d, /* NOT ENOUGH UNSOLICITED DATA */
|
||||
},
|
||||
[TCM_INVALID_CDB_FIELD] = {
|
||||
.key = ILLEGAL_REQUEST,
|
||||
.asc = 0x24, /* INVALID FIELD IN CDB */
|
||||
},
|
||||
[TCM_INVALID_PARAMETER_LIST] = {
|
||||
.key = ILLEGAL_REQUEST,
|
||||
.asc = 0x26, /* INVALID FIELD IN PARAMETER LIST */
|
||||
},
|
||||
[TCM_PARAMETER_LIST_LENGTH_ERROR] = {
|
||||
.key = ILLEGAL_REQUEST,
|
||||
.asc = 0x1a, /* PARAMETER LIST LENGTH ERROR */
|
||||
},
|
||||
[TCM_UNEXPECTED_UNSOLICITED_DATA] = {
|
||||
.key = ILLEGAL_REQUEST,
|
||||
.asc = 0x0c, /* WRITE ERROR */
|
||||
.ascq = 0x0c, /* UNEXPECTED_UNSOLICITED_DATA */
|
||||
},
|
||||
[TCM_SERVICE_CRC_ERROR] = {
|
||||
.key = ABORTED_COMMAND,
|
||||
.asc = 0x47, /* PROTOCOL SERVICE CRC ERROR */
|
||||
.ascq = 0x05, /* N/A */
|
||||
},
|
||||
[TCM_SNACK_REJECTED] = {
|
||||
.key = ABORTED_COMMAND,
|
||||
.asc = 0x11, /* READ ERROR */
|
||||
.ascq = 0x13, /* FAILED RETRANSMISSION REQUEST */
|
||||
},
|
||||
[TCM_WRITE_PROTECTED] = {
|
||||
.key = DATA_PROTECT,
|
||||
.asc = 0x27, /* WRITE PROTECTED */
|
||||
},
|
||||
[TCM_ADDRESS_OUT_OF_RANGE] = {
|
||||
.key = ILLEGAL_REQUEST,
|
||||
.asc = 0x21, /* LOGICAL BLOCK ADDRESS OUT OF RANGE */
|
||||
},
|
||||
[TCM_CHECK_CONDITION_UNIT_ATTENTION] = {
|
||||
.key = UNIT_ATTENTION,
|
||||
},
|
||||
[TCM_CHECK_CONDITION_NOT_READY] = {
|
||||
.key = NOT_READY,
|
||||
},
|
||||
[TCM_MISCOMPARE_VERIFY] = {
|
||||
.key = MISCOMPARE,
|
||||
.asc = 0x1d, /* MISCOMPARE DURING VERIFY OPERATION */
|
||||
.ascq = 0x00,
|
||||
},
|
||||
[TCM_LOGICAL_BLOCK_GUARD_CHECK_FAILED] = {
|
||||
.key = ABORTED_COMMAND,
|
||||
.asc = 0x10,
|
||||
.ascq = 0x01, /* LOGICAL BLOCK GUARD CHECK FAILED */
|
||||
.add_sector_info = true,
|
||||
},
|
||||
[TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED] = {
|
||||
.key = ABORTED_COMMAND,
|
||||
.asc = 0x10,
|
||||
.ascq = 0x02, /* LOGICAL BLOCK APPLICATION TAG CHECK FAILED */
|
||||
.add_sector_info = true,
|
||||
},
|
||||
[TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED] = {
|
||||
.key = ABORTED_COMMAND,
|
||||
.asc = 0x10,
|
||||
.ascq = 0x03, /* LOGICAL BLOCK REFERENCE TAG CHECK FAILED */
|
||||
.add_sector_info = true,
|
||||
},
|
||||
[TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE] = {
|
||||
/*
|
||||
* Returning ILLEGAL REQUEST would cause immediate IO errors on
|
||||
* Solaris initiators. Returning NOT READY instead means the
|
||||
* operations will be retried a finite number of times and we
|
||||
* can survive intermittent errors.
|
||||
*/
|
||||
.key = NOT_READY,
|
||||
.asc = 0x08, /* LOGICAL UNIT COMMUNICATION FAILURE */
|
||||
},
|
||||
};
|
||||
|
||||
static int translate_sense_reason(struct se_cmd *cmd, sense_reason_t reason)
|
||||
{
|
||||
*asc = cmd->scsi_asc;
|
||||
*ascq = cmd->scsi_ascq;
|
||||
const struct sense_info *si;
|
||||
u8 *buffer = cmd->sense_buffer;
|
||||
int r = (__force int)reason;
|
||||
u8 asc, ascq;
|
||||
bool desc_format = target_sense_desc_format(cmd->se_dev);
|
||||
|
||||
if (r < ARRAY_SIZE(sense_info_table) && sense_info_table[r].key)
|
||||
si = &sense_info_table[r];
|
||||
else
|
||||
si = &sense_info_table[(__force int)
|
||||
TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE];
|
||||
|
||||
if (reason == TCM_CHECK_CONDITION_UNIT_ATTENTION) {
|
||||
core_scsi3_ua_for_check_condition(cmd, &asc, &ascq);
|
||||
WARN_ON_ONCE(asc == 0);
|
||||
} else if (si->asc == 0) {
|
||||
WARN_ON_ONCE(cmd->scsi_asc == 0);
|
||||
asc = cmd->scsi_asc;
|
||||
ascq = cmd->scsi_ascq;
|
||||
} else {
|
||||
asc = si->asc;
|
||||
ascq = si->ascq;
|
||||
}
|
||||
|
||||
scsi_build_sense_buffer(desc_format, buffer, si->key, asc, ascq);
|
||||
if (si->add_sector_info)
|
||||
return scsi_set_sense_information(buffer,
|
||||
cmd->scsi_sense_length,
|
||||
cmd->bad_sector);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
void transport_err_sector_info(unsigned char *buffer, sector_t bad_sector)
|
||||
{
|
||||
/* Place failed LBA in sense data information descriptor 0. */
|
||||
buffer[SPC_ADD_SENSE_LEN_OFFSET] = 0xc;
|
||||
buffer[SPC_DESC_TYPE_OFFSET] = 0; /* Information */
|
||||
buffer[SPC_ADDITIONAL_DESC_LEN_OFFSET] = 0xa;
|
||||
buffer[SPC_VALIDITY_OFFSET] = 0x80;
|
||||
|
||||
/* Descriptor Information: failing sector */
|
||||
put_unaligned_be64(bad_sector, &buffer[12]);
|
||||
}
|
||||
|
||||
int
|
||||
transport_send_check_condition_and_sense(struct se_cmd *cmd,
|
||||
sense_reason_t reason, int from_transport)
|
||||
{
|
||||
unsigned char *buffer = cmd->sense_buffer;
|
||||
unsigned long flags;
|
||||
u8 asc = 0, ascq = 0;
|
||||
|
||||
spin_lock_irqsave(&cmd->t_state_lock, flags);
|
||||
if (cmd->se_cmd_flags & SCF_SENT_CHECK_CONDITION) {
|
||||
@ -2655,243 +2818,17 @@ transport_send_check_condition_and_sense(struct se_cmd *cmd,
|
||||
cmd->se_cmd_flags |= SCF_SENT_CHECK_CONDITION;
|
||||
spin_unlock_irqrestore(&cmd->t_state_lock, flags);
|
||||
|
||||
if (!reason && from_transport)
|
||||
goto after_reason;
|
||||
if (!from_transport) {
|
||||
int rc;
|
||||
|
||||
if (!from_transport)
|
||||
cmd->se_cmd_flags |= SCF_EMULATED_TASK_SENSE;
|
||||
|
||||
/*
|
||||
* Actual SENSE DATA, see SPC-3 7.23.2 SPC_SENSE_KEY_OFFSET uses
|
||||
* SENSE KEY values from include/scsi/scsi.h
|
||||
*/
|
||||
switch (reason) {
|
||||
case TCM_NO_SENSE:
|
||||
/* CURRENT ERROR */
|
||||
buffer[0] = 0x70;
|
||||
buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
|
||||
/* Not Ready */
|
||||
buffer[SPC_SENSE_KEY_OFFSET] = NOT_READY;
|
||||
/* NO ADDITIONAL SENSE INFORMATION */
|
||||
buffer[SPC_ASC_KEY_OFFSET] = 0;
|
||||
buffer[SPC_ASCQ_KEY_OFFSET] = 0;
|
||||
break;
|
||||
case TCM_NON_EXISTENT_LUN:
|
||||
/* CURRENT ERROR */
|
||||
buffer[0] = 0x70;
|
||||
buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
|
||||
/* ILLEGAL REQUEST */
|
||||
buffer[SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
|
||||
/* LOGICAL UNIT NOT SUPPORTED */
|
||||
buffer[SPC_ASC_KEY_OFFSET] = 0x25;
|
||||
break;
|
||||
case TCM_UNSUPPORTED_SCSI_OPCODE:
|
||||
case TCM_SECTOR_COUNT_TOO_MANY:
|
||||
/* CURRENT ERROR */
|
||||
buffer[0] = 0x70;
|
||||
buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
|
||||
/* ILLEGAL REQUEST */
|
||||
buffer[SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
|
||||
/* INVALID COMMAND OPERATION CODE */
|
||||
buffer[SPC_ASC_KEY_OFFSET] = 0x20;
|
||||
break;
|
||||
case TCM_UNKNOWN_MODE_PAGE:
|
||||
/* CURRENT ERROR */
|
||||
buffer[0] = 0x70;
|
||||
buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
|
||||
/* ILLEGAL REQUEST */
|
||||
buffer[SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
|
||||
/* INVALID FIELD IN CDB */
|
||||
buffer[SPC_ASC_KEY_OFFSET] = 0x24;
|
||||
break;
|
||||
case TCM_CHECK_CONDITION_ABORT_CMD:
|
||||
/* CURRENT ERROR */
|
||||
buffer[0] = 0x70;
|
||||
buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
|
||||
/* ABORTED COMMAND */
|
||||
buffer[SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND;
|
||||
/* BUS DEVICE RESET FUNCTION OCCURRED */
|
||||
buffer[SPC_ASC_KEY_OFFSET] = 0x29;
|
||||
buffer[SPC_ASCQ_KEY_OFFSET] = 0x03;
|
||||
break;
|
||||
case TCM_INCORRECT_AMOUNT_OF_DATA:
|
||||
/* CURRENT ERROR */
|
||||
buffer[0] = 0x70;
|
||||
buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
|
||||
/* ABORTED COMMAND */
|
||||
buffer[SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND;
|
||||
/* WRITE ERROR */
|
||||
buffer[SPC_ASC_KEY_OFFSET] = 0x0c;
|
||||
/* NOT ENOUGH UNSOLICITED DATA */
|
||||
buffer[SPC_ASCQ_KEY_OFFSET] = 0x0d;
|
||||
break;
|
||||
case TCM_INVALID_CDB_FIELD:
|
||||
/* CURRENT ERROR */
|
||||
buffer[0] = 0x70;
|
||||
buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
|
||||
/* ILLEGAL REQUEST */
|
||||
buffer[SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
|
||||
/* INVALID FIELD IN CDB */
|
||||
buffer[SPC_ASC_KEY_OFFSET] = 0x24;
|
||||
break;
|
||||
case TCM_INVALID_PARAMETER_LIST:
|
||||
/* CURRENT ERROR */
|
||||
buffer[0] = 0x70;
|
||||
buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
|
||||
/* ILLEGAL REQUEST */
|
||||
buffer[SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
|
||||
/* INVALID FIELD IN PARAMETER LIST */
|
||||
buffer[SPC_ASC_KEY_OFFSET] = 0x26;
|
||||
break;
|
||||
case TCM_PARAMETER_LIST_LENGTH_ERROR:
|
||||
/* CURRENT ERROR */
|
||||
buffer[0] = 0x70;
|
||||
buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
|
||||
/* ILLEGAL REQUEST */
|
||||
buffer[SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
|
||||
/* PARAMETER LIST LENGTH ERROR */
|
||||
buffer[SPC_ASC_KEY_OFFSET] = 0x1a;
|
||||
break;
|
||||
case TCM_UNEXPECTED_UNSOLICITED_DATA:
|
||||
/* CURRENT ERROR */
|
||||
buffer[0] = 0x70;
|
||||
buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
|
||||
/* ABORTED COMMAND */
|
||||
buffer[SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND;
|
||||
/* WRITE ERROR */
|
||||
buffer[SPC_ASC_KEY_OFFSET] = 0x0c;
|
||||
/* UNEXPECTED_UNSOLICITED_DATA */
|
||||
buffer[SPC_ASCQ_KEY_OFFSET] = 0x0c;
|
||||
break;
|
||||
case TCM_SERVICE_CRC_ERROR:
|
||||
/* CURRENT ERROR */
|
||||
buffer[0] = 0x70;
|
||||
buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
|
||||
/* ABORTED COMMAND */
|
||||
buffer[SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND;
|
||||
/* PROTOCOL SERVICE CRC ERROR */
|
||||
buffer[SPC_ASC_KEY_OFFSET] = 0x47;
|
||||
/* N/A */
|
||||
buffer[SPC_ASCQ_KEY_OFFSET] = 0x05;
|
||||
break;
|
||||
case TCM_SNACK_REJECTED:
|
||||
/* CURRENT ERROR */
|
||||
buffer[0] = 0x70;
|
||||
buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
|
||||
/* ABORTED COMMAND */
|
||||
buffer[SPC_SENSE_KEY_OFFSET] = ABORTED_COMMAND;
|
||||
/* READ ERROR */
|
||||
buffer[SPC_ASC_KEY_OFFSET] = 0x11;
|
||||
/* FAILED RETRANSMISSION REQUEST */
|
||||
buffer[SPC_ASCQ_KEY_OFFSET] = 0x13;
|
||||
break;
|
||||
case TCM_WRITE_PROTECTED:
|
||||
/* CURRENT ERROR */
|
||||
buffer[0] = 0x70;
|
||||
buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
|
||||
/* DATA PROTECT */
|
||||
buffer[SPC_SENSE_KEY_OFFSET] = DATA_PROTECT;
|
||||
/* WRITE PROTECTED */
|
||||
buffer[SPC_ASC_KEY_OFFSET] = 0x27;
|
||||
break;
|
||||
case TCM_ADDRESS_OUT_OF_RANGE:
|
||||
/* CURRENT ERROR */
|
||||
buffer[0] = 0x70;
|
||||
buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
|
||||
/* ILLEGAL REQUEST */
|
||||
buffer[SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
|
||||
/* LOGICAL BLOCK ADDRESS OUT OF RANGE */
|
||||
buffer[SPC_ASC_KEY_OFFSET] = 0x21;
|
||||
break;
|
||||
case TCM_CHECK_CONDITION_UNIT_ATTENTION:
|
||||
/* CURRENT ERROR */
|
||||
buffer[0] = 0x70;
|
||||
buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
|
||||
/* UNIT ATTENTION */
|
||||
buffer[SPC_SENSE_KEY_OFFSET] = UNIT_ATTENTION;
|
||||
core_scsi3_ua_for_check_condition(cmd, &asc, &ascq);
|
||||
buffer[SPC_ASC_KEY_OFFSET] = asc;
|
||||
buffer[SPC_ASCQ_KEY_OFFSET] = ascq;
|
||||
break;
|
||||
case TCM_CHECK_CONDITION_NOT_READY:
|
||||
/* CURRENT ERROR */
|
||||
buffer[0] = 0x70;
|
||||
buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
|
||||
/* Not Ready */
|
||||
buffer[SPC_SENSE_KEY_OFFSET] = NOT_READY;
|
||||
transport_get_sense_codes(cmd, &asc, &ascq);
|
||||
buffer[SPC_ASC_KEY_OFFSET] = asc;
|
||||
buffer[SPC_ASCQ_KEY_OFFSET] = ascq;
|
||||
break;
|
||||
case TCM_MISCOMPARE_VERIFY:
|
||||
/* CURRENT ERROR */
|
||||
buffer[0] = 0x70;
|
||||
buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
|
||||
buffer[SPC_SENSE_KEY_OFFSET] = MISCOMPARE;
|
||||
/* MISCOMPARE DURING VERIFY OPERATION */
|
||||
buffer[SPC_ASC_KEY_OFFSET] = 0x1d;
|
||||
buffer[SPC_ASCQ_KEY_OFFSET] = 0x00;
|
||||
break;
|
||||
case TCM_LOGICAL_BLOCK_GUARD_CHECK_FAILED:
|
||||
/* CURRENT ERROR */
|
||||
buffer[0] = 0x70;
|
||||
buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
|
||||
/* ILLEGAL REQUEST */
|
||||
buffer[SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
|
||||
/* LOGICAL BLOCK GUARD CHECK FAILED */
|
||||
buffer[SPC_ASC_KEY_OFFSET] = 0x10;
|
||||
buffer[SPC_ASCQ_KEY_OFFSET] = 0x01;
|
||||
transport_err_sector_info(buffer, cmd->bad_sector);
|
||||
break;
|
||||
case TCM_LOGICAL_BLOCK_APP_TAG_CHECK_FAILED:
|
||||
/* CURRENT ERROR */
|
||||
buffer[0] = 0x70;
|
||||
buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
|
||||
/* ILLEGAL REQUEST */
|
||||
buffer[SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
|
||||
/* LOGICAL BLOCK APPLICATION TAG CHECK FAILED */
|
||||
buffer[SPC_ASC_KEY_OFFSET] = 0x10;
|
||||
buffer[SPC_ASCQ_KEY_OFFSET] = 0x02;
|
||||
transport_err_sector_info(buffer, cmd->bad_sector);
|
||||
break;
|
||||
case TCM_LOGICAL_BLOCK_REF_TAG_CHECK_FAILED:
|
||||
/* CURRENT ERROR */
|
||||
buffer[0] = 0x70;
|
||||
buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
|
||||
/* ILLEGAL REQUEST */
|
||||
buffer[SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
|
||||
/* LOGICAL BLOCK REFERENCE TAG CHECK FAILED */
|
||||
buffer[SPC_ASC_KEY_OFFSET] = 0x10;
|
||||
buffer[SPC_ASCQ_KEY_OFFSET] = 0x03;
|
||||
transport_err_sector_info(buffer, cmd->bad_sector);
|
||||
break;
|
||||
case TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE:
|
||||
default:
|
||||
/* CURRENT ERROR */
|
||||
buffer[0] = 0x70;
|
||||
buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
|
||||
/*
|
||||
* Returning ILLEGAL REQUEST would cause immediate IO errors on
|
||||
* Solaris initiators. Returning NOT READY instead means the
|
||||
* operations will be retried a finite number of times and we
|
||||
* can survive intermittent errors.
|
||||
*/
|
||||
buffer[SPC_SENSE_KEY_OFFSET] = NOT_READY;
|
||||
/* LOGICAL UNIT COMMUNICATION FAILURE */
|
||||
buffer[SPC_ASC_KEY_OFFSET] = 0x08;
|
||||
break;
|
||||
cmd->scsi_status = SAM_STAT_CHECK_CONDITION;
|
||||
cmd->scsi_sense_length = TRANSPORT_SENSE_BUFFER;
|
||||
rc = translate_sense_reason(cmd, reason);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
/*
|
||||
* This code uses linux/include/scsi/scsi.h SAM status codes!
|
||||
*/
|
||||
cmd->scsi_status = SAM_STAT_CHECK_CONDITION;
|
||||
/*
|
||||
* Automatically padded, this value is encoded in the fabric's
|
||||
* data_length response PDU containing the SCSI defined sense data.
|
||||
*/
|
||||
cmd->scsi_sense_length = TRANSPORT_SENSE_BUFFER;
|
||||
|
||||
after_reason:
|
||||
trace_target_cmd_complete(cmd);
|
||||
return cmd->se_tfo->queue_status(cmd);
|
||||
}
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include <linux/parser.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/uio_driver.h>
|
||||
#include <linux/stringify.h>
|
||||
#include <net/genetlink.h>
|
||||
#include <scsi/scsi_common.h>
|
||||
#include <scsi/scsi_proto.h>
|
||||
@ -538,14 +539,8 @@ static void tcmu_handle_completion(struct tcmu_cmd *cmd, struct tcmu_cmd_entry *
|
||||
UPDATE_HEAD(udev->data_tail, cmd->data_length, udev->data_size);
|
||||
pr_warn("TCMU: Userspace set UNKNOWN_OP flag on se_cmd %p\n",
|
||||
cmd->se_cmd);
|
||||
transport_generic_request_failure(cmd->se_cmd,
|
||||
TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE);
|
||||
cmd->se_cmd = NULL;
|
||||
kmem_cache_free(tcmu_cmd_cache, cmd);
|
||||
return;
|
||||
}
|
||||
|
||||
if (entry->rsp.scsi_status == SAM_STAT_CHECK_CONDITION) {
|
||||
entry->rsp.scsi_status = SAM_STAT_CHECK_CONDITION;
|
||||
} else if (entry->rsp.scsi_status == SAM_STAT_CHECK_CONDITION) {
|
||||
memcpy(se_cmd->sense_buffer, entry->rsp.sense_buffer,
|
||||
se_cmd->scsi_sense_length);
|
||||
|
||||
@ -577,7 +572,6 @@ static void tcmu_handle_completion(struct tcmu_cmd *cmd, struct tcmu_cmd_entry *
|
||||
static unsigned int tcmu_handle_completions(struct tcmu_dev *udev)
|
||||
{
|
||||
struct tcmu_mailbox *mb;
|
||||
LIST_HEAD(cpl_cmds);
|
||||
unsigned long flags;
|
||||
int handled = 0;
|
||||
|
||||
@ -905,7 +899,7 @@ static int tcmu_configure_device(struct se_device *dev)
|
||||
WARN_ON(!PAGE_ALIGNED(udev->data_off));
|
||||
WARN_ON(udev->data_size % PAGE_SIZE);
|
||||
|
||||
info->version = xstr(TCMU_MAILBOX_VERSION);
|
||||
info->version = __stringify(TCMU_MAILBOX_VERSION);
|
||||
|
||||
info->mem[0].name = "tcm-user command & data buffer";
|
||||
info->mem[0].addr = (phys_addr_t) udev->mb_addr;
|
||||
|
@ -450,6 +450,8 @@ int target_xcopy_setup_pt(void)
|
||||
memset(&xcopy_pt_sess, 0, sizeof(struct se_session));
|
||||
INIT_LIST_HEAD(&xcopy_pt_sess.sess_list);
|
||||
INIT_LIST_HEAD(&xcopy_pt_sess.sess_acl_list);
|
||||
INIT_LIST_HEAD(&xcopy_pt_sess.sess_cmd_list);
|
||||
spin_lock_init(&xcopy_pt_sess.sess_cmd_lock);
|
||||
|
||||
xcopy_pt_nacl.se_tpg = &xcopy_pt_tpg;
|
||||
xcopy_pt_nacl.nacl_sess = &xcopy_pt_sess;
|
||||
@ -644,7 +646,7 @@ static int target_xcopy_read_source(
|
||||
pr_debug("XCOPY: Built READ_16: LBA: %llu Sectors: %u Length: %u\n",
|
||||
(unsigned long long)src_lba, src_sectors, length);
|
||||
|
||||
transport_init_se_cmd(se_cmd, &xcopy_pt_tfo, NULL, length,
|
||||
transport_init_se_cmd(se_cmd, &xcopy_pt_tfo, &xcopy_pt_sess, length,
|
||||
DMA_FROM_DEVICE, 0, &xpt_cmd->sense_buffer[0]);
|
||||
xop->src_pt_cmd = xpt_cmd;
|
||||
|
||||
@ -704,7 +706,7 @@ static int target_xcopy_write_destination(
|
||||
pr_debug("XCOPY: Built WRITE_16: LBA: %llu Sectors: %u Length: %u\n",
|
||||
(unsigned long long)dst_lba, dst_sectors, length);
|
||||
|
||||
transport_init_se_cmd(se_cmd, &xcopy_pt_tfo, NULL, length,
|
||||
transport_init_se_cmd(se_cmd, &xcopy_pt_tfo, &xcopy_pt_sess, length,
|
||||
DMA_TO_DEVICE, 0, &xpt_cmd->sense_buffer[0]);
|
||||
xop->dst_pt_cmd = xpt_cmd;
|
||||
|
||||
|
@ -255,7 +255,7 @@ static void ft_recv_seq(struct fc_seq *sp, struct fc_frame *fp, void *arg)
|
||||
struct ft_cmd *cmd = arg;
|
||||
struct fc_frame_header *fh;
|
||||
|
||||
if (unlikely(IS_ERR(fp))) {
|
||||
if (IS_ERR(fp)) {
|
||||
/* XXX need to find cmd if queued */
|
||||
cmd->seq = NULL;
|
||||
cmd->aborted = true;
|
||||
|
@ -61,4 +61,9 @@ static inline bool scsi_sense_valid(const struct scsi_sense_hdr *sshdr)
|
||||
extern bool scsi_normalize_sense(const u8 *sense_buffer, int sb_len,
|
||||
struct scsi_sense_hdr *sshdr);
|
||||
|
||||
extern void scsi_build_sense_buffer(int desc, u8 *buf, u8 key, u8 asc, u8 ascq);
|
||||
int scsi_set_sense_information(u8 *buf, int buf_len, u64 info);
|
||||
extern const u8 * scsi_sense_desc_find(const u8 * sense_buffer, int sb_len,
|
||||
int desc_type);
|
||||
|
||||
#endif /* _SCSI_COMMON_H_ */
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <linux/scatterlist.h>
|
||||
|
||||
#include <scsi/scsi_cmnd.h>
|
||||
#include <scsi/scsi_common.h>
|
||||
struct scsi_device;
|
||||
struct Scsi_Host;
|
||||
|
||||
@ -21,14 +22,9 @@ static inline bool scsi_sense_is_deferred(const struct scsi_sense_hdr *sshdr)
|
||||
return ((sshdr->response_code >= 0x70) && (sshdr->response_code & 1));
|
||||
}
|
||||
|
||||
extern const u8 * scsi_sense_desc_find(const u8 * sense_buffer, int sb_len,
|
||||
int desc_type);
|
||||
|
||||
extern int scsi_get_sense_info_fld(const u8 * sense_buffer, int sb_len,
|
||||
u64 * info_out);
|
||||
|
||||
extern void scsi_build_sense_buffer(int desc, u8 *buf, u8 key, u8 asc, u8 ascq);
|
||||
|
||||
extern int scsi_ioctl_reset(struct scsi_device *, int __user *);
|
||||
|
||||
struct scsi_eh_save {
|
||||
|
@ -62,6 +62,8 @@
|
||||
/* T10 protection information disabled by default */
|
||||
#define TA_DEFAULT_T10_PI 0
|
||||
#define TA_DEFAULT_FABRIC_PROT_TYPE 0
|
||||
/* TPG status needs to be enabled to return sendtargets discovery endpoint info */
|
||||
#define TA_DEFAULT_TPG_ENABLED_SENDTARGETS 1
|
||||
|
||||
#define ISCSI_IOV_DATA_BUFFER 5
|
||||
|
||||
@ -517,7 +519,6 @@ struct iscsi_conn {
|
||||
u16 cid;
|
||||
/* Remote TCP Port */
|
||||
u16 login_port;
|
||||
u16 local_port;
|
||||
int net_size;
|
||||
int login_family;
|
||||
u32 auth_id;
|
||||
@ -527,9 +528,8 @@ struct iscsi_conn {
|
||||
u32 exp_statsn;
|
||||
/* Per connection status sequence number */
|
||||
u32 stat_sn;
|
||||
#define IPV6_ADDRESS_SPACE 48
|
||||
unsigned char login_ip[IPV6_ADDRESS_SPACE];
|
||||
unsigned char local_ip[IPV6_ADDRESS_SPACE];
|
||||
struct sockaddr_storage login_sockaddr;
|
||||
struct sockaddr_storage local_sockaddr;
|
||||
int conn_usage_count;
|
||||
int conn_waiting_on_uc;
|
||||
atomic_t check_immediate_queue;
|
||||
@ -636,7 +636,7 @@ struct iscsi_session {
|
||||
/* session wide counter: expected command sequence number */
|
||||
u32 exp_cmd_sn;
|
||||
/* session wide counter: maximum allowed command sequence number */
|
||||
u32 max_cmd_sn;
|
||||
atomic_t max_cmd_sn;
|
||||
struct list_head sess_ooo_cmdsn_list;
|
||||
|
||||
/* LIO specific session ID */
|
||||
@ -764,6 +764,7 @@ struct iscsi_tpg_attrib {
|
||||
u32 default_erl;
|
||||
u8 t10_pi;
|
||||
u32 fabric_prot_type;
|
||||
u32 tpg_enabled_sendtargets;
|
||||
struct iscsi_portal_group *tpg;
|
||||
};
|
||||
|
||||
@ -776,12 +777,10 @@ struct iscsi_np {
|
||||
enum iscsi_timer_flags_table np_login_timer_flags;
|
||||
u32 np_exports;
|
||||
enum np_flags_table np_flags;
|
||||
unsigned char np_ip[IPV6_ADDRESS_SPACE];
|
||||
u16 np_port;
|
||||
spinlock_t np_thread_lock;
|
||||
struct completion np_restart_comp;
|
||||
struct socket *np_socket;
|
||||
struct __kernel_sockaddr_storage np_sockaddr;
|
||||
struct sockaddr_storage np_sockaddr;
|
||||
struct task_struct *np_thread;
|
||||
struct timer_list np_login_timer;
|
||||
void *np_context;
|
||||
|
@ -50,7 +50,7 @@ struct iscsi_login_stats {
|
||||
u64 last_fail_time; /* time stamp (jiffies) */
|
||||
u32 last_fail_type;
|
||||
int last_intr_fail_ip_family;
|
||||
unsigned char last_intr_fail_ip_addr[IPV6_ADDRESS_SPACE];
|
||||
struct sockaddr_storage last_intr_fail_sockaddr;
|
||||
char last_intr_fail_name[224];
|
||||
} ____cacheline_aligned;
|
||||
|
||||
|
@ -9,7 +9,7 @@ struct iscsit_transport {
|
||||
int priv_size;
|
||||
struct module *owner;
|
||||
struct list_head t_node;
|
||||
int (*iscsit_setup_np)(struct iscsi_np *, struct __kernel_sockaddr_storage *);
|
||||
int (*iscsit_setup_np)(struct iscsi_np *, struct sockaddr_storage *);
|
||||
int (*iscsit_accept_np)(struct iscsi_np *, struct iscsi_conn *);
|
||||
void (*iscsit_free_np)(struct iscsi_np *);
|
||||
void (*iscsit_wait_conn)(struct iscsi_conn *);
|
||||
|
@ -93,4 +93,6 @@ bool target_lun_is_rdonly(struct se_cmd *);
|
||||
sense_reason_t passthrough_parse_cdb(struct se_cmd *cmd,
|
||||
sense_reason_t (*exec_cmd)(struct se_cmd *cmd));
|
||||
|
||||
bool target_sense_desc_format(struct se_device *dev);
|
||||
|
||||
#endif /* TARGET_CORE_BACKEND_H */
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/blkdev.h>
|
||||
#include <linux/percpu_ida.h>
|
||||
#include <linux/t10-pi.h>
|
||||
#include <net/sock.h>
|
||||
#include <net/tcp.h>
|
||||
|
||||
@ -426,12 +427,6 @@ enum target_core_dif_check {
|
||||
TARGET_DIF_CHECK_REFTAG = 0x1 << 2,
|
||||
};
|
||||
|
||||
struct se_dif_v1_tuple {
|
||||
__be16 guard_tag;
|
||||
__be16 app_tag;
|
||||
__be32 ref_tag;
|
||||
};
|
||||
|
||||
/* for sam_task_attr */
|
||||
#define TCM_SIMPLE_TAG 0x20
|
||||
#define TCM_HEAD_TAG 0x21
|
||||
@ -444,6 +439,9 @@ struct se_cmd {
|
||||
u8 scsi_asc;
|
||||
u8 scsi_ascq;
|
||||
u16 scsi_sense_length;
|
||||
unsigned cmd_wait_set:1;
|
||||
unsigned unknown_data_length:1;
|
||||
bool state_active:1;
|
||||
u64 tag; /* SAM command identifier aka task tag */
|
||||
/* Delay for ALUA Active/NonOptimized state access in milliseconds */
|
||||
int alua_nonop_delay;
|
||||
@ -455,11 +453,8 @@ struct se_cmd {
|
||||
unsigned int map_tag;
|
||||
/* Transport protocol dependent state, see transport_state_table */
|
||||
enum transport_state_table t_state;
|
||||
unsigned cmd_wait_set:1;
|
||||
unsigned unknown_data_length:1;
|
||||
/* See se_cmd_flags_table */
|
||||
u32 se_cmd_flags;
|
||||
u32 se_ordered_id;
|
||||
/* Total size in bytes associated with command */
|
||||
u32 data_length;
|
||||
u32 residual_count;
|
||||
@ -477,7 +472,6 @@ struct se_cmd {
|
||||
struct se_tmr_req *se_tmr_req;
|
||||
struct list_head se_cmd_list;
|
||||
struct completion cmd_wait_comp;
|
||||
struct kref cmd_kref;
|
||||
const struct target_core_fabric_ops *se_tfo;
|
||||
sense_reason_t (*execute_cmd)(struct se_cmd *);
|
||||
sense_reason_t (*transport_complete_callback)(struct se_cmd *, bool);
|
||||
@ -497,6 +491,7 @@ struct se_cmd {
|
||||
#define CMD_T_REQUEST_STOP (1 << 8)
|
||||
#define CMD_T_BUSY (1 << 9)
|
||||
spinlock_t t_state_lock;
|
||||
struct kref cmd_kref;
|
||||
struct completion t_transport_stop_comp;
|
||||
|
||||
struct work_struct work;
|
||||
@ -509,8 +504,10 @@ struct se_cmd {
|
||||
struct scatterlist *t_bidi_data_sg;
|
||||
unsigned int t_bidi_data_nents;
|
||||
|
||||
/* Used for lun->lun_ref counting */
|
||||
int lun_ref_active;
|
||||
|
||||
struct list_head state_list;
|
||||
bool state_active;
|
||||
|
||||
/* old task stop completion, consider merging with some of the above */
|
||||
struct completion task_stop_comp;
|
||||
@ -518,20 +515,17 @@ struct se_cmd {
|
||||
/* backend private data */
|
||||
void *priv;
|
||||
|
||||
/* Used for lun->lun_ref counting */
|
||||
int lun_ref_active;
|
||||
|
||||
/* DIF related members */
|
||||
enum target_prot_op prot_op;
|
||||
enum target_prot_type prot_type;
|
||||
u8 prot_checks;
|
||||
bool prot_pto;
|
||||
u32 prot_length;
|
||||
u32 reftag_seed;
|
||||
struct scatterlist *t_prot_sg;
|
||||
unsigned int t_prot_nents;
|
||||
sense_reason_t pi_err;
|
||||
sector_t bad_sector;
|
||||
bool prot_pto;
|
||||
};
|
||||
|
||||
struct se_ua {
|
||||
@ -598,7 +592,6 @@ struct se_ml_stat_grps {
|
||||
};
|
||||
|
||||
struct se_lun_acl {
|
||||
char initiatorname[TRANSPORT_IQN_LEN];
|
||||
u64 mapped_lun;
|
||||
struct se_node_acl *se_lun_nacl;
|
||||
struct se_lun *se_lun;
|
||||
@ -685,7 +678,6 @@ struct se_lun {
|
||||
#define SE_LUN_LINK_MAGIC 0xffff7771
|
||||
u32 lun_link_magic;
|
||||
u32 lun_access;
|
||||
u32 lun_flags;
|
||||
u32 lun_index;
|
||||
|
||||
/* RELATIVE TARGET PORT IDENTIFER */
|
||||
@ -751,7 +743,6 @@ struct se_device {
|
||||
atomic_long_t write_bytes;
|
||||
/* Active commands on this virtual SE device */
|
||||
atomic_t simple_cmds;
|
||||
atomic_t dev_ordered_id;
|
||||
atomic_t dev_ordered_sync;
|
||||
atomic_t dev_qf_count;
|
||||
u32 export_count;
|
||||
|
@ -5,6 +5,19 @@ struct target_core_fabric_ops {
|
||||
struct module *module;
|
||||
const char *name;
|
||||
size_t node_acl_size;
|
||||
/*
|
||||
* Limits number of scatterlist entries per SCF_SCSI_DATA_CDB payload.
|
||||
* Setting this value tells target-core to enforce this limit, and
|
||||
* report as INQUIRY EVPD=b0 MAXIMUM TRANSFER LENGTH.
|
||||
*
|
||||
* target-core will currently reset se_cmd->data_length to this
|
||||
* maximum size, and set UNDERFLOW residual count if length exceeds
|
||||
* this limit.
|
||||
*
|
||||
* XXX: Not all initiator hosts honor this block-limit EVPD
|
||||
* XXX: Currently assumes single PAGE_SIZE per scatterlist entry
|
||||
*/
|
||||
u32 max_data_sg_nents;
|
||||
char *(*get_fabric_name)(void);
|
||||
char *(*tpg_get_wwn)(struct se_portal_group *);
|
||||
u16 (*tpg_get_tag)(struct se_portal_group *);
|
||||
@ -152,6 +165,7 @@ int transport_generic_handle_tmr(struct se_cmd *);
|
||||
void transport_generic_request_failure(struct se_cmd *, sense_reason_t);
|
||||
void __target_execute_cmd(struct se_cmd *);
|
||||
int transport_lookup_tmr_lun(struct se_cmd *, u64);
|
||||
void core_allocate_nexus_loss_ua(struct se_node_acl *acl);
|
||||
|
||||
struct se_node_acl *core_tpg_get_initiator_node_acl(struct se_portal_group *tpg,
|
||||
unsigned char *);
|
||||
|
@ -42,10 +42,6 @@
|
||||
#define TCMU_MAILBOX_VERSION 2
|
||||
#define ALIGN_SIZE 64 /* Should be enough for most CPUs */
|
||||
|
||||
/* See https://gcc.gnu.org/onlinedocs/cpp/Stringification.html */
|
||||
#define xstr(s) str(s)
|
||||
#define str(s) #s
|
||||
|
||||
struct tcmu_mailbox {
|
||||
__u16 version;
|
||||
__u16 flags;
|
||||
|
Loading…
Reference in New Issue
Block a user