xref: /linux/drivers/md/dm-pcache/segment.c (revision 6093a688a07da07808f0122f9aa2a3eed250d853)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 #include <linux/dax.h>
3 
4 #include "pcache_internal.h"
5 #include "cache_dev.h"
6 #include "segment.h"
7 
8 int segment_copy_to_bio(struct pcache_segment *segment,
9 		u32 data_off, u32 data_len, struct bio *bio, u32 bio_off)
10 {
11 	struct iov_iter iter;
12 	size_t copied;
13 	void *src;
14 
15 	iov_iter_bvec(&iter, ITER_DEST, &bio->bi_io_vec[bio->bi_iter.bi_idx],
16 			bio_segments(bio), bio->bi_iter.bi_size);
17 	iter.iov_offset = bio->bi_iter.bi_bvec_done;
18 	if (bio_off)
19 		iov_iter_advance(&iter, bio_off);
20 
21 	src = segment->data + data_off;
22 	copied = _copy_mc_to_iter(src, data_len, &iter);
23 	if (copied != data_len)
24 		return -EIO;
25 
26 	return 0;
27 }
28 
29 int segment_copy_from_bio(struct pcache_segment *segment,
30 		u32 data_off, u32 data_len, struct bio *bio, u32 bio_off)
31 {
32 	struct iov_iter iter;
33 	size_t copied;
34 	void *dst;
35 
36 	iov_iter_bvec(&iter, ITER_SOURCE, &bio->bi_io_vec[bio->bi_iter.bi_idx],
37 			bio_segments(bio), bio->bi_iter.bi_size);
38 	iter.iov_offset = bio->bi_iter.bi_bvec_done;
39 	if (bio_off)
40 		iov_iter_advance(&iter, bio_off);
41 
42 	dst = segment->data + data_off;
43 	copied = _copy_from_iter_flushcache(dst, data_len, &iter);
44 	if (copied != data_len)
45 		return -EIO;
46 	pmem_wmb();
47 
48 	return 0;
49 }
50 
51 void pcache_segment_init(struct pcache_cache_dev *cache_dev, struct pcache_segment *segment,
52 		      struct pcache_segment_init_options *options)
53 {
54 	segment->seg_info = options->seg_info;
55 	segment_info_set_type(segment->seg_info, options->type);
56 
57 	segment->cache_dev = cache_dev;
58 	segment->seg_id = options->seg_id;
59 	segment->data_size = PCACHE_SEG_SIZE - options->data_off;
60 	segment->data = CACHE_DEV_SEGMENT(cache_dev, options->seg_id) + options->data_off;
61 }
62