Line data Source code
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 11953044 : return bio_max_segs(howmany(count, PAGE_SIZE)); 10 : } 11 : 12 : int 13 11953044 : 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 11953044 : unsigned int is_vmalloc = is_vmalloc_addr(data); 22 11953044 : unsigned int left = count; 23 11953044 : int error; 24 11953044 : struct bio *bio; 25 : 26 11953044 : if (is_vmalloc && op == REQ_OP_WRITE) 27 : flush_kernel_vmap_range(data, count); 28 : 29 11953044 : bio = bio_alloc(bdev, bio_max_vecs(left), op | REQ_META | REQ_SYNC, 30 : GFP_KERNEL); 31 11953044 : bio->bi_iter.bi_sector = sector; 32 : 33 13191182 : do { 34 13191182 : struct page *page = kmem_to_page(data); 35 13191182 : unsigned int off = offset_in_page(data); 36 13191182 : unsigned int len = min_t(unsigned, left, PAGE_SIZE - off); 37 : 38 13191182 : while (bio_add_page(bio, page, len, off) != len) { 39 0 : struct bio *prev = bio; 40 : 41 0 : bio = bio_alloc(prev->bi_bdev, bio_max_vecs(left), 42 : prev->bi_opf, GFP_KERNEL); 43 0 : bio->bi_iter.bi_sector = bio_end_sector(prev); 44 0 : bio_chain(prev, bio); 45 : 46 0 : submit_bio(prev); 47 : } 48 : 49 13191182 : data += len; 50 13191182 : left -= len; 51 13191182 : } while (left > 0); 52 : 53 11953044 : error = submit_bio_wait(bio); 54 11953044 : bio_put(bio); 55 : 56 11953044 : if (is_vmalloc && op == REQ_OP_READ) 57 : invalidate_kernel_vmap_range(data, count); 58 11953044 : return error; 59 : }