Blame view

block/bio-integrity.c 14.2 KB
7ba1ba12e   Martin K. Petersen   block: Block laye...
1
2
3
  /*
   * bio-integrity.c - bio data integrity extensions
   *
7878cba9f   Martin K. Petersen   block: Create bip...
4
   * Copyright (C) 2007, 2008, 2009 Oracle Corporation
7ba1ba12e   Martin K. Petersen   block: Block laye...
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
   * Written by: Martin K. Petersen <martin.petersen@oracle.com>
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public License version
   * 2 as published by the Free Software Foundation.
   *
   * This program is distributed in the hope that it will be useful, but
   * WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; see the file COPYING.  If not, write to
   * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139,
   * USA.
   *
   */
  
  #include <linux/blkdev.h>
  #include <linux/mempool.h>
afeacc8c1   Paul Gortmaker   fs: add export.h ...
25
  #include <linux/export.h>
7ba1ba12e   Martin K. Petersen   block: Block laye...
26
27
  #include <linux/bio.h>
  #include <linux/workqueue.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
28
  #include <linux/slab.h>
1179a5a08   Bart Van Assche   block/bio-integri...
29
  #include "blk.h"
7ba1ba12e   Martin K. Petersen   block: Block laye...
30

9f060e223   Kent Overstreet   block: Convert in...
31
  #define BIP_INLINE_VECS	4
7878cba9f   Martin K. Petersen   block: Create bip...
32

9f060e223   Kent Overstreet   block: Convert in...
33
  static struct kmem_cache *bip_slab;
7ba1ba12e   Martin K. Petersen   block: Block laye...
34
  static struct workqueue_struct *kintegrityd_wq;
5a48fc147   Dan Williams   block: blk_flush_...
35
36
37
38
  void blk_flush_integrity(void)
  {
  	flush_workqueue(kintegrityd_wq);
  }
7ba1ba12e   Martin K. Petersen   block: Block laye...
39
  /**
1e2a410ff   Kent Overstreet   block: Ues bi_poo...
40
   * bio_integrity_alloc - Allocate integrity payload and attach it to bio
7ba1ba12e   Martin K. Petersen   block: Block laye...
41
42
43
   * @bio:	bio to attach integrity metadata to
   * @gfp_mask:	Memory allocation mask
   * @nr_vecs:	Number of integrity metadata scatter-gather elements
7ba1ba12e   Martin K. Petersen   block: Block laye...
44
45
46
47
48
   *
   * Description: This function prepares a bio for attaching integrity
   * metadata.  nr_vecs specifies the maximum number of pages containing
   * integrity metadata that can be attached.
   */
1e2a410ff   Kent Overstreet   block: Ues bi_poo...
49
50
51
  struct bio_integrity_payload *bio_integrity_alloc(struct bio *bio,
  						  gfp_t gfp_mask,
  						  unsigned int nr_vecs)
7ba1ba12e   Martin K. Petersen   block: Block laye...
52
53
  {
  	struct bio_integrity_payload *bip;
1e2a410ff   Kent Overstreet   block: Ues bi_poo...
54
  	struct bio_set *bs = bio->bi_pool;
9f060e223   Kent Overstreet   block: Convert in...
55
  	unsigned inline_vecs;
bb8bd38b9   Mike Snitzer   bio integrity: do...
56
  	if (!bs || !bs->bio_integrity_pool) {
9f060e223   Kent Overstreet   block: Convert in...
57
58
59
60
  		bip = kmalloc(sizeof(struct bio_integrity_payload) +
  			      sizeof(struct bio_vec) * nr_vecs, gfp_mask);
  		inline_vecs = nr_vecs;
  	} else {
7878cba9f   Martin K. Petersen   block: Create bip...
61
  		bip = mempool_alloc(bs->bio_integrity_pool, gfp_mask);
9f060e223   Kent Overstreet   block: Convert in...
62
  		inline_vecs = BIP_INLINE_VECS;
7ba1ba12e   Martin K. Petersen   block: Block laye...
63
  	}
9f060e223   Kent Overstreet   block: Convert in...
64
  	if (unlikely(!bip))
06c1e3902   Keith Busch   blk-integrity: em...
65
  		return ERR_PTR(-ENOMEM);
9f060e223   Kent Overstreet   block: Convert in...
66

7878cba9f   Martin K. Petersen   block: Create bip...
67
  	memset(bip, 0, sizeof(*bip));
9f060e223   Kent Overstreet   block: Convert in...
68
  	if (nr_vecs > inline_vecs) {
ed996a52c   Christoph Hellwig   block: simplify a...
69
  		unsigned long idx = 0;
9f060e223   Kent Overstreet   block: Convert in...
70
71
72
73
  		bip->bip_vec = bvec_alloc(gfp_mask, nr_vecs, &idx,
  					  bs->bvec_integrity_pool);
  		if (!bip->bip_vec)
  			goto err;
cbcd1054a   Gu Zheng   bio-integrity: ad...
74
  		bip->bip_max_vcnt = bvec_nr_vecs(idx);
ed996a52c   Christoph Hellwig   block: simplify a...
75
  		bip->bip_slab = idx;
9f060e223   Kent Overstreet   block: Convert in...
76
77
  	} else {
  		bip->bip_vec = bip->bip_inline_vecs;
cbcd1054a   Gu Zheng   bio-integrity: ad...
78
  		bip->bip_max_vcnt = inline_vecs;
9f060e223   Kent Overstreet   block: Convert in...
79
  	}
7ba1ba12e   Martin K. Petersen   block: Block laye...
80
81
  	bip->bip_bio = bio;
  	bio->bi_integrity = bip;
1eff9d322   Jens Axboe   block: rename bio...
82
  	bio->bi_opf |= REQ_INTEGRITY;
7ba1ba12e   Martin K. Petersen   block: Block laye...
83
84
  
  	return bip;
9f060e223   Kent Overstreet   block: Convert in...
85
86
  err:
  	mempool_free(bip, bs->bio_integrity_pool);
06c1e3902   Keith Busch   blk-integrity: em...
87
  	return ERR_PTR(-ENOMEM);
7ba1ba12e   Martin K. Petersen   block: Block laye...
88
  }
7ba1ba12e   Martin K. Petersen   block: Block laye...
89
90
91
92
93
  EXPORT_SYMBOL(bio_integrity_alloc);
  
  /**
   * bio_integrity_free - Free bio integrity payload
   * @bio:	bio containing bip to be freed
7ba1ba12e   Martin K. Petersen   block: Block laye...
94
95
96
97
   *
   * Description: Used to free the integrity portion of a bio. Usually
   * called from bio_free().
   */
1e2a410ff   Kent Overstreet   block: Ues bi_poo...
98
  void bio_integrity_free(struct bio *bio)
7ba1ba12e   Martin K. Petersen   block: Block laye...
99
  {
180b2f95d   Martin K. Petersen   block: Replace bi...
100
  	struct bio_integrity_payload *bip = bio_integrity(bio);
1e2a410ff   Kent Overstreet   block: Ues bi_poo...
101
  	struct bio_set *bs = bio->bi_pool;
b1f013885   Martin K. Petersen   block: Relocate b...
102
  	if (bip->bip_flags & BIP_BLOCK_INTEGRITY)
5f9378fa9   Martin K. Petersen   block: Remove bip...
103
104
  		kfree(page_address(bip->bip_vec->bv_page) +
  		      bip->bip_vec->bv_offset);
7ba1ba12e   Martin K. Petersen   block: Block laye...
105

bb8bd38b9   Mike Snitzer   bio integrity: do...
106
  	if (bs && bs->bio_integrity_pool) {
ed996a52c   Christoph Hellwig   block: simplify a...
107
  		bvec_free(bs->bvec_integrity_pool, bip->bip_vec, bip->bip_slab);
9f060e223   Kent Overstreet   block: Convert in...
108

7878cba9f   Martin K. Petersen   block: Create bip...
109
  		mempool_free(bip, bs->bio_integrity_pool);
9f060e223   Kent Overstreet   block: Convert in...
110
111
112
  	} else {
  		kfree(bip);
  	}
7ba1ba12e   Martin K. Petersen   block: Block laye...
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
  
  	bio->bi_integrity = NULL;
  }
  EXPORT_SYMBOL(bio_integrity_free);
  
  /**
   * bio_integrity_add_page - Attach integrity metadata
   * @bio:	bio to update
   * @page:	page containing integrity metadata
   * @len:	number of bytes of integrity metadata in page
   * @offset:	start offset within page
   *
   * Description: Attach a page containing integrity metadata to bio.
   */
  int bio_integrity_add_page(struct bio *bio, struct page *page,
  			   unsigned int len, unsigned int offset)
  {
180b2f95d   Martin K. Petersen   block: Replace bi...
130
  	struct bio_integrity_payload *bip = bio_integrity(bio);
7ba1ba12e   Martin K. Petersen   block: Block laye...
131
  	struct bio_vec *iv;
cbcd1054a   Gu Zheng   bio-integrity: ad...
132
  	if (bip->bip_vcnt >= bip->bip_max_vcnt) {
7ba1ba12e   Martin K. Petersen   block: Block laye...
133
134
135
136
  		printk(KERN_ERR "%s: bip_vec full
  ", __func__);
  		return 0;
  	}
d57a5f7c6   Kent Overstreet   bio-integrity: Co...
137
  	iv = bip->bip_vec + bip->bip_vcnt;
7ba1ba12e   Martin K. Petersen   block: Block laye...
138

87a816df5   Sagi Grimberg   block: Refuse add...
139
140
141
142
  	if (bip->bip_vcnt &&
  	    bvec_gap_to_prev(bdev_get_queue(bio->bi_bdev),
  			     &bip->bip_vec[bip->bip_vcnt - 1], offset))
  		return 0;
7ba1ba12e   Martin K. Petersen   block: Block laye...
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
  	iv->bv_page = page;
  	iv->bv_len = len;
  	iv->bv_offset = offset;
  	bip->bip_vcnt++;
  
  	return len;
  }
  EXPORT_SYMBOL(bio_integrity_add_page);
  
  /**
   * bio_integrity_enabled - Check whether integrity can be passed
   * @bio:	bio to check
   *
   * Description: Determines whether bio_integrity_prep() can be called
   * on this bio or not.	bio data direction and target device must be
   * set prior to calling.  The functions honors the write_generate and
   * read_verify flags in sysfs.
   */
e7258c1a2   Martin K. Petersen   block: Get rid of...
161
  bool bio_integrity_enabled(struct bio *bio)
7ba1ba12e   Martin K. Petersen   block: Block laye...
162
  {
e7258c1a2   Martin K. Petersen   block: Get rid of...
163
  	struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev);
e69f18f06   Martin K. Petersen   block: Ensure we ...
164
  	if (!bio_is_rw(bio))
e7258c1a2   Martin K. Petersen   block: Get rid of...
165
  		return false;
e69f18f06   Martin K. Petersen   block: Ensure we ...
166

7ba1ba12e   Martin K. Petersen   block: Block laye...
167
168
  	/* Already protected? */
  	if (bio_integrity(bio))
e7258c1a2   Martin K. Petersen   block: Get rid of...
169
170
171
172
  		return false;
  
  	if (bi == NULL)
  		return false;
0f8087ecd   Martin K. Petersen   block: Consolidat...
173
  	if (bio_data_dir(bio) == READ && bi->profile->verify_fn != NULL &&
8288f496e   Martin K. Petersen   block: Add prefix...
174
  	    (bi->flags & BLK_INTEGRITY_VERIFY))
e7258c1a2   Martin K. Petersen   block: Get rid of...
175
  		return true;
0f8087ecd   Martin K. Petersen   block: Consolidat...
176
  	if (bio_data_dir(bio) == WRITE && bi->profile->generate_fn != NULL &&
8288f496e   Martin K. Petersen   block: Add prefix...
177
  	    (bi->flags & BLK_INTEGRITY_GENERATE))
e7258c1a2   Martin K. Petersen   block: Get rid of...
178
  		return true;
7ba1ba12e   Martin K. Petersen   block: Block laye...
179

e7258c1a2   Martin K. Petersen   block: Get rid of...
180
  	return false;
7ba1ba12e   Martin K. Petersen   block: Block laye...
181
182
183
184
  }
  EXPORT_SYMBOL(bio_integrity_enabled);
  
  /**
3be91c4a3   Martin K. Petersen   block: Deprecate ...
185
   * bio_integrity_intervals - Return number of integrity intervals for a bio
7ba1ba12e   Martin K. Petersen   block: Block laye...
186
   * @bi:		blk_integrity profile for device
3be91c4a3   Martin K. Petersen   block: Deprecate ...
187
   * @sectors:	Size of the bio in 512-byte sectors
7ba1ba12e   Martin K. Petersen   block: Block laye...
188
189
   *
   * Description: The block layer calculates everything in 512 byte
3be91c4a3   Martin K. Petersen   block: Deprecate ...
190
191
192
   * sectors but integrity metadata is done in terms of the data integrity
   * interval size of the storage device.  Convert the block layer sectors
   * to the appropriate number of integrity intervals.
7ba1ba12e   Martin K. Petersen   block: Block laye...
193
   */
3be91c4a3   Martin K. Petersen   block: Deprecate ...
194
195
  static inline unsigned int bio_integrity_intervals(struct blk_integrity *bi,
  						   unsigned int sectors)
7ba1ba12e   Martin K. Petersen   block: Block laye...
196
  {
a48f041d9   Martin K. Petersen   block: Reduce the...
197
  	return sectors >> (bi->interval_exp - 9);
7ba1ba12e   Martin K. Petersen   block: Block laye...
198
  }
d57a5f7c6   Kent Overstreet   bio-integrity: Co...
199
200
201
  static inline unsigned int bio_integrity_bytes(struct blk_integrity *bi,
  					       unsigned int sectors)
  {
3be91c4a3   Martin K. Petersen   block: Deprecate ...
202
  	return bio_integrity_intervals(bi, sectors) * bi->tuple_size;
d57a5f7c6   Kent Overstreet   bio-integrity: Co...
203
  }
7ba1ba12e   Martin K. Petersen   block: Block laye...
204
  /**
185930885   Martin K. Petersen   block: Clean up t...
205
   * bio_integrity_process - Process integrity metadata for a bio
bf36f9cfa   Gu Zheng   fs/bio-integrity:...
206
   * @bio:	bio to generate/verify integrity metadata for
185930885   Martin K. Petersen   block: Clean up t...
207
   * @proc_fn:	Pointer to the relevant processing function
7ba1ba12e   Martin K. Petersen   block: Block laye...
208
   */
185930885   Martin K. Petersen   block: Clean up t...
209
210
  static int bio_integrity_process(struct bio *bio,
  				 integrity_processing_fn *proc_fn)
7ba1ba12e   Martin K. Petersen   block: Block laye...
211
212
  {
  	struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev);
185930885   Martin K. Petersen   block: Clean up t...
213
  	struct blk_integrity_iter iter;
594416a72   Darrick J. Wong   block: fix regres...
214
215
  	struct bvec_iter bviter;
  	struct bio_vec bv;
5f9378fa9   Martin K. Petersen   block: Remove bip...
216
  	struct bio_integrity_payload *bip = bio_integrity(bio);
594416a72   Darrick J. Wong   block: fix regres...
217
  	unsigned int ret = 0;
5f9378fa9   Martin K. Petersen   block: Remove bip...
218
219
  	void *prot_buf = page_address(bip->bip_vec->bv_page) +
  		bip->bip_vec->bv_offset;
7ba1ba12e   Martin K. Petersen   block: Block laye...
220

185930885   Martin K. Petersen   block: Clean up t...
221
  	iter.disk_name = bio->bi_bdev->bd_disk->disk_name;
a48f041d9   Martin K. Petersen   block: Reduce the...
222
  	iter.interval = 1 << bi->interval_exp;
185930885   Martin K. Petersen   block: Clean up t...
223
224
  	iter.seed = bip_get_seed(bip);
  	iter.prot_buf = prot_buf;
7ba1ba12e   Martin K. Petersen   block: Block laye...
225

594416a72   Darrick J. Wong   block: fix regres...
226
227
  	bio_for_each_segment(bv, bio, bviter) {
  		void *kaddr = kmap_atomic(bv.bv_page);
7ba1ba12e   Martin K. Petersen   block: Block laye...
228

594416a72   Darrick J. Wong   block: fix regres...
229
230
  		iter.data_buf = kaddr + bv.bv_offset;
  		iter.data_size = bv.bv_len;
185930885   Martin K. Petersen   block: Clean up t...
231
232
233
234
235
236
  
  		ret = proc_fn(&iter);
  		if (ret) {
  			kunmap_atomic(kaddr);
  			return ret;
  		}
7ba1ba12e   Martin K. Petersen   block: Block laye...
237

e8e3c3d66   Cong Wang   fs: remove the se...
238
  		kunmap_atomic(kaddr);
7ba1ba12e   Martin K. Petersen   block: Block laye...
239
  	}
bf36f9cfa   Gu Zheng   fs/bio-integrity:...
240
241
242
243
  	return ret;
  }
  
  /**
7ba1ba12e   Martin K. Petersen   block: Block laye...
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
   * bio_integrity_prep - Prepare bio for integrity I/O
   * @bio:	bio to prepare
   *
   * Description: Allocates a buffer for integrity metadata, maps the
   * pages and attaches them to a bio.  The bio must have data
   * direction, target device and start sector set priot to calling.  In
   * the WRITE case, integrity metadata will be generated using the
   * block device's integrity function.  In the READ case, the buffer
   * will be prepared for DMA and a suitable end_io handler set up.
   */
  int bio_integrity_prep(struct bio *bio)
  {
  	struct bio_integrity_payload *bip;
  	struct blk_integrity *bi;
  	struct request_queue *q;
  	void *buf;
  	unsigned long start, end;
  	unsigned int len, nr_pages;
  	unsigned int bytes, offset, i;
3be91c4a3   Martin K. Petersen   block: Deprecate ...
263
  	unsigned int intervals;
7ba1ba12e   Martin K. Petersen   block: Block laye...
264
265
266
267
268
  
  	bi = bdev_get_integrity(bio->bi_bdev);
  	q = bdev_get_queue(bio->bi_bdev);
  	BUG_ON(bi == NULL);
  	BUG_ON(bio_integrity(bio));
3be91c4a3   Martin K. Petersen   block: Deprecate ...
269
  	intervals = bio_integrity_intervals(bi, bio_sectors(bio));
7ba1ba12e   Martin K. Petersen   block: Block laye...
270
271
  
  	/* Allocate kernel buffer for protection data */
3be91c4a3   Martin K. Petersen   block: Deprecate ...
272
  	len = intervals * bi->tuple_size;
72f465033   David Rientjes   bio-integrity.c: ...
273
  	buf = kmalloc(len, GFP_NOIO | q->bounce_gfp);
7ba1ba12e   Martin K. Petersen   block: Block laye...
274
275
276
  	if (unlikely(buf == NULL)) {
  		printk(KERN_ERR "could not allocate integrity buffer
  ");
220eb7fd9   Andrew Morton   fs/bio-integrity....
277
  		return -ENOMEM;
7ba1ba12e   Martin K. Petersen   block: Block laye...
278
279
280
281
282
283
284
285
  	}
  
  	end = (((unsigned long) buf) + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
  	start = ((unsigned long) buf) >> PAGE_SHIFT;
  	nr_pages = end - start;
  
  	/* Allocate bio integrity payload and integrity vectors */
  	bip = bio_integrity_alloc(bio, GFP_NOIO, nr_pages);
7b6c0f803   Dan Carpenter   blk-integrity: ch...
286
  	if (IS_ERR(bip)) {
7ba1ba12e   Martin K. Petersen   block: Block laye...
287
288
289
  		printk(KERN_ERR "could not allocate data integrity bioset
  ");
  		kfree(buf);
7b6c0f803   Dan Carpenter   blk-integrity: ch...
290
  		return PTR_ERR(bip);
7ba1ba12e   Martin K. Petersen   block: Block laye...
291
  	}
b1f013885   Martin K. Petersen   block: Relocate b...
292
  	bip->bip_flags |= BIP_BLOCK_INTEGRITY;
d57a5f7c6   Kent Overstreet   bio-integrity: Co...
293
  	bip->bip_iter.bi_size = len;
185930885   Martin K. Petersen   block: Clean up t...
294
  	bip_set_seed(bip, bio->bi_iter.bi_sector);
7ba1ba12e   Martin K. Petersen   block: Block laye...
295

aae7df501   Martin K. Petersen   block: Integrity ...
296
297
  	if (bi->flags & BLK_INTEGRITY_IP_CHECKSUM)
  		bip->bip_flags |= BIP_IP_CHECKSUM;
7ba1ba12e   Martin K. Petersen   block: Block laye...
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
  	/* Map it */
  	offset = offset_in_page(buf);
  	for (i = 0 ; i < nr_pages ; i++) {
  		int ret;
  		bytes = PAGE_SIZE - offset;
  
  		if (len <= 0)
  			break;
  
  		if (bytes > len)
  			bytes = len;
  
  		ret = bio_integrity_add_page(bio, virt_to_page(buf),
  					     bytes, offset);
  
  		if (ret == 0)
  			return 0;
  
  		if (ret < bytes)
  			break;
  
  		buf += bytes;
  		len -= bytes;
  		offset = 0;
  	}
  
  	/* Install custom I/O completion handler if read verify is enabled */
  	if (bio_data_dir(bio) == READ) {
  		bip->bip_end_io = bio->bi_end_io;
  		bio->bi_end_io = bio_integrity_endio;
  	}
  
  	/* Auto-generate integrity metadata if this is a write */
  	if (bio_data_dir(bio) == WRITE)
0f8087ecd   Martin K. Petersen   block: Consolidat...
332
  		bio_integrity_process(bio, bi->profile->generate_fn);
7ba1ba12e   Martin K. Petersen   block: Block laye...
333
334
335
336
337
338
  
  	return 0;
  }
  EXPORT_SYMBOL(bio_integrity_prep);
  
  /**
7ba1ba12e   Martin K. Petersen   block: Block laye...
339
340
341
342
343
344
345
346
347
   * bio_integrity_verify_fn - Integrity I/O completion worker
   * @work:	Work struct stored in bio to be verified
   *
   * Description: This workqueue function is called to complete a READ
   * request.  The function verifies the transferred integrity metadata
   * and then calls the original bio end_io function.
   */
  static void bio_integrity_verify_fn(struct work_struct *work)
  {
b984679ef   Jens Axboe   block: integrity ...
348
  	struct bio_integrity_payload *bip =
7ba1ba12e   Martin K. Petersen   block: Block laye...
349
350
  		container_of(work, struct bio_integrity_payload, bip_work);
  	struct bio *bio = bip->bip_bio;
185930885   Martin K. Petersen   block: Clean up t...
351
  	struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev);
7ba1ba12e   Martin K. Petersen   block: Block laye...
352

0f8087ecd   Martin K. Petersen   block: Consolidat...
353
  	bio->bi_error = bio_integrity_process(bio, bi->profile->verify_fn);
7ba1ba12e   Martin K. Petersen   block: Block laye...
354
355
356
  
  	/* Restore original bio completion handler */
  	bio->bi_end_io = bip->bip_end_io;
4246a0b63   Christoph Hellwig   block: add a bi_e...
357
  	bio_endio(bio);
7ba1ba12e   Martin K. Petersen   block: Block laye...
358
359
360
361
362
363
364
365
366
367
368
369
370
371
  }
  
  /**
   * bio_integrity_endio - Integrity I/O completion function
   * @bio:	Protected bio
   * @error:	Pointer to errno
   *
   * Description: Completion for integrity I/O
   *
   * Normally I/O completion is done in interrupt context.  However,
   * verifying I/O integrity is a time-consuming task which must be run
   * in process context.	This function postpones completion
   * accordingly.
   */
4246a0b63   Christoph Hellwig   block: add a bi_e...
372
  void bio_integrity_endio(struct bio *bio)
7ba1ba12e   Martin K. Petersen   block: Block laye...
373
  {
180b2f95d   Martin K. Petersen   block: Replace bi...
374
  	struct bio_integrity_payload *bip = bio_integrity(bio);
7ba1ba12e   Martin K. Petersen   block: Block laye...
375
376
  
  	BUG_ON(bip->bip_bio != bio);
7b24fc4d7   Martin K. Petersen   block: Don't veri...
377
378
379
380
  	/* In case of an I/O error there is no point in verifying the
  	 * integrity metadata.  Restore original bio end_io handler
  	 * and run it.
  	 */
4246a0b63   Christoph Hellwig   block: add a bi_e...
381
  	if (bio->bi_error) {
7b24fc4d7   Martin K. Petersen   block: Don't veri...
382
  		bio->bi_end_io = bip->bip_end_io;
4246a0b63   Christoph Hellwig   block: add a bi_e...
383
  		bio_endio(bio);
7b24fc4d7   Martin K. Petersen   block: Don't veri...
384
385
386
  
  		return;
  	}
7ba1ba12e   Martin K. Petersen   block: Block laye...
387
388
389
390
391
392
  	INIT_WORK(&bip->bip_work, bio_integrity_verify_fn);
  	queue_work(kintegrityd_wq, &bip->bip_work);
  }
  EXPORT_SYMBOL(bio_integrity_endio);
  
  /**
7ba1ba12e   Martin K. Petersen   block: Block laye...
393
394
395
396
397
398
399
400
401
402
   * bio_integrity_advance - Advance integrity vector
   * @bio:	bio whose integrity vector to update
   * @bytes_done:	number of data bytes that have been completed
   *
   * Description: This function calculates how many integrity bytes the
   * number of completed data bytes correspond to and advances the
   * integrity vector accordingly.
   */
  void bio_integrity_advance(struct bio *bio, unsigned int bytes_done)
  {
180b2f95d   Martin K. Petersen   block: Replace bi...
403
  	struct bio_integrity_payload *bip = bio_integrity(bio);
7ba1ba12e   Martin K. Petersen   block: Block laye...
404
  	struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev);
d57a5f7c6   Kent Overstreet   bio-integrity: Co...
405
  	unsigned bytes = bio_integrity_bytes(bi, bytes_done >> 9);
7ba1ba12e   Martin K. Petersen   block: Block laye...
406

d57a5f7c6   Kent Overstreet   bio-integrity: Co...
407
  	bvec_iter_advance(bip->bip_vec, &bip->bip_iter, bytes);
7ba1ba12e   Martin K. Petersen   block: Block laye...
408
409
410
411
412
413
414
415
416
417
418
419
420
421
  }
  EXPORT_SYMBOL(bio_integrity_advance);
  
  /**
   * bio_integrity_trim - Trim integrity vector
   * @bio:	bio whose integrity vector to update
   * @offset:	offset to first data sector
   * @sectors:	number of data sectors
   *
   * Description: Used to trim the integrity vector in a cloned bio.
   * The ivec will be advanced corresponding to 'offset' data sectors
   * and the length will be truncated corresponding to 'len' data
   * sectors.
   */
b984679ef   Jens Axboe   block: integrity ...
422
423
  void bio_integrity_trim(struct bio *bio, unsigned int offset,
  			unsigned int sectors)
7ba1ba12e   Martin K. Petersen   block: Block laye...
424
  {
180b2f95d   Martin K. Petersen   block: Replace bi...
425
  	struct bio_integrity_payload *bip = bio_integrity(bio);
7ba1ba12e   Martin K. Petersen   block: Block laye...
426
  	struct blk_integrity *bi = bdev_get_integrity(bio->bi_bdev);
7ba1ba12e   Martin K. Petersen   block: Block laye...
427

d57a5f7c6   Kent Overstreet   bio-integrity: Co...
428
429
  	bio_integrity_advance(bio, offset << 9);
  	bip->bip_iter.bi_size = bio_integrity_bytes(bi, sectors);
7ba1ba12e   Martin K. Petersen   block: Block laye...
430
431
432
433
  }
  EXPORT_SYMBOL(bio_integrity_trim);
  
  /**
7ba1ba12e   Martin K. Petersen   block: Block laye...
434
435
436
   * bio_integrity_clone - Callback for cloning bios with integrity metadata
   * @bio:	New bio
   * @bio_src:	Original bio
87092698c   un'ichi Nomura   block: Add gfp_ma...
437
   * @gfp_mask:	Memory allocation mask
7ba1ba12e   Martin K. Petersen   block: Block laye...
438
439
440
   *
   * Description:	Called to allocate a bip when cloning a bio
   */
7878cba9f   Martin K. Petersen   block: Create bip...
441
  int bio_integrity_clone(struct bio *bio, struct bio *bio_src,
1e2a410ff   Kent Overstreet   block: Ues bi_poo...
442
  			gfp_t gfp_mask)
7ba1ba12e   Martin K. Petersen   block: Block laye...
443
  {
180b2f95d   Martin K. Petersen   block: Replace bi...
444
  	struct bio_integrity_payload *bip_src = bio_integrity(bio_src);
7ba1ba12e   Martin K. Petersen   block: Block laye...
445
446
447
  	struct bio_integrity_payload *bip;
  
  	BUG_ON(bip_src == NULL);
1e2a410ff   Kent Overstreet   block: Ues bi_poo...
448
  	bip = bio_integrity_alloc(bio, gfp_mask, bip_src->bip_vcnt);
7b6c0f803   Dan Carpenter   blk-integrity: ch...
449
450
  	if (IS_ERR(bip))
  		return PTR_ERR(bip);
7ba1ba12e   Martin K. Petersen   block: Block laye...
451
452
453
  
  	memcpy(bip->bip_vec, bip_src->bip_vec,
  	       bip_src->bip_vcnt * sizeof(struct bio_vec));
7ba1ba12e   Martin K. Petersen   block: Block laye...
454
  	bip->bip_vcnt = bip_src->bip_vcnt;
d57a5f7c6   Kent Overstreet   bio-integrity: Co...
455
  	bip->bip_iter = bip_src->bip_iter;
7ba1ba12e   Martin K. Petersen   block: Block laye...
456
457
458
459
  
  	return 0;
  }
  EXPORT_SYMBOL(bio_integrity_clone);
7878cba9f   Martin K. Petersen   block: Create bip...
460
  int bioset_integrity_create(struct bio_set *bs, int pool_size)
7ba1ba12e   Martin K. Petersen   block: Block laye...
461
  {
a91a2785b   Martin K. Petersen   block: Require su...
462
463
  	if (bs->bio_integrity_pool)
  		return 0;
9f060e223   Kent Overstreet   block: Convert in...
464
  	bs->bio_integrity_pool = mempool_create_slab_pool(pool_size, bip_slab);
bc5c8f078   Gu Zheng   fs/bio-integrity:...
465
  	if (!bs->bio_integrity_pool)
9f060e223   Kent Overstreet   block: Convert in...
466
  		return -1;
7ba1ba12e   Martin K. Petersen   block: Block laye...
467

a6c39cb4f   Fabian Frederick   fs/bio: remove bs...
468
  	bs->bvec_integrity_pool = biovec_create_pool(pool_size);
bc5c8f078   Gu Zheng   fs/bio-integrity:...
469
470
  	if (!bs->bvec_integrity_pool) {
  		mempool_destroy(bs->bio_integrity_pool);
7878cba9f   Martin K. Petersen   block: Create bip...
471
  		return -1;
bc5c8f078   Gu Zheng   fs/bio-integrity:...
472
  	}
7878cba9f   Martin K. Petersen   block: Create bip...
473
474
475
476
477
478
479
480
481
  
  	return 0;
  }
  EXPORT_SYMBOL(bioset_integrity_create);
  
  void bioset_integrity_free(struct bio_set *bs)
  {
  	if (bs->bio_integrity_pool)
  		mempool_destroy(bs->bio_integrity_pool);
9f060e223   Kent Overstreet   block: Convert in...
482
483
  
  	if (bs->bvec_integrity_pool)
adbe6991e   Bjorn Helgaas   bio-integrity: Fi...
484
  		mempool_destroy(bs->bvec_integrity_pool);
7878cba9f   Martin K. Petersen   block: Create bip...
485
486
487
488
489
  }
  EXPORT_SYMBOL(bioset_integrity_free);
  
  void __init bio_integrity_init(void)
  {
a6e8dc46f   Tejun Heo   bio-integrity: ma...
490
491
492
493
494
495
  	/*
  	 * kintegrityd won't block much but may burn a lot of CPU cycles.
  	 * Make it highpri CPU intensive wq with max concurrency of 1.
  	 */
  	kintegrityd_wq = alloc_workqueue("kintegrityd", WQ_MEM_RECLAIM |
  					 WQ_HIGHPRI | WQ_CPU_INTENSIVE, 1);
6d2a78e78   Martin K. Petersen   block: add privat...
496
497
498
  	if (!kintegrityd_wq)
  		panic("Failed to create kintegrityd
  ");
7ba1ba12e   Martin K. Petersen   block: Block laye...
499

9f060e223   Kent Overstreet   block: Convert in...
500
501
502
503
  	bip_slab = kmem_cache_create("bio_integrity_payload",
  				     sizeof(struct bio_integrity_payload) +
  				     sizeof(struct bio_vec) * BIP_INLINE_VECS,
  				     0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);
7ba1ba12e   Martin K. Petersen   block: Block laye...
504
  }