From: Nicholas Bellinger <nab@xxxxxxxxxxxxxxx> This patch converts target_core_fabric_ops->check_stop_free() usage in transport_cmd_check_stop() and associated fabric module usage to return '1' when the passed se_cmd has been released directly within ->check_stop_free(), or return '0' when the passed se_cmd has not been released. This addresses an issue where transport_cmd_finish_abort() -> transport_cmd_check_stop_to_fabric() was leaking descriptors during LUN_RESET for modules using ->check_stop_free(), but not directly releasing se_cmd in all cases. Cc: Christoph Hellwig <hch@xxxxxx> Signed-off-by: Nicholas Bellinger <nab@xxxxxxxxxxxxxxxxxxxxx> --- drivers/infiniband/ulp/srpt/ib_srpt.c | 4 ++-- drivers/scsi/ibmvscsi/ibmvscsis.c | 5 +++-- drivers/target/loopback/tcm_loop.c | 5 +++-- drivers/target/target_core_transport.c | 7 +++++-- drivers/target/tcm_fc/tcm_fc.h | 2 +- drivers/target/tcm_fc/tfc_cmd.c | 3 ++- drivers/target/tcm_qla2xxx/tcm_qla2xxx_fabric.c | 6 ++++-- drivers/target/tcm_qla2xxx/tcm_qla2xxx_fabric.h | 2 +- include/target/target_core_fabric_ops.h | 7 +++++-- 9 files changed, 26 insertions(+), 15 deletions(-) diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c b/drivers/infiniband/ulp/srpt/ib_srpt.c index 7892efc..283bc65 100644 --- a/drivers/infiniband/ulp/srpt/ib_srpt.c +++ b/drivers/infiniband/ulp/srpt/ib_srpt.c @@ -1707,12 +1707,12 @@ out_err: goto out; } -static void srpt_check_stop_free(struct se_cmd *cmd) +static int srpt_check_stop_free(struct se_cmd *cmd) { struct srpt_send_ioctx *ioctx; ioctx = container_of(cmd, struct srpt_send_ioctx, cmd); - kref_put(&ioctx->kref, srpt_put_send_ioctx_kref); + return kref_put(&ioctx->kref, srpt_put_send_ioctx_kref); } /** diff --git a/drivers/scsi/ibmvscsi/ibmvscsis.c b/drivers/scsi/ibmvscsi/ibmvscsis.c index 095f8be..85188a5 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsis.c +++ b/drivers/scsi/ibmvscsi/ibmvscsis.c @@ -895,11 +895,12 @@ static int tcm_queuecommand(struct ibmvscsis_adapter *adapter, return 0; } -static void ibmvscsis_check_stop_free(struct se_cmd *se_cmd) +static int ibmvscsis_check_stop_free(struct se_cmd *se_cmd) { if (se_cmd->se_tmr_req) - return; + return 0; transport_generic_free_cmd(se_cmd, 0); + return 1; } static u64 scsi_lun_to_int(u64 lun) diff --git a/drivers/target/loopback/tcm_loop.c b/drivers/target/loopback/tcm_loop.c index c0a2edc..c097164 100644 --- a/drivers/target/loopback/tcm_loop.c +++ b/drivers/target/loopback/tcm_loop.c @@ -205,7 +205,7 @@ static int tcm_loop_new_cmd_map(struct se_cmd *se_cmd) /* * Called from struct target_core_fabric_ops->check_stop_free() */ -static void tcm_loop_check_stop_free(struct se_cmd *se_cmd) +static int tcm_loop_check_stop_free(struct se_cmd *se_cmd) { /* * Do not release struct se_cmd's containing a valid TMR @@ -213,12 +213,13 @@ static void tcm_loop_check_stop_free(struct se_cmd *se_cmd) * with transport_generic_free_cmd(). */ if (se_cmd->se_tmr_req) - return; + return 0; /* * Release the struct se_cmd, which will make a callback to release * struct tcm_loop_cmd * in tcm_loop_deallocate_core_cmd() */ transport_generic_free_cmd(se_cmd, 0); + return 1; } static void tcm_loop_release_cmd(struct se_cmd *se_cmd) diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 1821606..d12131c 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -517,13 +517,16 @@ static int transport_cmd_check_stop( * Some fabric modules like tcm_loop can release * their internally allocated I/O reference now and * struct se_cmd now. + * + * Fabric modules are expected to return '1' here if the + * se_cmd being passed is released at this point, + * or zero if not being released. */ if (cmd->se_tfo->check_stop_free != NULL) { spin_unlock_irqrestore( &cmd->t_state_lock, flags); - cmd->se_tfo->check_stop_free(cmd); - return 1; + return cmd->se_tfo->check_stop_free(cmd); } } spin_unlock_irqrestore(&cmd->t_state_lock, flags); diff --git a/drivers/target/tcm_fc/tcm_fc.h b/drivers/target/tcm_fc/tcm_fc.h index 8279096..26061f0 100644 --- a/drivers/target/tcm_fc/tcm_fc.h +++ b/drivers/target/tcm_fc/tcm_fc.h @@ -156,7 +156,7 @@ int ft_lport_notify(struct notifier_block *, unsigned long, void *); /* * IO methods. */ -void ft_check_stop_free(struct se_cmd *); +int ft_check_stop_free(struct se_cmd *); void ft_release_cmd(struct se_cmd *); int ft_queue_status(struct se_cmd *); int ft_queue_data_in(struct se_cmd *); diff --git a/drivers/target/tcm_fc/tfc_cmd.c b/drivers/target/tcm_fc/tfc_cmd.c index ccb1239..247bfad 100644 --- a/drivers/target/tcm_fc/tfc_cmd.c +++ b/drivers/target/tcm_fc/tfc_cmd.c @@ -112,9 +112,10 @@ void ft_release_cmd(struct se_cmd *se_cmd) ft_free_cmd(cmd); } -void ft_check_stop_free(struct se_cmd *se_cmd) +int ft_check_stop_free(struct se_cmd *se_cmd) { transport_generic_free_cmd(se_cmd, 0); + return 1; } /* diff --git a/drivers/target/tcm_qla2xxx/tcm_qla2xxx_fabric.c b/drivers/target/tcm_qla2xxx/tcm_qla2xxx_fabric.c index e05cf90..cb97b68 100644 --- a/drivers/target/tcm_qla2xxx/tcm_qla2xxx_fabric.c +++ b/drivers/target/tcm_qla2xxx/tcm_qla2xxx_fabric.c @@ -417,7 +417,7 @@ void tcm_qla2xxx_free_cmd(struct qla_tgt_cmd *cmd) /* * Called from struct target_core_fabric_ops->check_stop_free() context */ -void tcm_qla2xxx_check_stop_free(struct se_cmd *se_cmd) +int tcm_qla2xxx_check_stop_free(struct se_cmd *se_cmd) { struct qla_tgt_cmd *cmd = container_of(se_cmd, struct qla_tgt_cmd, se_cmd); struct qla_tgt_mgmt_cmd *mcmd; @@ -432,7 +432,7 @@ void tcm_qla2xxx_check_stop_free(struct se_cmd *se_cmd) */ transport_generic_free_cmd(se_cmd, 1); qla_tgt_free_mcmd(mcmd); - return; + return 1; } ha = cmd->sess->vha->hw; /* @@ -444,6 +444,8 @@ void tcm_qla2xxx_check_stop_free(struct se_cmd *se_cmd) if (atomic_read(&cmd->cmd_free) != 0) complete(&cmd->cmd_stop_free_comp); spin_unlock_irqrestore(&ha->hardware_lock, flags); + + return 0; } /* diff --git a/drivers/target/tcm_qla2xxx/tcm_qla2xxx_fabric.h b/drivers/target/tcm_qla2xxx/tcm_qla2xxx_fabric.h index 55e4eeb..ce166ac 100644 --- a/drivers/target/tcm_qla2xxx/tcm_qla2xxx_fabric.h +++ b/drivers/target/tcm_qla2xxx/tcm_qla2xxx_fabric.h @@ -25,7 +25,7 @@ extern struct se_node_acl *tcm_qla2xxx_alloc_fabric_acl(struct se_portal_group * extern void tcm_qla2xxx_release_fabric_acl(struct se_portal_group *, struct se_node_acl *); extern u32 tcm_qla2xxx_tpg_get_inst_index(struct se_portal_group *); extern void tcm_qla2xxx_free_cmd(struct qla_tgt_cmd *); -extern void tcm_qla2xxx_check_stop_free(struct se_cmd *); +extern int tcm_qla2xxx_check_stop_free(struct se_cmd *); extern void tcm_qla2xxx_release_cmd(struct se_cmd *); extern int tcm_qla2xxx_shutdown_session(struct se_session *); extern void tcm_qla2xxx_close_session(struct se_session *); diff --git a/include/target/target_core_fabric_ops.h b/include/target/target_core_fabric_ops.h index 126c675..04c591d 100644 --- a/include/target/target_core_fabric_ops.h +++ b/include/target/target_core_fabric_ops.h @@ -46,9 +46,12 @@ struct target_core_fabric_ops { int (*new_cmd_map)(struct se_cmd *); /* * Optional to release struct se_cmd and fabric dependent allocated - * I/O descriptor in transport_cmd_check_stop() + * I/O descriptor in transport_cmd_check_stop(). + * + * Returning 1 will signal a descriptor has been released. + * Returning 0 will signal a descriptor has not been released. */ - void (*check_stop_free)(struct se_cmd *); + int (*check_stop_free)(struct se_cmd *); void (*release_cmd)(struct se_cmd *); /* * Called with spin_lock_bh(struct se_portal_group->session_lock held. -- 1.7.2.5 -- To unsubscribe from this list: send the line "unsubscribe target-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html