diff options
-rw-r--r-- | drivers/scsi/sg.c | 4 | ||||
-rw-r--r-- | fs/bio.c | 22 | ||||
-rw-r--r-- | include/linux/blkdev.h | 1 |
3 files changed, 17 insertions, 10 deletions
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 4d6f2fe1cfe9..9230402c45af 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c | |||
@@ -1656,6 +1656,10 @@ static int sg_start_req(Sg_request *srp, unsigned char *cmd) | |||
1656 | md->nr_entries = req_schp->k_use_sg; | 1656 | md->nr_entries = req_schp->k_use_sg; |
1657 | md->offset = 0; | 1657 | md->offset = 0; |
1658 | md->null_mapped = hp->dxferp ? 0 : 1; | 1658 | md->null_mapped = hp->dxferp ? 0 : 1; |
1659 | if (dxfer_dir == SG_DXFER_TO_FROM_DEV) | ||
1660 | md->from_user = 1; | ||
1661 | else | ||
1662 | md->from_user = 0; | ||
1659 | } | 1663 | } |
1660 | 1664 | ||
1661 | if (iov_count) { | 1665 | if (iov_count) { |
@@ -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 | } |
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index bb3d39978701..0146e0fecf1a 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h | |||
@@ -723,6 +723,7 @@ struct rq_map_data { | |||
723 | int nr_entries; | 723 | int nr_entries; |
724 | unsigned long offset; | 724 | unsigned long offset; |
725 | int null_mapped; | 725 | int null_mapped; |
726 | int from_user; | ||
726 | }; | 727 | }; |
727 | 728 | ||
728 | struct req_iterator { | 729 | struct req_iterator { |