summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Höppner <hoeppner@linux.ibm.com>2018-04-27 10:57:44 -0400
committerVasily Gorbik <gor@linux.ibm.com>2019-07-11 14:39:54 -0400
commit7e64db1597fe114b83fe17d0ba96c6aa5fca419a (patch)
treec6d4b47f6a4f4972f53b59b1370a71eaa51d5210
parentb54441534e9648f8df24b75a63bb00ed3aa123de (diff)
s390/dasd: Add discard support for ESE volumes
ESE (Extent Space Efficient) volumes are thin-provisioned and therefore space is only occupied with real data. In order to make previously used space available for re-allocation again, discard support is enabled for ESE volumes allowing the DASD driver to release said space. Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com> Reviewed-by: Stefan Haberland <sth@linux.ibm.com> Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
-rw-r--r--drivers/s390/block/dasd_eckd.c57
1 files changed, 54 insertions, 3 deletions
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index 3edb35359843..7f7429a99a67 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -1987,6 +1987,9 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
1987 if (readonly) 1987 if (readonly)
1988 set_bit(DASD_FLAG_DEVICE_RO, &device->flags); 1988 set_bit(DASD_FLAG_DEVICE_RO, &device->flags);
1989 1989
1990 if (dasd_eckd_is_ese(device))
1991 dasd_set_feature(device->cdev, DASD_FEATURE_DISCARD, 1);
1992
1990 dev_info(&device->cdev->dev, "New DASD %04X/%02X (CU %04X/%02X) " 1993 dev_info(&device->cdev->dev, "New DASD %04X/%02X (CU %04X/%02X) "
1991 "with %d cylinders, %d heads, %d sectors%s\n", 1994 "with %d cylinders, %d heads, %d sectors%s\n",
1992 private->rdc_data.dev_type, 1995 private->rdc_data.dev_type,
@@ -3617,6 +3620,14 @@ static int dasd_eckd_release_space(struct dasd_device *device,
3617 return -EINVAL; 3620 return -EINVAL;
3618} 3621}
3619 3622
3623static struct dasd_ccw_req *
3624dasd_eckd_build_cp_discard(struct dasd_device *device, struct dasd_block *block,
3625 struct request *req, sector_t first_trk,
3626 sector_t last_trk)
3627{
3628 return dasd_eckd_dso_ras(device, block, req, first_trk, last_trk, 1);
3629}
3630
3620static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_single( 3631static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_single(
3621 struct dasd_device *startdev, 3632 struct dasd_device *startdev,
3622 struct dasd_block *block, 3633 struct dasd_block *block,
@@ -4361,6 +4372,10 @@ static struct dasd_ccw_req *dasd_eckd_build_cp(struct dasd_device *startdev,
4361 cmdwtd = private->features.feature[12] & 0x40; 4372 cmdwtd = private->features.feature[12] & 0x40;
4362 use_prefix = private->features.feature[8] & 0x01; 4373 use_prefix = private->features.feature[8] & 0x01;
4363 4374
4375 if (req_op(req) == REQ_OP_DISCARD)
4376 return dasd_eckd_build_cp_discard(startdev, block, req,
4377 first_trk, last_trk);
4378
4364 cqr = NULL; 4379 cqr = NULL;
4365 if (cdlspecial || dasd_page_cache) { 4380 if (cdlspecial || dasd_page_cache) {
4366 /* do nothing, just fall through to the cmd mode single case */ 4381 /* do nothing, just fall through to the cmd mode single case */
@@ -4639,12 +4654,14 @@ static struct dasd_ccw_req *dasd_eckd_build_alias_cp(struct dasd_device *base,
4639 struct dasd_block *block, 4654 struct dasd_block *block,
4640 struct request *req) 4655 struct request *req)
4641{ 4656{
4657 struct dasd_device *startdev = NULL;
4642 struct dasd_eckd_private *private; 4658 struct dasd_eckd_private *private;
4643 struct dasd_device *startdev;
4644 unsigned long flags;
4645 struct dasd_ccw_req *cqr; 4659 struct dasd_ccw_req *cqr;
4660 unsigned long flags;
4646 4661
4647 startdev = dasd_alias_get_start_dev(base); 4662 /* Discard requests can only be processed on base devices */
4663 if (req_op(req) != REQ_OP_DISCARD)
4664 startdev = dasd_alias_get_start_dev(base);
4648 if (!startdev) 4665 if (!startdev)
4649 startdev = base; 4666 startdev = base;
4650 private = startdev->private; 4667 private = startdev->private;
@@ -6357,8 +6374,20 @@ static void dasd_eckd_setup_blk_queue(struct dasd_block *block)
6357 unsigned int logical_block_size = block->bp_block; 6374 unsigned int logical_block_size = block->bp_block;
6358 struct request_queue *q = block->request_queue; 6375 struct request_queue *q = block->request_queue;
6359 struct dasd_device *device = block->base; 6376 struct dasd_device *device = block->base;
6377 struct dasd_eckd_private *private;
6378 unsigned int max_discard_sectors;
6379 unsigned int max_bytes;
6380 unsigned int ext_bytes; /* Extent Size in Bytes */
6381 int recs_per_trk;
6382 int trks_per_cyl;
6383 int ext_limit;
6384 int ext_size; /* Extent Size in Cylinders */
6360 int max; 6385 int max;
6361 6386
6387 private = device->private;
6388 trks_per_cyl = private->rdc_data.trk_per_cyl;
6389 recs_per_trk = recs_per_track(&private->rdc_data, 0, logical_block_size);
6390
6362 if (device->features & DASD_FEATURE_USERAW) { 6391 if (device->features & DASD_FEATURE_USERAW) {
6363 /* 6392 /*
6364 * the max_blocks value for raw_track access is 256 6393 * the max_blocks value for raw_track access is 256
@@ -6379,6 +6408,28 @@ static void dasd_eckd_setup_blk_queue(struct dasd_block *block)
6379 /* With page sized segments each segment can be translated into one idaw/tidaw */ 6408 /* With page sized segments each segment can be translated into one idaw/tidaw */
6380 blk_queue_max_segment_size(q, PAGE_SIZE); 6409 blk_queue_max_segment_size(q, PAGE_SIZE);
6381 blk_queue_segment_boundary(q, PAGE_SIZE - 1); 6410 blk_queue_segment_boundary(q, PAGE_SIZE - 1);
6411
6412 if (dasd_eckd_is_ese(device)) {
6413 /*
6414 * Depending on the extent size, up to UINT_MAX bytes can be
6415 * accepted. However, neither DASD_ECKD_RAS_EXTS_MAX nor the
6416 * device limits should be exceeded.
6417 */
6418 ext_size = dasd_eckd_ext_size(device);
6419 ext_limit = min(private->real_cyl / ext_size, DASD_ECKD_RAS_EXTS_MAX);
6420 ext_bytes = ext_size * trks_per_cyl * recs_per_trk *
6421 logical_block_size;
6422 max_bytes = UINT_MAX - (UINT_MAX % ext_bytes);
6423 if (max_bytes / ext_bytes > ext_limit)
6424 max_bytes = ext_bytes * ext_limit;
6425
6426 max_discard_sectors = max_bytes / 512;
6427
6428 blk_queue_max_discard_sectors(q, max_discard_sectors);
6429 blk_queue_flag_set(QUEUE_FLAG_DISCARD, q);
6430 q->limits.discard_granularity = ext_bytes;
6431 q->limits.discard_alignment = ext_bytes;
6432 }
6382} 6433}
6383 6434
6384static struct ccw_driver dasd_eckd_driver = { 6435static struct ccw_driver dasd_eckd_driver = {