s390/dasd: fix read device characteristic with CONFIG_VMAP_STACK=y
authorMartin Schwidefsky <schwidefsky@de.ibm.com>
Fri, 1 Mar 2019 15:03:47 +0000 (16:03 +0100)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Fri, 1 Mar 2019 15:23:56 +0000 (16:23 +0100)
The dasd_eckd_restore_device() function calls dasd_generic_read_dev_chars
with a temporary buffer on the stack. With CONFIG_VMAP_STACK=y this is
a vmalloc address but dasd_generic_restore_device() uses the address of
the buffer as I/O address. Circumvent this by using the already allocated
cqr->data buffer for the RDC data.

Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
drivers/s390/block/dasd.c

index 397af07..e03304f 100644 (file)
@@ -3965,13 +3965,11 @@ int dasd_generic_restore_device(struct ccw_device *cdev)
 EXPORT_SYMBOL_GPL(dasd_generic_restore_device);
 
 static struct dasd_ccw_req *dasd_generic_build_rdc(struct dasd_device *device,
-                                                  void *rdc_buffer,
                                                   int rdc_buffer_size,
                                                   int magic)
 {
        struct dasd_ccw_req *cqr;
        struct ccw1 *ccw;
-       unsigned long *idaw;
 
        cqr = dasd_smalloc_request(magic, 1 /* RDC */, rdc_buffer_size, device,
                                   NULL);
@@ -3986,16 +3984,8 @@ static struct dasd_ccw_req *dasd_generic_build_rdc(struct dasd_device *device,
 
        ccw = cqr->cpaddr;
        ccw->cmd_code = CCW_CMD_RDC;
-       if (idal_is_needed(rdc_buffer, rdc_buffer_size)) {
-               idaw = (unsigned long *) (cqr->data);
-               ccw->cda = (__u32)(addr_t) idaw;
-               ccw->flags = CCW_FLAG_IDA;
-               idaw = idal_create_words(idaw, rdc_buffer, rdc_buffer_size);
-       } else {
-               ccw->cda = (__u32)(addr_t) rdc_buffer;
-               ccw->flags = 0;
-       }
-
+       ccw->cda = (__u32)(addr_t) cqr->data;
+       ccw->flags = 0;
        ccw->count = rdc_buffer_size;
        cqr->startdev = device;
        cqr->memdev = device;
@@ -4013,12 +4003,13 @@ int dasd_generic_read_dev_chars(struct dasd_device *device, int magic,
        int ret;
        struct dasd_ccw_req *cqr;
 
-       cqr = dasd_generic_build_rdc(device, rdc_buffer, rdc_buffer_size,
-                                    magic);
+       cqr = dasd_generic_build_rdc(device, rdc_buffer_size, magic);
        if (IS_ERR(cqr))
                return PTR_ERR(cqr);
 
        ret = dasd_sleep_on(cqr);
+       if (ret == 0)
+               memcpy(rdc_buffer, cqr->data, rdc_buffer_size);
        dasd_sfree_request(cqr, cqr->memdev);
        return ret;
 }