aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-11-29 12:03:57 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2015-11-29 12:03:57 -0500
commit36511e86079c57077493a07be60b39376d7cea74 (patch)
tree32803a94b1c33ad352943fd8e62d77b71c31259f
parent75a29ec1e833de4aeac21ef60e20f9ecf822d481 (diff)
parent8f90353950b2da8d877c6ac3dde5e1109257a117 (diff)
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
-rw-r--r--drivers/scsi/qla2xxx/tcm_qla2xxx.c2
-rw-r--r--drivers/target/iscsi/iscsi_target.c13
-rw-r--r--drivers/target/iscsi/iscsi_target_nego.c1
-rw-r--r--drivers/target/iscsi/iscsi_target_parameters.c10
-rw-r--r--drivers/target/target_core_sbc.c17
-rw-r--r--drivers/target/target_core_stat.c2
-rw-r--r--drivers/target/target_core_tmr.c7
-rw-r--r--drivers/target/target_core_transport.c26
-rw-r--r--drivers/target/target_core_user.c4
-rw-r--r--include/linux/kref.h33
-rw-r--r--include/target/target_core_base.h2
11 files changed, 53 insertions, 64 deletions
diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
index 3ba2e9564b9a..81af294f15a7 100644
--- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c
+++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
@@ -902,7 +902,7 @@ static ssize_t tcm_qla2xxx_tpg_fabric_prot_type_show(struct config_item *item,
902 return sprintf(page, "%d\n", tpg->tpg_attrib.fabric_prot_type); 902 return sprintf(page, "%d\n", tpg->tpg_attrib.fabric_prot_type);
903} 903}
904 904
905CONFIGFS_ATTR_WO(tcm_qla2xxx_tpg_, enable); 905CONFIGFS_ATTR(tcm_qla2xxx_tpg_, enable);
906CONFIGFS_ATTR_RO(tcm_qla2xxx_tpg_, dynamic_sessions); 906CONFIGFS_ATTR_RO(tcm_qla2xxx_tpg_, dynamic_sessions);
907CONFIGFS_ATTR(tcm_qla2xxx_tpg_, fabric_prot_type); 907CONFIGFS_ATTR(tcm_qla2xxx_tpg_, fabric_prot_type);
908 908
diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c
index 342a07c58d89..72204fbf2bb1 100644
--- a/drivers/target/iscsi/iscsi_target.c
+++ b/drivers/target/iscsi/iscsi_target.c
@@ -4074,6 +4074,17 @@ reject:
4074 return iscsit_add_reject(conn, ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf); 4074 return iscsit_add_reject(conn, ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf);
4075} 4075}
4076 4076
4077static 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
4077int iscsi_target_rx_thread(void *arg) 4088int iscsi_target_rx_thread(void *arg)
4078{ 4089{
4079 int ret, rc; 4090 int ret, rc;
@@ -4091,7 +4102,7 @@ int iscsi_target_rx_thread(void *arg)
4091 * incoming iscsi/tcp socket I/O, and/or failing the connection. 4102 * incoming iscsi/tcp socket I/O, and/or failing the connection.
4092 */ 4103 */
4093 rc = wait_for_completion_interruptible(&conn->rx_login_comp); 4104 rc = wait_for_completion_interruptible(&conn->rx_login_comp);
4094 if (rc < 0) 4105 if (rc < 0 || iscsi_target_check_conn_state(conn))
4095 return 0; 4106 return 0;
4096 4107
4097 if (conn->conn_transport->transport_type == ISCSI_INFINIBAND) { 4108 if (conn->conn_transport->transport_type == ISCSI_INFINIBAND) {
diff --git a/drivers/target/iscsi/iscsi_target_nego.c b/drivers/target/iscsi/iscsi_target_nego.c
index 5c964c09c89f..9fc9117d0f22 100644
--- a/drivers/target/iscsi/iscsi_target_nego.c
+++ b/drivers/target/iscsi/iscsi_target_nego.c
@@ -388,6 +388,7 @@ err:
388 if (login->login_complete) { 388 if (login->login_complete) {
389 if (conn->rx_thread && conn->rx_thread_active) { 389 if (conn->rx_thread && conn->rx_thread_active) {
390 send_sig(SIGINT, conn->rx_thread, 1); 390 send_sig(SIGINT, conn->rx_thread, 1);
391 complete(&conn->rx_login_comp);
391 kthread_stop(conn->rx_thread); 392 kthread_stop(conn->rx_thread);
392 } 393 }
393 if (conn->tx_thread && conn->tx_thread_active) { 394 if (conn->tx_thread && conn->tx_thread_active) {
diff --git a/drivers/target/iscsi/iscsi_target_parameters.c b/drivers/target/iscsi/iscsi_target_parameters.c
index 51d1734d5390..2cbea2af7cd0 100644
--- a/drivers/target/iscsi/iscsi_target_parameters.c
+++ b/drivers/target/iscsi/iscsi_target_parameters.c
@@ -208,7 +208,7 @@ int iscsi_create_default_params(struct iscsi_param_list **param_list_ptr)
208 if (!pl) { 208 if (!pl) {
209 pr_err("Unable to allocate memory for" 209 pr_err("Unable to allocate memory for"
210 " struct iscsi_param_list.\n"); 210 " struct iscsi_param_list.\n");
211 return -1 ; 211 return -ENOMEM;
212 } 212 }
213 INIT_LIST_HEAD(&pl->param_list); 213 INIT_LIST_HEAD(&pl->param_list);
214 INIT_LIST_HEAD(&pl->extra_response_list); 214 INIT_LIST_HEAD(&pl->extra_response_list);
@@ -578,7 +578,7 @@ int iscsi_copy_param_list(
578 param_list = kzalloc(sizeof(struct iscsi_param_list), GFP_KERNEL); 578 param_list = kzalloc(sizeof(struct iscsi_param_list), GFP_KERNEL);
579 if (!param_list) { 579 if (!param_list) {
580 pr_err("Unable to allocate memory for struct iscsi_param_list.\n"); 580 pr_err("Unable to allocate memory for struct iscsi_param_list.\n");
581 return -1; 581 return -ENOMEM;
582 } 582 }
583 INIT_LIST_HEAD(&param_list->param_list); 583 INIT_LIST_HEAD(&param_list->param_list);
584 INIT_LIST_HEAD(&param_list->extra_response_list); 584 INIT_LIST_HEAD(&param_list->extra_response_list);
@@ -629,7 +629,7 @@ int iscsi_copy_param_list(
629 629
630err_out: 630err_out:
631 iscsi_release_param_list(param_list); 631 iscsi_release_param_list(param_list);
632 return -1; 632 return -ENOMEM;
633} 633}
634 634
635static void iscsi_release_extra_responses(struct iscsi_param_list *param_list) 635static void iscsi_release_extra_responses(struct iscsi_param_list *param_list)
@@ -729,7 +729,7 @@ static int iscsi_add_notunderstood_response(
729 if (!extra_response) { 729 if (!extra_response) {
730 pr_err("Unable to allocate memory for" 730 pr_err("Unable to allocate memory for"
731 " struct iscsi_extra_response.\n"); 731 " struct iscsi_extra_response.\n");
732 return -1; 732 return -ENOMEM;
733 } 733 }
734 INIT_LIST_HEAD(&extra_response->er_list); 734 INIT_LIST_HEAD(&extra_response->er_list);
735 735
@@ -1370,7 +1370,7 @@ int iscsi_decode_text_input(
1370 tmpbuf = kzalloc(length + 1, GFP_KERNEL); 1370 tmpbuf = kzalloc(length + 1, GFP_KERNEL);
1371 if (!tmpbuf) { 1371 if (!tmpbuf) {
1372 pr_err("Unable to allocate %u + 1 bytes for tmpbuf.\n", length); 1372 pr_err("Unable to allocate %u + 1 bytes for tmpbuf.\n", length);
1373 return -1; 1373 return -ENOMEM;
1374 } 1374 }
1375 1375
1376 memcpy(tmpbuf, textbuf, length); 1376 memcpy(tmpbuf, textbuf, length);
diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c
index 0b4b2a67d9f9..98698d875742 100644
--- a/drivers/target/target_core_sbc.c
+++ b/drivers/target/target_core_sbc.c
@@ -371,7 +371,8 @@ sbc_setup_write_same(struct se_cmd *cmd, unsigned char *flags, struct sbc_ops *o
371 return 0; 371 return 0;
372} 372}
373 373
374static sense_reason_t xdreadwrite_callback(struct se_cmd *cmd, bool success) 374static sense_reason_t xdreadwrite_callback(struct se_cmd *cmd, bool success,
375 int *post_ret)
375{ 376{
376 unsigned char *buf, *addr; 377 unsigned char *buf, *addr;
377 struct scatterlist *sg; 378 struct scatterlist *sg;
@@ -437,7 +438,8 @@ sbc_execute_rw(struct se_cmd *cmd)
437 cmd->data_direction); 438 cmd->data_direction);
438} 439}
439 440
440static sense_reason_t compare_and_write_post(struct se_cmd *cmd, bool success) 441static sense_reason_t compare_and_write_post(struct se_cmd *cmd, bool success,
442 int *post_ret)
441{ 443{
442 struct se_device *dev = cmd->se_dev; 444 struct se_device *dev = cmd->se_dev;
443 445
@@ -447,8 +449,10 @@ static sense_reason_t compare_and_write_post(struct se_cmd *cmd, bool success)
447 * sent to the backend driver. 449 * sent to the backend driver.
448 */ 450 */
449 spin_lock_irq(&cmd->t_state_lock); 451 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) {
451 cmd->se_cmd_flags |= SCF_COMPARE_AND_WRITE_POST; 453 cmd->se_cmd_flags |= SCF_COMPARE_AND_WRITE_POST;
454 *post_ret = 1;
455 }
452 spin_unlock_irq(&cmd->t_state_lock); 456 spin_unlock_irq(&cmd->t_state_lock);
453 457
454 /* 458 /*
@@ -460,7 +464,8 @@ static sense_reason_t compare_and_write_post(struct se_cmd *cmd, bool success)
460 return TCM_NO_SENSE; 464 return TCM_NO_SENSE;
461} 465}
462 466
463static sense_reason_t compare_and_write_callback(struct se_cmd *cmd, bool success) 467static sense_reason_t compare_and_write_callback(struct se_cmd *cmd, bool success,
468 int *post_ret)
464{ 469{
465 struct se_device *dev = cmd->se_dev; 470 struct se_device *dev = cmd->se_dev;
466 struct scatterlist *write_sg = NULL, *sg; 471 struct scatterlist *write_sg = NULL, *sg;
@@ -556,11 +561,11 @@ static sense_reason_t compare_and_write_callback(struct se_cmd *cmd, bool succes
556 561
557 if (block_size < PAGE_SIZE) { 562 if (block_size < PAGE_SIZE) {
558 sg_set_page(&write_sg[i], m.page, block_size, 563 sg_set_page(&write_sg[i], m.page, block_size,
559 block_size); 564 m.piter.sg->offset + block_size);
560 } else { 565 } else {
561 sg_miter_next(&m); 566 sg_miter_next(&m);
562 sg_set_page(&write_sg[i], m.page, block_size, 567 sg_set_page(&write_sg[i], m.page, block_size,
563 0); 568 m.piter.sg->offset);
564 } 569 }
565 len -= block_size; 570 len -= block_size;
566 i++; 571 i++;
diff --git a/drivers/target/target_core_stat.c b/drivers/target/target_core_stat.c
index 273c72b2b83d..81a6b3e07687 100644
--- a/drivers/target/target_core_stat.c
+++ b/drivers/target/target_core_stat.c
@@ -246,7 +246,7 @@ static ssize_t target_stat_lu_prod_show(struct config_item *item, char *page)
246 char str[sizeof(dev->t10_wwn.model)+1]; 246 char str[sizeof(dev->t10_wwn.model)+1];
247 247
248 /* scsiLuProductId */ 248 /* scsiLuProductId */
249 for (i = 0; i < sizeof(dev->t10_wwn.vendor); i++) 249 for (i = 0; i < sizeof(dev->t10_wwn.model); i++)
250 str[i] = ISPRINT(dev->t10_wwn.model[i]) ? 250 str[i] = ISPRINT(dev->t10_wwn.model[i]) ?
251 dev->t10_wwn.model[i] : ' '; 251 dev->t10_wwn.model[i] : ' ';
252 str[i] = '\0'; 252 str[i] = '\0';
diff --git a/drivers/target/target_core_tmr.c b/drivers/target/target_core_tmr.c
index 5b2820312310..28fb3016370f 100644
--- a/drivers/target/target_core_tmr.c
+++ b/drivers/target/target_core_tmr.c
@@ -130,6 +130,9 @@ void core_tmr_abort_task(
130 if (tmr->ref_task_tag != ref_tag) 130 if (tmr->ref_task_tag != ref_tag)
131 continue; 131 continue;
132 132
133 if (!kref_get_unless_zero(&se_cmd->cmd_kref))
134 continue;
135
133 printk("ABORT_TASK: Found referenced %s task_tag: %llu\n", 136 printk("ABORT_TASK: Found referenced %s task_tag: %llu\n",
134 se_cmd->se_tfo->get_fabric_name(), ref_tag); 137 se_cmd->se_tfo->get_fabric_name(), ref_tag);
135 138
@@ -139,13 +142,15 @@ void core_tmr_abort_task(
139 " skipping\n", ref_tag); 142 " skipping\n", ref_tag);
140 spin_unlock(&se_cmd->t_state_lock); 143 spin_unlock(&se_cmd->t_state_lock);
141 spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags); 144 spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
145
146 target_put_sess_cmd(se_cmd);
147
142 goto out; 148 goto out;
143 } 149 }
144 se_cmd->transport_state |= CMD_T_ABORTED; 150 se_cmd->transport_state |= CMD_T_ABORTED;
145 spin_unlock(&se_cmd->t_state_lock); 151 spin_unlock(&se_cmd->t_state_lock);
146 152
147 list_del_init(&se_cmd->se_cmd_list); 153 list_del_init(&se_cmd->se_cmd_list);
148 kref_get(&se_cmd->cmd_kref);
149 spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags); 154 spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
150 155
151 cancel_work_sync(&se_cmd->work); 156 cancel_work_sync(&se_cmd->work);
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index 5bacc7b5ed6d..4fdcee2006d1 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -1658,7 +1658,7 @@ bool target_stop_cmd(struct se_cmd *cmd, unsigned long *flags)
1658void transport_generic_request_failure(struct se_cmd *cmd, 1658void transport_generic_request_failure(struct se_cmd *cmd,
1659 sense_reason_t sense_reason) 1659 sense_reason_t sense_reason)
1660{ 1660{
1661 int ret = 0; 1661 int ret = 0, post_ret = 0;
1662 1662
1663 pr_debug("-----[ Storage Engine Exception for cmd: %p ITT: 0x%08llx" 1663 pr_debug("-----[ Storage Engine Exception for cmd: %p ITT: 0x%08llx"
1664 " CDB: 0x%02x\n", cmd, cmd->tag, cmd->t_task_cdb[0]); 1664 " 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,
1680 */ 1680 */
1681 if ((cmd->se_cmd_flags & SCF_COMPARE_AND_WRITE) && 1681 if ((cmd->se_cmd_flags & SCF_COMPARE_AND_WRITE) &&
1682 cmd->transport_complete_callback) 1682 cmd->transport_complete_callback)
1683 cmd->transport_complete_callback(cmd, false); 1683 cmd->transport_complete_callback(cmd, false, &post_ret);
1684 1684
1685 switch (sense_reason) { 1685 switch (sense_reason) {
1686 case TCM_NON_EXISTENT_LUN: 1686 case TCM_NON_EXISTENT_LUN:
@@ -2068,11 +2068,13 @@ static void target_complete_ok_work(struct work_struct *work)
2068 */ 2068 */
2069 if (cmd->transport_complete_callback) { 2069 if (cmd->transport_complete_callback) {
2070 sense_reason_t rc; 2070 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;
2071 2074
2072 rc = cmd->transport_complete_callback(cmd, true); 2075 rc = cmd->transport_complete_callback(cmd, true, &post_ret);
2073 if (!rc && !(cmd->se_cmd_flags & SCF_COMPARE_AND_WRITE_POST)) { 2076 if (!rc && !post_ret) {
2074 if ((cmd->se_cmd_flags & SCF_COMPARE_AND_WRITE) && 2077 if (caw && zero_dl)
2075 !cmd->data_length)
2076 goto queue_rsp; 2078 goto queue_rsp;
2077 2079
2078 return; 2080 return;
@@ -2507,23 +2509,24 @@ out:
2507EXPORT_SYMBOL(target_get_sess_cmd); 2509EXPORT_SYMBOL(target_get_sess_cmd);
2508 2510
2509static void target_release_cmd_kref(struct kref *kref) 2511static void target_release_cmd_kref(struct kref *kref)
2510 __releases(&se_cmd->se_sess->sess_cmd_lock)
2511{ 2512{
2512 struct se_cmd *se_cmd = container_of(kref, struct se_cmd, cmd_kref); 2513 struct se_cmd *se_cmd = container_of(kref, struct se_cmd, cmd_kref);
2513 struct se_session *se_sess = se_cmd->se_sess; 2514 struct se_session *se_sess = se_cmd->se_sess;
2515 unsigned long flags;
2514 2516
2517 spin_lock_irqsave(&se_sess->sess_cmd_lock, flags);
2515 if (list_empty(&se_cmd->se_cmd_list)) { 2518 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);
2517 se_cmd->se_tfo->release_cmd(se_cmd); 2520 se_cmd->se_tfo->release_cmd(se_cmd);
2518 return; 2521 return;
2519 } 2522 }
2520 if (se_sess->sess_tearing_down && se_cmd->cmd_wait_set) { 2523 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);
2522 complete(&se_cmd->cmd_wait_comp); 2525 complete(&se_cmd->cmd_wait_comp);
2523 return; 2526 return;
2524 } 2527 }
2525 list_del(&se_cmd->se_cmd_list); 2528 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);
2527 2530
2528 se_cmd->se_tfo->release_cmd(se_cmd); 2531 se_cmd->se_tfo->release_cmd(se_cmd);
2529} 2532}
@@ -2539,8 +2542,7 @@ int target_put_sess_cmd(struct se_cmd *se_cmd)
2539 se_cmd->se_tfo->release_cmd(se_cmd); 2542 se_cmd->se_tfo->release_cmd(se_cmd);
2540 return 1; 2543 return 1;
2541 } 2544 }
2542 return kref_put_spinlock_irqsave(&se_cmd->cmd_kref, target_release_cmd_kref, 2545 return kref_put(&se_cmd->cmd_kref, target_release_cmd_kref);
2543 &se_sess->sess_cmd_lock);
2544} 2546}
2545EXPORT_SYMBOL(target_put_sess_cmd); 2547EXPORT_SYMBOL(target_put_sess_cmd);
2546 2548
diff --git a/drivers/target/target_core_user.c b/drivers/target/target_core_user.c
index 937cebf76633..5e6d6cb348fc 100644
--- a/drivers/target/target_core_user.c
+++ b/drivers/target/target_core_user.c
@@ -638,7 +638,7 @@ static int tcmu_check_expired_cmd(int id, void *p, void *data)
638 if (test_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags)) 638 if (test_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags))
639 return 0; 639 return 0;
640 640
641 if (!time_after(cmd->deadline, jiffies)) 641 if (!time_after(jiffies, cmd->deadline))
642 return 0; 642 return 0;
643 643
644 set_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags); 644 set_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags);
@@ -1101,8 +1101,6 @@ tcmu_parse_cdb(struct se_cmd *cmd)
1101 1101
1102static const struct target_backend_ops tcmu_ops = { 1102static const struct target_backend_ops tcmu_ops = {
1103 .name = "user", 1103 .name = "user",
1104 .inquiry_prod = "USER",
1105 .inquiry_rev = TCMU_VERSION,
1106 .owner = THIS_MODULE, 1104 .owner = THIS_MODULE,
1107 .transport_flags = TRANSPORT_FLAG_PASSTHROUGH, 1105 .transport_flags = TRANSPORT_FLAG_PASSTHROUGH,
1108 .attach_hba = tcmu_attach_hba, 1106 .attach_hba = tcmu_attach_hba,
diff --git a/include/linux/kref.h b/include/linux/kref.h
index 484604d184be..e15828fd71f1 100644
--- a/include/linux/kref.h
+++ b/include/linux/kref.h
@@ -19,7 +19,6 @@
19#include <linux/atomic.h> 19#include <linux/atomic.h>
20#include <linux/kernel.h> 20#include <linux/kernel.h>
21#include <linux/mutex.h> 21#include <linux/mutex.h>
22#include <linux/spinlock.h>
23 22
24struct kref { 23struct kref {
25 atomic_t refcount; 24 atomic_t refcount;
@@ -99,38 +98,6 @@ static inline int kref_put(struct kref *kref, void (*release)(struct kref *kref)
99 return kref_sub(kref, 1, release); 98 return kref_sub(kref, 1, release);
100} 99}
101 100
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 */
115static 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
134static inline int kref_put_mutex(struct kref *kref, 101static inline int kref_put_mutex(struct kref *kref,
135 void (*release)(struct kref *kref), 102 void (*release)(struct kref *kref),
136 struct mutex *lock) 103 struct mutex *lock)
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h
index 0a2c74008e53..aabf0aca0171 100644
--- a/include/target/target_core_base.h
+++ b/include/target/target_core_base.h
@@ -474,7 +474,7 @@ struct se_cmd {
474 struct completion cmd_wait_comp; 474 struct completion cmd_wait_comp;
475 const struct target_core_fabric_ops *se_tfo; 475 const struct target_core_fabric_ops *se_tfo;
476 sense_reason_t (*execute_cmd)(struct se_cmd *); 476 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 *);
478 void *protocol_data; 478 void *protocol_data;
479 479
480 unsigned char *t_task_cdb; 480 unsigned char *t_task_cdb;