aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/osd
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/osd')
-rw-r--r--drivers/scsi/osd/osd_initiator.c86
1 files changed, 68 insertions, 18 deletions
diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
index 76de88962237..e266f803aa96 100644
--- a/drivers/scsi/osd/osd_initiator.c
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -205,6 +205,69 @@ static unsigned _osd_req_alist_elem_size(struct osd_request *or, unsigned len)
205 osdv2_attr_list_elem_size(len); 205 osdv2_attr_list_elem_size(len);
206} 206}
207 207
208static void _osd_req_alist_elem_encode(struct osd_request *or,
209 void *attr_last, const struct osd_attr *oa)
210{
211 if (osd_req_is_ver1(or)) {
212 struct osdv1_attributes_list_element *attr = attr_last;
213
214 attr->attr_page = cpu_to_be32(oa->attr_page);
215 attr->attr_id = cpu_to_be32(oa->attr_id);
216 attr->attr_bytes = cpu_to_be16(oa->len);
217 memcpy(attr->attr_val, oa->val_ptr, oa->len);
218 } else {
219 struct osdv2_attributes_list_element *attr = attr_last;
220
221 attr->attr_page = cpu_to_be32(oa->attr_page);
222 attr->attr_id = cpu_to_be32(oa->attr_id);
223 attr->attr_bytes = cpu_to_be16(oa->len);
224 memcpy(attr->attr_val, oa->val_ptr, oa->len);
225 }
226}
227
228static int _osd_req_alist_elem_decode(struct osd_request *or,
229 void *cur_p, struct osd_attr *oa, unsigned max_bytes)
230{
231 unsigned inc;
232 if (osd_req_is_ver1(or)) {
233 struct osdv1_attributes_list_element *attr = cur_p;
234
235 if (max_bytes < sizeof(*attr))
236 return -1;
237
238 oa->len = be16_to_cpu(attr->attr_bytes);
239 inc = _osd_req_alist_elem_size(or, oa->len);
240 if (inc > max_bytes)
241 return -1;
242
243 oa->attr_page = be32_to_cpu(attr->attr_page);
244 oa->attr_id = be32_to_cpu(attr->attr_id);
245
246 /* OSD1: On empty attributes we return a pointer to 2 bytes
247 * of zeros. This keeps similar behaviour with OSD2.
248 * (See below)
249 */
250 oa->val_ptr = likely(oa->len) ? attr->attr_val :
251 (u8 *)&attr->attr_bytes;
252 } else {
253 struct osdv2_attributes_list_element *attr = cur_p;
254
255 if (max_bytes < sizeof(*attr))
256 return -1;
257
258 oa->len = be16_to_cpu(attr->attr_bytes);
259 inc = _osd_req_alist_elem_size(or, oa->len);
260 if (inc > max_bytes)
261 return -1;
262
263 oa->attr_page = be32_to_cpu(attr->attr_page);
264 oa->attr_id = be32_to_cpu(attr->attr_id);
265
266 oa->val_ptr = attr->attr_val;
267 }
268 return inc;
269}
270
208static unsigned _osd_req_alist_size(struct osd_request *or, void *list_head) 271static unsigned _osd_req_alist_size(struct osd_request *or, void *list_head)
209{ 272{
210 return osd_req_is_ver1(or) ? 273 return osd_req_is_ver1(or) ?
@@ -798,7 +861,6 @@ int osd_req_add_set_attr_list(struct osd_request *or,
798 attr_last = or->set_attr.buff + total_bytes; 861 attr_last = or->set_attr.buff + total_bytes;
799 862
800 for (; nelem; --nelem) { 863 for (; nelem; --nelem) {
801 struct osd_attributes_list_element *attr;
802 unsigned elem_size = _osd_req_alist_elem_size(or, oa->len); 864 unsigned elem_size = _osd_req_alist_elem_size(or, oa->len);
803 865
804 total_bytes += elem_size; 866 total_bytes += elem_size;
@@ -811,11 +873,7 @@ int osd_req_add_set_attr_list(struct osd_request *or,
811 or->set_attr.buff + or->set_attr.total_bytes; 873 or->set_attr.buff + or->set_attr.total_bytes;
812 } 874 }
813 875
814 attr = attr_last; 876 _osd_req_alist_elem_encode(or, attr_last, oa);
815 attr->attr_page = cpu_to_be32(oa->attr_page);
816 attr->attr_id = cpu_to_be32(oa->attr_id);
817 attr->attr_bytes = cpu_to_be16(oa->len);
818 memcpy(attr->attr_val, oa->val_ptr, oa->len);
819 877
820 attr_last += elem_size; 878 attr_last += elem_size;
821 ++oa; 879 ++oa;
@@ -1070,15 +1128,10 @@ int osd_req_decode_get_attr_list(struct osd_request *or,
1070 } 1128 }
1071 1129
1072 for (n = 0; (n < *nelem) && (cur_bytes < returned_bytes); ++n) { 1130 for (n = 0; (n < *nelem) && (cur_bytes < returned_bytes); ++n) {
1073 struct osd_attributes_list_element *attr = cur_p; 1131 int inc = _osd_req_alist_elem_decode(or, cur_p, oa,
1074 unsigned inc; 1132 returned_bytes - cur_bytes);
1075 1133
1076 oa->len = be16_to_cpu(attr->attr_bytes); 1134 if (inc < 0) {
1077 inc = _osd_req_alist_elem_size(or, oa->len);
1078 OSD_DEBUG("oa->len=%d inc=%d cur_bytes=%d\n",
1079 oa->len, inc, cur_bytes);
1080 cur_bytes += inc;
1081 if (cur_bytes > returned_bytes) {
1082 OSD_ERR("BAD FOOD from target. list not valid!" 1135 OSD_ERR("BAD FOOD from target. list not valid!"
1083 "c=%d r=%d n=%d\n", 1136 "c=%d r=%d n=%d\n",
1084 cur_bytes, returned_bytes, n); 1137 cur_bytes, returned_bytes, n);
@@ -1086,10 +1139,7 @@ int osd_req_decode_get_attr_list(struct osd_request *or,
1086 break; 1139 break;
1087 } 1140 }
1088 1141
1089 oa->attr_page = be32_to_cpu(attr->attr_page); 1142 cur_bytes += inc;
1090 oa->attr_id = be32_to_cpu(attr->attr_id);
1091 oa->val_ptr = attr->attr_val;
1092
1093 cur_p += inc; 1143 cur_p += inc;
1094 ++oa; 1144 ++oa;
1095 } 1145 }