From cdb5bbbc48f8b95caf810ddabca084ff938c512d Mon Sep 17 00:00:00 2001 From: Joe Thornber Date: Thu, 17 Jul 2003 23:15:56 +0000 Subject: [PATCH] Add another little example target. --- contrib/dm-reverse.README | 13 +++ contrib/dm-reverse.c | 173 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 186 insertions(+) create mode 100644 contrib/dm-reverse.README create mode 100644 contrib/dm-reverse.c diff --git a/contrib/dm-reverse.README b/contrib/dm-reverse.README new file mode 100644 index 0000000..fd10e4a --- /dev/null +++ b/contrib/dm-reverse.README @@ -0,0 +1,13 @@ +Sure. It's basically code from dm-linear.c and dm-stripe.c (you can +reverse chunks of a given size). The target syntax is " + ". + +I added some lines so that it can be compiled as module outside of the +kernel (the reference counting is working fine). + +dm-reverse.c is attached. + +-- +Christophe Saout +Please avoid sending me Word or PowerPoint attachments. +See http://www.fsf.org/philosophy/no-word-attachments.html diff --git a/contrib/dm-reverse.c b/contrib/dm-reverse.c new file mode 100644 index 0000000..669d485 --- /dev/null +++ b/contrib/dm-reverse.c @@ -0,0 +1,173 @@ +/* + * Copyright (C) 2001 Sistina Software (UK) Limited. + * + * This file is released under the GPL. + */ + +#include "dm.h" + +#include +#include +#include +#include +#include + +MODULE_AUTHOR("Christophe Saout "); +MODULE_DESCRIPTION(DM_NAME " target for reverse block mapping"); +MODULE_LICENSE("GPL"); + +struct reverse_c { + uint32_t chunk_shift; + sector_t chunk_mask; + sector_t chunk_last; + + struct dm_dev *dev; + sector_t start; +}; + +/* + * Construct a reverse mapping. + * + */ +static int reverse_ctr(struct dm_target *ti, unsigned int argc, char **argv) +{ + struct reverse_c *rc; + uint32_t chunk_size; + sector_t chunk_count; + char *end; + + if (argc != 3) { + ti->error = "dm-reverse: Not enough arguments"; + return -EINVAL; + } + + chunk_size = simple_strtoul(argv[0], &end, 10); + if (*end) { + ti->error = "dm-reverse: Invalid chunk_size"; + return -EINVAL; + } + + /* + * chunk_size is a power of two + */ + if (!chunk_size || (chunk_size & (chunk_size - 1))) { + ti->error = "dm-reverse: Invalid chunk size"; + return -EINVAL; + } + + /* + * How do we handle a small last <-> first chunk? + * We simply don't... so + * length has to be a multiple of the chunk size + */ + chunk_count = ti->len; + if (sector_div(chunk_count, chunk_size) > 0) { + ti->error = "dm-reverse: Size must be a multiple of the chunk size"; + return -EINVAL; + } + + rc = kmalloc(sizeof(*rc), GFP_KERNEL); + if (rc == NULL) { + ti->error = "dm-reverse: Cannot allocate reverse context "; + return -ENOMEM; + } + + if (sscanf(argv[2], SECTOR_FORMAT, &rc->start) != 1) { + ti->error = "dm-reverse: Invalid device sector"; + goto bad; + } + + if (dm_get_device(ti, argv[1], rc->start, ti->len, + dm_table_get_mode(ti->table), &rc->dev)) { + ti->error = "dm-reverse: Device lookup failed"; + goto bad; + } + + ti->split_io = chunk_size; + + rc->chunk_last = chunk_count - 1; + rc->chunk_mask = ((sector_t) chunk_size) - 1; + for (rc->chunk_shift = 0; chunk_size; rc->chunk_shift++) + chunk_size >>= 1; + rc->chunk_shift--; + + ti->private = rc; + return 0; + +bad: + kfree(rc); + return -EINVAL; +} + +static void reverse_dtr(struct dm_target *ti) +{ + struct reverse_c *rc = (struct reverse_c *) ti->private; + + dm_put_device(ti, rc->dev); + kfree(rc); +} + +static int reverse_map(struct dm_target *ti, struct bio *bio) +{ + struct reverse_c *rc = (struct reverse_c *) ti->private; + + sector_t offset = bio->bi_sector - ti->begin; + uint32_t chunk = (uint32_t) (offset >> rc->chunk_shift); + + chunk = rc->chunk_last - chunk; + + bio->bi_bdev = rc->dev->bdev; + bio->bi_sector = rc->start + (chunk << rc->chunk_shift) + + (offset & rc->chunk_mask); + return 1; +} + +static int reverse_status(struct dm_target *ti, + status_type_t type, char *result, unsigned int maxlen) +{ + struct reverse_c *rc = (struct reverse_c *) ti->private; + char b[BDEVNAME_SIZE]; + + switch (type) { + case STATUSTYPE_INFO: + result[0] = '\0'; + break; + + case STATUSTYPE_TABLE: + snprintf(result, maxlen, SECTOR_FORMAT " %s " SECTOR_FORMAT, + rc->chunk_mask + 1, bdevname(rc->dev->bdev, b), rc->start); + break; + } + return 0; +} + +static struct target_type reverse_target = { + .name = "reverse", + .module = THIS_MODULE, + .ctr = reverse_ctr, + .dtr = reverse_dtr, + .map = reverse_map, + .status = reverse_status, +}; + +int __init dm_reverse_init(void) +{ + int r; + + r = dm_register_target(&reverse_target); + if (r < 0) + DMWARN("reverse target registration failed"); + + return r; +} + +void dm_reverse_exit(void) +{ + if (dm_unregister_target(&reverse_target)) + DMWARN("reverse target unregistration failed"); + + return; +} + +module_init(dm_reverse_init) +module_exit(dm_reverse_exit) -- 2.43.5