From d251193d17321d44f96b78d9bb4c8b8ea6786e72 Mon Sep 17 00:00:00 2001 From: Julian Wiedmann Date: Thu, 10 Sep 2020 21:49:16 +0200 Subject: scsi: zfcp: Clarify access to erp_action in zfcp_fsf_req_complete() While reviewing commit 936e6b85da04 ("scsi: zfcp: Fix panic on ERP timeout for previously dismissed ERP action"), I stumbled over zfcp_fsf_req_complete() and wondered whether it has similar issues wrt concurrent modification of req->erp_action by zfcp_erp_strategy_check_fsfreq(). But a closer look shows that both its two callers [zfcp_fsf_reqid_check(), zfcp_fsf_req_dismiss_all()] remove the request from the adapter's req_list under the req_list's lock. Hence we can trust that if zfcp_erp_strategy_check_fsfreq() concurrently looks up the corresponding req_id, it won't find this request and is thus unable to modify it while it's being processed by zfcp_fsf_req_complete(). Add a code comment that hopefully makes this easier for future readers, and condense the two accesses to ->erp_action that made me trip over this code path in the first place. Link: https://lore.kernel.org/r/c500eac301fcbba5af942bbd200f2d6b14e46994.1599765652.git.bblock@linux.ibm.com Reviewed-by: Steffen Maier Reviewed-by: Benjamin Block Signed-off-by: Julian Wiedmann Signed-off-by: Benjamin Block Signed-off-by: Martin K. Petersen --- drivers/s390/scsi/zfcp_fsf.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 140186fe1d1e..6cb963a06777 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -426,9 +426,14 @@ static void zfcp_fsf_protstatus_eval(struct zfcp_fsf_req *req) * or it has been dismissed due to a queue shutdown, this function * is called to process the completion status and trigger further * events related to the FSF request. + * Caller must ensure that the request has been removed from + * adapter->req_list, to protect against concurrent modification + * by zfcp_erp_strategy_check_fsfreq(). */ static void zfcp_fsf_req_complete(struct zfcp_fsf_req *req) { + struct zfcp_erp_action *erp_action; + if (unlikely(zfcp_fsf_req_is_status_read_buffer(req))) { zfcp_fsf_status_read_handler(req); return; @@ -439,8 +444,9 @@ static void zfcp_fsf_req_complete(struct zfcp_fsf_req *req) zfcp_fsf_fsfstatus_eval(req); req->handler(req); - if (req->erp_action) - zfcp_erp_notify(req->erp_action, 0); + erp_action = req->erp_action; + if (erp_action) + zfcp_erp_notify(erp_action, 0); if (likely(req->status & ZFCP_STATUS_FSFREQ_CLEANUP)) zfcp_fsf_req_free(req); -- cgit v1.2.3