[Date Prev][Date Next] [Thread Prev][Thread Next]
[Thread Index]
[Date Index]
[Author Index]
Re: [dm-devel] Re: [lvm-devel] dm-crypt - some info, and a fewdevelopment questions
- From: Christophe Saout <christophe saout de>
- To: dm-devel sistina com
- Subject: Re: [dm-devel] Re: [lvm-devel] dm-crypt - some info, and a fewdevelopment questions
- Date: Thu Jul 17 17:32:01 2003
Am Fr, 2003-07-18 um 00.13 schrieb Joe Thornber:
> > Yes, that was really easy. Especially because alle the bio handling and
> > even splitting is already done outside the target file, you just have to
> > specify the mapping. Hey, it's even working. If anyone wants to see it,
> > tell me. ;)
>
> Excellent :) Why not post the code here, I'm sure people would be be
> interested.
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 "<chunk size>
<device> <first sector>".
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 <christophe saout de>
Please avoid sending me Word or PowerPoint attachments.
See http://www.fsf.org/philosophy/no-word-attachments.html
/*
* Copyright (C) 2001 Sistina Software (UK) Limited.
*
* This file is released under the GPL.
*/
#include "dm.h"
#include <linux/module.h>
#include <linux/init.h>
#include <linux/blkdev.h>
#include <linux/bio.h>
#include <linux/slab.h>
MODULE_AUTHOR("Christophe Saout <christophe saout de>");
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.
* <chunk size (2^^n)> <dev_path> <offset>
*/
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)
[Date Prev][Date Next] [Thread Prev][Thread Next]
[Thread Index]
[Date Index]
[Author Index]