18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * Copyright (C) 2001-2003 Sistina Software (UK) Limited.
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * This file is released under the GPL.
58c2ecf20Sopenharmony_ci */
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci#include "dm.h"
88c2ecf20Sopenharmony_ci#include <linux/device-mapper.h>
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci#include <linux/module.h>
118c2ecf20Sopenharmony_ci#include <linux/init.h>
128c2ecf20Sopenharmony_ci#include <linux/blkdev.h>
138c2ecf20Sopenharmony_ci#include <linux/bio.h>
148c2ecf20Sopenharmony_ci#include <linux/dax.h>
158c2ecf20Sopenharmony_ci#include <linux/slab.h>
168c2ecf20Sopenharmony_ci#include <linux/log2.h>
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci#define DM_MSG_PREFIX "striped"
198c2ecf20Sopenharmony_ci#define DM_IO_ERROR_THRESHOLD 15
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_cistruct stripe {
228c2ecf20Sopenharmony_ci	struct dm_dev *dev;
238c2ecf20Sopenharmony_ci	sector_t physical_start;
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci	atomic_t error_count;
268c2ecf20Sopenharmony_ci};
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_cistruct stripe_c {
298c2ecf20Sopenharmony_ci	uint32_t stripes;
308c2ecf20Sopenharmony_ci	int stripes_shift;
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci	/* The size of this target / num. stripes */
338c2ecf20Sopenharmony_ci	sector_t stripe_width;
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci	uint32_t chunk_size;
368c2ecf20Sopenharmony_ci	int chunk_size_shift;
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci	/* Needed for handling events */
398c2ecf20Sopenharmony_ci	struct dm_target *ti;
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci	/* Work struct used for triggering events*/
428c2ecf20Sopenharmony_ci	struct work_struct trigger_event;
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci	struct stripe stripe[];
458c2ecf20Sopenharmony_ci};
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci/*
488c2ecf20Sopenharmony_ci * An event is triggered whenever a drive
498c2ecf20Sopenharmony_ci * drops out of a stripe volume.
508c2ecf20Sopenharmony_ci */
518c2ecf20Sopenharmony_cistatic void trigger_event(struct work_struct *work)
528c2ecf20Sopenharmony_ci{
538c2ecf20Sopenharmony_ci	struct stripe_c *sc = container_of(work, struct stripe_c,
548c2ecf20Sopenharmony_ci					   trigger_event);
558c2ecf20Sopenharmony_ci	dm_table_event(sc->ti->table);
568c2ecf20Sopenharmony_ci}
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci/*
598c2ecf20Sopenharmony_ci * Parse a single <dev> <sector> pair
608c2ecf20Sopenharmony_ci */
618c2ecf20Sopenharmony_cistatic int get_stripe(struct dm_target *ti, struct stripe_c *sc,
628c2ecf20Sopenharmony_ci		      unsigned int stripe, char **argv)
638c2ecf20Sopenharmony_ci{
648c2ecf20Sopenharmony_ci	unsigned long long start;
658c2ecf20Sopenharmony_ci	char dummy;
668c2ecf20Sopenharmony_ci	int ret;
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_ci	if (sscanf(argv[1], "%llu%c", &start, &dummy) != 1)
698c2ecf20Sopenharmony_ci		return -EINVAL;
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci	ret = dm_get_device(ti, argv[0], dm_table_get_mode(ti->table),
728c2ecf20Sopenharmony_ci			    &sc->stripe[stripe].dev);
738c2ecf20Sopenharmony_ci	if (ret)
748c2ecf20Sopenharmony_ci		return ret;
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ci	sc->stripe[stripe].physical_start = start;
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci	return 0;
798c2ecf20Sopenharmony_ci}
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci/*
828c2ecf20Sopenharmony_ci * Construct a striped mapping.
838c2ecf20Sopenharmony_ci * <number of stripes> <chunk size> [<dev_path> <offset>]+
848c2ecf20Sopenharmony_ci */
858c2ecf20Sopenharmony_cistatic int stripe_ctr(struct dm_target *ti, unsigned int argc, char **argv)
868c2ecf20Sopenharmony_ci{
878c2ecf20Sopenharmony_ci	struct stripe_c *sc;
888c2ecf20Sopenharmony_ci	sector_t width, tmp_len;
898c2ecf20Sopenharmony_ci	uint32_t stripes;
908c2ecf20Sopenharmony_ci	uint32_t chunk_size;
918c2ecf20Sopenharmony_ci	int r;
928c2ecf20Sopenharmony_ci	unsigned int i;
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci	if (argc < 2) {
958c2ecf20Sopenharmony_ci		ti->error = "Not enough arguments";
968c2ecf20Sopenharmony_ci		return -EINVAL;
978c2ecf20Sopenharmony_ci	}
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_ci	if (kstrtouint(argv[0], 10, &stripes) || !stripes) {
1008c2ecf20Sopenharmony_ci		ti->error = "Invalid stripe count";
1018c2ecf20Sopenharmony_ci		return -EINVAL;
1028c2ecf20Sopenharmony_ci	}
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_ci	if (kstrtouint(argv[1], 10, &chunk_size) || !chunk_size) {
1058c2ecf20Sopenharmony_ci		ti->error = "Invalid chunk_size";
1068c2ecf20Sopenharmony_ci		return -EINVAL;
1078c2ecf20Sopenharmony_ci	}
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_ci	width = ti->len;
1108c2ecf20Sopenharmony_ci	if (sector_div(width, stripes)) {
1118c2ecf20Sopenharmony_ci		ti->error = "Target length not divisible by "
1128c2ecf20Sopenharmony_ci		    "number of stripes";
1138c2ecf20Sopenharmony_ci		return -EINVAL;
1148c2ecf20Sopenharmony_ci	}
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ci	tmp_len = width;
1178c2ecf20Sopenharmony_ci	if (sector_div(tmp_len, chunk_size)) {
1188c2ecf20Sopenharmony_ci		ti->error = "Target length not divisible by "
1198c2ecf20Sopenharmony_ci		    "chunk size";
1208c2ecf20Sopenharmony_ci		return -EINVAL;
1218c2ecf20Sopenharmony_ci	}
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_ci	/*
1248c2ecf20Sopenharmony_ci	 * Do we have enough arguments for that many stripes ?
1258c2ecf20Sopenharmony_ci	 */
1268c2ecf20Sopenharmony_ci	if (argc != (2 + 2 * stripes)) {
1278c2ecf20Sopenharmony_ci		ti->error = "Not enough destinations "
1288c2ecf20Sopenharmony_ci			"specified";
1298c2ecf20Sopenharmony_ci		return -EINVAL;
1308c2ecf20Sopenharmony_ci	}
1318c2ecf20Sopenharmony_ci
1328c2ecf20Sopenharmony_ci	sc = kmalloc(struct_size(sc, stripe, stripes), GFP_KERNEL);
1338c2ecf20Sopenharmony_ci	if (!sc) {
1348c2ecf20Sopenharmony_ci		ti->error = "Memory allocation for striped context "
1358c2ecf20Sopenharmony_ci		    "failed";
1368c2ecf20Sopenharmony_ci		return -ENOMEM;
1378c2ecf20Sopenharmony_ci	}
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci	INIT_WORK(&sc->trigger_event, trigger_event);
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_ci	/* Set pointer to dm target; used in trigger_event */
1428c2ecf20Sopenharmony_ci	sc->ti = ti;
1438c2ecf20Sopenharmony_ci	sc->stripes = stripes;
1448c2ecf20Sopenharmony_ci	sc->stripe_width = width;
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_ci	if (stripes & (stripes - 1))
1478c2ecf20Sopenharmony_ci		sc->stripes_shift = -1;
1488c2ecf20Sopenharmony_ci	else
1498c2ecf20Sopenharmony_ci		sc->stripes_shift = __ffs(stripes);
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_ci	r = dm_set_target_max_io_len(ti, chunk_size);
1528c2ecf20Sopenharmony_ci	if (r) {
1538c2ecf20Sopenharmony_ci		kfree(sc);
1548c2ecf20Sopenharmony_ci		return r;
1558c2ecf20Sopenharmony_ci	}
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_ci	ti->num_flush_bios = stripes;
1588c2ecf20Sopenharmony_ci	ti->num_discard_bios = stripes;
1598c2ecf20Sopenharmony_ci	ti->num_secure_erase_bios = stripes;
1608c2ecf20Sopenharmony_ci	ti->num_write_same_bios = stripes;
1618c2ecf20Sopenharmony_ci	ti->num_write_zeroes_bios = stripes;
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_ci	sc->chunk_size = chunk_size;
1648c2ecf20Sopenharmony_ci	if (chunk_size & (chunk_size - 1))
1658c2ecf20Sopenharmony_ci		sc->chunk_size_shift = -1;
1668c2ecf20Sopenharmony_ci	else
1678c2ecf20Sopenharmony_ci		sc->chunk_size_shift = __ffs(chunk_size);
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_ci	/*
1708c2ecf20Sopenharmony_ci	 * Get the stripe destinations.
1718c2ecf20Sopenharmony_ci	 */
1728c2ecf20Sopenharmony_ci	for (i = 0; i < stripes; i++) {
1738c2ecf20Sopenharmony_ci		argv += 2;
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_ci		r = get_stripe(ti, sc, i, argv);
1768c2ecf20Sopenharmony_ci		if (r < 0) {
1778c2ecf20Sopenharmony_ci			ti->error = "Couldn't parse stripe destination";
1788c2ecf20Sopenharmony_ci			while (i--)
1798c2ecf20Sopenharmony_ci				dm_put_device(ti, sc->stripe[i].dev);
1808c2ecf20Sopenharmony_ci			kfree(sc);
1818c2ecf20Sopenharmony_ci			return r;
1828c2ecf20Sopenharmony_ci		}
1838c2ecf20Sopenharmony_ci		atomic_set(&(sc->stripe[i].error_count), 0);
1848c2ecf20Sopenharmony_ci	}
1858c2ecf20Sopenharmony_ci
1868c2ecf20Sopenharmony_ci	ti->private = sc;
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_ci	return 0;
1898c2ecf20Sopenharmony_ci}
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_cistatic void stripe_dtr(struct dm_target *ti)
1928c2ecf20Sopenharmony_ci{
1938c2ecf20Sopenharmony_ci	unsigned int i;
1948c2ecf20Sopenharmony_ci	struct stripe_c *sc = (struct stripe_c *) ti->private;
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_ci	for (i = 0; i < sc->stripes; i++)
1978c2ecf20Sopenharmony_ci		dm_put_device(ti, sc->stripe[i].dev);
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ci	flush_work(&sc->trigger_event);
2008c2ecf20Sopenharmony_ci	kfree(sc);
2018c2ecf20Sopenharmony_ci}
2028c2ecf20Sopenharmony_ci
2038c2ecf20Sopenharmony_cistatic void stripe_map_sector(struct stripe_c *sc, sector_t sector,
2048c2ecf20Sopenharmony_ci			      uint32_t *stripe, sector_t *result)
2058c2ecf20Sopenharmony_ci{
2068c2ecf20Sopenharmony_ci	sector_t chunk = dm_target_offset(sc->ti, sector);
2078c2ecf20Sopenharmony_ci	sector_t chunk_offset;
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ci	if (sc->chunk_size_shift < 0)
2108c2ecf20Sopenharmony_ci		chunk_offset = sector_div(chunk, sc->chunk_size);
2118c2ecf20Sopenharmony_ci	else {
2128c2ecf20Sopenharmony_ci		chunk_offset = chunk & (sc->chunk_size - 1);
2138c2ecf20Sopenharmony_ci		chunk >>= sc->chunk_size_shift;
2148c2ecf20Sopenharmony_ci	}
2158c2ecf20Sopenharmony_ci
2168c2ecf20Sopenharmony_ci	if (sc->stripes_shift < 0)
2178c2ecf20Sopenharmony_ci		*stripe = sector_div(chunk, sc->stripes);
2188c2ecf20Sopenharmony_ci	else {
2198c2ecf20Sopenharmony_ci		*stripe = chunk & (sc->stripes - 1);
2208c2ecf20Sopenharmony_ci		chunk >>= sc->stripes_shift;
2218c2ecf20Sopenharmony_ci	}
2228c2ecf20Sopenharmony_ci
2238c2ecf20Sopenharmony_ci	if (sc->chunk_size_shift < 0)
2248c2ecf20Sopenharmony_ci		chunk *= sc->chunk_size;
2258c2ecf20Sopenharmony_ci	else
2268c2ecf20Sopenharmony_ci		chunk <<= sc->chunk_size_shift;
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_ci	*result = chunk + chunk_offset;
2298c2ecf20Sopenharmony_ci}
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_cistatic void stripe_map_range_sector(struct stripe_c *sc, sector_t sector,
2328c2ecf20Sopenharmony_ci				    uint32_t target_stripe, sector_t *result)
2338c2ecf20Sopenharmony_ci{
2348c2ecf20Sopenharmony_ci	uint32_t stripe;
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_ci	stripe_map_sector(sc, sector, &stripe, result);
2378c2ecf20Sopenharmony_ci	if (stripe == target_stripe)
2388c2ecf20Sopenharmony_ci		return;
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_ci	/* round down */
2418c2ecf20Sopenharmony_ci	sector = *result;
2428c2ecf20Sopenharmony_ci	if (sc->chunk_size_shift < 0)
2438c2ecf20Sopenharmony_ci		*result -= sector_div(sector, sc->chunk_size);
2448c2ecf20Sopenharmony_ci	else
2458c2ecf20Sopenharmony_ci		*result = sector & ~(sector_t)(sc->chunk_size - 1);
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ci	if (target_stripe < stripe)
2488c2ecf20Sopenharmony_ci		*result += sc->chunk_size;		/* next chunk */
2498c2ecf20Sopenharmony_ci}
2508c2ecf20Sopenharmony_ci
2518c2ecf20Sopenharmony_cistatic int stripe_map_range(struct stripe_c *sc, struct bio *bio,
2528c2ecf20Sopenharmony_ci			    uint32_t target_stripe)
2538c2ecf20Sopenharmony_ci{
2548c2ecf20Sopenharmony_ci	sector_t begin, end;
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_ci	stripe_map_range_sector(sc, bio->bi_iter.bi_sector,
2578c2ecf20Sopenharmony_ci				target_stripe, &begin);
2588c2ecf20Sopenharmony_ci	stripe_map_range_sector(sc, bio_end_sector(bio),
2598c2ecf20Sopenharmony_ci				target_stripe, &end);
2608c2ecf20Sopenharmony_ci	if (begin < end) {
2618c2ecf20Sopenharmony_ci		bio_set_dev(bio, sc->stripe[target_stripe].dev->bdev);
2628c2ecf20Sopenharmony_ci		bio->bi_iter.bi_sector = begin +
2638c2ecf20Sopenharmony_ci			sc->stripe[target_stripe].physical_start;
2648c2ecf20Sopenharmony_ci		bio->bi_iter.bi_size = to_bytes(end - begin);
2658c2ecf20Sopenharmony_ci		return DM_MAPIO_REMAPPED;
2668c2ecf20Sopenharmony_ci	} else {
2678c2ecf20Sopenharmony_ci		/* The range doesn't map to the target stripe */
2688c2ecf20Sopenharmony_ci		bio_endio(bio);
2698c2ecf20Sopenharmony_ci		return DM_MAPIO_SUBMITTED;
2708c2ecf20Sopenharmony_ci	}
2718c2ecf20Sopenharmony_ci}
2728c2ecf20Sopenharmony_ci
2738c2ecf20Sopenharmony_cistatic int stripe_map(struct dm_target *ti, struct bio *bio)
2748c2ecf20Sopenharmony_ci{
2758c2ecf20Sopenharmony_ci	struct stripe_c *sc = ti->private;
2768c2ecf20Sopenharmony_ci	uint32_t stripe;
2778c2ecf20Sopenharmony_ci	unsigned target_bio_nr;
2788c2ecf20Sopenharmony_ci
2798c2ecf20Sopenharmony_ci	if (bio->bi_opf & REQ_PREFLUSH) {
2808c2ecf20Sopenharmony_ci		target_bio_nr = dm_bio_get_target_bio_nr(bio);
2818c2ecf20Sopenharmony_ci		BUG_ON(target_bio_nr >= sc->stripes);
2828c2ecf20Sopenharmony_ci		bio_set_dev(bio, sc->stripe[target_bio_nr].dev->bdev);
2838c2ecf20Sopenharmony_ci		return DM_MAPIO_REMAPPED;
2848c2ecf20Sopenharmony_ci	}
2858c2ecf20Sopenharmony_ci	if (unlikely(bio_op(bio) == REQ_OP_DISCARD) ||
2868c2ecf20Sopenharmony_ci	    unlikely(bio_op(bio) == REQ_OP_SECURE_ERASE) ||
2878c2ecf20Sopenharmony_ci	    unlikely(bio_op(bio) == REQ_OP_WRITE_ZEROES) ||
2888c2ecf20Sopenharmony_ci	    unlikely(bio_op(bio) == REQ_OP_WRITE_SAME)) {
2898c2ecf20Sopenharmony_ci		target_bio_nr = dm_bio_get_target_bio_nr(bio);
2908c2ecf20Sopenharmony_ci		BUG_ON(target_bio_nr >= sc->stripes);
2918c2ecf20Sopenharmony_ci		return stripe_map_range(sc, bio, target_bio_nr);
2928c2ecf20Sopenharmony_ci	}
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_ci	stripe_map_sector(sc, bio->bi_iter.bi_sector,
2958c2ecf20Sopenharmony_ci			  &stripe, &bio->bi_iter.bi_sector);
2968c2ecf20Sopenharmony_ci
2978c2ecf20Sopenharmony_ci	bio->bi_iter.bi_sector += sc->stripe[stripe].physical_start;
2988c2ecf20Sopenharmony_ci	bio_set_dev(bio, sc->stripe[stripe].dev->bdev);
2998c2ecf20Sopenharmony_ci
3008c2ecf20Sopenharmony_ci	return DM_MAPIO_REMAPPED;
3018c2ecf20Sopenharmony_ci}
3028c2ecf20Sopenharmony_ci
3038c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_DAX_DRIVER)
3048c2ecf20Sopenharmony_cistatic long stripe_dax_direct_access(struct dm_target *ti, pgoff_t pgoff,
3058c2ecf20Sopenharmony_ci		long nr_pages, void **kaddr, pfn_t *pfn)
3068c2ecf20Sopenharmony_ci{
3078c2ecf20Sopenharmony_ci	sector_t dev_sector, sector = pgoff * PAGE_SECTORS;
3088c2ecf20Sopenharmony_ci	struct stripe_c *sc = ti->private;
3098c2ecf20Sopenharmony_ci	struct dax_device *dax_dev;
3108c2ecf20Sopenharmony_ci	struct block_device *bdev;
3118c2ecf20Sopenharmony_ci	uint32_t stripe;
3128c2ecf20Sopenharmony_ci	long ret;
3138c2ecf20Sopenharmony_ci
3148c2ecf20Sopenharmony_ci	stripe_map_sector(sc, sector, &stripe, &dev_sector);
3158c2ecf20Sopenharmony_ci	dev_sector += sc->stripe[stripe].physical_start;
3168c2ecf20Sopenharmony_ci	dax_dev = sc->stripe[stripe].dev->dax_dev;
3178c2ecf20Sopenharmony_ci	bdev = sc->stripe[stripe].dev->bdev;
3188c2ecf20Sopenharmony_ci
3198c2ecf20Sopenharmony_ci	ret = bdev_dax_pgoff(bdev, dev_sector, nr_pages * PAGE_SIZE, &pgoff);
3208c2ecf20Sopenharmony_ci	if (ret)
3218c2ecf20Sopenharmony_ci		return ret;
3228c2ecf20Sopenharmony_ci	return dax_direct_access(dax_dev, pgoff, nr_pages, kaddr, pfn);
3238c2ecf20Sopenharmony_ci}
3248c2ecf20Sopenharmony_ci
3258c2ecf20Sopenharmony_cistatic size_t stripe_dax_copy_from_iter(struct dm_target *ti, pgoff_t pgoff,
3268c2ecf20Sopenharmony_ci		void *addr, size_t bytes, struct iov_iter *i)
3278c2ecf20Sopenharmony_ci{
3288c2ecf20Sopenharmony_ci	sector_t dev_sector, sector = pgoff * PAGE_SECTORS;
3298c2ecf20Sopenharmony_ci	struct stripe_c *sc = ti->private;
3308c2ecf20Sopenharmony_ci	struct dax_device *dax_dev;
3318c2ecf20Sopenharmony_ci	struct block_device *bdev;
3328c2ecf20Sopenharmony_ci	uint32_t stripe;
3338c2ecf20Sopenharmony_ci
3348c2ecf20Sopenharmony_ci	stripe_map_sector(sc, sector, &stripe, &dev_sector);
3358c2ecf20Sopenharmony_ci	dev_sector += sc->stripe[stripe].physical_start;
3368c2ecf20Sopenharmony_ci	dax_dev = sc->stripe[stripe].dev->dax_dev;
3378c2ecf20Sopenharmony_ci	bdev = sc->stripe[stripe].dev->bdev;
3388c2ecf20Sopenharmony_ci
3398c2ecf20Sopenharmony_ci	if (bdev_dax_pgoff(bdev, dev_sector, ALIGN(bytes, PAGE_SIZE), &pgoff))
3408c2ecf20Sopenharmony_ci		return 0;
3418c2ecf20Sopenharmony_ci	return dax_copy_from_iter(dax_dev, pgoff, addr, bytes, i);
3428c2ecf20Sopenharmony_ci}
3438c2ecf20Sopenharmony_ci
3448c2ecf20Sopenharmony_cistatic size_t stripe_dax_copy_to_iter(struct dm_target *ti, pgoff_t pgoff,
3458c2ecf20Sopenharmony_ci		void *addr, size_t bytes, struct iov_iter *i)
3468c2ecf20Sopenharmony_ci{
3478c2ecf20Sopenharmony_ci	sector_t dev_sector, sector = pgoff * PAGE_SECTORS;
3488c2ecf20Sopenharmony_ci	struct stripe_c *sc = ti->private;
3498c2ecf20Sopenharmony_ci	struct dax_device *dax_dev;
3508c2ecf20Sopenharmony_ci	struct block_device *bdev;
3518c2ecf20Sopenharmony_ci	uint32_t stripe;
3528c2ecf20Sopenharmony_ci
3538c2ecf20Sopenharmony_ci	stripe_map_sector(sc, sector, &stripe, &dev_sector);
3548c2ecf20Sopenharmony_ci	dev_sector += sc->stripe[stripe].physical_start;
3558c2ecf20Sopenharmony_ci	dax_dev = sc->stripe[stripe].dev->dax_dev;
3568c2ecf20Sopenharmony_ci	bdev = sc->stripe[stripe].dev->bdev;
3578c2ecf20Sopenharmony_ci
3588c2ecf20Sopenharmony_ci	if (bdev_dax_pgoff(bdev, dev_sector, ALIGN(bytes, PAGE_SIZE), &pgoff))
3598c2ecf20Sopenharmony_ci		return 0;
3608c2ecf20Sopenharmony_ci	return dax_copy_to_iter(dax_dev, pgoff, addr, bytes, i);
3618c2ecf20Sopenharmony_ci}
3628c2ecf20Sopenharmony_ci
3638c2ecf20Sopenharmony_cistatic int stripe_dax_zero_page_range(struct dm_target *ti, pgoff_t pgoff,
3648c2ecf20Sopenharmony_ci				      size_t nr_pages)
3658c2ecf20Sopenharmony_ci{
3668c2ecf20Sopenharmony_ci	int ret;
3678c2ecf20Sopenharmony_ci	sector_t dev_sector, sector = pgoff * PAGE_SECTORS;
3688c2ecf20Sopenharmony_ci	struct stripe_c *sc = ti->private;
3698c2ecf20Sopenharmony_ci	struct dax_device *dax_dev;
3708c2ecf20Sopenharmony_ci	struct block_device *bdev;
3718c2ecf20Sopenharmony_ci	uint32_t stripe;
3728c2ecf20Sopenharmony_ci
3738c2ecf20Sopenharmony_ci	stripe_map_sector(sc, sector, &stripe, &dev_sector);
3748c2ecf20Sopenharmony_ci	dev_sector += sc->stripe[stripe].physical_start;
3758c2ecf20Sopenharmony_ci	dax_dev = sc->stripe[stripe].dev->dax_dev;
3768c2ecf20Sopenharmony_ci	bdev = sc->stripe[stripe].dev->bdev;
3778c2ecf20Sopenharmony_ci
3788c2ecf20Sopenharmony_ci	ret = bdev_dax_pgoff(bdev, dev_sector, nr_pages << PAGE_SHIFT, &pgoff);
3798c2ecf20Sopenharmony_ci	if (ret)
3808c2ecf20Sopenharmony_ci		return ret;
3818c2ecf20Sopenharmony_ci	return dax_zero_page_range(dax_dev, pgoff, nr_pages);
3828c2ecf20Sopenharmony_ci}
3838c2ecf20Sopenharmony_ci
3848c2ecf20Sopenharmony_ci#else
3858c2ecf20Sopenharmony_ci#define stripe_dax_direct_access NULL
3868c2ecf20Sopenharmony_ci#define stripe_dax_copy_from_iter NULL
3878c2ecf20Sopenharmony_ci#define stripe_dax_copy_to_iter NULL
3888c2ecf20Sopenharmony_ci#define stripe_dax_zero_page_range NULL
3898c2ecf20Sopenharmony_ci#endif
3908c2ecf20Sopenharmony_ci
3918c2ecf20Sopenharmony_ci/*
3928c2ecf20Sopenharmony_ci * Stripe status:
3938c2ecf20Sopenharmony_ci *
3948c2ecf20Sopenharmony_ci * INFO
3958c2ecf20Sopenharmony_ci * #stripes [stripe_name <stripe_name>] [group word count]
3968c2ecf20Sopenharmony_ci * [error count 'A|D' <error count 'A|D'>]
3978c2ecf20Sopenharmony_ci *
3988c2ecf20Sopenharmony_ci * TABLE
3998c2ecf20Sopenharmony_ci * #stripes [stripe chunk size]
4008c2ecf20Sopenharmony_ci * [stripe_name physical_start <stripe_name physical_start>]
4018c2ecf20Sopenharmony_ci *
4028c2ecf20Sopenharmony_ci */
4038c2ecf20Sopenharmony_ci
4048c2ecf20Sopenharmony_cistatic void stripe_status(struct dm_target *ti, status_type_t type,
4058c2ecf20Sopenharmony_ci			  unsigned status_flags, char *result, unsigned maxlen)
4068c2ecf20Sopenharmony_ci{
4078c2ecf20Sopenharmony_ci	struct stripe_c *sc = (struct stripe_c *) ti->private;
4088c2ecf20Sopenharmony_ci	unsigned int sz = 0;
4098c2ecf20Sopenharmony_ci	unsigned int i;
4108c2ecf20Sopenharmony_ci
4118c2ecf20Sopenharmony_ci	switch (type) {
4128c2ecf20Sopenharmony_ci	case STATUSTYPE_INFO:
4138c2ecf20Sopenharmony_ci		DMEMIT("%d ", sc->stripes);
4148c2ecf20Sopenharmony_ci		for (i = 0; i < sc->stripes; i++)  {
4158c2ecf20Sopenharmony_ci			DMEMIT("%s ", sc->stripe[i].dev->name);
4168c2ecf20Sopenharmony_ci		}
4178c2ecf20Sopenharmony_ci		DMEMIT("1 ");
4188c2ecf20Sopenharmony_ci		for (i = 0; i < sc->stripes; i++) {
4198c2ecf20Sopenharmony_ci			DMEMIT("%c", atomic_read(&(sc->stripe[i].error_count)) ?
4208c2ecf20Sopenharmony_ci			       'D' : 'A');
4218c2ecf20Sopenharmony_ci		}
4228c2ecf20Sopenharmony_ci		break;
4238c2ecf20Sopenharmony_ci
4248c2ecf20Sopenharmony_ci	case STATUSTYPE_TABLE:
4258c2ecf20Sopenharmony_ci		DMEMIT("%d %llu", sc->stripes,
4268c2ecf20Sopenharmony_ci			(unsigned long long)sc->chunk_size);
4278c2ecf20Sopenharmony_ci		for (i = 0; i < sc->stripes; i++)
4288c2ecf20Sopenharmony_ci			DMEMIT(" %s %llu", sc->stripe[i].dev->name,
4298c2ecf20Sopenharmony_ci			    (unsigned long long)sc->stripe[i].physical_start);
4308c2ecf20Sopenharmony_ci		break;
4318c2ecf20Sopenharmony_ci	}
4328c2ecf20Sopenharmony_ci}
4338c2ecf20Sopenharmony_ci
4348c2ecf20Sopenharmony_cistatic int stripe_end_io(struct dm_target *ti, struct bio *bio,
4358c2ecf20Sopenharmony_ci		blk_status_t *error)
4368c2ecf20Sopenharmony_ci{
4378c2ecf20Sopenharmony_ci	unsigned i;
4388c2ecf20Sopenharmony_ci	char major_minor[16];
4398c2ecf20Sopenharmony_ci	struct stripe_c *sc = ti->private;
4408c2ecf20Sopenharmony_ci
4418c2ecf20Sopenharmony_ci	if (!*error)
4428c2ecf20Sopenharmony_ci		return DM_ENDIO_DONE; /* I/O complete */
4438c2ecf20Sopenharmony_ci
4448c2ecf20Sopenharmony_ci	if (bio->bi_opf & REQ_RAHEAD)
4458c2ecf20Sopenharmony_ci		return DM_ENDIO_DONE;
4468c2ecf20Sopenharmony_ci
4478c2ecf20Sopenharmony_ci	if (*error == BLK_STS_NOTSUPP)
4488c2ecf20Sopenharmony_ci		return DM_ENDIO_DONE;
4498c2ecf20Sopenharmony_ci
4508c2ecf20Sopenharmony_ci	memset(major_minor, 0, sizeof(major_minor));
4518c2ecf20Sopenharmony_ci	sprintf(major_minor, "%d:%d", MAJOR(bio_dev(bio)), MINOR(bio_dev(bio)));
4528c2ecf20Sopenharmony_ci
4538c2ecf20Sopenharmony_ci	/*
4548c2ecf20Sopenharmony_ci	 * Test to see which stripe drive triggered the event
4558c2ecf20Sopenharmony_ci	 * and increment error count for all stripes on that device.
4568c2ecf20Sopenharmony_ci	 * If the error count for a given device exceeds the threshold
4578c2ecf20Sopenharmony_ci	 * value we will no longer trigger any further events.
4588c2ecf20Sopenharmony_ci	 */
4598c2ecf20Sopenharmony_ci	for (i = 0; i < sc->stripes; i++)
4608c2ecf20Sopenharmony_ci		if (!strcmp(sc->stripe[i].dev->name, major_minor)) {
4618c2ecf20Sopenharmony_ci			atomic_inc(&(sc->stripe[i].error_count));
4628c2ecf20Sopenharmony_ci			if (atomic_read(&(sc->stripe[i].error_count)) <
4638c2ecf20Sopenharmony_ci			    DM_IO_ERROR_THRESHOLD)
4648c2ecf20Sopenharmony_ci				schedule_work(&sc->trigger_event);
4658c2ecf20Sopenharmony_ci		}
4668c2ecf20Sopenharmony_ci
4678c2ecf20Sopenharmony_ci	return DM_ENDIO_DONE;
4688c2ecf20Sopenharmony_ci}
4698c2ecf20Sopenharmony_ci
4708c2ecf20Sopenharmony_cistatic int stripe_iterate_devices(struct dm_target *ti,
4718c2ecf20Sopenharmony_ci				  iterate_devices_callout_fn fn, void *data)
4728c2ecf20Sopenharmony_ci{
4738c2ecf20Sopenharmony_ci	struct stripe_c *sc = ti->private;
4748c2ecf20Sopenharmony_ci	int ret = 0;
4758c2ecf20Sopenharmony_ci	unsigned i = 0;
4768c2ecf20Sopenharmony_ci
4778c2ecf20Sopenharmony_ci	do {
4788c2ecf20Sopenharmony_ci		ret = fn(ti, sc->stripe[i].dev,
4798c2ecf20Sopenharmony_ci			 sc->stripe[i].physical_start,
4808c2ecf20Sopenharmony_ci			 sc->stripe_width, data);
4818c2ecf20Sopenharmony_ci	} while (!ret && ++i < sc->stripes);
4828c2ecf20Sopenharmony_ci
4838c2ecf20Sopenharmony_ci	return ret;
4848c2ecf20Sopenharmony_ci}
4858c2ecf20Sopenharmony_ci
4868c2ecf20Sopenharmony_cistatic void stripe_io_hints(struct dm_target *ti,
4878c2ecf20Sopenharmony_ci			    struct queue_limits *limits)
4888c2ecf20Sopenharmony_ci{
4898c2ecf20Sopenharmony_ci	struct stripe_c *sc = ti->private;
4908c2ecf20Sopenharmony_ci	unsigned chunk_size = sc->chunk_size << SECTOR_SHIFT;
4918c2ecf20Sopenharmony_ci
4928c2ecf20Sopenharmony_ci	blk_limits_io_min(limits, chunk_size);
4938c2ecf20Sopenharmony_ci	blk_limits_io_opt(limits, chunk_size * sc->stripes);
4948c2ecf20Sopenharmony_ci}
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_cistatic struct target_type stripe_target = {
4978c2ecf20Sopenharmony_ci	.name   = "striped",
4988c2ecf20Sopenharmony_ci	.version = {1, 6, 0},
4998c2ecf20Sopenharmony_ci	.features = DM_TARGET_PASSES_INTEGRITY,
5008c2ecf20Sopenharmony_ci	.module = THIS_MODULE,
5018c2ecf20Sopenharmony_ci	.ctr    = stripe_ctr,
5028c2ecf20Sopenharmony_ci	.dtr    = stripe_dtr,
5038c2ecf20Sopenharmony_ci	.map    = stripe_map,
5048c2ecf20Sopenharmony_ci	.end_io = stripe_end_io,
5058c2ecf20Sopenharmony_ci	.status = stripe_status,
5068c2ecf20Sopenharmony_ci	.iterate_devices = stripe_iterate_devices,
5078c2ecf20Sopenharmony_ci	.io_hints = stripe_io_hints,
5088c2ecf20Sopenharmony_ci	.direct_access = stripe_dax_direct_access,
5098c2ecf20Sopenharmony_ci	.dax_copy_from_iter = stripe_dax_copy_from_iter,
5108c2ecf20Sopenharmony_ci	.dax_copy_to_iter = stripe_dax_copy_to_iter,
5118c2ecf20Sopenharmony_ci	.dax_zero_page_range = stripe_dax_zero_page_range,
5128c2ecf20Sopenharmony_ci};
5138c2ecf20Sopenharmony_ci
5148c2ecf20Sopenharmony_ciint __init dm_stripe_init(void)
5158c2ecf20Sopenharmony_ci{
5168c2ecf20Sopenharmony_ci	int r;
5178c2ecf20Sopenharmony_ci
5188c2ecf20Sopenharmony_ci	r = dm_register_target(&stripe_target);
5198c2ecf20Sopenharmony_ci	if (r < 0)
5208c2ecf20Sopenharmony_ci		DMWARN("target registration failed");
5218c2ecf20Sopenharmony_ci
5228c2ecf20Sopenharmony_ci	return r;
5238c2ecf20Sopenharmony_ci}
5248c2ecf20Sopenharmony_ci
5258c2ecf20Sopenharmony_civoid dm_stripe_exit(void)
5268c2ecf20Sopenharmony_ci{
5278c2ecf20Sopenharmony_ci	dm_unregister_target(&stripe_target);
5288c2ecf20Sopenharmony_ci}
529