aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
authorBoaz Harrosh <bharrosh@panasas.com>2010-10-19 10:13:50 -0400
committerJames Bottomley <James.Bottomley@suse.de>2010-10-26 11:42:35 -0400
commit6dd1d8a7953cdc203c6eb694ce8eafe2dcd3e9da (patch)
treed75130fef86fd2a111a3908e7d32f4e6e3302f77 /drivers/scsi
parente96e72c45a1e78e9266dd70113b851395a440ef3 (diff)
[SCSI] libosd: write/read_sg_kern API
This is a trivial addition to the SG API that can receive kernel pointers. It is only used by the out-of-tree test module. So it's immediate need is questionable. For maintenance ease it might just get in, as it's very small. John. do you need this in the Kernel, or is it only for osd_ktest.ko? Signed-off-by: John A. Chandy <john.chandy@uconn.edu> Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/osd/osd_initiator.c71
1 files changed, 71 insertions, 0 deletions
diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
index f5b5735f76d5..0433ea6f27c9 100644
--- a/drivers/scsi/osd/osd_initiator.c
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -1015,6 +1015,77 @@ int osd_req_read_sg(struct osd_request *or,
1015} 1015}
1016EXPORT_SYMBOL(osd_req_read_sg); 1016EXPORT_SYMBOL(osd_req_read_sg);
1017 1017
1018/* SG-list write/read Kern API
1019 *
1020 * osd_req_{write,read}_sg_kern takes an array of @buff pointers and an array
1021 * of sg_entries. @numentries indicates how many pointers and sg_entries there
1022 * are. By requiring an array of buff pointers. This allows a caller to do a
1023 * single write/read and scatter into multiple buffers.
1024 * NOTE: Each buffer + len should not cross a page boundary.
1025 */
1026static struct bio *_create_sg_bios(struct osd_request *or,
1027 void **buff, const struct osd_sg_entry *sglist, unsigned numentries)
1028{
1029 struct request_queue *q = osd_request_queue(or->osd_dev);
1030 struct bio *bio;
1031 unsigned i;
1032
1033 bio = bio_kmalloc(GFP_KERNEL, numentries);
1034 if (unlikely(!bio)) {
1035 OSD_DEBUG("Faild to allocate BIO size=%u\n", numentries);
1036 return ERR_PTR(-ENOMEM);
1037 }
1038
1039 for (i = 0; i < numentries; i++) {
1040 unsigned offset = offset_in_page(buff[i]);
1041 struct page *page = virt_to_page(buff[i]);
1042 unsigned len = sglist[i].len;
1043 unsigned added_len;
1044
1045 BUG_ON(offset + len > PAGE_SIZE);
1046 added_len = bio_add_pc_page(q, bio, page, len, offset);
1047 if (unlikely(len != added_len)) {
1048 OSD_DEBUG("bio_add_pc_page len(%d) != added_len(%d)\n",
1049 len, added_len);
1050 bio_put(bio);
1051 return ERR_PTR(-ENOMEM);
1052 }
1053 }
1054
1055 return bio;
1056}
1057
1058int osd_req_write_sg_kern(struct osd_request *or,
1059 const struct osd_obj_id *obj, void **buff,
1060 const struct osd_sg_entry *sglist, unsigned numentries)
1061{
1062 struct bio *bio = _create_sg_bios(or, buff, sglist, numentries);
1063 if (IS_ERR(bio))
1064 return PTR_ERR(bio);
1065
1066 bio->bi_rw |= REQ_WRITE;
1067 osd_req_write_sg(or, obj, bio, sglist, numentries);
1068
1069 return 0;
1070}
1071EXPORT_SYMBOL(osd_req_write_sg_kern);
1072
1073int osd_req_read_sg_kern(struct osd_request *or,
1074 const struct osd_obj_id *obj, void **buff,
1075 const struct osd_sg_entry *sglist, unsigned numentries)
1076{
1077 struct bio *bio = _create_sg_bios(or, buff, sglist, numentries);
1078 if (IS_ERR(bio))
1079 return PTR_ERR(bio);
1080
1081 osd_req_read_sg(or, obj, bio, sglist, numentries);
1082
1083 return 0;
1084}
1085EXPORT_SYMBOL(osd_req_read_sg_kern);
1086
1087
1088
1018void osd_req_get_attributes(struct osd_request *or, 1089void osd_req_get_attributes(struct osd_request *or,
1019 const struct osd_obj_id *obj) 1090 const struct osd_obj_id *obj)
1020{ 1091{