Skip to content

Commit 5b53a40

Browse files
Stefan Haberlandaxboe
authored andcommitted
s390/dasd: fix data corruption for ESE devices
For ESE devices we get an error when accessing an unformatted track. The handling of this error will return zero data for read requests and format the track on demand before writing to it. To do this the code needs to distinguish between read and write requests. This is done with data from the blocklayer request. A pointer to the blocklayer request is stored in the CQR. If there is an error on the device an ERP request is built to do error recovery. While the ERP request is mostly a copy of the original CQR the pointer to the blocklayer request is not copied to not accidentally pass it back to the blocklayer without cleanup. This leads to the error that during ESE handling after an ERP request was built it is not possible to determine the IO direction. This leads to the formatting of a track for read requests which might in turn lead to data corruption. Fixes: 5e2b17e ("s390/dasd: Add dynamic formatting support for ESE volumes") Cc: stable@vger.kernel.org # 5.3+ Signed-off-by: Stefan Haberland <sth@linux.ibm.com> Reviewed-by: Jan Hoeppner <hoeppner@linux.ibm.com> Link: https://lore.kernel.org/r/20220505141733.1989450-2-sth@linux.ibm.com Signed-off-by: Jens Axboe <axboe@kernel.dk>
1 parent 285d573 commit 5b53a40

3 files changed

Lines changed: 20 additions & 2 deletions

File tree

drivers/s390/block/dasd.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1639,6 +1639,7 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
16391639
unsigned long now;
16401640
int nrf_suppressed = 0;
16411641
int fp_suppressed = 0;
1642+
struct request *req;
16421643
u8 *sense = NULL;
16431644
int expires;
16441645

@@ -1739,7 +1740,12 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
17391740
}
17401741

17411742
if (dasd_ese_needs_format(cqr->block, irb)) {
1742-
if (rq_data_dir((struct request *)cqr->callback_data) == READ) {
1743+
req = dasd_get_callback_data(cqr);
1744+
if (!req) {
1745+
cqr->status = DASD_CQR_ERROR;
1746+
return;
1747+
}
1748+
if (rq_data_dir(req) == READ) {
17431749
device->discipline->ese_read(cqr, irb);
17441750
cqr->status = DASD_CQR_SUCCESS;
17451751
cqr->stopclk = now;

drivers/s390/block/dasd_eckd.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3145,7 +3145,7 @@ dasd_eckd_ese_format(struct dasd_device *startdev, struct dasd_ccw_req *cqr,
31453145
sector_t curr_trk;
31463146
int rc;
31473147

3148-
req = cqr->callback_data;
3148+
req = dasd_get_callback_data(cqr);
31493149
block = cqr->block;
31503150
base = block->base;
31513151
private = base->private;

drivers/s390/block/dasd_int.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -756,6 +756,18 @@ dasd_check_blocksize(int bsize)
756756
return 0;
757757
}
758758

759+
/*
760+
* return the callback data of the original request in case there are
761+
* ERP requests build on top of it
762+
*/
763+
static inline void *dasd_get_callback_data(struct dasd_ccw_req *cqr)
764+
{
765+
while (cqr->refers)
766+
cqr = cqr->refers;
767+
768+
return cqr->callback_data;
769+
}
770+
759771
/* externals in dasd.c */
760772
#define DASD_PROFILE_OFF 0
761773
#define DASD_PROFILE_ON 1

0 commit comments

Comments
 (0)