Skip to content

Commit

Permalink
scsi: Revert "target/core: Inline transport_lun_remove_cmd()"
Browse files Browse the repository at this point in the history
Commit 83f85b8 postponed the percpu_ref_put(&se_cmd->se_lun->lun_ref)
call from command completion to the time when the final command reference
is dropped. That approach is not compatible with the iSCSI target driver
because the iSCSI target driver keeps the command with the highest stat_sn
after it has completed until the next command is received (see also
iscsit_ack_from_expstatsn()). Fix this regression by reverting commit
83f85b8.

Fixes: 83f85b8 ("scsi: target/core: Inline transport_lun_remove_cmd()")
Cc: Pavel Zakharov <pavel.zakharov@delphix.com>
Cc: Mike Christie <mchristi@redhat.com>
Cc: <stable@vger.kernel.org>
Link: https://lore.kernel.org/r/20200210051202.12934-1-bvanassche@acm.org
Reported-by: Pavel Zakharov <pavel.zakharov@delphix.com>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
  • Loading branch information
Bart Van Assche authored and Martin K. Petersen committed Feb 12, 2020
1 parent bb6d3fb commit c14335e
Showing 1 changed file with 28 additions and 3 deletions.
31 changes: 28 additions & 3 deletions drivers/target/target_core_transport.c
Original file line number Diff line number Diff line change
Expand Up @@ -666,6 +666,11 @@ static int transport_cmd_check_stop_to_fabric(struct se_cmd *cmd)

target_remove_from_state_list(cmd);

/*
* Clear struct se_cmd->se_lun before the handoff to FE.
*/
cmd->se_lun = NULL;

spin_lock_irqsave(&cmd->t_state_lock, flags);
/*
* Determine if frontend context caller is requesting the stopping of
Expand Down Expand Up @@ -693,6 +698,17 @@ static int transport_cmd_check_stop_to_fabric(struct se_cmd *cmd)
return cmd->se_tfo->check_stop_free(cmd);
}

static void transport_lun_remove_cmd(struct se_cmd *cmd)
{
struct se_lun *lun = cmd->se_lun;

if (!lun)
return;

if (cmpxchg(&cmd->lun_ref_active, true, false))
percpu_ref_put(&lun->lun_ref);
}

static void target_complete_failure_work(struct work_struct *work)
{
struct se_cmd *cmd = container_of(work, struct se_cmd, work);
Expand Down Expand Up @@ -783,6 +799,8 @@ static void target_handle_abort(struct se_cmd *cmd)

WARN_ON_ONCE(kref_read(&cmd->cmd_kref) == 0);

transport_lun_remove_cmd(cmd);

transport_cmd_check_stop_to_fabric(cmd);
}

Expand Down Expand Up @@ -1708,6 +1726,7 @@ static void target_complete_tmr_failure(struct work_struct *work)
se_cmd->se_tmr_req->response = TMR_LUN_DOES_NOT_EXIST;
se_cmd->se_tfo->queue_tm_rsp(se_cmd);

transport_lun_remove_cmd(se_cmd);
transport_cmd_check_stop_to_fabric(se_cmd);
}

Expand Down Expand Up @@ -1898,6 +1917,7 @@ void transport_generic_request_failure(struct se_cmd *cmd,
goto queue_full;

check_stop:
transport_lun_remove_cmd(cmd);
transport_cmd_check_stop_to_fabric(cmd);
return;

Expand Down Expand Up @@ -2195,6 +2215,7 @@ static void transport_complete_qf(struct se_cmd *cmd)
transport_handle_queue_full(cmd, cmd->se_dev, ret, false);
return;
}
transport_lun_remove_cmd(cmd);
transport_cmd_check_stop_to_fabric(cmd);
}

Expand Down Expand Up @@ -2289,6 +2310,7 @@ static void target_complete_ok_work(struct work_struct *work)
if (ret)
goto queue_full;

transport_lun_remove_cmd(cmd);
transport_cmd_check_stop_to_fabric(cmd);
return;
}
Expand All @@ -2314,6 +2336,7 @@ static void target_complete_ok_work(struct work_struct *work)
if (ret)
goto queue_full;

transport_lun_remove_cmd(cmd);
transport_cmd_check_stop_to_fabric(cmd);
return;
}
Expand Down Expand Up @@ -2349,6 +2372,7 @@ static void target_complete_ok_work(struct work_struct *work)
if (ret)
goto queue_full;

transport_lun_remove_cmd(cmd);
transport_cmd_check_stop_to_fabric(cmd);
return;
}
Expand Down Expand Up @@ -2384,6 +2408,7 @@ static void target_complete_ok_work(struct work_struct *work)
break;
}

transport_lun_remove_cmd(cmd);
transport_cmd_check_stop_to_fabric(cmd);
return;

Expand Down Expand Up @@ -2710,6 +2735,9 @@ int transport_generic_free_cmd(struct se_cmd *cmd, int wait_for_tasks)
*/
if (cmd->state_active)
target_remove_from_state_list(cmd);

if (cmd->se_lun)
transport_lun_remove_cmd(cmd);
}
if (aborted)
cmd->free_compl = &compl;
Expand Down Expand Up @@ -2781,9 +2809,6 @@ static void target_release_cmd_kref(struct kref *kref)
struct completion *abrt_compl = se_cmd->abrt_compl;
unsigned long flags;

if (se_cmd->lun_ref_active)
percpu_ref_put(&se_cmd->se_lun->lun_ref);

if (se_sess) {
spin_lock_irqsave(&se_sess->sess_cmd_lock, flags);
list_del_init(&se_cmd->se_cmd_list);
Expand Down

0 comments on commit c14335e

Please sign in to comment.