s390/dasd: remove ioctl_by_bdev calls
authorStefan Haberland <sth@linux.ibm.com>
Tue, 19 May 2020 14:22:59 +0000 (16:22 +0200)
committerJens Axboe <axboe@kernel.dk>
Thu, 21 May 2020 14:22:20 +0000 (08:22 -0600)
The IBM partition parser requires device type specific information only
available to the DASD driver to correctly register partitions. The
current approach of using ioctl_by_bdev with a fake user space pointer
is discouraged.

Fix this by replacing IOCTL calls with direct in-kernel function calls.

Suggested-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Stefan Haberland <sth@linux.ibm.com>
Reviewed-by: Jan Hoeppner <hoeppner@linux.ibm.com>
Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
MAINTAINERS
block/partitions/ibm.c
drivers/s390/block/dasd_ioctl.c
include/linux/dasd_mod.h [new file with mode: 0644]

index b816a453b10eba4288be034f340dd135a32742a9..927fd9845d2f5042de5f26c83a29fabdc2803f7d 100644 (file)
@@ -14628,6 +14628,7 @@ S:      Supported
 W:     http://www.ibm.com/developerworks/linux/linux390/
 F:     block/partitions/ibm.c
 F:     drivers/s390/block/dasd*
+F:     include/linux/dasd_mod.h
 
 S390 IOMMU (PCI)
 M:     Gerald Schaefer <gerald.schaefer@de.ibm.com>
index 073faa6a69b8afca444e417a1f79729bf097c135..d6e18df9c53c6de4de7d68242c4031b5232c6dbd 100644 (file)
 #include <asm/ebcdic.h>
 #include <linux/uaccess.h>
 #include <asm/vtoc.h>
+#include <linux/module.h>
+#include <linux/dasd_mod.h>
 
 #include "check.h"
 
-
 union label_t {
        struct vtoc_volume_label_cdl vol;
        struct vtoc_volume_label_ldl lnx;
@@ -288,7 +289,9 @@ static int find_cms1_partitions(struct parsed_partitions *state,
  */
 int ibm_partition(struct parsed_partitions *state)
 {
+       int (*fn)(struct gendisk *disk, dasd_information2_t *info);
        struct block_device *bdev = state->bdev;
+       struct gendisk *disk = bdev->bd_disk;
        int blocksize, res;
        loff_t i_size, offset, size;
        dasd_information2_t *info;
@@ -299,24 +302,31 @@ int ibm_partition(struct parsed_partitions *state)
        union label_t *label;
 
        res = 0;
+       if (!disk->fops->getgeo)
+               goto out_exit;
+       fn = symbol_get(dasd_biodasdinfo);
+       if (!fn)
+               goto out_exit;
        blocksize = bdev_logical_block_size(bdev);
        if (blocksize <= 0)
-               goto out_exit;
+               goto out_symbol;
        i_size = i_size_read(bdev->bd_inode);
        if (i_size == 0)
-               goto out_exit;
+               goto out_symbol;
        info = kmalloc(sizeof(dasd_information2_t), GFP_KERNEL);
        if (info == NULL)
-               goto out_exit;
+               goto out_symbol;
        geo = kmalloc(sizeof(struct hd_geometry), GFP_KERNEL);
        if (geo == NULL)
                goto out_nogeo;
        label = kmalloc(sizeof(union label_t), GFP_KERNEL);
        if (label == NULL)
                goto out_nolab;
-       if (ioctl_by_bdev(bdev, HDIO_GETGEO, (unsigned long)geo) != 0)
+       /* set start if not filled by getgeo function e.g. virtblk */
+       geo->start = get_start_sect(bdev);
+       if (disk->fops->getgeo(bdev, geo))
                goto out_freeall;
-       if (ioctl_by_bdev(bdev, BIODASDINFO2, (unsigned long)info) != 0) {
+       if (fn(disk, info)) {
                kfree(info);
                info = NULL;
        }
@@ -359,6 +369,8 @@ out_nolab:
        kfree(geo);
 out_nogeo:
        kfree(info);
+out_symbol:
+       symbol_put(dasd_biodasdinfo);
 out_exit:
        return res;
 }
index 9b7782395c379114aa80b18eceb4ee6d9061ab43..777734d1b4e58cfac5da5b7c7ca3c39d0b5d12eb 100644 (file)
@@ -22,6 +22,7 @@
 #include <asm/schid.h>
 #include <asm/cmb.h>
 #include <linux/uaccess.h>
+#include <linux/dasd_mod.h>
 
 /* This is ugly... */
 #define PRINTK_HEADER "dasd_ioctl:"
@@ -664,3 +665,36 @@ int dasd_ioctl(struct block_device *bdev, fmode_t mode,
        dasd_put_device(base);
        return rc;
 }
+
+
+/**
+ * dasd_biodasdinfo() - fill out the dasd information structure
+ * @disk [in]: pointer to gendisk structure that references a DASD
+ * @info [out]: pointer to the dasd_information2_t structure
+ *
+ * Provide access to DASD specific information.
+ * The gendisk structure is checked if it belongs to the DASD driver by
+ * comparing the gendisk->fops pointer.
+ * If it does not belong to the DASD driver -EINVAL is returned.
+ * Otherwise the provided dasd_information2_t structure is filled out.
+ *
+ * Returns:
+ *   %0 on success and a negative error value on failure.
+ */
+int dasd_biodasdinfo(struct gendisk *disk, struct dasd_information2_t *info)
+{
+       struct dasd_device *base;
+       int error;
+
+       if (disk->fops != &dasd_device_operations)
+               return -EINVAL;
+
+       base = dasd_device_from_gendisk(disk);
+       if (!base)
+               return -ENODEV;
+       error = __dasd_ioctl_information(base->block, info);
+       dasd_put_device(base);
+       return error;
+}
+/* export that symbol_get in partition detection is possible */
+EXPORT_SYMBOL_GPL(dasd_biodasdinfo);
diff --git a/include/linux/dasd_mod.h b/include/linux/dasd_mod.h
new file mode 100644 (file)
index 0000000..d39abad
--- /dev/null
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef DASD_MOD_H
+#define DASD_MOD_H
+
+#include <asm/dasd.h>
+
+extern int dasd_biodasdinfo(struct gendisk *disk, dasd_information2_t *info);
+
+#endif