diff options
Diffstat (limited to 'fs/bio.c')
-rw-r--r-- | fs/bio.c | 66 |
1 files changed, 66 insertions, 0 deletions
@@ -701,6 +701,71 @@ void bio_unmap_user(struct bio *bio) | |||
701 | bio_put(bio); | 701 | bio_put(bio); |
702 | } | 702 | } |
703 | 703 | ||
704 | static struct bio *__bio_map_kern(request_queue_t *q, void *data, | ||
705 | unsigned int len, unsigned int gfp_mask) | ||
706 | { | ||
707 | unsigned long kaddr = (unsigned long)data; | ||
708 | unsigned long end = (kaddr + len + PAGE_SIZE - 1) >> PAGE_SHIFT; | ||
709 | unsigned long start = kaddr >> PAGE_SHIFT; | ||
710 | const int nr_pages = end - start; | ||
711 | int offset, i; | ||
712 | struct bio *bio; | ||
713 | |||
714 | bio = bio_alloc(gfp_mask, nr_pages); | ||
715 | if (!bio) | ||
716 | return ERR_PTR(-ENOMEM); | ||
717 | |||
718 | offset = offset_in_page(kaddr); | ||
719 | for (i = 0; i < nr_pages; i++) { | ||
720 | unsigned int bytes = PAGE_SIZE - offset; | ||
721 | |||
722 | if (len <= 0) | ||
723 | break; | ||
724 | |||
725 | if (bytes > len) | ||
726 | bytes = len; | ||
727 | |||
728 | if (__bio_add_page(q, bio, virt_to_page(data), bytes, | ||
729 | offset) < bytes) | ||
730 | break; | ||
731 | |||
732 | data += bytes; | ||
733 | len -= bytes; | ||
734 | offset = 0; | ||
735 | } | ||
736 | |||
737 | return bio; | ||
738 | } | ||
739 | |||
740 | /** | ||
741 | * bio_map_kern - map kernel address into bio | ||
742 | * @q: the request_queue_t for the bio | ||
743 | * @data: pointer to buffer to map | ||
744 | * @len: length in bytes | ||
745 | * @gfp_mask: allocation flags for bio allocation | ||
746 | * | ||
747 | * Map the kernel address into a bio suitable for io to a block | ||
748 | * device. Returns an error pointer in case of error. | ||
749 | */ | ||
750 | struct bio *bio_map_kern(request_queue_t *q, void *data, unsigned int len, | ||
751 | unsigned int gfp_mask) | ||
752 | { | ||
753 | struct bio *bio; | ||
754 | |||
755 | bio = __bio_map_kern(q, data, len, gfp_mask); | ||
756 | if (IS_ERR(bio)) | ||
757 | return bio; | ||
758 | |||
759 | if (bio->bi_size == len) | ||
760 | return bio; | ||
761 | |||
762 | /* | ||
763 | * Don't support partial mappings. | ||
764 | */ | ||
765 | bio_put(bio); | ||
766 | return ERR_PTR(-EINVAL); | ||
767 | } | ||
768 | |||
704 | /* | 769 | /* |
705 | * bio_set_pages_dirty() and bio_check_pages_dirty() are support functions | 770 | * bio_set_pages_dirty() and bio_check_pages_dirty() are support functions |
706 | * for performing direct-IO in BIOs. | 771 | * for performing direct-IO in BIOs. |
@@ -1088,6 +1153,7 @@ EXPORT_SYMBOL(bio_add_page); | |||
1088 | EXPORT_SYMBOL(bio_get_nr_vecs); | 1153 | EXPORT_SYMBOL(bio_get_nr_vecs); |
1089 | EXPORT_SYMBOL(bio_map_user); | 1154 | EXPORT_SYMBOL(bio_map_user); |
1090 | EXPORT_SYMBOL(bio_unmap_user); | 1155 | EXPORT_SYMBOL(bio_unmap_user); |
1156 | EXPORT_SYMBOL(bio_map_kern); | ||
1091 | EXPORT_SYMBOL(bio_pair_release); | 1157 | EXPORT_SYMBOL(bio_pair_release); |
1092 | EXPORT_SYMBOL(bio_split); | 1158 | EXPORT_SYMBOL(bio_split); |
1093 | EXPORT_SYMBOL(bio_split_pool); | 1159 | EXPORT_SYMBOL(bio_split_pool); |