Commit 9f4aa523 authored by Stefan Haberland's avatar Stefan Haberland Committed by Jens Axboe

s390/dasd: fix inability to use DASD with DIAG driver

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: ce3dc447 ("s390: add support for virtually mapped kernel stacks")
Signed-off-by: default avatarStefan Haberland <sth@linux.ibm.com>
Reviewed-by: default avatarPeter Oberparleiter <oberpar@linux.ibm.com>
Cc: stable@vger.kernel.org #4.20
Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 2eaac320
...@@ -319,7 +319,7 @@ dasd_diag_check_device(struct dasd_device *device) ...@@ -319,7 +319,7 @@ dasd_diag_check_device(struct dasd_device *device)
struct dasd_diag_characteristics *rdc_data; struct dasd_diag_characteristics *rdc_data;
struct vtoc_cms_label *label; struct vtoc_cms_label *label;
struct dasd_block *block; struct dasd_block *block;
struct dasd_diag_bio bio; struct dasd_diag_bio *bio;
unsigned int sb, bsize; unsigned int sb, bsize;
blocknum_t end_block; blocknum_t end_block;
int rc; int rc;
...@@ -395,29 +395,36 @@ dasd_diag_check_device(struct dasd_device *device) ...@@ -395,29 +395,36 @@ dasd_diag_check_device(struct dasd_device *device)
rc = -ENOMEM; rc = -ENOMEM;
goto out; 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; rc = 0;
end_block = 0; end_block = 0;
/* try all sizes - needed for ECKD devices */ /* try all sizes - needed for ECKD devices */
for (bsize = 512; bsize <= PAGE_SIZE; bsize <<= 1) { for (bsize = 512; bsize <= PAGE_SIZE; bsize <<= 1) {
mdsk_init_io(device, bsize, 0, &end_block); mdsk_init_io(device, bsize, 0, &end_block);
memset(&bio, 0, sizeof (struct dasd_diag_bio)); memset(bio, 0, sizeof(*bio));
bio.type = MDSK_READ_REQ; bio->type = MDSK_READ_REQ;
bio.block_number = private->pt_block + 1; bio->block_number = private->pt_block + 1;
bio.buffer = label; bio->buffer = label;
memset(&private->iob, 0, sizeof (struct dasd_diag_rw_io)); memset(&private->iob, 0, sizeof (struct dasd_diag_rw_io));
private->iob.dev_nr = rdc_data->dev_nr; private->iob.dev_nr = rdc_data->dev_nr;
private->iob.key = 0; private->iob.key = 0;
private->iob.flags = 0; /* do synchronous io */ private->iob.flags = 0; /* do synchronous io */
private->iob.block_count = 1; private->iob.block_count = 1;
private->iob.interrupt_params = 0; private->iob.interrupt_params = 0;
private->iob.bio_list = &bio; private->iob.bio_list = bio;
private->iob.flaga = DASD_DIAG_FLAGA_DEFAULT; private->iob.flaga = DASD_DIAG_FLAGA_DEFAULT;
rc = dia250(&private->iob, RW_BIO); rc = dia250(&private->iob, RW_BIO);
if (rc == 3) { if (rc == 3) {
pr_warn("%s: A 64-bit DIAG call failed\n", pr_warn("%s: A 64-bit DIAG call failed\n",
dev_name(&device->cdev->dev)); dev_name(&device->cdev->dev));
rc = -EOPNOTSUPP; rc = -EOPNOTSUPP;
goto out_label; goto out_bio;
} }
mdsk_term_io(device); mdsk_term_io(device);
if (rc == 0) if (rc == 0)
...@@ -427,7 +434,7 @@ dasd_diag_check_device(struct dasd_device *device) ...@@ -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", pr_warn("%s: Accessing the DASD failed because of an incorrect format (rc=%d)\n",
dev_name(&device->cdev->dev), rc); dev_name(&device->cdev->dev), rc);
rc = -EIO; rc = -EIO;
goto out_label; goto out_bio;
} }
/* check for label block */ /* check for label block */
if (memcmp(label->label_id, DASD_DIAG_CMS1, if (memcmp(label->label_id, DASD_DIAG_CMS1,
...@@ -457,6 +464,8 @@ dasd_diag_check_device(struct dasd_device *device) ...@@ -457,6 +464,8 @@ dasd_diag_check_device(struct dasd_device *device)
(rc == 4) ? ", read-only device" : ""); (rc == 4) ? ", read-only device" : "");
rc = 0; rc = 0;
} }
out_bio:
kfree(bio);
out_label: out_label:
free_page((long) label); free_page((long) label);
out: out:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment