xref: /openbmc/linux/fs/xfs/xfs_bio_io.c (revision d03025ae)
16ad5b325SChristoph Hellwig // SPDX-License-Identifier: GPL-2.0
26ad5b325SChristoph Hellwig /*
36ad5b325SChristoph Hellwig  * Copyright (c) 2019 Christoph Hellwig.
46ad5b325SChristoph Hellwig  */
56ad5b325SChristoph Hellwig #include "xfs.h"
66ad5b325SChristoph Hellwig 
bio_max_vecs(unsigned int count)76ad5b325SChristoph Hellwig static inline unsigned int bio_max_vecs(unsigned int count)
86ad5b325SChristoph Hellwig {
95f7136dbSMatthew Wilcox (Oracle) 	return bio_max_segs(howmany(count, PAGE_SIZE));
106ad5b325SChristoph Hellwig }
116ad5b325SChristoph Hellwig 
126ad5b325SChristoph Hellwig int
xfs_rw_bdev(struct block_device * bdev,sector_t sector,unsigned int count,char * data,enum req_op op)136ad5b325SChristoph Hellwig xfs_rw_bdev(
146ad5b325SChristoph Hellwig 	struct block_device	*bdev,
156ad5b325SChristoph Hellwig 	sector_t		sector,
166ad5b325SChristoph Hellwig 	unsigned int		count,
176ad5b325SChristoph Hellwig 	char			*data,
18*d03025aeSBart Van Assche 	enum req_op		op)
196ad5b325SChristoph Hellwig 
206ad5b325SChristoph Hellwig {
216ad5b325SChristoph Hellwig 	unsigned int		is_vmalloc = is_vmalloc_addr(data);
226ad5b325SChristoph Hellwig 	unsigned int		left = count;
236ad5b325SChristoph Hellwig 	int			error;
246ad5b325SChristoph Hellwig 	struct bio		*bio;
256ad5b325SChristoph Hellwig 
266ad5b325SChristoph Hellwig 	if (is_vmalloc && op == REQ_OP_WRITE)
276ad5b325SChristoph Hellwig 		flush_kernel_vmap_range(data, count);
286ad5b325SChristoph Hellwig 
2907888c66SChristoph Hellwig 	bio = bio_alloc(bdev, bio_max_vecs(left), op | REQ_META | REQ_SYNC,
3007888c66SChristoph Hellwig 			GFP_KERNEL);
316ad5b325SChristoph Hellwig 	bio->bi_iter.bi_sector = sector;
326ad5b325SChristoph Hellwig 
336ad5b325SChristoph Hellwig 	do {
346ad5b325SChristoph Hellwig 		struct page	*page = kmem_to_page(data);
356ad5b325SChristoph Hellwig 		unsigned int	off = offset_in_page(data);
366ad5b325SChristoph Hellwig 		unsigned int	len = min_t(unsigned, left, PAGE_SIZE - off);
376ad5b325SChristoph Hellwig 
386ad5b325SChristoph Hellwig 		while (bio_add_page(bio, page, len, off) != len) {
396ad5b325SChristoph Hellwig 			struct bio	*prev = bio;
406ad5b325SChristoph Hellwig 
4107888c66SChristoph Hellwig 			bio = bio_alloc(prev->bi_bdev, bio_max_vecs(left),
4207888c66SChristoph Hellwig 					prev->bi_opf, GFP_KERNEL);
436ad5b325SChristoph Hellwig 			bio->bi_iter.bi_sector = bio_end_sector(prev);
44488ca3d8SChristoph Hellwig 			bio_chain(prev, bio);
456ad5b325SChristoph Hellwig 
466ad5b325SChristoph Hellwig 			submit_bio(prev);
476ad5b325SChristoph Hellwig 		}
486ad5b325SChristoph Hellwig 
496ad5b325SChristoph Hellwig 		data += len;
506ad5b325SChristoph Hellwig 		left -= len;
516ad5b325SChristoph Hellwig 	} while (left > 0);
526ad5b325SChristoph Hellwig 
536ad5b325SChristoph Hellwig 	error = submit_bio_wait(bio);
546ad5b325SChristoph Hellwig 	bio_put(bio);
556ad5b325SChristoph Hellwig 
566ad5b325SChristoph Hellwig 	if (is_vmalloc && op == REQ_OP_READ)
576ad5b325SChristoph Hellwig 		invalidate_kernel_vmap_range(data, count);
586ad5b325SChristoph Hellwig 	return error;
596ad5b325SChristoph Hellwig }
60