Skip to content

Commit f7c3601

Browse files
committed
s390/dasd: fix error recovery leading to data corruption on ESE devices
jira LE-2157 Rebuild_History Non-Buildable kernel-5.14.0-503.16.1.el9_5 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 30829a5 commit f7c3601

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
@@ -1629,9 +1629,15 @@ static int dasd_ese_needs_format(struct dasd_block *block, struct irb *irb)
16291629
if (!sense)
16301630
return 0;
16311631

1632-
return !!(sense[1] & SNS1_NO_REC_FOUND) ||
1633-
!!(sense[1] & SNS1_FILE_PROTECTED) ||
1634-
scsw_cstat(&irb->scsw) == SCHN_STAT_INCORR_LEN;
1632+
if (sense[1] & SNS1_NO_REC_FOUND)
1633+
return 1;
1634+
1635+
if ((sense[1] & SNS1_INV_TRACK_FORMAT) &&
1636+
scsw_is_tm(&irb->scsw) &&
1637+
!(sense[2] & SNS2_ENV_DATA_PRESENT))
1638+
return 1;
1639+
1640+
return 0;
16351641
}
16361642

16371643
static int dasd_ese_oos_cond(u8 *sense)
@@ -1652,7 +1658,7 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
16521658
struct dasd_device *device;
16531659
unsigned long now;
16541660
int nrf_suppressed = 0;
1655-
int fp_suppressed = 0;
1661+
int it_suppressed = 0;
16561662
struct request *req;
16571663
u8 *sense = NULL;
16581664
int expires;
@@ -1707,8 +1713,9 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
17071713
*/
17081714
sense = dasd_get_sense(irb);
17091715
if (sense) {
1710-
fp_suppressed = (sense[1] & SNS1_FILE_PROTECTED) &&
1711-
test_bit(DASD_CQR_SUPPRESS_FP, &cqr->flags);
1716+
it_suppressed = (sense[1] & SNS1_INV_TRACK_FORMAT) &&
1717+
!(sense[2] & SNS2_ENV_DATA_PRESENT) &&
1718+
test_bit(DASD_CQR_SUPPRESS_IT, &cqr->flags);
17121719
nrf_suppressed = (sense[1] & SNS1_NO_REC_FOUND) &&
17131720
test_bit(DASD_CQR_SUPPRESS_NRF, &cqr->flags);
17141721

@@ -1723,7 +1730,7 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
17231730
return;
17241731
}
17251732
}
1726-
if (!(fp_suppressed || nrf_suppressed))
1733+
if (!(it_suppressed || nrf_suppressed))
17271734
device->discipline->dump_sense_dbf(device, irb, "int");
17281735

17291736
if (device->features & DASD_FEATURE_ERPLOG)
@@ -2495,14 +2502,17 @@ static int _dasd_sleep_on_queue(struct list_head *ccw_queue, int interruptible)
24952502
rc = 0;
24962503
list_for_each_entry_safe(cqr, n, ccw_queue, blocklist) {
24972504
/*
2498-
* In some cases the 'File Protected' or 'Incorrect Length'
2499-
* error might be expected and error recovery would be
2500-
* unnecessary in these cases. Check if the according suppress
2501-
* bit is set.
2505+
* In some cases certain errors might be expected and
2506+
* error recovery would be unnecessary in these cases.
2507+
* Check if the according suppress bit is set.
25022508
*/
25032509
sense = dasd_get_sense(&cqr->irb);
2504-
if (sense && sense[1] & SNS1_FILE_PROTECTED &&
2505-
test_bit(DASD_CQR_SUPPRESS_FP, &cqr->flags))
2510+
if (sense && (sense[1] & SNS1_INV_TRACK_FORMAT) &&
2511+
!(sense[2] & SNS2_ENV_DATA_PRESENT) &&
2512+
test_bit(DASD_CQR_SUPPRESS_IT, &cqr->flags))
2513+
continue;
2514+
if (sense && (sense[1] & SNS1_NO_REC_FOUND) &&
2515+
test_bit(DASD_CQR_SUPPRESS_NRF, &cqr->flags))
25062516
continue;
25072517
if (scsw_cstat(&cqr->irb.scsw) == 0x40 &&
25082518
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
@@ -2292,6 +2292,7 @@ dasd_eckd_analysis_ccw(struct dasd_device *device)
22922292
cqr->status = DASD_CQR_FILLED;
22932293
/* Set flags to suppress output for expected errors */
22942294
set_bit(DASD_CQR_SUPPRESS_NRF, &cqr->flags);
2295+
set_bit(DASD_CQR_SUPPRESS_IT, &cqr->flags);
22952296

22962297
return cqr;
22972298
}
@@ -2573,7 +2574,6 @@ dasd_eckd_build_check_tcw(struct dasd_device *base, struct format_data_t *fdata,
25732574
cqr->buildclk = get_tod_clock();
25742575
cqr->status = DASD_CQR_FILLED;
25752576
/* Set flags to suppress output for expected errors */
2576-
set_bit(DASD_CQR_SUPPRESS_FP, &cqr->flags);
25772577
set_bit(DASD_CQR_SUPPRESS_IL, &cqr->flags);
25782578

25792579
return cqr;
@@ -4149,8 +4149,6 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_single(
41494149

41504150
/* Set flags to suppress output for expected errors */
41514151
if (dasd_eckd_is_ese(basedev)) {
4152-
set_bit(DASD_CQR_SUPPRESS_FP, &cqr->flags);
4153-
set_bit(DASD_CQR_SUPPRESS_IL, &cqr->flags);
41544152
set_bit(DASD_CQR_SUPPRESS_NRF, &cqr->flags);
41554153
}
41564154

@@ -4652,9 +4650,8 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_tpm_track(
46524650

46534651
/* Set flags to suppress output for expected errors */
46544652
if (dasd_eckd_is_ese(basedev)) {
4655-
set_bit(DASD_CQR_SUPPRESS_FP, &cqr->flags);
4656-
set_bit(DASD_CQR_SUPPRESS_IL, &cqr->flags);
46574653
set_bit(DASD_CQR_SUPPRESS_NRF, &cqr->flags);
4654+
set_bit(DASD_CQR_SUPPRESS_IT, &cqr->flags);
46584655
}
46594656

46604657
return cqr;
@@ -5824,36 +5821,32 @@ static void dasd_eckd_dump_sense(struct dasd_device *device,
58245821
{
58255822
u8 *sense = dasd_get_sense(irb);
58265823

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

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

5851-
if (sense && sense[1] & SNS1_NO_REC_FOUND &&
5852-
test_bit(DASD_CQR_SUPPRESS_NRF, &req->flags))
5853-
return;
5838+
if (sense && sense[1] & SNS1_NO_REC_FOUND &&
5839+
test_bit(DASD_CQR_SUPPRESS_NRF, &req->flags))
5840+
return;
58545841

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

58595852
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)