Commit d251193d authored by Julian Wiedmann's avatar Julian Wiedmann Committed by Martin K. Petersen
Browse files

scsi: zfcp: Clarify access to erp_action in zfcp_fsf_req_complete()

While reviewing commit 936e6b85 ("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: default avatarSteffen Maier <maier@linux.ibm.com>
Reviewed-by: default avatarBenjamin Block <bblock@linux.ibm.com>
Signed-off-by: default avatarJulian Wiedmann <jwi@linux.ibm.com>
Signed-off-by: default avatarBenjamin Block <bblock@linux.ibm.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent addf1372
Loading
Loading
Loading
Loading
+8 −2
Original line number Diff line number Diff line
@@ -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);