Whamcloud - gitweb
5b4ba4344560d2947c0d2d79ca5d21fa7c9168f8
[fs/lustre-release.git] / lustre / kernel_patches / patches / block-integrity-allow-optional-integrity-functions-rhel8.patch
1 This adds optional integrity functions for given bio, they are
2 passed to bio_integrity_prep and initialized in
3 bio_integrity_payload.
4 The optional integrity generate/verify functions take priority
5 over the ones registered on the block device.
6
7 It brings flexibility to bio integrity handling. e.g. a network
8 filesystem with integrity support would have integrity
9 generation happen on the clients, and send them over the wire.
10 On the server side once we receive the integrity bits and pass
11 the network layer checksums we would merely pass it on to the
12 block devices have integrity support, so we don't have to
13 calculate the integrity again.
14 Verification shares the same principle: on the server we just
15 copy the integrity bits from the device and send them through
16 the wire, then the verification happens on the clients.
17
18 Index: linux-4.18.0-80.el8/block/bio-integrity.c
19 ===================================================================
20 --- linux-4.18.0-80.el8.orig/block/bio-integrity.c
21 +++ linux-4.18.0-80.el8/block/bio-integrity.c
22 @@ -39,7 +39,7 @@ void blk_flush_integrity(void)
23  }
24  
25  /**
26 - * bio_integrity_alloc - Allocate integrity payload and attach it to bio
27 + * bio_integrity_alloc_fn - Allocate integrity payload and attach it to bio
28   * @bio:       bio to attach integrity metadata to
29   * @gfp_mask:  Memory allocation mask
30   * @nr_vecs:   Number of integrity metadata scatter-gather elements
31 @@ -48,9 +48,11 @@ void blk_flush_integrity(void)
32   * metadata.  nr_vecs specifies the maximum number of pages containing
33   * integrity metadata that can be attached.
34   */
35 -struct bio_integrity_payload *bio_integrity_alloc(struct bio *bio,
36 -                                                 gfp_t gfp_mask,
37 -                                                 unsigned int nr_vecs)
38 +struct bio_integrity_payload *bio_integrity_alloc_fn(struct bio *bio,
39 +                                                    gfp_t gfp_mask,
40 +                                                    unsigned int nr_vecs,
41 +                                                    integrity_processing_fn *generate_fn,
42 +                                                    integrity_processing_fn *verify_fn)
43  {
44         struct bio_integrity_payload *bip;
45         struct bio_set *bs = bio->bi_pool;
46 @@ -85,6 +87,8 @@ struct bio_integrity_payload *bio_integr
47         }
48  
49         bip->bip_bio = bio;
50 +       bip->bip_generate_fn = generate_fn;
51 +       bip->bip_verify_fn = verify_fn;
52         bio->bi_integrity = bip;
53         bio->bi_opf |= REQ_INTEGRITY;
54  
55 @@ -93,6 +97,13 @@ err:
56         mempool_free(bip, &bs->bio_integrity_pool);
57         return ERR_PTR(-ENOMEM);
58  }
59 +EXPORT_SYMBOL(bio_integrity_alloc_fn);
60 +
61 +struct bio_integrity_payload *bio_integrity_alloc(struct bio *bio, gfp_t gfp,
62 +                                                 unsigned int nr)
63 +{
64 +       return bio_integrity_alloc_fn(bio, gfp, nr, NULL, NULL);
65 +}
66  EXPORT_SYMBOL(bio_integrity_alloc);
67  
68  /**
69 @@ -213,7 +224,7 @@ static blk_status_t bio_integrity_proces
70   */
71  bool bio_integrity_prep(struct bio *bio)
72  {
73 -       struct bio_integrity_payload *bip;
74 +       struct bio_integrity_payload *bip = bio_integrity(bio);
75         struct blk_integrity *bi = blk_get_integrity(bio->bi_disk);
76         struct request_queue *q = bio->bi_disk->queue;
77         void *buf;
78 @@ -222,6 +233,8 @@ bool bio_integrity_prep(struct bio *bio)
79         unsigned int bytes, offset, i;
80         unsigned int intervals;
81         blk_status_t status;
82 +       integrity_processing_fn *generate_fn;
83 +       integrity_processing_fn *verify_fn;
84  
85         if (!bi)
86                 return true;
87 @@ -232,16 +245,20 @@ bool bio_integrity_prep(struct bio *bio)
88         if (!bio_sectors(bio))
89                 return true;
90  
91 -       /* Already protected? */
92 -       if (bio_integrity(bio))
93 -               return true;
94 +       if (bip != NULL) {
95 +               generate_fn = bip->bip_generate_fn ?: bi->profile->generate_fn;
96 +               verify_fn = bip->bip_verify_fn ?: bi->profile->verify_fn;
97 +       } else {
98 +               generate_fn = bi->profile->generate_fn;
99 +               verify_fn = bi->profile->verify_fn;
100 +       }
101  
102         if (bio_data_dir(bio) == READ) {
103 -               if (!bi->profile->verify_fn ||
104 +               if (!verify_fn ||
105                     !(bi->flags & BLK_INTEGRITY_VERIFY))
106                         return true;
107         } else {
108 -               if (!bi->profile->generate_fn ||
109 +               if (!generate_fn ||
110                     !(bi->flags & BLK_INTEGRITY_GENERATE))
111                         return true;
112         }
113 @@ -261,7 +278,8 @@ bool bio_integrity_prep(struct bio *bio)
114         nr_pages = end - start;
115  
116         /* Allocate bio integrity payload and integrity vectors */
117 -       bip = bio_integrity_alloc(bio, GFP_NOIO, nr_pages);
118 +       bip = bio_integrity_alloc_fn(bio, GFP_NOIO, nr_pages,
119 +                                    generate_fn, verify_fn);
120         if (IS_ERR(bip)) {
121                 printk(KERN_ERR "could not allocate data integrity bioset\n");
122                 kfree(buf);
123 @@ -304,8 +322,7 @@ bool bio_integrity_prep(struct bio *bio)
124  
125         /* Auto-generate integrity metadata if this is a write */
126         if (bio_data_dir(bio) == WRITE) {
127 -               bio_integrity_process(bio, &bio->bi_iter,
128 -                                     bi->profile->generate_fn);
129 +               bio_integrity_process(bio, &bio->bi_iter, generate_fn);
130         } else {
131                 bip->bio_iter = bio->bi_iter;
132         }
133 @@ -333,6 +350,13 @@ static void bio_integrity_verify_fn(stru
134                 container_of(work, struct bio_integrity_payload, bip_work);
135         struct bio *bio = bip->bip_bio;
136         struct blk_integrity *bi = blk_get_integrity(bio->bi_disk);
137 +       struct bio_integrity_payload *bio_bip = bio_integrity(bio);
138 +       integrity_processing_fn *verify_fn;
139 +
140 +       if (bio_bip != NULL)
141 +               verify_fn = bio_bip->bip_verify_fn ?: bi->profile->verify_fn;
142 +       else
143 +               verify_fn = bi->profile->verify_fn;
144  
145         /*
146          * At the moment verify is called bio's iterator was advanced
147 @@ -340,7 +364,7 @@ static void bio_integrity_verify_fn(stru
148          * it's original position.
149          */
150         bio->bi_status = bio_integrity_process(bio, &bip->bio_iter,
151 -                                               bi->profile->verify_fn);
152 +                                              verify_fn);
153         bio_integrity_free(bio);
154         bio_endio(bio);
155  }
156 @@ -423,7 +447,9 @@ int bio_integrity_clone(struct bio *bio,
157  
158         BUG_ON(bip_src == NULL);
159  
160 -       bip = bio_integrity_alloc(bio, gfp_mask, bip_src->bip_vcnt);
161 +       bip = bio_integrity_alloc_fn(bio, gfp_mask, bip_src->bip_vcnt,
162 +                                    bip_src->bip_generate_fn,
163 +                                    bip_src->bip_verify_fn);
164         if (IS_ERR(bip))
165                 return PTR_ERR(bip);
166  
167 Index: linux-4.18.0-372.19.1.el8_6/include/linux/bio.h
168 ===================================================================
169 --- linux-4.18.0-372.19.1.el8_6.orig/include/linux/bio.h
170 +++ linux-4.18.0-372.19.1.el8_6/include/linux/bio.h
171 @@ -307,8 +307,9 @@ struct bio_integrity_payload {
172  
173         struct bio_vec          *bip_vec;
174  
175 -       RH_KABI_RESERVE(1)
176 -       RH_KABI_RESERVE(2)
177 +       /* put after bip_vec as that is last externally-accessed bip_ field */
178 +       RH_KABI_USE(1, integrity_processing_fn *bip_generate_fn)
179 +       RH_KABI_USE(2, integrity_processing_fn *bip_verify_fn)
180  
181         struct bio_vec          bip_inline_vecs[0];/* embedded bvec array */
182  };
183 @@ -728,6 +729,11 @@ static inline bool bioset_initialized(st
184                 bip_for_each_vec(_bvl, _bio->bi_integrity, _iter)
185  
186  extern struct bio_integrity_payload *bio_integrity_alloc(struct bio *, gfp_t, unsigned int);
187 +extern struct bio_integrity_payload *bio_integrity_alloc_fn(struct bio *bio,
188 +                                               gfp_t gfp_mask,
189 +                                               unsigned int nr_vecs,
190 +                                               integrity_processing_fn *generate_fn,
191 +                                               integrity_processing_fn *verify_fn);
192  extern int bio_integrity_add_page(struct bio *, struct page *, unsigned int, unsigned int);
193  extern bool bio_integrity_prep(struct bio *);
194  extern void bio_integrity_advance(struct bio *, unsigned int);
195 Index: linux-4.18.0-80.el8/include/linux/blk_types.h
196 ===================================================================
197 --- linux-4.18.0-80.el8.orig/include/linux/blk_types.h
198 +++ linux-4.18.0-80.el8/include/linux/blk_types.h
199 @@ -18,6 +18,7 @@ struct page;
200  struct block_device;
201  struct io_context;
202  struct cgroup_subsys_state;
203 +struct blk_integrity_iter;
204  typedef void (bio_end_io_t) (struct bio *);
205  
206  /*
207 @@ -29,6 +30,9 @@ typedef u32 __bitwise blk_status_t;
208  #else
209  typedef u8 __bitwise blk_status_t;
210  #endif
211 +
212 +typedef blk_status_t (integrity_processing_fn) (struct blk_integrity_iter *);
213 +
214  #define        BLK_STS_OK 0
215  #define BLK_STS_NOTSUPP                ((__force blk_status_t)1)
216  #define BLK_STS_TIMEOUT                ((__force blk_status_t)2)