2020-05-19 14:24:58

by Stefan Haberland

[permalink] [raw]
Subject: [PATCH v4 0/2] s390/dasd: remove ioctl_by_bdev from DASD driver

Hi Christoph,

here are the patches again. Reviewed and tested internally with DASD as
well as DASD labeled virtblk devices.
So if you agree with the two patches I have no objection against an
inclusion.

v3->v4:
- merged patches
- use symbol_get instead of kallsyms_lookup_name
- add some comments and some cleanup

Christoph Hellwig (1):
dasd: refactor dasd_ioctl_information

Stefan Haberland (1):
s390/dasd: remove ioctl_by_bdev calls

MAINTAINERS | 1 +
block/partitions/ibm.c | 24 ++++++++---
drivers/s390/block/dasd_ioctl.c | 76 ++++++++++++++++++++++++---------
include/linux/dasd_mod.h | 9 ++++
4 files changed, 85 insertions(+), 25 deletions(-)
create mode 100644 include/linux/dasd_mod.h

--
2.17.1


2020-05-19 14:24:58

by Stefan Haberland

[permalink] [raw]
Subject: [PATCH v4 2/2] s390/dasd: remove ioctl_by_bdev calls

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 <[email protected]>
Signed-off-by: Stefan Haberland <[email protected]>
Reviewed-by: Jan Hoeppner <[email protected]>
Reviewed-by: Peter Oberparleiter <[email protected]>
---
MAINTAINERS | 1 +
block/partitions/ibm.c | 24 +++++++++++++++++------
drivers/s390/block/dasd_ioctl.c | 34 +++++++++++++++++++++++++++++++++
include/linux/dasd_mod.h | 9 +++++++++
4 files changed, 62 insertions(+), 6 deletions(-)
create mode 100644 include/linux/dasd_mod.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 1608ef8ce8d3..37f700187d74 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -14625,6 +14625,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 <[email protected]>
diff --git a/block/partitions/ibm.c b/block/partitions/ibm.c
index 073faa6a69b8..d6e18df9c53c 100644
--- a/block/partitions/ibm.c
+++ b/block/partitions/ibm.c
@@ -13,10 +13,11 @@
#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 @@ int ibm_partition(struct parsed_partitions *state)
kfree(geo);
out_nogeo:
kfree(info);
+out_symbol:
+ symbol_put(dasd_biodasdinfo);
out_exit:
return res;
}
diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c
index 9b7782395c37..777734d1b4e5 100644
--- a/drivers/s390/block/dasd_ioctl.c
+++ b/drivers/s390/block/dasd_ioctl.c
@@ -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
index 000000000000..d39abad2ff6e
--- /dev/null
+++ b/include/linux/dasd_mod.h
@@ -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
--
2.17.1

2020-05-19 14:25:22

by Stefan Haberland

[permalink] [raw]
Subject: [PATCH v4 1/2] dasd: refactor dasd_ioctl_information

From: Christoph Hellwig <[email protected]>

Prepare for in-kernel callers of this functionality.

Signed-off-by: Christoph Hellwig <[email protected]>
[[email protected]: remove leftover kfree]
Signed-off-by: Stefan Haberland <[email protected]>
Reviewed-by: Peter Oberparleiter <[email protected]>
Reviewed-by: Jan Hoeppner <[email protected]>
---
drivers/s390/block/dasd_ioctl.c | 42 ++++++++++++++++++---------------
1 file changed, 23 insertions(+), 19 deletions(-)

diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c
index 9a5f3add325f..9b7782395c37 100644
--- a/drivers/s390/block/dasd_ioctl.c
+++ b/drivers/s390/block/dasd_ioctl.c
@@ -457,10 +457,9 @@ static int dasd_ioctl_read_profile(struct dasd_block *block, void __user *argp)
/*
* Return dasd information. Used for BIODASDINFO and BIODASDINFO2.
*/
-static int dasd_ioctl_information(struct dasd_block *block,
- unsigned int cmd, void __user *argp)
+static int __dasd_ioctl_information(struct dasd_block *block,
+ struct dasd_information2_t *dasd_info)
{
- struct dasd_information2_t *dasd_info;
struct subchannel_id sch_id;
struct ccw_dev_id dev_id;
struct dasd_device *base;
@@ -473,15 +472,9 @@ static int dasd_ioctl_information(struct dasd_block *block,
if (!base->discipline || !base->discipline->fill_info)
return -EINVAL;

- dasd_info = kzalloc(sizeof(struct dasd_information2_t), GFP_KERNEL);
- if (dasd_info == NULL)
- return -ENOMEM;
-
rc = base->discipline->fill_info(base, dasd_info);
- if (rc) {
- kfree(dasd_info);
+ if (rc)
return rc;
- }

cdev = base->cdev;
ccw_device_get_id(cdev, &dev_id);
@@ -520,15 +513,24 @@ static int dasd_ioctl_information(struct dasd_block *block,
list_for_each(l, &base->ccw_queue)
dasd_info->chanq_len++;
spin_unlock_irqrestore(&block->queue_lock, flags);
+ return 0;
+}

- rc = 0;
- if (copy_to_user(argp, dasd_info,
- ((cmd == (unsigned int) BIODASDINFO2) ?
- sizeof(struct dasd_information2_t) :
- sizeof(struct dasd_information_t))))
- rc = -EFAULT;
+static int dasd_ioctl_information(struct dasd_block *block, void __user *argp,
+ size_t copy_size)
+{
+ struct dasd_information2_t *dasd_info;
+ int error;
+
+ dasd_info = kzalloc(sizeof(*dasd_info), GFP_KERNEL);
+ if (!dasd_info)
+ return -ENOMEM;
+
+ error = __dasd_ioctl_information(block, dasd_info);
+ if (!error && copy_to_user(argp, dasd_info, copy_size))
+ error = -EFAULT;
kfree(dasd_info);
- return rc;
+ return error;
}

/*
@@ -622,10 +624,12 @@ int dasd_ioctl(struct block_device *bdev, fmode_t mode,
rc = dasd_ioctl_check_format(bdev, argp);
break;
case BIODASDINFO:
- rc = dasd_ioctl_information(block, cmd, argp);
+ rc = dasd_ioctl_information(block, argp,
+ sizeof(struct dasd_information_t));
break;
case BIODASDINFO2:
- rc = dasd_ioctl_information(block, cmd, argp);
+ rc = dasd_ioctl_information(block, argp,
+ sizeof(struct dasd_information2_t));
break;
case BIODASDPRRD:
rc = dasd_ioctl_read_profile(block, argp);
--
2.17.1

2020-05-19 14:33:49

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [PATCH v4 2/2] s390/dasd: remove ioctl_by_bdev calls

Looks good:

Reviewed-by: Christoph Hellwig <[email protected]>

2020-05-19 14:35:38

by Christoph Hellwig

[permalink] [raw]
Subject: [PATCH 3/2] block: remove ioctl_by_bdev

No callers left.

Signed-off-by: Christoph Hellwig <[email protected]>
---
fs/block_dev.c | 12 ------------
include/linux/fs.h | 1 -
2 files changed, 13 deletions(-)

diff --git a/fs/block_dev.c b/fs/block_dev.c
index ebd1507789d29..2eb92456a22e7 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -2166,18 +2166,6 @@ const struct file_operations def_blk_fops = {
.fallocate = blkdev_fallocate,
};

-int ioctl_by_bdev(struct block_device *bdev, unsigned cmd, unsigned long arg)
-{
- int res;
- mm_segment_t old_fs = get_fs();
- set_fs(KERNEL_DS);
- res = blkdev_ioctl(bdev, 0, cmd, arg);
- set_fs(old_fs);
- return res;
-}
-
-EXPORT_SYMBOL(ioctl_by_bdev);
-
/**
* lookup_bdev - lookup a struct block_device by name
* @pathname: special file representing the block device
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 1a95e51588113..861ca61d728bc 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2636,7 +2636,6 @@ extern int sync_filesystem(struct super_block *);
extern const struct file_operations def_blk_fops;
extern const struct file_operations def_chr_fops;
#ifdef CONFIG_BLOCK
-extern int ioctl_by_bdev(struct block_device *, unsigned, unsigned long);
extern int blkdev_ioctl(struct block_device *, fmode_t, unsigned, unsigned long);
extern long compat_blkdev_ioctl(struct file *, unsigned, unsigned long);
extern int blkdev_get(struct block_device *bdev, fmode_t mode, void *holder);
--
2.26.2

2020-05-19 19:08:15

by Al Viro

[permalink] [raw]
Subject: Re: [PATCH 3/2] block: remove ioctl_by_bdev

On Tue, May 19, 2020 at 04:33:21PM +0200, Christoph Hellwig wrote:
> No callers left.

No callers left after...? IOW, where are the patches? There'd been
several patchsets posted, each with more than one revision...

I realize that some of that went into -mm, but could you repost
the final variant of the entire pile and/or tell which set of
git branches to look at?

2020-05-19 19:31:57

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [PATCH 3/2] block: remove ioctl_by_bdev

On Tue, May 19, 2020 at 08:03:33PM +0100, Al Viro wrote:
> On Tue, May 19, 2020 at 04:33:21PM +0200, Christoph Hellwig wrote:
> > No callers left.
>
> No callers left after...? IOW, where are the patches? There'd been
> several patchsets posted, each with more than one revision...

In Jens' for-5.8/block tree, which has all the patches to remove them
merged.

Link: https://git.kernel.dk/cgit/linux-block/log/?h=for-5.8/block

2020-05-21 14:24:59

by Jens Axboe

[permalink] [raw]
Subject: Re: [PATCH v4 0/2] s390/dasd: remove ioctl_by_bdev from DASD driver

On 5/19/20 8:22 AM, Stefan Haberland wrote:
> Hi Christoph,
>
> here are the patches again. Reviewed and tested internally with DASD as
> well as DASD labeled virtblk devices.
> So if you agree with the two patches I have no objection against an
> inclusion.

Applied for 5.8, with Christoph's removal patch as well.

--
Jens Axboe

2020-10-07 11:07:31

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [PATCH v4 2/2] s390/dasd: remove ioctl_by_bdev calls

On Wed, Oct 07, 2020 at 11:34:17AM +0200, Christian Borntraeger wrote:
>
> On 19.05.20 16:22, Stefan Haberland wrote:
> > 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 <[email protected]>
> > Signed-off-by: Stefan Haberland <[email protected]>
> > Reviewed-by: Jan Hoeppner <[email protected]>
> > Reviewed-by: Peter Oberparleiter <[email protected]>
>
> FWIW, this broken the ibm-partition code for virtio-blk, when CONFIG_DASD=m.

What are the symptoms?

2020-10-07 11:14:43

by Stefan Haberland

[permalink] [raw]
Subject: Re: [PATCH v4 2/2] s390/dasd: remove ioctl_by_bdev calls

Am 07.10.20 um 12:44 schrieb Christian Borntraeger:
>
> On 07.10.20 12:39, Christoph Hellwig wrote:
>> On Wed, Oct 07, 2020 at 11:34:17AM +0200, Christian Borntraeger wrote:
>>> On 19.05.20 16:22, Stefan Haberland wrote:
>>>> 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 <[email protected]>
>>>> Signed-off-by: Stefan Haberland <[email protected]>
>>>> Reviewed-by: Jan Hoeppner <[email protected]>
>>>> Reviewed-by: Peter Oberparleiter <[email protected]>
>>> FWIW, this broken the ibm-partition code for virtio-blk, when CONFIG_DASD=m.
>> What are the symptoms?
> During boot I normally have
>
> [ 0.930231] virtio_blk virtio1: [vda] 5409180 4096-byte logical blocks (22.2 GB/20.6 GiB)
> [ 0.930233] vda: detected capacity change from 0 to 22156001280
> [ 0.932806] vda:VOL1/ 0X3333: vda1 vda2 vda3
>
> With this change, the last line is no longer there (if CONFIG_DASD=m) and this also
> reflects itself in /proc/partitions. The partitions are no longer detected.

OK, looks like the module is not loaded and with

        fn = symbol_get(dasd_biodasdinfo);
        if (!fn)
                goto out_exit;

the ibm.c partition detection aborts.

Solution could be not to exit in this case but jump to the probing
process. I will have a closer look at this.

2020-10-07 12:12:28

by Christian Borntraeger

[permalink] [raw]
Subject: Re: [PATCH v4 2/2] s390/dasd: remove ioctl_by_bdev calls

On 07.10.20 14:00, Christoph Hellwig wrote:
> On Wed, Oct 07, 2020 at 12:44:55PM +0200, Christian Borntraeger wrote:
>>
>>
>> On 07.10.20 12:39, Christoph Hellwig wrote:
>>> On Wed, Oct 07, 2020 at 11:34:17AM +0200, Christian Borntraeger wrote:
>>>>
>>>> On 19.05.20 16:22, Stefan Haberland wrote:
>>>>> 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 <[email protected]>
>>>>> Signed-off-by: Stefan Haberland <[email protected]>
>>>>> Reviewed-by: Jan Hoeppner <[email protected]>
>>>>> Reviewed-by: Peter Oberparleiter <[email protected]>
>>>>
>>>> FWIW, this broken the ibm-partition code for virtio-blk, when CONFIG_DASD=m.
>>>
>>> What are the symptoms?
>>
>> During boot I normally have
>
>> [ 0.930231] virtio_blk virtio1: [vda] 5409180 4096-byte logical blocks (22.2 GB/20.6 GiB)
>> [ 0.930233] vda: detected capacity change from 0 to 22156001280
>> [ 0.932806] vda:VOL1/ 0X3333: vda1 vda2 vda3
>>
>> With this change, the last line is no longer there (if CONFIG_DASD=m) and this also
>> reflects itself in /proc/partitions. The partitions are no longer detected.
>
> Can you try this patch?


>
> diff --git a/block/partitions/ibm.c b/block/partitions/ibm.c
> index d6e18df9c53c6d..d91cee558ce67a 100644
> --- a/block/partitions/ibm.c
> +++ b/block/partitions/ibm.c
> @@ -305,8 +305,6 @@ int ibm_partition(struct parsed_partitions *state)
> 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_symbol;
> @@ -326,7 +324,7 @@ int ibm_partition(struct parsed_partitions *state)
> geo->start = get_start_sect(bdev);
> if (disk->fops->getgeo(bdev, geo))
> goto out_freeall;
> - if (fn(disk, info)) {
> + if (!fn || fn(disk, info)) {
> kfree(info);
> info = NULL;
> }
>

Unfortunately not. On insmodding virtio_blk I do get:
[ 3.331256] vda: detected capacity change from 0 to 22156001280
[ 3.332381] ------------[ cut here ]------------
[ 3.332382] kernel BUG at kernel/module.c:1081!
[ 3.332420] monitor event: 0040 ilc:2 [#1] SMP
[ 3.332422] Modules linked in: virtio_blk(+) kvm
[ 3.332425] CPU: 0 PID: 136 Comm: insmod Not tainted 5.8.13+ #54
[ 3.332425] Hardware name: IBM 3906 M04 704 (KVM/Linux)
[ 3.332426] Krnl PSW : 0704c00180000000 0000000016cf4fc6 (__symbol_put+0x56/0x58)
[ 3.332434] R:0 T:1 IO:1 EX:1 Key:0 M:1 W:0 P:0 AS:3 CC:0 PM:0 RI:0 EA:3
[ 3.332435] Krnl GPRS: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
[ 3.332436] 0000000000000000 0000000000000018 0000000000000000 0000000000000098
[ 3.332437] 0000000000000000 0000000000000001 0000000000000000 0000000004fd9180
[ 3.332438] 000000001f70c000 0000000004fd9360 0000000016cf4fa2 000003e0000f7648
[ 3.332445] Krnl Code: 0000000016cf4fb8: f0a8000407fe srp 4(11,%r0),2046,8
[ 3.332445] 0000000016cf4fbe: 47000700 bc 0,1792
[ 3.332445] #0000000016cf4fc2: af000000 mc 0,0
[ 3.332445] >0000000016cf4fc6: 0707 bcr 0,%r7
[ 3.332445] 0000000016cf4fc8: c00400000000 brcl 0,0000000016cf4fc8
[ 3.332445] 0000000016cf4fce: eb6ff0480024 stmg %r6,%r15,72(%r15)
[ 3.332445] 0000000016cf4fd4: b90400ef lgr %r14,%r15
[ 3.332445] 0000000016cf4fd8: b90400b4 lgr %r11,%r4
[ 3.332454] Call Trace:
[ 3.332456] [<0000000016cf4fc6>] __symbol_put+0x56/0x58
[ 3.332458] ([<0000000016cf4fa2>] __symbol_put+0x32/0x58)
[ 3.332462] [<00000000171be268>] ibm_partition+0xa0/0xa28
[ 3.332464] [<00000000171b952c>] blk_add_partitions+0x184/0x5b8
[ 3.332467] [<0000000016f07e94>] bdev_disk_changed+0x8c/0x120
[ 3.332468] [<0000000016f09872>] __blkdev_get+0x3fa/0x598
[ 3.332469] [<0000000016f09a42>] blkdev_get+0x32/0x1c8
[ 3.332471] [<00000000171b5ee4>] __device_add_disk+0x32c/0x510
[ 3.332473] [<000003ff80068de0>] virtblk_probe+0x5f0/0xc30 [virtio_blk]
[ 3.332477] [<00000000172cc110>] virtio_dev_probe+0x178/0x2a0
[ 3.332480] [<000000001731cecc>] really_probe+0xf4/0x498
[ 3.332481] [<000000001731da1a>] device_driver_attach+0xd2/0xd8
[ 3.332482] [<000000001731dad8>] __driver_attach+0xb8/0x180
[ 3.332483] [<000000001731a1e2>] bus_for_each_dev+0x82/0xb8
[ 3.332484] [<000000001731bf66>] bus_add_driver+0x1fe/0x248
[ 3.332486] [<000000001731e340>] driver_register+0xa0/0x168
[ 3.332487] [<000003ff8006e068>] init+0x68/0x1000 [virtio_blk]
[ 3.332489] [<0000000016bfc884>] do_one_initcall+0x3c/0x1f8
[ 3.332490] [<0000000016cf6c98>] do_init_module+0x68/0x290
[ 3.332491] [<0000000016cf9eec>] __do_sys_finit_module+0xa4/0xe8
[ 3.332494] [<000000001766c760>] system_call+0xdc/0x2b0
[ 3.332495] Last Breaking-Event-Address:
[ 3.332496] [<0000000016cf4fa6>] __symbol_put+0x36/0x58
[ 3.332498] ---[ end trace 4a4a7a5643aab422 ]---




2020-10-07 15:27:21

by Christian Borntraeger

[permalink] [raw]
Subject: Re: [PATCH v4 2/2] s390/dasd: remove ioctl_by_bdev calls


On 19.05.20 16:22, Stefan Haberland wrote:
> 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 <[email protected]>
> Signed-off-by: Stefan Haberland <[email protected]>
> Reviewed-by: Jan Hoeppner <[email protected]>
> Reviewed-by: Peter Oberparleiter <[email protected]>

FWIW, this broken the ibm-partition code for virtio-blk, when CONFIG_DASD=m.

> ---
> MAINTAINERS | 1 +
> block/partitions/ibm.c | 24 +++++++++++++++++------
> drivers/s390/block/dasd_ioctl.c | 34 +++++++++++++++++++++++++++++++++
> include/linux/dasd_mod.h | 9 +++++++++
> 4 files changed, 62 insertions(+), 6 deletions(-)
> create mode 100644 include/linux/dasd_mod.h
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 1608ef8ce8d3..37f700187d74 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -14625,6 +14625,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 <[email protected]>
> diff --git a/block/partitions/ibm.c b/block/partitions/ibm.c
> index 073faa6a69b8..d6e18df9c53c 100644
> --- a/block/partitions/ibm.c
> +++ b/block/partitions/ibm.c
> @@ -13,10 +13,11 @@
> #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 @@ int ibm_partition(struct parsed_partitions *state)
> kfree(geo);
> out_nogeo:
> kfree(info);
> +out_symbol:
> + symbol_put(dasd_biodasdinfo);
> out_exit:
> return res;
> }
> diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c
> index 9b7782395c37..777734d1b4e5 100644
> --- a/drivers/s390/block/dasd_ioctl.c
> +++ b/drivers/s390/block/dasd_ioctl.c
> @@ -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
> index 000000000000..d39abad2ff6e
> --- /dev/null
> +++ b/include/linux/dasd_mod.h
> @@ -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
>

2020-10-07 17:04:49

by Christian Borntraeger

[permalink] [raw]
Subject: Re: [PATCH v4 2/2] s390/dasd: remove ioctl_by_bdev calls



On 07.10.20 12:39, Christoph Hellwig wrote:
> On Wed, Oct 07, 2020 at 11:34:17AM +0200, Christian Borntraeger wrote:
>>
>> On 19.05.20 16:22, Stefan Haberland wrote:
>>> 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 <[email protected]>
>>> Signed-off-by: Stefan Haberland <[email protected]>
>>> Reviewed-by: Jan Hoeppner <[email protected]>
>>> Reviewed-by: Peter Oberparleiter <[email protected]>
>>
>> FWIW, this broken the ibm-partition code for virtio-blk, when CONFIG_DASD=m.
>
> What are the symptoms?

During boot I normally have

[ 0.930231] virtio_blk virtio1: [vda] 5409180 4096-byte logical blocks (22.2 GB/20.6 GiB)
[ 0.930233] vda: detected capacity change from 0 to 22156001280
[ 0.932806] vda:VOL1/ 0X3333: vda1 vda2 vda3

With this change, the last line is no longer there (if CONFIG_DASD=m) and this also
reflects itself in /proc/partitions. The partitions are no longer detected.

2020-10-07 17:08:31

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [PATCH v4 2/2] s390/dasd: remove ioctl_by_bdev calls

On Wed, Oct 07, 2020 at 12:44:55PM +0200, Christian Borntraeger wrote:
>
>
> On 07.10.20 12:39, Christoph Hellwig wrote:
> > On Wed, Oct 07, 2020 at 11:34:17AM +0200, Christian Borntraeger wrote:
> >>
> >> On 19.05.20 16:22, Stefan Haberland wrote:
> >>> 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 <[email protected]>
> >>> Signed-off-by: Stefan Haberland <[email protected]>
> >>> Reviewed-by: Jan Hoeppner <[email protected]>
> >>> Reviewed-by: Peter Oberparleiter <[email protected]>
> >>
> >> FWIW, this broken the ibm-partition code for virtio-blk, when CONFIG_DASD=m.
> >
> > What are the symptoms?
>
> During boot I normally have

> [ 0.930231] virtio_blk virtio1: [vda] 5409180 4096-byte logical blocks (22.2 GB/20.6 GiB)
> [ 0.930233] vda: detected capacity change from 0 to 22156001280
> [ 0.932806] vda:VOL1/ 0X3333: vda1 vda2 vda3
>
> With this change, the last line is no longer there (if CONFIG_DASD=m) and this also
> reflects itself in /proc/partitions. The partitions are no longer detected.

Can you try this patch?

diff --git a/block/partitions/ibm.c b/block/partitions/ibm.c
index d6e18df9c53c6d..d91cee558ce67a 100644
--- a/block/partitions/ibm.c
+++ b/block/partitions/ibm.c
@@ -305,8 +305,6 @@ int ibm_partition(struct parsed_partitions *state)
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_symbol;
@@ -326,7 +324,7 @@ int ibm_partition(struct parsed_partitions *state)
geo->start = get_start_sect(bdev);
if (disk->fops->getgeo(bdev, geo))
goto out_freeall;
- if (fn(disk, info)) {
+ if (!fn || fn(disk, info)) {
kfree(info);
info = NULL;
}

2020-10-07 17:13:53

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [PATCH v4 2/2] s390/dasd: remove ioctl_by_bdev calls

On Wed, Oct 07, 2020 at 02:09:18PM +0200, Christian Borntraeger wrote:
> Unfortunately not. On insmodding virtio_blk I do get:

Yeah, the symbol_put needs to be conditional as well. New version below:

diff --git a/block/partitions/ibm.c b/block/partitions/ibm.c
index d6e18df9c53c6d..4b044e620d3534 100644
--- a/block/partitions/ibm.c
+++ b/block/partitions/ibm.c
@@ -305,8 +305,6 @@ int ibm_partition(struct parsed_partitions *state)
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_symbol;
@@ -326,7 +324,7 @@ int ibm_partition(struct parsed_partitions *state)
geo->start = get_start_sect(bdev);
if (disk->fops->getgeo(bdev, geo))
goto out_freeall;
- if (fn(disk, info)) {
+ if (!fn || fn(disk, info)) {
kfree(info);
info = NULL;
}
@@ -370,7 +368,8 @@ int ibm_partition(struct parsed_partitions *state)
out_nogeo:
kfree(info);
out_symbol:
- symbol_put(dasd_biodasdinfo);
+ if (fn)
+ symbol_put(dasd_biodasdinfo);
out_exit:
return res;
}

2020-10-07 17:15:00

by Christian Borntraeger

[permalink] [raw]
Subject: Re: [PATCH v4 2/2] s390/dasd: remove ioctl_by_bdev calls



On 07.10.20 14:14, Christoph Hellwig wrote:
> On Wed, Oct 07, 2020 at 02:09:18PM +0200, Christian Borntraeger wrote:
>> Unfortunately not. On insmodding virtio_blk I do get:
>
> Yeah, the symbol_put needs to be conditional as well. New version below:

Yes, this works.
>
> diff --git a/block/partitions/ibm.c b/block/partitions/ibm.c
> index d6e18df9c53c6d..4b044e620d3534 100644
> --- a/block/partitions/ibm.c
> +++ b/block/partitions/ibm.c
> @@ -305,8 +305,6 @@ int ibm_partition(struct parsed_partitions *state)
> 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_symbol;
> @@ -326,7 +324,7 @@ int ibm_partition(struct parsed_partitions *state)
> geo->start = get_start_sect(bdev);
> if (disk->fops->getgeo(bdev, geo))
> goto out_freeall;
> - if (fn(disk, info)) {
> + if (!fn || fn(disk, info)) {
> kfree(info);
> info = NULL;
> }
> @@ -370,7 +368,8 @@ int ibm_partition(struct parsed_partitions *state)
> out_nogeo:
> kfree(info);
> out_symbol:
> - symbol_put(dasd_biodasdinfo);
> + if (fn)
> + symbol_put(dasd_biodasdinfo);
> out_exit:
> return res;
> }
>