diff mbox series

[1/2] s390/dasd: fix inability to use DASD with DIAG driver

Message ID 20200714200327.40927-2-sth@linux.ibm.com (mailing list archive)
State New, archived
Headers show
Series DASD DIAG patches | expand

Commit Message

Stefan Haberland July 14, 2020, 8:03 p.m. UTC
During initialization of the DASD DIAG driver a request is issued
that has a bio structure that resides on the stack. With virtually
mapped kernel stacks this bio address might be in virtual storage
which is unsuitable for usage with the diag250 call.
In this case the device can not be set online using the DIAG
discipline and fails with -EOPNOTSUP.
In the system journal the following error message is presented:

dasd: X.X.XXXX Setting the DASD online with discipline DIAG failed
with rc=-95

Fix by allocating the bio structure instead of having it on the stack.

Fixes: ce3dc447493f ("s390: add support for virtually mapped kernel stacks")
Cc: stable@vger.kernel.org #4.20
Signed-off-by: Stefan Haberland <sth@linux.ibm.com>
Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
---
 drivers/s390/block/dasd_diag.c | 25 +++++++++++++++++--------
 1 file changed, 17 insertions(+), 8 deletions(-)

Comments

Jens Axboe July 14, 2020, 8:12 p.m. UTC | #1
On 7/14/20 2:03 PM, Stefan Haberland wrote:
> During initialization of the DASD DIAG driver a request is issued
> that has a bio structure that resides on the stack. With virtually
> mapped kernel stacks this bio address might be in virtual storage
> which is unsuitable for usage with the diag250 call.
> In this case the device can not be set online using the DIAG
> discipline and fails with -EOPNOTSUP.
> In the system journal the following error message is presented:
> 
> dasd: X.X.XXXX Setting the DASD online with discipline DIAG failed
> with rc=-95
> 
> Fix by allocating the bio structure instead of having it on the stack.
> 
> Fixes: ce3dc447493f ("s390: add support for virtually mapped kernel stacks")
> Cc: stable@vger.kernel.org #4.20
> Signed-off-by: Stefan Haberland <sth@linux.ibm.com>
> Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com>
> ---
>  drivers/s390/block/dasd_diag.c | 25 +++++++++++++++++--------
>  1 file changed, 17 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c
> index facb588d09e4..069d6b39cacf 100644
> --- a/drivers/s390/block/dasd_diag.c
> +++ b/drivers/s390/block/dasd_diag.c
> @@ -319,7 +319,7 @@ dasd_diag_check_device(struct dasd_device *device)
>  	struct dasd_diag_characteristics *rdc_data;
>  	struct vtoc_cms_label *label;
>  	struct dasd_block *block;
> -	struct dasd_diag_bio bio;
> +	struct dasd_diag_bio *bio;
>  	unsigned int sb, bsize;
>  	blocknum_t end_block;
>  	int rc;
> @@ -395,29 +395,36 @@ dasd_diag_check_device(struct dasd_device *device)
>  		rc = -ENOMEM;
>  		goto out;
>  	}
> +	bio = kzalloc(sizeof(*bio), GFP_KERNEL);
> +	if (bio == NULL)  {
> +		DBF_DEV_EVENT(DBF_WARNING, device, "%s",
> +			      "No memory to allocate initialization bio");
> +		rc = -ENOMEM;
> +		goto out_label;
> +	}

Just curious, any reason this isn't just using bio_alloc()?
Christoph Hellwig July 15, 2020, 6:48 a.m. UTC | #2
On Tue, Jul 14, 2020 at 02:12:27PM -0600, Jens Axboe wrote:
> Just curious, any reason this isn't just using bio_alloc()?

The dasd_diag_bio doesn't seem to have anything to do with the
block layer struct bio..
Stefan Haberland July 15, 2020, 1:32 p.m. UTC | #3
Am 15.07.20 um 08:48 schrieb Christoph Hellwig:
> On Tue, Jul 14, 2020 at 02:12:27PM -0600, Jens Axboe wrote:
>> Just curious, any reason this isn't just using bio_alloc()?
> The dasd_diag_bio doesn't seem to have anything to do with the
> block layer struct bio..

exactly, that's a struct dasd_diag_bio.
Jens Axboe July 15, 2020, 2:46 p.m. UTC | #4
On 7/15/20 7:32 AM, Stefan Haberland wrote:
> Am 15.07.20 um 08:48 schrieb Christoph Hellwig:
>> On Tue, Jul 14, 2020 at 02:12:27PM -0600, Jens Axboe wrote:
>>> Just curious, any reason this isn't just using bio_alloc()?
>> The dasd_diag_bio doesn't seem to have anything to do with the
>> block layer struct bio..
> 
> exactly, that's a struct dasd_diag_bio.

Duh, guess I should have looked a bit more closely...
diff mbox series

Patch

diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c
index facb588d09e4..069d6b39cacf 100644
--- a/drivers/s390/block/dasd_diag.c
+++ b/drivers/s390/block/dasd_diag.c
@@ -319,7 +319,7 @@  dasd_diag_check_device(struct dasd_device *device)
 	struct dasd_diag_characteristics *rdc_data;
 	struct vtoc_cms_label *label;
 	struct dasd_block *block;
-	struct dasd_diag_bio bio;
+	struct dasd_diag_bio *bio;
 	unsigned int sb, bsize;
 	blocknum_t end_block;
 	int rc;
@@ -395,29 +395,36 @@  dasd_diag_check_device(struct dasd_device *device)
 		rc = -ENOMEM;
 		goto out;
 	}
+	bio = kzalloc(sizeof(*bio), GFP_KERNEL);
+	if (bio == NULL)  {
+		DBF_DEV_EVENT(DBF_WARNING, device, "%s",
+			      "No memory to allocate initialization bio");
+		rc = -ENOMEM;
+		goto out_label;
+	}
 	rc = 0;
 	end_block = 0;
 	/* try all sizes - needed for ECKD devices */
 	for (bsize = 512; bsize <= PAGE_SIZE; bsize <<= 1) {
 		mdsk_init_io(device, bsize, 0, &end_block);
-		memset(&bio, 0, sizeof (struct dasd_diag_bio));
-		bio.type = MDSK_READ_REQ;
-		bio.block_number = private->pt_block + 1;
-		bio.buffer = label;
+		memset(bio, 0, sizeof(*bio));
+		bio->type = MDSK_READ_REQ;
+		bio->block_number = private->pt_block + 1;
+		bio->buffer = label;
 		memset(&private->iob, 0, sizeof (struct dasd_diag_rw_io));
 		private->iob.dev_nr = rdc_data->dev_nr;
 		private->iob.key = 0;
 		private->iob.flags = 0;	/* do synchronous io */
 		private->iob.block_count = 1;
 		private->iob.interrupt_params = 0;
-		private->iob.bio_list = &bio;
+		private->iob.bio_list = bio;
 		private->iob.flaga = DASD_DIAG_FLAGA_DEFAULT;
 		rc = dia250(&private->iob, RW_BIO);
 		if (rc == 3) {
 			pr_warn("%s: A 64-bit DIAG call failed\n",
 				dev_name(&device->cdev->dev));
 			rc = -EOPNOTSUPP;
-			goto out_label;
+			goto out_bio;
 		}
 		mdsk_term_io(device);
 		if (rc == 0)
@@ -427,7 +434,7 @@  dasd_diag_check_device(struct dasd_device *device)
 		pr_warn("%s: Accessing the DASD failed because of an incorrect format (rc=%d)\n",
 			dev_name(&device->cdev->dev), rc);
 		rc = -EIO;
-		goto out_label;
+		goto out_bio;
 	}
 	/* check for label block */
 	if (memcmp(label->label_id, DASD_DIAG_CMS1,
@@ -457,6 +464,8 @@  dasd_diag_check_device(struct dasd_device *device)
 			(rc == 4) ? ", read-only device" : "");
 		rc = 0;
 	}
+out_bio:
+	kfree(bio);
 out_label:
 	free_page((long) label);
 out: