|
3 | 3 | * Copyright (C) 2010 Red Hat, Inc. |
4 | 4 | * Copyright (C) 2016-2023 Christoph Hellwig. |
5 | 5 | */ |
| 6 | +#include <linux/bio-integrity.h> |
6 | 7 | #include <linux/iomap.h> |
7 | 8 | #include <linux/pagemap.h> |
8 | 9 | #include "internal.h" |
9 | 10 | #include "trace.h" |
10 | 11 |
|
11 | | -static void iomap_read_end_io(struct bio *bio) |
| 12 | +static u32 __iomap_read_end_io(struct bio *bio, int error) |
12 | 13 | { |
13 | | - int error = blk_status_to_errno(bio->bi_status); |
14 | 14 | struct folio_iter fi; |
| 15 | + u32 folio_count = 0; |
15 | 16 |
|
16 | | - bio_for_each_folio_all(fi, bio) |
| 17 | + bio_for_each_folio_all(fi, bio) { |
17 | 18 | iomap_finish_folio_read(fi.folio, fi.offset, fi.length, error); |
| 19 | + folio_count++; |
| 20 | + } |
| 21 | + if (bio_integrity(bio)) |
| 22 | + fs_bio_integrity_free(bio); |
18 | 23 | bio_put(bio); |
| 24 | + return folio_count; |
| 25 | +} |
| 26 | + |
| 27 | +static void iomap_read_end_io(struct bio *bio) |
| 28 | +{ |
| 29 | + __iomap_read_end_io(bio, blk_status_to_errno(bio->bi_status)); |
19 | 30 | } |
20 | 31 |
|
21 | | -static void iomap_bio_submit_read(struct iomap_read_folio_ctx *ctx) |
| 32 | +u32 iomap_finish_ioend_buffered_read(struct iomap_ioend *ioend) |
| 33 | +{ |
| 34 | + return __iomap_read_end_io(&ioend->io_bio, ioend->io_error); |
| 35 | +} |
| 36 | + |
| 37 | +static void iomap_bio_submit_read(const struct iomap_iter *iter, |
| 38 | + struct iomap_read_folio_ctx *ctx) |
22 | 39 | { |
23 | 40 | struct bio *bio = ctx->read_ctx; |
24 | 41 |
|
25 | | - if (bio) |
26 | | - submit_bio(bio); |
| 42 | + if (iter->iomap.flags & IOMAP_F_INTEGRITY) |
| 43 | + fs_bio_integrity_alloc(bio); |
| 44 | + submit_bio(bio); |
| 45 | +} |
| 46 | + |
| 47 | +static struct bio_set *iomap_read_bio_set(struct iomap_read_folio_ctx *ctx) |
| 48 | +{ |
| 49 | + if (ctx->ops && ctx->ops->bio_set) |
| 50 | + return ctx->ops->bio_set; |
| 51 | + return &fs_bio_set; |
| 52 | +} |
| 53 | + |
| 54 | +static void iomap_read_alloc_bio(const struct iomap_iter *iter, |
| 55 | + struct iomap_read_folio_ctx *ctx, size_t plen) |
| 56 | +{ |
| 57 | + const struct iomap *iomap = &iter->iomap; |
| 58 | + unsigned int nr_vecs = DIV_ROUND_UP(iomap_length(iter), PAGE_SIZE); |
| 59 | + struct bio_set *bio_set = iomap_read_bio_set(ctx); |
| 60 | + struct folio *folio = ctx->cur_folio; |
| 61 | + gfp_t gfp = mapping_gfp_constraint(folio->mapping, GFP_KERNEL); |
| 62 | + gfp_t orig_gfp = gfp; |
| 63 | + struct bio *bio; |
| 64 | + |
| 65 | + /* Submit the existing range if there was one. */ |
| 66 | + if (ctx->read_ctx) |
| 67 | + ctx->ops->submit_read(iter, ctx); |
| 68 | + |
| 69 | + /* Same as readahead_gfp_mask: */ |
| 70 | + if (ctx->rac) |
| 71 | + gfp |= __GFP_NORETRY | __GFP_NOWARN; |
| 72 | + |
| 73 | + /* |
| 74 | + * If the bio_alloc fails, try it again for a single page to avoid |
| 75 | + * having to deal with partial page reads. This emulates what |
| 76 | + * do_mpage_read_folio does. |
| 77 | + */ |
| 78 | + bio = bio_alloc_bioset(iomap->bdev, bio_max_segs(nr_vecs), REQ_OP_READ, |
| 79 | + gfp, bio_set); |
| 80 | + if (!bio) |
| 81 | + bio = bio_alloc_bioset(iomap->bdev, 1, REQ_OP_READ, orig_gfp, |
| 82 | + bio_set); |
| 83 | + if (ctx->rac) |
| 84 | + bio->bi_opf |= REQ_RAHEAD; |
| 85 | + bio->bi_iter.bi_sector = iomap_sector(iomap, iter->pos); |
| 86 | + bio->bi_end_io = iomap_read_end_io; |
| 87 | + bio_add_folio_nofail(bio, folio, plen, |
| 88 | + offset_in_folio(folio, iter->pos)); |
| 89 | + ctx->read_ctx = bio; |
| 90 | + ctx->read_ctx_file_offset = iter->pos; |
27 | 91 | } |
28 | 92 |
|
29 | | -static int iomap_bio_read_folio_range(const struct iomap_iter *iter, |
| 93 | +int iomap_bio_read_folio_range(const struct iomap_iter *iter, |
30 | 94 | struct iomap_read_folio_ctx *ctx, size_t plen) |
31 | 95 | { |
32 | 96 | struct folio *folio = ctx->cur_folio; |
33 | | - const struct iomap *iomap = &iter->iomap; |
34 | | - loff_t pos = iter->pos; |
35 | | - size_t poff = offset_in_folio(folio, pos); |
36 | | - loff_t length = iomap_length(iter); |
37 | | - sector_t sector; |
38 | 97 | struct bio *bio = ctx->read_ctx; |
39 | 98 |
|
40 | | - sector = iomap_sector(iomap, pos); |
41 | | - if (!bio || bio_end_sector(bio) != sector || |
42 | | - !bio_add_folio(bio, folio, plen, poff)) { |
43 | | - gfp_t gfp = mapping_gfp_constraint(folio->mapping, GFP_KERNEL); |
44 | | - gfp_t orig_gfp = gfp; |
45 | | - unsigned int nr_vecs = DIV_ROUND_UP(length, PAGE_SIZE); |
46 | | - |
47 | | - if (bio) |
48 | | - submit_bio(bio); |
49 | | - |
50 | | - if (ctx->rac) /* same as readahead_gfp_mask */ |
51 | | - gfp |= __GFP_NORETRY | __GFP_NOWARN; |
52 | | - bio = bio_alloc(iomap->bdev, bio_max_segs(nr_vecs), REQ_OP_READ, |
53 | | - gfp); |
54 | | - /* |
55 | | - * If the bio_alloc fails, try it again for a single page to |
56 | | - * avoid having to deal with partial page reads. This emulates |
57 | | - * what do_mpage_read_folio does. |
58 | | - */ |
59 | | - if (!bio) |
60 | | - bio = bio_alloc(iomap->bdev, 1, REQ_OP_READ, orig_gfp); |
61 | | - if (ctx->rac) |
62 | | - bio->bi_opf |= REQ_RAHEAD; |
63 | | - bio->bi_iter.bi_sector = sector; |
64 | | - bio->bi_end_io = iomap_read_end_io; |
65 | | - bio_add_folio_nofail(bio, folio, plen, poff); |
66 | | - ctx->read_ctx = bio; |
67 | | - } |
| 99 | + if (!bio || |
| 100 | + bio_end_sector(bio) != iomap_sector(&iter->iomap, iter->pos) || |
| 101 | + bio->bi_iter.bi_size > iomap_max_bio_size(&iter->iomap) - plen || |
| 102 | + !bio_add_folio(bio, folio, plen, offset_in_folio(folio, iter->pos))) |
| 103 | + iomap_read_alloc_bio(iter, ctx, plen); |
68 | 104 | return 0; |
69 | 105 | } |
| 106 | +EXPORT_SYMBOL_GPL(iomap_bio_read_folio_range); |
70 | 107 |
|
71 | 108 | const struct iomap_read_ops iomap_bio_read_ops = { |
72 | | - .read_folio_range = iomap_bio_read_folio_range, |
73 | | - .submit_read = iomap_bio_submit_read, |
| 109 | + .read_folio_range = iomap_bio_read_folio_range, |
| 110 | + .submit_read = iomap_bio_submit_read, |
74 | 111 | }; |
75 | 112 | EXPORT_SYMBOL_GPL(iomap_bio_read_ops); |
76 | 113 |
|
77 | 114 | int iomap_bio_read_folio_range_sync(const struct iomap_iter *iter, |
78 | 115 | struct folio *folio, loff_t pos, size_t len) |
79 | 116 | { |
80 | 117 | const struct iomap *srcmap = iomap_iter_srcmap(iter); |
| 118 | + sector_t sector = iomap_sector(srcmap, pos); |
81 | 119 | struct bio_vec bvec; |
82 | 120 | struct bio bio; |
| 121 | + int error; |
83 | 122 |
|
84 | 123 | bio_init(&bio, srcmap->bdev, &bvec, 1, REQ_OP_READ); |
85 | | - bio.bi_iter.bi_sector = iomap_sector(srcmap, pos); |
| 124 | + bio.bi_iter.bi_sector = sector; |
86 | 125 | bio_add_folio_nofail(&bio, folio, len, offset_in_folio(folio, pos)); |
87 | | - return submit_bio_wait(&bio); |
| 126 | + if (srcmap->flags & IOMAP_F_INTEGRITY) |
| 127 | + fs_bio_integrity_alloc(&bio); |
| 128 | + error = submit_bio_wait(&bio); |
| 129 | + if (srcmap->flags & IOMAP_F_INTEGRITY) { |
| 130 | + if (!error) |
| 131 | + error = fs_bio_integrity_verify(&bio, sector, len); |
| 132 | + fs_bio_integrity_free(&bio); |
| 133 | + } |
| 134 | + return error; |
88 | 135 | } |
0 commit comments