summaryrefslogtreecommitdiff
path: root/drivers/s390
diff options
context:
space:
mode:
authorHarald Freudenberger <freude@linux.ibm.com>2021-10-14 10:58:24 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2021-11-18 21:17:17 +0300
commit3ef2272417f49edcecd349151345378c24ad7b04 (patch)
treeb8baf0176a95ac20e268a5f381e870ef02030795 /drivers/s390
parent3134c317b1b3403adee2cddc39c09e05f4d425c2 (diff)
downloadlinux-3ef2272417f49edcecd349151345378c24ad7b04.tar.xz
s390/ap: Fix hanging ioctl caused by orphaned replies
commit 3826350e6dd435e244eb6e47abad5a47c169ebc2 upstream. When a queue is switched to soft offline during heavy load and later switched to soft online again and now used, it may be that the caller is blocked forever in the ioctl call. The failure occurs because there is a pending reply after the queue(s) have been switched to offline. This orphaned reply is received when the queue is switched to online and is accidentally counted for the outstanding replies. So when there was a valid outstanding reply and this orphaned reply is received it counts as the outstanding one thus dropping the outstanding counter to 0. Voila, with this counter the receive function is not called any more and the real outstanding reply is never received (until another request comes in...) and the ioctl blocks. The fix is simple. However, instead of readjusting the counter when an orphaned reply is detected, I check the queue status for not empty and compare this to the outstanding counter. So if the queue is not empty then the counter must not drop to 0 but at least have a value of 1. Signed-off-by: Harald Freudenberger <freude@linux.ibm.com> Cc: stable@vger.kernel.org Signed-off-by: Vasily Gorbik <gor@linux.ibm.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/s390')
-rw-r--r--drivers/s390/crypto/ap_queue.c2
1 files changed, 2 insertions, 0 deletions
diff --git a/drivers/s390/crypto/ap_queue.c b/drivers/s390/crypto/ap_queue.c
index 9ea48bf0ee40..032bf7b282ba 100644
--- a/drivers/s390/crypto/ap_queue.c
+++ b/drivers/s390/crypto/ap_queue.c
@@ -157,6 +157,8 @@ static struct ap_queue_status ap_sm_recv(struct ap_queue *aq)
switch (status.response_code) {
case AP_RESPONSE_NORMAL:
aq->queue_count = max_t(int, 0, aq->queue_count - 1);
+ if (!status.queue_empty && !aq->queue_count)
+ aq->queue_count++;
if (aq->queue_count > 0)
mod_timer(&aq->timeout,
jiffies + aq->request_timeout);