Skip to content

Commit

Permalink
s390/dasd: remove ioctl_by_bdev calls
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Stefan Haberland authored and Jens Axboe committed May 21, 2020
1 parent 9353848 commit 26d7e28
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 6 deletions.
1 change: 1 addition & 0 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
24 changes: 18 additions & 6 deletions block/partitions/ibm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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;
}
Expand Down Expand Up @@ -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;
}
34 changes: 34 additions & 0 deletions drivers/s390/block/dasd_ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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:"
Expand Down Expand Up @@ -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);
9 changes: 9 additions & 0 deletions include/linux/dasd_mod.h
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 26d7e28

Please sign in to comment.