[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>

authored by Boaz Harrosh and committed by James Bottomley 6dd1d8a7 e96e72c4

+78
+71
drivers/scsi/osd/osd_initiator.c
··· 1015 1015 } 1016 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 1089 void osd_req_get_attributes(struct osd_request *or, 1019 1090 const struct osd_obj_id *obj) 1020 1091 {
+7
include/scsi/osd_initiator.h
··· 455 455 int osd_req_read_sg(struct osd_request *or, 456 456 const struct osd_obj_id *obj, struct bio *bio, 457 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 466 * Root/Partition/Collection/Object Attributes commands 460 467 */