Commit c99bff34 authored by Stefan Haberland's avatar Stefan Haberland Committed by Jens Axboe

s390/dasd: fix command reject error on ESE devices

Formatting a thin-provisioned (ESE) device that is part of a PPRC copy
relation might fail with the following error:

dasd-eckd 0.0.f500: An error occurred in the DASD device driver, reason=09
[...]
24 Byte: 0 MSG 4, no MSGb to SYSOP

During format of an ESE disk the Release Allocated Space command is used.
A bit in the payload of the command is set that is not allowed to be set
for devices in a copy relation. This bit is set to allow the partial
release of an extent.

Check for the existence of a copy relation before setting the respective
bit.

Fixes: 91dc4a19 ("s390/dasd: Add new ioctl to release space")
Cc: stable@kernel.org # 5.3+
Signed-off-by: default avatarStefan Haberland <sth@linux.ibm.com>
Reviewed-by: default avatarJan Hoeppner <hoeppner@linux.ibm.com>
Link: https://lore.kernel.org/r/20230519102340.3854819-2-sth@linux.ibm.comSigned-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent 1878b736
...@@ -127,6 +127,8 @@ static int prepare_itcw(struct itcw *, unsigned int, unsigned int, int, ...@@ -127,6 +127,8 @@ static int prepare_itcw(struct itcw *, unsigned int, unsigned int, int,
struct dasd_device *, struct dasd_device *, struct dasd_device *, struct dasd_device *,
unsigned int, int, unsigned int, unsigned int, unsigned int, int, unsigned int, unsigned int,
unsigned int, unsigned int); unsigned int, unsigned int);
static int dasd_eckd_query_pprc_status(struct dasd_device *,
struct dasd_pprc_data_sc4 *);
/* initial attempt at a probe function. this can be simplified once /* initial attempt at a probe function. this can be simplified once
* the other detection code is gone */ * the other detection code is gone */
...@@ -3733,6 +3735,26 @@ static int count_exts(unsigned int from, unsigned int to, int trks_per_ext) ...@@ -3733,6 +3735,26 @@ static int count_exts(unsigned int from, unsigned int to, int trks_per_ext)
return count; return count;
} }
static int dasd_in_copy_relation(struct dasd_device *device)
{
struct dasd_pprc_data_sc4 *temp;
int rc;
if (!dasd_eckd_pprc_enabled(device))
return 0;
temp = kzalloc(sizeof(*temp), GFP_KERNEL);
if (!temp)
return -ENOMEM;
rc = dasd_eckd_query_pprc_status(device, temp);
if (!rc)
rc = temp->dev_info[0].state;
kfree(temp);
return rc;
}
/* /*
* Release allocated space for a given range or an entire volume. * Release allocated space for a given range or an entire volume.
*/ */
...@@ -3749,6 +3771,7 @@ dasd_eckd_dso_ras(struct dasd_device *device, struct dasd_block *block, ...@@ -3749,6 +3771,7 @@ dasd_eckd_dso_ras(struct dasd_device *device, struct dasd_block *block,
int cur_to_trk, cur_from_trk; int cur_to_trk, cur_from_trk;
struct dasd_ccw_req *cqr; struct dasd_ccw_req *cqr;
u32 beg_cyl, end_cyl; u32 beg_cyl, end_cyl;
int copy_relation;
struct ccw1 *ccw; struct ccw1 *ccw;
int trks_per_ext; int trks_per_ext;
size_t ras_size; size_t ras_size;
...@@ -3760,6 +3783,10 @@ dasd_eckd_dso_ras(struct dasd_device *device, struct dasd_block *block, ...@@ -3760,6 +3783,10 @@ dasd_eckd_dso_ras(struct dasd_device *device, struct dasd_block *block,
if (dasd_eckd_ras_sanity_checks(device, first_trk, last_trk)) if (dasd_eckd_ras_sanity_checks(device, first_trk, last_trk))
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
copy_relation = dasd_in_copy_relation(device);
if (copy_relation < 0)
return ERR_PTR(copy_relation);
rq = req ? blk_mq_rq_to_pdu(req) : NULL; rq = req ? blk_mq_rq_to_pdu(req) : NULL;
features = &private->features; features = &private->features;
...@@ -3788,9 +3815,11 @@ dasd_eckd_dso_ras(struct dasd_device *device, struct dasd_block *block, ...@@ -3788,9 +3815,11 @@ dasd_eckd_dso_ras(struct dasd_device *device, struct dasd_block *block,
/* /*
* This bit guarantees initialisation of tracks within an extent that is * This bit guarantees initialisation of tracks within an extent that is
* not fully specified, but is only supported with a certain feature * not fully specified, but is only supported with a certain feature
* subset. * subset and for devices not in a copy relation.
*/ */
ras_data->op_flags.guarantee_init = !!(features->feature[56] & 0x01); if (features->feature[56] & 0x01 && !copy_relation)
ras_data->op_flags.guarantee_init = 1;
ras_data->lss = private->conf.ned->ID; ras_data->lss = private->conf.ned->ID;
ras_data->dev_addr = private->conf.ned->unit_addr; ras_data->dev_addr = private->conf.ned->unit_addr;
ras_data->nr_exts = nr_exts; ras_data->nr_exts = nr_exts;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment