diff options
| -rw-r--r-- | drivers/scsi/osd/osd_initiator.c | 71 | ||||
| -rw-r--r-- | include/scsi/osd_initiator.h | 7 |
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 | } |
| 1016 | EXPORT_SYMBOL(osd_req_read_sg); | 1016 | EXPORT_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 | */ | ||
| 1026 | static 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 | |||
| 1058 | int 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 | } | ||
| 1071 | EXPORT_SYMBOL(osd_req_write_sg_kern); | ||
| 1072 | |||
| 1073 | int 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 | } | ||
| 1085 | EXPORT_SYMBOL(osd_req_read_sg_kern); | ||
| 1086 | |||
| 1087 | |||
| 1088 | |||
| 1018 | void osd_req_get_attributes(struct osd_request *or, | 1089 | void 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, | |||
| 455 | int osd_req_read_sg(struct osd_request *or, | 455 | int 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); |
| 458 | int 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); | ||
| 461 | int 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 | */ |
