lkml.org 
[lkml]   [2021]   [Nov]   [15]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.14 820/849] s390/ap: Fix hanging ioctl caused by orphaned replies
    Date
    From: Harald Freudenberger <freude@linux.ibm.com>

    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>
    ---
    drivers/s390/crypto/ap_queue.c | 2 ++
    1 file changed, 2 insertions(+)

    --- 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
    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);

    \
     
     \ /
      Last update: 2021-11-16 00:27    [W:2.188 / U:0.796 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site