All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] dm ioctl: retrieve status from inactive table
@ 2009-10-20 21:02 Mike Snitzer
  2009-11-06  2:15 ` Alasdair G Kergon
  0 siblings, 1 reply; 2+ messages in thread
From: Mike Snitzer @ 2009-10-20 21:02 UTC (permalink / raw)
  To: dm-devel

Adds input flag (DM_STATUS_INACTIVE_FLAG) for use in the ioctl STATUS
command.  Introduces dm_get_inactive_table() to get a reference on the
inactive table so that it is protected during use in table_status().
Allows us to safely display the status/table of a DM device's inactive
table.

This is useful for seeing when a DM device is in the middle a complex
transition, e.g. snapshot-merge's exception handover:

Before snapshot-merge:
----------------------
# dmsetup status test-testlv
0 67108864 snapshot-origin
# dmsetup status test-testlv_snap
0 67108864 snapshot 1328904/14680064 5184

# dmsetup status --inactive test-testlv
0 0
# dmsetup status --inactive test-testlv_snap
0 0


Snapshot-merge target created, about to handover exceptions:
------------------------------------------------------------
# dmsetup status test-testlv
0 67108864 snapshot-origin
# dmsetup status test-testlv_snap
0 67108864 snapshot 1328904/14680064 5184

# dmsetup status --inactive test-testlv
0 67108864 snapshot-merge 16/14680064 16

NOTE: the snapshot-merge store is empty (handover hasn't happened yet)


After exception handover, before merge has started:
---------------------------------------------------
# dmsetup status test-testlv
0 67108864 snapshot-origin

# dmsetup status --inactive test-testlv
0 67108864 snapshot-merge 1328904/14680064 5184


Snapshot-merge table is now active and is merging:
--------------------------------------------------
# dmsetup status test-testlv
0 67108864 snapshot-merge 1114360/14680064 4344

# dmsetup table --inactive test-testlv
0 0


Signed-off-by: Mike Snitzer <snitzer@redhat.com>

---
 drivers/md/dm-ioctl.c    |   33 ++++++++++++++++++++++++++++++++-
 include/linux/dm-ioctl.h |   10 ++++++++--
 2 files changed, 40 insertions(+), 3 deletions(-)

Index: linux-2.6/drivers/md/dm-ioctl.c
===================================================================
--- linux-2.6.orig/drivers/md/dm-ioctl.c
+++ linux-2.6/drivers/md/dm-ioctl.c
@@ -650,6 +650,23 @@ static struct mapped_device *find_device
 	return md;
 }
 
+static struct dm_table *dm_get_inactive_table(struct dm_ioctl *param)
+{
+	struct hash_cell *hc;
+	struct dm_table *table = NULL;
+
+	down_read(&_hash_lock);
+	hc = __find_device_hash_cell(param);
+	if (hc) {
+		table = hc->new_map;
+		if (table)
+			dm_table_get(table);
+	}
+        up_read(&_hash_lock);
+
+	return table;
+}
+
 static int dev_remove(struct dm_ioctl *param, size_t param_size)
 {
 	struct hash_cell *hc;
@@ -1226,6 +1243,20 @@ static int table_deps(struct dm_ioctl *p
 	return r;
 }
 
+static struct dm_table* __dm_get_table(struct mapped_device *md,
+				       struct dm_ioctl *param)
+{
+	struct dm_table *table = NULL;
+
+	if (param->flags & DM_STATUS_INACTIVE_FLAG) {
+		if (param->flags & DM_INACTIVE_PRESENT_FLAG)
+			table = dm_get_inactive_table(param);
+	} else
+		table = dm_get_table(md);
+
+	return table;
+}
+
 /*
  * Return the status of a device as a text string for each
  * target.
@@ -1244,7 +1275,7 @@ static int table_status(struct dm_ioctl 
 	if (r)
 		goto out;
 
-	table = dm_get_table(md);
+	table = __dm_get_table(md, param);
 	if (table) {
 		retrieve_status(table, param, param_size);
 		dm_table_put(table);
Index: linux-2.6/include/linux/dm-ioctl.h
===================================================================
--- linux-2.6.orig/include/linux/dm-ioctl.h
+++ linux-2.6/include/linux/dm-ioctl.h
@@ -266,9 +266,9 @@ enum {
 #define DM_DEV_SET_GEOMETRY	_IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl)
 
 #define DM_VERSION_MAJOR	4
-#define DM_VERSION_MINOR	15
+#define DM_VERSION_MINOR	16
 #define DM_VERSION_PATCHLEVEL	0
-#define DM_VERSION_EXTRA	"-ioctl (2009-04-01)"
+#define DM_VERSION_EXTRA	"-ioctl (2009-10-20)"
 
 /* Status bits */
 #define DM_READONLY_FLAG	(1 << 0) /* In/Out */
@@ -282,6 +282,12 @@ enum {
 #define DM_STATUS_TABLE_FLAG	(1 << 4) /* In */
 
 /*
+ * Flag passed into ioctl STATUS command to get table information
+ * or current status from the inactive table.
+ */
+#define DM_STATUS_INACTIVE_FLAG	(1 << 7) /* In */
+
+/*
  * Flags that indicate whether a table is present in either of
  * the two table slots that a device has.
  */

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [PATCH] dm ioctl: retrieve status from inactive table
  2009-10-20 21:02 [PATCH] dm ioctl: retrieve status from inactive table Mike Snitzer
@ 2009-11-06  2:15 ` Alasdair G Kergon
  0 siblings, 0 replies; 2+ messages in thread
From: Alasdair G Kergon @ 2009-11-06  2:15 UTC (permalink / raw)
  To: device-mapper development

Latest version.  The userspace support is now in dmsetup in CVS.

Please could some people who are familiar with the ioctls and dmsetup 
try these out?

The --inactive flag is meant to work with all dmsetup cmds that return
any table information, and all table information should be affected
(including number of targets).

(Patch is also here: 
http://www.kernel.org/pub/linux/kernel/people/agk/patches/2.6/editing/dm-ioctl-retrieve-status-from-inactive-table.patch
and should apply on top of current linux-next.)

Alasdair



Add the flag DM_QUERY_INACTIVE_TABLE_FLAG to the ioctls to return
infomation about the loaded-but-not-yet-active table instead of the live
table.  Prior to this patch it was impossible to obtain this information
until the device had been 'resumed'.

Userspace dmsetup and libdevmapper support the flag as of version 1.02.40.
e.g. dmsetup info --inactive vg1-lv1

Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>

---
 drivers/md/dm-ioctl.c    |   70 ++++++++++++++++++++++++++++++++++++++---------
 include/linux/dm-ioctl.h |   13 ++++++--
 2 files changed, 67 insertions(+), 16 deletions(-)

Index: linux-2.6.32-rc6/drivers/md/dm-ioctl.c
===================================================================
--- linux-2.6.32-rc6.orig/drivers/md/dm-ioctl.c
+++ linux-2.6.32-rc6/drivers/md/dm-ioctl.c
@@ -512,8 +512,6 @@ static int list_versions(struct dm_ioctl
 	return 0;
 }
 
-
-
 static int check_name(const char *name)
 {
 	if (strchr(name, '/')) {
@@ -525,6 +523,40 @@ static int check_name(const char *name)
 }
 
 /*
+ * On successful return, the caller must not attempt to acquire
+ * _hash_lock without first calling dm_table_put, because dm_table_destroy
+ * waits for this dm_table_put and could be called under this lock.
+ */
+static struct dm_table *dm_get_inactive_table(struct mapped_device *md)
+{
+	struct hash_cell *hc;
+	struct dm_table *table = NULL;
+
+	down_read(&_hash_lock);
+	hc = dm_get_mdptr(md);
+	if (!hc || hc->md != md) {
+		DMWARN("device has been removed from the dev hash table.");
+		goto out;
+	}
+
+	table = hc->new_map;
+	if (table)
+		dm_table_get(table);
+
+out:
+	up_read(&_hash_lock);
+
+	return table;
+}
+
+static struct dm_table *dm_get_live_or_inactive_table(struct mapped_device *md,
+						      struct dm_ioctl *param)
+{
+	return (param->flags & DM_QUERY_INACTIVE_TABLE_FLAG) ?
+		dm_get_inactive_table(md) : dm_get_live_table(md);
+}
+
+/*
  * Fills in a dm_ioctl structure, ready for sending back to
  * userland.
  */
@@ -548,18 +580,30 @@ static int __dev_status(struct mapped_de
 	 */
 	param->open_count = dm_open_count(md);
 
-	if (get_disk_ro(disk))
-		param->flags |= DM_READONLY_FLAG;
-
 	param->event_nr = dm_get_event_nr(md);
+	param->target_count = 0;
 
 	table = dm_get_live_table(md);
 	if (table) {
-		param->flags |= DM_ACTIVE_PRESENT_FLAG;
-		param->target_count = dm_table_get_num_targets(table);
+		if (!(param->flags & DM_QUERY_INACTIVE_TABLE_FLAG)) {
+			if (get_disk_ro(disk))
+				param->flags |= DM_READONLY_FLAG;
+			param->target_count = dm_table_get_num_targets(table);
+		}
 		dm_table_put(table);
-	} else
-		param->target_count = 0;
+
+		param->flags |= DM_ACTIVE_PRESENT_FLAG;
+	}
+
+	if (param->flags & DM_QUERY_INACTIVE_TABLE_FLAG) {
+		table = dm_get_inactive_table(md);
+		if (table) {
+			if (!(dm_table_get_mode(table) & FMODE_WRITE))
+				param->flags |= DM_READONLY_FLAG;
+			param->target_count = dm_table_get_num_targets(table);
+			dm_table_put(table);
+		}
+	}
 
 	return 0;
 }
@@ -982,7 +1026,7 @@ static int dev_wait(struct dm_ioctl *par
 	if (r)
 		goto out;
 
-	table = dm_get_live_table(md);
+	table = dm_get_live_or_inactive_table(md, param);
 	if (table) {
 		retrieve_status(table, param, param_size);
 		dm_table_put(table);
@@ -1215,7 +1259,7 @@ static int table_deps(struct dm_ioctl *p
 	if (r)
 		goto out;
 
-	table = dm_get_live_table(md);
+	table = dm_get_live_or_inactive_table(md, param);
 	if (table) {
 		retrieve_deps(table, param, param_size);
 		dm_table_put(table);
@@ -1244,13 +1288,13 @@ static int table_status(struct dm_ioctl 
 	if (r)
 		goto out;
 
-	table = dm_get_live_table(md);
+	table = dm_get_live_or_inactive_table(md, param);
 	if (table) {
 		retrieve_status(table, param, param_size);
 		dm_table_put(table);
 	}
 
- out:
+out:
 	dm_put(md);
 	return r;
 }
Index: linux-2.6.32-rc6/include/linux/dm-ioctl.h
===================================================================
--- linux-2.6.32-rc6.orig/include/linux/dm-ioctl.h
+++ linux-2.6.32-rc6/include/linux/dm-ioctl.h
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2001 - 2003 Sistina Software (UK) Limited.
- * Copyright (C) 2004 - 2005 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2004 - 2009 Red Hat, Inc. All rights reserved.
  *
  * This file is released under the LGPL.
  */
@@ -266,9 +266,9 @@ enum {
 #define DM_DEV_SET_GEOMETRY	_IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl)
 
 #define DM_VERSION_MAJOR	4
-#define DM_VERSION_MINOR	15
+#define DM_VERSION_MINOR	16
 #define DM_VERSION_PATCHLEVEL	0
-#define DM_VERSION_EXTRA	"-ioctl (2009-04-01)"
+#define DM_VERSION_EXTRA	"-ioctl (2009-11-05)"
 
 /* Status bits */
 #define DM_READONLY_FLAG	(1 << 0) /* In/Out */
@@ -309,4 +309,11 @@ enum {
  */
 #define DM_NOFLUSH_FLAG		(1 << 11) /* In */
 
+/*
+ * If set, any table information returned will relate to the inactive
+ * table instead of the live one.  Always check DM_INACTIVE_PRESENT_FLAG
+ * is set before using the data returned.
+ */
+#define DM_QUERY_INACTIVE_TABLE_FLAG	(1 << 12) /* In */
+
 #endif				/* _LINUX_DM_IOCTL_H */

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2009-11-06  2:15 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-10-20 21:02 [PATCH] dm ioctl: retrieve status from inactive table Mike Snitzer
2009-11-06  2:15 ` Alasdair G Kergon

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.