Skip to content

Commit 13caa8e

Browse files
committed
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
2 parents 831ae3c + 9e20ae3 commit 13caa8e

File tree

8 files changed

+67
-25
lines changed

8 files changed

+67
-25
lines changed

drivers/infiniband/ulp/srpt/ib_srpt.c

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1588,7 +1588,7 @@ static int srpt_build_tskmgmt_rsp(struct srpt_rdma_ch *ch,
15881588
int resp_data_len;
15891589
int resp_len;
15901590

1591-
resp_data_len = (rsp_code == SRP_TSK_MGMT_SUCCESS) ? 0 : 4;
1591+
resp_data_len = 4;
15921592
resp_len = sizeof(*srp_rsp) + resp_data_len;
15931593

15941594
srp_rsp = ioctx->ioctx.buf;
@@ -1600,11 +1600,9 @@ static int srpt_build_tskmgmt_rsp(struct srpt_rdma_ch *ch,
16001600
+ atomic_xchg(&ch->req_lim_delta, 0));
16011601
srp_rsp->tag = tag;
16021602

1603-
if (rsp_code != SRP_TSK_MGMT_SUCCESS) {
1604-
srp_rsp->flags |= SRP_RSP_FLAG_RSPVALID;
1605-
srp_rsp->resp_data_len = cpu_to_be32(resp_data_len);
1606-
srp_rsp->data[3] = rsp_code;
1607-
}
1603+
srp_rsp->flags |= SRP_RSP_FLAG_RSPVALID;
1604+
srp_rsp->resp_data_len = cpu_to_be32(resp_data_len);
1605+
srp_rsp->data[3] = rsp_code;
16081606

16091607
return resp_len;
16101608
}
@@ -2358,6 +2356,8 @@ static void srpt_release_channel_work(struct work_struct *w)
23582356
transport_deregister_session(se_sess);
23592357
ch->sess = NULL;
23602358

2359+
ib_destroy_cm_id(ch->cm_id);
2360+
23612361
srpt_destroy_ch_ib(ch);
23622362

23632363
srpt_free_ioctx_ring((struct srpt_ioctx **)ch->ioctx_ring,
@@ -2368,8 +2368,6 @@ static void srpt_release_channel_work(struct work_struct *w)
23682368
list_del(&ch->list);
23692369
spin_unlock_irq(&sdev->spinlock);
23702370

2371-
ib_destroy_cm_id(ch->cm_id);
2372-
23732371
if (ch->release_done)
23742372
complete(ch->release_done);
23752373

drivers/target/iscsi/iscsi_target.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -753,27 +753,32 @@ static void iscsit_unmap_iovec(struct iscsi_cmd *cmd)
753753

754754
static void iscsit_ack_from_expstatsn(struct iscsi_conn *conn, u32 exp_statsn)
755755
{
756-
struct iscsi_cmd *cmd;
756+
LIST_HEAD(ack_list);
757+
struct iscsi_cmd *cmd, *cmd_p;
757758

758759
conn->exp_statsn = exp_statsn;
759760

760761
if (conn->sess->sess_ops->RDMAExtensions)
761762
return;
762763

763764
spin_lock_bh(&conn->cmd_lock);
764-
list_for_each_entry(cmd, &conn->conn_cmd_list, i_conn_node) {
765+
list_for_each_entry_safe(cmd, cmd_p, &conn->conn_cmd_list, i_conn_node) {
765766
spin_lock(&cmd->istate_lock);
766767
if ((cmd->i_state == ISTATE_SENT_STATUS) &&
767768
iscsi_sna_lt(cmd->stat_sn, exp_statsn)) {
768769
cmd->i_state = ISTATE_REMOVE;
769770
spin_unlock(&cmd->istate_lock);
770-
iscsit_add_cmd_to_immediate_queue(cmd, conn,
771-
cmd->i_state);
771+
list_move_tail(&cmd->i_conn_node, &ack_list);
772772
continue;
773773
}
774774
spin_unlock(&cmd->istate_lock);
775775
}
776776
spin_unlock_bh(&conn->cmd_lock);
777+
778+
list_for_each_entry_safe(cmd, cmd_p, &ack_list, i_conn_node) {
779+
list_del(&cmd->i_conn_node);
780+
iscsit_free_cmd(cmd, false);
781+
}
777782
}
778783

779784
static int iscsit_allocate_iovecs(struct iscsi_cmd *cmd)

drivers/target/iscsi/iscsi_target_nego.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1192,7 +1192,7 @@ int iscsi_target_locate_portal(
11921192
*/
11931193
alloc_tags:
11941194
tag_num = max_t(u32, ISCSIT_MIN_TAGS, queue_depth);
1195-
tag_num += ISCSIT_EXTRA_TAGS;
1195+
tag_num += (tag_num / 2) + ISCSIT_EXTRA_TAGS;
11961196
tag_size = sizeof(struct iscsi_cmd) + conn->conn_transport->priv_size;
11971197

11981198
ret = transport_alloc_session_tags(sess->se_sess, tag_num, tag_size);

drivers/target/iscsi/iscsi_target_util.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -736,7 +736,7 @@ void iscsit_free_cmd(struct iscsi_cmd *cmd, bool shutdown)
736736
* Fallthrough
737737
*/
738738
case ISCSI_OP_SCSI_TMFUNC:
739-
rc = transport_generic_free_cmd(&cmd->se_cmd, 1);
739+
rc = transport_generic_free_cmd(&cmd->se_cmd, shutdown);
740740
if (!rc && shutdown && se_cmd && se_cmd->se_sess) {
741741
__iscsit_free_cmd(cmd, true, shutdown);
742742
target_put_sess_cmd(se_cmd->se_sess, se_cmd);
@@ -752,7 +752,7 @@ void iscsit_free_cmd(struct iscsi_cmd *cmd, bool shutdown)
752752
se_cmd = &cmd->se_cmd;
753753
__iscsit_free_cmd(cmd, true, shutdown);
754754

755-
rc = transport_generic_free_cmd(&cmd->se_cmd, 1);
755+
rc = transport_generic_free_cmd(&cmd->se_cmd, shutdown);
756756
if (!rc && shutdown && se_cmd->se_sess) {
757757
__iscsit_free_cmd(cmd, true, shutdown);
758758
target_put_sess_cmd(se_cmd->se_sess, se_cmd);

drivers/target/target_core_sbc.c

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,16 @@ static sense_reason_t compare_and_write_post(struct se_cmd *cmd)
349349
{
350350
struct se_device *dev = cmd->se_dev;
351351

352-
cmd->se_cmd_flags |= SCF_COMPARE_AND_WRITE_POST;
352+
/*
353+
* Only set SCF_COMPARE_AND_WRITE_POST to force a response fall-through
354+
* within target_complete_ok_work() if the command was successfully
355+
* sent to the backend driver.
356+
*/
357+
spin_lock_irq(&cmd->t_state_lock);
358+
if ((cmd->transport_state & CMD_T_SENT) && !cmd->scsi_status)
359+
cmd->se_cmd_flags |= SCF_COMPARE_AND_WRITE_POST;
360+
spin_unlock_irq(&cmd->t_state_lock);
361+
353362
/*
354363
* Unlock ->caw_sem originally obtained during sbc_compare_and_write()
355364
* before the original READ I/O submission.
@@ -363,7 +372,7 @@ static sense_reason_t compare_and_write_callback(struct se_cmd *cmd)
363372
{
364373
struct se_device *dev = cmd->se_dev;
365374
struct scatterlist *write_sg = NULL, *sg;
366-
unsigned char *buf, *addr;
375+
unsigned char *buf = NULL, *addr;
367376
struct sg_mapping_iter m;
368377
unsigned int offset = 0, len;
369378
unsigned int nlbas = cmd->t_task_nolb;
@@ -378,6 +387,15 @@ static sense_reason_t compare_and_write_callback(struct se_cmd *cmd)
378387
*/
379388
if (!cmd->t_data_sg || !cmd->t_bidi_data_sg)
380389
return TCM_NO_SENSE;
390+
/*
391+
* Immediately exit + release dev->caw_sem if command has already
392+
* been failed with a non-zero SCSI status.
393+
*/
394+
if (cmd->scsi_status) {
395+
pr_err("compare_and_write_callback: non zero scsi_status:"
396+
" 0x%02x\n", cmd->scsi_status);
397+
goto out;
398+
}
381399

382400
buf = kzalloc(cmd->data_length, GFP_KERNEL);
383401
if (!buf) {
@@ -508,6 +526,12 @@ sbc_compare_and_write(struct se_cmd *cmd)
508526
cmd->transport_complete_callback = NULL;
509527
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
510528
}
529+
/*
530+
* Reset cmd->data_length to individual block_size in order to not
531+
* confuse backend drivers that depend on this value matching the
532+
* size of the I/O being submitted.
533+
*/
534+
cmd->data_length = cmd->t_task_nolb * dev->dev_attrib.block_size;
511535

512536
ret = cmd->execute_rw(cmd, cmd->t_bidi_data_sg, cmd->t_bidi_data_nents,
513537
DMA_FROM_DEVICE);

drivers/target/target_core_transport.c

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -236,17 +236,24 @@ int transport_alloc_session_tags(struct se_session *se_sess,
236236
{
237237
int rc;
238238

239-
se_sess->sess_cmd_map = kzalloc(tag_num * tag_size, GFP_KERNEL);
239+
se_sess->sess_cmd_map = kzalloc(tag_num * tag_size,
240+
GFP_KERNEL | __GFP_NOWARN | __GFP_REPEAT);
240241
if (!se_sess->sess_cmd_map) {
241-
pr_err("Unable to allocate se_sess->sess_cmd_map\n");
242-
return -ENOMEM;
242+
se_sess->sess_cmd_map = vzalloc(tag_num * tag_size);
243+
if (!se_sess->sess_cmd_map) {
244+
pr_err("Unable to allocate se_sess->sess_cmd_map\n");
245+
return -ENOMEM;
246+
}
243247
}
244248

245249
rc = percpu_ida_init(&se_sess->sess_tag_pool, tag_num);
246250
if (rc < 0) {
247251
pr_err("Unable to init se_sess->sess_tag_pool,"
248252
" tag_num: %u\n", tag_num);
249-
kfree(se_sess->sess_cmd_map);
253+
if (is_vmalloc_addr(se_sess->sess_cmd_map))
254+
vfree(se_sess->sess_cmd_map);
255+
else
256+
kfree(se_sess->sess_cmd_map);
250257
se_sess->sess_cmd_map = NULL;
251258
return -ENOMEM;
252259
}
@@ -412,7 +419,10 @@ void transport_free_session(struct se_session *se_sess)
412419
{
413420
if (se_sess->sess_cmd_map) {
414421
percpu_ida_destroy(&se_sess->sess_tag_pool);
415-
kfree(se_sess->sess_cmd_map);
422+
if (is_vmalloc_addr(se_sess->sess_cmd_map))
423+
vfree(se_sess->sess_cmd_map);
424+
else
425+
kfree(se_sess->sess_cmd_map);
416426
}
417427
kmem_cache_free(se_sess_cache, se_sess);
418428
}

drivers/target/target_core_xcopy.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -298,8 +298,8 @@ static int target_xcopy_parse_segdesc_02(struct se_cmd *se_cmd, struct xcopy_op
298298
(unsigned long long)xop->dst_lba);
299299

300300
if (dc != 0) {
301-
xop->dbl = (desc[29] << 16) & 0xff;
302-
xop->dbl |= (desc[30] << 8) & 0xff;
301+
xop->dbl = (desc[29] & 0xff) << 16;
302+
xop->dbl |= (desc[30] & 0xff) << 8;
303303
xop->dbl |= desc[31] & 0xff;
304304

305305
pr_debug("XCOPY seg desc 0x02: DC=1 w/ dbl: %u\n", xop->dbl);

drivers/vhost/scsi.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -728,7 +728,12 @@ vhost_scsi_get_tag(struct vhost_virtqueue *vq,
728728
}
729729
se_sess = tv_nexus->tvn_se_sess;
730730

731-
tag = percpu_ida_alloc(&se_sess->sess_tag_pool, GFP_KERNEL);
731+
tag = percpu_ida_alloc(&se_sess->sess_tag_pool, GFP_ATOMIC);
732+
if (tag < 0) {
733+
pr_err("Unable to obtain tag for tcm_vhost_cmd\n");
734+
return ERR_PTR(-ENOMEM);
735+
}
736+
732737
cmd = &((struct tcm_vhost_cmd *)se_sess->sess_cmd_map)[tag];
733738
sg = cmd->tvc_sgl;
734739
pages = cmd->tvc_upages;

0 commit comments

Comments
 (0)