From: Mike Anderson 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: Mike Anderson Signed-off-by: Alasdair G Kergon Signed-off-by: Andrew Morton --- drivers/md/dm-ioctl.c | 32 +++++++++++++++++++++----------- drivers/md/dm-table.c | 13 ++++++++++++- drivers/md/dm.c | 6 +++--- drivers/md/dm.h | 4 +++- 4 files changed, 39 insertions(+), 16 deletions(-) diff -puN drivers/md/dm.c~dm-table-store-md drivers/md/dm.c --- devel/drivers/md/dm.c~dm-table-store-md 2006-03-12 16:53:43.000000000 -0800 +++ devel-akpm/drivers/md/dm.c 2006-03-12 16:53:43.000000000 -0800 @@ -1002,18 +1002,18 @@ void dm_get(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)) { + map = dm_get_table(md); if (!dm_suspended(md)) { dm_table_presuspend_targets(map); dm_table_postsuspend_targets(map); } __unbind(md); + dm_table_put(map); free_dev(md); } - - dm_table_put(map); } /* diff -puN drivers/md/dm.h~dm-table-store-md drivers/md/dm.h --- devel/drivers/md/dm.h~dm-table-store-md 2006-03-12 16:53:43.000000000 -0800 +++ devel-akpm/drivers/md/dm.h 2006-03-12 16:53:43.000000000 -0800 @@ -89,7 +89,8 @@ int dm_suspended(struct mapped_device *m * Functions for manipulating a table. Tables are also reference * 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_put(struct dm_table *t); @@ -107,6 +108,7 @@ void dm_table_set_restrictions(struct dm unsigned int dm_table_get_num_targets(struct dm_table *t); struct list_head *dm_table_get_devices(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_postsuspend_targets(struct dm_table *t); void dm_table_resume_targets(struct dm_table *t); diff -puN drivers/md/dm-ioctl.c~dm-table-store-md drivers/md/dm-ioctl.c --- devel/drivers/md/dm-ioctl.c~dm-table-store-md 2006-03-12 16:53:43.000000000 -0800 +++ devel-akpm/drivers/md/dm-ioctl.c 2006-03-12 16:53:43.000000000 -0800 @@ -244,9 +244,9 @@ static void __hash_remove(struct hash_ce dm_table_put(table); } - dm_put(hc->md); if (hc->new_map) dm_table_put(hc->new_map); + dm_put(hc->md); free_cell(hc); } @@ -985,33 +985,43 @@ static int table_load(struct dm_ioctl *p int r; struct hash_cell *hc; 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) - return r; + goto out; r = populate_table(t, param, param_size); if (r) { dm_table_put(t); - return r; + goto out; } down_write(&_hash_lock); - hc = __find_device_hash_cell(param); - if (!hc) { - DMWARN("device doesn't appear to be in the dev hash table."); - up_write(&_hash_lock); + hc = dm_get_mdptr(md); + if (!hc || hc->md != md) { + DMWARN("device has been removed from the dev hash table."); dm_table_put(t); - return -ENXIO; + up_write(&_hash_lock); + r = -ENXIO; + goto out; } if (hc->new_map) dm_table_put(hc->new_map); hc->new_map = t; + up_write(&_hash_lock); + 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; } diff -puN drivers/md/dm-table.c~dm-table-store-md drivers/md/dm-table.c --- devel/drivers/md/dm-table.c~dm-table-store-md 2006-03-12 16:53:43.000000000 -0800 +++ devel-akpm/drivers/md/dm-table.c 2006-03-12 16:53:43.000000000 -0800 @@ -22,6 +22,7 @@ #define CHILDREN_PER_NODE (KEYS_PER_NODE + 1) struct dm_table { + struct mapped_device *md; atomic_t holders; /* btree table */ @@ -206,7 +207,8 @@ static int alloc_targets(struct dm_table 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); @@ -229,6 +231,7 @@ int dm_table_create(struct dm_table **re } t->mode = mode; + t->md = md; *result = t; return 0; } @@ -954,12 +957,20 @@ int dm_table_flush_all(struct dm_table * 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_get_device); EXPORT_SYMBOL(dm_put_device); EXPORT_SYMBOL(dm_table_event); EXPORT_SYMBOL(dm_table_get_size); EXPORT_SYMBOL(dm_table_get_mode); +EXPORT_SYMBOL(dm_table_get_md); EXPORT_SYMBOL(dm_table_put); EXPORT_SYMBOL(dm_table_get); EXPORT_SYMBOL(dm_table_unplug_all); _