1
0
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:
Joe Thornber 2001-08-31 16:36:56 +00:00
parent 0f29dc2f2d
commit a46d94071b
6 changed files with 92 additions and 32 deletions

View File

@ -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

View File

@ -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;

View File

@ -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
*/ */

View File

@ -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);

View File

@ -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;

View File

@ -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);