Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 71f32e31 authored by Boaz Harrosh's avatar Boaz Harrosh Committed by James Bottomley
Browse files

[SCSI] libosd: OSD2r05: Prepare for rev5 attribute list changes



In OSD2r05 draft each attribute list element header was changed
so attribute-value would be 8 bytes aligned. In OSD2r01-r04
it was aligned on 2 bytes. (This is because in OSD2r01 the complete
element was 8 bytes padded at end but the header was not adjusted
and caused permanent miss-alignment.)

OSD1 elements are not padded and might be or might not be aligned.
OSD1 is still supported.

In this code we do all the code re-factoring to separate OSD1/OSD2
differences but do not change actual wire format. All wire format
changes will happen in one patch later, for bisect-ability.

Signed-off-by: default avatarBoaz Harrosh <bharrosh@panasas.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@HansenPartnership.com>
parent bf5e84f6
Loading
Loading
Loading
Loading
+68 −18
Original line number Diff line number Diff line
@@ -205,6 +205,69 @@ static unsigned _osd_req_alist_elem_size(struct osd_request *or, unsigned len)
		osdv2_attr_list_elem_size(len);
}

static void _osd_req_alist_elem_encode(struct osd_request *or,
	void *attr_last, const struct osd_attr *oa)
{
	if (osd_req_is_ver1(or)) {
		struct osdv1_attributes_list_element *attr = attr_last;

		attr->attr_page = cpu_to_be32(oa->attr_page);
		attr->attr_id = cpu_to_be32(oa->attr_id);
		attr->attr_bytes = cpu_to_be16(oa->len);
		memcpy(attr->attr_val, oa->val_ptr, oa->len);
	} else {
		struct osdv2_attributes_list_element *attr = attr_last;

		attr->attr_page = cpu_to_be32(oa->attr_page);
		attr->attr_id = cpu_to_be32(oa->attr_id);
		attr->attr_bytes = cpu_to_be16(oa->len);
		memcpy(attr->attr_val, oa->val_ptr, oa->len);
	}
}

static int _osd_req_alist_elem_decode(struct osd_request *or,
	void *cur_p, struct osd_attr *oa, unsigned max_bytes)
{
	unsigned inc;
	if (osd_req_is_ver1(or)) {
		struct osdv1_attributes_list_element *attr = cur_p;

		if (max_bytes < sizeof(*attr))
			return -1;

		oa->len = be16_to_cpu(attr->attr_bytes);
		inc = _osd_req_alist_elem_size(or, oa->len);
		if (inc > max_bytes)
			return -1;

		oa->attr_page = be32_to_cpu(attr->attr_page);
		oa->attr_id = be32_to_cpu(attr->attr_id);

		/* OSD1: On empty attributes we return a pointer to 2 bytes
		 * of zeros. This keeps similar behaviour with OSD2.
		 * (See below)
		 */
		oa->val_ptr = likely(oa->len) ? attr->attr_val :
						(u8 *)&attr->attr_bytes;
	} else {
		struct osdv2_attributes_list_element *attr = cur_p;

		if (max_bytes < sizeof(*attr))
			return -1;

		oa->len = be16_to_cpu(attr->attr_bytes);
		inc = _osd_req_alist_elem_size(or, oa->len);
		if (inc > max_bytes)
			return -1;

		oa->attr_page = be32_to_cpu(attr->attr_page);
		oa->attr_id = be32_to_cpu(attr->attr_id);

		oa->val_ptr = attr->attr_val;
	}
	return inc;
}

static unsigned _osd_req_alist_size(struct osd_request *or, void *list_head)
{
	return osd_req_is_ver1(or) ?
@@ -798,7 +861,6 @@ int osd_req_add_set_attr_list(struct osd_request *or,
	attr_last = or->set_attr.buff + total_bytes;

	for (; nelem; --nelem) {
		struct osd_attributes_list_element *attr;
		unsigned elem_size = _osd_req_alist_elem_size(or, oa->len);

		total_bytes += elem_size;
@@ -811,11 +873,7 @@ int osd_req_add_set_attr_list(struct osd_request *or,
				or->set_attr.buff + or->set_attr.total_bytes;
		}

		attr = attr_last;
		attr->attr_page = cpu_to_be32(oa->attr_page);
		attr->attr_id = cpu_to_be32(oa->attr_id);
		attr->attr_bytes = cpu_to_be16(oa->len);
		memcpy(attr->attr_val, oa->val_ptr, oa->len);
		_osd_req_alist_elem_encode(or, attr_last, oa);

		attr_last += elem_size;
		++oa;
@@ -1070,15 +1128,10 @@ int osd_req_decode_get_attr_list(struct osd_request *or,
	}

	for (n = 0; (n < *nelem) && (cur_bytes < returned_bytes); ++n) {
		struct osd_attributes_list_element *attr = cur_p;
		unsigned inc;
		int inc = _osd_req_alist_elem_decode(or, cur_p, oa,
						 returned_bytes - cur_bytes);

		oa->len = be16_to_cpu(attr->attr_bytes);
		inc = _osd_req_alist_elem_size(or, oa->len);
		OSD_DEBUG("oa->len=%d inc=%d cur_bytes=%d\n",
			  oa->len, inc, cur_bytes);
		cur_bytes += inc;
		if (cur_bytes > returned_bytes) {
		if (inc < 0) {
			OSD_ERR("BAD FOOD from target. list not valid!"
				"c=%d r=%d n=%d\n",
				cur_bytes, returned_bytes, n);
@@ -1086,10 +1139,7 @@ int osd_req_decode_get_attr_list(struct osd_request *or,
			break;
		}

		oa->attr_page = be32_to_cpu(attr->attr_page);
		oa->attr_id = be32_to_cpu(attr->attr_id);
		oa->val_ptr = attr->attr_val;

		cur_bytes += inc;
		cur_p += inc;
		++oa;
	}
+15 −5
Original line number Diff line number Diff line
@@ -300,15 +300,25 @@ struct osd_attributes_list_attrid {
	__be32 attr_id;
} __packed;

/*
 * NOTE: v1: is not aligned.
 */
struct osdv1_attributes_list_element {
	__be32 attr_page;
	__be32 attr_id;
	__be16 attr_bytes; /* valid bytes at attr_val without padding */
	u8 attr_val[0];
} __packed;

/*
 * osd2r03: 7.1.3.3 List entry format for retrieved attributes and
 *                  for setting attributes
 * NOTE: v2 is 8-bytes aligned, v1 is not aligned.
 * NOTE: v2 is 8-bytes aligned
 */
struct osd_attributes_list_element {
struct osdv2_attributes_list_element {
	__be32 attr_page;
	__be32 attr_id;
	__be16 attr_bytes;
	__be16 attr_bytes; /* valid bytes at attr_val without padding */
	u8 attr_val[0];
} __packed;

@@ -324,13 +334,13 @@ enum {

static inline unsigned osdv1_attr_list_elem_size(unsigned len)
{
	return ALIGN(len + sizeof(struct osd_attributes_list_element),
	return ALIGN(len + sizeof(struct osdv1_attributes_list_element),
		     OSDv1_ATTRIBUTES_ELEM_ALIGN);
}

static inline unsigned osdv2_attr_list_elem_size(unsigned len)
{
	return ALIGN(len + sizeof(struct osd_attributes_list_element),
	return ALIGN(len + sizeof(struct osdv2_attributes_list_element),
		     OSD_ATTRIBUTES_ELEM_ALIGN);
}