You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending
Pull scsi-target changes from Nicholas Bellinger:
"There has been lots of work in existing code in a number of areas this
past cycle. The major highlights have been:
* Removal of transport_do_task_sg_chain() from core + fabrics
(Roland)
* target-core: Removal of se_task abstraction from target-core and
enforce hw_max_sectors for pSCSI backends (hch)
* Re-factoring of iscsi-target tx immediate/response queues (agrover)
* Conversion of iscsi-target back to using target core memory
allocation logic (agrover)
We've had one last minute iscsi-target patch go into for-next to
address a nasty regression bug related to the target core allocation
logic conversion from agrover that is not included in friday's
linux-next build, but has been included in this series.
On the new fabric module code front for-3.5, here is a brief status
update for the three currently in flight this round:
* usb-gadget target driver:
Sebastian Siewior's driver for supporting usb-gadget target mode
operation. This will be going out as a separate PULL request from
target-pending/usb-target-merge with subsystem maintainer ACKs. There
is one minor target-core patch in this series required to function.
* sbp ieee-1394/firewire target driver:
Chris Boot's driver for supportting the Serial Block Protocol (SBP)
across IEEE-1394 Firewire hardware. This will be going out as a
separate PULL request from target-pending/sbp-target-merge with two
additional drivers/firewire/ patches w/ subsystem maintainer ACKs.
* qla2xxx LLD target mode infrastructure changes + tcm_qla2xxx:
The Qlogic >= 24xx series HW target mode LLD infrastructure patch-set
and tcm_qla2xxx fabric driver. Support for FC target mode using
qla2xxx LLD code has been officially submitted by Qlogic to James
below, and is currently outstanding but not yet merged into
scsi.git/for-next..
[PATCH 00/22] qla2xxx: Updates for scsi "misc" branch
http://www.spinics.net/lists/linux-scsi/msg59350.html
Note there are *zero* direct dependencies upon this for-next series
for the qla2xxx LLD target + tcm_qla2xxx patches submitted above, and
over the last days the target mode team has been tracking down an
tcm_qla2xxx specific active I/O shutdown bug that appears to now be
almost squashed for 3.5-rc-fixes."
* 'for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending: (47 commits)
iscsi-target: Fix iov_count calculation bug in iscsit_allocate_iovecs
iscsi-target: remove dead code in iscsi_check_valuelist_for_support
target: Handle ATA_16 passthrough for pSCSI backend devices
target: Add MI_REPORT_TARGET_PGS ext. header + implict_trans_secs attribute
target: Fix MAINTENANCE_IN service action CDB checks to use lower 5 bits
target: add support for the WRITE_VERIFY command
target: make target_put_session void
target: cleanup transport_execute_tasks()
target: Remove max_sectors device attribute for modern se_task less code
target: lock => unlock typo in transport_lun_wait_for_tasks
target: Enforce hw_max_sectors for SCF_SCSI_DATA_SG_IO_CDB
target: remove the t_se_count field in struct se_cmd
target: remove the t_task_cdbs_ex_left field in struct se_cmd
target: remove the t_task_cdbs_left field in struct se_cmd
target: remove struct se_task
target: move the state and execute lists to the command
target: simplify command to task linkage
target: always allocate a single task
target: replace ->execute_task with ->execute_cmd
target: remove the task_sectors field in struct se_task
...
This commit is contained in:
+402
-419
File diff suppressed because it is too large
Load Diff
@@ -18,8 +18,7 @@ extern int iscsit_logout_closesession(struct iscsi_cmd *, struct iscsi_conn *);
|
||||
extern int iscsit_logout_closeconnection(struct iscsi_cmd *, struct iscsi_conn *);
|
||||
extern int iscsit_logout_removeconnforrecovery(struct iscsi_cmd *, struct iscsi_conn *);
|
||||
extern int iscsit_send_async_msg(struct iscsi_conn *, u16, u8, u8);
|
||||
extern int iscsit_send_r2t(struct iscsi_cmd *, struct iscsi_conn *);
|
||||
extern int iscsit_build_r2ts_for_cmd(struct iscsi_cmd *, struct iscsi_conn *, int);
|
||||
extern int iscsit_build_r2ts_for_cmd(struct iscsi_cmd *, struct iscsi_conn *, bool recovery);
|
||||
extern void iscsit_thread_get_cpumask(struct iscsi_conn *);
|
||||
extern int iscsi_target_tx_thread(void *);
|
||||
extern int iscsi_target_rx_thread(void *);
|
||||
|
||||
@@ -1538,7 +1538,7 @@ static int lio_write_pending(struct se_cmd *se_cmd)
|
||||
struct iscsi_cmd *cmd = container_of(se_cmd, struct iscsi_cmd, se_cmd);
|
||||
|
||||
if (!cmd->immediate_data && !cmd->unsolicited_data)
|
||||
return iscsit_build_r2ts_for_cmd(cmd, cmd->conn, 1);
|
||||
return iscsit_build_r2ts_for_cmd(cmd, cmd->conn, false);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -296,12 +296,11 @@ struct iscsi_datain_req {
|
||||
u32 runlength;
|
||||
u32 data_length;
|
||||
u32 data_offset;
|
||||
u32 data_offset_end;
|
||||
u32 data_sn;
|
||||
u32 next_burst_len;
|
||||
u32 read_data_done;
|
||||
u32 seq_send_order;
|
||||
struct list_head dr_list;
|
||||
struct list_head cmd_datain_node;
|
||||
} ____cacheline_aligned;
|
||||
|
||||
struct iscsi_ooo_cmdsn {
|
||||
@@ -381,8 +380,6 @@ struct iscsi_cmd {
|
||||
u32 buf_ptr_size;
|
||||
/* Used to store DataDigest */
|
||||
u32 data_crc;
|
||||
/* Total size in bytes associated with command */
|
||||
u32 data_length;
|
||||
/* Counter for MaxOutstandingR2T */
|
||||
u32 outstanding_r2ts;
|
||||
/* Next R2T Offset when DataSequenceInOrder=Yes */
|
||||
@@ -464,16 +461,13 @@ struct iscsi_cmd {
|
||||
/* Session the command is part of, used for connection recovery */
|
||||
struct iscsi_session *sess;
|
||||
/* list_head for connection list */
|
||||
struct list_head i_list;
|
||||
struct list_head i_conn_node;
|
||||
/* The TCM I/O descriptor that is accessed via container_of() */
|
||||
struct se_cmd se_cmd;
|
||||
/* Sense buffer that will be mapped into outgoing status */
|
||||
#define ISCSI_SENSE_BUFFER_LEN (TRANSPORT_SENSE_BUFFER + 2)
|
||||
unsigned char sense_buffer[ISCSI_SENSE_BUFFER_LEN];
|
||||
|
||||
struct scatterlist *t_mem_sg;
|
||||
u32 t_mem_sg_nents;
|
||||
|
||||
u32 padding;
|
||||
u8 pad_bytes[4];
|
||||
|
||||
@@ -500,8 +494,6 @@ struct iscsi_conn {
|
||||
u8 network_transport;
|
||||
enum iscsi_timer_flags_table nopin_timer_flags;
|
||||
enum iscsi_timer_flags_table nopin_response_timer_flags;
|
||||
u8 tx_immediate_queue;
|
||||
u8 tx_response_queue;
|
||||
/* Used to know what thread encountered a transport failure */
|
||||
u8 which_thread;
|
||||
/* connection id assigned by the Initiator */
|
||||
|
||||
@@ -37,7 +37,7 @@ struct iscsi_datain_req *iscsit_allocate_datain_req(void)
|
||||
" struct iscsi_datain_req\n");
|
||||
return NULL;
|
||||
}
|
||||
INIT_LIST_HEAD(&dr->dr_list);
|
||||
INIT_LIST_HEAD(&dr->cmd_datain_node);
|
||||
|
||||
return dr;
|
||||
}
|
||||
@@ -45,14 +45,14 @@ struct iscsi_datain_req *iscsit_allocate_datain_req(void)
|
||||
void iscsit_attach_datain_req(struct iscsi_cmd *cmd, struct iscsi_datain_req *dr)
|
||||
{
|
||||
spin_lock(&cmd->datain_lock);
|
||||
list_add_tail(&dr->dr_list, &cmd->datain_list);
|
||||
list_add_tail(&dr->cmd_datain_node, &cmd->datain_list);
|
||||
spin_unlock(&cmd->datain_lock);
|
||||
}
|
||||
|
||||
void iscsit_free_datain_req(struct iscsi_cmd *cmd, struct iscsi_datain_req *dr)
|
||||
{
|
||||
spin_lock(&cmd->datain_lock);
|
||||
list_del(&dr->dr_list);
|
||||
list_del(&dr->cmd_datain_node);
|
||||
spin_unlock(&cmd->datain_lock);
|
||||
|
||||
kmem_cache_free(lio_dr_cache, dr);
|
||||
@@ -63,8 +63,8 @@ void iscsit_free_all_datain_reqs(struct iscsi_cmd *cmd)
|
||||
struct iscsi_datain_req *dr, *dr_tmp;
|
||||
|
||||
spin_lock(&cmd->datain_lock);
|
||||
list_for_each_entry_safe(dr, dr_tmp, &cmd->datain_list, dr_list) {
|
||||
list_del(&dr->dr_list);
|
||||
list_for_each_entry_safe(dr, dr_tmp, &cmd->datain_list, cmd_datain_node) {
|
||||
list_del(&dr->cmd_datain_node);
|
||||
kmem_cache_free(lio_dr_cache, dr);
|
||||
}
|
||||
spin_unlock(&cmd->datain_lock);
|
||||
@@ -72,17 +72,14 @@ void iscsit_free_all_datain_reqs(struct iscsi_cmd *cmd)
|
||||
|
||||
struct iscsi_datain_req *iscsit_get_datain_req(struct iscsi_cmd *cmd)
|
||||
{
|
||||
struct iscsi_datain_req *dr;
|
||||
|
||||
if (list_empty(&cmd->datain_list)) {
|
||||
pr_err("cmd->datain_list is empty for ITT:"
|
||||
" 0x%08x\n", cmd->init_task_tag);
|
||||
return NULL;
|
||||
}
|
||||
list_for_each_entry(dr, &cmd->datain_list, dr_list)
|
||||
break;
|
||||
|
||||
return dr;
|
||||
return list_first_entry(&cmd->datain_list, struct iscsi_datain_req,
|
||||
cmd_datain_node);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -113,7 +110,7 @@ static struct iscsi_datain_req *iscsit_set_datain_values_yes_and_yes(
|
||||
read_data_done = (!dr->recovery) ?
|
||||
cmd->read_data_done : dr->read_data_done;
|
||||
|
||||
read_data_left = (cmd->data_length - read_data_done);
|
||||
read_data_left = (cmd->se_cmd.data_length - read_data_done);
|
||||
if (!read_data_left) {
|
||||
pr_err("ITT: 0x%08x read_data_left is zero!\n",
|
||||
cmd->init_task_tag);
|
||||
@@ -212,7 +209,7 @@ static struct iscsi_datain_req *iscsit_set_datain_values_no_and_yes(
|
||||
seq_send_order = (!dr->recovery) ?
|
||||
cmd->seq_send_order : dr->seq_send_order;
|
||||
|
||||
read_data_left = (cmd->data_length - read_data_done);
|
||||
read_data_left = (cmd->se_cmd.data_length - read_data_done);
|
||||
if (!read_data_left) {
|
||||
pr_err("ITT: 0x%08x read_data_left is zero!\n",
|
||||
cmd->init_task_tag);
|
||||
@@ -231,8 +228,8 @@ static struct iscsi_datain_req *iscsit_set_datain_values_no_and_yes(
|
||||
offset = (seq->offset + seq->next_burst_len);
|
||||
|
||||
if ((offset + conn->conn_ops->MaxRecvDataSegmentLength) >=
|
||||
cmd->data_length) {
|
||||
datain->length = (cmd->data_length - offset);
|
||||
cmd->se_cmd.data_length) {
|
||||
datain->length = (cmd->se_cmd.data_length - offset);
|
||||
datain->offset = offset;
|
||||
|
||||
datain->flags |= ISCSI_FLAG_CMD_FINAL;
|
||||
@@ -264,7 +261,7 @@ static struct iscsi_datain_req *iscsit_set_datain_values_no_and_yes(
|
||||
}
|
||||
}
|
||||
|
||||
if ((read_data_done + datain->length) == cmd->data_length)
|
||||
if ((read_data_done + datain->length) == cmd->se_cmd.data_length)
|
||||
datain->flags |= ISCSI_FLAG_DATA_STATUS;
|
||||
|
||||
datain->data_sn = (!dr->recovery) ? cmd->data_sn++ : dr->data_sn++;
|
||||
@@ -333,7 +330,7 @@ static struct iscsi_datain_req *iscsit_set_datain_values_yes_and_no(
|
||||
read_data_done = (!dr->recovery) ?
|
||||
cmd->read_data_done : dr->read_data_done;
|
||||
|
||||
read_data_left = (cmd->data_length - read_data_done);
|
||||
read_data_left = (cmd->se_cmd.data_length - read_data_done);
|
||||
if (!read_data_left) {
|
||||
pr_err("ITT: 0x%08x read_data_left is zero!\n",
|
||||
cmd->init_task_tag);
|
||||
@@ -344,7 +341,7 @@ static struct iscsi_datain_req *iscsit_set_datain_values_yes_and_no(
|
||||
if (!pdu)
|
||||
return dr;
|
||||
|
||||
if ((read_data_done + pdu->length) == cmd->data_length) {
|
||||
if ((read_data_done + pdu->length) == cmd->se_cmd.data_length) {
|
||||
pdu->flags |= (ISCSI_FLAG_CMD_FINAL | ISCSI_FLAG_DATA_STATUS);
|
||||
if (conn->sess->sess_ops->ErrorRecoveryLevel > 0)
|
||||
pdu->flags |= ISCSI_FLAG_DATA_ACK;
|
||||
@@ -433,7 +430,7 @@ static struct iscsi_datain_req *iscsit_set_datain_values_no_and_no(
|
||||
seq_send_order = (!dr->recovery) ?
|
||||
cmd->seq_send_order : dr->seq_send_order;
|
||||
|
||||
read_data_left = (cmd->data_length - read_data_done);
|
||||
read_data_left = (cmd->se_cmd.data_length - read_data_done);
|
||||
if (!read_data_left) {
|
||||
pr_err("ITT: 0x%08x read_data_left is zero!\n",
|
||||
cmd->init_task_tag);
|
||||
@@ -463,7 +460,7 @@ static struct iscsi_datain_req *iscsit_set_datain_values_no_and_no(
|
||||
} else
|
||||
seq->next_burst_len += pdu->length;
|
||||
|
||||
if ((read_data_done + pdu->length) == cmd->data_length)
|
||||
if ((read_data_done + pdu->length) == cmd->se_cmd.data_length)
|
||||
pdu->flags |= ISCSI_FLAG_DATA_STATUS;
|
||||
|
||||
pdu->data_sn = (!dr->recovery) ? cmd->data_sn++ : dr->data_sn++;
|
||||
|
||||
@@ -48,9 +48,9 @@ void iscsit_set_dataout_sequence_values(
|
||||
if (cmd->unsolicited_data) {
|
||||
cmd->seq_start_offset = cmd->write_data_done;
|
||||
cmd->seq_end_offset = (cmd->write_data_done +
|
||||
(cmd->data_length >
|
||||
(cmd->se_cmd.data_length >
|
||||
conn->sess->sess_ops->FirstBurstLength) ?
|
||||
conn->sess->sess_ops->FirstBurstLength : cmd->data_length);
|
||||
conn->sess->sess_ops->FirstBurstLength : cmd->se_cmd.data_length);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -59,15 +59,15 @@ void iscsit_set_dataout_sequence_values(
|
||||
|
||||
if (!cmd->seq_start_offset && !cmd->seq_end_offset) {
|
||||
cmd->seq_start_offset = cmd->write_data_done;
|
||||
cmd->seq_end_offset = (cmd->data_length >
|
||||
cmd->seq_end_offset = (cmd->se_cmd.data_length >
|
||||
conn->sess->sess_ops->MaxBurstLength) ?
|
||||
(cmd->write_data_done +
|
||||
conn->sess->sess_ops->MaxBurstLength) : cmd->data_length;
|
||||
conn->sess->sess_ops->MaxBurstLength) : cmd->se_cmd.data_length;
|
||||
} else {
|
||||
cmd->seq_start_offset = cmd->seq_end_offset;
|
||||
cmd->seq_end_offset = ((cmd->seq_end_offset +
|
||||
conn->sess->sess_ops->MaxBurstLength) >=
|
||||
cmd->data_length) ? cmd->data_length :
|
||||
cmd->se_cmd.data_length) ? cmd->se_cmd.data_length :
|
||||
(cmd->seq_end_offset +
|
||||
conn->sess->sess_ops->MaxBurstLength);
|
||||
}
|
||||
@@ -182,13 +182,13 @@ static int iscsit_dataout_check_unsolicited_sequence(
|
||||
if (!conn->sess->sess_ops->DataPDUInOrder)
|
||||
goto out;
|
||||
|
||||
if ((first_burst_len != cmd->data_length) &&
|
||||
if ((first_burst_len != cmd->se_cmd.data_length) &&
|
||||
(first_burst_len != conn->sess->sess_ops->FirstBurstLength)) {
|
||||
pr_err("Unsolicited non-immediate data"
|
||||
" received %u does not equal FirstBurstLength: %u, and"
|
||||
" does not equal ExpXferLen %u.\n", first_burst_len,
|
||||
conn->sess->sess_ops->FirstBurstLength,
|
||||
cmd->data_length);
|
||||
cmd->se_cmd.data_length);
|
||||
transport_send_check_condition_and_sense(&cmd->se_cmd,
|
||||
TCM_INCORRECT_AMOUNT_OF_DATA, 0);
|
||||
return DATAOUT_CANNOT_RECOVER;
|
||||
@@ -201,10 +201,10 @@ static int iscsit_dataout_check_unsolicited_sequence(
|
||||
conn->sess->sess_ops->FirstBurstLength);
|
||||
return DATAOUT_CANNOT_RECOVER;
|
||||
}
|
||||
if (first_burst_len == cmd->data_length) {
|
||||
if (first_burst_len == cmd->se_cmd.data_length) {
|
||||
pr_err("Command ITT: 0x%08x reached"
|
||||
" ExpXferLen: %u, but ISCSI_FLAG_CMD_FINAL is not set. protocol"
|
||||
" error.\n", cmd->init_task_tag, cmd->data_length);
|
||||
" error.\n", cmd->init_task_tag, cmd->se_cmd.data_length);
|
||||
return DATAOUT_CANNOT_RECOVER;
|
||||
}
|
||||
}
|
||||
@@ -294,7 +294,7 @@ static int iscsit_dataout_check_sequence(
|
||||
if ((next_burst_len <
|
||||
conn->sess->sess_ops->MaxBurstLength) &&
|
||||
((cmd->write_data_done + payload_length) <
|
||||
cmd->data_length)) {
|
||||
cmd->se_cmd.data_length)) {
|
||||
pr_err("Command ITT: 0x%08x set ISCSI_FLAG_CMD_FINAL"
|
||||
" before end of DataOUT sequence, protocol"
|
||||
" error.\n", cmd->init_task_tag);
|
||||
@@ -319,7 +319,7 @@ static int iscsit_dataout_check_sequence(
|
||||
return DATAOUT_CANNOT_RECOVER;
|
||||
}
|
||||
if ((cmd->write_data_done + payload_length) ==
|
||||
cmd->data_length) {
|
||||
cmd->se_cmd.data_length) {
|
||||
pr_err("Command ITT: 0x%08x reached"
|
||||
" last DataOUT PDU in sequence but ISCSI_FLAG_"
|
||||
"CMD_FINAL is not set, protocol error.\n",
|
||||
@@ -640,9 +640,12 @@ static int iscsit_dataout_post_crc_passed(
|
||||
|
||||
cmd->write_data_done += payload_length;
|
||||
|
||||
return (cmd->write_data_done == cmd->data_length) ?
|
||||
DATAOUT_SEND_TO_TRANSPORT : (send_r2t) ?
|
||||
DATAOUT_SEND_R2T : DATAOUT_NORMAL;
|
||||
if (cmd->write_data_done == cmd->se_cmd.data_length)
|
||||
return DATAOUT_SEND_TO_TRANSPORT;
|
||||
else if (send_r2t)
|
||||
return DATAOUT_SEND_R2T;
|
||||
else
|
||||
return DATAOUT_NORMAL;
|
||||
}
|
||||
|
||||
static int iscsit_dataout_post_crc_failed(
|
||||
|
||||
@@ -279,11 +279,9 @@ int iscsit_create_recovery_datain_values_datasequenceinorder_no(
|
||||
* seq->first_datasn and seq->last_datasn have not been set.
|
||||
*/
|
||||
if (!seq->sent) {
|
||||
#if 0
|
||||
pr_err("Ignoring non-sent sequence 0x%08x ->"
|
||||
" 0x%08x\n\n", seq->first_datasn,
|
||||
seq->last_datasn);
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -294,11 +292,10 @@ int iscsit_create_recovery_datain_values_datasequenceinorder_no(
|
||||
*/
|
||||
if ((seq->first_datasn < begrun) &&
|
||||
(seq->last_datasn < begrun)) {
|
||||
#if 0
|
||||
pr_err("Pre BegRun sequence 0x%08x ->"
|
||||
" 0x%08x\n", seq->first_datasn,
|
||||
seq->last_datasn);
|
||||
#endif
|
||||
|
||||
read_data_done += cmd->seq_list[i].xfer_len;
|
||||
seq->next_burst_len = seq->pdu_send_order = 0;
|
||||
continue;
|
||||
@@ -309,11 +306,10 @@ int iscsit_create_recovery_datain_values_datasequenceinorder_no(
|
||||
*/
|
||||
if ((seq->first_datasn <= begrun) &&
|
||||
(seq->last_datasn >= begrun)) {
|
||||
#if 0
|
||||
pr_err("Found sequence begrun: 0x%08x in"
|
||||
" 0x%08x -> 0x%08x\n", begrun,
|
||||
seq->first_datasn, seq->last_datasn);
|
||||
#endif
|
||||
|
||||
seq_send_order = seq->seq_send_order;
|
||||
data_sn = seq->first_datasn;
|
||||
seq->next_burst_len = seq->pdu_send_order = 0;
|
||||
@@ -369,10 +365,9 @@ int iscsit_create_recovery_datain_values_datasequenceinorder_no(
|
||||
*/
|
||||
if ((seq->first_datasn > begrun) ||
|
||||
(seq->last_datasn > begrun)) {
|
||||
#if 0
|
||||
pr_err("Post BegRun sequence 0x%08x -> 0x%08x\n",
|
||||
seq->first_datasn, seq->last_datasn);
|
||||
#endif
|
||||
|
||||
seq->next_burst_len = seq->pdu_send_order = 0;
|
||||
continue;
|
||||
}
|
||||
@@ -526,7 +521,7 @@ int iscsit_handle_status_snack(
|
||||
found_cmd = 0;
|
||||
|
||||
spin_lock_bh(&conn->cmd_lock);
|
||||
list_for_each_entry(cmd, &conn->conn_cmd_list, i_list) {
|
||||
list_for_each_entry(cmd, &conn->conn_cmd_list, i_conn_node) {
|
||||
if (cmd->stat_sn == begrun) {
|
||||
found_cmd = 1;
|
||||
break;
|
||||
@@ -987,7 +982,7 @@ int iscsit_execute_cmd(struct iscsi_cmd *cmd, int ooo)
|
||||
return 0;
|
||||
|
||||
iscsit_set_dataout_sequence_values(cmd);
|
||||
iscsit_build_r2ts_for_cmd(cmd, cmd->conn, 0);
|
||||
iscsit_build_r2ts_for_cmd(cmd, cmd->conn, false);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -1121,8 +1116,8 @@ static int iscsit_set_dataout_timeout_values(
|
||||
if (cmd->unsolicited_data) {
|
||||
*offset = 0;
|
||||
*length = (conn->sess->sess_ops->FirstBurstLength >
|
||||
cmd->data_length) ?
|
||||
cmd->data_length :
|
||||
cmd->se_cmd.data_length) ?
|
||||
cmd->se_cmd.data_length :
|
||||
conn->sess->sess_ops->FirstBurstLength;
|
||||
return 0;
|
||||
}
|
||||
@@ -1193,8 +1188,8 @@ static void iscsit_handle_dataout_timeout(unsigned long data)
|
||||
if (conn->sess->sess_ops->DataPDUInOrder) {
|
||||
pdu_offset = cmd->write_data_done;
|
||||
if ((pdu_offset + (conn->sess->sess_ops->MaxBurstLength -
|
||||
cmd->next_burst_len)) > cmd->data_length)
|
||||
pdu_length = (cmd->data_length -
|
||||
cmd->next_burst_len)) > cmd->se_cmd.data_length)
|
||||
pdu_length = (cmd->se_cmd.data_length -
|
||||
cmd->write_data_done);
|
||||
else
|
||||
pdu_length = (conn->sess->sess_ops->MaxBurstLength -
|
||||
|
||||
@@ -138,9 +138,9 @@ void iscsit_free_connection_recovery_entires(struct iscsi_session *sess)
|
||||
|
||||
spin_lock(&cr->conn_recovery_cmd_lock);
|
||||
list_for_each_entry_safe(cmd, cmd_tmp,
|
||||
&cr->conn_recovery_cmd_list, i_list) {
|
||||
&cr->conn_recovery_cmd_list, i_conn_node) {
|
||||
|
||||
list_del(&cmd->i_list);
|
||||
list_del(&cmd->i_conn_node);
|
||||
cmd->conn = NULL;
|
||||
spin_unlock(&cr->conn_recovery_cmd_lock);
|
||||
iscsit_free_cmd(cmd);
|
||||
@@ -160,9 +160,9 @@ void iscsit_free_connection_recovery_entires(struct iscsi_session *sess)
|
||||
|
||||
spin_lock(&cr->conn_recovery_cmd_lock);
|
||||
list_for_each_entry_safe(cmd, cmd_tmp,
|
||||
&cr->conn_recovery_cmd_list, i_list) {
|
||||
&cr->conn_recovery_cmd_list, i_conn_node) {
|
||||
|
||||
list_del(&cmd->i_list);
|
||||
list_del(&cmd->i_conn_node);
|
||||
cmd->conn = NULL;
|
||||
spin_unlock(&cr->conn_recovery_cmd_lock);
|
||||
iscsit_free_cmd(cmd);
|
||||
@@ -220,7 +220,7 @@ int iscsit_remove_cmd_from_connection_recovery(
|
||||
}
|
||||
cr = cmd->cr;
|
||||
|
||||
list_del(&cmd->i_list);
|
||||
list_del(&cmd->i_conn_node);
|
||||
return --cr->cmd_count;
|
||||
}
|
||||
|
||||
@@ -234,7 +234,7 @@ void iscsit_discard_cr_cmds_by_expstatsn(
|
||||
|
||||
spin_lock(&cr->conn_recovery_cmd_lock);
|
||||
list_for_each_entry_safe(cmd, cmd_tmp,
|
||||
&cr->conn_recovery_cmd_list, i_list) {
|
||||
&cr->conn_recovery_cmd_list, i_conn_node) {
|
||||
|
||||
if (((cmd->deferred_i_state != ISTATE_SENT_STATUS) &&
|
||||
(cmd->deferred_i_state != ISTATE_REMOVE)) ||
|
||||
@@ -297,11 +297,11 @@ int iscsit_discard_unacknowledged_ooo_cmdsns_for_conn(struct iscsi_conn *conn)
|
||||
mutex_unlock(&sess->cmdsn_mutex);
|
||||
|
||||
spin_lock_bh(&conn->cmd_lock);
|
||||
list_for_each_entry_safe(cmd, cmd_tmp, &conn->conn_cmd_list, i_list) {
|
||||
list_for_each_entry_safe(cmd, cmd_tmp, &conn->conn_cmd_list, i_conn_node) {
|
||||
if (!(cmd->cmd_flags & ICF_OOO_CMDSN))
|
||||
continue;
|
||||
|
||||
list_del(&cmd->i_list);
|
||||
list_del(&cmd->i_conn_node);
|
||||
|
||||
spin_unlock_bh(&conn->cmd_lock);
|
||||
iscsit_free_cmd(cmd);
|
||||
@@ -339,14 +339,14 @@ int iscsit_prepare_cmds_for_realligance(struct iscsi_conn *conn)
|
||||
/*
|
||||
* Only perform connection recovery on ISCSI_OP_SCSI_CMD or
|
||||
* ISCSI_OP_NOOP_OUT opcodes. For all other opcodes call
|
||||
* list_del(&cmd->i_list); to release the command to the
|
||||
* list_del(&cmd->i_conn_node); to release the command to the
|
||||
* session pool and remove it from the connection's list.
|
||||
*
|
||||
* Also stop the DataOUT timer, which will be restarted after
|
||||
* sending the TMR response.
|
||||
*/
|
||||
spin_lock_bh(&conn->cmd_lock);
|
||||
list_for_each_entry_safe(cmd, cmd_tmp, &conn->conn_cmd_list, i_list) {
|
||||
list_for_each_entry_safe(cmd, cmd_tmp, &conn->conn_cmd_list, i_conn_node) {
|
||||
|
||||
if ((cmd->iscsi_opcode != ISCSI_OP_SCSI_CMD) &&
|
||||
(cmd->iscsi_opcode != ISCSI_OP_NOOP_OUT)) {
|
||||
@@ -355,7 +355,7 @@ int iscsit_prepare_cmds_for_realligance(struct iscsi_conn *conn)
|
||||
" CID: %hu\n", cmd->iscsi_opcode,
|
||||
cmd->init_task_tag, cmd->cmd_sn, conn->cid);
|
||||
|
||||
list_del(&cmd->i_list);
|
||||
list_del(&cmd->i_conn_node);
|
||||
spin_unlock_bh(&conn->cmd_lock);
|
||||
iscsit_free_cmd(cmd);
|
||||
spin_lock_bh(&conn->cmd_lock);
|
||||
@@ -375,7 +375,7 @@ int iscsit_prepare_cmds_for_realligance(struct iscsi_conn *conn)
|
||||
*/
|
||||
if (!(cmd->cmd_flags & ICF_OOO_CMDSN) && !cmd->immediate_cmd &&
|
||||
(cmd->cmd_sn >= conn->sess->exp_cmd_sn)) {
|
||||
list_del(&cmd->i_list);
|
||||
list_del(&cmd->i_conn_node);
|
||||
spin_unlock_bh(&conn->cmd_lock);
|
||||
iscsit_free_cmd(cmd);
|
||||
spin_lock_bh(&conn->cmd_lock);
|
||||
@@ -397,7 +397,7 @@ int iscsit_prepare_cmds_for_realligance(struct iscsi_conn *conn)
|
||||
|
||||
cmd->sess = conn->sess;
|
||||
|
||||
list_del(&cmd->i_list);
|
||||
list_del(&cmd->i_conn_node);
|
||||
spin_unlock_bh(&conn->cmd_lock);
|
||||
|
||||
iscsit_free_all_datain_reqs(cmd);
|
||||
@@ -407,7 +407,7 @@ int iscsit_prepare_cmds_for_realligance(struct iscsi_conn *conn)
|
||||
* Add the struct iscsi_cmd to the connection recovery cmd list
|
||||
*/
|
||||
spin_lock(&cr->conn_recovery_cmd_lock);
|
||||
list_add_tail(&cmd->i_list, &cr->conn_recovery_cmd_list);
|
||||
list_add_tail(&cmd->i_conn_node, &cr->conn_recovery_cmd_list);
|
||||
spin_unlock(&cr->conn_recovery_cmd_lock);
|
||||
|
||||
spin_lock_bh(&conn->cmd_lock);
|
||||
|
||||
@@ -803,14 +803,6 @@ static int iscsi_check_numerical_value(struct iscsi_param *param, char *value_pt
|
||||
|
||||
value = simple_strtoul(value_ptr, &tmpptr, 0);
|
||||
|
||||
/* #warning FIXME: Fix this */
|
||||
#if 0
|
||||
if (strspn(endptr, WHITE_SPACE) != strlen(endptr)) {
|
||||
pr_err("Illegal value \"%s\" for \"%s\".\n",
|
||||
value, param->name);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
if (IS_TYPERANGE_0_TO_2(param)) {
|
||||
if ((value < 0) || (value > 2)) {
|
||||
pr_err("Illegal value for \"%s\", must be"
|
||||
@@ -1045,13 +1037,6 @@ static char *iscsi_check_valuelist_for_support(
|
||||
tmp2 = strchr(acceptor_values, ',');
|
||||
if (tmp2)
|
||||
*tmp2 = '\0';
|
||||
if (!acceptor_values || !proposer_values) {
|
||||
if (tmp1)
|
||||
*tmp1 = ',';
|
||||
if (tmp2)
|
||||
*tmp2 = ',';
|
||||
return NULL;
|
||||
}
|
||||
if (!strcmp(acceptor_values, proposer_values)) {
|
||||
if (tmp2)
|
||||
*tmp2 = ',';
|
||||
@@ -1061,8 +1046,6 @@ static char *iscsi_check_valuelist_for_support(
|
||||
*tmp2++ = ',';
|
||||
|
||||
acceptor_values = tmp2;
|
||||
if (!acceptor_values)
|
||||
break;
|
||||
} while (acceptor_values);
|
||||
if (tmp1)
|
||||
*tmp1++ = ',';
|
||||
|
||||
@@ -24,11 +24,13 @@
|
||||
|
||||
#include "iscsi_target_core.h"
|
||||
#include "iscsi_target_util.h"
|
||||
#include "iscsi_target_tpg.h"
|
||||
#include "iscsi_target_seq_pdu_list.h"
|
||||
|
||||
#define OFFLOAD_BUF_SIZE 32768
|
||||
|
||||
void iscsit_dump_seq_list(struct iscsi_cmd *cmd)
|
||||
#ifdef DEBUG
|
||||
static void iscsit_dump_seq_list(struct iscsi_cmd *cmd)
|
||||
{
|
||||
int i;
|
||||
struct iscsi_seq *seq;
|
||||
@@ -46,7 +48,7 @@ void iscsit_dump_seq_list(struct iscsi_cmd *cmd)
|
||||
}
|
||||
}
|
||||
|
||||
void iscsit_dump_pdu_list(struct iscsi_cmd *cmd)
|
||||
static void iscsit_dump_pdu_list(struct iscsi_cmd *cmd)
|
||||
{
|
||||
int i;
|
||||
struct iscsi_pdu *pdu;
|
||||
@@ -61,6 +63,10 @@ void iscsit_dump_pdu_list(struct iscsi_cmd *cmd)
|
||||
pdu->length, pdu->pdu_send_order, pdu->seq_no);
|
||||
}
|
||||
}
|
||||
#else
|
||||
static void iscsit_dump_seq_list(struct iscsi_cmd *cmd) {}
|
||||
static void iscsit_dump_pdu_list(struct iscsi_cmd *cmd) {}
|
||||
#endif
|
||||
|
||||
static void iscsit_ordered_seq_lists(
|
||||
struct iscsi_cmd *cmd,
|
||||
@@ -135,11 +141,11 @@ redo:
|
||||
seq_count++;
|
||||
continue;
|
||||
}
|
||||
array = kzalloc(seq_count * sizeof(u32), GFP_KERNEL);
|
||||
array = kcalloc(seq_count, sizeof(u32), GFP_KERNEL);
|
||||
if (!array) {
|
||||
pr_err("Unable to allocate memory"
|
||||
" for random array.\n");
|
||||
return -1;
|
||||
return -ENOMEM;
|
||||
}
|
||||
iscsit_create_random_array(array, seq_count);
|
||||
|
||||
@@ -155,11 +161,11 @@ redo:
|
||||
}
|
||||
|
||||
if (seq_count) {
|
||||
array = kzalloc(seq_count * sizeof(u32), GFP_KERNEL);
|
||||
array = kcalloc(seq_count, sizeof(u32), GFP_KERNEL);
|
||||
if (!array) {
|
||||
pr_err("Unable to allocate memory for"
|
||||
" random array.\n");
|
||||
return -1;
|
||||
return -ENOMEM;
|
||||
}
|
||||
iscsit_create_random_array(array, seq_count);
|
||||
|
||||
@@ -187,10 +193,10 @@ static int iscsit_randomize_seq_lists(
|
||||
if (!seq_count)
|
||||
return 0;
|
||||
|
||||
array = kzalloc(seq_count * sizeof(u32), GFP_KERNEL);
|
||||
array = kcalloc(seq_count, sizeof(u32), GFP_KERNEL);
|
||||
if (!array) {
|
||||
pr_err("Unable to allocate memory for random array.\n");
|
||||
return -1;
|
||||
return -ENOMEM;
|
||||
}
|
||||
iscsit_create_random_array(array, seq_count);
|
||||
|
||||
@@ -221,11 +227,10 @@ static void iscsit_determine_counts_for_list(
|
||||
|
||||
if ((bl->type == PDULIST_UNSOLICITED) ||
|
||||
(bl->type == PDULIST_IMMEDIATE_AND_UNSOLICITED))
|
||||
unsolicited_data_length = (cmd->data_length >
|
||||
conn->sess->sess_ops->FirstBurstLength) ?
|
||||
conn->sess->sess_ops->FirstBurstLength : cmd->data_length;
|
||||
unsolicited_data_length = min(cmd->se_cmd.data_length,
|
||||
conn->sess->sess_ops->FirstBurstLength);
|
||||
|
||||
while (offset < cmd->data_length) {
|
||||
while (offset < cmd->se_cmd.data_length) {
|
||||
*pdu_count += 1;
|
||||
|
||||
if (check_immediate) {
|
||||
@@ -239,10 +244,10 @@ static void iscsit_determine_counts_for_list(
|
||||
}
|
||||
if (unsolicited_data_length > 0) {
|
||||
if ((offset + conn->conn_ops->MaxRecvDataSegmentLength)
|
||||
>= cmd->data_length) {
|
||||
>= cmd->se_cmd.data_length) {
|
||||
unsolicited_data_length -=
|
||||
(cmd->data_length - offset);
|
||||
offset += (cmd->data_length - offset);
|
||||
(cmd->se_cmd.data_length - offset);
|
||||
offset += (cmd->se_cmd.data_length - offset);
|
||||
continue;
|
||||
}
|
||||
if ((offset + conn->conn_ops->MaxRecvDataSegmentLength)
|
||||
@@ -263,8 +268,8 @@ static void iscsit_determine_counts_for_list(
|
||||
continue;
|
||||
}
|
||||
if ((offset + conn->conn_ops->MaxRecvDataSegmentLength) >=
|
||||
cmd->data_length) {
|
||||
offset += (cmd->data_length - offset);
|
||||
cmd->se_cmd.data_length) {
|
||||
offset += (cmd->se_cmd.data_length - offset);
|
||||
continue;
|
||||
}
|
||||
if ((burstlength + conn->conn_ops->MaxRecvDataSegmentLength) >=
|
||||
@@ -283,10 +288,10 @@ static void iscsit_determine_counts_for_list(
|
||||
|
||||
|
||||
/*
|
||||
* Builds PDU and/or Sequence list, called while DataSequenceInOrder=No
|
||||
* and DataPDUInOrder=No.
|
||||
* Builds PDU and/or Sequence list, called while DataSequenceInOrder=No
|
||||
* or DataPDUInOrder=No.
|
||||
*/
|
||||
static int iscsit_build_pdu_and_seq_list(
|
||||
static int iscsit_do_build_pdu_and_seq_lists(
|
||||
struct iscsi_cmd *cmd,
|
||||
struct iscsi_build_list *bl)
|
||||
{
|
||||
@@ -306,11 +311,10 @@ static int iscsit_build_pdu_and_seq_list(
|
||||
|
||||
if ((bl->type == PDULIST_UNSOLICITED) ||
|
||||
(bl->type == PDULIST_IMMEDIATE_AND_UNSOLICITED))
|
||||
unsolicited_data_length = (cmd->data_length >
|
||||
conn->sess->sess_ops->FirstBurstLength) ?
|
||||
conn->sess->sess_ops->FirstBurstLength : cmd->data_length;
|
||||
unsolicited_data_length = min(cmd->se_cmd.data_length,
|
||||
conn->sess->sess_ops->FirstBurstLength);
|
||||
|
||||
while (offset < cmd->data_length) {
|
||||
while (offset < cmd->se_cmd.data_length) {
|
||||
pdu_count++;
|
||||
if (!datapduinorder) {
|
||||
pdu[i].offset = offset;
|
||||
@@ -346,21 +350,21 @@ static int iscsit_build_pdu_and_seq_list(
|
||||
if (unsolicited_data_length > 0) {
|
||||
if ((offset +
|
||||
conn->conn_ops->MaxRecvDataSegmentLength) >=
|
||||
cmd->data_length) {
|
||||
cmd->se_cmd.data_length) {
|
||||
if (!datapduinorder) {
|
||||
pdu[i].type = PDUTYPE_UNSOLICITED;
|
||||
pdu[i].length =
|
||||
(cmd->data_length - offset);
|
||||
(cmd->se_cmd.data_length - offset);
|
||||
}
|
||||
if (!datasequenceinorder) {
|
||||
seq[seq_no].type = SEQTYPE_UNSOLICITED;
|
||||
seq[seq_no].pdu_count = pdu_count;
|
||||
seq[seq_no].xfer_len = (burstlength +
|
||||
(cmd->data_length - offset));
|
||||
(cmd->se_cmd.data_length - offset));
|
||||
}
|
||||
unsolicited_data_length -=
|
||||
(cmd->data_length - offset);
|
||||
offset += (cmd->data_length - offset);
|
||||
(cmd->se_cmd.data_length - offset);
|
||||
offset += (cmd->se_cmd.data_length - offset);
|
||||
continue;
|
||||
}
|
||||
if ((offset +
|
||||
@@ -402,18 +406,18 @@ static int iscsit_build_pdu_and_seq_list(
|
||||
continue;
|
||||
}
|
||||
if ((offset + conn->conn_ops->MaxRecvDataSegmentLength) >=
|
||||
cmd->data_length) {
|
||||
cmd->se_cmd.data_length) {
|
||||
if (!datapduinorder) {
|
||||
pdu[i].type = PDUTYPE_NORMAL;
|
||||
pdu[i].length = (cmd->data_length - offset);
|
||||
pdu[i].length = (cmd->se_cmd.data_length - offset);
|
||||
}
|
||||
if (!datasequenceinorder) {
|
||||
seq[seq_no].type = SEQTYPE_NORMAL;
|
||||
seq[seq_no].pdu_count = pdu_count;
|
||||
seq[seq_no].xfer_len = (burstlength +
|
||||
(cmd->data_length - offset));
|
||||
(cmd->se_cmd.data_length - offset));
|
||||
}
|
||||
offset += (cmd->data_length - offset);
|
||||
offset += (cmd->se_cmd.data_length - offset);
|
||||
continue;
|
||||
}
|
||||
if ((burstlength + conn->conn_ops->MaxRecvDataSegmentLength) >=
|
||||
@@ -464,9 +468,8 @@ static int iscsit_build_pdu_and_seq_list(
|
||||
} else
|
||||
iscsit_ordered_seq_lists(cmd, bl->type);
|
||||
}
|
||||
#if 0
|
||||
|
||||
iscsit_dump_seq_list(cmd);
|
||||
#endif
|
||||
}
|
||||
if (!datapduinorder) {
|
||||
if (bl->data_direction & ISCSI_PDU_WRITE) {
|
||||
@@ -484,50 +487,86 @@ static int iscsit_build_pdu_and_seq_list(
|
||||
} else
|
||||
iscsit_ordered_pdu_lists(cmd, bl->type);
|
||||
}
|
||||
#if 0
|
||||
|
||||
iscsit_dump_pdu_list(cmd);
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Only called while DataSequenceInOrder=No or DataPDUInOrder=No.
|
||||
*/
|
||||
int iscsit_do_build_list(
|
||||
int iscsit_build_pdu_and_seq_lists(
|
||||
struct iscsi_cmd *cmd,
|
||||
struct iscsi_build_list *bl)
|
||||
u32 immediate_data_length)
|
||||
{
|
||||
struct iscsi_build_list bl;
|
||||
u32 pdu_count = 0, seq_count = 1;
|
||||
struct iscsi_conn *conn = cmd->conn;
|
||||
struct iscsi_pdu *pdu = NULL;
|
||||
struct iscsi_seq *seq = NULL;
|
||||
|
||||
iscsit_determine_counts_for_list(cmd, bl, &seq_count, &pdu_count);
|
||||
struct iscsi_session *sess = conn->sess;
|
||||
struct iscsi_node_attrib *na;
|
||||
|
||||
/*
|
||||
* Do nothing if no OOO shenanigans
|
||||
*/
|
||||
if (sess->sess_ops->DataSequenceInOrder &&
|
||||
sess->sess_ops->DataPDUInOrder)
|
||||
return 0;
|
||||
|
||||
if (cmd->data_direction == DMA_NONE)
|
||||
return 0;
|
||||
|
||||
na = iscsit_tpg_get_node_attrib(sess);
|
||||
memset(&bl, 0, sizeof(struct iscsi_build_list));
|
||||
|
||||
if (cmd->data_direction == DMA_FROM_DEVICE) {
|
||||
bl.data_direction = ISCSI_PDU_READ;
|
||||
bl.type = PDULIST_NORMAL;
|
||||
if (na->random_datain_pdu_offsets)
|
||||
bl.randomize |= RANDOM_DATAIN_PDU_OFFSETS;
|
||||
if (na->random_datain_seq_offsets)
|
||||
bl.randomize |= RANDOM_DATAIN_SEQ_OFFSETS;
|
||||
} else {
|
||||
bl.data_direction = ISCSI_PDU_WRITE;
|
||||
bl.immediate_data_length = immediate_data_length;
|
||||
if (na->random_r2t_offsets)
|
||||
bl.randomize |= RANDOM_R2T_OFFSETS;
|
||||
|
||||
if (!cmd->immediate_data && !cmd->unsolicited_data)
|
||||
bl.type = PDULIST_NORMAL;
|
||||
else if (cmd->immediate_data && !cmd->unsolicited_data)
|
||||
bl.type = PDULIST_IMMEDIATE;
|
||||
else if (!cmd->immediate_data && cmd->unsolicited_data)
|
||||
bl.type = PDULIST_UNSOLICITED;
|
||||
else if (cmd->immediate_data && cmd->unsolicited_data)
|
||||
bl.type = PDULIST_IMMEDIATE_AND_UNSOLICITED;
|
||||
}
|
||||
|
||||
iscsit_determine_counts_for_list(cmd, &bl, &seq_count, &pdu_count);
|
||||
|
||||
if (!conn->sess->sess_ops->DataSequenceInOrder) {
|
||||
seq = kzalloc(seq_count * sizeof(struct iscsi_seq), GFP_ATOMIC);
|
||||
seq = kcalloc(seq_count, sizeof(struct iscsi_seq), GFP_ATOMIC);
|
||||
if (!seq) {
|
||||
pr_err("Unable to allocate struct iscsi_seq list\n");
|
||||
return -1;
|
||||
return -ENOMEM;
|
||||
}
|
||||
cmd->seq_list = seq;
|
||||
cmd->seq_count = seq_count;
|
||||
}
|
||||
|
||||
if (!conn->sess->sess_ops->DataPDUInOrder) {
|
||||
pdu = kzalloc(pdu_count * sizeof(struct iscsi_pdu), GFP_ATOMIC);
|
||||
pdu = kcalloc(pdu_count, sizeof(struct iscsi_pdu), GFP_ATOMIC);
|
||||
if (!pdu) {
|
||||
pr_err("Unable to allocate struct iscsi_pdu list.\n");
|
||||
kfree(seq);
|
||||
return -1;
|
||||
return -ENOMEM;
|
||||
}
|
||||
cmd->pdu_list = pdu;
|
||||
cmd->pdu_count = pdu_count;
|
||||
}
|
||||
|
||||
return iscsit_build_pdu_and_seq_list(cmd, bl);
|
||||
return iscsit_do_build_pdu_and_seq_lists(cmd, &bl);
|
||||
}
|
||||
|
||||
struct iscsi_pdu *iscsit_get_pdu_holder(
|
||||
@@ -572,13 +611,12 @@ redo:
|
||||
pdu = &cmd->pdu_list[cmd->pdu_start];
|
||||
|
||||
for (i = 0; pdu[i].seq_no != cmd->seq_no; i++) {
|
||||
#if 0
|
||||
pr_debug("pdu[i].seq_no: %d, pdu[i].pdu"
|
||||
"_send_order: %d, pdu[i].offset: %d,"
|
||||
" pdu[i].length: %d\n", pdu[i].seq_no,
|
||||
pdu[i].pdu_send_order, pdu[i].offset,
|
||||
pdu[i].length);
|
||||
#endif
|
||||
|
||||
if (pdu[i].pdu_send_order == cmd->pdu_send_order) {
|
||||
cmd->pdu_send_order++;
|
||||
return &pdu[i];
|
||||
@@ -601,11 +639,11 @@ redo:
|
||||
pr_err("struct iscsi_seq is NULL!\n");
|
||||
return NULL;
|
||||
}
|
||||
#if 0
|
||||
|
||||
pr_debug("seq->pdu_start: %d, seq->pdu_count: %d,"
|
||||
" seq->seq_no: %d\n", seq->pdu_start, seq->pdu_count,
|
||||
seq->seq_no);
|
||||
#endif
|
||||
|
||||
pdu = &cmd->pdu_list[seq->pdu_start];
|
||||
|
||||
if (seq->pdu_send_order == seq->pdu_count) {
|
||||
@@ -645,12 +683,11 @@ struct iscsi_seq *iscsit_get_seq_holder(
|
||||
}
|
||||
|
||||
for (i = 0; i < cmd->seq_count; i++) {
|
||||
#if 0
|
||||
pr_debug("seq_list[i].orig_offset: %d, seq_list[i]."
|
||||
"xfer_len: %d, seq_list[i].seq_no %u\n",
|
||||
cmd->seq_list[i].orig_offset, cmd->seq_list[i].xfer_len,
|
||||
cmd->seq_list[i].seq_no);
|
||||
#endif
|
||||
|
||||
if ((cmd->seq_list[i].orig_offset +
|
||||
cmd->seq_list[i].xfer_len) >=
|
||||
(offset + length))
|
||||
|
||||
@@ -78,7 +78,7 @@ struct iscsi_seq {
|
||||
u32 xfer_len;
|
||||
} ____cacheline_aligned;
|
||||
|
||||
extern int iscsit_do_build_list(struct iscsi_cmd *, struct iscsi_build_list *);
|
||||
extern int iscsit_build_pdu_and_seq_lists(struct iscsi_cmd *, u32);
|
||||
extern struct iscsi_pdu *iscsit_get_pdu_holder(struct iscsi_cmd *, u32, u32);
|
||||
extern struct iscsi_pdu *iscsit_get_pdu_holder_for_seq(struct iscsi_cmd *, struct iscsi_seq *);
|
||||
extern struct iscsi_seq *iscsit_get_seq_holder(struct iscsi_cmd *, u32, u32);
|
||||
|
||||
@@ -78,10 +78,7 @@ int iscsit_tmr_task_warm_reset(
|
||||
{
|
||||
struct iscsi_session *sess = conn->sess;
|
||||
struct iscsi_node_attrib *na = iscsit_tpg_get_node_attrib(sess);
|
||||
#if 0
|
||||
struct iscsi_init_task_mgt_cmnd *hdr =
|
||||
(struct iscsi_init_task_mgt_cmnd *) buf;
|
||||
#endif
|
||||
|
||||
if (!na->tmr_warm_reset) {
|
||||
pr_err("TMR Opcode TARGET_WARM_RESET authorization"
|
||||
" failed for Initiator Node: %s\n",
|
||||
@@ -216,7 +213,7 @@ static int iscsit_task_reassign_complete_nop_out(
|
||||
iscsit_task_reassign_remove_cmd(cmd, cr, conn->sess);
|
||||
|
||||
spin_lock_bh(&conn->cmd_lock);
|
||||
list_add_tail(&cmd->i_list, &conn->conn_cmd_list);
|
||||
list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
|
||||
spin_unlock_bh(&conn->cmd_lock);
|
||||
|
||||
cmd->i_state = ISTATE_SEND_NOPIN;
|
||||
@@ -272,9 +269,9 @@ static int iscsit_task_reassign_complete_write(
|
||||
offset = cmd->next_burst_len = cmd->write_data_done;
|
||||
|
||||
if ((conn->sess->sess_ops->FirstBurstLength - offset) >=
|
||||
cmd->data_length) {
|
||||
cmd->se_cmd.data_length) {
|
||||
no_build_r2ts = 1;
|
||||
length = (cmd->data_length - offset);
|
||||
length = (cmd->se_cmd.data_length - offset);
|
||||
} else
|
||||
length = (conn->sess->sess_ops->FirstBurstLength - offset);
|
||||
|
||||
@@ -292,7 +289,7 @@ static int iscsit_task_reassign_complete_write(
|
||||
/*
|
||||
* iscsit_build_r2ts_for_cmd() can handle the rest from here.
|
||||
*/
|
||||
return iscsit_build_r2ts_for_cmd(cmd, conn, 2);
|
||||
return iscsit_build_r2ts_for_cmd(cmd, conn, true);
|
||||
}
|
||||
|
||||
static int iscsit_task_reassign_complete_read(
|
||||
@@ -385,7 +382,7 @@ static int iscsit_task_reassign_complete_scsi_cmnd(
|
||||
iscsit_task_reassign_remove_cmd(cmd, cr, conn->sess);
|
||||
|
||||
spin_lock_bh(&conn->cmd_lock);
|
||||
list_add_tail(&cmd->i_list, &conn->conn_cmd_list);
|
||||
list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
|
||||
spin_unlock_bh(&conn->cmd_lock);
|
||||
|
||||
if (se_cmd->se_cmd_flags & SCF_SENT_CHECK_CONDITION) {
|
||||
|
||||
@@ -163,7 +163,7 @@ struct iscsi_cmd *iscsit_allocate_cmd(struct iscsi_conn *conn, gfp_t gfp_mask)
|
||||
}
|
||||
|
||||
cmd->conn = conn;
|
||||
INIT_LIST_HEAD(&cmd->i_list);
|
||||
INIT_LIST_HEAD(&cmd->i_conn_node);
|
||||
INIT_LIST_HEAD(&cmd->datain_list);
|
||||
INIT_LIST_HEAD(&cmd->cmd_r2t_list);
|
||||
init_completion(&cmd->reject_comp);
|
||||
@@ -176,174 +176,6 @@ struct iscsi_cmd *iscsit_allocate_cmd(struct iscsi_conn *conn, gfp_t gfp_mask)
|
||||
return cmd;
|
||||
}
|
||||
|
||||
/*
|
||||
* Called from iscsi_handle_scsi_cmd()
|
||||
*/
|
||||
struct iscsi_cmd *iscsit_allocate_se_cmd(
|
||||
struct iscsi_conn *conn,
|
||||
u32 data_length,
|
||||
int data_direction,
|
||||
int iscsi_task_attr)
|
||||
{
|
||||
struct iscsi_cmd *cmd;
|
||||
struct se_cmd *se_cmd;
|
||||
int sam_task_attr;
|
||||
|
||||
cmd = iscsit_allocate_cmd(conn, GFP_KERNEL);
|
||||
if (!cmd)
|
||||
return NULL;
|
||||
|
||||
cmd->data_direction = data_direction;
|
||||
cmd->data_length = data_length;
|
||||
/*
|
||||
* Figure out the SAM Task Attribute for the incoming SCSI CDB
|
||||
*/
|
||||
if ((iscsi_task_attr == ISCSI_ATTR_UNTAGGED) ||
|
||||
(iscsi_task_attr == ISCSI_ATTR_SIMPLE))
|
||||
sam_task_attr = MSG_SIMPLE_TAG;
|
||||
else if (iscsi_task_attr == ISCSI_ATTR_ORDERED)
|
||||
sam_task_attr = MSG_ORDERED_TAG;
|
||||
else if (iscsi_task_attr == ISCSI_ATTR_HEAD_OF_QUEUE)
|
||||
sam_task_attr = MSG_HEAD_TAG;
|
||||
else if (iscsi_task_attr == ISCSI_ATTR_ACA)
|
||||
sam_task_attr = MSG_ACA_TAG;
|
||||
else {
|
||||
pr_debug("Unknown iSCSI Task Attribute: 0x%02x, using"
|
||||
" MSG_SIMPLE_TAG\n", iscsi_task_attr);
|
||||
sam_task_attr = MSG_SIMPLE_TAG;
|
||||
}
|
||||
|
||||
se_cmd = &cmd->se_cmd;
|
||||
/*
|
||||
* Initialize struct se_cmd descriptor from target_core_mod infrastructure
|
||||
*/
|
||||
transport_init_se_cmd(se_cmd, &lio_target_fabric_configfs->tf_ops,
|
||||
conn->sess->se_sess, data_length, data_direction,
|
||||
sam_task_attr, &cmd->sense_buffer[0]);
|
||||
return cmd;
|
||||
}
|
||||
|
||||
struct iscsi_cmd *iscsit_allocate_se_cmd_for_tmr(
|
||||
struct iscsi_conn *conn,
|
||||
u8 function)
|
||||
{
|
||||
struct iscsi_cmd *cmd;
|
||||
struct se_cmd *se_cmd;
|
||||
int rc;
|
||||
u8 tcm_function;
|
||||
|
||||
cmd = iscsit_allocate_cmd(conn, GFP_KERNEL);
|
||||
if (!cmd)
|
||||
return NULL;
|
||||
|
||||
cmd->data_direction = DMA_NONE;
|
||||
|
||||
cmd->tmr_req = kzalloc(sizeof(struct iscsi_tmr_req), GFP_KERNEL);
|
||||
if (!cmd->tmr_req) {
|
||||
pr_err("Unable to allocate memory for"
|
||||
" Task Management command!\n");
|
||||
goto out;
|
||||
}
|
||||
/*
|
||||
* TASK_REASSIGN for ERL=2 / connection stays inside of
|
||||
* LIO-Target $FABRIC_MOD
|
||||
*/
|
||||
if (function == ISCSI_TM_FUNC_TASK_REASSIGN)
|
||||
return cmd;
|
||||
|
||||
se_cmd = &cmd->se_cmd;
|
||||
/*
|
||||
* Initialize struct se_cmd descriptor from target_core_mod infrastructure
|
||||
*/
|
||||
transport_init_se_cmd(se_cmd, &lio_target_fabric_configfs->tf_ops,
|
||||
conn->sess->se_sess, 0, DMA_NONE,
|
||||
MSG_SIMPLE_TAG, &cmd->sense_buffer[0]);
|
||||
|
||||
switch (function) {
|
||||
case ISCSI_TM_FUNC_ABORT_TASK:
|
||||
tcm_function = TMR_ABORT_TASK;
|
||||
break;
|
||||
case ISCSI_TM_FUNC_ABORT_TASK_SET:
|
||||
tcm_function = TMR_ABORT_TASK_SET;
|
||||
break;
|
||||
case ISCSI_TM_FUNC_CLEAR_ACA:
|
||||
tcm_function = TMR_CLEAR_ACA;
|
||||
break;
|
||||
case ISCSI_TM_FUNC_CLEAR_TASK_SET:
|
||||
tcm_function = TMR_CLEAR_TASK_SET;
|
||||
break;
|
||||
case ISCSI_TM_FUNC_LOGICAL_UNIT_RESET:
|
||||
tcm_function = TMR_LUN_RESET;
|
||||
break;
|
||||
case ISCSI_TM_FUNC_TARGET_WARM_RESET:
|
||||
tcm_function = TMR_TARGET_WARM_RESET;
|
||||
break;
|
||||
case ISCSI_TM_FUNC_TARGET_COLD_RESET:
|
||||
tcm_function = TMR_TARGET_COLD_RESET;
|
||||
break;
|
||||
default:
|
||||
pr_err("Unknown iSCSI TMR Function:"
|
||||
" 0x%02x\n", function);
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = core_tmr_alloc_req(se_cmd, cmd->tmr_req, tcm_function, GFP_KERNEL);
|
||||
if (rc < 0)
|
||||
goto out;
|
||||
|
||||
cmd->tmr_req->se_tmr_req = se_cmd->se_tmr_req;
|
||||
|
||||
return cmd;
|
||||
out:
|
||||
iscsit_release_cmd(cmd);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int iscsit_decide_list_to_build(
|
||||
struct iscsi_cmd *cmd,
|
||||
u32 immediate_data_length)
|
||||
{
|
||||
struct iscsi_build_list bl;
|
||||
struct iscsi_conn *conn = cmd->conn;
|
||||
struct iscsi_session *sess = conn->sess;
|
||||
struct iscsi_node_attrib *na;
|
||||
|
||||
if (sess->sess_ops->DataSequenceInOrder &&
|
||||
sess->sess_ops->DataPDUInOrder)
|
||||
return 0;
|
||||
|
||||
if (cmd->data_direction == DMA_NONE)
|
||||
return 0;
|
||||
|
||||
na = iscsit_tpg_get_node_attrib(sess);
|
||||
memset(&bl, 0, sizeof(struct iscsi_build_list));
|
||||
|
||||
if (cmd->data_direction == DMA_FROM_DEVICE) {
|
||||
bl.data_direction = ISCSI_PDU_READ;
|
||||
bl.type = PDULIST_NORMAL;
|
||||
if (na->random_datain_pdu_offsets)
|
||||
bl.randomize |= RANDOM_DATAIN_PDU_OFFSETS;
|
||||
if (na->random_datain_seq_offsets)
|
||||
bl.randomize |= RANDOM_DATAIN_SEQ_OFFSETS;
|
||||
} else {
|
||||
bl.data_direction = ISCSI_PDU_WRITE;
|
||||
bl.immediate_data_length = immediate_data_length;
|
||||
if (na->random_r2t_offsets)
|
||||
bl.randomize |= RANDOM_R2T_OFFSETS;
|
||||
|
||||
if (!cmd->immediate_data && !cmd->unsolicited_data)
|
||||
bl.type = PDULIST_NORMAL;
|
||||
else if (cmd->immediate_data && !cmd->unsolicited_data)
|
||||
bl.type = PDULIST_IMMEDIATE;
|
||||
else if (!cmd->immediate_data && cmd->unsolicited_data)
|
||||
bl.type = PDULIST_UNSOLICITED;
|
||||
else if (cmd->immediate_data && cmd->unsolicited_data)
|
||||
bl.type = PDULIST_IMMEDIATE_AND_UNSOLICITED;
|
||||
}
|
||||
|
||||
return iscsit_do_build_list(cmd, &bl);
|
||||
}
|
||||
|
||||
struct iscsi_seq *iscsit_get_seq_holder_for_datain(
|
||||
struct iscsi_cmd *cmd,
|
||||
u32 seq_send_order)
|
||||
@@ -502,14 +334,14 @@ int iscsit_check_unsolicited_dataout(struct iscsi_cmd *cmd, unsigned char *buf)
|
||||
if (!(hdr->flags & ISCSI_FLAG_CMD_FINAL))
|
||||
return 0;
|
||||
|
||||
if (((cmd->first_burst_len + payload_length) != cmd->data_length) &&
|
||||
if (((cmd->first_burst_len + payload_length) != cmd->se_cmd.data_length) &&
|
||||
((cmd->first_burst_len + payload_length) !=
|
||||
conn->sess->sess_ops->FirstBurstLength)) {
|
||||
pr_err("Unsolicited non-immediate data received %u"
|
||||
" does not equal FirstBurstLength: %u, and does"
|
||||
" not equal ExpXferLen %u.\n",
|
||||
(cmd->first_burst_len + payload_length),
|
||||
conn->sess->sess_ops->FirstBurstLength, cmd->data_length);
|
||||
conn->sess->sess_ops->FirstBurstLength, cmd->se_cmd.data_length);
|
||||
transport_send_check_condition_and_sense(se_cmd,
|
||||
TCM_INCORRECT_AMOUNT_OF_DATA, 0);
|
||||
return -1;
|
||||
@@ -524,7 +356,7 @@ struct iscsi_cmd *iscsit_find_cmd_from_itt(
|
||||
struct iscsi_cmd *cmd;
|
||||
|
||||
spin_lock_bh(&conn->cmd_lock);
|
||||
list_for_each_entry(cmd, &conn->conn_cmd_list, i_list) {
|
||||
list_for_each_entry(cmd, &conn->conn_cmd_list, i_conn_node) {
|
||||
if (cmd->init_task_tag == init_task_tag) {
|
||||
spin_unlock_bh(&conn->cmd_lock);
|
||||
return cmd;
|
||||
@@ -545,7 +377,7 @@ struct iscsi_cmd *iscsit_find_cmd_from_itt_or_dump(
|
||||
struct iscsi_cmd *cmd;
|
||||
|
||||
spin_lock_bh(&conn->cmd_lock);
|
||||
list_for_each_entry(cmd, &conn->conn_cmd_list, i_list) {
|
||||
list_for_each_entry(cmd, &conn->conn_cmd_list, i_conn_node) {
|
||||
if (cmd->init_task_tag == init_task_tag) {
|
||||
spin_unlock_bh(&conn->cmd_lock);
|
||||
return cmd;
|
||||
@@ -568,7 +400,7 @@ struct iscsi_cmd *iscsit_find_cmd_from_ttt(
|
||||
struct iscsi_cmd *cmd = NULL;
|
||||
|
||||
spin_lock_bh(&conn->cmd_lock);
|
||||
list_for_each_entry(cmd, &conn->conn_cmd_list, i_list) {
|
||||
list_for_each_entry(cmd, &conn->conn_cmd_list, i_conn_node) {
|
||||
if (cmd->targ_xfer_tag == targ_xfer_tag) {
|
||||
spin_unlock_bh(&conn->cmd_lock);
|
||||
return cmd;
|
||||
@@ -596,7 +428,7 @@ int iscsit_find_cmd_for_recovery(
|
||||
spin_lock(&sess->cr_i_lock);
|
||||
list_for_each_entry(cr, &sess->cr_inactive_list, cr_list) {
|
||||
spin_lock(&cr->conn_recovery_cmd_lock);
|
||||
list_for_each_entry(cmd, &cr->conn_recovery_cmd_list, i_list) {
|
||||
list_for_each_entry(cmd, &cr->conn_recovery_cmd_list, i_conn_node) {
|
||||
if (cmd->init_task_tag == init_task_tag) {
|
||||
spin_unlock(&cr->conn_recovery_cmd_lock);
|
||||
spin_unlock(&sess->cr_i_lock);
|
||||
@@ -616,7 +448,7 @@ int iscsit_find_cmd_for_recovery(
|
||||
spin_lock(&sess->cr_a_lock);
|
||||
list_for_each_entry(cr, &sess->cr_active_list, cr_list) {
|
||||
spin_lock(&cr->conn_recovery_cmd_lock);
|
||||
list_for_each_entry(cmd, &cr->conn_recovery_cmd_list, i_list) {
|
||||
list_for_each_entry(cmd, &cr->conn_recovery_cmd_list, i_conn_node) {
|
||||
if (cmd->init_task_tag == init_task_tag) {
|
||||
spin_unlock(&cr->conn_recovery_cmd_lock);
|
||||
spin_unlock(&sess->cr_a_lock);
|
||||
@@ -813,7 +645,6 @@ void iscsit_free_queue_reqs_for_conn(struct iscsi_conn *conn)
|
||||
void iscsit_release_cmd(struct iscsi_cmd *cmd)
|
||||
{
|
||||
struct iscsi_conn *conn = cmd->conn;
|
||||
int i;
|
||||
|
||||
iscsit_free_r2ts_from_list(cmd);
|
||||
iscsit_free_all_datain_reqs(cmd);
|
||||
@@ -824,11 +655,6 @@ void iscsit_release_cmd(struct iscsi_cmd *cmd)
|
||||
kfree(cmd->tmr_req);
|
||||
kfree(cmd->iov_data);
|
||||
|
||||
for (i = 0; i < cmd->t_mem_sg_nents; i++)
|
||||
__free_page(sg_page(&cmd->t_mem_sg[i]));
|
||||
|
||||
kfree(cmd->t_mem_sg);
|
||||
|
||||
if (conn) {
|
||||
iscsit_remove_cmd_from_immediate_queue(cmd, conn);
|
||||
iscsit_remove_cmd_from_response_queue(cmd, conn);
|
||||
@@ -1038,7 +864,7 @@ static int iscsit_add_nopin(struct iscsi_conn *conn, int want_response)
|
||||
spin_unlock_bh(&conn->sess->ttt_lock);
|
||||
|
||||
spin_lock_bh(&conn->cmd_lock);
|
||||
list_add_tail(&cmd->i_list, &conn->conn_cmd_list);
|
||||
list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
|
||||
spin_unlock_bh(&conn->cmd_lock);
|
||||
|
||||
if (want_response)
|
||||
|
||||
@@ -9,9 +9,6 @@ extern struct iscsi_r2t *iscsit_get_r2t_from_list(struct iscsi_cmd *);
|
||||
extern void iscsit_free_r2t(struct iscsi_r2t *, struct iscsi_cmd *);
|
||||
extern void iscsit_free_r2ts_from_list(struct iscsi_cmd *);
|
||||
extern struct iscsi_cmd *iscsit_allocate_cmd(struct iscsi_conn *, gfp_t);
|
||||
extern struct iscsi_cmd *iscsit_allocate_se_cmd(struct iscsi_conn *, u32, int, int);
|
||||
extern struct iscsi_cmd *iscsit_allocate_se_cmd_for_tmr(struct iscsi_conn *, u8);
|
||||
extern int iscsit_decide_list_to_build(struct iscsi_cmd *, u32);
|
||||
extern struct iscsi_seq *iscsit_get_seq_holder_for_datain(struct iscsi_cmd *, u32);
|
||||
extern struct iscsi_seq *iscsit_get_seq_holder_for_r2t(struct iscsi_cmd *);
|
||||
extern struct iscsi_r2t *iscsit_get_holder_for_r2tsn(struct iscsi_cmd *, u32);
|
||||
|
||||
@@ -213,7 +213,7 @@ static void tcm_loop_submission_work(struct work_struct *work)
|
||||
* associated read buffers, go ahead and do that here for type
|
||||
* SCF_SCSI_CONTROL_SG_IO_CDB. Also note that this is currently
|
||||
* guaranteed to be a single SGL for SCF_SCSI_CONTROL_SG_IO_CDB
|
||||
* by target core in transport_generic_allocate_tasks() ->
|
||||
* by target core in target_setup_cmd_from_cdb() ->
|
||||
* transport_generic_cmd_sequencer().
|
||||
*/
|
||||
if (se_cmd->se_cmd_flags & SCF_SCSI_CONTROL_SG_IO_CDB &&
|
||||
@@ -227,7 +227,7 @@ static void tcm_loop_submission_work(struct work_struct *work)
|
||||
}
|
||||
}
|
||||
|
||||
ret = transport_generic_allocate_tasks(se_cmd, sc->cmnd);
|
||||
ret = target_setup_cmd_from_cdb(se_cmd, sc->cmnd);
|
||||
if (ret == -ENOMEM) {
|
||||
transport_send_check_condition_and_sense(se_cmd,
|
||||
TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE, 0);
|
||||
|
||||
@@ -59,26 +59,31 @@ struct t10_alua_lu_gp *default_lu_gp;
|
||||
*
|
||||
* See spc4r17 section 6.27
|
||||
*/
|
||||
int target_emulate_report_target_port_groups(struct se_task *task)
|
||||
int target_emulate_report_target_port_groups(struct se_cmd *cmd)
|
||||
{
|
||||
struct se_cmd *cmd = task->task_se_cmd;
|
||||
struct se_subsystem_dev *su_dev = cmd->se_dev->se_sub_dev;
|
||||
struct se_port *port;
|
||||
struct t10_alua_tg_pt_gp *tg_pt_gp;
|
||||
struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem;
|
||||
unsigned char *buf;
|
||||
u32 rd_len = 0, off = 4; /* Skip over RESERVED area to first
|
||||
Target port group descriptor */
|
||||
u32 rd_len = 0, off;
|
||||
int ext_hdr = (cmd->t_task_cdb[1] & 0x20);
|
||||
/*
|
||||
* Need at least 4 bytes of response data or else we can't
|
||||
* even fit the return data length.
|
||||
* Skip over RESERVED area to first Target port group descriptor
|
||||
* depending on the PARAMETER DATA FORMAT type..
|
||||
*/
|
||||
if (cmd->data_length < 4) {
|
||||
pr_warn("REPORT TARGET PORT GROUPS allocation length %u"
|
||||
" too small\n", cmd->data_length);
|
||||
if (ext_hdr != 0)
|
||||
off = 8;
|
||||
else
|
||||
off = 4;
|
||||
|
||||
if (cmd->data_length < off) {
|
||||
pr_warn("REPORT TARGET PORT GROUPS allocation length %u too"
|
||||
" small for %s header\n", cmd->data_length,
|
||||
(ext_hdr) ? "extended" : "normal");
|
||||
cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
buf = transport_kmap_data_sg(cmd);
|
||||
|
||||
spin_lock(&su_dev->t10_alua.tg_pt_gps_lock);
|
||||
@@ -159,15 +164,34 @@ int target_emulate_report_target_port_groups(struct se_task *task)
|
||||
/*
|
||||
* Set the RETURN DATA LENGTH set in the header of the DataIN Payload
|
||||
*/
|
||||
buf[0] = ((rd_len >> 24) & 0xff);
|
||||
buf[1] = ((rd_len >> 16) & 0xff);
|
||||
buf[2] = ((rd_len >> 8) & 0xff);
|
||||
buf[3] = (rd_len & 0xff);
|
||||
put_unaligned_be32(rd_len, &buf[0]);
|
||||
|
||||
/*
|
||||
* Fill in the Extended header parameter data format if requested
|
||||
*/
|
||||
if (ext_hdr != 0) {
|
||||
buf[4] = 0x10;
|
||||
/*
|
||||
* Set the implict transition time (in seconds) for the application
|
||||
* client to use as a base for it's transition timeout value.
|
||||
*
|
||||
* Use the current tg_pt_gp_mem -> tg_pt_gp membership from the LUN
|
||||
* this CDB was received upon to determine this value individually
|
||||
* for ALUA target port group.
|
||||
*/
|
||||
port = cmd->se_lun->lun_sep;
|
||||
tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem;
|
||||
if (tg_pt_gp_mem) {
|
||||
spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
|
||||
tg_pt_gp = tg_pt_gp_mem->tg_pt_gp;
|
||||
if (tg_pt_gp)
|
||||
buf[5] = tg_pt_gp->tg_pt_gp_implict_trans_secs;
|
||||
spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
|
||||
}
|
||||
}
|
||||
transport_kunmap_data_sg(cmd);
|
||||
|
||||
task->task_scsi_status = GOOD;
|
||||
transport_complete_task(task, 1);
|
||||
target_complete_cmd(cmd, GOOD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -176,9 +200,8 @@ int target_emulate_report_target_port_groups(struct se_task *task)
|
||||
*
|
||||
* See spc4r17 section 6.35
|
||||
*/
|
||||
int target_emulate_set_target_port_groups(struct se_task *task)
|
||||
int target_emulate_set_target_port_groups(struct se_cmd *cmd)
|
||||
{
|
||||
struct se_cmd *cmd = task->task_se_cmd;
|
||||
struct se_device *dev = cmd->se_dev;
|
||||
struct se_subsystem_dev *su_dev = dev->se_sub_dev;
|
||||
struct se_port *port, *l_port = cmd->se_lun->lun_sep;
|
||||
@@ -351,8 +374,7 @@ int target_emulate_set_target_port_groups(struct se_task *task)
|
||||
|
||||
out:
|
||||
transport_kunmap_data_sg(cmd);
|
||||
task->task_scsi_status = GOOD;
|
||||
transport_complete_task(task, 1);
|
||||
target_complete_cmd(cmd, GOOD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -391,7 +413,7 @@ static inline int core_alua_state_standby(
|
||||
case RECEIVE_DIAGNOSTIC:
|
||||
case SEND_DIAGNOSTIC:
|
||||
case MAINTENANCE_IN:
|
||||
switch (cdb[1]) {
|
||||
switch (cdb[1] & 0x1f) {
|
||||
case MI_REPORT_TARGET_PGS:
|
||||
return 0;
|
||||
default:
|
||||
@@ -433,7 +455,7 @@ static inline int core_alua_state_unavailable(
|
||||
case INQUIRY:
|
||||
case REPORT_LUNS:
|
||||
case MAINTENANCE_IN:
|
||||
switch (cdb[1]) {
|
||||
switch (cdb[1] & 0x1f) {
|
||||
case MI_REPORT_TARGET_PGS:
|
||||
return 0;
|
||||
default:
|
||||
@@ -473,7 +495,7 @@ static inline int core_alua_state_transition(
|
||||
case INQUIRY:
|
||||
case REPORT_LUNS:
|
||||
case MAINTENANCE_IN:
|
||||
switch (cdb[1]) {
|
||||
switch (cdb[1] & 0x1f) {
|
||||
case MI_REPORT_TARGET_PGS:
|
||||
return 0;
|
||||
default:
|
||||
@@ -1359,6 +1381,7 @@ struct t10_alua_tg_pt_gp *core_alua_allocate_tg_pt_gp(
|
||||
*/
|
||||
tg_pt_gp->tg_pt_gp_nonop_delay_msecs = ALUA_DEFAULT_NONOP_DELAY_MSECS;
|
||||
tg_pt_gp->tg_pt_gp_trans_delay_msecs = ALUA_DEFAULT_TRANS_DELAY_MSECS;
|
||||
tg_pt_gp->tg_pt_gp_implict_trans_secs = ALUA_DEFAULT_IMPLICT_TRANS_SECS;
|
||||
|
||||
if (def_group) {
|
||||
spin_lock(&su_dev->t10_alua.tg_pt_gps_lock);
|
||||
@@ -1855,6 +1878,37 @@ ssize_t core_alua_store_trans_delay_msecs(
|
||||
return count;
|
||||
}
|
||||
|
||||
ssize_t core_alua_show_implict_trans_secs(
|
||||
struct t10_alua_tg_pt_gp *tg_pt_gp,
|
||||
char *page)
|
||||
{
|
||||
return sprintf(page, "%d\n", tg_pt_gp->tg_pt_gp_implict_trans_secs);
|
||||
}
|
||||
|
||||
ssize_t core_alua_store_implict_trans_secs(
|
||||
struct t10_alua_tg_pt_gp *tg_pt_gp,
|
||||
const char *page,
|
||||
size_t count)
|
||||
{
|
||||
unsigned long tmp;
|
||||
int ret;
|
||||
|
||||
ret = strict_strtoul(page, 0, &tmp);
|
||||
if (ret < 0) {
|
||||
pr_err("Unable to extract implict_trans_secs\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (tmp > ALUA_MAX_IMPLICT_TRANS_SECS) {
|
||||
pr_err("Passed implict_trans_secs: %lu, exceeds"
|
||||
" ALUA_MAX_IMPLICT_TRANS_SECS: %d\n", tmp,
|
||||
ALUA_MAX_IMPLICT_TRANS_SECS);
|
||||
return -EINVAL;
|
||||
}
|
||||
tg_pt_gp->tg_pt_gp_implict_trans_secs = (int)tmp;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
ssize_t core_alua_show_preferred_bit(
|
||||
struct t10_alua_tg_pt_gp *tg_pt_gp,
|
||||
char *page)
|
||||
|
||||
@@ -51,6 +51,12 @@
|
||||
*/
|
||||
#define ALUA_DEFAULT_TRANS_DELAY_MSECS 0
|
||||
#define ALUA_MAX_TRANS_DELAY_MSECS 30000 /* 30 seconds */
|
||||
/*
|
||||
* Used for the recommended application client implict transition timeout
|
||||
* in seconds, returned by the REPORT_TARGET_PORT_GROUPS w/ extended header.
|
||||
*/
|
||||
#define ALUA_DEFAULT_IMPLICT_TRANS_SECS 0
|
||||
#define ALUA_MAX_IMPLICT_TRANS_SECS 255
|
||||
/*
|
||||
* Used by core_alua_update_tpg_primary_metadata() and
|
||||
* core_alua_update_tpg_secondary_metadata()
|
||||
@@ -66,8 +72,8 @@ extern struct kmem_cache *t10_alua_lu_gp_mem_cache;
|
||||
extern struct kmem_cache *t10_alua_tg_pt_gp_cache;
|
||||
extern struct kmem_cache *t10_alua_tg_pt_gp_mem_cache;
|
||||
|
||||
extern int target_emulate_report_target_port_groups(struct se_task *);
|
||||
extern int target_emulate_set_target_port_groups(struct se_task *);
|
||||
extern int target_emulate_report_target_port_groups(struct se_cmd *);
|
||||
extern int target_emulate_set_target_port_groups(struct se_cmd *);
|
||||
extern int core_alua_check_nonop_delay(struct se_cmd *);
|
||||
extern int core_alua_do_port_transition(struct t10_alua_tg_pt_gp *,
|
||||
struct se_device *, struct se_port *,
|
||||
@@ -107,6 +113,10 @@ extern ssize_t core_alua_show_trans_delay_msecs(struct t10_alua_tg_pt_gp *,
|
||||
char *);
|
||||
extern ssize_t core_alua_store_trans_delay_msecs(struct t10_alua_tg_pt_gp *,
|
||||
const char *, size_t);
|
||||
extern ssize_t core_alua_show_implict_trans_secs(struct t10_alua_tg_pt_gp *,
|
||||
char *);
|
||||
extern ssize_t core_alua_store_implict_trans_secs(struct t10_alua_tg_pt_gp *,
|
||||
const char *, size_t);
|
||||
extern ssize_t core_alua_show_preferred_bit(struct t10_alua_tg_pt_gp *,
|
||||
char *);
|
||||
extern ssize_t core_alua_store_preferred_bit(struct t10_alua_tg_pt_gp *,
|
||||
|
||||
@@ -432,6 +432,7 @@ static int
|
||||
target_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf)
|
||||
{
|
||||
struct se_device *dev = cmd->se_dev;
|
||||
u32 max_sectors;
|
||||
int have_tp = 0;
|
||||
|
||||
/*
|
||||
@@ -456,7 +457,9 @@ target_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf)
|
||||
/*
|
||||
* Set MAXIMUM TRANSFER LENGTH
|
||||
*/
|
||||
put_unaligned_be32(dev->se_sub_dev->se_dev_attrib.fabric_max_sectors, &buf[8]);
|
||||
max_sectors = min(dev->se_sub_dev->se_dev_attrib.fabric_max_sectors,
|
||||
dev->se_sub_dev->se_dev_attrib.hw_max_sectors);
|
||||
put_unaligned_be32(max_sectors, &buf[8]);
|
||||
|
||||
/*
|
||||
* Set OPTIMAL TRANSFER LENGTH
|
||||
@@ -598,9 +601,8 @@ target_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int target_emulate_inquiry(struct se_task *task)
|
||||
int target_emulate_inquiry(struct se_cmd *cmd)
|
||||
{
|
||||
struct se_cmd *cmd = task->task_se_cmd;
|
||||
struct se_device *dev = cmd->se_dev;
|
||||
struct se_portal_group *tpg = cmd->se_lun->lun_sep->sep_tpg;
|
||||
unsigned char *buf, *map_buf;
|
||||
@@ -664,16 +666,13 @@ out:
|
||||
}
|
||||
transport_kunmap_data_sg(cmd);
|
||||
|
||||
if (!ret) {
|
||||
task->task_scsi_status = GOOD;
|
||||
transport_complete_task(task, 1);
|
||||
}
|
||||
if (!ret)
|
||||
target_complete_cmd(cmd, GOOD);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int target_emulate_readcapacity(struct se_task *task)
|
||||
int target_emulate_readcapacity(struct se_cmd *cmd)
|
||||
{
|
||||
struct se_cmd *cmd = task->task_se_cmd;
|
||||
struct se_device *dev = cmd->se_dev;
|
||||
unsigned char *buf;
|
||||
unsigned long long blocks_long = dev->transport->get_blocks(dev);
|
||||
@@ -697,14 +696,12 @@ int target_emulate_readcapacity(struct se_task *task)
|
||||
|
||||
transport_kunmap_data_sg(cmd);
|
||||
|
||||
task->task_scsi_status = GOOD;
|
||||
transport_complete_task(task, 1);
|
||||
target_complete_cmd(cmd, GOOD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int target_emulate_readcapacity_16(struct se_task *task)
|
||||
int target_emulate_readcapacity_16(struct se_cmd *cmd)
|
||||
{
|
||||
struct se_cmd *cmd = task->task_se_cmd;
|
||||
struct se_device *dev = cmd->se_dev;
|
||||
unsigned char *buf;
|
||||
unsigned long long blocks = dev->transport->get_blocks(dev);
|
||||
@@ -732,8 +729,7 @@ int target_emulate_readcapacity_16(struct se_task *task)
|
||||
|
||||
transport_kunmap_data_sg(cmd);
|
||||
|
||||
task->task_scsi_status = GOOD;
|
||||
transport_complete_task(task, 1);
|
||||
target_complete_cmd(cmd, GOOD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -872,9 +868,8 @@ target_modesense_dpofua(unsigned char *buf, int type)
|
||||
}
|
||||
}
|
||||
|
||||
int target_emulate_modesense(struct se_task *task)
|
||||
int target_emulate_modesense(struct se_cmd *cmd)
|
||||
{
|
||||
struct se_cmd *cmd = task->task_se_cmd;
|
||||
struct se_device *dev = cmd->se_dev;
|
||||
char *cdb = cmd->t_task_cdb;
|
||||
unsigned char *rbuf;
|
||||
@@ -947,14 +942,12 @@ int target_emulate_modesense(struct se_task *task)
|
||||
memcpy(rbuf, buf, offset);
|
||||
transport_kunmap_data_sg(cmd);
|
||||
|
||||
task->task_scsi_status = GOOD;
|
||||
transport_complete_task(task, 1);
|
||||
target_complete_cmd(cmd, GOOD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int target_emulate_request_sense(struct se_task *task)
|
||||
int target_emulate_request_sense(struct se_cmd *cmd)
|
||||
{
|
||||
struct se_cmd *cmd = task->task_se_cmd;
|
||||
unsigned char *cdb = cmd->t_task_cdb;
|
||||
unsigned char *buf;
|
||||
u8 ua_asc = 0, ua_ascq = 0;
|
||||
@@ -1008,8 +1001,7 @@ int target_emulate_request_sense(struct se_task *task)
|
||||
|
||||
end:
|
||||
transport_kunmap_data_sg(cmd);
|
||||
task->task_scsi_status = GOOD;
|
||||
transport_complete_task(task, 1);
|
||||
target_complete_cmd(cmd, GOOD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1017,9 +1009,8 @@ end:
|
||||
* Used for TCM/IBLOCK and TCM/FILEIO for block/blk-lib.c level discard support.
|
||||
* Note this is not used for TCM/pSCSI passthrough
|
||||
*/
|
||||
int target_emulate_unmap(struct se_task *task)
|
||||
int target_emulate_unmap(struct se_cmd *cmd)
|
||||
{
|
||||
struct se_cmd *cmd = task->task_se_cmd;
|
||||
struct se_device *dev = cmd->se_dev;
|
||||
unsigned char *buf, *ptr = NULL;
|
||||
unsigned char *cdb = &cmd->t_task_cdb[0];
|
||||
@@ -1066,10 +1057,8 @@ int target_emulate_unmap(struct se_task *task)
|
||||
|
||||
err:
|
||||
transport_kunmap_data_sg(cmd);
|
||||
if (!ret) {
|
||||
task->task_scsi_status = GOOD;
|
||||
transport_complete_task(task, 1);
|
||||
}
|
||||
if (!ret)
|
||||
target_complete_cmd(cmd, GOOD);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1077,9 +1066,8 @@ err:
|
||||
* Used for TCM/IBLOCK and TCM/FILEIO for block/blk-lib.c level discard support.
|
||||
* Note this is not used for TCM/pSCSI passthrough
|
||||
*/
|
||||
int target_emulate_write_same(struct se_task *task)
|
||||
int target_emulate_write_same(struct se_cmd *cmd)
|
||||
{
|
||||
struct se_cmd *cmd = task->task_se_cmd;
|
||||
struct se_device *dev = cmd->se_dev;
|
||||
sector_t range;
|
||||
sector_t lba = cmd->t_task_lba;
|
||||
@@ -1118,79 +1106,25 @@ int target_emulate_write_same(struct se_task *task)
|
||||
return ret;
|
||||
}
|
||||
|
||||
task->task_scsi_status = GOOD;
|
||||
transport_complete_task(task, 1);
|
||||
target_complete_cmd(cmd, GOOD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int target_emulate_synchronize_cache(struct se_task *task)
|
||||
int target_emulate_synchronize_cache(struct se_cmd *cmd)
|
||||
{
|
||||
struct se_device *dev = task->task_se_cmd->se_dev;
|
||||
struct se_cmd *cmd = task->task_se_cmd;
|
||||
|
||||
if (!dev->transport->do_sync_cache) {
|
||||
if (!cmd->se_dev->transport->do_sync_cache) {
|
||||
pr_err("SYNCHRONIZE_CACHE emulation not supported"
|
||||
" for: %s\n", dev->transport->name);
|
||||
" for: %s\n", cmd->se_dev->transport->name);
|
||||
cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE;
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
dev->transport->do_sync_cache(task);
|
||||
cmd->se_dev->transport->do_sync_cache(cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int target_emulate_noop(struct se_task *task)
|
||||
int target_emulate_noop(struct se_cmd *cmd)
|
||||
{
|
||||
task->task_scsi_status = GOOD;
|
||||
transport_complete_task(task, 1);
|
||||
target_complete_cmd(cmd, GOOD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write a CDB into @cdb that is based on the one the intiator sent us,
|
||||
* but updated to only cover the sectors that the current task handles.
|
||||
*/
|
||||
void target_get_task_cdb(struct se_task *task, unsigned char *cdb)
|
||||
{
|
||||
struct se_cmd *cmd = task->task_se_cmd;
|
||||
unsigned int cdb_len = scsi_command_size(cmd->t_task_cdb);
|
||||
|
||||
memcpy(cdb, cmd->t_task_cdb, cdb_len);
|
||||
if (cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB) {
|
||||
unsigned long long lba = task->task_lba;
|
||||
u32 sectors = task->task_sectors;
|
||||
|
||||
switch (cdb_len) {
|
||||
case 6:
|
||||
/* 21-bit LBA and 8-bit sectors */
|
||||
cdb[1] = (lba >> 16) & 0x1f;
|
||||
cdb[2] = (lba >> 8) & 0xff;
|
||||
cdb[3] = lba & 0xff;
|
||||
cdb[4] = sectors & 0xff;
|
||||
break;
|
||||
case 10:
|
||||
/* 32-bit LBA and 16-bit sectors */
|
||||
put_unaligned_be32(lba, &cdb[2]);
|
||||
put_unaligned_be16(sectors, &cdb[7]);
|
||||
break;
|
||||
case 12:
|
||||
/* 32-bit LBA and 32-bit sectors */
|
||||
put_unaligned_be32(lba, &cdb[2]);
|
||||
put_unaligned_be32(sectors, &cdb[6]);
|
||||
break;
|
||||
case 16:
|
||||
/* 64-bit LBA and 32-bit sectors */
|
||||
put_unaligned_be64(lba, &cdb[2]);
|
||||
put_unaligned_be32(sectors, &cdb[10]);
|
||||
break;
|
||||
case 32:
|
||||
/* 64-bit LBA and 32-bit sectors, extended CDB */
|
||||
put_unaligned_be64(lba, &cdb[12]);
|
||||
put_unaligned_be32(sectors, &cdb[28]);
|
||||
break;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(target_get_task_cdb);
|
||||
|
||||
@@ -683,9 +683,6 @@ SE_DEV_ATTR(block_size, S_IRUGO | S_IWUSR);
|
||||
DEF_DEV_ATTRIB_RO(hw_max_sectors);
|
||||
SE_DEV_ATTR_RO(hw_max_sectors);
|
||||
|
||||
DEF_DEV_ATTRIB(max_sectors);
|
||||
SE_DEV_ATTR(max_sectors, S_IRUGO | S_IWUSR);
|
||||
|
||||
DEF_DEV_ATTRIB(fabric_max_sectors);
|
||||
SE_DEV_ATTR(fabric_max_sectors, S_IRUGO | S_IWUSR);
|
||||
|
||||
@@ -727,7 +724,6 @@ static struct configfs_attribute *target_core_dev_attrib_attrs[] = {
|
||||
&target_core_dev_attrib_hw_block_size.attr,
|
||||
&target_core_dev_attrib_block_size.attr,
|
||||
&target_core_dev_attrib_hw_max_sectors.attr,
|
||||
&target_core_dev_attrib_max_sectors.attr,
|
||||
&target_core_dev_attrib_fabric_max_sectors.attr,
|
||||
&target_core_dev_attrib_optimal_sectors.attr,
|
||||
&target_core_dev_attrib_hw_queue_depth.attr,
|
||||
@@ -2450,6 +2446,26 @@ static ssize_t target_core_alua_tg_pt_gp_store_attr_trans_delay_msecs(
|
||||
|
||||
SE_DEV_ALUA_TG_PT_ATTR(trans_delay_msecs, S_IRUGO | S_IWUSR);
|
||||
|
||||
/*
|
||||
* implict_trans_secs
|
||||
*/
|
||||
static ssize_t target_core_alua_tg_pt_gp_show_attr_implict_trans_secs(
|
||||
struct t10_alua_tg_pt_gp *tg_pt_gp,
|
||||
char *page)
|
||||
{
|
||||
return core_alua_show_implict_trans_secs(tg_pt_gp, page);
|
||||
}
|
||||
|
||||
static ssize_t target_core_alua_tg_pt_gp_store_attr_implict_trans_secs(
|
||||
struct t10_alua_tg_pt_gp *tg_pt_gp,
|
||||
const char *page,
|
||||
size_t count)
|
||||
{
|
||||
return core_alua_store_implict_trans_secs(tg_pt_gp, page, count);
|
||||
}
|
||||
|
||||
SE_DEV_ALUA_TG_PT_ATTR(implict_trans_secs, S_IRUGO | S_IWUSR);
|
||||
|
||||
/*
|
||||
* preferred
|
||||
*/
|
||||
@@ -2574,6 +2590,7 @@ static struct configfs_attribute *target_core_alua_tg_pt_gp_attrs[] = {
|
||||
&target_core_alua_tg_pt_gp_alua_write_metadata.attr,
|
||||
&target_core_alua_tg_pt_gp_nonop_delay_msecs.attr,
|
||||
&target_core_alua_tg_pt_gp_trans_delay_msecs.attr,
|
||||
&target_core_alua_tg_pt_gp_implict_trans_secs.attr,
|
||||
&target_core_alua_tg_pt_gp_preferred.attr,
|
||||
&target_core_alua_tg_pt_gp_tg_pt_gp_id.attr,
|
||||
&target_core_alua_tg_pt_gp_members.attr,
|
||||
|
||||
@@ -643,9 +643,8 @@ void core_dev_unexport(
|
||||
lun->lun_se_dev = NULL;
|
||||
}
|
||||
|
||||
int target_report_luns(struct se_task *se_task)
|
||||
int target_report_luns(struct se_cmd *se_cmd)
|
||||
{
|
||||
struct se_cmd *se_cmd = se_task->task_se_cmd;
|
||||
struct se_dev_entry *deve;
|
||||
struct se_session *se_sess = se_cmd->se_sess;
|
||||
unsigned char *buf;
|
||||
@@ -696,8 +695,7 @@ done:
|
||||
buf[3] = (lun_count & 0xff);
|
||||
transport_kunmap_data_sg(se_cmd);
|
||||
|
||||
se_task->task_scsi_status = GOOD;
|
||||
transport_complete_task(se_task, 1);
|
||||
target_complete_cmd(se_cmd, GOOD);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -878,15 +876,12 @@ void se_dev_set_default_attribs(
|
||||
dev->se_sub_dev->se_dev_attrib.hw_block_size = limits->logical_block_size;
|
||||
dev->se_sub_dev->se_dev_attrib.block_size = limits->logical_block_size;
|
||||
/*
|
||||
* max_sectors is based on subsystem plugin dependent requirements.
|
||||
* Align max_hw_sectors down to PAGE_SIZE I/O transfers
|
||||
*/
|
||||
dev->se_sub_dev->se_dev_attrib.hw_max_sectors = limits->max_hw_sectors;
|
||||
/*
|
||||
* Align max_sectors down to PAGE_SIZE to follow transport_allocate_data_tasks()
|
||||
*/
|
||||
limits->max_sectors = se_dev_align_max_sectors(limits->max_sectors,
|
||||
limits->max_hw_sectors = se_dev_align_max_sectors(limits->max_hw_sectors,
|
||||
limits->logical_block_size);
|
||||
dev->se_sub_dev->se_dev_attrib.max_sectors = limits->max_sectors;
|
||||
dev->se_sub_dev->se_dev_attrib.hw_max_sectors = limits->max_hw_sectors;
|
||||
|
||||
/*
|
||||
* Set fabric_max_sectors, which is reported in block limits
|
||||
* VPD page (B0h).
|
||||
@@ -1170,64 +1165,6 @@ int se_dev_set_queue_depth(struct se_device *dev, u32 queue_depth)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int se_dev_set_max_sectors(struct se_device *dev, u32 max_sectors)
|
||||
{
|
||||
int force = 0; /* Force setting for VDEVS */
|
||||
|
||||
if (atomic_read(&dev->dev_export_obj.obj_access_count)) {
|
||||
pr_err("dev[%p]: Unable to change SE Device"
|
||||
" max_sectors while dev_export_obj: %d count exists\n",
|
||||
dev, atomic_read(&dev->dev_export_obj.obj_access_count));
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!max_sectors) {
|
||||
pr_err("dev[%p]: Illegal ZERO value for"
|
||||
" max_sectors\n", dev);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (max_sectors < DA_STATUS_MAX_SECTORS_MIN) {
|
||||
pr_err("dev[%p]: Passed max_sectors: %u less than"
|
||||
" DA_STATUS_MAX_SECTORS_MIN: %u\n", dev, max_sectors,
|
||||
DA_STATUS_MAX_SECTORS_MIN);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV) {
|
||||
if (max_sectors > dev->se_sub_dev->se_dev_attrib.hw_max_sectors) {
|
||||
pr_err("dev[%p]: Passed max_sectors: %u"
|
||||
" greater than TCM/SE_Device max_sectors:"
|
||||
" %u\n", dev, max_sectors,
|
||||
dev->se_sub_dev->se_dev_attrib.hw_max_sectors);
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
if (!force && (max_sectors >
|
||||
dev->se_sub_dev->se_dev_attrib.hw_max_sectors)) {
|
||||
pr_err("dev[%p]: Passed max_sectors: %u"
|
||||
" greater than TCM/SE_Device max_sectors"
|
||||
": %u, use force=1 to override.\n", dev,
|
||||
max_sectors, dev->se_sub_dev->se_dev_attrib.hw_max_sectors);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (max_sectors > DA_STATUS_MAX_SECTORS_MAX) {
|
||||
pr_err("dev[%p]: Passed max_sectors: %u"
|
||||
" greater than DA_STATUS_MAX_SECTORS_MAX:"
|
||||
" %u\n", dev, max_sectors,
|
||||
DA_STATUS_MAX_SECTORS_MAX);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Align max_sectors down to PAGE_SIZE to follow transport_allocate_data_tasks()
|
||||
*/
|
||||
max_sectors = se_dev_align_max_sectors(max_sectors,
|
||||
dev->se_sub_dev->se_dev_attrib.block_size);
|
||||
|
||||
dev->se_sub_dev->se_dev_attrib.max_sectors = max_sectors;
|
||||
pr_debug("dev[%p]: SE Device max_sectors changed to %u\n",
|
||||
dev, max_sectors);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int se_dev_set_fabric_max_sectors(struct se_device *dev, u32 fabric_max_sectors)
|
||||
{
|
||||
if (atomic_read(&dev->dev_export_obj.obj_access_count)) {
|
||||
@@ -1341,7 +1278,6 @@ struct se_lun *core_dev_add_lun(
|
||||
u32 lun)
|
||||
{
|
||||
struct se_lun *lun_p;
|
||||
u32 lun_access = 0;
|
||||
int rc;
|
||||
|
||||
if (atomic_read(&dev->dev_access_obj.obj_access_count) != 0) {
|
||||
@@ -1354,12 +1290,8 @@ struct se_lun *core_dev_add_lun(
|
||||
if (IS_ERR(lun_p))
|
||||
return lun_p;
|
||||
|
||||
if (dev->dev_flags & DF_READ_ONLY)
|
||||
lun_access = TRANSPORT_LUNFLAGS_READ_ONLY;
|
||||
else
|
||||
lun_access = TRANSPORT_LUNFLAGS_READ_WRITE;
|
||||
|
||||
rc = core_tpg_post_addlun(tpg, lun_p, lun_access, dev);
|
||||
rc = core_tpg_post_addlun(tpg, lun_p,
|
||||
TRANSPORT_LUNFLAGS_READ_WRITE, dev);
|
||||
if (rc < 0)
|
||||
return ERR_PTR(rc);
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user