aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/osd
diff options
context:
space:
mode:
authorBoaz Harrosh <bharrosh@panasas.com>2009-01-25 10:09:40 -0500
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2009-03-12 13:58:08 -0400
commitc6572c983726fe3f3bb5f07e9afe3a9b8e402d1b (patch)
treee5d1b19779db4d94dded752c2f8a940d9843ff5b /drivers/scsi/osd
parentae30c994a4bb70510fdcb9e7223805bb2a8bc9ee (diff)
[SCSI] libosd: OSD version 2 Support
Add support for OSD2 at run time. It is now possible to run with both OSDv1 and OSDv2 targets at the same time. The actual detection should be preformed by the security manager, as the version is encoded in the capability structure. Signed-off-by: Boaz Harrosh <bharrosh@panasas.com> Reviewed-by: Benny Halevy <bhalevy@panasas.com> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
Diffstat (limited to 'drivers/scsi/osd')
-rw-r--r--drivers/scsi/osd/osd_initiator.c94
1 files changed, 80 insertions, 14 deletions
diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
index 3fd021a57e5..86a76cccfeb 100644
--- a/drivers/scsi/osd/osd_initiator.c
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -59,36 +59,50 @@ static inline void build_test(void)
59{ 59{
60 /* structures were not packed */ 60 /* structures were not packed */
61 BUILD_BUG_ON(sizeof(struct osd_capability) != OSD_CAP_LEN); 61 BUILD_BUG_ON(sizeof(struct osd_capability) != OSD_CAP_LEN);
62 BUILD_BUG_ON(sizeof(struct osdv2_cdb) != OSD_TOTAL_CDB_LEN);
62 BUILD_BUG_ON(sizeof(struct osdv1_cdb) != OSDv1_TOTAL_CDB_LEN); 63 BUILD_BUG_ON(sizeof(struct osdv1_cdb) != OSDv1_TOTAL_CDB_LEN);
63} 64}
64 65
65static unsigned _osd_req_cdb_len(struct osd_request *or) 66static unsigned _osd_req_cdb_len(struct osd_request *or)
66{ 67{
67 return OSDv1_TOTAL_CDB_LEN; 68 return osd_req_is_ver1(or) ? OSDv1_TOTAL_CDB_LEN : OSD_TOTAL_CDB_LEN;
68} 69}
69 70
70static unsigned _osd_req_alist_elem_size(struct osd_request *or, unsigned len) 71static unsigned _osd_req_alist_elem_size(struct osd_request *or, unsigned len)
71{ 72{
72 return osdv1_attr_list_elem_size(len); 73 return osd_req_is_ver1(or) ?
74 osdv1_attr_list_elem_size(len) :
75 osdv2_attr_list_elem_size(len);
73} 76}
74 77
75static unsigned _osd_req_alist_size(struct osd_request *or, void *list_head) 78static unsigned _osd_req_alist_size(struct osd_request *or, void *list_head)
76{ 79{
77 return osdv1_list_size(list_head); 80 return osd_req_is_ver1(or) ?
81 osdv1_list_size(list_head) :
82 osdv2_list_size(list_head);
78} 83}
79 84
80static unsigned _osd_req_sizeof_alist_header(struct osd_request *or) 85static unsigned _osd_req_sizeof_alist_header(struct osd_request *or)
81{ 86{
82 return sizeof(struct osdv1_attributes_list_header); 87 return osd_req_is_ver1(or) ?
88 sizeof(struct osdv1_attributes_list_header) :
89 sizeof(struct osdv2_attributes_list_header);
83} 90}
84 91
85static void _osd_req_set_alist_type(struct osd_request *or, 92static void _osd_req_set_alist_type(struct osd_request *or,
86 void *list, int list_type) 93 void *list, int list_type)
87{ 94{
88 struct osdv1_attributes_list_header *attr_list = list; 95 if (osd_req_is_ver1(or)) {
96 struct osdv1_attributes_list_header *attr_list = list;
97
98 memset(attr_list, 0, sizeof(*attr_list));
99 attr_list->type = list_type;
100 } else {
101 struct osdv2_attributes_list_header *attr_list = list;
89 102
90 memset(attr_list, 0, sizeof(*attr_list)); 103 memset(attr_list, 0, sizeof(*attr_list));
91 attr_list->type = list_type; 104 attr_list->type = list_type;
105 }
92} 106}
93 107
94static bool _osd_req_is_alist_type(struct osd_request *or, 108static bool _osd_req_is_alist_type(struct osd_request *or,
@@ -97,10 +111,14 @@ static bool _osd_req_is_alist_type(struct osd_request *or,
97 if (!list) 111 if (!list)
98 return false; 112 return false;
99 113
100 if (1) { 114 if (osd_req_is_ver1(or)) {
101 struct osdv1_attributes_list_header *attr_list = list; 115 struct osdv1_attributes_list_header *attr_list = list;
102 116
103 return attr_list->type == list_type; 117 return attr_list->type == list_type;
118 } else {
119 struct osdv2_attributes_list_header *attr_list = list;
120
121 return attr_list->type == list_type;
104 } 122 }
105} 123}
106 124
@@ -110,15 +128,22 @@ static void _osd_req_encode_olist(struct osd_request *or,
110{ 128{
111 struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb); 129 struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
112 130
113 cdbh->v1.list_identifier = list->list_identifier; 131 if (osd_req_is_ver1(or)) {
114 cdbh->v1.start_address = list->continuation_id; 132 cdbh->v1.list_identifier = list->list_identifier;
133 cdbh->v1.start_address = list->continuation_id;
134 } else {
135 cdbh->v2.list_identifier = list->list_identifier;
136 cdbh->v2.start_address = list->continuation_id;
137 }
115} 138}
116 139
117static osd_cdb_offset osd_req_encode_offset(struct osd_request *or, 140static osd_cdb_offset osd_req_encode_offset(struct osd_request *or,
118 u64 offset, unsigned *padding) 141 u64 offset, unsigned *padding)
119{ 142{
120 return __osd_encode_offset(offset, padding, 143 return __osd_encode_offset(offset, padding,
121 OSDv1_OFFSET_MIN_SHIFT, OSD_OFFSET_MAX_SHIFT); 144 osd_req_is_ver1(or) ?
145 OSDv1_OFFSET_MIN_SHIFT : OSD_OFFSET_MIN_SHIFT,
146 OSD_OFFSET_MAX_SHIFT);
122} 147}
123 148
124static struct osd_security_parameters * 149static struct osd_security_parameters *
@@ -126,7 +151,10 @@ _osd_req_sec_params(struct osd_request *or)
126{ 151{
127 struct osd_cdb *ocdb = &or->cdb; 152 struct osd_cdb *ocdb = &or->cdb;
128 153
129 return &ocdb->v1.sec_params; 154 if (osd_req_is_ver1(or))
155 return &ocdb->v1.sec_params;
156 else
157 return &ocdb->v2.sec_params;
130} 158}
131 159
132void osd_dev_init(struct osd_dev *osdd, struct scsi_device *scsi_device) 160void osd_dev_init(struct osd_dev *osdd, struct scsi_device *scsi_device)
@@ -134,6 +162,9 @@ void osd_dev_init(struct osd_dev *osdd, struct scsi_device *scsi_device)
134 memset(osdd, 0, sizeof(*osdd)); 162 memset(osdd, 0, sizeof(*osdd));
135 osdd->scsi_device = scsi_device; 163 osdd->scsi_device = scsi_device;
136 osdd->def_timeout = BLK_DEFAULT_SG_TIMEOUT; 164 osdd->def_timeout = BLK_DEFAULT_SG_TIMEOUT;
165#ifdef OSD_VER1_SUPPORT
166 osdd->version = OSD_VER2;
167#endif
137 /* TODO: Allocate pools for osd_request attributes ... */ 168 /* TODO: Allocate pools for osd_request attributes ... */
138} 169}
139EXPORT_SYMBOL(osd_dev_init); 170EXPORT_SYMBOL(osd_dev_init);
@@ -334,10 +365,30 @@ static void _osdv1_req_encode_common(struct osd_request *or,
334 ocdb->h.v1.start_address = cpu_to_be64(offset); 365 ocdb->h.v1.start_address = cpu_to_be64(offset);
335} 366}
336 367
368static void _osdv2_req_encode_common(struct osd_request *or,
369 __be16 act, const struct osd_obj_id *obj, u64 offset, u64 len)
370{
371 struct osdv2_cdb *ocdb = &or->cdb.v2;
372
373 OSD_DEBUG("OSDv2 execute opcode 0x%x\n", be16_to_cpu(act));
374
375 ocdb->h.varlen_cdb.opcode = VARIABLE_LENGTH_CMD;
376 ocdb->h.varlen_cdb.additional_cdb_length = OSD_ADDITIONAL_CDB_LENGTH;
377 ocdb->h.varlen_cdb.service_action = act;
378
379 ocdb->h.partition = cpu_to_be64(obj->partition);
380 ocdb->h.object = cpu_to_be64(obj->id);
381 ocdb->h.v2.length = cpu_to_be64(len);
382 ocdb->h.v2.start_address = cpu_to_be64(offset);
383}
384
337static void _osd_req_encode_common(struct osd_request *or, 385static void _osd_req_encode_common(struct osd_request *or,
338 __be16 act, const struct osd_obj_id *obj, u64 offset, u64 len) 386 __be16 act, const struct osd_obj_id *obj, u64 offset, u64 len)
339{ 387{
340 _osdv1_req_encode_common(or, act, obj, offset, len); 388 if (osd_req_is_ver1(or))
389 _osdv1_req_encode_common(or, act, obj, offset, len);
390 else
391 _osdv2_req_encode_common(or, act, obj, offset, len);
341} 392}
342 393
343/* 394/*
@@ -546,6 +597,12 @@ void osd_req_flush_object(struct osd_request *or,
546 const struct osd_obj_id *obj, enum osd_options_flush_scope_values op, 597 const struct osd_obj_id *obj, enum osd_options_flush_scope_values op,
547 /*V2*/ u64 offset, /*V2*/ u64 len) 598 /*V2*/ u64 offset, /*V2*/ u64 len)
548{ 599{
600 if (unlikely(osd_req_is_ver1(or) && (offset || len))) {
601 OSD_DEBUG("OSD Ver1 flush on specific range ignored\n");
602 offset = 0;
603 len = 0;
604 }
605
549 _osd_req_encode_common(or, OSD_ACT_FLUSH, obj, offset, len); 606 _osd_req_encode_common(or, OSD_ACT_FLUSH, obj, offset, len);
550 _osd_req_encode_flush(or, op); 607 _osd_req_encode_flush(or, op);
551} 608}
@@ -1169,6 +1226,10 @@ enum { OSD_SEC_CAP_V1_ALL_CAPS =
1169 OSD_SEC_CAP_GLOBAL | OSD_SEC_CAP_DEV_MGMT 1226 OSD_SEC_CAP_GLOBAL | OSD_SEC_CAP_DEV_MGMT
1170}; 1227};
1171 1228
1229enum { OSD_SEC_CAP_V2_ALL_CAPS =
1230 OSD_SEC_CAP_V1_ALL_CAPS | OSD_SEC_CAP_QUERY | OSD_SEC_CAP_M_OBJECT
1231};
1232
1172void osd_sec_init_nosec_doall_caps(void *caps, 1233void osd_sec_init_nosec_doall_caps(void *caps,
1173 const struct osd_obj_id *obj, bool is_collection, const bool is_v1) 1234 const struct osd_obj_id *obj, bool is_collection, const bool is_v1)
1174{ 1235{
@@ -1210,9 +1271,14 @@ void osd_sec_init_nosec_doall_caps(void *caps,
1210} 1271}
1211EXPORT_SYMBOL(osd_sec_init_nosec_doall_caps); 1272EXPORT_SYMBOL(osd_sec_init_nosec_doall_caps);
1212 1273
1274/* FIXME: Extract version from caps pointer.
1275 * Also Pete's target only supports caps from OSDv1 for now
1276 */
1213void osd_set_caps(struct osd_cdb *cdb, const void *caps) 1277void osd_set_caps(struct osd_cdb *cdb, const void *caps)
1214{ 1278{
1215 memcpy(&cdb->v1.caps, caps, OSDv1_CAP_LEN); 1279 bool is_ver1 = true;
1280 /* NOTE: They start at same address */
1281 memcpy(&cdb->v1.caps, caps, is_ver1 ? OSDv1_CAP_LEN : OSD_CAP_LEN);
1216} 1282}
1217 1283
1218bool osd_is_sec_alldata(struct osd_security_parameters *sec_parms __unused) 1284bool osd_is_sec_alldata(struct osd_security_parameters *sec_parms __unused)