diff options
-rw-r--r-- | drivers/md/dm-ioctl.c | 70 | ||||
-rw-r--r-- | include/linux/dm-ioctl.h | 13 |
2 files changed, 67 insertions, 16 deletions
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index d06dd39856f3..a3d20265ffc1 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c | |||
@@ -523,8 +523,6 @@ static int list_versions(struct dm_ioctl *param, size_t param_size) | |||
523 | return 0; | 523 | return 0; |
524 | } | 524 | } |
525 | 525 | ||
526 | |||
527 | |||
528 | static int check_name(const char *name) | 526 | static int check_name(const char *name) |
529 | { | 527 | { |
530 | if (strchr(name, '/')) { | 528 | if (strchr(name, '/')) { |
@@ -536,6 +534,40 @@ static int check_name(const char *name) | |||
536 | } | 534 | } |
537 | 535 | ||
538 | /* | 536 | /* |
537 | * On successful return, the caller must not attempt to acquire | ||
538 | * _hash_lock without first calling dm_table_put, because dm_table_destroy | ||
539 | * waits for this dm_table_put and could be called under this lock. | ||
540 | */ | ||
541 | static struct dm_table *dm_get_inactive_table(struct mapped_device *md) | ||
542 | { | ||
543 | struct hash_cell *hc; | ||
544 | struct dm_table *table = NULL; | ||
545 | |||
546 | down_read(&_hash_lock); | ||
547 | hc = dm_get_mdptr(md); | ||
548 | if (!hc || hc->md != md) { | ||
549 | DMWARN("device has been removed from the dev hash table."); | ||
550 | goto out; | ||
551 | } | ||
552 | |||
553 | table = hc->new_map; | ||
554 | if (table) | ||
555 | dm_table_get(table); | ||
556 | |||
557 | out: | ||
558 | up_read(&_hash_lock); | ||
559 | |||
560 | return table; | ||
561 | } | ||
562 | |||
563 | static struct dm_table *dm_get_live_or_inactive_table(struct mapped_device *md, | ||
564 | struct dm_ioctl *param) | ||
565 | { | ||
566 | return (param->flags & DM_QUERY_INACTIVE_TABLE_FLAG) ? | ||
567 | dm_get_inactive_table(md) : dm_get_live_table(md); | ||
568 | } | ||
569 | |||
570 | /* | ||
539 | * Fills in a dm_ioctl structure, ready for sending back to | 571 | * Fills in a dm_ioctl structure, ready for sending back to |
540 | * userland. | 572 | * userland. |
541 | */ | 573 | */ |
@@ -559,18 +591,30 @@ static int __dev_status(struct mapped_device *md, struct dm_ioctl *param) | |||
559 | */ | 591 | */ |
560 | param->open_count = dm_open_count(md); | 592 | param->open_count = dm_open_count(md); |
561 | 593 | ||
562 | if (get_disk_ro(disk)) | ||
563 | param->flags |= DM_READONLY_FLAG; | ||
564 | |||
565 | param->event_nr = dm_get_event_nr(md); | 594 | param->event_nr = dm_get_event_nr(md); |
595 | param->target_count = 0; | ||
566 | 596 | ||
567 | table = dm_get_live_table(md); | 597 | table = dm_get_live_table(md); |
568 | if (table) { | 598 | if (table) { |
569 | param->flags |= DM_ACTIVE_PRESENT_FLAG; | 599 | if (!(param->flags & DM_QUERY_INACTIVE_TABLE_FLAG)) { |
570 | param->target_count = dm_table_get_num_targets(table); | 600 | if (get_disk_ro(disk)) |
601 | param->flags |= DM_READONLY_FLAG; | ||
602 | param->target_count = dm_table_get_num_targets(table); | ||
603 | } | ||
571 | dm_table_put(table); | 604 | dm_table_put(table); |
572 | } else | 605 | |
573 | param->target_count = 0; | 606 | param->flags |= DM_ACTIVE_PRESENT_FLAG; |
607 | } | ||
608 | |||
609 | if (param->flags & DM_QUERY_INACTIVE_TABLE_FLAG) { | ||
610 | table = dm_get_inactive_table(md); | ||
611 | if (table) { | ||
612 | if (!(dm_table_get_mode(table) & FMODE_WRITE)) | ||
613 | param->flags |= DM_READONLY_FLAG; | ||
614 | param->target_count = dm_table_get_num_targets(table); | ||
615 | dm_table_put(table); | ||
616 | } | ||
617 | } | ||
574 | 618 | ||
575 | return 0; | 619 | return 0; |
576 | } | 620 | } |
@@ -993,7 +1037,7 @@ static int dev_wait(struct dm_ioctl *param, size_t param_size) | |||
993 | if (r) | 1037 | if (r) |
994 | goto out; | 1038 | goto out; |
995 | 1039 | ||
996 | table = dm_get_live_table(md); | 1040 | table = dm_get_live_or_inactive_table(md, param); |
997 | if (table) { | 1041 | if (table) { |
998 | retrieve_status(table, param, param_size); | 1042 | retrieve_status(table, param, param_size); |
999 | dm_table_put(table); | 1043 | dm_table_put(table); |
@@ -1226,7 +1270,7 @@ static int table_deps(struct dm_ioctl *param, size_t param_size) | |||
1226 | if (r) | 1270 | if (r) |
1227 | goto out; | 1271 | goto out; |
1228 | 1272 | ||
1229 | table = dm_get_live_table(md); | 1273 | table = dm_get_live_or_inactive_table(md, param); |
1230 | if (table) { | 1274 | if (table) { |
1231 | retrieve_deps(table, param, param_size); | 1275 | retrieve_deps(table, param, param_size); |
1232 | dm_table_put(table); | 1276 | dm_table_put(table); |
@@ -1255,13 +1299,13 @@ static int table_status(struct dm_ioctl *param, size_t param_size) | |||
1255 | if (r) | 1299 | if (r) |
1256 | goto out; | 1300 | goto out; |
1257 | 1301 | ||
1258 | table = dm_get_live_table(md); | 1302 | table = dm_get_live_or_inactive_table(md, param); |
1259 | if (table) { | 1303 | if (table) { |
1260 | retrieve_status(table, param, param_size); | 1304 | retrieve_status(table, param, param_size); |
1261 | dm_table_put(table); | 1305 | dm_table_put(table); |
1262 | } | 1306 | } |
1263 | 1307 | ||
1264 | out: | 1308 | out: |
1265 | dm_put(md); | 1309 | dm_put(md); |
1266 | return r; | 1310 | return r; |
1267 | } | 1311 | } |
diff --git a/include/linux/dm-ioctl.h b/include/linux/dm-ioctl.h index 2ab84c83c31a..aa95508d2f95 100644 --- a/include/linux/dm-ioctl.h +++ b/include/linux/dm-ioctl.h | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2001 - 2003 Sistina Software (UK) Limited. | 2 | * Copyright (C) 2001 - 2003 Sistina Software (UK) Limited. |
3 | * Copyright (C) 2004 - 2005 Red Hat, Inc. All rights reserved. | 3 | * Copyright (C) 2004 - 2009 Red Hat, Inc. All rights reserved. |
4 | * | 4 | * |
5 | * This file is released under the LGPL. | 5 | * This file is released under the LGPL. |
6 | */ | 6 | */ |
@@ -266,9 +266,9 @@ enum { | |||
266 | #define DM_DEV_SET_GEOMETRY _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl) | 266 | #define DM_DEV_SET_GEOMETRY _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl) |
267 | 267 | ||
268 | #define DM_VERSION_MAJOR 4 | 268 | #define DM_VERSION_MAJOR 4 |
269 | #define DM_VERSION_MINOR 15 | 269 | #define DM_VERSION_MINOR 16 |
270 | #define DM_VERSION_PATCHLEVEL 0 | 270 | #define DM_VERSION_PATCHLEVEL 0 |
271 | #define DM_VERSION_EXTRA "-ioctl (2009-04-01)" | 271 | #define DM_VERSION_EXTRA "-ioctl (2009-11-05)" |
272 | 272 | ||
273 | /* Status bits */ | 273 | /* Status bits */ |
274 | #define DM_READONLY_FLAG (1 << 0) /* In/Out */ | 274 | #define DM_READONLY_FLAG (1 << 0) /* In/Out */ |
@@ -309,4 +309,11 @@ enum { | |||
309 | */ | 309 | */ |
310 | #define DM_NOFLUSH_FLAG (1 << 11) /* In */ | 310 | #define DM_NOFLUSH_FLAG (1 << 11) /* In */ |
311 | 311 | ||
312 | /* | ||
313 | * If set, any table information returned will relate to the inactive | ||
314 | * table instead of the live one. Always check DM_INACTIVE_PRESENT_FLAG | ||
315 | * is set before using the data returned. | ||
316 | */ | ||
317 | #define DM_QUERY_INACTIVE_TABLE_FLAG (1 << 12) /* In */ | ||
318 | |||
312 | #endif /* _LINUX_DM_IOCTL_H */ | 319 | #endif /* _LINUX_DM_IOCTL_H */ |