diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/md/dm-ioctl.c | 32 | ||||
-rw-r--r-- | drivers/md/dm-table.c | 13 | ||||
-rw-r--r-- | drivers/md/dm.c | 6 | ||||
-rw-r--r-- | drivers/md/dm.h | 4 |
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 | |||
1022 | out: | ||
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 | ||
24 | struct dm_table { | 24 | struct 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 | ||
209 | int dm_table_create(struct dm_table **result, int mode, unsigned num_targets) | 210 | int 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 | ||
958 | struct mapped_device *dm_table_get_md(struct dm_table *t) | ||
959 | { | ||
960 | dm_get(t->md); | ||
961 | |||
962 | return t->md; | ||
963 | } | ||
964 | |||
955 | EXPORT_SYMBOL(dm_vcalloc); | 965 | EXPORT_SYMBOL(dm_vcalloc); |
956 | EXPORT_SYMBOL(dm_get_device); | 966 | EXPORT_SYMBOL(dm_get_device); |
957 | EXPORT_SYMBOL(dm_put_device); | 967 | EXPORT_SYMBOL(dm_put_device); |
958 | EXPORT_SYMBOL(dm_table_event); | 968 | EXPORT_SYMBOL(dm_table_event); |
959 | EXPORT_SYMBOL(dm_table_get_size); | 969 | EXPORT_SYMBOL(dm_table_get_size); |
960 | EXPORT_SYMBOL(dm_table_get_mode); | 970 | EXPORT_SYMBOL(dm_table_get_mode); |
971 | EXPORT_SYMBOL(dm_table_get_md); | ||
961 | EXPORT_SYMBOL(dm_table_put); | 972 | EXPORT_SYMBOL(dm_table_put); |
962 | EXPORT_SYMBOL(dm_table_get); | 973 | EXPORT_SYMBOL(dm_table_get); |
963 | EXPORT_SYMBOL(dm_table_unplug_all); | 974 | EXPORT_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 | ||
1008 | void dm_put(struct mapped_device *md) | 1008 | void 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 | *---------------------------------------------------------------*/ |
92 | int dm_table_create(struct dm_table **result, int mode, unsigned num_targets); | 92 | int dm_table_create(struct dm_table **result, int mode, |
93 | unsigned num_targets, struct mapped_device *md); | ||
93 | 94 | ||
94 | void dm_table_get(struct dm_table *t); | 95 | void dm_table_get(struct dm_table *t); |
95 | void dm_table_put(struct dm_table *t); | 96 | 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 | unsigned int dm_table_get_num_targets(struct dm_table *t); | 108 | unsigned int dm_table_get_num_targets(struct dm_table *t); |
108 | struct list_head *dm_table_get_devices(struct dm_table *t); | 109 | struct list_head *dm_table_get_devices(struct dm_table *t); |
109 | int dm_table_get_mode(struct dm_table *t); | 110 | int dm_table_get_mode(struct dm_table *t); |
111 | struct mapped_device *dm_table_get_md(struct dm_table *t); | ||
110 | void dm_table_presuspend_targets(struct dm_table *t); | 112 | void dm_table_presuspend_targets(struct dm_table *t); |
111 | void dm_table_postsuspend_targets(struct dm_table *t); | 113 | void dm_table_postsuspend_targets(struct dm_table *t); |
112 | void dm_table_resume_targets(struct dm_table *t); | 114 | void dm_table_resume_targets(struct dm_table *t); |