diff options
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) |