aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/bio.c54
1 files changed, 4 insertions, 50 deletions
diff --git a/fs/bio.c b/fs/bio.c
index a2f072647cdf..9d68ddb89b71 100644
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -995,48 +995,13 @@ static void bio_copy_kern_endio(struct bio *bio, int err)
995struct bio *bio_copy_kern(struct request_queue *q, void *data, unsigned int len, 995struct bio *bio_copy_kern(struct request_queue *q, void *data, unsigned int len,
996 gfp_t gfp_mask, int reading) 996 gfp_t gfp_mask, int reading)
997{ 997{
998 unsigned long kaddr = (unsigned long)data;
999 unsigned long end = (kaddr + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
1000 unsigned long start = kaddr >> PAGE_SHIFT;
1001 const int nr_pages = end - start;
1002 struct bio *bio; 998 struct bio *bio;
1003 struct bio_vec *bvec; 999 struct bio_vec *bvec;
1004 struct bio_map_data *bmd; 1000 int i;
1005 int i, ret;
1006 struct sg_iovec iov;
1007
1008 iov.iov_base = data;
1009 iov.iov_len = len;
1010
1011 bmd = bio_alloc_map_data(nr_pages, 1, gfp_mask);
1012 if (!bmd)
1013 return ERR_PTR(-ENOMEM);
1014
1015 ret = -ENOMEM;
1016 bio = bio_alloc(gfp_mask, nr_pages);
1017 if (!bio)
1018 goto out_bmd;
1019
1020 while (len) {
1021 struct page *page;
1022 unsigned int bytes = PAGE_SIZE;
1023
1024 if (bytes > len)
1025 bytes = len;
1026
1027 page = alloc_page(q->bounce_gfp | gfp_mask);
1028 if (!page) {
1029 ret = -ENOMEM;
1030 goto cleanup;
1031 }
1032
1033 if (bio_add_pc_page(q, bio, page, bytes, 0) < bytes) {
1034 ret = -EINVAL;
1035 goto cleanup;
1036 }
1037 1001
1038 len -= bytes; 1002 bio = bio_copy_user(q, NULL, (unsigned long)data, len, 1, gfp_mask);
1039 } 1003 if (IS_ERR(bio))
1004 return bio;
1040 1005
1041 if (!reading) { 1006 if (!reading) {
1042 void *p = data; 1007 void *p = data;
@@ -1049,20 +1014,9 @@ struct bio *bio_copy_kern(struct request_queue *q, void *data, unsigned int len,
1049 } 1014 }
1050 } 1015 }
1051 1016
1052 bio->bi_private = bmd;
1053 bio->bi_end_io = bio_copy_kern_endio; 1017 bio->bi_end_io = bio_copy_kern_endio;
1054 1018
1055 bio_set_map_data(bmd, bio, &iov, 1, 1);
1056 return bio; 1019 return bio;
1057cleanup:
1058 bio_for_each_segment(bvec, bio, i)
1059 __free_page(bvec->bv_page);
1060
1061 bio_put(bio);
1062out_bmd:
1063 bio_free_map_data(bmd);
1064
1065 return ERR_PTR(ret);
1066} 1020}
1067 1021
1068/* 1022/*