Skip to content

Commit 24c39aa

Browse files
committed
s390/dasd: fix error recovery leading to data corruption on ESE devices
jira LE-3201 Rebuild_History Non-Buildable kernel-rt-4.18.0-553.22.1.rt7.363.el8_10 commit-author Stefan Haberland <[email protected]> commit 7db4042 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: [email protected] # 5.3+ Fixes: 5e2b17e ("s390/dasd: Add dynamic formatting support for ESE volumes") Reviewed-by: Jan Hoeppner <[email protected]> Signed-off-by: Stefan Haberland <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jens Axboe <[email protected]> (cherry picked from commit 7db4042) Signed-off-by: Jonathan Maple <[email protected]>
1 parent f2ff8b0 commit 24c39aa

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
@@ -1670,9 +1670,15 @@ static int dasd_ese_needs_format(struct dasd_block *block, struct irb *irb)
16701670
if (!sense)
16711671
return 0;
16721672

1673-
return !!(sense[1] & SNS1_NO_REC_FOUND) ||
1674-
!!(sense[1] & SNS1_FILE_PROTECTED) ||
1675-
scsw_cstat(&irb->scsw) == SCHN_STAT_INCORR_LEN;
1673+
if (sense[1] & SNS1_NO_REC_FOUND)
1674+
return 1;
1675+
1676+
if ((sense[1] & SNS1_INV_TRACK_FORMAT) &&
1677+
scsw_is_tm(&irb->scsw) &&
1678+
!(sense[2] & SNS2_ENV_DATA_PRESENT))
1679+
return 1;
1680+
1681+
return 0;
16761682
}
16771683

16781684
static int dasd_ese_oos_cond(u8 *sense)
@@ -1693,7 +1699,7 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
16931699
struct dasd_device *device;
16941700
unsigned long now;
16951701
int nrf_suppressed = 0;
1696-
int fp_suppressed = 0;
1702+
int it_suppressed = 0;
16971703
struct request *req;
16981704
u8 *sense = NULL;
16991705
int expires;
@@ -1748,8 +1754,9 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
17481754
*/
17491755
sense = dasd_get_sense(irb);
17501756
if (sense) {
1751-
fp_suppressed = (sense[1] & SNS1_FILE_PROTECTED) &&
1752-
test_bit(DASD_CQR_SUPPRESS_FP, &cqr->flags);
1757+
it_suppressed = (sense[1] & SNS1_INV_TRACK_FORMAT) &&
1758+
!(sense[2] & SNS2_ENV_DATA_PRESENT) &&
1759+
test_bit(DASD_CQR_SUPPRESS_IT, &cqr->flags);
17531760
nrf_suppressed = (sense[1] & SNS1_NO_REC_FOUND) &&
17541761
test_bit(DASD_CQR_SUPPRESS_NRF, &cqr->flags);
17551762

@@ -1764,7 +1771,7 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
17641771
return;
17651772
}
17661773
}
1767-
if (!(fp_suppressed || nrf_suppressed))
1774+
if (!(it_suppressed || nrf_suppressed))
17681775
device->discipline->dump_sense_dbf(device, irb, "int");
17691776

17701777
if (device->features & DASD_FEATURE_ERPLOG)
@@ -2533,14 +2540,17 @@ static int _dasd_sleep_on_queue(struct list_head *ccw_queue, int interruptible)
25332540
rc = 0;
25342541
list_for_each_entry_safe(cqr, n, ccw_queue, blocklist) {
25352542
/*
2536-
* In some cases the 'File Protected' or 'Incorrect Length'
2537-
* error might be expected and error recovery would be
2538-
* unnecessary in these cases. Check if the according suppress
2539-
* bit is set.
2543+
* In some cases certain errors might be expected and
2544+
* error recovery would be unnecessary in these cases.
2545+
* Check if the according suppress bit is set.
25402546
*/
25412547
sense = dasd_get_sense(&cqr->irb);
2542-
if (sense && sense[1] & SNS1_FILE_PROTECTED &&
2543-
test_bit(DASD_CQR_SUPPRESS_FP, &cqr->flags))
2548+
if (sense && (sense[1] & SNS1_INV_TRACK_FORMAT) &&
2549+
!(sense[2] & SNS2_ENV_DATA_PRESENT) &&
2550+
test_bit(DASD_CQR_SUPPRESS_IT, &cqr->flags))
2551+
continue;
2552+
if (sense && (sense[1] & SNS1_NO_REC_FOUND) &&
2553+
test_bit(DASD_CQR_SUPPRESS_NRF, &cqr->flags))
25442554
continue;
25452555
if (scsw_cstat(&cqr->irb.scsw) == 0x40 &&
25462556
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
@@ -2304,6 +2304,7 @@ dasd_eckd_analysis_ccw(struct dasd_device *device)
23042304
cqr->status = DASD_CQR_FILLED;
23052305
/* Set flags to suppress output for expected errors */
23062306
set_bit(DASD_CQR_SUPPRESS_NRF, &cqr->flags);
2307+
set_bit(DASD_CQR_SUPPRESS_IT, &cqr->flags);
23072308

23082309
return cqr;
23092310
}
@@ -2582,7 +2583,6 @@ dasd_eckd_build_check_tcw(struct dasd_device *base, struct format_data_t *fdata,
25822583
cqr->buildclk = get_tod_clock();
25832584
cqr->status = DASD_CQR_FILLED;
25842585
/* Set flags to suppress output for expected errors */
2585-
set_bit(DASD_CQR_SUPPRESS_FP, &cqr->flags);
25862586
set_bit(DASD_CQR_SUPPRESS_IL, &cqr->flags);
25872587

25882588
return cqr;
@@ -4158,8 +4158,6 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_single(
41584158

41594159
/* Set flags to suppress output for expected errors */
41604160
if (dasd_eckd_is_ese(basedev)) {
4161-
set_bit(DASD_CQR_SUPPRESS_FP, &cqr->flags);
4162-
set_bit(DASD_CQR_SUPPRESS_IL, &cqr->flags);
41634161
set_bit(DASD_CQR_SUPPRESS_NRF, &cqr->flags);
41644162
}
41654163

@@ -4661,9 +4659,8 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_tpm_track(
46614659

46624660
/* Set flags to suppress output for expected errors */
46634661
if (dasd_eckd_is_ese(basedev)) {
4664-
set_bit(DASD_CQR_SUPPRESS_FP, &cqr->flags);
4665-
set_bit(DASD_CQR_SUPPRESS_IL, &cqr->flags);
46664662
set_bit(DASD_CQR_SUPPRESS_NRF, &cqr->flags);
4663+
set_bit(DASD_CQR_SUPPRESS_IT, &cqr->flags);
46674664
}
46684665

46694666
return cqr;
@@ -5825,36 +5822,32 @@ static void dasd_eckd_dump_sense(struct dasd_device *device,
58255822
{
58265823
u8 *sense = dasd_get_sense(irb);
58275824

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

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

5852-
if (sense && sense[1] & SNS1_NO_REC_FOUND &&
5853-
test_bit(DASD_CQR_SUPPRESS_NRF, &req->flags))
5854-
return;
5839+
if (sense && sense[1] & SNS1_NO_REC_FOUND &&
5840+
test_bit(DASD_CQR_SUPPRESS_NRF, &req->flags))
5841+
return;
58555842

5843+
if (scsw_cstat(&irb->scsw) == 0x40 &&
5844+
test_bit(DASD_CQR_SUPPRESS_IL, &req->flags))
5845+
return;
5846+
5847+
if (scsw_is_tm(&irb->scsw))
5848+
dasd_eckd_dump_sense_tcw(device, req, irb);
5849+
else
58565850
dasd_eckd_dump_sense_ccw(device, req, irb);
5857-
}
58585851
}
58595852

58605853
static int dasd_eckd_pm_freeze(struct dasd_device *device)

drivers/s390/block/dasd_int.h

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

0 commit comments

Comments
 (0)