Skip to content

Commit 36511e8

Browse files
committed
Merge git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending
Pull SCSI target fixes from Nicholas Bellinger: - fix tcm-user backend driver expired cmd time processing (agrover) - eliminate kref_put_spinlock_irqsave() for I/O completion (bart) - fix iscsi login kthread failure case hung task regression (nab) - fix COMPARE_AND_WRITE completion use-after-free race (nab) - fix COMPARE_AND_WRITE with SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC non zero SGL offset data corruption. (Jan + Doug) - fix >= v4.4-rc1 regression for tcm_qla2xxx enable configfs attribute (Himanshu + HCH) * git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending: target/stat: print full t10_wwn.model buffer target: fix COMPARE_AND_WRITE non zero SGL offset data corruption qla2xxx: Fix regression introduced by target configFS changes kref: Remove kref_put_spinlock_irqsave() target: Invoke release_cmd() callback without holding a spinlock target: Fix race for SCF_COMPARE_AND_WRITE_POST checking iscsi-target: Fix rx_login_comp hang after login failure iscsi-target: return -ENOMEM instead of -1 in case of failed kmalloc() target/user: Do not set unused fields in tcmu_ops target/user: Fix time calc in expired cmd processing
2 parents 75a29ec + 8f90353 commit 36511e8

File tree

11 files changed

+53
-64
lines changed

11 files changed

+53
-64
lines changed

drivers/scsi/qla2xxx/tcm_qla2xxx.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -902,7 +902,7 @@ static ssize_t tcm_qla2xxx_tpg_fabric_prot_type_show(struct config_item *item,
902902
return sprintf(page, "%d\n", tpg->tpg_attrib.fabric_prot_type);
903903
}
904904

905-
CONFIGFS_ATTR_WO(tcm_qla2xxx_tpg_, enable);
905+
CONFIGFS_ATTR(tcm_qla2xxx_tpg_, enable);
906906
CONFIGFS_ATTR_RO(tcm_qla2xxx_tpg_, dynamic_sessions);
907907
CONFIGFS_ATTR(tcm_qla2xxx_tpg_, fabric_prot_type);
908908

drivers/target/iscsi/iscsi_target.c

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4074,6 +4074,17 @@ static int iscsi_target_rx_opcode(struct iscsi_conn *conn, unsigned char *buf)
40744074
return iscsit_add_reject(conn, ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);
40754075
}
40764076

4077+
static bool iscsi_target_check_conn_state(struct iscsi_conn *conn)
4078+
{
4079+
bool ret;
4080+
4081+
spin_lock_bh(&conn->state_lock);
4082+
ret = (conn->conn_state != TARG_CONN_STATE_LOGGED_IN);
4083+
spin_unlock_bh(&conn->state_lock);
4084+
4085+
return ret;
4086+
}
4087+
40774088
int iscsi_target_rx_thread(void *arg)
40784089
{
40794090
int ret, rc;
@@ -4091,7 +4102,7 @@ int iscsi_target_rx_thread(void *arg)
40914102
* incoming iscsi/tcp socket I/O, and/or failing the connection.
40924103
*/
40934104
rc = wait_for_completion_interruptible(&conn->rx_login_comp);
4094-
if (rc < 0)
4105+
if (rc < 0 || iscsi_target_check_conn_state(conn))
40954106
return 0;
40964107

40974108
if (conn->conn_transport->transport_type == ISCSI_INFINIBAND) {

drivers/target/iscsi/iscsi_target_nego.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,7 @@ static int iscsi_target_do_tx_login_io(struct iscsi_conn *conn, struct iscsi_log
388388
if (login->login_complete) {
389389
if (conn->rx_thread && conn->rx_thread_active) {
390390
send_sig(SIGINT, conn->rx_thread, 1);
391+
complete(&conn->rx_login_comp);
391392
kthread_stop(conn->rx_thread);
392393
}
393394
if (conn->tx_thread && conn->tx_thread_active) {

drivers/target/iscsi/iscsi_target_parameters.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ int iscsi_create_default_params(struct iscsi_param_list **param_list_ptr)
208208
if (!pl) {
209209
pr_err("Unable to allocate memory for"
210210
" struct iscsi_param_list.\n");
211-
return -1 ;
211+
return -ENOMEM;
212212
}
213213
INIT_LIST_HEAD(&pl->param_list);
214214
INIT_LIST_HEAD(&pl->extra_response_list);
@@ -578,7 +578,7 @@ int iscsi_copy_param_list(
578578
param_list = kzalloc(sizeof(struct iscsi_param_list), GFP_KERNEL);
579579
if (!param_list) {
580580
pr_err("Unable to allocate memory for struct iscsi_param_list.\n");
581-
return -1;
581+
return -ENOMEM;
582582
}
583583
INIT_LIST_HEAD(&param_list->param_list);
584584
INIT_LIST_HEAD(&param_list->extra_response_list);
@@ -629,7 +629,7 @@ int iscsi_copy_param_list(
629629

630630
err_out:
631631
iscsi_release_param_list(param_list);
632-
return -1;
632+
return -ENOMEM;
633633
}
634634

635635
static void iscsi_release_extra_responses(struct iscsi_param_list *param_list)
@@ -729,7 +729,7 @@ static int iscsi_add_notunderstood_response(
729729
if (!extra_response) {
730730
pr_err("Unable to allocate memory for"
731731
" struct iscsi_extra_response.\n");
732-
return -1;
732+
return -ENOMEM;
733733
}
734734
INIT_LIST_HEAD(&extra_response->er_list);
735735

@@ -1370,7 +1370,7 @@ int iscsi_decode_text_input(
13701370
tmpbuf = kzalloc(length + 1, GFP_KERNEL);
13711371
if (!tmpbuf) {
13721372
pr_err("Unable to allocate %u + 1 bytes for tmpbuf.\n", length);
1373-
return -1;
1373+
return -ENOMEM;
13741374
}
13751375

13761376
memcpy(tmpbuf, textbuf, length);

drivers/target/target_core_sbc.c

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -371,7 +371,8 @@ sbc_setup_write_same(struct se_cmd *cmd, unsigned char *flags, struct sbc_ops *o
371371
return 0;
372372
}
373373

374-
static sense_reason_t xdreadwrite_callback(struct se_cmd *cmd, bool success)
374+
static sense_reason_t xdreadwrite_callback(struct se_cmd *cmd, bool success,
375+
int *post_ret)
375376
{
376377
unsigned char *buf, *addr;
377378
struct scatterlist *sg;
@@ -437,7 +438,8 @@ sbc_execute_rw(struct se_cmd *cmd)
437438
cmd->data_direction);
438439
}
439440

440-
static sense_reason_t compare_and_write_post(struct se_cmd *cmd, bool success)
441+
static sense_reason_t compare_and_write_post(struct se_cmd *cmd, bool success,
442+
int *post_ret)
441443
{
442444
struct se_device *dev = cmd->se_dev;
443445

@@ -447,8 +449,10 @@ static sense_reason_t compare_and_write_post(struct se_cmd *cmd, bool success)
447449
* sent to the backend driver.
448450
*/
449451
spin_lock_irq(&cmd->t_state_lock);
450-
if ((cmd->transport_state & CMD_T_SENT) && !cmd->scsi_status)
452+
if ((cmd->transport_state & CMD_T_SENT) && !cmd->scsi_status) {
451453
cmd->se_cmd_flags |= SCF_COMPARE_AND_WRITE_POST;
454+
*post_ret = 1;
455+
}
452456
spin_unlock_irq(&cmd->t_state_lock);
453457

454458
/*
@@ -460,7 +464,8 @@ static sense_reason_t compare_and_write_post(struct se_cmd *cmd, bool success)
460464
return TCM_NO_SENSE;
461465
}
462466

463-
static sense_reason_t compare_and_write_callback(struct se_cmd *cmd, bool success)
467+
static sense_reason_t compare_and_write_callback(struct se_cmd *cmd, bool success,
468+
int *post_ret)
464469
{
465470
struct se_device *dev = cmd->se_dev;
466471
struct scatterlist *write_sg = NULL, *sg;
@@ -556,11 +561,11 @@ static sense_reason_t compare_and_write_callback(struct se_cmd *cmd, bool succes
556561

557562
if (block_size < PAGE_SIZE) {
558563
sg_set_page(&write_sg[i], m.page, block_size,
559-
block_size);
564+
m.piter.sg->offset + block_size);
560565
} else {
561566
sg_miter_next(&m);
562567
sg_set_page(&write_sg[i], m.page, block_size,
563-
0);
568+
m.piter.sg->offset);
564569
}
565570
len -= block_size;
566571
i++;

drivers/target/target_core_stat.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ static ssize_t target_stat_lu_prod_show(struct config_item *item, char *page)
246246
char str[sizeof(dev->t10_wwn.model)+1];
247247

248248
/* scsiLuProductId */
249-
for (i = 0; i < sizeof(dev->t10_wwn.vendor); i++)
249+
for (i = 0; i < sizeof(dev->t10_wwn.model); i++)
250250
str[i] = ISPRINT(dev->t10_wwn.model[i]) ?
251251
dev->t10_wwn.model[i] : ' ';
252252
str[i] = '\0';

drivers/target/target_core_tmr.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,9 @@ void core_tmr_abort_task(
130130
if (tmr->ref_task_tag != ref_tag)
131131
continue;
132132

133+
if (!kref_get_unless_zero(&se_cmd->cmd_kref))
134+
continue;
135+
133136
printk("ABORT_TASK: Found referenced %s task_tag: %llu\n",
134137
se_cmd->se_tfo->get_fabric_name(), ref_tag);
135138

@@ -139,13 +142,15 @@ void core_tmr_abort_task(
139142
" skipping\n", ref_tag);
140143
spin_unlock(&se_cmd->t_state_lock);
141144
spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
145+
146+
target_put_sess_cmd(se_cmd);
147+
142148
goto out;
143149
}
144150
se_cmd->transport_state |= CMD_T_ABORTED;
145151
spin_unlock(&se_cmd->t_state_lock);
146152

147153
list_del_init(&se_cmd->se_cmd_list);
148-
kref_get(&se_cmd->cmd_kref);
149154
spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
150155

151156
cancel_work_sync(&se_cmd->work);

drivers/target/target_core_transport.c

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1658,7 +1658,7 @@ bool target_stop_cmd(struct se_cmd *cmd, unsigned long *flags)
16581658
void transport_generic_request_failure(struct se_cmd *cmd,
16591659
sense_reason_t sense_reason)
16601660
{
1661-
int ret = 0;
1661+
int ret = 0, post_ret = 0;
16621662

16631663
pr_debug("-----[ Storage Engine Exception for cmd: %p ITT: 0x%08llx"
16641664
" CDB: 0x%02x\n", cmd, cmd->tag, cmd->t_task_cdb[0]);
@@ -1680,7 +1680,7 @@ void transport_generic_request_failure(struct se_cmd *cmd,
16801680
*/
16811681
if ((cmd->se_cmd_flags & SCF_COMPARE_AND_WRITE) &&
16821682
cmd->transport_complete_callback)
1683-
cmd->transport_complete_callback(cmd, false);
1683+
cmd->transport_complete_callback(cmd, false, &post_ret);
16841684

16851685
switch (sense_reason) {
16861686
case TCM_NON_EXISTENT_LUN:
@@ -2068,11 +2068,13 @@ static void target_complete_ok_work(struct work_struct *work)
20682068
*/
20692069
if (cmd->transport_complete_callback) {
20702070
sense_reason_t rc;
2071+
bool caw = (cmd->se_cmd_flags & SCF_COMPARE_AND_WRITE);
2072+
bool zero_dl = !(cmd->data_length);
2073+
int post_ret = 0;
20712074

2072-
rc = cmd->transport_complete_callback(cmd, true);
2073-
if (!rc && !(cmd->se_cmd_flags & SCF_COMPARE_AND_WRITE_POST)) {
2074-
if ((cmd->se_cmd_flags & SCF_COMPARE_AND_WRITE) &&
2075-
!cmd->data_length)
2075+
rc = cmd->transport_complete_callback(cmd, true, &post_ret);
2076+
if (!rc && !post_ret) {
2077+
if (caw && zero_dl)
20762078
goto queue_rsp;
20772079

20782080
return;
@@ -2507,23 +2509,24 @@ int target_get_sess_cmd(struct se_cmd *se_cmd, bool ack_kref)
25072509
EXPORT_SYMBOL(target_get_sess_cmd);
25082510

25092511
static void target_release_cmd_kref(struct kref *kref)
2510-
__releases(&se_cmd->se_sess->sess_cmd_lock)
25112512
{
25122513
struct se_cmd *se_cmd = container_of(kref, struct se_cmd, cmd_kref);
25132514
struct se_session *se_sess = se_cmd->se_sess;
2515+
unsigned long flags;
25142516

2517+
spin_lock_irqsave(&se_sess->sess_cmd_lock, flags);
25152518
if (list_empty(&se_cmd->se_cmd_list)) {
2516-
spin_unlock(&se_sess->sess_cmd_lock);
2519+
spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
25172520
se_cmd->se_tfo->release_cmd(se_cmd);
25182521
return;
25192522
}
25202523
if (se_sess->sess_tearing_down && se_cmd->cmd_wait_set) {
2521-
spin_unlock(&se_sess->sess_cmd_lock);
2524+
spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
25222525
complete(&se_cmd->cmd_wait_comp);
25232526
return;
25242527
}
25252528
list_del(&se_cmd->se_cmd_list);
2526-
spin_unlock(&se_sess->sess_cmd_lock);
2529+
spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
25272530

25282531
se_cmd->se_tfo->release_cmd(se_cmd);
25292532
}
@@ -2539,8 +2542,7 @@ int target_put_sess_cmd(struct se_cmd *se_cmd)
25392542
se_cmd->se_tfo->release_cmd(se_cmd);
25402543
return 1;
25412544
}
2542-
return kref_put_spinlock_irqsave(&se_cmd->cmd_kref, target_release_cmd_kref,
2543-
&se_sess->sess_cmd_lock);
2545+
return kref_put(&se_cmd->cmd_kref, target_release_cmd_kref);
25442546
}
25452547
EXPORT_SYMBOL(target_put_sess_cmd);
25462548

drivers/target/target_core_user.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -638,7 +638,7 @@ static int tcmu_check_expired_cmd(int id, void *p, void *data)
638638
if (test_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags))
639639
return 0;
640640

641-
if (!time_after(cmd->deadline, jiffies))
641+
if (!time_after(jiffies, cmd->deadline))
642642
return 0;
643643

644644
set_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags);
@@ -1101,8 +1101,6 @@ tcmu_parse_cdb(struct se_cmd *cmd)
11011101

11021102
static const struct target_backend_ops tcmu_ops = {
11031103
.name = "user",
1104-
.inquiry_prod = "USER",
1105-
.inquiry_rev = TCMU_VERSION,
11061104
.owner = THIS_MODULE,
11071105
.transport_flags = TRANSPORT_FLAG_PASSTHROUGH,
11081106
.attach_hba = tcmu_attach_hba,

include/linux/kref.h

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
#include <linux/atomic.h>
2020
#include <linux/kernel.h>
2121
#include <linux/mutex.h>
22-
#include <linux/spinlock.h>
2322

2423
struct kref {
2524
atomic_t refcount;
@@ -99,38 +98,6 @@ static inline int kref_put(struct kref *kref, void (*release)(struct kref *kref)
9998
return kref_sub(kref, 1, release);
10099
}
101100

102-
/**
103-
* kref_put_spinlock_irqsave - decrement refcount for object.
104-
* @kref: object.
105-
* @release: pointer to the function that will clean up the object when the
106-
* last reference to the object is released.
107-
* This pointer is required, and it is not acceptable to pass kfree
108-
* in as this function.
109-
* @lock: lock to take in release case
110-
*
111-
* Behaves identical to kref_put with one exception. If the reference count
112-
* drops to zero, the lock will be taken atomically wrt dropping the reference
113-
* count. The release function has to call spin_unlock() without _irqrestore.
114-
*/
115-
static inline int kref_put_spinlock_irqsave(struct kref *kref,
116-
void (*release)(struct kref *kref),
117-
spinlock_t *lock)
118-
{
119-
unsigned long flags;
120-
121-
WARN_ON(release == NULL);
122-
if (atomic_add_unless(&kref->refcount, -1, 1))
123-
return 0;
124-
spin_lock_irqsave(lock, flags);
125-
if (atomic_dec_and_test(&kref->refcount)) {
126-
release(kref);
127-
local_irq_restore(flags);
128-
return 1;
129-
}
130-
spin_unlock_irqrestore(lock, flags);
131-
return 0;
132-
}
133-
134101
static inline int kref_put_mutex(struct kref *kref,
135102
void (*release)(struct kref *kref),
136103
struct mutex *lock)

include/target/target_core_base.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -474,7 +474,7 @@ struct se_cmd {
474474
struct completion cmd_wait_comp;
475475
const struct target_core_fabric_ops *se_tfo;
476476
sense_reason_t (*execute_cmd)(struct se_cmd *);
477-
sense_reason_t (*transport_complete_callback)(struct se_cmd *, bool);
477+
sense_reason_t (*transport_complete_callback)(struct se_cmd *, bool, int *);
478478
void *protocol_data;
479479

480480
unsigned char *t_task_cdb;

0 commit comments

Comments
 (0)