mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
scsi: target: Clear cmd_cnt when initial counter enrollment fails
When target_get_sess_cmd() fails during session shutdown because percpu_ref_tryget_live() returns false, the command keeps the se_cmd->cmd_cnt pointer that __target_init_cmd() assigned earlier without owning a reference. Final release through target_release_cmd_kref() then issues an unmatched percpu_ref_put(). Commit8e288be860("scsi: target: Pass in cmd counter to use during cmd setup") moved the cmd_cnt assignment ahead of the reference acquisition. Clear se_cmd->cmd_cnt whenever the initial target_get_sess_cmd() fails in target_init_cmd() and target_submit_tmr(), so release performs exactly one matching put per acquired reference. Fixes:8e288be860("scsi: target: Pass in cmd counter to use during cmd setup") Signed-off-by: Leon Romanovsky <leonro@nvidia.com> Reviewed-by: Mike Christie <michael.christie@oracle.com> Link: https://patch.msgid.link/20260722-reference-count-underflow-in-target-v1-1-63ab664f12fd@nvidia.com Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
committed by
Martin K. Petersen
parent
b601fa590e
commit
a8ddfd2425
@@ -1734,6 +1734,7 @@ int target_init_cmd(struct se_cmd *se_cmd, struct se_session *se_sess,
|
||||
u32 data_length, int task_attr, int data_dir, int flags)
|
||||
{
|
||||
struct se_portal_group *se_tpg;
|
||||
int ret;
|
||||
|
||||
se_tpg = se_sess->se_tpg;
|
||||
BUG_ON(!se_tpg);
|
||||
@@ -1763,7 +1764,11 @@ int target_init_cmd(struct se_cmd *se_cmd, struct se_session *se_sess,
|
||||
* necessary for fabrics using TARGET_SCF_ACK_KREF that expect a second
|
||||
* kref_put() to happen during fabric packet acknowledgement.
|
||||
*/
|
||||
return target_get_sess_cmd(se_cmd, flags & TARGET_SCF_ACK_KREF);
|
||||
ret = target_get_sess_cmd(se_cmd, flags & TARGET_SCF_ACK_KREF);
|
||||
if (ret)
|
||||
se_cmd->cmd_cnt = NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(target_init_cmd);
|
||||
|
||||
@@ -2039,8 +2044,10 @@ int target_submit_tmr(struct se_cmd *se_cmd, struct se_session *se_sess,
|
||||
* allocation failure.
|
||||
*/
|
||||
ret = core_tmr_alloc_req(se_cmd, fabric_tmr_ptr, tm_type, gfp);
|
||||
if (ret < 0)
|
||||
if (ret < 0) {
|
||||
se_cmd->cmd_cnt = NULL;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (tm_type == TMR_ABORT_TASK)
|
||||
se_cmd->se_tmr_req->ref_task_tag = tag;
|
||||
@@ -2048,6 +2055,7 @@ int target_submit_tmr(struct se_cmd *se_cmd, struct se_session *se_sess,
|
||||
/* See target_submit_cmd for commentary */
|
||||
ret = target_get_sess_cmd(se_cmd, flags & TARGET_SCF_ACK_KREF);
|
||||
if (ret) {
|
||||
se_cmd->cmd_cnt = NULL;
|
||||
core_tmr_release_req(se_cmd->se_tmr_req);
|
||||
return ret;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user