mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00

Delegate to bdev_rw_virt when operating on non-vmalloc memory and use bio_add_vmalloc_chunk to insulate xfs from the details of adding vmalloc memory to a bio. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Damien Le Moal <dlemoal@kernel.org> Reviewed-by: Darrick J. Wong <djwong@kernel.org> Link: https://lore.kernel.org/r/20250507120451.4000627-17-hch@lst.de Signed-off-by: Jens Axboe <axboe@kernel.dk>
53 lines
1.1 KiB
C
53 lines
1.1 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* Copyright (c) 2019 Christoph Hellwig.
|
|
*/
|
|
#include "xfs.h"
|
|
|
|
static inline unsigned int bio_max_vecs(unsigned int count)
|
|
{
|
|
return bio_max_segs(howmany(count, PAGE_SIZE));
|
|
}
|
|
|
|
int
|
|
xfs_rw_bdev(
|
|
struct block_device *bdev,
|
|
sector_t sector,
|
|
unsigned int count,
|
|
char *data,
|
|
enum req_op op)
|
|
|
|
{
|
|
unsigned int done = 0, added;
|
|
int error;
|
|
struct bio *bio;
|
|
|
|
op |= REQ_META | REQ_SYNC;
|
|
if (!is_vmalloc_addr(data))
|
|
return bdev_rw_virt(bdev, sector, data, count, op);
|
|
|
|
bio = bio_alloc(bdev, bio_max_vecs(count), op, GFP_KERNEL);
|
|
bio->bi_iter.bi_sector = sector;
|
|
|
|
do {
|
|
added = bio_add_vmalloc_chunk(bio, data + done, count - done);
|
|
if (!added) {
|
|
struct bio *prev = bio;
|
|
|
|
bio = bio_alloc(prev->bi_bdev,
|
|
bio_max_vecs(count - done),
|
|
prev->bi_opf, GFP_KERNEL);
|
|
bio->bi_iter.bi_sector = bio_end_sector(prev);
|
|
bio_chain(prev, bio);
|
|
submit_bio(prev);
|
|
}
|
|
done += added;
|
|
} while (done < count);
|
|
|
|
error = submit_bio_wait(bio);
|
|
bio_put(bio);
|
|
|
|
if (op == REQ_OP_READ)
|
|
invalidate_kernel_vmap_range(data, count);
|
|
return error;
|
|
}
|