• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  // SPDX-License-Identifier: GPL-2.0
2  /*
3   * Copyright (c) 2019 Christoph Hellwig.
4   */
5  #include "xfs.h"
6  
bio_max_vecs(unsigned int count)7  static inline unsigned int bio_max_vecs(unsigned int count)
8  {
9  	return bio_max_segs(howmany(count, PAGE_SIZE));
10  }
11  
12  int
xfs_rw_bdev(struct block_device * bdev,sector_t sector,unsigned int count,char * data,enum req_op op)13  xfs_rw_bdev(
14  	struct block_device	*bdev,
15  	sector_t		sector,
16  	unsigned int		count,
17  	char			*data,
18  	enum req_op		op)
19  
20  {
21  	unsigned int		is_vmalloc = is_vmalloc_addr(data);
22  	unsigned int		left = count;
23  	int			error;
24  	struct bio		*bio;
25  
26  	if (is_vmalloc && op == REQ_OP_WRITE)
27  		flush_kernel_vmap_range(data, count);
28  
29  	bio = bio_alloc(bdev, bio_max_vecs(left), op | REQ_META | REQ_SYNC,
30  			GFP_KERNEL);
31  	bio->bi_iter.bi_sector = sector;
32  
33  	do {
34  		struct page	*page = kmem_to_page(data);
35  		unsigned int	off = offset_in_page(data);
36  		unsigned int	len = min_t(unsigned, left, PAGE_SIZE - off);
37  
38  		while (bio_add_page(bio, page, len, off) != len) {
39  			struct bio	*prev = bio;
40  
41  			bio = bio_alloc(prev->bi_bdev, bio_max_vecs(left),
42  					prev->bi_opf, GFP_KERNEL);
43  			bio->bi_iter.bi_sector = bio_end_sector(prev);
44  			bio_chain(prev, bio);
45  
46  			submit_bio(prev);
47  		}
48  
49  		data += len;
50  		left -= len;
51  	} while (left > 0);
52  
53  	error = submit_bio_wait(bio);
54  	bio_put(bio);
55  
56  	if (is_vmalloc && op == REQ_OP_READ)
57  		invalidate_kernel_vmap_range(data, count);
58  	return error;
59  }
60