mirror of
git://sourceware.org/git/lvm2.git
synced 2025-03-25 18:50:51 +03:00
Ok. this is the big one.... the change to the new fs interface.
Things to note: o Changes to the dm-*.c files have been kept as small as possible during the development of the new fs interface and there are a few places where the new code does odd things to give the original code what it wants. These places will gradually go away during the next few days once we are sure the new code is sound. o I've spent most of my testing time looking at the parser since thats where a lot of the changes are, I've not checked the actual I/O very much, but then that code hasn't changed at all. o The print operation in the target type operations is there to help in debugging and will go away eventually o There are some other printk's which will also go away once we are sure that things are working correctly. o I've tagged the old code with PRE_DMFS if you want to use that until this is stable. o There are no kernel patches for this yet (will fix after lunch... :-) o Makefile needs some changes o need to EXPORT_SYMBOL(deny_write_access); in ksyms.c How to use the new interface ? mount -t dmfs dmfs /mnt/dm cd /mnt/dm mkdir fish fish/tank cd fish/tank cat ~/my.table > table cd .. ln -s tank ACTIVE Creates a logical volume called fish and activates a table called tank, if there is a problem doing the link, look in /mnt/dm/fish/tank/errors to see what is wrong. If you see any odd things happening, let me know right away as I'm sure there'll be one or two things that slipped through my testing.
This commit is contained in:
parent
f8686d0e75
commit
38397f99aa
@ -22,7 +22,6 @@
|
||||
|
||||
struct dm_table;
|
||||
struct dm_dev;
|
||||
struct text_region;
|
||||
typedef unsigned int offset_t;
|
||||
|
||||
typedef void (*dm_error_fn)(const char *message, void *private);
|
||||
@ -31,13 +30,12 @@ typedef void (*dm_error_fn)(const char *message, void *private);
|
||||
* constructor, destructor and map fn types
|
||||
*/
|
||||
typedef int (*dm_ctr_fn)(struct dm_table *t, offset_t b, offset_t l,
|
||||
struct text_region *args, void **context,
|
||||
dm_error_fn err, void *e_private);
|
||||
char *args, void **context);
|
||||
|
||||
typedef void (*dm_dtr_fn)(struct dm_table *t, void *c);
|
||||
typedef int (*dm_map_fn)(struct buffer_head *bh, int rw, void *context);
|
||||
typedef int (*dm_err_fn)(struct buffer_head *bh, int rw, void *context);
|
||||
|
||||
typedef char *(*dm_print_fn)(void *context);
|
||||
|
||||
/*
|
||||
* Contructors should call this to make sure any
|
||||
@ -58,25 +56,23 @@ struct target_type {
|
||||
dm_dtr_fn dtr;
|
||||
dm_map_fn map;
|
||||
dm_err_fn err;
|
||||
dm_print_fn print;
|
||||
};
|
||||
|
||||
int dm_register_target(struct target_type *t);
|
||||
int dm_unregister_target(struct target_type *t);
|
||||
|
||||
/*
|
||||
* These may be useful for people writing target
|
||||
* types.
|
||||
*/
|
||||
struct text_region {
|
||||
const char *b;
|
||||
const char *e;
|
||||
};
|
||||
static inline char *next_token(char **p)
|
||||
{
|
||||
static const char *delim = " \t";
|
||||
char *r;
|
||||
|
||||
int dm_get_number(struct text_region *txt, unsigned int *n);
|
||||
int dm_get_line(struct text_region *txt, struct text_region *line);
|
||||
int dm_get_word(struct text_region *txt, struct text_region *word);
|
||||
void dm_txt_copy(char *dest, size_t max, struct text_region *txt);
|
||||
void dm_eat_space(struct text_region *txt);
|
||||
do {
|
||||
r = strsep(p, delim);
|
||||
} while(r && *r == 0);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
#endif /* DEVICE_MAPPER_H */
|
||||
|
@ -29,44 +29,43 @@ struct linear_c {
|
||||
* <dev_path> <offset>
|
||||
*/
|
||||
static int linear_ctr(struct dm_table *t, offset_t b, offset_t l,
|
||||
struct text_region *args, void **context,
|
||||
dm_error_fn err, void *e_private)
|
||||
char *args, void **context)
|
||||
{
|
||||
struct linear_c *lc;
|
||||
unsigned int start;
|
||||
struct text_region word;
|
||||
char path[256]; /* FIXME: magic */
|
||||
int r = -EINVAL;
|
||||
char *tok;
|
||||
char *path;
|
||||
char *p = args;
|
||||
|
||||
if (!(lc = kmalloc(sizeof(lc), GFP_KERNEL))) {
|
||||
err("couldn't allocate memory for linear context", e_private);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (!dm_get_word(args, &word)) {
|
||||
err("couldn't get device path", e_private);
|
||||
*context = "No device path given";
|
||||
path = next_token(&p);
|
||||
if (!path)
|
||||
goto bad;
|
||||
}
|
||||
|
||||
dm_txt_copy(path, sizeof(path) - 1, &word);
|
||||
|
||||
if (!dm_get_number(args, &start)) {
|
||||
err("destination start not given", e_private);
|
||||
*context = "No initial offset given";
|
||||
tok = next_token(&p);
|
||||
if (!tok)
|
||||
goto bad;
|
||||
}
|
||||
start = simple_strtoul(tok, NULL, 10);
|
||||
|
||||
if ((r = dm_table_get_device(t, path, &lc->dev))) {
|
||||
err("couldn't lookup device", e_private);
|
||||
r = -ENXIO;
|
||||
*context = "Cannot allocate linear context private structure";
|
||||
lc = kmalloc(sizeof(lc), GFP_KERNEL);
|
||||
if (lc == NULL)
|
||||
goto bad;
|
||||
}
|
||||
|
||||
*context = "Cannot get target device";
|
||||
r = dm_table_get_device(t, path, &lc->dev);
|
||||
if (r)
|
||||
goto bad_free;
|
||||
|
||||
lc->delta = (int) start - (int) b;
|
||||
*context = lc;
|
||||
return 0;
|
||||
|
||||
bad:
|
||||
bad_free:
|
||||
kfree(lc);
|
||||
bad:
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -86,12 +85,24 @@ static int linear_map(struct buffer_head *bh, int rw, void *context)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Debugging use only.
|
||||
*/
|
||||
static char *linear_print(void *context)
|
||||
{
|
||||
struct linear_c *lc = (struct linear_c *)context;
|
||||
static char buf[256];
|
||||
sprintf(buf, " %lu", lc->delta);
|
||||
return buf;
|
||||
}
|
||||
|
||||
static struct target_type linear_target = {
|
||||
name: "linear",
|
||||
module: THIS_MODULE,
|
||||
ctr: linear_ctr,
|
||||
dtr: linear_dtr,
|
||||
map: linear_map,
|
||||
print: linear_print,
|
||||
};
|
||||
|
||||
static int __init linear_init(void)
|
||||
@ -119,7 +130,5 @@ module_exit(linear_exit);
|
||||
|
||||
MODULE_AUTHOR("Joe Thornber <thornber@uk.sistina.com>");
|
||||
MODULE_DESCRIPTION("Device Mapper: Linear mapping");
|
||||
#ifdef MODULE_LICENSE
|
||||
MODULE_LICENSE("GPL");
|
||||
#endif
|
||||
|
||||
|
@ -114,6 +114,7 @@ struct dm_table *dm_table_create(void)
|
||||
|
||||
memset(t, 0, sizeof(*t));
|
||||
INIT_LIST_HEAD(&t->devices);
|
||||
INIT_LIST_HEAD(&t->errors);
|
||||
|
||||
/* allocate a single nodes worth of targets to
|
||||
begin with */
|
||||
@ -140,18 +141,22 @@ void dm_table_destroy(struct dm_table *t)
|
||||
{
|
||||
int i;
|
||||
|
||||
dmfs_zap_errors(t);
|
||||
|
||||
/* free the indexes (see dm_table_complete) */
|
||||
if (t->depth >= 2)
|
||||
vfree(t->index[t->depth - 2]);
|
||||
vfree(t->highs);
|
||||
|
||||
|
||||
/* free the targets */
|
||||
for (i = 0; i < t->num_targets; i++) {
|
||||
struct target *tgt = &t->targets[i];
|
||||
if (tgt->private)
|
||||
if (tgt->type->dtr)
|
||||
tgt->type->dtr(t, tgt->private);
|
||||
}
|
||||
|
||||
vfree(t->highs);
|
||||
|
||||
/* free the device list */
|
||||
if (t->devices.next != &t->devices) {
|
||||
WARN("there are still devices present, someone isn't "
|
||||
@ -202,7 +207,7 @@ int lookup_device(const char *path, kdev_t *dev)
|
||||
goto bad;
|
||||
}
|
||||
|
||||
*dev = inode->i_bdev->bd_dev;
|
||||
*dev = inode->i_rdev;
|
||||
|
||||
bad:
|
||||
path_release(&nd);
|
||||
|
@ -145,8 +145,7 @@ int dm_unregister_target(struct target_type *t)
|
||||
* up LV's that have holes in them.
|
||||
*/
|
||||
static int io_err_ctr(struct dm_table *t, offset_t b, offset_t l,
|
||||
struct text_region *args, void **context,
|
||||
dm_error_fn err, void *e_private)
|
||||
char *args, void **context)
|
||||
{
|
||||
*context = 0;
|
||||
return 0;
|
||||
|
@ -75,26 +75,38 @@ static devfs_handle_t _dev_dir;
|
||||
|
||||
static int request(request_queue_t *q, int rw, struct buffer_head *bh);
|
||||
static int dm_user_bmap(struct inode *inode, struct lv_bmap *lvb);
|
||||
static DECLARE_FSTYPE(dmfs_fstype, "dmfs", dmfs_read_super, FS_SINGLE);
|
||||
static struct vfsmount *dmfs_mnt;
|
||||
|
||||
/*
|
||||
* setup and teardown the driver
|
||||
*/
|
||||
static int dm_init(void)
|
||||
{
|
||||
int ret;
|
||||
int ret = -ENOMEM;
|
||||
|
||||
init_rwsem(&_dev_lock);
|
||||
|
||||
if (!_io_hook_cache)
|
||||
_io_hook_cache = kmem_cache_create("dm io hooks",
|
||||
sizeof(struct io_hook),
|
||||
0, 0, NULL, NULL);
|
||||
_io_hook_cache = kmem_cache_create("dm io hooks",
|
||||
sizeof(struct io_hook),
|
||||
0, 0, NULL, NULL);
|
||||
|
||||
if (!_io_hook_cache)
|
||||
return -ENOMEM;
|
||||
goto err;
|
||||
|
||||
if ((ret = dm_fs_init()) || (ret = dm_target_init()))
|
||||
return ret;
|
||||
ret = register_filesystem(&dmfs_fstype);
|
||||
if (ret < 0)
|
||||
goto err_kmem_cache_destroy;
|
||||
|
||||
dmfs_mnt = kern_mount(&dmfs_fstype);
|
||||
if (IS_ERR(dmfs_mnt)) {
|
||||
ret = PTR_ERR(dmfs_mnt);
|
||||
goto err_unregister;
|
||||
}
|
||||
|
||||
ret = dm_target_init();
|
||||
if (ret)
|
||||
goto err_umount;
|
||||
|
||||
/* set up the arrays */
|
||||
read_ahead[MAJOR_NR] = DEFAULT_READ_AHEAD;
|
||||
@ -102,10 +114,9 @@ static int dm_init(void)
|
||||
blksize_size[MAJOR_NR] = _blksize_size;
|
||||
hardsect_size[MAJOR_NR] = _hardsect_size;
|
||||
|
||||
if (devfs_register_blkdev(MAJOR_NR, _name, &dm_blk_dops) < 0) {
|
||||
printk(KERN_ERR "%s -- register_blkdev failed\n", _name);
|
||||
return -EIO;
|
||||
}
|
||||
ret = -EIO;
|
||||
if (devfs_register_blkdev(MAJOR_NR, _name, &dm_blk_dops) < 0)
|
||||
goto err_blkdev;
|
||||
|
||||
blk_queue_make_request(BLK_DEFAULT_QUEUE(MAJOR_NR), request);
|
||||
|
||||
@ -114,15 +125,28 @@ static int dm_init(void)
|
||||
printk(KERN_INFO "%s %d.%d.%d initialised\n", _name,
|
||||
_version[0], _version[1], _version[2]);
|
||||
return 0;
|
||||
|
||||
err_blkdev:
|
||||
printk(KERN_ERR "%s -- register_blkdev failed\n", _name);
|
||||
err_umount:
|
||||
/* kern_umount(&dmfs_mnt); */
|
||||
err_unregister:
|
||||
unregister_filesystem(&dmfs_fstype);
|
||||
err_kmem_cache_destroy:
|
||||
kmem_cache_destroy(_io_hook_cache);
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void dm_exit(void)
|
||||
{
|
||||
/* kern_umount(&dmfs_mnt); */
|
||||
|
||||
unregister_filesystem(&dmfs_fstype);
|
||||
|
||||
if (kmem_cache_destroy(_io_hook_cache))
|
||||
WARN("it looks like there are still some io_hooks allocated");
|
||||
_io_hook_cache = 0;
|
||||
|
||||
dm_fs_exit();
|
||||
|
||||
if (devfs_unregister_blkdev(MAJOR_NR, _name) < 0)
|
||||
printk(KERN_ERR "%s -- unregister_blkdev failed\n", _name);
|
||||
@ -663,6 +687,7 @@ struct mapped_device *dm_find_by_minor(int minor)
|
||||
return md;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DEVFS
|
||||
static int register_device(struct mapped_device *md)
|
||||
{
|
||||
md->devfs_entry =
|
||||
@ -676,6 +701,12 @@ static int register_device(struct mapped_device *md)
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static int register_device(struct mapped_device *md)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int unregister_device(struct mapped_device *md)
|
||||
{
|
||||
|
@ -178,6 +178,8 @@ struct dm_table {
|
||||
|
||||
/* a list of devices used by this table */
|
||||
struct list_head devices;
|
||||
|
||||
struct list_head errors;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -202,6 +204,15 @@ struct mapped_device {
|
||||
devfs_handle_t devfs_entry;
|
||||
};
|
||||
|
||||
struct dmfs_i {
|
||||
struct semaphore sem;
|
||||
struct dm_table *table;
|
||||
struct mapped_device *md;
|
||||
struct dentry *dentry;
|
||||
};
|
||||
|
||||
#define DMFS_I(inode) ((struct dmfs_i *)(inode)->u.generic_ip)
|
||||
|
||||
extern struct block_device_operations dm_blk_dops;
|
||||
|
||||
|
||||
@ -230,24 +241,13 @@ int dm_table_add_target(struct dm_table *t, offset_t high,
|
||||
struct target_type *type, void *private);
|
||||
int dm_table_complete(struct dm_table *t);
|
||||
|
||||
/* dm-parse.c */
|
||||
typedef int (*extract_line_fn)(struct text_region *line,
|
||||
void *private);
|
||||
|
||||
struct dm_table *dm_parse(extract_line_fn line_fn, void *line_private,
|
||||
dm_error_fn err_fn, void *err_private);
|
||||
|
||||
|
||||
static inline int dm_empty_tok(struct text_region *txt)
|
||||
{
|
||||
return txt->b >= txt->e;
|
||||
}
|
||||
|
||||
/* dm-fs.c */
|
||||
int dm_fs_init(void);
|
||||
void dm_fs_exit(void);
|
||||
|
||||
/* dmfs-error.c */
|
||||
void dmfs_add_error(struct dm_table *t, unsigned num, char *str);
|
||||
void dmfs_zap_errors(struct dm_table *t);
|
||||
|
||||
/* dmfs-super.c */
|
||||
struct super_block *dmfs_read_super(struct super_block *, void *, int);
|
||||
struct inode *dmfs_new_inode(struct super_block *sb, int mode);
|
||||
|
||||
#define WARN(f, x...) printk(KERN_WARNING "device-mapper: " f "\n" , ## x)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user