Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright (c) 2019 Christoph Hellwig.
0004  */
0005 #include "xfs.h"
0006 
0007 static inline unsigned int bio_max_vecs(unsigned int count)
0008 {
0009     return bio_max_segs(howmany(count, PAGE_SIZE));
0010 }
0011 
0012 int
0013 xfs_rw_bdev(
0014     struct block_device *bdev,
0015     sector_t        sector,
0016     unsigned int        count,
0017     char            *data,
0018     enum req_op     op)
0019 
0020 {
0021     unsigned int        is_vmalloc = is_vmalloc_addr(data);
0022     unsigned int        left = count;
0023     int         error;
0024     struct bio      *bio;
0025 
0026     if (is_vmalloc && op == REQ_OP_WRITE)
0027         flush_kernel_vmap_range(data, count);
0028 
0029     bio = bio_alloc(bdev, bio_max_vecs(left), op | REQ_META | REQ_SYNC,
0030             GFP_KERNEL);
0031     bio->bi_iter.bi_sector = sector;
0032 
0033     do {
0034         struct page *page = kmem_to_page(data);
0035         unsigned int    off = offset_in_page(data);
0036         unsigned int    len = min_t(unsigned, left, PAGE_SIZE - off);
0037 
0038         while (bio_add_page(bio, page, len, off) != len) {
0039             struct bio  *prev = bio;
0040 
0041             bio = bio_alloc(prev->bi_bdev, bio_max_vecs(left),
0042                     prev->bi_opf, GFP_KERNEL);
0043             bio->bi_iter.bi_sector = bio_end_sector(prev);
0044             bio_chain(prev, bio);
0045 
0046             submit_bio(prev);
0047         }
0048 
0049         data += len;
0050         left -= len;
0051     } while (left > 0);
0052 
0053     error = submit_bio_wait(bio);
0054     bio_put(bio);
0055 
0056     if (is_vmalloc && op == REQ_OP_READ)
0057         invalidate_kernel_vmap_range(data, count);
0058     return error;
0059 }