diff options
author | Benjamin Coddington <bcodding@redhat.com> | 2024-10-31 16:06:48 +0100 |
---|---|---|
committer | Mikulas Patocka <mpatocka@redhat.com> | 2024-11-20 11:38:04 +0100 |
commit | d5f01ace542de62af857fa0bd405cc16f2c45bd6 (patch) | |
tree | 1dfa4103c3d451e46ae7cb1b1d194b86feb85d58 /drivers/md/dm.c | |
parent | dm vdo: fix function doc comment formatting (diff) | |
download | linux-d5f01ace542de62af857fa0bd405cc16f2c45bd6.tar.xz linux-d5f01ace542de62af857fa0bd405cc16f2c45bd6.zip |
dm: add support for get_unique_id
This adds support to obtain a device's unique id through dm, similar to the
existing ioctl and persistent resevation handling. We limit this to
single-target devices.
This enables knfsd to export pNFS SCSI luns that have been exported from
multipath devices.
Signed-off-by: Benjamin Coddington <bcodding@redhat.com>
Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Diffstat (limited to '')
-rw-r--r-- | drivers/md/dm.c | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/drivers/md/dm.c b/drivers/md/dm.c index adf0dde68947..12ecf07a3841 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -3343,6 +3343,59 @@ void dm_free_md_mempools(struct dm_md_mempools *pools) kfree(pools); } +struct dm_blkdev_id { + u8 *id; + enum blk_unique_id type; +}; + +static int __dm_get_unique_id(struct dm_target *ti, struct dm_dev *dev, + sector_t start, sector_t len, void *data) +{ + struct dm_blkdev_id *dm_id = data; + const struct block_device_operations *fops = dev->bdev->bd_disk->fops; + + if (!fops->get_unique_id) + return 0; + + return fops->get_unique_id(dev->bdev->bd_disk, dm_id->id, dm_id->type); +} + +/* + * Allow access to get_unique_id() for the first device returning a + * non-zero result. Reasonable use expects all devices to have the + * same unique id. + */ +static int dm_blk_get_unique_id(struct gendisk *disk, u8 *id, + enum blk_unique_id type) +{ + struct mapped_device *md = disk->private_data; + struct dm_table *table; + struct dm_target *ti; + int ret = 0, srcu_idx; + + struct dm_blkdev_id dm_id = { + .id = id, + .type = type, + }; + + table = dm_get_live_table(md, &srcu_idx); + if (!table || !dm_table_get_size(table)) + goto out; + + /* We only support devices that have a single target */ + if (table->num_targets != 1) + goto out; + ti = dm_table_get_target(table, 0); + + if (!ti->type->iterate_devices) + goto out; + + ret = ti->type->iterate_devices(ti, __dm_get_unique_id, &dm_id); +out: + dm_put_live_table(md, srcu_idx); + return ret; +} + struct dm_pr { u64 old_key; u64 new_key; @@ -3668,6 +3721,7 @@ static const struct block_device_operations dm_blk_dops = { .ioctl = dm_blk_ioctl, .getgeo = dm_blk_getgeo, .report_zones = dm_blk_report_zones, + .get_unique_id = dm_blk_get_unique_id, .pr_ops = &dm_pr_ops, .owner = THIS_MODULE }; @@ -3677,6 +3731,7 @@ static const struct block_device_operations dm_rq_blk_dops = { .release = dm_blk_close, .ioctl = dm_blk_ioctl, .getgeo = dm_blk_getgeo, + .get_unique_id = dm_blk_get_unique_id, .pr_ops = &dm_pr_ops, .owner = THIS_MODULE }; |