From 5e2c956b8aa24d4f33ff7afef92d409eed164746 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Wed, 25 May 2016 12:25:04 -0700 Subject: target: Fix missing complete during ABORT_TASK + CMD_T_FABRIC_STOP During transport_generic_free_cmd() with a concurrent TMR ABORT_TASK and shutdown CMD_T_FABRIC_STOP bit set, the caller will be blocked on se_cmd->cmd_wait_stop completion until the final kref_put() -> target_release_cmd_kref() has been invoked to call complete(). However, when ABORT_TASK is completed with FUNCTION_COMPLETE in core_tmr_abort_task(), the aborted se_cmd will have already been removed from se_sess->sess_cmd_list via list_del_init(). This results in target_release_cmd_kref() hitting the legacy list_empty() == true check, invoking ->release_cmd() but skipping complete() to wakeup se_cmd->cmd_wait_stop blocked earlier in transport_generic_free_cmd() code. To address this bug, it's safe to go ahead and drop the original list_empty() check so that fabric_stop invokes the complete() as expected, since list_del_init() can safely be used on a empty list. Cc: Mike Christie Cc: Quinn Tran Cc: Himanshu Madhani Cc: Christoph Hellwig Cc: Hannes Reinecke Cc: stable@vger.kernel.org # 3.14+ Tested-by: Nicholas Bellinger Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_transport.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers/target') diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 5ab3967dda43..ae97e81141ed 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -2557,12 +2557,6 @@ static void target_release_cmd_kref(struct kref *kref) bool fabric_stop; spin_lock_irqsave(&se_sess->sess_cmd_lock, flags); - if (list_empty(&se_cmd->se_cmd_list)) { - spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags); - target_free_cmd_mem(se_cmd); - se_cmd->se_tfo->release_cmd(se_cmd); - return; - } spin_lock(&se_cmd->t_state_lock); fabric_stop = (se_cmd->transport_state & CMD_T_FABRIC_STOP); -- cgit From 064cdd2d91c2805d788876082f31cc63506f22c3 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Thu, 2 Jun 2016 14:56:45 -0700 Subject: target: Fix race between iscsi-target connection shutdown + ABORT_TASK This patch fixes a race in iscsit_release_commands_from_conn() -> iscsit_free_cmd() -> transport_generic_free_cmd() + wait_for_tasks=1, where CMD_T_FABRIC_STOP could end up being set after the final kref_put() is called from core_tmr_abort_task() context. This results in transport_generic_free_cmd() blocking indefinately on se_cmd->cmd_wait_comp, because the target_release_cmd_kref() check for CMD_T_FABRIC_STOP returns false. To address this bug, make iscsit_release_commands_from_conn() do list_splice and set CMD_T_FABRIC_STOP early while holding iscsi_conn->cmd_lock. Also make iscsit_aborted_task() only remove iscsi_cmd_t if CMD_T_FABRIC_STOP has not already been set. Finally in target_release_cmd_kref(), only honor fabric_stop if CMD_T_ABORTED has been set. Cc: Mike Christie Cc: Quinn Tran Cc: Himanshu Madhani Cc: Christoph Hellwig Cc: Hannes Reinecke Cc: stable@vger.kernel.org # 3.14+ Tested-by: Nicholas Bellinger Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target.c | 22 ++++++++++++++++------ drivers/target/target_core_transport.c | 3 ++- 2 files changed, 18 insertions(+), 7 deletions(-) (limited to 'drivers/target') diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index 50f3d3a0dd7b..39b928c2849d 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -492,7 +492,8 @@ void iscsit_aborted_task(struct iscsi_conn *conn, struct iscsi_cmd *cmd) bool scsi_cmd = (cmd->iscsi_opcode == ISCSI_OP_SCSI_CMD); spin_lock_bh(&conn->cmd_lock); - if (!list_empty(&cmd->i_conn_node)) + if (!list_empty(&cmd->i_conn_node) && + !(cmd->se_cmd.transport_state & CMD_T_FABRIC_STOP)) list_del_init(&cmd->i_conn_node); spin_unlock_bh(&conn->cmd_lock); @@ -4034,6 +4035,7 @@ int iscsi_target_rx_thread(void *arg) static void iscsit_release_commands_from_conn(struct iscsi_conn *conn) { + LIST_HEAD(tmp_list); struct iscsi_cmd *cmd = NULL, *cmd_tmp = NULL; struct iscsi_session *sess = conn->sess; /* @@ -4042,18 +4044,26 @@ static void iscsit_release_commands_from_conn(struct iscsi_conn *conn) * has been reset -> returned sleeping pre-handler state. */ spin_lock_bh(&conn->cmd_lock); - list_for_each_entry_safe(cmd, cmd_tmp, &conn->conn_cmd_list, i_conn_node) { + list_splice_init(&conn->conn_cmd_list, &tmp_list); + list_for_each_entry(cmd, &tmp_list, i_conn_node) { + struct se_cmd *se_cmd = &cmd->se_cmd; + + if (se_cmd->se_tfo != NULL) { + spin_lock(&se_cmd->t_state_lock); + se_cmd->transport_state |= CMD_T_FABRIC_STOP; + spin_unlock(&se_cmd->t_state_lock); + } + } + spin_unlock_bh(&conn->cmd_lock); + + list_for_each_entry_safe(cmd, cmd_tmp, &tmp_list, i_conn_node) { list_del_init(&cmd->i_conn_node); - spin_unlock_bh(&conn->cmd_lock); iscsit_increment_maxcmdsn(cmd, sess); - iscsit_free_cmd(cmd, true); - spin_lock_bh(&conn->cmd_lock); } - spin_unlock_bh(&conn->cmd_lock); } static void iscsit_stop_timers_for_cmds( diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index ae97e81141ed..38bf2dcf926a 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -2559,7 +2559,8 @@ static void target_release_cmd_kref(struct kref *kref) spin_lock_irqsave(&se_sess->sess_cmd_lock, flags); spin_lock(&se_cmd->t_state_lock); - fabric_stop = (se_cmd->transport_state & CMD_T_FABRIC_STOP); + fabric_stop = (se_cmd->transport_state & CMD_T_FABRIC_STOP) && + (se_cmd->transport_state & CMD_T_ABORTED); spin_unlock(&se_cmd->t_state_lock); if (se_cmd->cmd_wait_set || fabric_stop) { -- cgit From ea263c7fada4af8ec7fe5fcfd6e7d7705a89351b Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Thu, 2 Jun 2016 20:12:37 -0500 Subject: target: Fix max_unmap_lba_count calc overflow max_discard_sectors only 32bits, and some non scsi backend devices will set this to the max 0xffffffff, so we can end up overflowing during the max_unmap_lba_count calculation. This fixes a regression caused by my patch: commit 8a9ebe717a133ba7bc90b06047f43cc6b8bcb8b3 Author: Mike Christie Date: Mon Jan 18 14:09:27 2016 -0600 target: Fix WRITE_SAME/DISCARD conversion to linux 512b sectors which can result in extra discards being sent to due the overflow causing max_unmap_lba_count to be smaller than what the backing device can actually support. Signed-off-by: Mike Christie Reviewed-by: Bart Van Assche Cc: stable@vger.kernel.org Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_device.c | 8 +++++--- drivers/target/target_core_file.c | 3 +-- drivers/target/target_core_iblock.c | 3 +-- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers/target') diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index a4046ca6e60d..6b423485c5d6 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -821,13 +821,15 @@ struct se_device *target_alloc_device(struct se_hba *hba, const char *name) * in ATA and we need to set TPE=1 */ bool target_configure_unmap_from_queue(struct se_dev_attrib *attrib, - struct request_queue *q, int block_size) + struct request_queue *q) { + int block_size = queue_logical_block_size(q); + if (!blk_queue_discard(q)) return false; - attrib->max_unmap_lba_count = (q->limits.max_discard_sectors << 9) / - block_size; + attrib->max_unmap_lba_count = + q->limits.max_discard_sectors >> (ilog2(block_size) - 9); /* * Currently hardcoded to 1 in Linux/SCSI code.. */ diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c index 75f0f08b2a34..79291869bce6 100644 --- a/drivers/target/target_core_file.c +++ b/drivers/target/target_core_file.c @@ -161,8 +161,7 @@ static int fd_configure_device(struct se_device *dev) dev_size, div_u64(dev_size, fd_dev->fd_block_size), fd_dev->fd_block_size); - if (target_configure_unmap_from_queue(&dev->dev_attrib, q, - fd_dev->fd_block_size)) + if (target_configure_unmap_from_queue(&dev->dev_attrib, q)) pr_debug("IFILE: BLOCK Discard support available," " disabled by default\n"); /* diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c index 7c4efb4417b0..2077bc28640a 100644 --- a/drivers/target/target_core_iblock.c +++ b/drivers/target/target_core_iblock.c @@ -121,8 +121,7 @@ static int iblock_configure_device(struct se_device *dev) dev->dev_attrib.hw_max_sectors = queue_max_hw_sectors(q); dev->dev_attrib.hw_queue_depth = q->nr_requests; - if (target_configure_unmap_from_queue(&dev->dev_attrib, q, - dev->dev_attrib.hw_block_size)) + if (target_configure_unmap_from_queue(&dev->dev_attrib, q)) pr_debug("IBLOCK: BLOCK Discard support available," " disabled by default\n"); -- cgit From dff0ca9ea7dc8be2181a62df4a722c32ce68ff4a Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Tue, 17 May 2016 22:19:10 -0700 Subject: target: Fix ordered task target_setup_cmd_from_cdb exception hang If a command with a Simple task attribute is failed due to a Unit Attention, then a subsequent command with an Ordered task attribute will hang forever. The reason for this is that the Unit Attention status is checked for in target_setup_cmd_from_cdb, before the call to target_execute_cmd, which calls target_handle_task_attr, which in turn increments dev->simple_cmds. However, transport_generic_request_failure still calls transport_complete_task_attr, which will decrement dev->simple_cmds. In this case, simple_cmds is now -1. So when a command with the Ordered task attribute is sent, target_handle_task_attr sees that dev->simple_cmds is not 0, so it decides it can't execute the command until all the (nonexistent) Simple commands have completed. Reported-by: Michael Cyr Tested-by: Michael Cyr Reported-by: Bryant G. Ly Tested-by: Bryant G. Ly Cc: stable@vger.kernel.org # 4.4+ Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_internal.h | 1 + drivers/target/target_core_sbc.c | 2 +- drivers/target/target_core_transport.c | 62 +++++++++++++++++++--------------- 3 files changed, 37 insertions(+), 28 deletions(-) (limited to 'drivers/target') diff --git a/drivers/target/target_core_internal.h b/drivers/target/target_core_internal.h index fc91e85f54ba..e2c970a9d61c 100644 --- a/drivers/target/target_core_internal.h +++ b/drivers/target/target_core_internal.h @@ -146,6 +146,7 @@ sense_reason_t target_cmd_size_check(struct se_cmd *cmd, unsigned int size); void target_qf_do_work(struct work_struct *work); bool target_check_wce(struct se_device *dev); bool target_check_fua(struct se_device *dev); +void __target_execute_cmd(struct se_cmd *, bool); /* target_core_stat.c */ void target_stat_setup_dev_default_groups(struct se_device *); diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c index a9057aa07176..04f616b3ba0a 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c @@ -602,7 +602,7 @@ static sense_reason_t compare_and_write_callback(struct se_cmd *cmd, bool succes cmd->transport_state |= CMD_T_ACTIVE|CMD_T_BUSY|CMD_T_SENT; spin_unlock_irq(&cmd->t_state_lock); - __target_execute_cmd(cmd); + __target_execute_cmd(cmd, false); kfree(buf); return ret; diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 38bf2dcf926a..a6e1edcfefbd 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -1303,23 +1303,6 @@ target_setup_cmd_from_cdb(struct se_cmd *cmd, unsigned char *cdb) trace_target_sequencer_start(cmd); - /* - * Check for an existing UNIT ATTENTION condition - */ - ret = target_scsi3_ua_check(cmd); - if (ret) - return ret; - - ret = target_alua_state_check(cmd); - if (ret) - return ret; - - ret = target_check_reservation(cmd); - if (ret) { - cmd->scsi_status = SAM_STAT_RESERVATION_CONFLICT; - return ret; - } - ret = dev->transport->parse_cdb(cmd); if (ret == TCM_UNSUPPORTED_SCSI_OPCODE) pr_warn_ratelimited("%s/%s: Unsupported SCSI Opcode 0x%02x, sending CHECK_CONDITION.\n", @@ -1761,20 +1744,45 @@ queue_full: } EXPORT_SYMBOL(transport_generic_request_failure); -void __target_execute_cmd(struct se_cmd *cmd) +void __target_execute_cmd(struct se_cmd *cmd, bool do_checks) { sense_reason_t ret; - if (cmd->execute_cmd) { - ret = cmd->execute_cmd(cmd); - if (ret) { - spin_lock_irq(&cmd->t_state_lock); - cmd->transport_state &= ~(CMD_T_BUSY|CMD_T_SENT); - spin_unlock_irq(&cmd->t_state_lock); + if (!cmd->execute_cmd) { + ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; + goto err; + } + if (do_checks) { + /* + * Check for an existing UNIT ATTENTION condition after + * target_handle_task_attr() has done SAM task attr + * checking, and possibly have already defered execution + * out to target_restart_delayed_cmds() context. + */ + ret = target_scsi3_ua_check(cmd); + if (ret) + goto err; + + ret = target_alua_state_check(cmd); + if (ret) + goto err; - transport_generic_request_failure(cmd, ret); + ret = target_check_reservation(cmd); + if (ret) { + cmd->scsi_status = SAM_STAT_RESERVATION_CONFLICT; + goto err; } } + + ret = cmd->execute_cmd(cmd); + if (!ret) + return; +err: + spin_lock_irq(&cmd->t_state_lock); + cmd->transport_state &= ~(CMD_T_BUSY|CMD_T_SENT); + spin_unlock_irq(&cmd->t_state_lock); + + transport_generic_request_failure(cmd, ret); } static int target_write_prot_action(struct se_cmd *cmd) @@ -1899,7 +1907,7 @@ void target_execute_cmd(struct se_cmd *cmd) return; } - __target_execute_cmd(cmd); + __target_execute_cmd(cmd, true); } EXPORT_SYMBOL(target_execute_cmd); @@ -1923,7 +1931,7 @@ static void target_restart_delayed_cmds(struct se_device *dev) list_del(&cmd->se_delayed_node); spin_unlock(&dev->delayed_cmd_lock); - __target_execute_cmd(cmd); + __target_execute_cmd(cmd, true); if (cmd->sam_task_attr == TCM_ORDERED_TAG) break; -- cgit From 410c29dfbfdf73d0d0b5d14a21868ab038eca703 Mon Sep 17 00:00:00 2001 From: Nicholas Bellinger Date: Mon, 13 Jun 2016 22:58:09 -0700 Subject: target: Fix ordered task CHECK_CONDITION early exception handling If a Simple command is sent with a failure, target_setup_cmd_from_cdb returns with TCM_UNSUPPORTED_SCSI_OPCODE or TCM_INVALID_CDB_FIELD. So in the cases where target_setup_cmd_from_cdb returns an error, we never get far enough to call target_execute_cmd to increment simple_cmds. Since simple_cmds isn't incremented, the result of the failure from target_setup_cmd_from_cdb causes transport_generic_request_failure to decrement simple_cmds, due to call to transport_complete_task_attr. With this dev->simple_cmds or dev->dev_ordered_sync is now -1, not 0. So when a subsequent command with an Ordered Task is sent, it causes a hang, since dev->simple_cmds is at -1. Tested-by: Bryant G. Ly Signed-off-by: Bryant G. Ly Tested-by: Michael Cyr Signed-off-by: Michael Cyr Cc: stable@vger.kernel.org # 4.4+ Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_transport.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/target') diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index a6e1edcfefbd..42c2a44b83dd 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -1827,6 +1827,8 @@ static bool target_handle_task_attr(struct se_cmd *cmd) if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH) return false; + cmd->se_cmd_flags |= SCF_TASK_ATTR_SET; + /* * Check for the existence of HEAD_OF_QUEUE, and if true return 1 * to allow the passed struct se_cmd list of tasks to the front of the list. @@ -1949,6 +1951,9 @@ static void transport_complete_task_attr(struct se_cmd *cmd) if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH) return; + if (!(cmd->se_cmd_flags & SCF_TASK_ATTR_SET)) + goto restart; + if (cmd->sam_task_attr == TCM_SIMPLE_TAG) { atomic_dec_mb(&dev->simple_cmds); dev->dev_cur_ordered_id++; @@ -1965,7 +1970,7 @@ static void transport_complete_task_attr(struct se_cmd *cmd) pr_debug("Incremented dev_cur_ordered_id: %u for ORDERED\n", dev->dev_cur_ordered_id); } - +restart: target_restart_delayed_cmds(dev); } -- cgit From 8abc718de6e9e52d8a6bfdb735060554aeae25e4 Mon Sep 17 00:00:00 2001 From: Feng Li Date: Tue, 12 Jul 2016 06:15:44 +0800 Subject: iscsi-target: Fix panic when adding second TCP connection to iSCSI session In MC/S scenario, the conn->sess has been set NULL in iscsi_login_non_zero_tsih_s1 when the second connection comes here, then kernel panic. The conn->sess will be assigned in iscsi_login_non_zero_tsih_s2. So we should check whether it's NULL before calling. Signed-off-by: Feng Li Tested-by: Sumit Rai Cc: stable@vger.kernel.org # 3.14+ Signed-off-by: Nicholas Bellinger --- drivers/target/iscsi/iscsi_target_login.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/target') diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c index b5212f0f9571..adf419fa4291 100644 --- a/drivers/target/iscsi/iscsi_target_login.c +++ b/drivers/target/iscsi/iscsi_target_login.c @@ -1371,8 +1371,9 @@ static int __iscsi_target_login_thread(struct iscsi_np *np) } login->zero_tsih = zero_tsih; - conn->sess->se_sess->sup_prot_ops = - conn->conn_transport->iscsit_get_sup_prot_ops(conn); + if (conn->sess) + conn->sess->se_sess->sup_prot_ops = + conn->conn_transport->iscsit_get_sup_prot_ops(conn); tpg = conn->tpg; if (!tpg) { -- cgit From 107818e2dad943ec357f6fdfa70377317a142d9d Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Tue, 19 Jul 2016 15:01:55 +0200 Subject: tcm_fc: set and unset FCP_SPPF_TARG_FCN When registering and unregistering as an target port we should be setting the FC-4 service params correctly. Signed-off-by: Hannes Reinecke Signed-off-by: Nicholas Bellinger --- drivers/target/tcm_fc/tfc_sess.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/target') diff --git a/drivers/target/tcm_fc/tfc_sess.c b/drivers/target/tcm_fc/tfc_sess.c index f5186a744399..6ffbb603d912 100644 --- a/drivers/target/tcm_fc/tfc_sess.c +++ b/drivers/target/tcm_fc/tfc_sess.c @@ -91,6 +91,7 @@ static void ft_tport_delete(struct ft_tport *tport) ft_sess_delete_all(tport); lport = tport->lport; + lport->service_params &= ~FCP_SPPF_TARG_FCN; BUG_ON(tport != lport->prov[FC_TYPE_FCP]); RCU_INIT_POINTER(lport->prov[FC_TYPE_FCP], NULL); @@ -110,6 +111,7 @@ void ft_lport_add(struct fc_lport *lport, void *arg) { mutex_lock(&ft_lport_lock); ft_tport_get(lport); + lport->service_params |= FCP_SPPF_TARG_FCN; mutex_unlock(&ft_lport_lock); } -- cgit From c1ccbfe0311e2380a6d2dcb0714b36904f5d586f Mon Sep 17 00:00:00 2001 From: Sumit Rai Date: Wed, 20 Jul 2016 13:59:42 -0700 Subject: target: Fix residual overflow handling in target_complete_cmd_with_length MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch fixes residual overflow handling to correctly set the residual_count using SPDTL, instead of SCSI Allocation Length. Allocation Length is the maximum value of the SPDTL and not substitute for it, hence it shouldn’t be used to calculate ResidualCount except for cases where SPDTL > Allocation Length and Data is truncated (in that case both Alloc Len and SPDTL are same). (SPC 5r01 Section 4.2.5.6). Thanks to Ajay Nair in assisting with this patch. Signed-off-by: Sumit Rai Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_transport.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'drivers/target') diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 42c2a44b83dd..6094a6beddde 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -754,7 +754,15 @@ EXPORT_SYMBOL(target_complete_cmd); void target_complete_cmd_with_length(struct se_cmd *cmd, u8 scsi_status, int length) { - if (scsi_status == SAM_STAT_GOOD && length < cmd->data_length) { + if (scsi_status != SAM_STAT_GOOD) { + return; + } + + /* + * Calculate new residual count based upon length of SCSI data + * transferred. + */ + if (length < cmd->data_length) { if (cmd->se_cmd_flags & SCF_UNDERFLOW_BIT) { cmd->residual_count += cmd->data_length - length; } else { @@ -763,6 +771,12 @@ void target_complete_cmd_with_length(struct se_cmd *cmd, u8 scsi_status, int len } cmd->data_length = length; + } else if (length > cmd->data_length) { + cmd->se_cmd_flags |= SCF_OVERFLOW_BIT; + cmd->residual_count = length - cmd->data_length; + } else { + cmd->se_cmd_flags &= ~(SCF_OVERFLOW_BIT | SCF_UNDERFLOW_BIT); + cmd->residual_count = 0; } target_complete_cmd(cmd, scsi_status); -- cgit From 291e3e51a34d2f546608bfd31f185151621135b7 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 22 Jun 2016 19:31:51 +0100 Subject: target: fix spelling mistake: "limitiation" -> "limitation" trivial fix to spelling mistake Signed-off-by: Colin Ian King Signed-off-by: Nicholas Bellinger --- drivers/target/target_core_file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/target') diff --git a/drivers/target/target_core_file.c b/drivers/target/target_core_file.c index 79291869bce6..d545993df18b 100644 --- a/drivers/target/target_core_file.c +++ b/drivers/target/target_core_file.c @@ -522,7 +522,7 @@ fd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, */ if (cmd->data_length > FD_MAX_BYTES) { pr_err("FILEIO: Not able to process I/O of %u bytes due to" - "FD_MAX_BYTES: %u iovec count limitiation\n", + "FD_MAX_BYTES: %u iovec count limitation\n", cmd->data_length, FD_MAX_BYTES); return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; } -- cgit