aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/osd/osd_initiator.c71
-rw-r--r--include/scsi/osd_initiator.h7
2 files changed, 78 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{
diff --git a/include/scsi/osd_initiator.h b/include/scsi/osd_initiator.h
index 169a5dcda096..53a9e886612b 100644
--- a/include/scsi/osd_initiator.h
+++ b/include/scsi/osd_initiator.h
@@ -455,6 +455,13 @@ int osd_req_write_sg(struct osd_request *or,
455int osd_req_read_sg(struct osd_request *or, 455int osd_req_read_sg(struct osd_request *or,
456 const struct osd_obj_id *obj, struct bio *bio, 456 const struct osd_obj_id *obj, struct bio *bio,
457 const struct osd_sg_entry *sglist, unsigned numentries); 457 const struct osd_sg_entry *sglist, unsigned numentries);
458int osd_req_write_sg_kern(struct osd_request *or,
459 const struct osd_obj_id *obj, void **buff,
460 const struct osd_sg_entry *sglist, unsigned numentries);
461int osd_req_read_sg_kern(struct osd_request *or,
462 const struct osd_obj_id *obj, void **buff,
463 const struct osd_sg_entry *sglist, unsigned numentries);
464
458/* 465/*
459 * Root/Partition/Collection/Object Attributes commands 466 * Root/Partition/Collection/Object Attributes commands
460 */ 467 */