1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18#include <linux/mm.h>
19#include <linux/swap.h>
20#include <linux/bio.h>
21#include <linux/blkdev.h>
22#include <linux/slab.h>
23#include <linux/init.h>
24#include <linux/kernel.h>
25#include <linux/module.h>
26#include <linux/mempool.h>
27#include <linux/workqueue.h>
28
29#define BIO_POOL_SIZE 256
30
31static mempool_t *bio_pool;
32static kmem_cache_t *bio_slab;
33
34#define BIOVEC_NR_POOLS 6
35
36
37
38
39
40#define BIO_SPLIT_ENTRIES 8
41mempool_t *bio_split_pool;
42
43struct biovec_pool {
44 int nr_vecs;
45 char *name;
46 kmem_cache_t *slab;
47 mempool_t *pool;
48};
49
50
51
52
53
54
55
56#define BV(x) { .nr_vecs = x, .name = "biovec-"__stringify(x) }
57static struct biovec_pool bvec_array[BIOVEC_NR_POOLS] = {
58 BV(1), BV(4), BV(16), BV(64), BV(128), BV(BIO_MAX_PAGES),
59};
60#undef BV
61
62static inline struct bio_vec *bvec_alloc(int gfp_mask, int nr, unsigned long *idx)
63{
64 struct biovec_pool *bp;
65 struct bio_vec *bvl;
66
67
68
69
70 switch (nr) {
71 case 1 : *idx = 0; break;
72 case 2 ... 4: *idx = 1; break;
73 case 5 ... 16: *idx = 2; break;
74 case 17 ... 64: *idx = 3; break;
75 case 65 ... 128: *idx = 4; break;
76 case 129 ... BIO_MAX_PAGES: *idx = 5; break;
77 default:
78 return NULL;
79 }
80
81
82
83 bp = bvec_array + *idx;
84
85 bvl = mempool_alloc(bp->pool, gfp_mask);
86 if (bvl)
87 memset(bvl, 0, bp->nr_vecs * sizeof(struct bio_vec));
88 return bvl;
89}
90
91
92
93
94void bio_destructor(struct bio *bio)
95{
96 const int pool_idx = BIO_POOL_IDX(bio);
97 struct biovec_pool *bp = bvec_array + pool_idx;
98
99 BIO_BUG_ON(pool_idx >= BIOVEC_NR_POOLS);
100
101 mempool_free(bio->bi_io_vec, bp->pool);
102 mempool_free(bio, bio_pool);
103}
104
105inline void bio_init(struct bio *bio)
106{
107 bio->bi_next = NULL;
108 bio->bi_flags = 1 << BIO_UPTODATE;
109 bio->bi_rw = 0;
110 bio->bi_vcnt = 0;
111 bio->bi_idx = 0;
112 bio->bi_phys_segments = 0;
113 bio->bi_hw_segments = 0;
114 bio->bi_hw_front_size = 0;
115 bio->bi_hw_back_size = 0;
116 bio->bi_size = 0;
117 bio->bi_max_vecs = 0;
118 bio->bi_end_io = NULL;
119 atomic_set(&bio->bi_cnt, 1);
120 bio->bi_private = NULL;
121}
122
123
124
125
126
127
128
129
130
131
132
133struct bio *bio_alloc(int gfp_mask, int nr_iovecs)
134{
135 struct bio *bio = mempool_alloc(bio_pool, gfp_mask);
136
137 if (likely(bio)) {
138 struct bio_vec *bvl = NULL;
139
140 bio_init(bio);
141 if (likely(nr_iovecs)) {
142 unsigned long idx;
143
144 bvl = bvec_alloc(gfp_mask, nr_iovecs, &idx);
145 if (unlikely(!bvl)) {
146 mempool_free(bio, bio_pool);
147 bio = NULL;
148 goto out;
149 }
150 bio->bi_flags |= idx << BIO_POOL_OFFSET;
151 bio->bi_max_vecs = bvec_array[idx].nr_vecs;
152 }
153 bio->bi_io_vec = bvl;
154 bio->bi_destructor = bio_destructor;
155 }
156out:
157 return bio;
158}
159
160
161
162
163
164
165
166
167
168void bio_put(struct bio *bio)
169{
170 BIO_BUG_ON(!atomic_read(&bio->bi_cnt));
171
172
173
174
175 if (atomic_dec_and_test(&bio->bi_cnt)) {
176 bio->bi_next = NULL;
177 bio->bi_destructor(bio);
178 }
179}
180
181inline int bio_phys_segments(request_queue_t *q, struct bio *bio)
182{
183 if (unlikely(!bio_flagged(bio, BIO_SEG_VALID)))
184 blk_recount_segments(q, bio);
185
186 return bio->bi_phys_segments;
187}
188
189inline int bio_hw_segments(request_queue_t *q, struct bio *bio)
190{
191 if (unlikely(!bio_flagged(bio, BIO_SEG_VALID)))
192 blk_recount_segments(q, bio);
193
194 return bio->bi_hw_segments;
195}
196
197
198
199
200
201
202
203
204
205
206inline void __bio_clone(struct bio *bio, struct bio *bio_src)
207{
208 request_queue_t *q = bdev_get_queue(bio_src->bi_bdev);
209
210 memcpy(bio->bi_io_vec, bio_src->bi_io_vec, bio_src->bi_max_vecs * sizeof(struct bio_vec));
211
212 bio->bi_sector = bio_src->bi_sector;
213 bio->bi_bdev = bio_src->bi_bdev;
214 bio->bi_flags |= 1 << BIO_CLONED;
215 bio->bi_rw = bio_src->bi_rw;
216
217
218
219
220
221 bio->bi_vcnt = bio_src->bi_vcnt;
222 bio->bi_size = bio_src->bi_size;
223 bio->bi_idx = bio_src->bi_idx;
224 bio_phys_segments(q, bio);
225 bio_hw_segments(q, bio);
226}
227
228
229
230
231
232
233
234
235struct bio *bio_clone(struct bio *bio, int gfp_mask)
236{
237 struct bio *b = bio_alloc(gfp_mask, bio->bi_max_vecs);
238
239 if (b)
240 __bio_clone(b, bio);
241
242 return b;
243}
244
245
246
247
248
249
250
251
252
253
254int bio_get_nr_vecs(struct block_device *bdev)
255{
256 request_queue_t *q = bdev_get_queue(bdev);
257 int nr_pages;
258
259 nr_pages = ((q->max_sectors << 9) + PAGE_SIZE - 1) >> PAGE_SHIFT;
260 if (nr_pages > q->max_phys_segments)
261 nr_pages = q->max_phys_segments;
262 if (nr_pages > q->max_hw_segments)
263 nr_pages = q->max_hw_segments;
264
265 return nr_pages;
266}
267
268static int __bio_add_page(request_queue_t *q, struct bio *bio, struct page
269 *page, unsigned int len, unsigned int offset)
270{
271 int retried_segments = 0;
272 struct bio_vec *bvec;
273
274
275
276
277 if (unlikely(bio_flagged(bio, BIO_CLONED)))
278 return 0;
279
280 if (bio->bi_vcnt >= bio->bi_max_vecs)
281 return 0;
282
283 if (((bio->bi_size + len) >> 9) > q->max_sectors)
284 return 0;
285
286
287
288
289
290
291 while (bio->bi_phys_segments >= q->max_phys_segments
292 || bio->bi_hw_segments >= q->max_hw_segments
293 || BIOVEC_VIRT_OVERSIZE(bio->bi_size)) {
294
295 if (retried_segments)
296 return 0;
297
298 retried_segments = 1;
299 blk_recount_segments(q, bio);
300 }
301
302
303
304
305
306 bvec = &bio->bi_io_vec[bio->bi_vcnt];
307 bvec->bv_page = page;
308 bvec->bv_len = len;
309 bvec->bv_offset = offset;
310
311
312
313
314
315
316 if (q->merge_bvec_fn) {
317
318
319
320
321 if (q->merge_bvec_fn(q, bio, bvec) < len) {
322 bvec->bv_page = NULL;
323 bvec->bv_len = 0;
324 bvec->bv_offset = 0;
325 return 0;
326 }
327 }
328
329
330 if (bio->bi_vcnt && (BIOVEC_PHYS_MERGEABLE(bvec-1, bvec) ||
331 BIOVEC_VIRT_MERGEABLE(bvec-1, bvec)))
332 bio->bi_flags &= ~(1 << BIO_SEG_VALID);
333
334 bio->bi_vcnt++;
335 bio->bi_phys_segments++;
336 bio->bi_hw_segments++;
337 bio->bi_size += len;
338 return len;
339}
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354int bio_add_page(struct bio *bio, struct page *page, unsigned int len,
355 unsigned int offset)
356{
357 return __bio_add_page(bdev_get_queue(bio->bi_bdev), bio, page,
358 len, offset);
359}
360
361struct bio_map_data {
362 struct bio_vec *iovecs;
363 void __user *userptr;
364};
365
366static void bio_set_map_data(struct bio_map_data *bmd, struct bio *bio)
367{
368 memcpy(bmd->iovecs, bio->bi_io_vec, sizeof(struct bio_vec) * bio->bi_vcnt);
369 bio->bi_private = bmd;
370}
371
372static void bio_free_map_data(struct bio_map_data *bmd)
373{
374 kfree(bmd->iovecs);
375 kfree(bmd);
376}
377
378static struct bio_map_data *bio_alloc_map_data(int nr_segs)
379{
380 struct bio_map_data *bmd = kmalloc(sizeof(*bmd), GFP_KERNEL);
381
382 if (!bmd)
383 return NULL;
384
385 bmd->iovecs = kmalloc(sizeof(struct bio_vec) * nr_segs, GFP_KERNEL);
386 if (bmd->iovecs)
387 return bmd;
388
389 kfree(bmd);
390 return NULL;
391}
392
393
394
395
396
397
398
399
400int bio_uncopy_user(struct bio *bio)
401{
402 struct bio_map_data *bmd = bio->bi_private;
403 const int read = bio_data_dir(bio) == READ;
404 struct bio_vec *bvec;
405 int i, ret = 0;
406
407 __bio_for_each_segment(bvec, bio, i, 0) {
408 char *addr = page_address(bvec->bv_page);
409 unsigned int len = bmd->iovecs[i].bv_len;
410
411 if (read && !ret && copy_to_user(bmd->userptr, addr, len))
412 ret = -EFAULT;
413
414 __free_page(bvec->bv_page);
415 bmd->userptr += len;
416 }
417 bio_free_map_data(bmd);
418 bio_put(bio);
419 return ret;
420}
421
422
423
424
425
426
427
428
429
430
431
432
433struct bio *bio_copy_user(request_queue_t *q, unsigned long uaddr,
434 unsigned int len, int write_to_vm)
435{
436 unsigned long end = (uaddr + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
437 unsigned long start = uaddr >> PAGE_SHIFT;
438 struct bio_map_data *bmd;
439 struct bio_vec *bvec;
440 struct page *page;
441 struct bio *bio;
442 int i, ret;
443
444 bmd = bio_alloc_map_data(end - start);
445 if (!bmd)
446 return ERR_PTR(-ENOMEM);
447
448 bmd->userptr = (void __user *) uaddr;
449
450 ret = -ENOMEM;
451 bio = bio_alloc(GFP_KERNEL, end - start);
452 if (!bio)
453 goto out_bmd;
454
455 bio->bi_rw |= (!write_to_vm << BIO_RW);
456
457 ret = 0;
458 while (len) {
459 unsigned int bytes = PAGE_SIZE;
460
461 if (bytes > len)
462 bytes = len;
463
464 page = alloc_page(q->bounce_gfp | GFP_KERNEL);
465 if (!page) {
466 ret = -ENOMEM;
467 break;
468 }
469
470 if (__bio_add_page(q, bio, page, bytes, 0) < bytes) {
471 ret = -EINVAL;
472 break;
473 }
474
475 len -= bytes;
476 }
477
478 if (ret)
479 goto cleanup;
480
481
482
483
484 if (!write_to_vm) {
485 char __user *p = (char __user *) uaddr;
486
487
488
489
490 ret = -EFAULT;
491 bio_for_each_segment(bvec, bio, i) {
492 char *addr = page_address(bvec->bv_page);
493
494 if (copy_from_user(addr, p, bvec->bv_len))
495 goto cleanup;
496 p += bvec->bv_len;
497 }
498 }
499
500 bio_set_map_data(bmd, bio);
501 return bio;
502cleanup:
503 bio_for_each_segment(bvec, bio, i)
504 __free_page(bvec->bv_page);
505
506 bio_put(bio);
507out_bmd:
508 bio_free_map_data(bmd);
509 return ERR_PTR(ret);
510}
511
512static struct bio *__bio_map_user(request_queue_t *q, struct block_device *bdev,
513 unsigned long uaddr, unsigned int len,
514 int write_to_vm)
515{
516 unsigned long end = (uaddr + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
517 unsigned long start = uaddr >> PAGE_SHIFT;
518 const int nr_pages = end - start;
519 int ret, offset, i;
520 struct page **pages;
521 struct bio *bio;
522
523
524
525
526
527 if ((uaddr & queue_dma_alignment(q)) || (len & queue_dma_alignment(q)))
528 return ERR_PTR(-EINVAL);
529
530 bio = bio_alloc(GFP_KERNEL, nr_pages);
531 if (!bio)
532 return ERR_PTR(-ENOMEM);
533
534 ret = -ENOMEM;
535 pages = kcalloc(nr_pages, sizeof(struct page *), GFP_KERNEL);
536 if (!pages)
537 goto out;
538
539 down_read(¤t->mm->mmap_sem);
540 ret = get_user_pages(current, current->mm, uaddr, nr_pages,
541 write_to_vm, 0, pages, NULL);
542 up_read(¤t->mm->mmap_sem);
543
544 if (ret < nr_pages) {
545 ret = -EFAULT;
546 goto out_unmap;
547 }
548
549 bio->bi_bdev = bdev;
550
551 offset = uaddr & ~PAGE_MASK;
552 for (i = 0; i < nr_pages; i++) {
553 unsigned int bytes = PAGE_SIZE - offset;
554
555 if (len <= 0)
556 break;
557
558 if (bytes > len)
559 bytes = len;
560
561
562
563
564 if (__bio_add_page(q, bio, pages[i], bytes, offset) < bytes)
565 break;
566
567 len -= bytes;
568 offset = 0;
569 }
570
571
572
573
574 while (i < nr_pages)
575 page_cache_release(pages[i++]);
576
577 kfree(pages);
578
579
580
581
582 if (!write_to_vm)
583 bio->bi_rw |= (1 << BIO_RW);
584
585 bio->bi_flags |= (1 << BIO_USER_MAPPED);
586 return bio;
587
588out_unmap:
589 for (i = 0; i < nr_pages; i++) {
590 if(!pages[i])
591 break;
592 page_cache_release(pages[i]);
593 }
594out:
595 kfree(pages);
596 bio_put(bio);
597 return ERR_PTR(ret);
598}
599
600
601
602
603
604
605
606
607
608
609
610struct bio *bio_map_user(request_queue_t *q, struct block_device *bdev,
611 unsigned long uaddr, unsigned int len, int write_to_vm)
612{
613 struct bio *bio;
614
615 bio = __bio_map_user(q, bdev, uaddr, len, write_to_vm);
616
617 if (IS_ERR(bio))
618 return bio;
619
620
621
622
623
624
625
626 bio_get(bio);
627
628 if (bio->bi_size == len)
629 return bio;
630
631
632
633
634 bio_endio(bio, bio->bi_size, 0);
635 bio_unmap_user(bio);
636 return ERR_PTR(-EINVAL);
637}
638
639static void __bio_unmap_user(struct bio *bio)
640{
641 struct bio_vec *bvec;
642 int i;
643
644
645
646
647 __bio_for_each_segment(bvec, bio, i, 0) {
648 if ((bio_data_dir(bio) == READ) &&
649 !PageCompound(bvec->bv_page))
650 set_page_dirty_lock(bvec->bv_page);
651
652 page_cache_release(bvec->bv_page);
653 }
654
655 bio_put(bio);
656}
657
658
659
660
661
662
663
664
665
666
667void bio_unmap_user(struct bio *bio)
668{
669 __bio_unmap_user(bio);
670 bio_put(bio);
671}
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702void bio_set_pages_dirty(struct bio *bio)
703{
704 struct bio_vec *bvec = bio->bi_io_vec;
705 int i;
706
707 for (i = 0; i < bio->bi_vcnt; i++) {
708 struct page *page = bvec[i].bv_page;
709
710 if (page && !PageCompound(page))
711 set_page_dirty_lock(page);
712 }
713}
714
715static void bio_release_pages(struct bio *bio)
716{
717 struct bio_vec *bvec = bio->bi_io_vec;
718 int i;
719
720 for (i = 0; i < bio->bi_vcnt; i++) {
721 struct page *page = bvec[i].bv_page;
722
723 if (page)
724 put_page(page);
725 }
726}
727
728
729
730
731
732
733
734
735
736
737
738
739static void bio_dirty_fn(void *data);
740
741static DECLARE_WORK(bio_dirty_work, bio_dirty_fn, NULL);
742static spinlock_t bio_dirty_lock = SPIN_LOCK_UNLOCKED;
743static struct bio *bio_dirty_list;
744
745
746
747
748static void bio_dirty_fn(void *data)
749{
750 unsigned long flags;
751 struct bio *bio;
752
753 spin_lock_irqsave(&bio_dirty_lock, flags);
754 bio = bio_dirty_list;
755 bio_dirty_list = NULL;
756 spin_unlock_irqrestore(&bio_dirty_lock, flags);
757
758 while (bio) {
759 struct bio *next = bio->bi_private;
760
761 bio_set_pages_dirty(bio);
762 bio_release_pages(bio);
763 bio_put(bio);
764 bio = next;
765 }
766}
767
768void bio_check_pages_dirty(struct bio *bio)
769{
770 struct bio_vec *bvec = bio->bi_io_vec;
771 int nr_clean_pages = 0;
772 int i;
773
774 for (i = 0; i < bio->bi_vcnt; i++) {
775 struct page *page = bvec[i].bv_page;
776
777 if (PageDirty(page) || PageCompound(page)) {
778 page_cache_release(page);
779 bvec[i].bv_page = NULL;
780 } else {
781 nr_clean_pages++;
782 }
783 }
784
785 if (nr_clean_pages) {
786 unsigned long flags;
787
788 spin_lock_irqsave(&bio_dirty_lock, flags);
789 bio->bi_private = bio_dirty_list;
790 bio_dirty_list = bio;
791 spin_unlock_irqrestore(&bio_dirty_lock, flags);
792 schedule_work(&bio_dirty_work);
793 } else {
794 bio_put(bio);
795 }
796}
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813void bio_endio(struct bio *bio, unsigned int bytes_done, int error)
814{
815 if (error)
816 clear_bit(BIO_UPTODATE, &bio->bi_flags);
817
818 if (unlikely(bytes_done > bio->bi_size)) {
819 printk("%s: want %u bytes done, only %u left\n", __FUNCTION__,
820 bytes_done, bio->bi_size);
821 bytes_done = bio->bi_size;
822 }
823
824 bio->bi_size -= bytes_done;
825 bio->bi_sector += (bytes_done >> 9);
826
827 if (bio->bi_end_io)
828 bio->bi_end_io(bio, bytes_done, error);
829}
830
831void bio_pair_release(struct bio_pair *bp)
832{
833 if (atomic_dec_and_test(&bp->cnt)) {
834 struct bio *master = bp->bio1.bi_private;
835
836 bio_endio(master, master->bi_size, bp->error);
837 mempool_free(bp, bp->bio2.bi_private);
838 }
839}
840
841static int bio_pair_end_1(struct bio * bi, unsigned int done, int err)
842{
843 struct bio_pair *bp = container_of(bi, struct bio_pair, bio1);
844
845 if (err)
846 bp->error = err;
847
848 if (bi->bi_size)
849 return 1;
850
851 bio_pair_release(bp);
852 return 0;
853}
854
855static int bio_pair_end_2(struct bio * bi, unsigned int done, int err)
856{
857 struct bio_pair *bp = container_of(bi, struct bio_pair, bio2);
858
859 if (err)
860 bp->error = err;
861
862 if (bi->bi_size)
863 return 1;
864
865 bio_pair_release(bp);
866 return 0;
867}
868
869
870
871
872
873struct bio_pair *bio_split(struct bio *bi, mempool_t *pool, int first_sectors)
874{
875 struct bio_pair *bp = mempool_alloc(pool, GFP_NOIO);
876
877 if (!bp)
878 return bp;
879
880 BUG_ON(bi->bi_vcnt != 1);
881 BUG_ON(bi->bi_idx != 0);
882 atomic_set(&bp->cnt, 3);
883 bp->error = 0;
884 bp->bio1 = *bi;
885 bp->bio2 = *bi;
886 bp->bio2.bi_sector += first_sectors;
887 bp->bio2.bi_size -= first_sectors << 9;
888 bp->bio1.bi_size = first_sectors << 9;
889
890 bp->bv1 = bi->bi_io_vec[0];
891 bp->bv2 = bi->bi_io_vec[0];
892 bp->bv2.bv_offset += first_sectors << 9;
893 bp->bv2.bv_len -= first_sectors << 9;
894 bp->bv1.bv_len = first_sectors << 9;
895
896 bp->bio1.bi_io_vec = &bp->bv1;
897 bp->bio2.bi_io_vec = &bp->bv2;
898
899 bp->bio1.bi_end_io = bio_pair_end_1;
900 bp->bio2.bi_end_io = bio_pair_end_2;
901
902 bp->bio1.bi_private = bi;
903 bp->bio2.bi_private = pool;
904
905 return bp;
906}
907
908static void *bio_pair_alloc(int gfp_flags, void *data)
909{
910 return kmalloc(sizeof(struct bio_pair), gfp_flags);
911}
912
913static void bio_pair_free(void *bp, void *data)
914{
915 kfree(bp);
916}
917
918static void __init biovec_init_pools(void)
919{
920 int i, size, megabytes, pool_entries = BIO_POOL_SIZE;
921 int scale = BIOVEC_NR_POOLS;
922
923 megabytes = nr_free_pages() >> (20 - PAGE_SHIFT);
924
925
926
927
928 if (megabytes <= 16)
929 scale = 0;
930 else if (megabytes <= 32)
931 scale = 1;
932 else if (megabytes <= 64)
933 scale = 2;
934 else if (megabytes <= 96)
935 scale = 3;
936 else if (megabytes <= 128)
937 scale = 4;
938
939
940
941
942 pool_entries = megabytes * 2;
943 if (pool_entries > 256)
944 pool_entries = 256;
945
946 for (i = 0; i < BIOVEC_NR_POOLS; i++) {
947 struct biovec_pool *bp = bvec_array + i;
948
949 size = bp->nr_vecs * sizeof(struct bio_vec);
950
951 bp->slab = kmem_cache_create(bp->name, size, 0,
952 SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL);
953
954 if (i >= scale)
955 pool_entries >>= 1;
956
957 bp->pool = mempool_create(pool_entries, mempool_alloc_slab,
958 mempool_free_slab, bp->slab);
959 if (!bp->pool)
960 panic("biovec: can't init mempool\n");
961 }
962}
963
964static int __init init_bio(void)
965{
966 bio_slab = kmem_cache_create("bio", sizeof(struct bio), 0,
967 SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL);
968 bio_pool = mempool_create(BIO_POOL_SIZE, mempool_alloc_slab,
969 mempool_free_slab, bio_slab);
970 if (!bio_pool)
971 panic("bio: can't create mempool\n");
972
973 biovec_init_pools();
974
975 bio_split_pool = mempool_create(BIO_SPLIT_ENTRIES,
976 bio_pair_alloc, bio_pair_free, NULL);
977 if (!bio_split_pool)
978 panic("bio: can't create split pool\n");
979
980 return 0;
981}
982
983subsys_initcall(init_bio);
984
985EXPORT_SYMBOL(bio_alloc);
986EXPORT_SYMBOL(bio_put);
987EXPORT_SYMBOL(bio_endio);
988EXPORT_SYMBOL(bio_init);
989EXPORT_SYMBOL(__bio_clone);
990EXPORT_SYMBOL(bio_clone);
991EXPORT_SYMBOL(bio_phys_segments);
992EXPORT_SYMBOL(bio_hw_segments);
993EXPORT_SYMBOL(bio_add_page);
994EXPORT_SYMBOL(bio_get_nr_vecs);
995EXPORT_SYMBOL(bio_map_user);
996EXPORT_SYMBOL(bio_unmap_user);
997EXPORT_SYMBOL(bio_pair_release);
998EXPORT_SYMBOL(bio_split);
999EXPORT_SYMBOL(bio_split_pool);
1000EXPORT_SYMBOL(bio_copy_user);
1001EXPORT_SYMBOL(bio_uncopy_user);
1002