diff options
Diffstat (limited to 'fs/bio.c')
-rw-r--r-- | fs/bio.c | 12 |
1 files changed, 9 insertions, 3 deletions
@@ -788,6 +788,7 @@ struct bio *bio_copy_user_iov(struct request_queue *q, | |||
788 | int i, ret; | 788 | int i, ret; |
789 | int nr_pages = 0; | 789 | int nr_pages = 0; |
790 | unsigned int len = 0; | 790 | unsigned int len = 0; |
791 | unsigned int offset = map_data ? map_data->offset & ~PAGE_MASK : 0; | ||
791 | 792 | ||
792 | for (i = 0; i < iov_count; i++) { | 793 | for (i = 0; i < iov_count; i++) { |
793 | unsigned long uaddr; | 794 | unsigned long uaddr; |
@@ -814,12 +815,16 @@ struct bio *bio_copy_user_iov(struct request_queue *q, | |||
814 | bio->bi_rw |= (!write_to_vm << BIO_RW); | 815 | bio->bi_rw |= (!write_to_vm << BIO_RW); |
815 | 816 | ||
816 | ret = 0; | 817 | ret = 0; |
817 | i = 0; | 818 | |
818 | if (map_data) | 819 | if (map_data) { |
819 | nr_pages = 1 << map_data->page_order; | 820 | nr_pages = 1 << map_data->page_order; |
821 | i = map_data->offset / PAGE_SIZE; | ||
822 | } | ||
820 | while (len) { | 823 | while (len) { |
821 | unsigned int bytes = PAGE_SIZE; | 824 | unsigned int bytes = PAGE_SIZE; |
822 | 825 | ||
826 | bytes -= offset; | ||
827 | |||
823 | if (bytes > len) | 828 | if (bytes > len) |
824 | bytes = len; | 829 | bytes = len; |
825 | 830 | ||
@@ -841,10 +846,11 @@ struct bio *bio_copy_user_iov(struct request_queue *q, | |||
841 | } | 846 | } |
842 | } | 847 | } |
843 | 848 | ||
844 | if (bio_add_pc_page(q, bio, page, bytes, 0) < bytes) | 849 | if (bio_add_pc_page(q, bio, page, bytes, offset) < bytes) |
845 | break; | 850 | break; |
846 | 851 | ||
847 | len -= bytes; | 852 | len -= bytes; |
853 | offset = 0; | ||
848 | } | 854 | } |
849 | 855 | ||
850 | if (ret) | 856 | if (ret) |