All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] dm: also check for conflicting table type in dm_table_set_type
@ 2010-05-20 22:26 Mike Snitzer
  2010-05-21  9:01 ` Kiyoshi Ueda
  0 siblings, 1 reply; 2+ messages in thread
From: Mike Snitzer @ 2010-05-20 22:26 UTC (permalink / raw)
  To: dm-devel; +Cc: Kiyoshi Ueda

Factorize live table type compatibility check into
dm_table_type_matches_live_table().  Catching a conflicting table type
early, during table load, avoids failing during resume -- which always
leaves the DM device suspended.

So also check type during dm_table_set_type() -- which happens as part
of a table load.  But preserve the existing check during resume, in
dm_swap_table(), because a racing table load could stage an inactive
table that conflicts with the table type that dm_swap_table() is about
to make live:

table_load() for bio-based               do_resume() for rq-based
-----------------------------------------------------------------
dm_table_type_matches_live_table(t)
                                         down_write(_hash_lock)
                                         new_map = hc->new_map
                                         up_write(_hash_lock)
down_write(_hash_lock)
hc->new_map = t
up_write(_hash_lock)
                                         dm_swap_table(md, new_map)
                                         dm_table_type_matches_live_table(t)
                                         __bind(md, new_map)

Signed-off-by: Mike Snitzer <snitzer@redhat.com>
---
 drivers/md/dm-table.c |   24 +++++++++++++++++++++++-
 drivers/md/dm.c       |    6 +-----
 drivers/md/dm.h       |    1 +
 3 files changed, 25 insertions(+), 6 deletions(-)

Index: linux-2.6/drivers/md/dm-table.c
===================================================================
--- linux-2.6.orig/drivers/md/dm-table.c
+++ linux-2.6/drivers/md/dm-table.c
@@ -803,7 +803,7 @@ int dm_table_set_type(struct dm_table *t
 	if (bio_based) {
 		/* We must use this table as bio-based */
 		t->type = DM_TYPE_BIO_BASED;
-		return 0;
+		goto finish;
 	}
 
 	BUG_ON(!request_based); /* No targets in this table */
@@ -831,6 +831,10 @@ int dm_table_set_type(struct dm_table *t
 
 	t->type = DM_TYPE_REQUEST_BASED;
 
+finish:
+	if (!dm_table_type_matches_live_table(t))
+		return -EINVAL;
+
 	return 0;
 }
 
@@ -839,6 +843,24 @@ unsigned dm_table_get_type(struct dm_tab
 	return t->type;
 }
 
+int dm_table_type_matches_live_table(struct dm_table *t)
+{
+	int r = 1;
+	struct dm_table *live_table = NULL;
+
+	live_table = dm_get_live_table(t->md);
+	if (!live_table)
+		return 1; /* no live table, return success */
+
+	if (dm_table_get_type(live_table) != dm_table_get_type(t)) {
+		DMWARN("can't change the device type after a table is bound");
+		r = 0;
+	}
+	dm_table_put(live_table);
+
+	return r;
+}
+
 bool dm_table_request_based(struct dm_table *t)
 {
 	return dm_table_get_type(t) == DM_TYPE_REQUEST_BASED;
Index: linux-2.6/drivers/md/dm.c
===================================================================
--- linux-2.6.orig/drivers/md/dm.c
+++ linux-2.6/drivers/md/dm.c
@@ -2403,12 +2403,8 @@ struct dm_table *dm_swap_table(struct ma
 		goto out;
 	}
 
-	/* cannot change the device type, once a table is bound */
-	if (md->map &&
-	    (dm_table_get_type(md->map) != dm_table_get_type(table))) {
-		DMWARN("can't change the device type after a table is bound");
+	if (!dm_table_type_matches_live_table(table))
 		goto out;
-	}
 
 	map = __bind(md, table, &limits);
 
Index: linux-2.6/drivers/md/dm.h
===================================================================
--- linux-2.6.orig/drivers/md/dm.h
+++ linux-2.6/drivers/md/dm.h
@@ -61,6 +61,7 @@ int dm_table_any_congested(struct dm_tab
 int dm_table_any_busy_target(struct dm_table *t);
 int dm_table_set_type(struct dm_table *t);
 unsigned dm_table_get_type(struct dm_table *t);
+int dm_table_type_matches_live_table(struct dm_table *t);
 bool dm_table_request_based(struct dm_table *t);
 int dm_table_alloc_md_mempools(struct dm_table *t);
 void dm_table_free_md_mempools(struct dm_table *t);

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

* Re: [PATCH] dm: also check for conflicting table type in dm_table_set_type
  2010-05-20 22:26 [PATCH] dm: also check for conflicting table type in dm_table_set_type Mike Snitzer
@ 2010-05-21  9:01 ` Kiyoshi Ueda
  0 siblings, 0 replies; 2+ messages in thread
From: Kiyoshi Ueda @ 2010-05-21  9:01 UTC (permalink / raw)
  To: Mike Snitzer; +Cc: dm-devel

Hi Mike,

On 05/21/2010 07:26 AM +0900, Mike Snitzer wrote:
> Factorize live table type compatibility check into
> dm_table_type_matches_live_table().  Catching a conflicting table type
> early, during table load, avoids failing during resume -- which always
> leaves the DM device suspended.
> 
> So also check type during dm_table_set_type() -- which happens as part
> of a table load.  But preserve the existing check during resume, in
> dm_swap_table(), because a racing table load could stage an inactive
> table that conflicts with the table type that dm_swap_table() is about
> to make live:

As you noted, the additional check in dm_table_set_type() is racy and
has no guarantee to detect problematic table loading in some cases.
Although I'm not sure such a duplicated racy check is really needed,
it will detect most cases and users may be happy with that.

So I have no objection, but at least, please put some comments that
it's racy in the code below.

> +finish:
> +	if (!dm_table_type_matches_live_table(t))
> +		return -EINVAL;
> +

Thanks,
Kiyoshi Ueda

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

end of thread, other threads:[~2010-05-21  9:01 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-05-20 22:26 [PATCH] dm: also check for conflicting table type in dm_table_set_type Mike Snitzer
2010-05-21  9:01 ` Kiyoshi Ueda

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.