mirror of
git://sourceware.org/git/lvm2.git
synced 2025-01-04 09:18:36 +03:00
o added reference counting to the destination devices, make sure that the
destructor for any targets you write call dm_table_remove_device.
This commit is contained in:
parent
0f29dc2f2d
commit
a46d94071b
@ -39,13 +39,14 @@ struct dm_table;
|
|||||||
typedef unsigned int offset_t;
|
typedef unsigned int offset_t;
|
||||||
|
|
||||||
/* constructor, destructor and map fn types */
|
/* constructor, destructor and map fn types */
|
||||||
typedef int (*dm_ctr_fn)(offset_t b, offset_t e, struct dm_table *t,
|
typedef int (*dm_ctr_fn)(struct dm_table *t,
|
||||||
|
offset_t b, offset_t e,
|
||||||
const char *cb, const char *ce, void **result);
|
const char *cb, const char *ce, void **result);
|
||||||
typedef void (*dm_dtr_fn)(void *c);
|
typedef void (*dm_dtr_fn)(struct dm_table *t, void *c);
|
||||||
typedef int (*dm_map_fn)(struct buffer_head *bh, void *context);
|
typedef int (*dm_map_fn)(struct buffer_head *bh, void *context);
|
||||||
|
|
||||||
int register_map_target(const char *name, dm_ctr_fn ctr, dm_dtr_fn dtr,
|
int dm_register_target(const char *name, dm_ctr_fn ctr, dm_dtr_fn dtr,
|
||||||
dm_map_fn map);
|
dm_map_fn map);
|
||||||
|
|
||||||
|
|
||||||
/* contructors should call this to make sure any
|
/* contructors should call this to make sure any
|
||||||
@ -53,6 +54,7 @@ int register_map_target(const char *name, dm_ctr_fn ctr, dm_dtr_fn dtr,
|
|||||||
* (ie. opened/closed).
|
* (ie. opened/closed).
|
||||||
*/
|
*/
|
||||||
int dm_table_add_device(struct dm_table *t, kdev_t dev);
|
int dm_table_add_device(struct dm_table *t, kdev_t dev);
|
||||||
|
void dm_table_remove_device(struct dm_table *t, kdev_t dev);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
@ -277,11 +277,13 @@ static int process_table(const char *b, const char *e, int minor,
|
|||||||
}
|
}
|
||||||
|
|
||||||
high = start + (size - 1);
|
high = start + (size - 1);
|
||||||
if ((r = t->ctr(start, high, table, we, e, &context)))
|
if ((r = t->ctr(table, start, high, we, e, &context)))
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
if ((r = dm_table_add_entry(table, high, t->map, context)))
|
if ((r = dm_table_add_entry(table, high, t->map, context))) {
|
||||||
|
t->dtr(table, context);
|
||||||
return r;
|
return r;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -147,7 +147,6 @@ struct dm_table *dm_table_create(void)
|
|||||||
|
|
||||||
void dm_table_destroy(struct dm_table *t)
|
void dm_table_destroy(struct dm_table *t)
|
||||||
{
|
{
|
||||||
struct dev_list *d, *n;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (!t)
|
if (!t)
|
||||||
@ -164,9 +163,16 @@ void dm_table_destroy(struct dm_table *t)
|
|||||||
kfree(t);
|
kfree(t);
|
||||||
|
|
||||||
/* free the device list */
|
/* free the device list */
|
||||||
for (d = t->devices; d; d = n) {
|
if (t->devices) {
|
||||||
n = d->next;
|
struct dev_list *d, *n;
|
||||||
kfree(d);
|
|
||||||
|
WARN("there are still devices present, someone isn't "
|
||||||
|
"calling dm_table_remove_device");
|
||||||
|
|
||||||
|
for (d = t->devices; d; d = n) {
|
||||||
|
n = d->next;
|
||||||
|
kfree(d);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,20 +206,62 @@ int dm_table_add_entry(struct dm_table *t, offset_t high,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* see if we've already got a device in the list.
|
||||||
|
*/
|
||||||
|
static struct dev_list *find_device(struct dev_list *d, kdev_t dev)
|
||||||
|
{
|
||||||
|
while(d) {
|
||||||
|
if (d->dev == dev)
|
||||||
|
break;
|
||||||
|
|
||||||
|
d = d->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* add a device to the list, or just increment the
|
||||||
|
* usage count if it's already present.
|
||||||
|
*/
|
||||||
int dm_table_add_device(struct dm_table *t, kdev_t dev)
|
int dm_table_add_device(struct dm_table *t, kdev_t dev)
|
||||||
{
|
{
|
||||||
struct dev_list *d = kmalloc(sizeof(*d), GFP_KERNEL);
|
struct dev_list *d;
|
||||||
|
|
||||||
if (!d)
|
d = find_device(t->devices, dev);
|
||||||
return -ENOMEM;
|
if (!d) {
|
||||||
|
d = kmalloc(sizeof(*d), GFP_KERNEL);
|
||||||
|
if (!d)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
d->dev = dev;
|
d->dev = dev;
|
||||||
d->next = t->devices;
|
atomic_set(&d->count, 0);
|
||||||
t->devices = d;
|
d->next = t->devices;
|
||||||
|
t->devices = d;
|
||||||
|
}
|
||||||
|
atomic_inc(&d->count);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* decrement a devices use count and remove it if
|
||||||
|
* neccessary.
|
||||||
|
*/
|
||||||
|
void dm_table_remove_device(struct dm_table *t, kdev_t dev)
|
||||||
|
{
|
||||||
|
struct dev_list *d = find_device(t->devices, dev);
|
||||||
|
|
||||||
|
if (!d) {
|
||||||
|
WARN("asked to remove a device that isn't present");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (atomic_dec_and_test(&d->count))
|
||||||
|
kfree(d);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* builds the btree to index the map
|
* builds the btree to index the map
|
||||||
*/
|
*/
|
||||||
|
@ -50,8 +50,8 @@ struct target_type *dm_get_target(const char *name)
|
|||||||
/*
|
/*
|
||||||
* register a new target_type.
|
* register a new target_type.
|
||||||
*/
|
*/
|
||||||
int register_map_target(const char *name, dm_ctr_fn ctr,
|
int dm_register_target(const char *name, dm_ctr_fn ctr,
|
||||||
dm_dtr_fn dtr, dm_map_fn map)
|
dm_dtr_fn dtr, dm_map_fn map)
|
||||||
{
|
{
|
||||||
struct target_type *t =
|
struct target_type *t =
|
||||||
kmalloc(sizeof(*t) + strlen(name) + 1, GFP_KERNEL);
|
kmalloc(sizeof(*t) + strlen(name) + 1, GFP_KERNEL);
|
||||||
@ -85,7 +85,8 @@ int register_map_target(const char *name, dm_ctr_fn ctr,
|
|||||||
* io-err: always fails an io, useful for bringing
|
* io-err: always fails an io, useful for bringing
|
||||||
* up LV's that have holes in them.
|
* up LV's that have holes in them.
|
||||||
*/
|
*/
|
||||||
static int io_err_ctr(offset_t b, offset_t e, struct dm_table *t,
|
static int io_err_ctr(struct dm_table *t,
|
||||||
|
offset_t b, offset_t e,
|
||||||
const char *cb, const char *ce, void **result)
|
const char *cb, const char *ce, void **result)
|
||||||
{
|
{
|
||||||
/* this takes no arguments */
|
/* this takes no arguments */
|
||||||
@ -93,7 +94,7 @@ static int io_err_ctr(offset_t b, offset_t e, struct dm_table *t,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void io_err_dtr(void *c)
|
static void io_err_dtr(struct dm_table *t, void *c)
|
||||||
{
|
{
|
||||||
/* empty */
|
/* empty */
|
||||||
}
|
}
|
||||||
@ -116,7 +117,8 @@ struct linear_c {
|
|||||||
* construct a linear mapping.
|
* construct a linear mapping.
|
||||||
* <major> <minor> <offset>
|
* <major> <minor> <offset>
|
||||||
*/
|
*/
|
||||||
static int linear_ctr(offset_t low, offset_t high, struct dm_table *t,
|
static int linear_ctr(struct dm_table *t,
|
||||||
|
offset_t low, offset_t high,
|
||||||
const char *cb, const char *ce, void **result)
|
const char *cb, const char *ce, void **result)
|
||||||
{
|
{
|
||||||
struct linear_c *lc;
|
struct linear_c *lc;
|
||||||
@ -149,8 +151,10 @@ static int linear_ctr(offset_t low, offset_t high, struct dm_table *t,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void linear_dtr(void *c)
|
static void linear_dtr(struct dm_table *t, void *c)
|
||||||
{
|
{
|
||||||
|
struct linear_c *lc = (struct linear_c *) c;
|
||||||
|
dm_table_remove_device(t, lc->dev);
|
||||||
kfree(c);
|
kfree(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -171,7 +175,7 @@ int dm_target_init(void)
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
#define xx(n, fn) \
|
#define xx(n, fn) \
|
||||||
if ((ret = register_map_target(n, \
|
if ((ret = dm_register_target(n, \
|
||||||
fn ## _ctr, fn ## _dtr, fn ## _map) < 0)) return ret
|
fn ## _ctr, fn ## _dtr, fn ## _map) < 0)) return ret
|
||||||
|
|
||||||
xx("io-err", io_err);
|
xx("io-err", io_err);
|
||||||
@ -180,3 +184,5 @@ int dm_target_init(void)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EXPORT_SYMBOL(dm_register_target);
|
||||||
|
@ -216,12 +216,12 @@ static int blk_ioctl(struct inode *inode, struct file *file,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static struct io_hook *alloc_io_hook(void)
|
static inline struct io_hook *alloc_io_hook(void)
|
||||||
{
|
{
|
||||||
return kmem_cache_alloc(_io_hook_cache, GFP_NOIO);
|
return kmem_cache_alloc(_io_hook_cache, GFP_NOIO);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static void free_io_hook(struct io_hook *ih)
|
static inline void free_io_hook(struct io_hook *ih)
|
||||||
{
|
{
|
||||||
kmem_cache_free(_io_hook_cache, ih);
|
kmem_cache_free(_io_hook_cache, ih);
|
||||||
}
|
}
|
||||||
@ -231,12 +231,12 @@ inline static void free_io_hook(struct io_hook *ih)
|
|||||||
* their own slab, I say no for now since they are
|
* their own slab, I say no for now since they are
|
||||||
* only used when the device is suspended.
|
* only used when the device is suspended.
|
||||||
*/
|
*/
|
||||||
inline static struct deferred_io *alloc_deferred(void)
|
static inline struct deferred_io *alloc_deferred(void)
|
||||||
{
|
{
|
||||||
return kmalloc(sizeof(struct deferred_io), GFP_NOIO);
|
return kmalloc(sizeof(struct deferred_io), GFP_NOIO);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static void free_deferred(struct deferred_io *di)
|
static inline void free_deferred(struct deferred_io *di)
|
||||||
{
|
{
|
||||||
kfree(di);
|
kfree(di);
|
||||||
}
|
}
|
||||||
@ -289,7 +289,7 @@ static int queue_io(struct mapped_device *md, struct buffer_head *bh, int rw)
|
|||||||
/*
|
/*
|
||||||
* do the bh mapping for a given leaf
|
* do the bh mapping for a given leaf
|
||||||
*/
|
*/
|
||||||
inline static int __map_buffer(struct mapped_device *md,
|
static inline int __map_buffer(struct mapped_device *md,
|
||||||
struct buffer_head *bh, int leaf)
|
struct buffer_head *bh, int leaf)
|
||||||
{
|
{
|
||||||
dm_map_fn fn;
|
dm_map_fn fn;
|
||||||
@ -336,7 +336,7 @@ inline static int __map_buffer(struct mapped_device *md,
|
|||||||
/*
|
/*
|
||||||
* search the btree for the correct target.
|
* search the btree for the correct target.
|
||||||
*/
|
*/
|
||||||
inline static int __find_node(struct dm_table *t, struct buffer_head *bh)
|
static inline int __find_node(struct dm_table *t, struct buffer_head *bh)
|
||||||
{
|
{
|
||||||
int i = 0, l, r = 0;
|
int i = 0, l, r = 0;
|
||||||
offset_t *node;
|
offset_t *node;
|
||||||
|
@ -147,6 +147,8 @@ enum {
|
|||||||
*/
|
*/
|
||||||
struct dev_list {
|
struct dev_list {
|
||||||
kdev_t dev;
|
kdev_t dev;
|
||||||
|
atomic_t count;
|
||||||
|
|
||||||
struct block_device *bd;
|
struct block_device *bd;
|
||||||
struct dev_list *next;
|
struct dev_list *next;
|
||||||
};
|
};
|
||||||
@ -260,12 +262,12 @@ int dm_fs_remove(struct mapped_device *md);
|
|||||||
|
|
||||||
#define WARN(f, x...) printk(KERN_WARNING "device-mapper: " f "\n" , ## x)
|
#define WARN(f, x...) printk(KERN_WARNING "device-mapper: " f "\n" , ## x)
|
||||||
|
|
||||||
inline static int is_active(struct mapped_device *md)
|
static inline int is_active(struct mapped_device *md)
|
||||||
{
|
{
|
||||||
return test_bit(DM_ACTIVE, &md->state);
|
return test_bit(DM_ACTIVE, &md->state);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static const char *eat_space(const char *b, const char *e)
|
static inline const char *eat_space(const char *b, const char *e)
|
||||||
{
|
{
|
||||||
while(b != e && isspace((int) *b))
|
while(b != e && isspace((int) *b))
|
||||||
b++;
|
b++;
|
||||||
@ -273,7 +275,7 @@ inline static const char *eat_space(const char *b, const char *e)
|
|||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static int get_number(const char **b, const char *e, unsigned int *n)
|
static inline int get_number(const char **b, const char *e, unsigned int *n)
|
||||||
{
|
{
|
||||||
char *ptr;
|
char *ptr;
|
||||||
*b = eat_space(*b, e);
|
*b = eat_space(*b, e);
|
||||||
|
Loading…
Reference in New Issue
Block a user