Skip to content

Commit 93a7e28

Browse files
Stefan Haberlandgregkh
authored andcommitted
s390/dasd: fix error recovery leading to data corruption on ESE devices
commit 7db4042 upstream. Extent Space Efficient (ESE) or thin provisioned volumes need to be formatted on demand during usual IO processing. The dasd_ese_needs_format function checks for error codes that signal the non existence of a proper track format. The check for incorrect length is to imprecise since other error cases leading to transport of insufficient data also have this flag set. This might lead to data corruption in certain error cases for example during a storage server warmstart. Fix by removing the check for incorrect length and replacing by explicitly checking for invalid track format in transport mode. Also remove the check for file protected since this is not a valid ESE handling case. Cc: stable@vger.kernel.org # 5.3+ Fixes: 5e2b17e ("s390/dasd: Add dynamic formatting support for ESE volumes") Reviewed-by: Jan Hoeppner <hoeppner@linux.ibm.com> Signed-off-by: Stefan Haberland <sth@linux.ibm.com> Link: https://lore.kernel.org/r/20240812125733.126431-3-sth@linux.ibm.com Signed-off-by: Jens Axboe <axboe@kernel.dk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 31ba132 commit 93a7e28

File tree

4 files changed

+50
-53
lines changed

4 files changed

+50
-53
lines changed

drivers/s390/block/dasd.c

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1599,9 +1599,15 @@ static int dasd_ese_needs_format(struct dasd_block *block, struct irb *irb)
15991599
if (!sense)
16001600
return 0;
16011601

1602-
return !!(sense[1] & SNS1_NO_REC_FOUND) ||
1603-
!!(sense[1] & SNS1_FILE_PROTECTED) ||
1604-
scsw_cstat(&irb->scsw) == SCHN_STAT_INCORR_LEN;
1602+
if (sense[1] & SNS1_NO_REC_FOUND)
1603+
return 1;
1604+
1605+
if ((sense[1] & SNS1_INV_TRACK_FORMAT) &&
1606+
scsw_is_tm(&irb->scsw) &&
1607+
!(sense[2] & SNS2_ENV_DATA_PRESENT))
1608+
return 1;
1609+
1610+
return 0;
16051611
}
16061612

16071613
static int dasd_ese_oos_cond(u8 *sense)
@@ -1622,7 +1628,7 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
16221628
struct dasd_device *device;
16231629
unsigned long now;
16241630
int nrf_suppressed = 0;
1625-
int fp_suppressed = 0;
1631+
int it_suppressed = 0;
16261632
struct request *req;
16271633
u8 *sense = NULL;
16281634
int expires;
@@ -1677,8 +1683,9 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
16771683
*/
16781684
sense = dasd_get_sense(irb);
16791685
if (sense) {
1680-
fp_suppressed = (sense[1] & SNS1_FILE_PROTECTED) &&
1681-
test_bit(DASD_CQR_SUPPRESS_FP, &cqr->flags);
1686+
it_suppressed = (sense[1] & SNS1_INV_TRACK_FORMAT) &&
1687+
!(sense[2] & SNS2_ENV_DATA_PRESENT) &&
1688+
test_bit(DASD_CQR_SUPPRESS_IT, &cqr->flags);
16821689
nrf_suppressed = (sense[1] & SNS1_NO_REC_FOUND) &&
16831690
test_bit(DASD_CQR_SUPPRESS_NRF, &cqr->flags);
16841691

@@ -1693,7 +1700,7 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
16931700
return;
16941701
}
16951702
}
1696-
if (!(fp_suppressed || nrf_suppressed))
1703+
if (!(it_suppressed || nrf_suppressed))
16971704
device->discipline->dump_sense_dbf(device, irb, "int");
16981705

16991706
if (device->features & DASD_FEATURE_ERPLOG)
@@ -2465,14 +2472,17 @@ static int _dasd_sleep_on_queue(struct list_head *ccw_queue, int interruptible)
24652472
rc = 0;
24662473
list_for_each_entry_safe(cqr, n, ccw_queue, blocklist) {
24672474
/*
2468-
* In some cases the 'File Protected' or 'Incorrect Length'
2469-
* error might be expected and error recovery would be
2470-
* unnecessary in these cases. Check if the according suppress
2471-
* bit is set.
2475+
* In some cases certain errors might be expected and
2476+
* error recovery would be unnecessary in these cases.
2477+
* Check if the according suppress bit is set.
24722478
*/
24732479
sense = dasd_get_sense(&cqr->irb);
2474-
if (sense && sense[1] & SNS1_FILE_PROTECTED &&
2475-
test_bit(DASD_CQR_SUPPRESS_FP, &cqr->flags))
2480+
if (sense && (sense[1] & SNS1_INV_TRACK_FORMAT) &&
2481+
!(sense[2] & SNS2_ENV_DATA_PRESENT) &&
2482+
test_bit(DASD_CQR_SUPPRESS_IT, &cqr->flags))
2483+
continue;
2484+
if (sense && (sense[1] & SNS1_NO_REC_FOUND) &&
2485+
test_bit(DASD_CQR_SUPPRESS_NRF, &cqr->flags))
24762486
continue;
24772487
if (scsw_cstat(&cqr->irb.scsw) == 0x40 &&
24782488
test_bit(DASD_CQR_SUPPRESS_IL, &cqr->flags))

drivers/s390/block/dasd_3990_erp.c

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1406,14 +1406,8 @@ dasd_3990_erp_file_prot(struct dasd_ccw_req * erp)
14061406

14071407
struct dasd_device *device = erp->startdev;
14081408

1409-
/*
1410-
* In some cases the 'File Protected' error might be expected and
1411-
* log messages shouldn't be written then.
1412-
* Check if the according suppress bit is set.
1413-
*/
1414-
if (!test_bit(DASD_CQR_SUPPRESS_FP, &erp->flags))
1415-
dev_err(&device->cdev->dev,
1416-
"Accessing the DASD failed because of a hardware error\n");
1409+
dev_err(&device->cdev->dev,
1410+
"Accessing the DASD failed because of a hardware error\n");
14171411

14181412
return dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED);
14191413

drivers/s390/block/dasd_eckd.c

Lines changed: 24 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2289,6 +2289,7 @@ dasd_eckd_analysis_ccw(struct dasd_device *device)
22892289
cqr->status = DASD_CQR_FILLED;
22902290
/* Set flags to suppress output for expected errors */
22912291
set_bit(DASD_CQR_SUPPRESS_NRF, &cqr->flags);
2292+
set_bit(DASD_CQR_SUPPRESS_IT, &cqr->flags);
22922293

22932294
return cqr;
22942295
}
@@ -2570,7 +2571,6 @@ dasd_eckd_build_check_tcw(struct dasd_device *base, struct format_data_t *fdata,
25702571
cqr->buildclk = get_tod_clock();
25712572
cqr->status = DASD_CQR_FILLED;
25722573
/* Set flags to suppress output for expected errors */
2573-
set_bit(DASD_CQR_SUPPRESS_FP, &cqr->flags);
25742574
set_bit(DASD_CQR_SUPPRESS_IL, &cqr->flags);
25752575

25762576
return cqr;
@@ -4146,8 +4146,6 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_single(
41464146

41474147
/* Set flags to suppress output for expected errors */
41484148
if (dasd_eckd_is_ese(basedev)) {
4149-
set_bit(DASD_CQR_SUPPRESS_FP, &cqr->flags);
4150-
set_bit(DASD_CQR_SUPPRESS_IL, &cqr->flags);
41514149
set_bit(DASD_CQR_SUPPRESS_NRF, &cqr->flags);
41524150
}
41534151

@@ -4649,9 +4647,8 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_tpm_track(
46494647

46504648
/* Set flags to suppress output for expected errors */
46514649
if (dasd_eckd_is_ese(basedev)) {
4652-
set_bit(DASD_CQR_SUPPRESS_FP, &cqr->flags);
4653-
set_bit(DASD_CQR_SUPPRESS_IL, &cqr->flags);
46544650
set_bit(DASD_CQR_SUPPRESS_NRF, &cqr->flags);
4651+
set_bit(DASD_CQR_SUPPRESS_IT, &cqr->flags);
46554652
}
46564653

46574654
return cqr;
@@ -5820,36 +5817,32 @@ static void dasd_eckd_dump_sense(struct dasd_device *device,
58205817
{
58215818
u8 *sense = dasd_get_sense(irb);
58225819

5823-
if (scsw_is_tm(&irb->scsw)) {
5824-
/*
5825-
* In some cases the 'File Protected' or 'Incorrect Length'
5826-
* error might be expected and log messages shouldn't be written
5827-
* then. Check if the according suppress bit is set.
5828-
*/
5829-
if (sense && (sense[1] & SNS1_FILE_PROTECTED) &&
5830-
test_bit(DASD_CQR_SUPPRESS_FP, &req->flags))
5831-
return;
5832-
if (scsw_cstat(&irb->scsw) == 0x40 &&
5833-
test_bit(DASD_CQR_SUPPRESS_IL, &req->flags))
5834-
return;
5820+
/*
5821+
* In some cases certain errors might be expected and
5822+
* log messages shouldn't be written then.
5823+
* Check if the according suppress bit is set.
5824+
*/
5825+
if (sense && (sense[1] & SNS1_INV_TRACK_FORMAT) &&
5826+
!(sense[2] & SNS2_ENV_DATA_PRESENT) &&
5827+
test_bit(DASD_CQR_SUPPRESS_IT, &req->flags))
5828+
return;
58355829

5836-
dasd_eckd_dump_sense_tcw(device, req, irb);
5837-
} else {
5838-
/*
5839-
* In some cases the 'Command Reject' or 'No Record Found'
5840-
* error might be expected and log messages shouldn't be
5841-
* written then. Check if the according suppress bit is set.
5842-
*/
5843-
if (sense && sense[0] & SNS0_CMD_REJECT &&
5844-
test_bit(DASD_CQR_SUPPRESS_CR, &req->flags))
5845-
return;
5830+
if (sense && sense[0] & SNS0_CMD_REJECT &&
5831+
test_bit(DASD_CQR_SUPPRESS_CR, &req->flags))
5832+
return;
58465833

5847-
if (sense && sense[1] & SNS1_NO_REC_FOUND &&
5848-
test_bit(DASD_CQR_SUPPRESS_NRF, &req->flags))
5849-
return;
5834+
if (sense && sense[1] & SNS1_NO_REC_FOUND &&
5835+
test_bit(DASD_CQR_SUPPRESS_NRF, &req->flags))
5836+
return;
58505837

5838+
if (scsw_cstat(&irb->scsw) == 0x40 &&
5839+
test_bit(DASD_CQR_SUPPRESS_IL, &req->flags))
5840+
return;
5841+
5842+
if (scsw_is_tm(&irb->scsw))
5843+
dasd_eckd_dump_sense_tcw(device, req, irb);
5844+
else
58515845
dasd_eckd_dump_sense_ccw(device, req, irb);
5852-
}
58535846
}
58545847

58555848
static int dasd_eckd_reload_device(struct dasd_device *device)

drivers/s390/block/dasd_int.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ struct dasd_ccw_req {
225225
* The following flags are used to suppress output of certain errors.
226226
*/
227227
#define DASD_CQR_SUPPRESS_NRF 4 /* Suppress 'No Record Found' error */
228-
#define DASD_CQR_SUPPRESS_FP 5 /* Suppress 'File Protected' error*/
228+
#define DASD_CQR_SUPPRESS_IT 5 /* Suppress 'Invalid Track' error*/
229229
#define DASD_CQR_SUPPRESS_IL 6 /* Suppress 'Incorrect Length' error */
230230
#define DASD_CQR_SUPPRESS_CR 7 /* Suppress 'Command Reject' error */
231231

0 commit comments

Comments
 (0)