logfs: query block device for number of pages to send with bio
authorPrasad Joshi <prasadjoshi.linux@gmail.com>
Mon, 23 Jul 2012 05:02:11 +0000 (10:32 +0530)
committerPrasad Joshi <prasadjoshi.linux@gmail.com>
Mon, 23 Jul 2012 05:02:11 +0000 (10:32 +0530)
The block device driver puts a limit on maximum number of pages that
can be sent with the bio. Not all block devices can handle
BIO_MAX_PAGES number of pages in bio. Specifically the virtio-blk
diriver limits it to 126. When the LogFS file system was excersized in
KVM, the following bug from do_virtblk_request() was observed

static void do_virtblk_request(struct request_queue *q)
{
....
....
while ((req = blk_peek_request(q)) != NULL) {
BUG_ON(req->nr_phys_segments + 2 > vblk->sg_elems);
....
....
}
....
}

The patch fixes the problem by querring the maximum number of pages in
bio allowed from block device driver and then using those many pages
during submit_bio.

Signed-off-by: Prasad Joshi <prasadjoshi.linux@gmail.com>
fs/logfs/dev_bdev.c

index ea29df36893d3b12069689a07533e7946c7b751a..e784a217b50067919ad3ebffe559b3552b58a9bc 100644 (file)
@@ -96,12 +96,11 @@ static int __bdev_writeseg(struct super_block *sb, u64 ofs, pgoff_t index,
        struct address_space *mapping = super->s_mapping_inode->i_mapping;
        struct bio *bio;
        struct page *page;
-       struct request_queue *q = bdev_get_queue(sb->s_bdev);
-       unsigned int max_pages = queue_max_hw_sectors(q) >> (PAGE_SHIFT - 9);
+       unsigned int max_pages;
        int i;
 
-       if (max_pages > BIO_MAX_PAGES)
-               max_pages = BIO_MAX_PAGES;
+       max_pages = min(nr_pages, (size_t) bio_get_nr_vecs(super->s_bdev));
+
        bio = bio_alloc(GFP_NOFS, max_pages);
        BUG_ON(!bio);
 
@@ -191,12 +190,11 @@ static int do_erase(struct super_block *sb, u64 ofs, pgoff_t index,
 {
        struct logfs_super *super = logfs_super(sb);
        struct bio *bio;
-       struct request_queue *q = bdev_get_queue(sb->s_bdev);
-       unsigned int max_pages = queue_max_hw_sectors(q) >> (PAGE_SHIFT - 9);
+       unsigned int max_pages;
        int i;
 
-       if (max_pages > BIO_MAX_PAGES)
-               max_pages = BIO_MAX_PAGES;
+       max_pages = min(nr_pages, (size_t) bio_get_nr_vecs(super->s_bdev));
+
        bio = bio_alloc(GFP_NOFS, max_pages);
        BUG_ON(!bio);