Merge git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending
Pull SCSI target fixes from Nicholas Bellinger: "Here are the outstanding target fixes queued up for v3.12-rc4 code. The highlights include: - Make vhost/scsi tag percpu_ida_alloc() use GFP_ATOMIC - Allow sess_cmd_map allocation failure fallback to use vzalloc - Fix COMPARE_AND_WRITE se_cmd->data_length bug with FILEIO backends - Fixes for COMPARE_AND_WRITE callback recursive failure OOPs + non zero scsi_status bug - Make iscsi-target do acknowledgement tag release from RX context - Setup iscsi-target with extra (cmdsn_depth / 2) percpu_ida tags Also included is a iscsi-target patch CC'ed for v3.10+ that avoids legacy wait_for_task=true release during fast-past StatSN acknowledgement, and two other SRP target related patches that address long-standing issues that are CC'ed for v3.3+. Extra thanks to Thomas Glanzmann for his testing feedback with COMPARE_AND_WRITE + EXTENDED_COPY VAAI logic" * git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending: iscsi-target; Allow an extra tag_num / 2 number of percpu_ida tags iscsi-target: Perform release of acknowledged tags from RX context iscsi-target: Only perform wait_for_tasks when performing shutdown target: Fail on non zero scsi_status in compare_and_write_callback target: Fix recursive COMPARE_AND_WRITE callback failure target: Reset data_length for COMPARE_AND_WRITE to NoLB * block_size ib_srpt: always set response for task management target: Fall back to vzalloc upon ->sess_cmd_map kzalloc failure vhost/scsi: Use GFP_ATOMIC with percpu_ida_alloc for obtaining tag ib_srpt: Destroy cm_id before destroying QP. target: Fix xop->dbl assignment in target_xcopy_parse_segdesc_02
This commit is contained in:
commit
13caa8ed93
8 changed files with 67 additions and 25 deletions
|
@ -1588,7 +1588,7 @@ static int srpt_build_tskmgmt_rsp(struct srpt_rdma_ch *ch,
|
|||
int resp_data_len;
|
||||
int resp_len;
|
||||
|
||||
resp_data_len = (rsp_code == SRP_TSK_MGMT_SUCCESS) ? 0 : 4;
|
||||
resp_data_len = 4;
|
||||
resp_len = sizeof(*srp_rsp) + resp_data_len;
|
||||
|
||||
srp_rsp = ioctx->ioctx.buf;
|
||||
|
@ -1600,11 +1600,9 @@ static int srpt_build_tskmgmt_rsp(struct srpt_rdma_ch *ch,
|
|||
+ atomic_xchg(&ch->req_lim_delta, 0));
|
||||
srp_rsp->tag = tag;
|
||||
|
||||
if (rsp_code != SRP_TSK_MGMT_SUCCESS) {
|
||||
srp_rsp->flags |= SRP_RSP_FLAG_RSPVALID;
|
||||
srp_rsp->resp_data_len = cpu_to_be32(resp_data_len);
|
||||
srp_rsp->data[3] = rsp_code;
|
||||
}
|
||||
srp_rsp->flags |= SRP_RSP_FLAG_RSPVALID;
|
||||
srp_rsp->resp_data_len = cpu_to_be32(resp_data_len);
|
||||
srp_rsp->data[3] = rsp_code;
|
||||
|
||||
return resp_len;
|
||||
}
|
||||
|
@ -2358,6 +2356,8 @@ static void srpt_release_channel_work(struct work_struct *w)
|
|||
transport_deregister_session(se_sess);
|
||||
ch->sess = NULL;
|
||||
|
||||
ib_destroy_cm_id(ch->cm_id);
|
||||
|
||||
srpt_destroy_ch_ib(ch);
|
||||
|
||||
srpt_free_ioctx_ring((struct srpt_ioctx **)ch->ioctx_ring,
|
||||
|
@ -2368,8 +2368,6 @@ static void srpt_release_channel_work(struct work_struct *w)
|
|||
list_del(&ch->list);
|
||||
spin_unlock_irq(&sdev->spinlock);
|
||||
|
||||
ib_destroy_cm_id(ch->cm_id);
|
||||
|
||||
if (ch->release_done)
|
||||
complete(ch->release_done);
|
||||
|
||||
|
|
|
@ -753,7 +753,8 @@ static void iscsit_unmap_iovec(struct iscsi_cmd *cmd)
|
|||
|
||||
static void iscsit_ack_from_expstatsn(struct iscsi_conn *conn, u32 exp_statsn)
|
||||
{
|
||||
struct iscsi_cmd *cmd;
|
||||
LIST_HEAD(ack_list);
|
||||
struct iscsi_cmd *cmd, *cmd_p;
|
||||
|
||||
conn->exp_statsn = exp_statsn;
|
||||
|
||||
|
@ -761,19 +762,23 @@ static void iscsit_ack_from_expstatsn(struct iscsi_conn *conn, u32 exp_statsn)
|
|||
return;
|
||||
|
||||
spin_lock_bh(&conn->cmd_lock);
|
||||
list_for_each_entry(cmd, &conn->conn_cmd_list, i_conn_node) {
|
||||
list_for_each_entry_safe(cmd, cmd_p, &conn->conn_cmd_list, i_conn_node) {
|
||||
spin_lock(&cmd->istate_lock);
|
||||
if ((cmd->i_state == ISTATE_SENT_STATUS) &&
|
||||
iscsi_sna_lt(cmd->stat_sn, exp_statsn)) {
|
||||
cmd->i_state = ISTATE_REMOVE;
|
||||
spin_unlock(&cmd->istate_lock);
|
||||
iscsit_add_cmd_to_immediate_queue(cmd, conn,
|
||||
cmd->i_state);
|
||||
list_move_tail(&cmd->i_conn_node, &ack_list);
|
||||
continue;
|
||||
}
|
||||
spin_unlock(&cmd->istate_lock);
|
||||
}
|
||||
spin_unlock_bh(&conn->cmd_lock);
|
||||
|
||||
list_for_each_entry_safe(cmd, cmd_p, &ack_list, i_conn_node) {
|
||||
list_del(&cmd->i_conn_node);
|
||||
iscsit_free_cmd(cmd, false);
|
||||
}
|
||||
}
|
||||
|
||||
static int iscsit_allocate_iovecs(struct iscsi_cmd *cmd)
|
||||
|
|
|
@ -1192,7 +1192,7 @@ int iscsi_target_locate_portal(
|
|||
*/
|
||||
alloc_tags:
|
||||
tag_num = max_t(u32, ISCSIT_MIN_TAGS, queue_depth);
|
||||
tag_num += ISCSIT_EXTRA_TAGS;
|
||||
tag_num += (tag_num / 2) + ISCSIT_EXTRA_TAGS;
|
||||
tag_size = sizeof(struct iscsi_cmd) + conn->conn_transport->priv_size;
|
||||
|
||||
ret = transport_alloc_session_tags(sess->se_sess, tag_num, tag_size);
|
||||
|
|
|
@ -736,7 +736,7 @@ void iscsit_free_cmd(struct iscsi_cmd *cmd, bool shutdown)
|
|||
* Fallthrough
|
||||
*/
|
||||
case ISCSI_OP_SCSI_TMFUNC:
|
||||
rc = transport_generic_free_cmd(&cmd->se_cmd, 1);
|
||||
rc = transport_generic_free_cmd(&cmd->se_cmd, shutdown);
|
||||
if (!rc && shutdown && se_cmd && se_cmd->se_sess) {
|
||||
__iscsit_free_cmd(cmd, true, shutdown);
|
||||
target_put_sess_cmd(se_cmd->se_sess, se_cmd);
|
||||
|
@ -752,7 +752,7 @@ void iscsit_free_cmd(struct iscsi_cmd *cmd, bool shutdown)
|
|||
se_cmd = &cmd->se_cmd;
|
||||
__iscsit_free_cmd(cmd, true, shutdown);
|
||||
|
||||
rc = transport_generic_free_cmd(&cmd->se_cmd, 1);
|
||||
rc = transport_generic_free_cmd(&cmd->se_cmd, shutdown);
|
||||
if (!rc && shutdown && se_cmd->se_sess) {
|
||||
__iscsit_free_cmd(cmd, true, shutdown);
|
||||
target_put_sess_cmd(se_cmd->se_sess, se_cmd);
|
||||
|
|
|
@ -349,7 +349,16 @@ static sense_reason_t compare_and_write_post(struct se_cmd *cmd)
|
|||
{
|
||||
struct se_device *dev = cmd->se_dev;
|
||||
|
||||
cmd->se_cmd_flags |= SCF_COMPARE_AND_WRITE_POST;
|
||||
/*
|
||||
* Only set SCF_COMPARE_AND_WRITE_POST to force a response fall-through
|
||||
* within target_complete_ok_work() if the command was successfully
|
||||
* sent to the backend driver.
|
||||
*/
|
||||
spin_lock_irq(&cmd->t_state_lock);
|
||||
if ((cmd->transport_state & CMD_T_SENT) && !cmd->scsi_status)
|
||||
cmd->se_cmd_flags |= SCF_COMPARE_AND_WRITE_POST;
|
||||
spin_unlock_irq(&cmd->t_state_lock);
|
||||
|
||||
/*
|
||||
* Unlock ->caw_sem originally obtained during sbc_compare_and_write()
|
||||
* before the original READ I/O submission.
|
||||
|
@ -363,7 +372,7 @@ static sense_reason_t compare_and_write_callback(struct se_cmd *cmd)
|
|||
{
|
||||
struct se_device *dev = cmd->se_dev;
|
||||
struct scatterlist *write_sg = NULL, *sg;
|
||||
unsigned char *buf, *addr;
|
||||
unsigned char *buf = NULL, *addr;
|
||||
struct sg_mapping_iter m;
|
||||
unsigned int offset = 0, len;
|
||||
unsigned int nlbas = cmd->t_task_nolb;
|
||||
|
@ -378,6 +387,15 @@ static sense_reason_t compare_and_write_callback(struct se_cmd *cmd)
|
|||
*/
|
||||
if (!cmd->t_data_sg || !cmd->t_bidi_data_sg)
|
||||
return TCM_NO_SENSE;
|
||||
/*
|
||||
* Immediately exit + release dev->caw_sem if command has already
|
||||
* been failed with a non-zero SCSI status.
|
||||
*/
|
||||
if (cmd->scsi_status) {
|
||||
pr_err("compare_and_write_callback: non zero scsi_status:"
|
||||
" 0x%02x\n", cmd->scsi_status);
|
||||
goto out;
|
||||
}
|
||||
|
||||
buf = kzalloc(cmd->data_length, GFP_KERNEL);
|
||||
if (!buf) {
|
||||
|
@ -508,6 +526,12 @@ sbc_compare_and_write(struct se_cmd *cmd)
|
|||
cmd->transport_complete_callback = NULL;
|
||||
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
|
||||
}
|
||||
/*
|
||||
* Reset cmd->data_length to individual block_size in order to not
|
||||
* confuse backend drivers that depend on this value matching the
|
||||
* size of the I/O being submitted.
|
||||
*/
|
||||
cmd->data_length = cmd->t_task_nolb * dev->dev_attrib.block_size;
|
||||
|
||||
ret = cmd->execute_rw(cmd, cmd->t_bidi_data_sg, cmd->t_bidi_data_nents,
|
||||
DMA_FROM_DEVICE);
|
||||
|
|
|
@ -236,17 +236,24 @@ int transport_alloc_session_tags(struct se_session *se_sess,
|
|||
{
|
||||
int rc;
|
||||
|
||||
se_sess->sess_cmd_map = kzalloc(tag_num * tag_size, GFP_KERNEL);
|
||||
se_sess->sess_cmd_map = kzalloc(tag_num * tag_size,
|
||||
GFP_KERNEL | __GFP_NOWARN | __GFP_REPEAT);
|
||||
if (!se_sess->sess_cmd_map) {
|
||||
pr_err("Unable to allocate se_sess->sess_cmd_map\n");
|
||||
return -ENOMEM;
|
||||
se_sess->sess_cmd_map = vzalloc(tag_num * tag_size);
|
||||
if (!se_sess->sess_cmd_map) {
|
||||
pr_err("Unable to allocate se_sess->sess_cmd_map\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
rc = percpu_ida_init(&se_sess->sess_tag_pool, tag_num);
|
||||
if (rc < 0) {
|
||||
pr_err("Unable to init se_sess->sess_tag_pool,"
|
||||
" tag_num: %u\n", tag_num);
|
||||
kfree(se_sess->sess_cmd_map);
|
||||
if (is_vmalloc_addr(se_sess->sess_cmd_map))
|
||||
vfree(se_sess->sess_cmd_map);
|
||||
else
|
||||
kfree(se_sess->sess_cmd_map);
|
||||
se_sess->sess_cmd_map = NULL;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
@ -412,7 +419,10 @@ void transport_free_session(struct se_session *se_sess)
|
|||
{
|
||||
if (se_sess->sess_cmd_map) {
|
||||
percpu_ida_destroy(&se_sess->sess_tag_pool);
|
||||
kfree(se_sess->sess_cmd_map);
|
||||
if (is_vmalloc_addr(se_sess->sess_cmd_map))
|
||||
vfree(se_sess->sess_cmd_map);
|
||||
else
|
||||
kfree(se_sess->sess_cmd_map);
|
||||
}
|
||||
kmem_cache_free(se_sess_cache, se_sess);
|
||||
}
|
||||
|
|
|
@ -298,8 +298,8 @@ static int target_xcopy_parse_segdesc_02(struct se_cmd *se_cmd, struct xcopy_op
|
|||
(unsigned long long)xop->dst_lba);
|
||||
|
||||
if (dc != 0) {
|
||||
xop->dbl = (desc[29] << 16) & 0xff;
|
||||
xop->dbl |= (desc[30] << 8) & 0xff;
|
||||
xop->dbl = (desc[29] & 0xff) << 16;
|
||||
xop->dbl |= (desc[30] & 0xff) << 8;
|
||||
xop->dbl |= desc[31] & 0xff;
|
||||
|
||||
pr_debug("XCOPY seg desc 0x02: DC=1 w/ dbl: %u\n", xop->dbl);
|
||||
|
|
|
@ -728,7 +728,12 @@ vhost_scsi_get_tag(struct vhost_virtqueue *vq,
|
|||
}
|
||||
se_sess = tv_nexus->tvn_se_sess;
|
||||
|
||||
tag = percpu_ida_alloc(&se_sess->sess_tag_pool, GFP_KERNEL);
|
||||
tag = percpu_ida_alloc(&se_sess->sess_tag_pool, GFP_ATOMIC);
|
||||
if (tag < 0) {
|
||||
pr_err("Unable to obtain tag for tcm_vhost_cmd\n");
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
cmd = &((struct tcm_vhost_cmd *)se_sess->sess_cmd_map)[tag];
|
||||
sg = cmd->tvc_sgl;
|
||||
pages = cmd->tvc_upages;
|
||||
|
|
Loading…
Reference in a new issue