Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

block: Fix discard topology stacking and reporting

In some cases we would end up stacking discard_zeroes_data incorrectly.
Fix this by enabling the feature by default for stacking drivers and
clearing it for low-level drivers. Incorporating a device that does not
support dzd will then cause the feature to be disabled in the stacking
driver.

Also ensure that the maximum discard value does not overflow when
exported in sysfs and return 0 in the alignment and dzd fields for
devices that don't support discard.

Reported-by: Lukas Czerner <lczerner@redhat.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Acked-by: Mike Snitzer <snitzer@redhat.com>
Cc: stable@kernel.org
Signed-off-by: Jens Axboe <jaxboe@fusionio.com>

authored by

Martin K. Petersen and committed by
Jens Axboe
a934a00a bbdd304c

+9 -4
+2 -1
block/blk-settings.c
··· 120 120 lim->discard_granularity = 0; 121 121 lim->discard_alignment = 0; 122 122 lim->discard_misaligned = 0; 123 - lim->discard_zeroes_data = -1; 123 + lim->discard_zeroes_data = 1; 124 124 lim->logical_block_size = lim->physical_block_size = lim->io_min = 512; 125 125 lim->bounce_pfn = (unsigned long)(BLK_BOUNCE_ANY >> PAGE_SHIFT); 126 126 lim->alignment_offset = 0; ··· 166 166 167 167 blk_set_default_limits(&q->limits); 168 168 blk_queue_max_hw_sectors(q, BLK_SAFE_MAX_SECTORS); 169 + q->limits.discard_zeroes_data = 0; 169 170 170 171 /* 171 172 * by default assume old behaviour and bounce for any highmem page
+2 -1
block/blk-sysfs.c
··· 152 152 153 153 static ssize_t queue_discard_max_show(struct request_queue *q, char *page) 154 154 { 155 - return queue_var_show(q->limits.max_discard_sectors << 9, page); 155 + return sprintf(page, "%llu\n", 156 + (unsigned long long)q->limits.max_discard_sectors << 9); 156 157 } 157 158 158 159 static ssize_t queue_discard_zeroes_data_show(struct request_queue *q, char *page)
+5 -2
include/linux/blkdev.h
··· 257 257 unsigned char misaligned; 258 258 unsigned char discard_misaligned; 259 259 unsigned char cluster; 260 - signed char discard_zeroes_data; 260 + unsigned char discard_zeroes_data; 261 261 }; 262 262 263 263 struct request_queue ··· 1069 1069 { 1070 1070 unsigned int alignment = (sector << 9) & (lim->discard_granularity - 1); 1071 1071 1072 + if (!lim->max_discard_sectors) 1073 + return 0; 1074 + 1072 1075 return (lim->discard_granularity + lim->discard_alignment - alignment) 1073 1076 & (lim->discard_granularity - 1); 1074 1077 } 1075 1078 1076 1079 static inline unsigned int queue_discard_zeroes_data(struct request_queue *q) 1077 1080 { 1078 - if (q->limits.discard_zeroes_data == 1) 1081 + if (q->limits.max_discard_sectors && q->limits.discard_zeroes_data == 1) 1079 1082 return 1; 1080 1083 1081 1084 return 0;