aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/md/dm-ioctl.c32
-rw-r--r--drivers/md/dm-table.c13
-rw-r--r--drivers/md/dm.c6
-rw-r--r--drivers/md/dm.h4
4 files changed, 39 insertions, 16 deletions
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index 0693b6f54b7d..65826bdac00c 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -244,9 +244,9 @@ static void __hash_remove(struct hash_cell *hc)
244 dm_table_put(table); 244 dm_table_put(table);
245 } 245 }
246 246
247 dm_put(hc->md);
248 if (hc->new_map) 247 if (hc->new_map)
249 dm_table_put(hc->new_map); 248 dm_table_put(hc->new_map);
249 dm_put(hc->md);
250 free_cell(hc); 250 free_cell(hc);
251} 251}
252 252
@@ -985,33 +985,43 @@ static int table_load(struct dm_ioctl *param, size_t param_size)
985 int r; 985 int r;
986 struct hash_cell *hc; 986 struct hash_cell *hc;
987 struct dm_table *t; 987 struct dm_table *t;
988 struct mapped_device *md;
989
990 md = find_device(param);
991 if (!md)
992 return -ENXIO;
988 993
989 r = dm_table_create(&t, get_mode(param), param->target_count); 994 r = dm_table_create(&t, get_mode(param), param->target_count, md);
990 if (r) 995 if (r)
991 return r; 996 goto out;
992 997
993 r = populate_table(t, param, param_size); 998 r = populate_table(t, param, param_size);
994 if (r) { 999 if (r) {
995 dm_table_put(t); 1000 dm_table_put(t);
996 return r; 1001 goto out;
997 } 1002 }
998 1003
999 down_write(&_hash_lock); 1004 down_write(&_hash_lock);
1000 hc = __find_device_hash_cell(param); 1005 hc = dm_get_mdptr(md);
1001 if (!hc) { 1006 if (!hc || hc->md != md) {
1002 DMWARN("device doesn't appear to be in the dev hash table."); 1007 DMWARN("device has been removed from the dev hash table.");
1003 up_write(&_hash_lock);
1004 dm_table_put(t); 1008 dm_table_put(t);
1005 return -ENXIO; 1009 up_write(&_hash_lock);
1010 r = -ENXIO;
1011 goto out;
1006 } 1012 }
1007 1013
1008 if (hc->new_map) 1014 if (hc->new_map)
1009 dm_table_put(hc->new_map); 1015 dm_table_put(hc->new_map);
1010 hc->new_map = t; 1016 hc->new_map = t;
1017 up_write(&_hash_lock);
1018
1011 param->flags |= DM_INACTIVE_PRESENT_FLAG; 1019 param->flags |= DM_INACTIVE_PRESENT_FLAG;
1020 r = __dev_status(md, param);
1021
1022out:
1023 dm_put(md);
1012 1024
1013 r = __dev_status(hc->md, param);
1014 up_write(&_hash_lock);
1015 return r; 1025 return r;
1016} 1026}
1017 1027
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index 9558a4acec12..84f4594afd3c 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -22,6 +22,7 @@
22#define CHILDREN_PER_NODE (KEYS_PER_NODE + 1) 22#define CHILDREN_PER_NODE (KEYS_PER_NODE + 1)
23 23
24struct dm_table { 24struct dm_table {
25 struct mapped_device *md;
25 atomic_t holders; 26 atomic_t holders;
26 27
27 /* btree table */ 28 /* btree table */
@@ -206,7 +207,8 @@ static int alloc_targets(struct dm_table *t, unsigned int num)
206 return 0; 207 return 0;
207} 208}
208 209
209int dm_table_create(struct dm_table **result, int mode, unsigned num_targets) 210int dm_table_create(struct dm_table **result, int mode,
211 unsigned num_targets, struct mapped_device *md)
210{ 212{
211 struct dm_table *t = kmalloc(sizeof(*t), GFP_KERNEL); 213 struct dm_table *t = kmalloc(sizeof(*t), GFP_KERNEL);
212 214
@@ -229,6 +231,7 @@ int dm_table_create(struct dm_table **result, int mode, unsigned num_targets)
229 } 231 }
230 232
231 t->mode = mode; 233 t->mode = mode;
234 t->md = md;
232 *result = t; 235 *result = t;
233 return 0; 236 return 0;
234} 237}
@@ -952,12 +955,20 @@ int dm_table_flush_all(struct dm_table *t)
952 return ret; 955 return ret;
953} 956}
954 957
958struct mapped_device *dm_table_get_md(struct dm_table *t)
959{
960 dm_get(t->md);
961
962 return t->md;
963}
964
955EXPORT_SYMBOL(dm_vcalloc); 965EXPORT_SYMBOL(dm_vcalloc);
956EXPORT_SYMBOL(dm_get_device); 966EXPORT_SYMBOL(dm_get_device);
957EXPORT_SYMBOL(dm_put_device); 967EXPORT_SYMBOL(dm_put_device);
958EXPORT_SYMBOL(dm_table_event); 968EXPORT_SYMBOL(dm_table_event);
959EXPORT_SYMBOL(dm_table_get_size); 969EXPORT_SYMBOL(dm_table_get_size);
960EXPORT_SYMBOL(dm_table_get_mode); 970EXPORT_SYMBOL(dm_table_get_mode);
971EXPORT_SYMBOL(dm_table_get_md);
961EXPORT_SYMBOL(dm_table_put); 972EXPORT_SYMBOL(dm_table_put);
962EXPORT_SYMBOL(dm_table_get); 973EXPORT_SYMBOL(dm_table_get);
963EXPORT_SYMBOL(dm_table_unplug_all); 974EXPORT_SYMBOL(dm_table_unplug_all);
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 3d121cbc2fde..b99df48cffed 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -1007,18 +1007,18 @@ void dm_get(struct mapped_device *md)
1007 1007
1008void dm_put(struct mapped_device *md) 1008void dm_put(struct mapped_device *md)
1009{ 1009{
1010 struct dm_table *map = dm_get_table(md); 1010 struct dm_table *map;
1011 1011
1012 if (atomic_dec_and_test(&md->holders)) { 1012 if (atomic_dec_and_test(&md->holders)) {
1013 map = dm_get_table(md);
1013 if (!dm_suspended(md)) { 1014 if (!dm_suspended(md)) {
1014 dm_table_presuspend_targets(map); 1015 dm_table_presuspend_targets(map);
1015 dm_table_postsuspend_targets(map); 1016 dm_table_postsuspend_targets(map);
1016 } 1017 }
1017 __unbind(md); 1018 __unbind(md);
1019 dm_table_put(map);
1018 free_dev(md); 1020 free_dev(md);
1019 } 1021 }
1020
1021 dm_table_put(map);
1022} 1022}
1023 1023
1024/* 1024/*
diff --git a/drivers/md/dm.h b/drivers/md/dm.h
index 17ffa8d671a7..79e800051a10 100644
--- a/drivers/md/dm.h
+++ b/drivers/md/dm.h
@@ -89,7 +89,8 @@ int dm_suspended(struct mapped_device *md);
89 * Functions for manipulating a table. Tables are also reference 89 * Functions for manipulating a table. Tables are also reference
90 * counted. 90 * counted.
91 *---------------------------------------------------------------*/ 91 *---------------------------------------------------------------*/
92int dm_table_create(struct dm_table **result, int mode, unsigned num_targets); 92int dm_table_create(struct dm_table **result, int mode,
93 unsigned num_targets, struct mapped_device *md);
93 94
94void dm_table_get(struct dm_table *t); 95void dm_table_get(struct dm_table *t);
95void dm_table_put(struct dm_table *t); 96void dm_table_put(struct dm_table *t);
@@ -107,6 +108,7 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q);
107unsigned int dm_table_get_num_targets(struct dm_table *t); 108unsigned int dm_table_get_num_targets(struct dm_table *t);
108struct list_head *dm_table_get_devices(struct dm_table *t); 109struct list_head *dm_table_get_devices(struct dm_table *t);
109int dm_table_get_mode(struct dm_table *t); 110int dm_table_get_mode(struct dm_table *t);
111struct mapped_device *dm_table_get_md(struct dm_table *t);
110void dm_table_presuspend_targets(struct dm_table *t); 112void dm_table_presuspend_targets(struct dm_table *t);
111void dm_table_postsuspend_targets(struct dm_table *t); 113void dm_table_postsuspend_targets(struct dm_table *t);
112void dm_table_resume_targets(struct dm_table *t); 114void dm_table_resume_targets(struct dm_table *t);