]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
block: Fix discard topology stacking and reporting
authorMartin K. Petersen <martin.petersen@oracle.com>
Wed, 18 May 2011 08:37:35 +0000 (10:37 +0200)
committerGreg Kroah-Hartman <gregkh@suse.de>
Fri, 3 Jun 2011 01:33:44 +0000 (10:33 +0900)
commit a934a00a69e940b126b9bdbf83e630ef5fe43523 upstream.

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>
Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
block/blk-settings.c
block/blk-sysfs.c
include/linux/blkdev.h

index 36c8c1f2af18088fb5fa34f4889d2fead2556600..0aef26e6dc2f4d2cf11d2749912d8d27ca739394 100644 (file)
@@ -120,7 +120,7 @@ void blk_set_default_limits(struct queue_limits *lim)
        lim->discard_granularity = 0;
        lim->discard_alignment = 0;
        lim->discard_misaligned = 0;
-       lim->discard_zeroes_data = -1;
+       lim->discard_zeroes_data = 1;
        lim->logical_block_size = lim->physical_block_size = lim->io_min = 512;
        lim->bounce_pfn = (unsigned long)(BLK_BOUNCE_ANY >> PAGE_SHIFT);
        lim->alignment_offset = 0;
@@ -174,6 +174,7 @@ void blk_queue_make_request(struct request_queue *q, make_request_fn *mfn)
 
        blk_set_default_limits(&q->limits);
        blk_queue_max_hw_sectors(q, BLK_SAFE_MAX_SECTORS);
+       q->limits.discard_zeroes_data = 0;
 
        /*
         * If the caller didn't supply a lock, fall back to our embedded
index 3655e193e60eab31f18712be498c181ab810ba91..629070309f0d3180ce9fa5007049eff7424e5105 100644 (file)
@@ -152,7 +152,8 @@ static ssize_t queue_discard_granularity_show(struct request_queue *q, char *pag
 
 static ssize_t queue_discard_max_show(struct request_queue *q, char *page)
 {
-       return queue_var_show(q->limits.max_discard_sectors << 9, page);
+       return sprintf(page, "%llu\n",
+                      (unsigned long long)q->limits.max_discard_sectors << 9);
 }
 
 static ssize_t queue_discard_zeroes_data_show(struct request_queue *q, char *page)
index d5063e1b55559f0ecfa1e0e757d136510c99b4bf..65661479a232cb0e28fcc119248fa3b99b106500 100644 (file)
@@ -252,7 +252,7 @@ struct queue_limits {
        unsigned char           misaligned;
        unsigned char           discard_misaligned;
        unsigned char           cluster;
-       signed char             discard_zeroes_data;
+       unsigned char           discard_zeroes_data;
 };
 
 struct request_queue
@@ -1032,13 +1032,16 @@ static inline int queue_limit_discard_alignment(struct queue_limits *lim, sector
 {
        unsigned int alignment = (sector << 9) & (lim->discard_granularity - 1);
 
+       if (!lim->max_discard_sectors)
+               return 0;
+
        return (lim->discard_granularity + lim->discard_alignment - alignment)
                & (lim->discard_granularity - 1);
 }
 
 static inline unsigned int queue_discard_zeroes_data(struct request_queue *q)
 {
-       if (q->limits.discard_zeroes_data == 1)
+       if (q->limits.max_discard_sectors && q->limits.discard_zeroes_data == 1)
                return 1;
 
        return 0;