aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorMike Christie <michaelc@cs.wisc.edu>2005-06-20 08:04:44 -0400
committerJens Axboe <axboe@suse.de>2005-06-20 08:04:44 -0400
commitdf46b9a44ceb5af2ea2351ce8e28ae7bd840b00f (patch)
tree30ab71759486f94d60af2283fc55bfffcc22155a /fs
parent8b22c249e7de453961e4d253b19fc2a0bdd65d53 (diff)
[PATCH] Add blk_rq_map_kern()
Add blk_rq_map_kern which takes a kernel buffer and maps it into a request and bio. This can be used by the dm hw_handlers, old sg_scsi_ioctl, and one day scsi special requests so all requests comming into scsi will have bios. All requests having bios should allow scsi to use scatter lists for all IO and allow it to use block layer functions. Signed-off-by: Jens Axboe <axboe@suse.de>
Diffstat (limited to 'fs')
-rw-r--r--fs/bio.c66
1 files changed, 66 insertions, 0 deletions
diff --git a/fs/bio.c b/fs/bio.c
index 3a1472acc361..707b9af2dd01 100644
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -701,6 +701,71 @@ void bio_unmap_user(struct bio *bio)
701 bio_put(bio); 701 bio_put(bio);
702} 702}
703 703
704static 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 */
750struct 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);
1088EXPORT_SYMBOL(bio_get_nr_vecs); 1153EXPORT_SYMBOL(bio_get_nr_vecs);
1089EXPORT_SYMBOL(bio_map_user); 1154EXPORT_SYMBOL(bio_map_user);
1090EXPORT_SYMBOL(bio_unmap_user); 1155EXPORT_SYMBOL(bio_unmap_user);
1156EXPORT_SYMBOL(bio_map_kern);
1091EXPORT_SYMBOL(bio_pair_release); 1157EXPORT_SYMBOL(bio_pair_release);
1092EXPORT_SYMBOL(bio_split); 1158EXPORT_SYMBOL(bio_split);
1093EXPORT_SYMBOL(bio_split_pool); 1159EXPORT_SYMBOL(bio_split_pool);