1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2019 Christoph Hellwig. 4 */ 5 #include "xfs.h" 6 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 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 done = 0, added; 22 int error; 23 struct bio *bio; 24 25 op |= REQ_META | REQ_SYNC; 26 if (!is_vmalloc_addr(data)) 27 return bdev_rw_virt(bdev, sector, data, count, op); 28 29 bio = bio_alloc(bdev, bio_max_vecs(count), op, GFP_KERNEL); 30 bio->bi_iter.bi_sector = sector; 31 32 do { 33 added = bio_add_vmalloc_chunk(bio, data + done, count - done); 34 if (!added) { 35 struct bio *prev = bio; 36 37 bio = bio_alloc(prev->bi_bdev, 38 bio_max_vecs(count - done), 39 prev->bi_opf, GFP_KERNEL); 40 bio->bi_iter.bi_sector = bio_end_sector(prev); 41 bio_chain(prev, bio); 42 submit_bio(prev); 43 } 44 done += added; 45 } while (done < count); 46 47 error = submit_bio_wait(bio); 48 bio_put(bio); 49 50 if (op == REQ_OP_READ) 51 invalidate_kernel_vmap_range(data, count); 52 return error; 53 } 54