]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
s390/hypfs_diag: Diag204 busy loop
authorMete Durlu <meted@linux.ibm.com>
Thu, 4 Jul 2024 12:10:08 +0000 (14:10 +0200)
committerVasily Gorbik <gor@linux.ibm.com>
Wed, 10 Jul 2024 17:50:45 +0000 (19:50 +0200)
When diag204 busy-indiciation facility is installed and diag204 is
returning busy, hypfs diag204 handler now does an interruptable busy
wait until diag204 is no longer busy. If there is a signal pending, call
would be restarted with -ERESTARTSYSCALL, except for fatal signals.

Acked-by: Heiko Carstens <hca@linux.ibm.com>
Reviewed-by: Tobias Huschle <huschle@linux.ibm.com>
Signed-off-by: Mete Durlu <meted@linux.ibm.com>
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
arch/s390/hypfs/hypfs_dbfs.c
arch/s390/hypfs/hypfs_diag.c
arch/s390/include/asm/diag.h

index 4024599eb448eaaf29941ca5713ed9b80080bf1b..0e855c5e91c5c27330059171f8ea996e12abd480 100644 (file)
@@ -39,7 +39,9 @@ static ssize_t dbfs_read(struct file *file, char __user *buf,
                return 0;
 
        df = file_inode(file)->i_private;
-       mutex_lock(&df->lock);
+       if (mutex_lock_interruptible(&df->lock))
+               return -ERESTARTSYS;
+
        data = hypfs_dbfs_data_alloc(df);
        if (!data) {
                mutex_unlock(&df->lock);
index 279b7bba4d430d8bfcd8e8f60a13f0c542521322..26a009f9c49e92de1d15669b40b0101a75a924d5 100644 (file)
@@ -140,11 +140,22 @@ fail_alloc:
 
 int diag204_store(void *buf, int pages)
 {
+       unsigned long subcode;
        int rc;
 
-       rc = diag204((unsigned long)diag204_store_sc |
-                    (unsigned long)diag204_get_info_type(), pages, buf);
-       return rc < 0 ? -EOPNOTSUPP : 0;
+       subcode = diag204_get_info_type();
+       subcode |= diag204_store_sc;
+       if (diag204_has_bif())
+               subcode |= DIAG204_BIF_BIT;
+       while (1) {
+               rc = diag204(subcode, pages, buf);
+               if (rc != -EBUSY)
+                       break;
+               if (signal_pending(current))
+                       return -ERESTARTSYS;
+               schedule_timeout_interruptible(DIAG204_BUSY_WAIT);
+       }
+       return rc < 0 ? rc : 0;
 }
 
 struct dbfs_d204_hdr {
index 6527d7e8e010f644b1f47528a382941c84b4274d..c0d43512f4fc66ed319f234370a230bb0b0f1b89 100644 (file)
@@ -119,6 +119,7 @@ enum diag204_sc {
 
 #define DIAG204_SUBCODE_MASK 0xffff
 #define DIAG204_BIF_BIT 0x80000000
+#define DIAG204_BUSY_WAIT (HZ / 10)
 
 /* The two available diag 204 data formats */
 enum diag204_format {