dm: move zone related code to dm-zone.c
Move core and table code used for zoned targets and conditionally defined with #ifdef CONFIG_BLK_DEV_ZONED to the new file dm-zone.c. This file is conditionally compiled depending on CONFIG_BLK_DEV_ZONED. The small helper dm_set_zones_restrictions() is introduced to initialize a mapped device request queue zone attributes in dm_table_set_restrictions(). Signed-off-by: Damien Le Moal <damien.lemoal@wdc.com> Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com> Reviewed-by: Hannes Reinecke <hare@suse.de> Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com> Signed-off-by: Mike Snitzer <snitzer@redhat.com>
This commit is contained in:
parent
dd73c320ec
commit
7fc1872848
|
@ -92,6 +92,10 @@ ifeq ($(CONFIG_DM_UEVENT),y)
|
|||
dm-mod-objs += dm-uevent.o
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BLK_DEV_ZONED),y)
|
||||
dm-mod-objs += dm-zone.o
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_DM_VERITY_FEC),y)
|
||||
dm-verity-objs += dm-verity-fec.o
|
||||
endif
|
||||
|
|
|
@ -2064,17 +2064,9 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
|
|||
dm_table_any_dev_attr(t, device_is_not_random, NULL))
|
||||
blk_queue_flag_clear(QUEUE_FLAG_ADD_RANDOM, q);
|
||||
|
||||
/*
|
||||
* For a zoned target, the number of zones should be updated for the
|
||||
* correct value to be exposed in sysfs queue/nr_zones. For a BIO based
|
||||
* target, this is all that is needed.
|
||||
*/
|
||||
#ifdef CONFIG_BLK_DEV_ZONED
|
||||
if (blk_queue_is_zoned(q)) {
|
||||
WARN_ON_ONCE(queue_is_mq(q));
|
||||
q->nr_zones = blkdev_nr_zones(t->md->disk);
|
||||
}
|
||||
#endif
|
||||
/* For a zoned target, setup the zones related queue attributes */
|
||||
if (blk_queue_is_zoned(q))
|
||||
dm_set_zones_restrictions(t, q);
|
||||
|
||||
dm_update_keyslot_manager(q, t);
|
||||
blk_queue_update_readahead(q);
|
||||
|
|
|
@ -0,0 +1,101 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (C) 2021 Western Digital Corporation or its affiliates.
|
||||
*/
|
||||
|
||||
#include <linux/blkdev.h>
|
||||
|
||||
#include "dm-core.h"
|
||||
|
||||
/*
|
||||
* User facing dm device block device report zone operation. This calls the
|
||||
* report_zones operation for each target of a device table. This operation is
|
||||
* generally implemented by targets using dm_report_zones().
|
||||
*/
|
||||
int dm_blk_report_zones(struct gendisk *disk, sector_t sector,
|
||||
unsigned int nr_zones, report_zones_cb cb, void *data)
|
||||
{
|
||||
struct mapped_device *md = disk->private_data;
|
||||
struct dm_table *map;
|
||||
int srcu_idx, ret;
|
||||
struct dm_report_zones_args args = {
|
||||
.next_sector = sector,
|
||||
.orig_data = data,
|
||||
.orig_cb = cb,
|
||||
};
|
||||
|
||||
if (dm_suspended_md(md))
|
||||
return -EAGAIN;
|
||||
|
||||
map = dm_get_live_table(md, &srcu_idx);
|
||||
if (!map) {
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
do {
|
||||
struct dm_target *tgt;
|
||||
|
||||
tgt = dm_table_find_target(map, args.next_sector);
|
||||
if (WARN_ON_ONCE(!tgt->type->report_zones)) {
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
args.tgt = tgt;
|
||||
ret = tgt->type->report_zones(tgt, &args,
|
||||
nr_zones - args.zone_idx);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
} while (args.zone_idx < nr_zones &&
|
||||
args.next_sector < get_capacity(disk));
|
||||
|
||||
ret = args.zone_idx;
|
||||
out:
|
||||
dm_put_live_table(md, srcu_idx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int dm_report_zones_cb(struct blk_zone *zone, unsigned int idx, void *data)
|
||||
{
|
||||
struct dm_report_zones_args *args = data;
|
||||
sector_t sector_diff = args->tgt->begin - args->start;
|
||||
|
||||
/*
|
||||
* Ignore zones beyond the target range.
|
||||
*/
|
||||
if (zone->start >= args->start + args->tgt->len)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Remap the start sector and write pointer position of the zone
|
||||
* to match its position in the target range.
|
||||
*/
|
||||
zone->start += sector_diff;
|
||||
if (zone->type != BLK_ZONE_TYPE_CONVENTIONAL) {
|
||||
if (zone->cond == BLK_ZONE_COND_FULL)
|
||||
zone->wp = zone->start + zone->len;
|
||||
else if (zone->cond == BLK_ZONE_COND_EMPTY)
|
||||
zone->wp = zone->start;
|
||||
else
|
||||
zone->wp += sector_diff;
|
||||
}
|
||||
|
||||
args->next_sector = zone->start + zone->len;
|
||||
return args->orig_cb(zone, args->zone_idx++, args->orig_data);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dm_report_zones_cb);
|
||||
|
||||
void dm_set_zones_restrictions(struct dm_table *t, struct request_queue *q)
|
||||
{
|
||||
if (!blk_queue_is_zoned(q))
|
||||
return;
|
||||
|
||||
/*
|
||||
* For a zoned target, the number of zones should be updated for the
|
||||
* correct value to be exposed in sysfs queue/nr_zones. For a BIO based
|
||||
* target, this is all that is needed.
|
||||
*/
|
||||
WARN_ON_ONCE(queue_is_mq(q));
|
||||
q->nr_zones = blkdev_nr_zones(t->md->disk);
|
||||
}
|
|
@ -444,84 +444,6 @@ static int dm_blk_getgeo(struct block_device *bdev, struct hd_geometry *geo)
|
|||
return dm_get_geometry(md, geo);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BLK_DEV_ZONED
|
||||
int dm_report_zones_cb(struct blk_zone *zone, unsigned int idx, void *data)
|
||||
{
|
||||
struct dm_report_zones_args *args = data;
|
||||
sector_t sector_diff = args->tgt->begin - args->start;
|
||||
|
||||
/*
|
||||
* Ignore zones beyond the target range.
|
||||
*/
|
||||
if (zone->start >= args->start + args->tgt->len)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Remap the start sector and write pointer position of the zone
|
||||
* to match its position in the target range.
|
||||
*/
|
||||
zone->start += sector_diff;
|
||||
if (zone->type != BLK_ZONE_TYPE_CONVENTIONAL) {
|
||||
if (zone->cond == BLK_ZONE_COND_FULL)
|
||||
zone->wp = zone->start + zone->len;
|
||||
else if (zone->cond == BLK_ZONE_COND_EMPTY)
|
||||
zone->wp = zone->start;
|
||||
else
|
||||
zone->wp += sector_diff;
|
||||
}
|
||||
|
||||
args->next_sector = zone->start + zone->len;
|
||||
return args->orig_cb(zone, args->zone_idx++, args->orig_data);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dm_report_zones_cb);
|
||||
|
||||
static int dm_blk_report_zones(struct gendisk *disk, sector_t sector,
|
||||
unsigned int nr_zones, report_zones_cb cb, void *data)
|
||||
{
|
||||
struct mapped_device *md = disk->private_data;
|
||||
struct dm_table *map;
|
||||
int srcu_idx, ret;
|
||||
struct dm_report_zones_args args = {
|
||||
.next_sector = sector,
|
||||
.orig_data = data,
|
||||
.orig_cb = cb,
|
||||
};
|
||||
|
||||
if (dm_suspended_md(md))
|
||||
return -EAGAIN;
|
||||
|
||||
map = dm_get_live_table(md, &srcu_idx);
|
||||
if (!map) {
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
do {
|
||||
struct dm_target *tgt;
|
||||
|
||||
tgt = dm_table_find_target(map, args.next_sector);
|
||||
if (WARN_ON_ONCE(!tgt->type->report_zones)) {
|
||||
ret = -EIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
args.tgt = tgt;
|
||||
ret = tgt->type->report_zones(tgt, &args,
|
||||
nr_zones - args.zone_idx);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
} while (args.zone_idx < nr_zones &&
|
||||
args.next_sector < get_capacity(disk));
|
||||
|
||||
ret = args.zone_idx;
|
||||
out:
|
||||
dm_put_live_table(md, srcu_idx);
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
#define dm_blk_report_zones NULL
|
||||
#endif /* CONFIG_BLK_DEV_ZONED */
|
||||
|
||||
static int dm_prepare_ioctl(struct mapped_device *md, int *srcu_idx,
|
||||
struct block_device **bdev)
|
||||
{
|
||||
|
|
|
@ -100,6 +100,17 @@ int dm_setup_md_queue(struct mapped_device *md, struct dm_table *t);
|
|||
*/
|
||||
#define dm_target_hybrid(t) (dm_target_bio_based(t) && dm_target_request_based(t))
|
||||
|
||||
/*
|
||||
* Zoned targets related functions.
|
||||
*/
|
||||
void dm_set_zones_restrictions(struct dm_table *t, struct request_queue *q);
|
||||
#ifdef CONFIG_BLK_DEV_ZONED
|
||||
int dm_blk_report_zones(struct gendisk *disk, sector_t sector,
|
||||
unsigned int nr_zones, report_zones_cb cb, void *data);
|
||||
#else
|
||||
#define dm_blk_report_zones NULL
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------------
|
||||
* A registry of target types.
|
||||
*---------------------------------------------------------------*/
|
||||
|
|
Loading…
Reference in New Issue