Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

block: add support to pass user meta buffer

If an iocb contains metadata, extract that and prepare the bip.
Based on flags specified by the user, set corresponding guard/app/ref
tags to be checked in bip.

Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Anuj Gupta <anuj20.g@samsung.com>
Signed-off-by: Kanchan Joshi <joshi.k@samsung.com>
Reviewed-by: Keith Busch <kbusch@kernel.org>
Link: https://lore.kernel.org/r/20241128112240.8867-11-anuj20.g@samsung.com
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by

Kanchan Joshi and committed by
Jens Axboe
3d8b5a22 18623503

+92 -10
+50
block/bio-integrity.c
··· 364 364 return ret; 365 365 } 366 366 367 + static void bio_uio_meta_to_bip(struct bio *bio, struct uio_meta *meta) 368 + { 369 + struct bio_integrity_payload *bip = bio_integrity(bio); 370 + 371 + if (meta->flags & IO_INTEGRITY_CHK_GUARD) 372 + bip->bip_flags |= BIP_CHECK_GUARD; 373 + if (meta->flags & IO_INTEGRITY_CHK_APPTAG) 374 + bip->bip_flags |= BIP_CHECK_APPTAG; 375 + if (meta->flags & IO_INTEGRITY_CHK_REFTAG) 376 + bip->bip_flags |= BIP_CHECK_REFTAG; 377 + 378 + bip->app_tag = meta->app_tag; 379 + } 380 + 381 + int bio_integrity_map_iter(struct bio *bio, struct uio_meta *meta) 382 + { 383 + struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk); 384 + unsigned int integrity_bytes; 385 + int ret; 386 + struct iov_iter it; 387 + 388 + if (!bi) 389 + return -EINVAL; 390 + /* 391 + * original meta iterator can be bigger. 392 + * process integrity info corresponding to current data buffer only. 393 + */ 394 + it = meta->iter; 395 + integrity_bytes = bio_integrity_bytes(bi, bio_sectors(bio)); 396 + if (it.count < integrity_bytes) 397 + return -EINVAL; 398 + 399 + /* should fit into two bytes */ 400 + BUILD_BUG_ON(IO_INTEGRITY_VALID_FLAGS >= (1 << 16)); 401 + 402 + if (meta->flags && (meta->flags & ~IO_INTEGRITY_VALID_FLAGS)) 403 + return -EINVAL; 404 + 405 + it.count = integrity_bytes; 406 + ret = bio_integrity_map_user(bio, &it); 407 + if (!ret) { 408 + bio_uio_meta_to_bip(bio, meta); 409 + bip_set_seed(bio_integrity(bio), meta->seed); 410 + iov_iter_advance(&meta->iter, integrity_bytes); 411 + meta->seed += bio_integrity_intervals(bi, bio_sectors(bio)); 412 + } 413 + return ret; 414 + } 415 + 367 416 /** 368 417 * bio_integrity_prep - Prepare bio for integrity I/O 369 418 * @bio: bio to prepare ··· 613 564 bip->bip_vec = bip_src->bip_vec; 614 565 bip->bip_iter = bip_src->bip_iter; 615 566 bip->bip_flags = bip_src->bip_flags & BIP_CLONE_FLAGS; 567 + bip->app_tag = bip_src->app_tag; 616 568 617 569 return 0; 618 570 }
+35 -10
block/fops.c
··· 54 54 struct bio bio; 55 55 ssize_t ret; 56 56 57 + WARN_ON_ONCE(iocb->ki_flags & IOCB_HAS_METADATA); 57 58 if (nr_pages <= DIO_INLINE_BIO_VECS) 58 59 vecs = inline_vecs; 59 60 else { ··· 125 124 { 126 125 struct blkdev_dio *dio = bio->bi_private; 127 126 bool should_dirty = dio->flags & DIO_SHOULD_DIRTY; 127 + bool is_sync = dio->flags & DIO_IS_SYNC; 128 128 129 129 if (bio->bi_status && !dio->bio.bi_status) 130 130 dio->bio.bi_status = bio->bi_status; 131 131 132 + if (!is_sync && (dio->iocb->ki_flags & IOCB_HAS_METADATA)) 133 + bio_integrity_unmap_user(bio); 134 + 132 135 if (atomic_dec_and_test(&dio->ref)) { 133 - if (!(dio->flags & DIO_IS_SYNC)) { 136 + if (!is_sync) { 134 137 struct kiocb *iocb = dio->iocb; 135 138 ssize_t ret; 136 139 ··· 226 221 * a retry of this from blocking context. 227 222 */ 228 223 if (unlikely(iov_iter_count(iter))) { 229 - bio_release_pages(bio, false); 230 - bio_clear_flag(bio, BIO_REFFED); 231 - bio_put(bio); 232 - blk_finish_plug(&plug); 233 - return -EAGAIN; 224 + ret = -EAGAIN; 225 + goto fail; 234 226 } 235 227 bio->bi_opf |= REQ_NOWAIT; 228 + } 229 + if (!is_sync && (iocb->ki_flags & IOCB_HAS_METADATA)) { 230 + ret = bio_integrity_map_iter(bio, iocb->private); 231 + if (unlikely(ret)) 232 + goto fail; 236 233 } 237 234 238 235 if (is_read) { ··· 276 269 277 270 bio_put(&dio->bio); 278 271 return ret; 272 + fail: 273 + bio_release_pages(bio, false); 274 + bio_clear_flag(bio, BIO_REFFED); 275 + bio_put(bio); 276 + blk_finish_plug(&plug); 277 + return ret; 279 278 } 280 279 281 280 static void blkdev_bio_end_io_async(struct bio *bio) ··· 298 285 } else { 299 286 ret = blk_status_to_errno(bio->bi_status); 300 287 } 288 + 289 + if (iocb->ki_flags & IOCB_HAS_METADATA) 290 + bio_integrity_unmap_user(bio); 301 291 302 292 iocb->ki_complete(iocb, ret); 303 293 ··· 346 330 bio_iov_bvec_set(bio, iter); 347 331 } else { 348 332 ret = bio_iov_iter_get_pages(bio, iter); 349 - if (unlikely(ret)) { 350 - bio_put(bio); 351 - return ret; 352 - } 333 + if (unlikely(ret)) 334 + goto out_bio_put; 353 335 } 354 336 dio->size = bio->bi_iter.bi_size; 355 337 ··· 358 344 } 359 345 } else { 360 346 task_io_account_write(bio->bi_iter.bi_size); 347 + } 348 + 349 + if (iocb->ki_flags & IOCB_HAS_METADATA) { 350 + ret = bio_integrity_map_iter(bio, iocb->private); 351 + WRITE_ONCE(iocb->private, NULL); 352 + if (unlikely(ret)) 353 + goto out_bio_put; 361 354 } 362 355 363 356 if (iocb->ki_flags & IOCB_ATOMIC) ··· 381 360 submit_bio(bio); 382 361 } 383 362 return -EIOCBQUEUED; 363 + 364 + out_bio_put: 365 + bio_put(bio); 366 + return ret; 384 367 } 385 368 386 369 static ssize_t blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
+7
include/linux/bio-integrity.h
··· 23 23 unsigned short bip_vcnt; /* # of integrity bio_vecs */ 24 24 unsigned short bip_max_vcnt; /* integrity bio_vec slots */ 25 25 unsigned short bip_flags; /* control flags */ 26 + u16 app_tag; /* application tag value */ 26 27 27 28 struct bvec_iter bio_iter; /* for rewinding parent bio */ 28 29 ··· 79 78 int bio_integrity_add_page(struct bio *bio, struct page *page, unsigned int len, 80 79 unsigned int offset); 81 80 int bio_integrity_map_user(struct bio *bio, struct iov_iter *iter); 81 + int bio_integrity_map_iter(struct bio *bio, struct uio_meta *meta); 82 82 void bio_integrity_unmap_user(struct bio *bio); 83 83 bool bio_integrity_prep(struct bio *bio); 84 84 void bio_integrity_advance(struct bio *bio, unsigned int bytes_done); ··· 106 104 } 107 105 108 106 static int bio_integrity_map_user(struct bio *bio, struct iov_iter *iter) 107 + { 108 + return -EINVAL; 109 + } 110 + 111 + static inline int bio_integrity_map_iter(struct bio *bio, struct uio_meta *meta) 109 112 { 110 113 return -EINVAL; 111 114 }