diff options
author | Thomas Gleixner <tglx@mtd.linutronix.de> | 2005-11-06 09:36:37 -0500 |
---|---|---|
committer | Thomas Gleixner <tglx@mtd.linutronix.de> | 2005-11-06 09:36:37 -0500 |
commit | 2fc2991175bf77395e6b15fe6b2304d3bf72da40 (patch) | |
tree | b0ff38c09240e7c00e1577d447ebe89143d752dc /fs/bio.c | |
parent | 8b491d750885ebe8e7d385ce4186c85957d67123 (diff) | |
parent | 7015faa7df829876a0f931cd18aa6d7c24a1b581 (diff) |
Merge branch 'master' of /home/tglx/work/mtd/git/linux-2.6.git/
Diffstat (limited to 'fs/bio.c')
-rw-r--r-- | fs/bio.c | 277 |
1 files changed, 210 insertions, 67 deletions
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/module.h> | 25 | #include <linux/module.h> |
26 | #include <linux/mempool.h> | 26 | #include <linux/mempool.h> |
27 | #include <linux/workqueue.h> | 27 | #include <linux/workqueue.h> |
28 | #include <scsi/sg.h> /* for struct sg_iovec */ | ||
28 | 29 | ||
29 | #define BIO_POOL_SIZE 256 | 30 | #define BIO_POOL_SIZE 256 |
30 | 31 | ||
@@ -74,7 +75,7 @@ struct bio_set { | |||
74 | */ | 75 | */ |
75 | static struct bio_set *fs_bio_set; | 76 | static struct bio_set *fs_bio_set; |
76 | 77 | ||
77 | static inline struct bio_vec *bvec_alloc_bs(unsigned int __nocast gfp_mask, int nr, unsigned long *idx, struct bio_set *bs) | 78 | static inline struct bio_vec *bvec_alloc_bs(gfp_t gfp_mask, int nr, unsigned long *idx, struct bio_set *bs) |
78 | { | 79 | { |
79 | struct bio_vec *bvl; | 80 | struct bio_vec *bvl; |
80 | struct biovec_slab *bp; | 81 | struct biovec_slab *bp; |
@@ -104,18 +105,22 @@ static inline struct bio_vec *bvec_alloc_bs(unsigned int __nocast gfp_mask, int | |||
104 | return bvl; | 105 | return bvl; |
105 | } | 106 | } |
106 | 107 | ||
107 | /* | 108 | void bio_free(struct bio *bio, struct bio_set *bio_set) |
108 | * default destructor for a bio allocated with bio_alloc_bioset() | ||
109 | */ | ||
110 | static void bio_destructor(struct bio *bio) | ||
111 | { | 109 | { |
112 | const int pool_idx = BIO_POOL_IDX(bio); | 110 | const int pool_idx = BIO_POOL_IDX(bio); |
113 | struct bio_set *bs = bio->bi_set; | ||
114 | 111 | ||
115 | BIO_BUG_ON(pool_idx >= BIOVEC_NR_POOLS); | 112 | BIO_BUG_ON(pool_idx >= BIOVEC_NR_POOLS); |
116 | 113 | ||
117 | mempool_free(bio->bi_io_vec, bs->bvec_pools[pool_idx]); | 114 | mempool_free(bio->bi_io_vec, bio_set->bvec_pools[pool_idx]); |
118 | mempool_free(bio, bs->bio_pool); | 115 | mempool_free(bio, bio_set->bio_pool); |
116 | } | ||
117 | |||
118 | /* | ||
119 | * default destructor for a bio allocated with bio_alloc_bioset() | ||
120 | */ | ||
121 | static void bio_fs_destructor(struct bio *bio) | ||
122 | { | ||
123 | bio_free(bio, fs_bio_set); | ||
119 | } | 124 | } |
120 | 125 | ||
121 | inline void bio_init(struct bio *bio) | 126 | inline void bio_init(struct bio *bio) |
@@ -150,7 +155,7 @@ inline void bio_init(struct bio *bio) | |||
150 | * allocate bio and iovecs from the memory pools specified by the | 155 | * allocate bio and iovecs from the memory pools specified by the |
151 | * bio_set structure. | 156 | * bio_set structure. |
152 | **/ | 157 | **/ |
153 | struct bio *bio_alloc_bioset(unsigned int __nocast gfp_mask, int nr_iovecs, struct bio_set *bs) | 158 | struct bio *bio_alloc_bioset(gfp_t gfp_mask, int nr_iovecs, struct bio_set *bs) |
154 | { | 159 | { |
155 | struct bio *bio = mempool_alloc(bs->bio_pool, gfp_mask); | 160 | struct bio *bio = mempool_alloc(bs->bio_pool, gfp_mask); |
156 | 161 | ||
@@ -171,16 +176,19 @@ struct bio *bio_alloc_bioset(unsigned int __nocast gfp_mask, int nr_iovecs, stru | |||
171 | bio->bi_max_vecs = bvec_slabs[idx].nr_vecs; | 176 | bio->bi_max_vecs = bvec_slabs[idx].nr_vecs; |
172 | } | 177 | } |
173 | bio->bi_io_vec = bvl; | 178 | bio->bi_io_vec = bvl; |
174 | bio->bi_destructor = bio_destructor; | ||
175 | bio->bi_set = bs; | ||
176 | } | 179 | } |
177 | out: | 180 | out: |
178 | return bio; | 181 | return bio; |
179 | } | 182 | } |
180 | 183 | ||
181 | struct bio *bio_alloc(unsigned int __nocast gfp_mask, int nr_iovecs) | 184 | struct bio *bio_alloc(gfp_t gfp_mask, int nr_iovecs) |
182 | { | 185 | { |
183 | return bio_alloc_bioset(gfp_mask, nr_iovecs, fs_bio_set); | 186 | struct bio *bio = bio_alloc_bioset(gfp_mask, nr_iovecs, fs_bio_set); |
187 | |||
188 | if (bio) | ||
189 | bio->bi_destructor = bio_fs_destructor; | ||
190 | |||
191 | return bio; | ||
184 | } | 192 | } |
185 | 193 | ||
186 | void zero_fill_bio(struct bio *bio) | 194 | void zero_fill_bio(struct bio *bio) |
@@ -248,17 +256,13 @@ inline void __bio_clone(struct bio *bio, struct bio *bio_src) | |||
248 | { | 256 | { |
249 | request_queue_t *q = bdev_get_queue(bio_src->bi_bdev); | 257 | request_queue_t *q = bdev_get_queue(bio_src->bi_bdev); |
250 | 258 | ||
251 | memcpy(bio->bi_io_vec, bio_src->bi_io_vec, bio_src->bi_max_vecs * sizeof(struct bio_vec)); | 259 | memcpy(bio->bi_io_vec, bio_src->bi_io_vec, |
260 | bio_src->bi_max_vecs * sizeof(struct bio_vec)); | ||
252 | 261 | ||
253 | bio->bi_sector = bio_src->bi_sector; | 262 | bio->bi_sector = bio_src->bi_sector; |
254 | bio->bi_bdev = bio_src->bi_bdev; | 263 | bio->bi_bdev = bio_src->bi_bdev; |
255 | bio->bi_flags |= 1 << BIO_CLONED; | 264 | bio->bi_flags |= 1 << BIO_CLONED; |
256 | bio->bi_rw = bio_src->bi_rw; | 265 | bio->bi_rw = bio_src->bi_rw; |
257 | |||
258 | /* | ||
259 | * notes -- maybe just leave bi_idx alone. assume identical mapping | ||
260 | * for the clone | ||
261 | */ | ||
262 | bio->bi_vcnt = bio_src->bi_vcnt; | 266 | bio->bi_vcnt = bio_src->bi_vcnt; |
263 | bio->bi_size = bio_src->bi_size; | 267 | bio->bi_size = bio_src->bi_size; |
264 | bio->bi_idx = bio_src->bi_idx; | 268 | bio->bi_idx = bio_src->bi_idx; |
@@ -273,12 +277,14 @@ inline void __bio_clone(struct bio *bio, struct bio *bio_src) | |||
273 | * | 277 | * |
274 | * Like __bio_clone, only also allocates the returned bio | 278 | * Like __bio_clone, only also allocates the returned bio |
275 | */ | 279 | */ |
276 | struct bio *bio_clone(struct bio *bio, unsigned int __nocast gfp_mask) | 280 | struct bio *bio_clone(struct bio *bio, gfp_t gfp_mask) |
277 | { | 281 | { |
278 | struct bio *b = bio_alloc_bioset(gfp_mask, bio->bi_max_vecs, fs_bio_set); | 282 | struct bio *b = bio_alloc_bioset(gfp_mask, bio->bi_max_vecs, fs_bio_set); |
279 | 283 | ||
280 | if (b) | 284 | if (b) { |
285 | b->bi_destructor = bio_fs_destructor; | ||
281 | __bio_clone(b, bio); | 286 | __bio_clone(b, bio); |
287 | } | ||
282 | 288 | ||
283 | return b; | 289 | return b; |
284 | } | 290 | } |
@@ -550,22 +556,34 @@ out_bmd: | |||
550 | return ERR_PTR(ret); | 556 | return ERR_PTR(ret); |
551 | } | 557 | } |
552 | 558 | ||
553 | static struct bio *__bio_map_user(request_queue_t *q, struct block_device *bdev, | 559 | static struct bio *__bio_map_user_iov(request_queue_t *q, |
554 | unsigned long uaddr, unsigned int len, | 560 | struct block_device *bdev, |
555 | int write_to_vm) | 561 | struct sg_iovec *iov, int iov_count, |
562 | int write_to_vm) | ||
556 | { | 563 | { |
557 | unsigned long end = (uaddr + len + PAGE_SIZE - 1) >> PAGE_SHIFT; | 564 | int i, j; |
558 | unsigned long start = uaddr >> PAGE_SHIFT; | 565 | int nr_pages = 0; |
559 | const int nr_pages = end - start; | ||
560 | int ret, offset, i; | ||
561 | struct page **pages; | 566 | struct page **pages; |
562 | struct bio *bio; | 567 | struct bio *bio; |
568 | int cur_page = 0; | ||
569 | int ret, offset; | ||
563 | 570 | ||
564 | /* | 571 | for (i = 0; i < iov_count; i++) { |
565 | * transfer and buffer must be aligned to at least hardsector | 572 | unsigned long uaddr = (unsigned long)iov[i].iov_base; |
566 | * size for now, in the future we can relax this restriction | 573 | unsigned long len = iov[i].iov_len; |
567 | */ | 574 | unsigned long end = (uaddr + len + PAGE_SIZE - 1) >> PAGE_SHIFT; |
568 | if ((uaddr & queue_dma_alignment(q)) || (len & queue_dma_alignment(q))) | 575 | unsigned long start = uaddr >> PAGE_SHIFT; |
576 | |||
577 | nr_pages += end - start; | ||
578 | /* | ||
579 | * transfer and buffer must be aligned to at least hardsector | ||
580 | * size for now, in the future we can relax this restriction | ||
581 | */ | ||
582 | if ((uaddr & queue_dma_alignment(q)) || (len & queue_dma_alignment(q))) | ||
583 | return ERR_PTR(-EINVAL); | ||
584 | } | ||
585 | |||
586 | if (!nr_pages) | ||
569 | return ERR_PTR(-EINVAL); | 587 | return ERR_PTR(-EINVAL); |
570 | 588 | ||
571 | bio = bio_alloc(GFP_KERNEL, nr_pages); | 589 | bio = bio_alloc(GFP_KERNEL, nr_pages); |
@@ -577,42 +595,54 @@ static struct bio *__bio_map_user(request_queue_t *q, struct block_device *bdev, | |||
577 | if (!pages) | 595 | if (!pages) |
578 | goto out; | 596 | goto out; |
579 | 597 | ||
580 | down_read(¤t->mm->mmap_sem); | 598 | memset(pages, 0, nr_pages * sizeof(struct page *)); |
581 | ret = get_user_pages(current, current->mm, uaddr, nr_pages, | 599 | |
582 | write_to_vm, 0, pages, NULL); | 600 | for (i = 0; i < iov_count; i++) { |
583 | up_read(¤t->mm->mmap_sem); | 601 | unsigned long uaddr = (unsigned long)iov[i].iov_base; |
584 | 602 | unsigned long len = iov[i].iov_len; | |
585 | if (ret < nr_pages) | 603 | unsigned long end = (uaddr + len + PAGE_SIZE - 1) >> PAGE_SHIFT; |
586 | goto out; | 604 | unsigned long start = uaddr >> PAGE_SHIFT; |
587 | 605 | const int local_nr_pages = end - start; | |
588 | bio->bi_bdev = bdev; | 606 | const int page_limit = cur_page + local_nr_pages; |
589 | 607 | ||
590 | offset = uaddr & ~PAGE_MASK; | 608 | down_read(¤t->mm->mmap_sem); |
591 | for (i = 0; i < nr_pages; i++) { | 609 | ret = get_user_pages(current, current->mm, uaddr, |
592 | unsigned int bytes = PAGE_SIZE - offset; | 610 | local_nr_pages, |
593 | 611 | write_to_vm, 0, &pages[cur_page], NULL); | |
594 | if (len <= 0) | 612 | up_read(¤t->mm->mmap_sem); |
595 | break; | 613 | |
596 | 614 | if (ret < local_nr_pages) | |
597 | if (bytes > len) | 615 | goto out_unmap; |
598 | bytes = len; | 616 | |
617 | |||
618 | offset = uaddr & ~PAGE_MASK; | ||
619 | for (j = cur_page; j < page_limit; j++) { | ||
620 | unsigned int bytes = PAGE_SIZE - offset; | ||
621 | |||
622 | if (len <= 0) | ||
623 | break; | ||
624 | |||
625 | if (bytes > len) | ||
626 | bytes = len; | ||
627 | |||
628 | /* | ||
629 | * sorry... | ||
630 | */ | ||
631 | if (__bio_add_page(q, bio, pages[j], bytes, offset) < bytes) | ||
632 | break; | ||
633 | |||
634 | len -= bytes; | ||
635 | offset = 0; | ||
636 | } | ||
599 | 637 | ||
638 | cur_page = j; | ||
600 | /* | 639 | /* |
601 | * sorry... | 640 | * release the pages we didn't map into the bio, if any |
602 | */ | 641 | */ |
603 | if (__bio_add_page(q, bio, pages[i], bytes, offset) < bytes) | 642 | while (j < page_limit) |
604 | break; | 643 | page_cache_release(pages[j++]); |
605 | |||
606 | len -= bytes; | ||
607 | offset = 0; | ||
608 | } | 644 | } |
609 | 645 | ||
610 | /* | ||
611 | * release the pages we didn't map into the bio, if any | ||
612 | */ | ||
613 | while (i < nr_pages) | ||
614 | page_cache_release(pages[i++]); | ||
615 | |||
616 | kfree(pages); | 646 | kfree(pages); |
617 | 647 | ||
618 | /* | 648 | /* |
@@ -621,9 +651,17 @@ static struct bio *__bio_map_user(request_queue_t *q, struct block_device *bdev, | |||
621 | if (!write_to_vm) | 651 | if (!write_to_vm) |
622 | bio->bi_rw |= (1 << BIO_RW); | 652 | bio->bi_rw |= (1 << BIO_RW); |
623 | 653 | ||
654 | bio->bi_bdev = bdev; | ||
624 | bio->bi_flags |= (1 << BIO_USER_MAPPED); | 655 | bio->bi_flags |= (1 << BIO_USER_MAPPED); |
625 | return bio; | 656 | return bio; |
626 | out: | 657 | |
658 | out_unmap: | ||
659 | for (i = 0; i < nr_pages; i++) { | ||
660 | if(!pages[i]) | ||
661 | break; | ||
662 | page_cache_release(pages[i]); | ||
663 | } | ||
664 | out: | ||
627 | kfree(pages); | 665 | kfree(pages); |
628 | bio_put(bio); | 666 | bio_put(bio); |
629 | return ERR_PTR(ret); | 667 | return ERR_PTR(ret); |
@@ -643,9 +681,33 @@ out: | |||
643 | struct bio *bio_map_user(request_queue_t *q, struct block_device *bdev, | 681 | struct bio *bio_map_user(request_queue_t *q, struct block_device *bdev, |
644 | unsigned long uaddr, unsigned int len, int write_to_vm) | 682 | unsigned long uaddr, unsigned int len, int write_to_vm) |
645 | { | 683 | { |
684 | struct sg_iovec iov; | ||
685 | |||
686 | iov.iov_base = (void __user *)uaddr; | ||
687 | iov.iov_len = len; | ||
688 | |||
689 | return bio_map_user_iov(q, bdev, &iov, 1, write_to_vm); | ||
690 | } | ||
691 | |||
692 | /** | ||
693 | * bio_map_user_iov - map user sg_iovec table into bio | ||
694 | * @q: the request_queue_t for the bio | ||
695 | * @bdev: destination block device | ||
696 | * @iov: the iovec. | ||
697 | * @iov_count: number of elements in the iovec | ||
698 | * @write_to_vm: bool indicating writing to pages or not | ||
699 | * | ||
700 | * Map the user space address into a bio suitable for io to a block | ||
701 | * device. Returns an error pointer in case of error. | ||
702 | */ | ||
703 | struct bio *bio_map_user_iov(request_queue_t *q, struct block_device *bdev, | ||
704 | struct sg_iovec *iov, int iov_count, | ||
705 | int write_to_vm) | ||
706 | { | ||
646 | struct bio *bio; | 707 | struct bio *bio; |
708 | int len = 0, i; | ||
647 | 709 | ||
648 | bio = __bio_map_user(q, bdev, uaddr, len, write_to_vm); | 710 | bio = __bio_map_user_iov(q, bdev, iov, iov_count, write_to_vm); |
649 | 711 | ||
650 | if (IS_ERR(bio)) | 712 | if (IS_ERR(bio)) |
651 | return bio; | 713 | return bio; |
@@ -658,6 +720,9 @@ struct bio *bio_map_user(request_queue_t *q, struct block_device *bdev, | |||
658 | */ | 720 | */ |
659 | bio_get(bio); | 721 | bio_get(bio); |
660 | 722 | ||
723 | for (i = 0; i < iov_count; i++) | ||
724 | len += iov[i].iov_len; | ||
725 | |||
661 | if (bio->bi_size == len) | 726 | if (bio->bi_size == len) |
662 | return bio; | 727 | return bio; |
663 | 728 | ||
@@ -702,6 +767,82 @@ void bio_unmap_user(struct bio *bio) | |||
702 | bio_put(bio); | 767 | bio_put(bio); |
703 | } | 768 | } |
704 | 769 | ||
770 | static int bio_map_kern_endio(struct bio *bio, unsigned int bytes_done, int err) | ||
771 | { | ||
772 | if (bio->bi_size) | ||
773 | return 1; | ||
774 | |||
775 | bio_put(bio); | ||
776 | return 0; | ||
777 | } | ||
778 | |||
779 | |||
780 | static struct bio *__bio_map_kern(request_queue_t *q, void *data, | ||
781 | unsigned int len, gfp_t gfp_mask) | ||
782 | { | ||
783 | unsigned long kaddr = (unsigned long)data; | ||
784 | unsigned long end = (kaddr + len + PAGE_SIZE - 1) >> PAGE_SHIFT; | ||
785 | unsigned long start = kaddr >> PAGE_SHIFT; | ||
786 | const int nr_pages = end - start; | ||
787 | int offset, i; | ||
788 | struct bio *bio; | ||
789 | |||
790 | bio = bio_alloc(gfp_mask, nr_pages); | ||
791 | if (!bio) | ||
792 | return ERR_PTR(-ENOMEM); | ||
793 | |||
794 | offset = offset_in_page(kaddr); | ||
795 | for (i = 0; i < nr_pages; i++) { | ||
796 | unsigned int bytes = PAGE_SIZE - offset; | ||
797 | |||
798 | if (len <= 0) | ||
799 | break; | ||
800 | |||
801 | if (bytes > len) | ||
802 | bytes = len; | ||
803 | |||
804 | if (__bio_add_page(q, bio, virt_to_page(data), bytes, | ||
805 | offset) < bytes) | ||
806 | break; | ||
807 | |||
808 | data += bytes; | ||
809 | len -= bytes; | ||
810 | offset = 0; | ||
811 | } | ||
812 | |||
813 | bio->bi_end_io = bio_map_kern_endio; | ||
814 | return bio; | ||
815 | } | ||
816 | |||
817 | /** | ||
818 | * bio_map_kern - map kernel address into bio | ||
819 | * @q: the request_queue_t for the bio | ||
820 | * @data: pointer to buffer to map | ||
821 | * @len: length in bytes | ||
822 | * @gfp_mask: allocation flags for bio allocation | ||
823 | * | ||
824 | * Map the kernel address into a bio suitable for io to a block | ||
825 | * device. Returns an error pointer in case of error. | ||
826 | */ | ||
827 | struct bio *bio_map_kern(request_queue_t *q, void *data, unsigned int len, | ||
828 | gfp_t gfp_mask) | ||
829 | { | ||
830 | struct bio *bio; | ||
831 | |||
832 | bio = __bio_map_kern(q, data, len, gfp_mask); | ||
833 | if (IS_ERR(bio)) | ||
834 | return bio; | ||
835 | |||
836 | if (bio->bi_size == len) | ||
837 | return bio; | ||
838 | |||
839 | /* | ||
840 | * Don't support partial mappings. | ||
841 | */ | ||
842 | bio_put(bio); | ||
843 | return ERR_PTR(-EINVAL); | ||
844 | } | ||
845 | |||
705 | /* | 846 | /* |
706 | * bio_set_pages_dirty() and bio_check_pages_dirty() are support functions | 847 | * bio_set_pages_dirty() and bio_check_pages_dirty() are support functions |
707 | * for performing direct-IO in BIOs. | 848 | * for performing direct-IO in BIOs. |
@@ -937,7 +1078,7 @@ struct bio_pair *bio_split(struct bio *bi, mempool_t *pool, int first_sectors) | |||
937 | return bp; | 1078 | return bp; |
938 | } | 1079 | } |
939 | 1080 | ||
940 | static void *bio_pair_alloc(unsigned int __nocast gfp_flags, void *data) | 1081 | static void *bio_pair_alloc(gfp_t gfp_flags, void *data) |
941 | { | 1082 | { |
942 | return kmalloc(sizeof(struct bio_pair), gfp_flags); | 1083 | return kmalloc(sizeof(struct bio_pair), gfp_flags); |
943 | } | 1084 | } |
@@ -1079,6 +1220,7 @@ subsys_initcall(init_bio); | |||
1079 | 1220 | ||
1080 | EXPORT_SYMBOL(bio_alloc); | 1221 | EXPORT_SYMBOL(bio_alloc); |
1081 | EXPORT_SYMBOL(bio_put); | 1222 | EXPORT_SYMBOL(bio_put); |
1223 | EXPORT_SYMBOL(bio_free); | ||
1082 | EXPORT_SYMBOL(bio_endio); | 1224 | EXPORT_SYMBOL(bio_endio); |
1083 | EXPORT_SYMBOL(bio_init); | 1225 | EXPORT_SYMBOL(bio_init); |
1084 | EXPORT_SYMBOL(__bio_clone); | 1226 | EXPORT_SYMBOL(__bio_clone); |
@@ -1089,6 +1231,7 @@ EXPORT_SYMBOL(bio_add_page); | |||
1089 | EXPORT_SYMBOL(bio_get_nr_vecs); | 1231 | EXPORT_SYMBOL(bio_get_nr_vecs); |
1090 | EXPORT_SYMBOL(bio_map_user); | 1232 | EXPORT_SYMBOL(bio_map_user); |
1091 | EXPORT_SYMBOL(bio_unmap_user); | 1233 | EXPORT_SYMBOL(bio_unmap_user); |
1234 | EXPORT_SYMBOL(bio_map_kern); | ||
1092 | EXPORT_SYMBOL(bio_pair_release); | 1235 | EXPORT_SYMBOL(bio_pair_release); |
1093 | EXPORT_SYMBOL(bio_split); | 1236 | EXPORT_SYMBOL(bio_split); |
1094 | EXPORT_SYMBOL(bio_split_pool); | 1237 | EXPORT_SYMBOL(bio_split_pool); |