diff options
Diffstat (limited to 'fs/bio.c')
-rw-r--r-- | fs/bio.c | 33 |
1 files changed, 20 insertions, 13 deletions
@@ -238,7 +238,7 @@ void bio_free(struct bio *bio, struct bio_set *bs) | |||
238 | bvec_free_bs(bs, bio->bi_io_vec, BIO_POOL_IDX(bio)); | 238 | bvec_free_bs(bs, bio->bi_io_vec, BIO_POOL_IDX(bio)); |
239 | 239 | ||
240 | if (bio_integrity(bio)) | 240 | if (bio_integrity(bio)) |
241 | bio_integrity_free(bio); | 241 | bio_integrity_free(bio, bs); |
242 | 242 | ||
243 | /* | 243 | /* |
244 | * If we have front padding, adjust the bio pointer before freeing | 244 | * If we have front padding, adjust the bio pointer before freeing |
@@ -341,7 +341,7 @@ struct bio *bio_alloc(gfp_t gfp_mask, int nr_iovecs) | |||
341 | static void bio_kmalloc_destructor(struct bio *bio) | 341 | static void bio_kmalloc_destructor(struct bio *bio) |
342 | { | 342 | { |
343 | if (bio_integrity(bio)) | 343 | if (bio_integrity(bio)) |
344 | bio_integrity_free(bio); | 344 | bio_integrity_free(bio, fs_bio_set); |
345 | kfree(bio); | 345 | kfree(bio); |
346 | } | 346 | } |
347 | 347 | ||
@@ -472,7 +472,7 @@ struct bio *bio_clone(struct bio *bio, gfp_t gfp_mask) | |||
472 | if (bio_integrity(bio)) { | 472 | if (bio_integrity(bio)) { |
473 | int ret; | 473 | int ret; |
474 | 474 | ||
475 | ret = bio_integrity_clone(b, bio, gfp_mask); | 475 | ret = bio_integrity_clone(b, bio, gfp_mask, fs_bio_set); |
476 | 476 | ||
477 | if (ret < 0) { | 477 | if (ret < 0) { |
478 | bio_put(b); | 478 | bio_put(b); |
@@ -705,14 +705,13 @@ static struct bio_map_data *bio_alloc_map_data(int nr_segs, int iov_count, | |||
705 | } | 705 | } |
706 | 706 | ||
707 | static int __bio_copy_iov(struct bio *bio, struct bio_vec *iovecs, | 707 | static int __bio_copy_iov(struct bio *bio, struct bio_vec *iovecs, |
708 | struct sg_iovec *iov, int iov_count, int uncopy, | 708 | struct sg_iovec *iov, int iov_count, |
709 | int do_free_page) | 709 | int to_user, int from_user, int do_free_page) |
710 | { | 710 | { |
711 | int ret = 0, i; | 711 | int ret = 0, i; |
712 | struct bio_vec *bvec; | 712 | struct bio_vec *bvec; |
713 | int iov_idx = 0; | 713 | int iov_idx = 0; |
714 | unsigned int iov_off = 0; | 714 | unsigned int iov_off = 0; |
715 | int read = bio_data_dir(bio) == READ; | ||
716 | 715 | ||
717 | __bio_for_each_segment(bvec, bio, i, 0) { | 716 | __bio_for_each_segment(bvec, bio, i, 0) { |
718 | char *bv_addr = page_address(bvec->bv_page); | 717 | char *bv_addr = page_address(bvec->bv_page); |
@@ -727,13 +726,14 @@ static int __bio_copy_iov(struct bio *bio, struct bio_vec *iovecs, | |||
727 | iov_addr = iov[iov_idx].iov_base + iov_off; | 726 | iov_addr = iov[iov_idx].iov_base + iov_off; |
728 | 727 | ||
729 | if (!ret) { | 728 | if (!ret) { |
730 | if (!read && !uncopy) | 729 | if (to_user) |
731 | ret = copy_from_user(bv_addr, iov_addr, | ||
732 | bytes); | ||
733 | if (read && uncopy) | ||
734 | ret = copy_to_user(iov_addr, bv_addr, | 730 | ret = copy_to_user(iov_addr, bv_addr, |
735 | bytes); | 731 | bytes); |
736 | 732 | ||
733 | if (from_user) | ||
734 | ret = copy_from_user(bv_addr, iov_addr, | ||
735 | bytes); | ||
736 | |||
737 | if (ret) | 737 | if (ret) |
738 | ret = -EFAULT; | 738 | ret = -EFAULT; |
739 | } | 739 | } |
@@ -770,7 +770,8 @@ int bio_uncopy_user(struct bio *bio) | |||
770 | 770 | ||
771 | if (!bio_flagged(bio, BIO_NULL_MAPPED)) | 771 | if (!bio_flagged(bio, BIO_NULL_MAPPED)) |
772 | ret = __bio_copy_iov(bio, bmd->iovecs, bmd->sgvecs, | 772 | ret = __bio_copy_iov(bio, bmd->iovecs, bmd->sgvecs, |
773 | bmd->nr_sgvecs, 1, bmd->is_our_pages); | 773 | bmd->nr_sgvecs, bio_data_dir(bio) == READ, |
774 | 0, bmd->is_our_pages); | ||
774 | bio_free_map_data(bmd); | 775 | bio_free_map_data(bmd); |
775 | bio_put(bio); | 776 | bio_put(bio); |
776 | return ret; | 777 | return ret; |
@@ -875,8 +876,9 @@ struct bio *bio_copy_user_iov(struct request_queue *q, | |||
875 | /* | 876 | /* |
876 | * success | 877 | * success |
877 | */ | 878 | */ |
878 | if (!write_to_vm && (!map_data || !map_data->null_mapped)) { | 879 | if ((!write_to_vm && (!map_data || !map_data->null_mapped)) || |
879 | ret = __bio_copy_iov(bio, bio->bi_io_vec, iov, iov_count, 0, 0); | 880 | (map_data && map_data->from_user)) { |
881 | ret = __bio_copy_iov(bio, bio->bi_io_vec, iov, iov_count, 0, 1, 0); | ||
880 | if (ret) | 882 | if (ret) |
881 | goto cleanup; | 883 | goto cleanup; |
882 | } | 884 | } |
@@ -1539,6 +1541,7 @@ void bioset_free(struct bio_set *bs) | |||
1539 | if (bs->bio_pool) | 1541 | if (bs->bio_pool) |
1540 | mempool_destroy(bs->bio_pool); | 1542 | mempool_destroy(bs->bio_pool); |
1541 | 1543 | ||
1544 | bioset_integrity_free(bs); | ||
1542 | biovec_free_pools(bs); | 1545 | biovec_free_pools(bs); |
1543 | bio_put_slab(bs); | 1546 | bio_put_slab(bs); |
1544 | 1547 | ||
@@ -1579,6 +1582,9 @@ struct bio_set *bioset_create(unsigned int pool_size, unsigned int front_pad) | |||
1579 | if (!bs->bio_pool) | 1582 | if (!bs->bio_pool) |
1580 | goto bad; | 1583 | goto bad; |
1581 | 1584 | ||
1585 | if (bioset_integrity_create(bs, pool_size)) | ||
1586 | goto bad; | ||
1587 | |||
1582 | if (!biovec_create_pools(bs, pool_size)) | 1588 | if (!biovec_create_pools(bs, pool_size)) |
1583 | return bs; | 1589 | return bs; |
1584 | 1590 | ||
@@ -1616,6 +1622,7 @@ static int __init init_bio(void) | |||
1616 | if (!bio_slabs) | 1622 | if (!bio_slabs) |
1617 | panic("bio: can't allocate bios\n"); | 1623 | panic("bio: can't allocate bios\n"); |
1618 | 1624 | ||
1625 | bio_integrity_init(); | ||
1619 | biovec_init_slabs(); | 1626 | biovec_init_slabs(); |
1620 | 1627 | ||
1621 | fs_bio_set = bioset_create(BIO_POOL_SIZE, 0); | 1628 | fs_bio_set = bioset_create(BIO_POOL_SIZE, 0); |