diff options
author | Mike Snitzer <snitzer@redhat.com> | 2012-10-12 16:02:07 -0400 |
---|---|---|
committer | Alasdair G Kergon <agk@redhat.com> | 2012-10-12 16:02:07 -0400 |
commit | 28eed34e7662d7602da6753b0ba2563006b8e7a2 (patch) | |
tree | 0aeeda160b7cccfb77be58d47084a8e606905bf7 /drivers/md | |
parent | 0bcf08798eb9fc3cd0fe2e6b74b25f3f57fa8af2 (diff) |
dm thin: support discard with non power of two block size
Support discards when the pool's block size is not a power of 2.
The block layer assumes discard_granularity is a power of 2 (in
blkdev_issue_discard), so we set this to the largest power of 2 that is
a divides into the number of sectors in each block, but never less than
DATA_DEV_BLOCK_SIZE_MIN_SECTORS.
This patch eliminates the "Discard support must be disabled when the
block size is not a power of 2" constraint that was imposed in commit
55f2b8b ("dm thin: support for non power of 2 pool blocksize"). That
commit was incomplete: using a block size that is not a power of 2
shouldn't mean disabling discard support on the device completely.
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Signed-off-by: Joe Thornber <ejt@redhat.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>
Diffstat (limited to 'drivers/md')
-rw-r--r-- | drivers/md/dm-thin.c | 23 |
1 files changed, 13 insertions, 10 deletions
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c index c29410af1e22..df20a115136f 100644 --- a/drivers/md/dm-thin.c +++ b/drivers/md/dm-thin.c | |||
@@ -2272,15 +2272,6 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv) | |||
2272 | goto out_flags_changed; | 2272 | goto out_flags_changed; |
2273 | } | 2273 | } |
2274 | 2274 | ||
2275 | /* | ||
2276 | * The block layer requires discard_granularity to be a power of 2. | ||
2277 | */ | ||
2278 | if (pf.discard_enabled && !is_power_of_2(block_size)) { | ||
2279 | ti->error = "Discard support must be disabled when the block size is not a power of 2"; | ||
2280 | r = -EINVAL; | ||
2281 | goto out_flags_changed; | ||
2282 | } | ||
2283 | |||
2284 | pt->pool = pool; | 2275 | pt->pool = pool; |
2285 | pt->ti = ti; | 2276 | pt->ti = ti; |
2286 | pt->metadata_dev = metadata_dev; | 2277 | pt->metadata_dev = metadata_dev; |
@@ -2762,6 +2753,11 @@ static int pool_merge(struct dm_target *ti, struct bvec_merge_data *bvm, | |||
2762 | return min(max_size, q->merge_bvec_fn(q, bvm, biovec)); | 2753 | return min(max_size, q->merge_bvec_fn(q, bvm, biovec)); |
2763 | } | 2754 | } |
2764 | 2755 | ||
2756 | static bool block_size_is_power_of_two(struct pool *pool) | ||
2757 | { | ||
2758 | return pool->sectors_per_block_shift >= 0; | ||
2759 | } | ||
2760 | |||
2765 | static void set_discard_limits(struct pool_c *pt, struct queue_limits *limits) | 2761 | static void set_discard_limits(struct pool_c *pt, struct queue_limits *limits) |
2766 | { | 2762 | { |
2767 | struct pool *pool = pt->pool; | 2763 | struct pool *pool = pt->pool; |
@@ -2775,8 +2771,15 @@ static void set_discard_limits(struct pool_c *pt, struct queue_limits *limits) | |||
2775 | if (pt->adjusted_pf.discard_passdown) { | 2771 | if (pt->adjusted_pf.discard_passdown) { |
2776 | data_limits = &bdev_get_queue(pt->data_dev->bdev)->limits; | 2772 | data_limits = &bdev_get_queue(pt->data_dev->bdev)->limits; |
2777 | limits->discard_granularity = data_limits->discard_granularity; | 2773 | limits->discard_granularity = data_limits->discard_granularity; |
2778 | } else | 2774 | } else if (block_size_is_power_of_two(pool)) |
2779 | limits->discard_granularity = pool->sectors_per_block << SECTOR_SHIFT; | 2775 | limits->discard_granularity = pool->sectors_per_block << SECTOR_SHIFT; |
2776 | else | ||
2777 | /* | ||
2778 | * Use largest power of 2 that is a factor of sectors_per_block | ||
2779 | * but at least DATA_DEV_BLOCK_SIZE_MIN_SECTORS. | ||
2780 | */ | ||
2781 | limits->discard_granularity = max(1 << (ffs(pool->sectors_per_block) - 1), | ||
2782 | DATA_DEV_BLOCK_SIZE_MIN_SECTORS) << SECTOR_SHIFT; | ||
2780 | } | 2783 | } |
2781 | 2784 | ||
2782 | static void pool_io_hints(struct dm_target *ti, struct queue_limits *limits) | 2785 | static void pool_io_hints(struct dm_target *ti, struct queue_limits *limits) |