Commit 1a9e3941 authored by Matthew R. Ochs's avatar Matthew R. Ochs Committed by Martin K. Petersen

scsi: cxlflash: Avoid double mutex unlock

The AFU recovery routine uses an interruptible mutex to control the flow
of in-flight recoveries. Upon receiving an interruptible signal the code
branches to a common exit path which wrongly assumes the mutex is
held. Add a local variable to track when the mutex should be unlocked.
Signed-off-by: default avatarMatthew R. Ochs <mrochs@linux.vnet.ibm.com>
Signed-off-by: default avatarUma Krishnan <ukrishn@linux.vnet.ibm.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 48a17ad5
...@@ -1651,6 +1651,7 @@ static int cxlflash_afu_recover(struct scsi_device *sdev, ...@@ -1651,6 +1651,7 @@ static int cxlflash_afu_recover(struct scsi_device *sdev,
u64 ctxid = DECODE_CTXID(recover->context_id), u64 ctxid = DECODE_CTXID(recover->context_id),
rctxid = recover->context_id; rctxid = recover->context_id;
long reg; long reg;
bool locked = true;
int lretry = 20; /* up to 2 seconds */ int lretry = 20; /* up to 2 seconds */
int new_adap_fd = -1; int new_adap_fd = -1;
int rc = 0; int rc = 0;
...@@ -1659,8 +1660,11 @@ static int cxlflash_afu_recover(struct scsi_device *sdev, ...@@ -1659,8 +1660,11 @@ static int cxlflash_afu_recover(struct scsi_device *sdev,
up_read(&cfg->ioctl_rwsem); up_read(&cfg->ioctl_rwsem);
rc = mutex_lock_interruptible(mutex); rc = mutex_lock_interruptible(mutex);
down_read(&cfg->ioctl_rwsem); down_read(&cfg->ioctl_rwsem);
if (rc) if (rc) {
locked = false;
goto out; goto out;
}
rc = check_state(cfg); rc = check_state(cfg);
if (rc) { if (rc) {
dev_err(dev, "%s: Failed state rc=%d\n", __func__, rc); dev_err(dev, "%s: Failed state rc=%d\n", __func__, rc);
...@@ -1694,8 +1698,10 @@ static int cxlflash_afu_recover(struct scsi_device *sdev, ...@@ -1694,8 +1698,10 @@ static int cxlflash_afu_recover(struct scsi_device *sdev,
mutex_unlock(mutex); mutex_unlock(mutex);
msleep(100); msleep(100);
rc = mutex_lock_interruptible(mutex); rc = mutex_lock_interruptible(mutex);
if (rc) if (rc) {
locked = false;
goto out; goto out;
}
goto retry_recover; goto retry_recover;
} }
...@@ -1739,6 +1745,7 @@ static int cxlflash_afu_recover(struct scsi_device *sdev, ...@@ -1739,6 +1745,7 @@ static int cxlflash_afu_recover(struct scsi_device *sdev,
out: out:
if (likely(ctxi)) if (likely(ctxi))
put_context(ctxi); put_context(ctxi);
if (locked)
mutex_unlock(mutex); mutex_unlock(mutex);
atomic_dec_if_positive(&cfg->recovery_threads); atomic_dec_if_positive(&cfg->recovery_threads);
return rc; return rc;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment