cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

dm-stripe.c (11944B)


      1/*
      2 * Copyright (C) 2001-2003 Sistina Software (UK) Limited.
      3 *
      4 * This file is released under the GPL.
      5 */
      6
      7#include "dm.h"
      8#include <linux/device-mapper.h>
      9
     10#include <linux/module.h>
     11#include <linux/init.h>
     12#include <linux/blkdev.h>
     13#include <linux/bio.h>
     14#include <linux/dax.h>
     15#include <linux/slab.h>
     16#include <linux/log2.h>
     17
     18#define DM_MSG_PREFIX "striped"
     19#define DM_IO_ERROR_THRESHOLD 15
     20
     21struct stripe {
     22	struct dm_dev *dev;
     23	sector_t physical_start;
     24
     25	atomic_t error_count;
     26};
     27
     28struct stripe_c {
     29	uint32_t stripes;
     30	int stripes_shift;
     31
     32	/* The size of this target / num. stripes */
     33	sector_t stripe_width;
     34
     35	uint32_t chunk_size;
     36	int chunk_size_shift;
     37
     38	/* Needed for handling events */
     39	struct dm_target *ti;
     40
     41	/* Work struct used for triggering events*/
     42	struct work_struct trigger_event;
     43
     44	struct stripe stripe[];
     45};
     46
     47/*
     48 * An event is triggered whenever a drive
     49 * drops out of a stripe volume.
     50 */
     51static void trigger_event(struct work_struct *work)
     52{
     53	struct stripe_c *sc = container_of(work, struct stripe_c,
     54					   trigger_event);
     55	dm_table_event(sc->ti->table);
     56}
     57
     58/*
     59 * Parse a single <dev> <sector> pair
     60 */
     61static int get_stripe(struct dm_target *ti, struct stripe_c *sc,
     62		      unsigned int stripe, char **argv)
     63{
     64	unsigned long long start;
     65	char dummy;
     66	int ret;
     67
     68	if (sscanf(argv[1], "%llu%c", &start, &dummy) != 1)
     69		return -EINVAL;
     70
     71	ret = dm_get_device(ti, argv[0], dm_table_get_mode(ti->table),
     72			    &sc->stripe[stripe].dev);
     73	if (ret)
     74		return ret;
     75
     76	sc->stripe[stripe].physical_start = start;
     77
     78	return 0;
     79}
     80
     81/*
     82 * Construct a striped mapping.
     83 * <number of stripes> <chunk size> [<dev_path> <offset>]+
     84 */
     85static int stripe_ctr(struct dm_target *ti, unsigned int argc, char **argv)
     86{
     87	struct stripe_c *sc;
     88	sector_t width, tmp_len;
     89	uint32_t stripes;
     90	uint32_t chunk_size;
     91	int r;
     92	unsigned int i;
     93
     94	if (argc < 2) {
     95		ti->error = "Not enough arguments";
     96		return -EINVAL;
     97	}
     98
     99	if (kstrtouint(argv[0], 10, &stripes) || !stripes) {
    100		ti->error = "Invalid stripe count";
    101		return -EINVAL;
    102	}
    103
    104	if (kstrtouint(argv[1], 10, &chunk_size) || !chunk_size) {
    105		ti->error = "Invalid chunk_size";
    106		return -EINVAL;
    107	}
    108
    109	width = ti->len;
    110	if (sector_div(width, stripes)) {
    111		ti->error = "Target length not divisible by "
    112		    "number of stripes";
    113		return -EINVAL;
    114	}
    115
    116	tmp_len = width;
    117	if (sector_div(tmp_len, chunk_size)) {
    118		ti->error = "Target length not divisible by "
    119		    "chunk size";
    120		return -EINVAL;
    121	}
    122
    123	/*
    124	 * Do we have enough arguments for that many stripes ?
    125	 */
    126	if (argc != (2 + 2 * stripes)) {
    127		ti->error = "Not enough destinations "
    128			"specified";
    129		return -EINVAL;
    130	}
    131
    132	sc = kmalloc(struct_size(sc, stripe, stripes), GFP_KERNEL);
    133	if (!sc) {
    134		ti->error = "Memory allocation for striped context "
    135		    "failed";
    136		return -ENOMEM;
    137	}
    138
    139	INIT_WORK(&sc->trigger_event, trigger_event);
    140
    141	/* Set pointer to dm target; used in trigger_event */
    142	sc->ti = ti;
    143	sc->stripes = stripes;
    144	sc->stripe_width = width;
    145
    146	if (stripes & (stripes - 1))
    147		sc->stripes_shift = -1;
    148	else
    149		sc->stripes_shift = __ffs(stripes);
    150
    151	r = dm_set_target_max_io_len(ti, chunk_size);
    152	if (r) {
    153		kfree(sc);
    154		return r;
    155	}
    156
    157	ti->num_flush_bios = stripes;
    158	ti->num_discard_bios = stripes;
    159	ti->num_secure_erase_bios = stripes;
    160	ti->num_write_zeroes_bios = stripes;
    161
    162	sc->chunk_size = chunk_size;
    163	if (chunk_size & (chunk_size - 1))
    164		sc->chunk_size_shift = -1;
    165	else
    166		sc->chunk_size_shift = __ffs(chunk_size);
    167
    168	/*
    169	 * Get the stripe destinations.
    170	 */
    171	for (i = 0; i < stripes; i++) {
    172		argv += 2;
    173
    174		r = get_stripe(ti, sc, i, argv);
    175		if (r < 0) {
    176			ti->error = "Couldn't parse stripe destination";
    177			while (i--)
    178				dm_put_device(ti, sc->stripe[i].dev);
    179			kfree(sc);
    180			return r;
    181		}
    182		atomic_set(&(sc->stripe[i].error_count), 0);
    183	}
    184
    185	ti->private = sc;
    186
    187	return 0;
    188}
    189
    190static void stripe_dtr(struct dm_target *ti)
    191{
    192	unsigned int i;
    193	struct stripe_c *sc = (struct stripe_c *) ti->private;
    194
    195	for (i = 0; i < sc->stripes; i++)
    196		dm_put_device(ti, sc->stripe[i].dev);
    197
    198	flush_work(&sc->trigger_event);
    199	kfree(sc);
    200}
    201
    202static void stripe_map_sector(struct stripe_c *sc, sector_t sector,
    203			      uint32_t *stripe, sector_t *result)
    204{
    205	sector_t chunk = dm_target_offset(sc->ti, sector);
    206	sector_t chunk_offset;
    207
    208	if (sc->chunk_size_shift < 0)
    209		chunk_offset = sector_div(chunk, sc->chunk_size);
    210	else {
    211		chunk_offset = chunk & (sc->chunk_size - 1);
    212		chunk >>= sc->chunk_size_shift;
    213	}
    214
    215	if (sc->stripes_shift < 0)
    216		*stripe = sector_div(chunk, sc->stripes);
    217	else {
    218		*stripe = chunk & (sc->stripes - 1);
    219		chunk >>= sc->stripes_shift;
    220	}
    221
    222	if (sc->chunk_size_shift < 0)
    223		chunk *= sc->chunk_size;
    224	else
    225		chunk <<= sc->chunk_size_shift;
    226
    227	*result = chunk + chunk_offset;
    228}
    229
    230static void stripe_map_range_sector(struct stripe_c *sc, sector_t sector,
    231				    uint32_t target_stripe, sector_t *result)
    232{
    233	uint32_t stripe;
    234
    235	stripe_map_sector(sc, sector, &stripe, result);
    236	if (stripe == target_stripe)
    237		return;
    238
    239	/* round down */
    240	sector = *result;
    241	if (sc->chunk_size_shift < 0)
    242		*result -= sector_div(sector, sc->chunk_size);
    243	else
    244		*result = sector & ~(sector_t)(sc->chunk_size - 1);
    245
    246	if (target_stripe < stripe)
    247		*result += sc->chunk_size;		/* next chunk */
    248}
    249
    250static int stripe_map_range(struct stripe_c *sc, struct bio *bio,
    251			    uint32_t target_stripe)
    252{
    253	sector_t begin, end;
    254
    255	stripe_map_range_sector(sc, bio->bi_iter.bi_sector,
    256				target_stripe, &begin);
    257	stripe_map_range_sector(sc, bio_end_sector(bio),
    258				target_stripe, &end);
    259	if (begin < end) {
    260		bio_set_dev(bio, sc->stripe[target_stripe].dev->bdev);
    261		bio->bi_iter.bi_sector = begin +
    262			sc->stripe[target_stripe].physical_start;
    263		bio->bi_iter.bi_size = to_bytes(end - begin);
    264		return DM_MAPIO_REMAPPED;
    265	} else {
    266		/* The range doesn't map to the target stripe */
    267		bio_endio(bio);
    268		return DM_MAPIO_SUBMITTED;
    269	}
    270}
    271
    272static int stripe_map(struct dm_target *ti, struct bio *bio)
    273{
    274	struct stripe_c *sc = ti->private;
    275	uint32_t stripe;
    276	unsigned target_bio_nr;
    277
    278	if (bio->bi_opf & REQ_PREFLUSH) {
    279		target_bio_nr = dm_bio_get_target_bio_nr(bio);
    280		BUG_ON(target_bio_nr >= sc->stripes);
    281		bio_set_dev(bio, sc->stripe[target_bio_nr].dev->bdev);
    282		return DM_MAPIO_REMAPPED;
    283	}
    284	if (unlikely(bio_op(bio) == REQ_OP_DISCARD) ||
    285	    unlikely(bio_op(bio) == REQ_OP_SECURE_ERASE) ||
    286	    unlikely(bio_op(bio) == REQ_OP_WRITE_ZEROES)) {
    287		target_bio_nr = dm_bio_get_target_bio_nr(bio);
    288		BUG_ON(target_bio_nr >= sc->stripes);
    289		return stripe_map_range(sc, bio, target_bio_nr);
    290	}
    291
    292	stripe_map_sector(sc, bio->bi_iter.bi_sector,
    293			  &stripe, &bio->bi_iter.bi_sector);
    294
    295	bio->bi_iter.bi_sector += sc->stripe[stripe].physical_start;
    296	bio_set_dev(bio, sc->stripe[stripe].dev->bdev);
    297
    298	return DM_MAPIO_REMAPPED;
    299}
    300
    301#if IS_ENABLED(CONFIG_FS_DAX)
    302static struct dax_device *stripe_dax_pgoff(struct dm_target *ti, pgoff_t *pgoff)
    303{
    304	struct stripe_c *sc = ti->private;
    305	struct block_device *bdev;
    306	sector_t dev_sector;
    307	uint32_t stripe;
    308
    309	stripe_map_sector(sc, *pgoff * PAGE_SECTORS, &stripe, &dev_sector);
    310	dev_sector += sc->stripe[stripe].physical_start;
    311	bdev = sc->stripe[stripe].dev->bdev;
    312
    313	*pgoff = (get_start_sect(bdev) + dev_sector) >> PAGE_SECTORS_SHIFT;
    314	return sc->stripe[stripe].dev->dax_dev;
    315}
    316
    317static long stripe_dax_direct_access(struct dm_target *ti, pgoff_t pgoff,
    318		long nr_pages, enum dax_access_mode mode, void **kaddr,
    319		pfn_t *pfn)
    320{
    321	struct dax_device *dax_dev = stripe_dax_pgoff(ti, &pgoff);
    322
    323	return dax_direct_access(dax_dev, pgoff, nr_pages, mode, kaddr, pfn);
    324}
    325
    326static int stripe_dax_zero_page_range(struct dm_target *ti, pgoff_t pgoff,
    327				      size_t nr_pages)
    328{
    329	struct dax_device *dax_dev = stripe_dax_pgoff(ti, &pgoff);
    330
    331	return dax_zero_page_range(dax_dev, pgoff, nr_pages);
    332}
    333
    334static size_t stripe_dax_recovery_write(struct dm_target *ti, pgoff_t pgoff,
    335		void *addr, size_t bytes, struct iov_iter *i)
    336{
    337	struct dax_device *dax_dev = stripe_dax_pgoff(ti, &pgoff);
    338
    339	return dax_recovery_write(dax_dev, pgoff, addr, bytes, i);
    340}
    341
    342#else
    343#define stripe_dax_direct_access NULL
    344#define stripe_dax_zero_page_range NULL
    345#define stripe_dax_recovery_write NULL
    346#endif
    347
    348/*
    349 * Stripe status:
    350 *
    351 * INFO
    352 * #stripes [stripe_name <stripe_name>] [group word count]
    353 * [error count 'A|D' <error count 'A|D'>]
    354 *
    355 * TABLE
    356 * #stripes [stripe chunk size]
    357 * [stripe_name physical_start <stripe_name physical_start>]
    358 *
    359 */
    360
    361static void stripe_status(struct dm_target *ti, status_type_t type,
    362			  unsigned status_flags, char *result, unsigned maxlen)
    363{
    364	struct stripe_c *sc = (struct stripe_c *) ti->private;
    365	unsigned int sz = 0;
    366	unsigned int i;
    367
    368	switch (type) {
    369	case STATUSTYPE_INFO:
    370		DMEMIT("%d ", sc->stripes);
    371		for (i = 0; i < sc->stripes; i++)  {
    372			DMEMIT("%s ", sc->stripe[i].dev->name);
    373		}
    374		DMEMIT("1 ");
    375		for (i = 0; i < sc->stripes; i++) {
    376			DMEMIT("%c", atomic_read(&(sc->stripe[i].error_count)) ?
    377			       'D' : 'A');
    378		}
    379		break;
    380
    381	case STATUSTYPE_TABLE:
    382		DMEMIT("%d %llu", sc->stripes,
    383			(unsigned long long)sc->chunk_size);
    384		for (i = 0; i < sc->stripes; i++)
    385			DMEMIT(" %s %llu", sc->stripe[i].dev->name,
    386			    (unsigned long long)sc->stripe[i].physical_start);
    387		break;
    388
    389	case STATUSTYPE_IMA:
    390		DMEMIT_TARGET_NAME_VERSION(ti->type);
    391		DMEMIT(",stripes=%d,chunk_size=%llu", sc->stripes,
    392		       (unsigned long long)sc->chunk_size);
    393
    394		for (i = 0; i < sc->stripes; i++) {
    395			DMEMIT(",stripe_%d_device_name=%s", i, sc->stripe[i].dev->name);
    396			DMEMIT(",stripe_%d_physical_start=%llu", i,
    397			       (unsigned long long)sc->stripe[i].physical_start);
    398			DMEMIT(",stripe_%d_status=%c", i,
    399			       atomic_read(&(sc->stripe[i].error_count)) ? 'D' : 'A');
    400		}
    401		DMEMIT(";");
    402		break;
    403	}
    404}
    405
    406static int stripe_end_io(struct dm_target *ti, struct bio *bio,
    407		blk_status_t *error)
    408{
    409	unsigned i;
    410	char major_minor[16];
    411	struct stripe_c *sc = ti->private;
    412
    413	if (!*error)
    414		return DM_ENDIO_DONE; /* I/O complete */
    415
    416	if (bio->bi_opf & REQ_RAHEAD)
    417		return DM_ENDIO_DONE;
    418
    419	if (*error == BLK_STS_NOTSUPP)
    420		return DM_ENDIO_DONE;
    421
    422	memset(major_minor, 0, sizeof(major_minor));
    423	sprintf(major_minor, "%d:%d", MAJOR(bio_dev(bio)), MINOR(bio_dev(bio)));
    424
    425	/*
    426	 * Test to see which stripe drive triggered the event
    427	 * and increment error count for all stripes on that device.
    428	 * If the error count for a given device exceeds the threshold
    429	 * value we will no longer trigger any further events.
    430	 */
    431	for (i = 0; i < sc->stripes; i++)
    432		if (!strcmp(sc->stripe[i].dev->name, major_minor)) {
    433			atomic_inc(&(sc->stripe[i].error_count));
    434			if (atomic_read(&(sc->stripe[i].error_count)) <
    435			    DM_IO_ERROR_THRESHOLD)
    436				schedule_work(&sc->trigger_event);
    437		}
    438
    439	return DM_ENDIO_DONE;
    440}
    441
    442static int stripe_iterate_devices(struct dm_target *ti,
    443				  iterate_devices_callout_fn fn, void *data)
    444{
    445	struct stripe_c *sc = ti->private;
    446	int ret = 0;
    447	unsigned i = 0;
    448
    449	do {
    450		ret = fn(ti, sc->stripe[i].dev,
    451			 sc->stripe[i].physical_start,
    452			 sc->stripe_width, data);
    453	} while (!ret && ++i < sc->stripes);
    454
    455	return ret;
    456}
    457
    458static void stripe_io_hints(struct dm_target *ti,
    459			    struct queue_limits *limits)
    460{
    461	struct stripe_c *sc = ti->private;
    462	unsigned chunk_size = sc->chunk_size << SECTOR_SHIFT;
    463
    464	blk_limits_io_min(limits, chunk_size);
    465	blk_limits_io_opt(limits, chunk_size * sc->stripes);
    466}
    467
    468static struct target_type stripe_target = {
    469	.name   = "striped",
    470	.version = {1, 6, 0},
    471	.features = DM_TARGET_PASSES_INTEGRITY | DM_TARGET_NOWAIT,
    472	.module = THIS_MODULE,
    473	.ctr    = stripe_ctr,
    474	.dtr    = stripe_dtr,
    475	.map    = stripe_map,
    476	.end_io = stripe_end_io,
    477	.status = stripe_status,
    478	.iterate_devices = stripe_iterate_devices,
    479	.io_hints = stripe_io_hints,
    480	.direct_access = stripe_dax_direct_access,
    481	.dax_zero_page_range = stripe_dax_zero_page_range,
    482	.dax_recovery_write = stripe_dax_recovery_write,
    483};
    484
    485int __init dm_stripe_init(void)
    486{
    487	int r;
    488
    489	r = dm_register_target(&stripe_target);
    490	if (r < 0)
    491		DMWARN("target registration failed");
    492
    493	return r;
    494}
    495
    496void dm_stripe_exit(void)
    497{
    498	dm_unregister_target(&stripe_target);
    499}