s390/zcrypt: return EIO when msg retry limit reached
authorHarald Freudenberger <freude@linux.ibm.com>
Thu, 21 Jan 2021 15:03:08 +0000 (16:03 +0100)
committerVasily Gorbik <gor@linux.ibm.com>
Tue, 9 Feb 2021 14:57:04 +0000 (15:57 +0100)
When a msg is retried because the lower ap layer returns -EAGAIN
there is a retry limit (currently 10). When this limit is reached
the last return code from the lower layer is returned, causing
the userspace to get -1 on the ioctl with errno EAGAIN.

This EAGAIN is misleading here. After 10 retry attempts the
userspace should receive a clear failure indication like EINVAL
or EIO or ENODEV. However, the reason why these retries all
fail is unclear. On an invalid message EINVAL would be returned
by the lower layer, and if devices go away or are not available
an ENODEV is seen. So this patch now reworks the retry loops
to return EIO to userspace when the retry limit is reached.

Fixes: 91ffc519c199 ("s390/zcrypt: introduce msg tracking in zcrypt functions")
Signed-off-by: Harald Freudenberger <freude@linux.ibm.com>
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
drivers/s390/crypto/zcrypt_api.c

index 10206e4..52eaf51 100644 (file)
@@ -1438,6 +1438,8 @@ static int icarsamodexpo_ioctl(struct ap_perms *perms, unsigned long arg)
                        if (rc == -EAGAIN)
                                tr.again_counter++;
                } while (rc == -EAGAIN && tr.again_counter < TRACK_AGAIN_MAX);
+       if (rc == -EAGAIN && tr.again_counter >= TRACK_AGAIN_MAX)
+               rc = -EIO;
        if (rc) {
                ZCRYPT_DBF(DBF_DEBUG, "ioctl ICARSAMODEXPO rc=%d\n", rc);
                return rc;
@@ -1481,6 +1483,8 @@ static int icarsacrt_ioctl(struct ap_perms *perms, unsigned long arg)
                        if (rc == -EAGAIN)
                                tr.again_counter++;
                } while (rc == -EAGAIN && tr.again_counter < TRACK_AGAIN_MAX);
+       if (rc == -EAGAIN && tr.again_counter >= TRACK_AGAIN_MAX)
+               rc = -EIO;
        if (rc) {
                ZCRYPT_DBF(DBF_DEBUG, "ioctl ICARSACRT rc=%d\n", rc);
                return rc;
@@ -1524,6 +1528,8 @@ static int zsecsendcprb_ioctl(struct ap_perms *perms, unsigned long arg)
                        if (rc == -EAGAIN)
                                tr.again_counter++;
                } while (rc == -EAGAIN && tr.again_counter < TRACK_AGAIN_MAX);
+       if (rc == -EAGAIN && tr.again_counter >= TRACK_AGAIN_MAX)
+               rc = -EIO;
        if (rc)
                ZCRYPT_DBF(DBF_DEBUG, "ioctl ZSENDCPRB rc=%d status=0x%x\n",
                           rc, xcRB.status);
@@ -1568,6 +1574,8 @@ static int zsendep11cprb_ioctl(struct ap_perms *perms, unsigned long arg)
                        if (rc == -EAGAIN)
                                tr.again_counter++;
                } while (rc == -EAGAIN && tr.again_counter < TRACK_AGAIN_MAX);
+       if (rc == -EAGAIN && tr.again_counter >= TRACK_AGAIN_MAX)
+               rc = -EIO;
        if (rc)
                ZCRYPT_DBF(DBF_DEBUG, "ioctl ZSENDEP11CPRB rc=%d\n", rc);
        if (copy_to_user(uxcrb, &xcrb, sizeof(xcrb)))
@@ -1744,6 +1752,8 @@ static long trans_modexpo32(struct ap_perms *perms, struct file *filp,
                        if (rc == -EAGAIN)
                                tr.again_counter++;
                } while (rc == -EAGAIN && tr.again_counter < TRACK_AGAIN_MAX);
+       if (rc == -EAGAIN && tr.again_counter >= TRACK_AGAIN_MAX)
+               rc = -EIO;
        if (rc)
                return rc;
        return put_user(mex64.outputdatalength,
@@ -1795,6 +1805,8 @@ static long trans_modexpo_crt32(struct ap_perms *perms, struct file *filp,
                        if (rc == -EAGAIN)
                                tr.again_counter++;
                } while (rc == -EAGAIN && tr.again_counter < TRACK_AGAIN_MAX);
+       if (rc == -EAGAIN && tr.again_counter >= TRACK_AGAIN_MAX)
+               rc = -EIO;
        if (rc)
                return rc;
        return put_user(crt64.outputdatalength,
@@ -1865,6 +1877,8 @@ static long trans_xcRB32(struct ap_perms *perms, struct file *filp,
                        if (rc == -EAGAIN)
                                tr.again_counter++;
                } while (rc == -EAGAIN && tr.again_counter < TRACK_AGAIN_MAX);
+       if (rc == -EAGAIN && tr.again_counter >= TRACK_AGAIN_MAX)
+               rc = -EIO;
        xcRB32.reply_control_blk_length = xcRB64.reply_control_blk_length;
        xcRB32.reply_data_length = xcRB64.reply_data_length;
        xcRB32.status = xcRB64.status;