[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20210208105530.3072869-10-ruansy.fnst@cn.fujitsu.com>
Date: Mon, 8 Feb 2021 18:55:28 +0800
From: Shiyang Ruan <ruansy.fnst@...fujitsu.com>
To: <linux-kernel@...r.kernel.org>, <linux-xfs@...r.kernel.org>,
<linux-nvdimm@...ts.01.org>, <linux-mm@...ck.org>,
<linux-fsdevel@...r.kernel.org>, <dm-devel@...hat.com>
CC: <darrick.wong@...cle.com>, <dan.j.williams@...el.com>,
<david@...morbit.com>, <hch@....de>, <agk@...hat.com>,
<snitzer@...hat.com>, <rgoldwyn@...e.de>, <qi.fuli@...itsu.com>,
<y-goto@...itsu.com>
Subject: [PATCH v3 09/11] md: Implement ->corrupted_range()
With the support of ->rmap(), it is possible to obtain the superblock on
a mapped device.
Signed-off-by: Shiyang Ruan <ruansy.fnst@...fujitsu.com>
---
drivers/md/dm.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 61 insertions(+)
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 7bac564f3faa..31b0c340b695 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -507,6 +507,66 @@ static int dm_blk_report_zones(struct gendisk *disk, sector_t sector,
#define dm_blk_report_zones NULL
#endif /* CONFIG_BLK_DEV_ZONED */
+struct corrupted_hit_info {
+ struct block_device *bdev;
+ sector_t offset;
+};
+
+static int dm_blk_corrupted_hit(struct dm_target *ti, struct dm_dev *dev,
+ sector_t start, sector_t count, void *data)
+{
+ struct corrupted_hit_info *bc = data;
+
+ return bc->bdev == (void *)dev->bdev &&
+ (start <= bc->offset && bc->offset < start + count);
+}
+
+struct corrupted_do_info {
+ size_t length;
+ void *data;
+};
+
+static int dm_blk_corrupted_do(struct dm_target *ti, struct block_device *bdev,
+ sector_t disk_sect, void *data)
+{
+ struct corrupted_do_info *bc = data;
+ loff_t disk_off = to_bytes(disk_sect);
+ loff_t bdev_off = to_bytes(disk_sect - get_start_sect(bdev));
+
+ return bd_corrupted_range(bdev, disk_off, bdev_off, bc->length, bc->data);
+}
+
+static int dm_blk_corrupted_range(struct gendisk *disk,
+ struct block_device *target_bdev,
+ loff_t target_offset, size_t len, void *data)
+{
+ struct mapped_device *md = disk->private_data;
+ struct dm_table *map;
+ struct dm_target *ti;
+ sector_t target_sect = to_sector(target_offset);
+ struct corrupted_hit_info hi = {target_bdev, target_sect};
+ struct corrupted_do_info di = {len, data};
+ int srcu_idx, i, rc = -ENODEV;
+
+ map = dm_get_live_table(md, &srcu_idx);
+ if (!map)
+ return rc;
+
+ for (i = 0; i < dm_table_get_num_targets(map); i++) {
+ ti = dm_table_get_target(map, i);
+ if (!(ti->type->iterate_devices && ti->type->rmap))
+ continue;
+ if (!ti->type->iterate_devices(ti, dm_blk_corrupted_hit, &hi))
+ continue;
+
+ rc = ti->type->rmap(ti, target_sect, dm_blk_corrupted_do, &di);
+ break;
+ }
+
+ dm_put_live_table(md, srcu_idx);
+ return rc;
+}
+
static int dm_prepare_ioctl(struct mapped_device *md, int *srcu_idx,
struct block_device **bdev)
{
@@ -3062,6 +3122,7 @@ static const struct block_device_operations dm_blk_dops = {
.getgeo = dm_blk_getgeo,
.report_zones = dm_blk_report_zones,
.pr_ops = &dm_pr_ops,
+ .corrupted_range = dm_blk_corrupted_range,
.owner = THIS_MODULE
};
--
2.30.0
Powered by blists - more mailing lists