diff mbox

[v4,23/37] target: Remove the write_pending_status() callback function

Message ID 20170208222507.25715-24-bart.vanassche@sandisk.com (mailing list archive)
State Superseded
Headers show

Commit Message

Bart Van Assche Feb. 8, 2017, 10:24 p.m. UTC
Due to the previous patch the write_pending_status() callback
function is no longer called. Hence remove it.

Signed-off-by: Bart Van Assche <bart.vanassche@sandisk.com>
Acked-by: Felipe Balbi <balbi@ti.com>
Reviewed-by: Sagi Grimberg <sagig@mellanox.com>
Reviewed-by: Andy Grover <agrover@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Hannes Reinecke <hare@suse.com>
Reviewed-by: Bryant G. Ly <bryantly@linux.vnet.ibm.com>
Cc: Himanshu Madhani <himanshu.madhani@qlogic.com>
Cc: Quinn Tran <quinn.tran@qlogic.com>
Cc: Saurav Kashyap <saurav.kashyap@qlogic.com>
Cc: Michael S. Tsirkin <mst@redhat.com>
Cc: Juergen Gross <jgross@suse.com>
---
 Documentation/target/tcm_mod_builder.py      |  8 --------
 drivers/infiniband/ulp/srpt/ib_srpt.c        |  9 ---------
 drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c     |  6 ------
 drivers/scsi/qla2xxx/tcm_qla2xxx.c           | 30 +---------------------------
 drivers/target/iscsi/iscsi_target_configfs.c | 13 ------------
 drivers/target/loopback/tcm_loop.c           |  6 ------
 drivers/target/sbp/sbp_target.c              |  6 ------
 drivers/target/target_core_configfs.c        |  4 ----
 drivers/target/target_core_xcopy.c           |  6 ------
 drivers/target/tcm_fc/tcm_fc.h               |  1 -
 drivers/target/tcm_fc/tfc_cmd.c              |  7 -------
 drivers/target/tcm_fc/tfc_conf.c             |  1 -
 drivers/usb/gadget/function/f_tcm.c          |  9 ---------
 drivers/vhost/scsi.c                         |  6 ------
 drivers/xen/xen-scsiback.c                   |  6 ------
 include/target/target_core_fabric.h          |  1 -
 16 files changed, 1 insertion(+), 118 deletions(-)

Comments

Nicholas A. Bellinger Feb. 9, 2017, 10:59 a.m. UTC | #1
On Wed, 2017-02-08 at 14:24 -0800, Bart Van Assche wrote:
> Due to the previous patch the write_pending_status() callback
> function is no longer called. Hence remove it.
> 
> Signed-off-by: Bart Van Assche <bart.vanassche@sandisk.com>
> Acked-by: Felipe Balbi <balbi@ti.com>
> Reviewed-by: Sagi Grimberg <sagig@mellanox.com>
> Reviewed-by: Andy Grover <agrover@redhat.com>
> Reviewed-by: Christoph Hellwig <hch@lst.de>
> Reviewed-by: Hannes Reinecke <hare@suse.com>
> Reviewed-by: Bryant G. Ly <bryantly@linux.vnet.ibm.com>
> Cc: Himanshu Madhani <himanshu.madhani@qlogic.com>
> Cc: Quinn Tran <quinn.tran@qlogic.com>
> Cc: Saurav Kashyap <saurav.kashyap@qlogic.com>
> Cc: Michael S. Tsirkin <mst@redhat.com>
> Cc: Juergen Gross <jgross@suse.com>
> ---
>  
> diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
> index 4d9180efb9aa..9a188b508973 100644
> --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c
> +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
> @@ -413,26 +413,6 @@ static int tcm_qla2xxx_write_pending(struct se_cmd *se_cmd)
>  	return qlt_rdy_to_xfer(cmd);
>  }
>  
> -static int tcm_qla2xxx_write_pending_status(struct se_cmd *se_cmd)
> -{
> -	unsigned long flags;
> -	/*
> -	 * Check for WRITE_PENDING status to determine if we need to wait for
> -	 * CTIO aborts to be posted via hardware in tcm_qla2xxx_handle_data().
> -	 */
> -	spin_lock_irqsave(&se_cmd->t_state_lock, flags);
> -	if (se_cmd->t_state == TRANSPORT_WRITE_PENDING ||
> -	    se_cmd->t_state == TRANSPORT_COMPLETE_QF_WP) {
> -		spin_unlock_irqrestore(&se_cmd->t_state_lock, flags);
> -		wait_for_completion_timeout(&se_cmd->t_transport_stop_comp,
> -						50);
> -		return 0;
> -	}
> -	spin_unlock_irqrestore(&se_cmd->t_state_lock, flags);
> -
> -	return 0;
> -}
> -

Yeah, you can't randomly remove this code.

The whole reason this exists is to allow in-flight CTIOs for outstanding
WRITEs that have been aborted to complete, before going ahead and
completing sending status and releasing se_cmd memory.

This breaks with WRITEs + CMD_T_ABORTED in qla-target code.

>  static void tcm_qla2xxx_set_default_node_attrs(struct se_node_acl *nacl)
>  {
>  	return;
> @@ -522,14 +502,8 @@ static void tcm_qla2xxx_handle_data_work(struct work_struct *work)
>  
>  	cmd->vha->tgt_counters.qla_core_ret_ctio++;
>  	if (!cmd->write_data_transferred) {
> -		/*
> -		 * Check if se_cmd has already been aborted via LUN_RESET, and
> -		 * waiting upon completion in tcm_qla2xxx_write_pending_status()
> -		 */
> -		if (cmd->se_cmd.transport_state & CMD_T_ABORTED) {
> -			complete(&cmd->se_cmd.t_transport_stop_comp);
> +		if (cmd->se_cmd.transport_state & CMD_T_ABORTED)
>  			return;
> -		}
>  

Likewise, the callback into tcm_qla2xxx_handle_data_work must wakeup the
se_tfo->write_pending_status() caller to tell target_core_tmr.c logic
the write transfer has completed, and it's safe to proceed with
CMD_T_ABORTED.

> diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c
> index bf40f03755dd..7e112380d6d4 100644
> --- a/drivers/target/iscsi/iscsi_target_configfs.c
> +++ b/drivers/target/iscsi/iscsi_target_configfs.c
> @@ -1416,18 +1416,6 @@ static int lio_write_pending(struct se_cmd *se_cmd)
>  	return 0;
>  }
>  
> -static int lio_write_pending_status(struct se_cmd *se_cmd)
> -{
> -	struct iscsi_cmd *cmd = container_of(se_cmd, struct iscsi_cmd, se_cmd);
> -	int ret;
> -
> -	spin_lock_bh(&cmd->istate_lock);
> -	ret = !(cmd->cmd_flags & ICF_GOT_LAST_DATAOUT);
> -	spin_unlock_bh(&cmd->istate_lock);
> -
> -	return ret;
> -}
> -

This breaks solicited data-out WRITE handling with CMD_T_ABORTED in
iscsi-target.

iscsi-target must be allowed to complete it's solicited data-out WRITE
transfers before proceeding with CMD_T_ABORTED using delayed TAS logic.

open-iscsi expects solicited WRITE transfer to complete before getting a
SAM_STAT_TASK_ABORTED, and this will likely break other initiators as
well.

A big NACK on this.

--
To unsubscribe from this list: send the line "unsubscribe target-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Bart Van Assche Feb. 9, 2017, 10:37 p.m. UTC | #2
On Thu, 2017-02-09 at 02:59 -0800, Nicholas A. Bellinger wrote:
> Yeah, you can't randomly remove this code.

I will ignore this feedback since I have already explained in a previous
patch that you have misunderstood how the new approach to abort commands
works. Additionally, the mere existence of the write_pending_status()
callback function is a design bug. It is impossible to check whether or
not a write is pending without protecting that call with some kind of
locking. That by itself is more than sufficient as a reason to remove this
callback function.

Bart.--
To unsubscribe from this list: send the line "unsubscribe target-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Nicholas A. Bellinger Feb. 10, 2017, 1:06 a.m. UTC | #3
On Thu, 2017-02-09 at 22:37 +0000, Bart Van Assche wrote:
> On Thu, 2017-02-09 at 02:59 -0800, Nicholas A. Bellinger wrote:
> > Yeah, you can't randomly remove this code.
> 
> I will ignore this feedback since I have already explained in a previous
> patch that you have misunderstood how the new approach to abort commands
> works. Additionally, the mere existence of the write_pending_status()
> callback function is a design bug. It is impossible to check whether or
> not a write is pending without protecting that call with some kind of
> locking. That by itself is more than sufficient as a reason to remove this
> callback function.
> 

Incorrect.

qla2xxx must wait until the CTIO hw completion for the outstanding WRITE
transfer is finished, before the abort can continue processing.

This change and the previous changes ignore all of that.



--
To unsubscribe from this list: send the line "unsubscribe target-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Bart Van Assche Feb. 10, 2017, 1:11 a.m. UTC | #4
On Thu, 2017-02-09 at 17:06 -0800, Nicholas A. Bellinger wrote:
> qla2xxx must wait until the CTIO hw completion for the outstanding WRITE
> transfer is finished, before the abort can continue processing.
> 
> This change and the previous changes ignore all of that.

Incorrect. My patches wait for the CTIO hw completion.

Bart.--
To unsubscribe from this list: send the line "unsubscribe target-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Nicholas A. Bellinger Feb. 10, 2017, 6:56 a.m. UTC | #5
On Fri, 2017-02-10 at 01:11 +0000, Bart Van Assche wrote:
> On Thu, 2017-02-09 at 17:06 -0800, Nicholas A. Bellinger wrote:
> > qla2xxx must wait until the CTIO hw completion for the outstanding WRITE
> > transfer is finished, before the abort can continue processing.
> > 
> > This change and the previous changes ignore all of that.
> 
> Incorrect. My patches wait for the CTIO hw completion.
> 

Looking at your -v4 and -v5 changes, this doesn't appear to be the
case.

Let's walk through how it works in the existing code, yes..?

So a LUN_RESET occurs in tmr_wq context for a particular se_cmd and
CMD_T_ABORTED is set, while a qla2xxx CTIO for WRITE transfer is still
outstanding to ISP HW.

Since the se_cmd is !CMD_T_ACTIVE while it's owned by the fabric driver
once se_cmd->se_tfo->write_pending() has been called to perform the
transfer, the normal transport_wait_for_tasks() code-path will not block
on se_cmd->t_transport_stop_cmp because CMD_T_ACTIVE is not set.

From there, transport_cmd_finish_abort() proceeds to block waiting for
CTIO interrupt completion in tcm_qla2xxx_handle_data_work() to occur,
and subsequently completes se_cmd->t_transport_stop_cmp to allow
CMD_T_ABORT in tmr_wq context to proceed, et al.

With v4 and v5 changes, tmr_wq blocks on a new cmd->[finished,complete]
completion after CMD_T_STOP has been set.  CTIO interrupts fire for the
outstanding WRITE transfer, and tcm_qla2xxx_handle_data_work() returns
immediately for the aborted qla_tgt_cmd->se_cmd.

How can that possibly allow the aborted command to continue
processing..?

--
To unsubscribe from this list: send the line "unsubscribe target-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Bart Van Assche Feb. 10, 2017, 7:15 p.m. UTC | #6
On Thu, 2017-02-09 at 22:56 -0800, Nicholas A. Bellinger wrote:
> With v4 and v5 changes, tmr_wq blocks on a new cmd->[finished,complete]
> completion after CMD_T_STOP has been set.  CTIO interrupts fire for the
> outstanding WRITE transfer, and tcm_qla2xxx_handle_data_work() returns
> immediately for the aborted qla_tgt_cmd->se_cmd.
> 
> How can that possibly allow the aborted command to continue
> processing..?

The LIO core calls the tcm_qla2xxx .write_pending() callback function to
initiate an asynchronous data transfer from initiator to target. After that
data transfer has finished the tcm_qla2xxx target driver calls
target_execute_cmd(). That function will check the CMD_T_ABORTED flag and
will call target_handle_abort() if that flag has been set. No matter whether
or not that last function decides to queue a response, after all command
references have been dropped the 'complete' completion will be set. The
ABORT TMF waits for that completion.

Bart.--
To unsubscribe from this list: send the line "unsubscribe target-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/Documentation/target/tcm_mod_builder.py b/Documentation/target/tcm_mod_builder.py
index 94bf6944bb1e..95d6e31f1e3a 100755
--- a/Documentation/target/tcm_mod_builder.py
+++ b/Documentation/target/tcm_mod_builder.py
@@ -297,7 +297,6 @@  def tcm_mod_build_configfs(proto_ident, fabric_mod_dir_var, fabric_mod_name):
 	buf += "	.sess_get_index			= " + fabric_mod_name + "_sess_get_index,\n"
 	buf += "	.sess_get_initiator_sid		= NULL,\n"
 	buf += "	.write_pending			= " + fabric_mod_name + "_write_pending,\n"
-	buf += "	.write_pending_status		= " + fabric_mod_name + "_write_pending_status,\n"
 	buf += "	.set_default_node_attributes	= " + fabric_mod_name + "_set_default_node_attrs,\n"
 	buf += "	.get_cmd_state			= " + fabric_mod_name + "_get_cmd_state,\n"
 	buf += "	.queue_data_in			= " + fabric_mod_name + "_queue_data_in,\n"
@@ -479,13 +478,6 @@  def tcm_mod_dump_fabric_ops(proto_ident, fabric_mod_dir_var, fabric_mod_name):
 			buf += "}\n\n"
 			bufi += "int " + fabric_mod_name + "_write_pending(struct se_cmd *);\n"
 
-		if re.search('write_pending_status\)\(', fo):
-			buf += "int " + fabric_mod_name + "_write_pending_status(struct se_cmd *se_cmd)\n"
-			buf += "{\n"
-			buf += "	return 0;\n"
-			buf += "}\n\n"
-			bufi += "int " + fabric_mod_name + "_write_pending_status(struct se_cmd *);\n"
-
 		if re.search('set_default_node_attributes\)\(', fo):
 			buf += "void " + fabric_mod_name + "_set_default_node_attrs(struct se_node_acl *nacl)\n"
 			buf += "{\n"
diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c
index 9241553f796d..d955c521a6e9 100644
--- a/drivers/infiniband/ulp/srpt/ib_srpt.c
+++ b/drivers/infiniband/ulp/srpt/ib_srpt.c
@@ -2187,14 +2187,6 @@  static int srpt_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event)
 	return ret;
 }
 
-static int srpt_write_pending_status(struct se_cmd *se_cmd)
-{
-	struct srpt_send_ioctx *ioctx;
-
-	ioctx = container_of(se_cmd, struct srpt_send_ioctx, cmd);
-	return srpt_get_cmd_state(ioctx) == SRPT_STATE_NEED_DATA;
-}
-
 /*
  * srpt_write_pending() - Start data transfer from initiator to target (write).
  */
@@ -3055,7 +3047,6 @@  static const struct target_core_fabric_ops srpt_template = {
 	.sess_get_index			= srpt_sess_get_index,
 	.sess_get_initiator_sid		= NULL,
 	.write_pending			= srpt_write_pending,
-	.write_pending_status		= srpt_write_pending_status,
 	.set_default_node_attributes	= srpt_set_default_node_attrs,
 	.get_cmd_state			= srpt_get_tcm_cmd_state,
 	.queue_data_in			= srpt_queue_data_in,
diff --git a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c
index 99b747cedbeb..ceb5f8a0fdbc 100644
--- a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c
+++ b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c
@@ -3596,11 +3596,6 @@  static int ibmvscsis_write_pending(struct se_cmd *se_cmd)
 	return 0;
 }
 
-static int ibmvscsis_write_pending_status(struct se_cmd *se_cmd)
-{
-	return 0;
-}
-
 static void ibmvscsis_set_default_node_attrs(struct se_node_acl *nacl)
 {
 }
@@ -3829,7 +3824,6 @@  static const struct target_core_fabric_ops ibmvscsis_ops = {
 	.release_cmd			= ibmvscsis_release_cmd,
 	.sess_get_index			= ibmvscsis_sess_get_index,
 	.write_pending			= ibmvscsis_write_pending,
-	.write_pending_status		= ibmvscsis_write_pending_status,
 	.set_default_node_attributes	= ibmvscsis_set_default_node_attrs,
 	.get_cmd_state			= ibmvscsis_get_cmd_state,
 	.queue_data_in			= ibmvscsis_queue_data_in,
diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
index 4d9180efb9aa..9a188b508973 100644
--- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c
+++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
@@ -413,26 +413,6 @@  static int tcm_qla2xxx_write_pending(struct se_cmd *se_cmd)
 	return qlt_rdy_to_xfer(cmd);
 }
 
-static int tcm_qla2xxx_write_pending_status(struct se_cmd *se_cmd)
-{
-	unsigned long flags;
-	/*
-	 * Check for WRITE_PENDING status to determine if we need to wait for
-	 * CTIO aborts to be posted via hardware in tcm_qla2xxx_handle_data().
-	 */
-	spin_lock_irqsave(&se_cmd->t_state_lock, flags);
-	if (se_cmd->t_state == TRANSPORT_WRITE_PENDING ||
-	    se_cmd->t_state == TRANSPORT_COMPLETE_QF_WP) {
-		spin_unlock_irqrestore(&se_cmd->t_state_lock, flags);
-		wait_for_completion_timeout(&se_cmd->t_transport_stop_comp,
-						50);
-		return 0;
-	}
-	spin_unlock_irqrestore(&se_cmd->t_state_lock, flags);
-
-	return 0;
-}
-
 static void tcm_qla2xxx_set_default_node_attrs(struct se_node_acl *nacl)
 {
 	return;
@@ -522,14 +502,8 @@  static void tcm_qla2xxx_handle_data_work(struct work_struct *work)
 
 	cmd->vha->tgt_counters.qla_core_ret_ctio++;
 	if (!cmd->write_data_transferred) {
-		/*
-		 * Check if se_cmd has already been aborted via LUN_RESET, and
-		 * waiting upon completion in tcm_qla2xxx_write_pending_status()
-		 */
-		if (cmd->se_cmd.transport_state & CMD_T_ABORTED) {
-			complete(&cmd->se_cmd.t_transport_stop_comp);
+		if (cmd->se_cmd.transport_state & CMD_T_ABORTED)
 			return;
-		}
 
 		if (cmd->se_cmd.pi_err)
 			transport_generic_request_failure(&cmd->se_cmd,
@@ -1896,7 +1870,6 @@  static const struct target_core_fabric_ops tcm_qla2xxx_ops = {
 	.sess_get_index			= tcm_qla2xxx_sess_get_index,
 	.sess_get_initiator_sid		= NULL,
 	.write_pending			= tcm_qla2xxx_write_pending,
-	.write_pending_status		= tcm_qla2xxx_write_pending_status,
 	.set_default_node_attributes	= tcm_qla2xxx_set_default_node_attrs,
 	.get_cmd_state			= tcm_qla2xxx_get_cmd_state,
 	.queue_data_in			= tcm_qla2xxx_queue_data_in,
@@ -1938,7 +1911,6 @@  static const struct target_core_fabric_ops tcm_qla2xxx_npiv_ops = {
 	.sess_get_index			= tcm_qla2xxx_sess_get_index,
 	.sess_get_initiator_sid		= NULL,
 	.write_pending			= tcm_qla2xxx_write_pending,
-	.write_pending_status		= tcm_qla2xxx_write_pending_status,
 	.set_default_node_attributes	= tcm_qla2xxx_set_default_node_attrs,
 	.get_cmd_state			= tcm_qla2xxx_get_cmd_state,
 	.queue_data_in			= tcm_qla2xxx_queue_data_in,
diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c
index bf40f03755dd..7e112380d6d4 100644
--- a/drivers/target/iscsi/iscsi_target_configfs.c
+++ b/drivers/target/iscsi/iscsi_target_configfs.c
@@ -1416,18 +1416,6 @@  static int lio_write_pending(struct se_cmd *se_cmd)
 	return 0;
 }
 
-static int lio_write_pending_status(struct se_cmd *se_cmd)
-{
-	struct iscsi_cmd *cmd = container_of(se_cmd, struct iscsi_cmd, se_cmd);
-	int ret;
-
-	spin_lock_bh(&cmd->istate_lock);
-	ret = !(cmd->cmd_flags & ICF_GOT_LAST_DATAOUT);
-	spin_unlock_bh(&cmd->istate_lock);
-
-	return ret;
-}
-
 static int lio_queue_status(struct se_cmd *se_cmd)
 {
 	struct iscsi_cmd *cmd = container_of(se_cmd, struct iscsi_cmd, se_cmd);
@@ -1592,7 +1580,6 @@  const struct target_core_fabric_ops iscsi_ops = {
 	.sess_get_index			= lio_sess_get_index,
 	.sess_get_initiator_sid		= lio_sess_get_initiator_sid,
 	.write_pending			= lio_write_pending,
-	.write_pending_status		= lio_write_pending_status,
 	.set_default_node_attributes	= lio_set_default_node_attributes,
 	.get_cmd_state			= iscsi_get_cmd_state,
 	.queue_data_in			= lio_queue_data_in,
diff --git a/drivers/target/loopback/tcm_loop.c b/drivers/target/loopback/tcm_loop.c
index 5091b31b3e56..378c8d41768c 100644
--- a/drivers/target/loopback/tcm_loop.c
+++ b/drivers/target/loopback/tcm_loop.c
@@ -616,11 +616,6 @@  static int tcm_loop_write_pending(struct se_cmd *se_cmd)
 	return 0;
 }
 
-static int tcm_loop_write_pending_status(struct se_cmd *se_cmd)
-{
-	return 0;
-}
-
 static int tcm_loop_queue_data_in(struct se_cmd *se_cmd)
 {
 	struct tcm_loop_cmd *tl_cmd = container_of(se_cmd,
@@ -1235,7 +1230,6 @@  static const struct target_core_fabric_ops loop_ops = {
 	.release_cmd			= tcm_loop_release_cmd,
 	.sess_get_index			= tcm_loop_sess_get_index,
 	.write_pending			= tcm_loop_write_pending,
-	.write_pending_status		= tcm_loop_write_pending_status,
 	.set_default_node_attributes	= tcm_loop_set_default_node_attributes,
 	.get_cmd_state			= tcm_loop_get_cmd_state,
 	.queue_data_in			= tcm_loop_queue_data_in,
diff --git a/drivers/target/sbp/sbp_target.c b/drivers/target/sbp/sbp_target.c
index e5c3e5f827d0..0341313e2aa5 100644
--- a/drivers/target/sbp/sbp_target.c
+++ b/drivers/target/sbp/sbp_target.c
@@ -1755,11 +1755,6 @@  static int sbp_write_pending(struct se_cmd *se_cmd)
 	return 0;
 }
 
-static int sbp_write_pending_status(struct se_cmd *se_cmd)
-{
-	return 0;
-}
-
 static void sbp_set_default_node_attrs(struct se_node_acl *nacl)
 {
 	return;
@@ -2342,7 +2337,6 @@  static const struct target_core_fabric_ops sbp_ops = {
 	.release_cmd			= sbp_release_cmd,
 	.sess_get_index			= sbp_sess_get_index,
 	.write_pending			= sbp_write_pending,
-	.write_pending_status		= sbp_write_pending_status,
 	.set_default_node_attributes	= sbp_set_default_node_attrs,
 	.get_cmd_state			= sbp_get_cmd_state,
 	.queue_data_in			= sbp_queue_data_in,
diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c
index 54b36c9835be..f87f7196ad8f 100644
--- a/drivers/target/target_core_configfs.c
+++ b/drivers/target/target_core_configfs.c
@@ -393,10 +393,6 @@  static int target_fabric_tf_ops_check(const struct target_core_fabric_ops *tfo)
 		pr_err("Missing tfo->write_pending()\n");
 		return -EINVAL;
 	}
-	if (!tfo->write_pending_status) {
-		pr_err("Missing tfo->write_pending_status()\n");
-		return -EINVAL;
-	}
 	if (!tfo->set_default_node_attributes) {
 		pr_err("Missing tfo->set_default_node_attributes()\n");
 		return -EINVAL;
diff --git a/drivers/target/target_core_xcopy.c b/drivers/target/target_core_xcopy.c
index d828b3b5000b..180d8d718db5 100644
--- a/drivers/target/target_core_xcopy.c
+++ b/drivers/target/target_core_xcopy.c
@@ -436,11 +436,6 @@  static int xcopy_pt_write_pending(struct se_cmd *se_cmd)
 	return 0;
 }
 
-static int xcopy_pt_write_pending_status(struct se_cmd *se_cmd)
-{
-	return 0;
-}
-
 static int xcopy_pt_queue_data_in(struct se_cmd *se_cmd)
 {
 	return 0;
@@ -457,7 +452,6 @@  static const struct target_core_fabric_ops xcopy_pt_tfo = {
 	.release_cmd		= xcopy_pt_release_cmd,
 	.check_stop_free	= xcopy_pt_check_stop_free,
 	.write_pending		= xcopy_pt_write_pending,
-	.write_pending_status	= xcopy_pt_write_pending_status,
 	.queue_data_in		= xcopy_pt_queue_data_in,
 	.queue_status		= xcopy_pt_queue_status,
 };
diff --git a/drivers/target/tcm_fc/tcm_fc.h b/drivers/target/tcm_fc/tcm_fc.h
index 11d27b93b413..b8ced4458118 100644
--- a/drivers/target/tcm_fc/tcm_fc.h
+++ b/drivers/target/tcm_fc/tcm_fc.h
@@ -158,7 +158,6 @@  void ft_release_cmd(struct se_cmd *);
 int ft_queue_status(struct se_cmd *);
 int ft_queue_data_in(struct se_cmd *);
 int ft_write_pending(struct se_cmd *);
-int ft_write_pending_status(struct se_cmd *);
 int ft_get_cmd_state(struct se_cmd *);
 void ft_queue_tm_resp(struct se_cmd *);
 void ft_aborted_task(struct se_cmd *);
diff --git a/drivers/target/tcm_fc/tfc_cmd.c b/drivers/target/tcm_fc/tfc_cmd.c
index ec372860106f..e748b414a614 100644
--- a/drivers/target/tcm_fc/tfc_cmd.c
+++ b/drivers/target/tcm_fc/tfc_cmd.c
@@ -185,13 +185,6 @@  int ft_queue_status(struct se_cmd *se_cmd)
 	return 0;
 }
 
-int ft_write_pending_status(struct se_cmd *se_cmd)
-{
-	struct ft_cmd *cmd = container_of(se_cmd, struct ft_cmd, se_cmd);
-
-	return cmd->write_data_len != se_cmd->data_length;
-}
-
 /*
  * Send TX_RDY (transfer ready).
  */
diff --git a/drivers/target/tcm_fc/tfc_conf.c b/drivers/target/tcm_fc/tfc_conf.c
index 42ee91123dca..c88e44bdcbe1 100644
--- a/drivers/target/tcm_fc/tfc_conf.c
+++ b/drivers/target/tcm_fc/tfc_conf.c
@@ -446,7 +446,6 @@  static const struct target_core_fabric_ops ft_fabric_ops = {
 	.sess_get_index =		ft_sess_get_index,
 	.sess_get_initiator_sid =	NULL,
 	.write_pending =		ft_write_pending,
-	.write_pending_status =		ft_write_pending_status,
 	.set_default_node_attributes =	ft_set_default_node_attr,
 	.get_cmd_state =		ft_get_cmd_state,
 	.queue_data_in =		ft_queue_data_in,
diff --git a/drivers/usb/gadget/function/f_tcm.c b/drivers/usb/gadget/function/f_tcm.c
index d2351139342f..008a411d5185 100644
--- a/drivers/usb/gadget/function/f_tcm.c
+++ b/drivers/usb/gadget/function/f_tcm.c
@@ -1295,14 +1295,6 @@  static u32 usbg_sess_get_index(struct se_session *se_sess)
 	return 0;
 }
 
-/*
- * XXX Error recovery: return != 0 if we expect writes. Dunno when that could be
- */
-static int usbg_write_pending_status(struct se_cmd *se_cmd)
-{
-	return 0;
-}
-
 static void usbg_set_default_node_attrs(struct se_node_acl *nacl)
 {
 }
@@ -1731,7 +1723,6 @@  static const struct target_core_fabric_ops usbg_ops = {
 	.sess_get_index			= usbg_sess_get_index,
 	.sess_get_initiator_sid		= NULL,
 	.write_pending			= usbg_send_write_request,
-	.write_pending_status		= usbg_write_pending_status,
 	.set_default_node_attributes	= usbg_set_default_node_attrs,
 	.get_cmd_state			= usbg_get_cmd_state,
 	.queue_data_in			= usbg_send_read_response,
diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c
index fd6c8b66f06f..c706221b295e 100644
--- a/drivers/vhost/scsi.c
+++ b/drivers/vhost/scsi.c
@@ -345,11 +345,6 @@  static int vhost_scsi_write_pending(struct se_cmd *se_cmd)
 	return 0;
 }
 
-static int vhost_scsi_write_pending_status(struct se_cmd *se_cmd)
-{
-	return 0;
-}
-
 static void vhost_scsi_set_default_node_attrs(struct se_node_acl *nacl)
 {
 	return;
@@ -2104,7 +2099,6 @@  static const struct target_core_fabric_ops vhost_scsi_ops = {
 	.sess_get_index			= vhost_scsi_sess_get_index,
 	.sess_get_initiator_sid		= NULL,
 	.write_pending			= vhost_scsi_write_pending,
-	.write_pending_status		= vhost_scsi_write_pending_status,
 	.set_default_node_attributes	= vhost_scsi_set_default_node_attrs,
 	.get_cmd_state			= vhost_scsi_get_cmd_state,
 	.queue_data_in			= vhost_scsi_queue_data_in,
diff --git a/drivers/xen/xen-scsiback.c b/drivers/xen/xen-scsiback.c
index d6950e0802b7..8d77dbd70276 100644
--- a/drivers/xen/xen-scsiback.c
+++ b/drivers/xen/xen-scsiback.c
@@ -1412,11 +1412,6 @@  static int scsiback_write_pending(struct se_cmd *se_cmd)
 	return 0;
 }
 
-static int scsiback_write_pending_status(struct se_cmd *se_cmd)
-{
-	return 0;
-}
-
 static void scsiback_set_default_node_attrs(struct se_node_acl *nacl)
 {
 }
@@ -1835,7 +1830,6 @@  static const struct target_core_fabric_ops scsiback_ops = {
 	.sess_get_index			= scsiback_sess_get_index,
 	.sess_get_initiator_sid		= NULL,
 	.write_pending			= scsiback_write_pending,
-	.write_pending_status		= scsiback_write_pending_status,
 	.set_default_node_attributes	= scsiback_set_default_node_attrs,
 	.get_cmd_state			= scsiback_get_cmd_state,
 	.queue_data_in			= scsiback_queue_data_in,
diff --git a/include/target/target_core_fabric.h b/include/target/target_core_fabric.h
index 4c2d6fbf5f95..25bfdd0d24b0 100644
--- a/include/target/target_core_fabric.h
+++ b/include/target/target_core_fabric.h
@@ -63,7 +63,6 @@  struct target_core_fabric_ops {
 	u32 (*sess_get_initiator_sid)(struct se_session *,
 				      unsigned char *, u32);
 	int (*write_pending)(struct se_cmd *);
-	int (*write_pending_status)(struct se_cmd *);
 	void (*set_default_node_attributes)(struct se_node_acl *);
 	int (*get_cmd_state)(struct se_cmd *);
 	int (*queue_data_in)(struct se_cmd *);