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