From 0b25e17e9018a0ea68a9f0b4787672e8c68fa8d5 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Mon, 31 Oct 2022 15:47:25 -0700 Subject: [PATCH] scsi: alua: Move a scsi_device_put() call out of alua_check_vpd() Fix the following smatch warning: drivers/scsi/device_handler/scsi_dh_alua.c:1013 alua_rtpg_queue() warn: sleeping in atomic context alua_check_vpd() <- disables preempt -> alua_rtpg_queue() -> scsi_device_put() Cc: Hannes Reinecke Cc: Dan Carpenter Reported-by: Dan Carpenter Signed-off-by: Bart Van Assche Link: https://lore.kernel.org/r/20221031224728.2607760-2-bvanassche@acm.org Reviewed-by: Hannes Reinecke Signed-off-by: Martin K. Petersen --- drivers/scsi/device_handler/scsi_dh_alua.c | 23 ++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index 610a51538f03..f7bc81cc59ab 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c @@ -324,6 +324,7 @@ static int alua_check_vpd(struct scsi_device *sdev, struct alua_dh_data *h, struct alua_port_group *pg, *old_pg = NULL; bool pg_updated = false; unsigned long flags; + bool put_sdev; group_id = scsi_vpd_tpg_id(sdev, &rel_port); if (group_id < 0) { @@ -373,11 +374,14 @@ static int alua_check_vpd(struct scsi_device *sdev, struct alua_dh_data *h, list_add_rcu(&h->node, &pg->dh_list); spin_unlock_irqrestore(&pg->lock, flags); - alua_rtpg_queue(rcu_dereference_protected(h->pg, + put_sdev = alua_rtpg_queue(rcu_dereference_protected(h->pg, lockdep_is_held(&h->pg_lock)), sdev, NULL, true); spin_unlock(&h->pg_lock); + if (put_sdev) + scsi_device_put(sdev); + if (old_pg) kref_put(&old_pg->kref, release_port_group); @@ -968,9 +972,10 @@ static void alua_rtpg_work(struct work_struct *work) * RTPG already has been scheduled. * * Returns true if and only if alua_rtpg_work() will be called asynchronously. - * That function is responsible for calling @qdata->fn(). + * That function is responsible for calling @qdata->fn(). If this function + * returns true, the caller is responsible for invoking scsi_device_put(@sdev). */ -static bool alua_rtpg_queue(struct alua_port_group *pg, +static bool __must_check alua_rtpg_queue(struct alua_port_group *pg, struct scsi_device *sdev, struct alua_queue_data *qdata, bool force) { @@ -1009,8 +1014,6 @@ static bool alua_rtpg_queue(struct alua_port_group *pg, else kref_put(&pg->kref, release_port_group); } - if (sdev) - scsi_device_put(sdev); return true; } @@ -1117,10 +1120,12 @@ static int alua_activate(struct scsi_device *sdev, rcu_read_unlock(); mutex_unlock(&h->init_mutex); - if (alua_rtpg_queue(pg, sdev, qdata, true)) + if (alua_rtpg_queue(pg, sdev, qdata, true)) { + scsi_device_put(sdev); fn = NULL; - else + } else { err = SCSI_DH_DEV_OFFLINED; + } kref_put(&pg->kref, release_port_group); out: if (fn) @@ -1146,7 +1151,9 @@ static void alua_check(struct scsi_device *sdev, bool force) return; } rcu_read_unlock(); - alua_rtpg_queue(pg, sdev, NULL, force); + + if (alua_rtpg_queue(pg, sdev, NULL, force)) + scsi_device_put(sdev); kref_put(&pg->kref, release_port_group); } -- 2.25.1