diff options
author | Martin K. Petersen <martin.petersen@oracle.com> | 2009-12-03 03:24:48 -0500 |
---|---|---|
committer | Jens Axboe <jens.axboe@oracle.com> | 2009-12-03 03:24:48 -0500 |
commit | 98262f2762f0067375f83824d81ea929e37e6bfe (patch) | |
tree | a26618d5c305eed975501c80cb02bc0f1b6e4524 /block | |
parent | 464191c65b85a8ec68a6e1a6293af625287c807e (diff) |
block: Allow devices to indicate whether discarded blocks are zeroed
The discard ioctl is used by mkfs utilities to clear a block device
prior to putting metadata down. However, not all devices return zeroed
blocks after a discard. Some drives return stale data, potentially
containing old superblocks. It is therefore important to know whether
discarded blocks are properly zeroed.
Both ATA and SCSI drives have configuration bits that indicate whether
zeroes are returned after a discard operation. Implement a block level
interface that allows this information to be bubbled up the stack and
queried via a new block device ioctl.
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'block')
-rw-r--r-- | block/blk-settings.c | 2 | ||||
-rw-r--r-- | block/blk-sysfs.c | 11 | ||||
-rw-r--r-- | block/compat_ioctl.c | 2 | ||||
-rw-r--r-- | block/ioctl.c | 2 |
4 files changed, 17 insertions, 0 deletions
diff --git a/block/blk-settings.c b/block/blk-settings.c index 1ebc1fdb9144..dd1f1e0e196f 100644 --- a/block/blk-settings.c +++ b/block/blk-settings.c | |||
@@ -101,6 +101,7 @@ void blk_set_default_limits(struct queue_limits *lim) | |||
101 | lim->discard_granularity = 0; | 101 | lim->discard_granularity = 0; |
102 | lim->discard_alignment = 0; | 102 | lim->discard_alignment = 0; |
103 | lim->discard_misaligned = 0; | 103 | lim->discard_misaligned = 0; |
104 | lim->discard_zeroes_data = -1; | ||
104 | lim->logical_block_size = lim->physical_block_size = lim->io_min = 512; | 105 | lim->logical_block_size = lim->physical_block_size = lim->io_min = 512; |
105 | lim->bounce_pfn = (unsigned long)(BLK_BOUNCE_ANY >> PAGE_SHIFT); | 106 | lim->bounce_pfn = (unsigned long)(BLK_BOUNCE_ANY >> PAGE_SHIFT); |
106 | lim->alignment_offset = 0; | 107 | lim->alignment_offset = 0; |
@@ -544,6 +545,7 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b, | |||
544 | 545 | ||
545 | t->io_min = max(t->io_min, b->io_min); | 546 | t->io_min = max(t->io_min, b->io_min); |
546 | t->no_cluster |= b->no_cluster; | 547 | t->no_cluster |= b->no_cluster; |
548 | t->discard_zeroes_data &= b->discard_zeroes_data; | ||
547 | 549 | ||
548 | /* Bottom device offset aligned? */ | 550 | /* Bottom device offset aligned? */ |
549 | if (offset && | 551 | if (offset && |
diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c index 3147145edc15..8606c9543fdd 100644 --- a/block/blk-sysfs.c +++ b/block/blk-sysfs.c | |||
@@ -136,6 +136,11 @@ static ssize_t queue_discard_max_show(struct request_queue *q, char *page) | |||
136 | return queue_var_show(q->limits.max_discard_sectors << 9, page); | 136 | return queue_var_show(q->limits.max_discard_sectors << 9, page); |
137 | } | 137 | } |
138 | 138 | ||
139 | static ssize_t queue_discard_zeroes_data_show(struct request_queue *q, char *page) | ||
140 | { | ||
141 | return queue_var_show(queue_discard_zeroes_data(q), page); | ||
142 | } | ||
143 | |||
139 | static ssize_t | 144 | static ssize_t |
140 | queue_max_sectors_store(struct request_queue *q, const char *page, size_t count) | 145 | queue_max_sectors_store(struct request_queue *q, const char *page, size_t count) |
141 | { | 146 | { |
@@ -313,6 +318,11 @@ static struct queue_sysfs_entry queue_discard_max_entry = { | |||
313 | .show = queue_discard_max_show, | 318 | .show = queue_discard_max_show, |
314 | }; | 319 | }; |
315 | 320 | ||
321 | static struct queue_sysfs_entry queue_discard_zeroes_data_entry = { | ||
322 | .attr = {.name = "discard_zeroes_data", .mode = S_IRUGO }, | ||
323 | .show = queue_discard_zeroes_data_show, | ||
324 | }; | ||
325 | |||
316 | static struct queue_sysfs_entry queue_nonrot_entry = { | 326 | static struct queue_sysfs_entry queue_nonrot_entry = { |
317 | .attr = {.name = "rotational", .mode = S_IRUGO | S_IWUSR }, | 327 | .attr = {.name = "rotational", .mode = S_IRUGO | S_IWUSR }, |
318 | .show = queue_nonrot_show, | 328 | .show = queue_nonrot_show, |
@@ -350,6 +360,7 @@ static struct attribute *default_attrs[] = { | |||
350 | &queue_io_opt_entry.attr, | 360 | &queue_io_opt_entry.attr, |
351 | &queue_discard_granularity_entry.attr, | 361 | &queue_discard_granularity_entry.attr, |
352 | &queue_discard_max_entry.attr, | 362 | &queue_discard_max_entry.attr, |
363 | &queue_discard_zeroes_data_entry.attr, | ||
353 | &queue_nonrot_entry.attr, | 364 | &queue_nonrot_entry.attr, |
354 | &queue_nomerges_entry.attr, | 365 | &queue_nomerges_entry.attr, |
355 | &queue_rq_affinity_entry.attr, | 366 | &queue_rq_affinity_entry.attr, |
diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c index 9bd086c1a4d5..4eb8e9ea4af5 100644 --- a/block/compat_ioctl.c +++ b/block/compat_ioctl.c | |||
@@ -747,6 +747,8 @@ long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg) | |||
747 | return compat_put_uint(arg, bdev_io_opt(bdev)); | 747 | return compat_put_uint(arg, bdev_io_opt(bdev)); |
748 | case BLKALIGNOFF: | 748 | case BLKALIGNOFF: |
749 | return compat_put_int(arg, bdev_alignment_offset(bdev)); | 749 | return compat_put_int(arg, bdev_alignment_offset(bdev)); |
750 | case BLKDISCARDZEROES: | ||
751 | return compat_put_uint(arg, bdev_discard_zeroes_data(bdev)); | ||
750 | case BLKFLSBUF: | 752 | case BLKFLSBUF: |
751 | case BLKROSET: | 753 | case BLKROSET: |
752 | case BLKDISCARD: | 754 | case BLKDISCARD: |
diff --git a/block/ioctl.c b/block/ioctl.c index 1f4d1de12b09..be48ea51faee 100644 --- a/block/ioctl.c +++ b/block/ioctl.c | |||
@@ -280,6 +280,8 @@ int blkdev_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, | |||
280 | return put_uint(arg, bdev_io_opt(bdev)); | 280 | return put_uint(arg, bdev_io_opt(bdev)); |
281 | case BLKALIGNOFF: | 281 | case BLKALIGNOFF: |
282 | return put_int(arg, bdev_alignment_offset(bdev)); | 282 | return put_int(arg, bdev_alignment_offset(bdev)); |
283 | case BLKDISCARDZEROES: | ||
284 | return put_uint(arg, bdev_discard_zeroes_data(bdev)); | ||
283 | case BLKSECTGET: | 285 | case BLKSECTGET: |
284 | return put_ushort(arg, queue_max_sectors(bdev_get_queue(bdev))); | 286 | return put_ushort(arg, queue_max_sectors(bdev_get_queue(bdev))); |
285 | case BLKRASET: | 287 | case BLKRASET: |