Commit 1134e5ae authored by Mike Anderson's avatar Mike Anderson Committed by Linus Torvalds

[PATCH] dm table: store md

Store an up-pointer to the owning struct mapped_device in every table when it
is created.

Access it with:
  struct mapped_device *dm_table_get_md(struct dm_table *t)

Tables linked to md must be destroyed before the md itself.
Signed-off-by: default avatarMike Anderson <andmike@us.ibm.com>
Signed-off-by: default avatarAlasdair G Kergon <agk@redhat.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 9ade92a9
...@@ -244,9 +244,9 @@ static void __hash_remove(struct hash_cell *hc) ...@@ -244,9 +244,9 @@ static void __hash_remove(struct hash_cell *hc)
dm_table_put(table); dm_table_put(table);
} }
dm_put(hc->md);
if (hc->new_map) if (hc->new_map)
dm_table_put(hc->new_map); dm_table_put(hc->new_map);
dm_put(hc->md);
free_cell(hc); free_cell(hc);
} }
...@@ -985,33 +985,43 @@ static int table_load(struct dm_ioctl *param, size_t param_size) ...@@ -985,33 +985,43 @@ static int table_load(struct dm_ioctl *param, size_t param_size)
int r; int r;
struct hash_cell *hc; struct hash_cell *hc;
struct dm_table *t; struct dm_table *t;
struct mapped_device *md;
md = find_device(param);
if (!md)
return -ENXIO;
r = dm_table_create(&t, get_mode(param), param->target_count); r = dm_table_create(&t, get_mode(param), param->target_count, md);
if (r) if (r)
return r; goto out;
r = populate_table(t, param, param_size); r = populate_table(t, param, param_size);
if (r) { if (r) {
dm_table_put(t); dm_table_put(t);
return r; goto out;
} }
down_write(&_hash_lock); down_write(&_hash_lock);
hc = __find_device_hash_cell(param); hc = dm_get_mdptr(md);
if (!hc) { if (!hc || hc->md != md) {
DMWARN("device doesn't appear to be in the dev hash table."); DMWARN("device has been removed from the dev hash table.");
up_write(&_hash_lock);
dm_table_put(t); dm_table_put(t);
return -ENXIO; up_write(&_hash_lock);
r = -ENXIO;
goto out;
} }
if (hc->new_map) if (hc->new_map)
dm_table_put(hc->new_map); dm_table_put(hc->new_map);
hc->new_map = t; hc->new_map = t;
up_write(&_hash_lock);
param->flags |= DM_INACTIVE_PRESENT_FLAG; param->flags |= DM_INACTIVE_PRESENT_FLAG;
r = __dev_status(md, param);
out:
dm_put(md);
r = __dev_status(hc->md, param);
up_write(&_hash_lock);
return r; return r;
} }
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#define CHILDREN_PER_NODE (KEYS_PER_NODE + 1) #define CHILDREN_PER_NODE (KEYS_PER_NODE + 1)
struct dm_table { struct dm_table {
struct mapped_device *md;
atomic_t holders; atomic_t holders;
/* btree table */ /* btree table */
...@@ -206,7 +207,8 @@ static int alloc_targets(struct dm_table *t, unsigned int num) ...@@ -206,7 +207,8 @@ static int alloc_targets(struct dm_table *t, unsigned int num)
return 0; return 0;
} }
int dm_table_create(struct dm_table **result, int mode, unsigned num_targets) int dm_table_create(struct dm_table **result, int mode,
unsigned num_targets, struct mapped_device *md)
{ {
struct dm_table *t = kmalloc(sizeof(*t), GFP_KERNEL); struct dm_table *t = kmalloc(sizeof(*t), GFP_KERNEL);
...@@ -229,6 +231,7 @@ int dm_table_create(struct dm_table **result, int mode, unsigned num_targets) ...@@ -229,6 +231,7 @@ int dm_table_create(struct dm_table **result, int mode, unsigned num_targets)
} }
t->mode = mode; t->mode = mode;
t->md = md;
*result = t; *result = t;
return 0; return 0;
} }
...@@ -952,12 +955,20 @@ int dm_table_flush_all(struct dm_table *t) ...@@ -952,12 +955,20 @@ int dm_table_flush_all(struct dm_table *t)
return ret; return ret;
} }
struct mapped_device *dm_table_get_md(struct dm_table *t)
{
dm_get(t->md);
return t->md;
}
EXPORT_SYMBOL(dm_vcalloc); EXPORT_SYMBOL(dm_vcalloc);
EXPORT_SYMBOL(dm_get_device); EXPORT_SYMBOL(dm_get_device);
EXPORT_SYMBOL(dm_put_device); EXPORT_SYMBOL(dm_put_device);
EXPORT_SYMBOL(dm_table_event); EXPORT_SYMBOL(dm_table_event);
EXPORT_SYMBOL(dm_table_get_size); EXPORT_SYMBOL(dm_table_get_size);
EXPORT_SYMBOL(dm_table_get_mode); EXPORT_SYMBOL(dm_table_get_mode);
EXPORT_SYMBOL(dm_table_get_md);
EXPORT_SYMBOL(dm_table_put); EXPORT_SYMBOL(dm_table_put);
EXPORT_SYMBOL(dm_table_get); EXPORT_SYMBOL(dm_table_get);
EXPORT_SYMBOL(dm_table_unplug_all); EXPORT_SYMBOL(dm_table_unplug_all);
......
...@@ -1007,18 +1007,18 @@ void dm_get(struct mapped_device *md) ...@@ -1007,18 +1007,18 @@ void dm_get(struct mapped_device *md)
void dm_put(struct mapped_device *md) void dm_put(struct mapped_device *md)
{ {
struct dm_table *map = dm_get_table(md); struct dm_table *map;
if (atomic_dec_and_test(&md->holders)) { if (atomic_dec_and_test(&md->holders)) {
map = dm_get_table(md);
if (!dm_suspended(md)) { if (!dm_suspended(md)) {
dm_table_presuspend_targets(map); dm_table_presuspend_targets(map);
dm_table_postsuspend_targets(map); dm_table_postsuspend_targets(map);
} }
__unbind(md); __unbind(md);
dm_table_put(map);
free_dev(md); free_dev(md);
} }
dm_table_put(map);
} }
/* /*
......
...@@ -89,7 +89,8 @@ int dm_suspended(struct mapped_device *md); ...@@ -89,7 +89,8 @@ int dm_suspended(struct mapped_device *md);
* Functions for manipulating a table. Tables are also reference * Functions for manipulating a table. Tables are also reference
* counted. * counted.
*---------------------------------------------------------------*/ *---------------------------------------------------------------*/
int dm_table_create(struct dm_table **result, int mode, unsigned num_targets); int dm_table_create(struct dm_table **result, int mode,
unsigned num_targets, struct mapped_device *md);
void dm_table_get(struct dm_table *t); void dm_table_get(struct dm_table *t);
void dm_table_put(struct dm_table *t); void dm_table_put(struct dm_table *t);
...@@ -107,6 +108,7 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q); ...@@ -107,6 +108,7 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q);
unsigned int dm_table_get_num_targets(struct dm_table *t); unsigned int dm_table_get_num_targets(struct dm_table *t);
struct list_head *dm_table_get_devices(struct dm_table *t); struct list_head *dm_table_get_devices(struct dm_table *t);
int dm_table_get_mode(struct dm_table *t); int dm_table_get_mode(struct dm_table *t);
struct mapped_device *dm_table_get_md(struct dm_table *t);
void dm_table_presuspend_targets(struct dm_table *t); void dm_table_presuspend_targets(struct dm_table *t);
void dm_table_postsuspend_targets(struct dm_table *t); void dm_table_postsuspend_targets(struct dm_table *t);
void dm_table_resume_targets(struct dm_table *t); void dm_table_resume_targets(struct dm_table *t);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment