diff options
Diffstat (limited to 'fs/logfs/dev_bdev.c')
| -rw-r--r-- | fs/logfs/dev_bdev.c | 83 | 
1 files changed, 31 insertions, 52 deletions
diff --git a/fs/logfs/dev_bdev.c b/fs/logfs/dev_bdev.c index 92ca6fbe09b..76279e11982 100644 --- a/fs/logfs/dev_bdev.c +++ b/fs/logfs/dev_bdev.c @@ -10,38 +10,27 @@  #include <linux/blkdev.h>  #include <linux/buffer_head.h>  #include <linux/gfp.h> +#include <linux/prefetch.h>  #define PAGE_OFS(ofs) ((ofs) & (PAGE_SIZE-1)) -static void request_complete(struct bio *bio, int err) -{ -	complete((struct completion *)bio->bi_private); -} -  static int sync_request(struct page *page, struct block_device *bdev, int rw)  {  	struct bio bio;  	struct bio_vec bio_vec; -	struct completion complete;  	bio_init(&bio); +	bio.bi_max_vecs = 1;  	bio.bi_io_vec = &bio_vec;  	bio_vec.bv_page = page;  	bio_vec.bv_len = PAGE_SIZE;  	bio_vec.bv_offset = 0;  	bio.bi_vcnt = 1; -	bio.bi_idx = 0; -	bio.bi_size = PAGE_SIZE;  	bio.bi_bdev = bdev; -	bio.bi_sector = page->index * (PAGE_SIZE >> 9); -	init_completion(&complete); -	bio.bi_private = &complete; -	bio.bi_end_io = request_complete; - -	submit_bio(rw, &bio); -	generic_unplug_device(bdev_get_queue(bdev)); -	wait_for_completion(&complete); -	return test_bit(BIO_UPTODATE, &bio.bi_flags) ? 0 : -EIO; +	bio.bi_iter.bi_sector = page->index * (PAGE_SIZE >> 9); +	bio.bi_iter.bi_size = PAGE_SIZE; + +	return submit_bio_wait(rw, &bio);  }  static int bdev_readpage(void *_sb, struct page *page) @@ -67,22 +56,18 @@ static DECLARE_WAIT_QUEUE_HEAD(wq);  static void writeseg_end_io(struct bio *bio, int err)  {  	const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); -	struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1; +	struct bio_vec *bvec; +	int i;  	struct super_block *sb = bio->bi_private;  	struct logfs_super *super = logfs_super(sb); -	struct page *page;  	BUG_ON(!uptodate); /* FIXME: Retry io or write elsewhere */  	BUG_ON(err); -	BUG_ON(bio->bi_vcnt == 0); -	do { -		page = bvec->bv_page; -		if (--bvec >= bio->bi_io_vec) -			prefetchw(&bvec->bv_page->flags); - -		end_page_writeback(page); -		page_cache_release(page); -	} while (bvec >= bio->bi_io_vec); + +	bio_for_each_segment_all(bvec, bio, i) { +		end_page_writeback(bvec->bv_page); +		page_cache_release(bvec->bv_page); +	}  	bio_put(bio);  	if (atomic_dec_and_test(&super->s_pending_writes))  		wake_up(&wq); @@ -95,12 +80,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); @@ -108,10 +92,9 @@ static int __bdev_writeseg(struct super_block *sb, u64 ofs, pgoff_t index,  		if (i >= max_pages) {  			/* Block layer cannot split bios :( */  			bio->bi_vcnt = i; -			bio->bi_idx = 0; -			bio->bi_size = i * PAGE_SIZE; +			bio->bi_iter.bi_size = i * PAGE_SIZE;  			bio->bi_bdev = super->s_bdev; -			bio->bi_sector = ofs >> 9; +			bio->bi_iter.bi_sector = ofs >> 9;  			bio->bi_private = sb;  			bio->bi_end_io = writeseg_end_io;  			atomic_inc(&super->s_pending_writes); @@ -136,10 +119,9 @@ static int __bdev_writeseg(struct super_block *sb, u64 ofs, pgoff_t index,  		unlock_page(page);  	}  	bio->bi_vcnt = nr_pages; -	bio->bi_idx = 0; -	bio->bi_size = nr_pages * PAGE_SIZE; +	bio->bi_iter.bi_size = nr_pages * PAGE_SIZE;  	bio->bi_bdev = super->s_bdev; -	bio->bi_sector = ofs >> 9; +	bio->bi_iter.bi_sector = ofs >> 9;  	bio->bi_private = sb;  	bio->bi_end_io = writeseg_end_io;  	atomic_inc(&super->s_pending_writes); @@ -168,7 +150,6 @@ static void bdev_writeseg(struct super_block *sb, u64 ofs, size_t len)  	}  	len = PAGE_ALIGN(len);  	__bdev_writeseg(sb, ofs, ofs >> PAGE_SHIFT, len >> PAGE_SHIFT); -	generic_unplug_device(bdev_get_queue(logfs_super(sb)->s_bdev));  } @@ -191,12 +172,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); @@ -204,10 +184,9 @@ static int do_erase(struct super_block *sb, u64 ofs, pgoff_t index,  		if (i >= max_pages) {  			/* Block layer cannot split bios :( */  			bio->bi_vcnt = i; -			bio->bi_idx = 0; -			bio->bi_size = i * PAGE_SIZE; +			bio->bi_iter.bi_size = i * PAGE_SIZE;  			bio->bi_bdev = super->s_bdev; -			bio->bi_sector = ofs >> 9; +			bio->bi_iter.bi_sector = ofs >> 9;  			bio->bi_private = sb;  			bio->bi_end_io = erase_end_io;  			atomic_inc(&super->s_pending_writes); @@ -226,10 +205,9 @@ static int do_erase(struct super_block *sb, u64 ofs, pgoff_t index,  		bio->bi_io_vec[i].bv_offset = 0;  	}  	bio->bi_vcnt = nr_pages; -	bio->bi_idx = 0; -	bio->bi_size = nr_pages * PAGE_SIZE; +	bio->bi_iter.bi_size = nr_pages * PAGE_SIZE;  	bio->bi_bdev = super->s_bdev; -	bio->bi_sector = ofs >> 9; +	bio->bi_iter.bi_sector = ofs >> 9;  	bio->bi_private = sb;  	bio->bi_end_io = erase_end_io;  	atomic_inc(&super->s_pending_writes); @@ -300,7 +278,7 @@ static int bdev_write_sb(struct super_block *sb, struct page *page)  static void bdev_put_device(struct logfs_super *s)  { -	close_bdev_exclusive(s->s_bdev, FMODE_READ|FMODE_WRITE); +	blkdev_put(s->s_bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);  }  static int bdev_can_write_buf(struct super_block *sb, u64 ofs) @@ -325,13 +303,14 @@ int logfs_get_sb_bdev(struct logfs_super *p, struct file_system_type *type,  {  	struct block_device *bdev; -	bdev = open_bdev_exclusive(devname, FMODE_READ|FMODE_WRITE, type); +	bdev = blkdev_get_by_path(devname, FMODE_READ|FMODE_WRITE|FMODE_EXCL, +				  type);  	if (IS_ERR(bdev))  		return PTR_ERR(bdev);  	if (MAJOR(bdev->bd_dev) == MTD_BLOCK_MAJOR) {  		int mtdnr = MINOR(bdev->bd_dev); -		close_bdev_exclusive(bdev, FMODE_READ|FMODE_WRITE); +		blkdev_put(bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL);  		return logfs_get_sb_mtd(p, mtdnr);  	}  | 
