[dm-devel] [PATCH] dm thin: fix pool target flags that control discard

Mike Snitzer snitzer at redhat.com
Fri Mar 23 21:55:02 UTC 2012


On Fri, Mar 23 2012 at  8:37am -0400,
Alasdair G Kergon <agk at redhat.com> wrote:

> On Fri, Mar 16, 2012 at 03:22:34PM +0000, Joe Thornber wrote:
> > +      'ignore_discard': disable discard support
> > +      'no_discard_passdown': don't pass discards down to the underlying data device
> 
> If someone reloads the pool target changing either of these options, how do connected
> thin targets pick up the change?  If they don't pick it up automatically, how do you
> determine whether they did or didn't pick it up - is that internal state not
> exposed to userspace yet?

Here are various fixes for dm_thin-add-pool-target-flags-to-control-discard.patch

o wire up 'discard_passdown' so that it does control whether or not the
  discard is passed to the pool's underlying data device
o disallow disabling discards if a pool was already configured with
  discards enabled (the default)
  - justification is inlined in the code
  - required pool_ctr knowing whether pool was created or not; so added
    'created' flag to __pool_find()
o if 'discard_passdown' is enabled (the default) verify that the pool's
  data device supports discards; if not warn and disable discard_passdown
o the pool device's discard support should _not_ be limited by whether
  'discard_passdown' is enabled or not.

Signed-off-by: Mike Snitzer <snitzer at redhat.com>
---
 drivers/md/dm-thin.c |   41 ++++++++++++++++++++++++++++++++++-------
 1 file changed, 34 insertions(+), 7 deletions(-)

Index: linux/drivers/md/dm-thin.c
===================================================================
--- linux.orig/drivers/md/dm-thin.c
+++ linux/drivers/md/dm-thin.c
@@ -1209,7 +1209,7 @@ static void process_discard(struct thin_
 			 */
 			m = get_next_mapping(pool);
 			m->tc = tc;
-			m->pass_discard = !lookup_result.shared;
+			m->pass_discard = (!lookup_result.shared) & pool->pf.discard_passdown;
 			m->virt_block = block;
 			m->data_block = lookup_result.block;
 			m->cell = cell;
@@ -1790,7 +1790,8 @@ static void __pool_dec(struct pool *pool
 
 static struct pool *__pool_find(struct mapped_device *pool_md,
 				struct block_device *metadata_dev,
-				unsigned long block_size, char **error)
+				unsigned long block_size, char **error,
+				int *created)
 {
 	struct pool *pool = __pool_table_lookup_metadata_dev(metadata_dev);
 
@@ -1806,8 +1807,10 @@ static struct pool *__pool_find(struct m
 				return ERR_PTR(-EINVAL);
 			__pool_inc(pool);
 
-		} else
+		} else {
 			pool = pool_create(pool_md, metadata_dev, block_size, error);
+			*created = 1;
+		}
 	}
 
 	return pool;
@@ -1887,7 +1890,7 @@ static int parse_pool_features(struct dm
  */
 static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
 {
-	int r;
+	int r, pool_created = 0;
 	struct pool_c *pt;
 	struct pool *pool;
 	struct pool_features pf;
@@ -1961,12 +1964,36 @@ static int pool_ctr(struct dm_target *ti
 	}
 
 	pool = __pool_find(dm_table_get_md(ti->table), metadata_dev->bdev,
-			   block_size, &ti->error);
+			   block_size, &ti->error, &pool_created);
 	if (IS_ERR(pool)) {
 		r = PTR_ERR(pool);
 		goto out_free_pt;
 	}
 
+	/*
+	 * 'pool_created' reflects whether this is the first table load.
+	 * Discard support is not allowed to be disabled after initial load.
+	 * Disabling it would require a pool reload to trigger thin device
+	 * changes (e.g. ti->discards_supported and QUEUE_FLAG_DISCARD).
+	 */
+	if (!pool_created && !pf.discard_enabled && pool->pf.discard_enabled) {
+		ti->error = "Discard support cannot be disabled once enabled";
+		r = -EINVAL;
+		goto out_free_pt;
+	}
+
+	/*
+	 * If discard_passdown was enabled verify that the data device
+	 * supports discards.  Disable discard_passdown if not.
+	 */
+	if (pf.discard_passdown) {
+		struct request_queue *q = bdev_get_queue(data_dev->bdev);
+		if (!q || !blk_queue_discard(q)) {
+			DMWARN("Discard unsupported by data device, disabling discard passdown");
+			pf.discard_passdown = 0;
+		}
+	}
+
 	pt->pool = pool;
 	pt->ti = ti;
 	pt->metadata_dev = metadata_dev;
@@ -1974,9 +2001,9 @@ static int pool_ctr(struct dm_target *ti
 	pt->low_water_blocks = low_water_blocks;
 	pt->pf = pf;
 	ti->num_flush_requests = 1;
-	if (pf.discard_enabled && pf.discard_passdown) {
-		ti->discards_supported = 1;
+	if (pf.discard_enabled) {
 		ti->num_discard_requests = 1;
+		ti->discards_supported = 1;
 	}
 	ti->private = pt;
 




More information about the dm-devel mailing list