mirror of
git://sourceware.org/git/lvm2.git
synced 2025-01-03 05:18:29 +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;
|
||||
|
||||
/* 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);
|
||||
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);
|
||||
|
||||
int register_map_target(const char *name, dm_ctr_fn ctr, dm_dtr_fn dtr,
|
||||
dm_map_fn map);
|
||||
int dm_register_target(const char *name, dm_ctr_fn ctr, dm_dtr_fn dtr,
|
||||
dm_map_fn map);
|
||||
|
||||
|
||||
/* 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).
|
||||
*/
|
||||
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
|
||||
|
@ -277,11 +277,13 @@ static int process_table(const char *b, const char *e, int minor,
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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 0;
|
||||
|
@ -147,7 +147,6 @@ struct dm_table *dm_table_create(void)
|
||||
|
||||
void dm_table_destroy(struct dm_table *t)
|
||||
{
|
||||
struct dev_list *d, *n;
|
||||
int i;
|
||||
|
||||
if (!t)
|
||||
@ -164,9 +163,16 @@ void dm_table_destroy(struct dm_table *t)
|
||||
kfree(t);
|
||||
|
||||
/* free the device list */
|
||||
for (d = t->devices; d; d = n) {
|
||||
n = d->next;
|
||||
kfree(d);
|
||||
if (t->devices) {
|
||||
struct dev_list *d, *n;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
struct dev_list *d = kmalloc(sizeof(*d), GFP_KERNEL);
|
||||
struct dev_list *d;
|
||||
|
||||
if (!d)
|
||||
return -ENOMEM;
|
||||
d = find_device(t->devices, dev);
|
||||
if (!d) {
|
||||
d = kmalloc(sizeof(*d), GFP_KERNEL);
|
||||
if (!d)
|
||||
return -ENOMEM;
|
||||
|
||||
d->dev = dev;
|
||||
d->next = t->devices;
|
||||
t->devices = d;
|
||||
d->dev = dev;
|
||||
atomic_set(&d->count, 0);
|
||||
d->next = t->devices;
|
||||
t->devices = d;
|
||||
}
|
||||
atomic_inc(&d->count);
|
||||
|
||||
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
|
||||
*/
|
||||
|
@ -50,8 +50,8 @@ struct target_type *dm_get_target(const char *name)
|
||||
/*
|
||||
* register a new target_type.
|
||||
*/
|
||||
int register_map_target(const char *name, dm_ctr_fn ctr,
|
||||
dm_dtr_fn dtr, dm_map_fn map)
|
||||
int dm_register_target(const char *name, dm_ctr_fn ctr,
|
||||
dm_dtr_fn dtr, dm_map_fn map)
|
||||
{
|
||||
struct target_type *t =
|
||||
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
|
||||
* 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)
|
||||
{
|
||||
/* 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;
|
||||
}
|
||||
|
||||
static void io_err_dtr(void *c)
|
||||
static void io_err_dtr(struct dm_table *t, void *c)
|
||||
{
|
||||
/* empty */
|
||||
}
|
||||
@ -116,7 +117,8 @@ struct linear_c {
|
||||
* construct a linear mapping.
|
||||
* <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)
|
||||
{
|
||||
struct linear_c *lc;
|
||||
@ -149,8 +151,10 @@ static int linear_ctr(offset_t low, offset_t high, struct dm_table *t,
|
||||
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);
|
||||
}
|
||||
|
||||
@ -171,7 +175,7 @@ int dm_target_init(void)
|
||||
int ret;
|
||||
|
||||
#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
|
||||
|
||||
xx("io-err", io_err);
|
||||
@ -180,3 +184,5 @@ int dm_target_init(void)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(dm_register_target);
|
||||
|
@ -216,12 +216,12 @@ static int blk_ioctl(struct inode *inode, struct file *file,
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
@ -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
|
||||
* 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);
|
||||
}
|
||||
|
||||
inline static void free_deferred(struct deferred_io *di)
|
||||
static inline void free_deferred(struct deferred_io *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
|
||||
*/
|
||||
inline static int __map_buffer(struct mapped_device *md,
|
||||
static inline int __map_buffer(struct mapped_device *md,
|
||||
struct buffer_head *bh, int leaf)
|
||||
{
|
||||
dm_map_fn fn;
|
||||
@ -336,7 +336,7 @@ inline static int __map_buffer(struct mapped_device *md,
|
||||
/*
|
||||
* 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;
|
||||
offset_t *node;
|
||||
|
@ -147,6 +147,8 @@ enum {
|
||||
*/
|
||||
struct dev_list {
|
||||
kdev_t dev;
|
||||
atomic_t count;
|
||||
|
||||
struct block_device *bd;
|
||||
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)
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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))
|
||||
b++;
|
||||
@ -273,7 +275,7 @@ inline static const char *eat_space(const char *b, const char *e)
|
||||
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;
|
||||
*b = eat_space(*b, e);
|
||||
|
Loading…
Reference in New Issue
Block a user