2 * Object-Based pNFS Layout XDR layer
4 * Copyright (C) 2007 Panasas Inc. [year of first publication]
7 * Benny Halevy <bhalevy@panasas.com>
8 * Boaz Harrosh <bharrosh@panasas.com>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2
12 * See the file COPYING included with this distribution for more details.
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
18 * 1. Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
20 * 2. Redistributions in binary form must reproduce the above copyright
21 * notice, this list of conditions and the following disclaimer in the
22 * documentation and/or other materials provided with the distribution.
23 * 3. Neither the name of the Panasas company nor the names of its
24 * contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
27 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
28 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
29 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
30 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
34 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
35 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
36 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
37 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 #include <linux/pnfs_osd_xdr.h>
42 #define NFSDBG_FACILITY NFSDBG_PNFS_LD
45 * The following implementation is based on RFC5664
49 * struct pnfs_osd_objid {
50 * struct nfs4_deviceid oid_device_id;
51 * u64 oid_partition_id;
53 * }; // xdr size 32 bytes
56 _osd_xdr_decode_objid(__be32
*p
, struct pnfs_osd_objid
*objid
)
58 p
= xdr_decode_opaque_fixed(p
, objid
->oid_device_id
.data
,
59 sizeof(objid
->oid_device_id
.data
));
61 p
= xdr_decode_hyper(p
, &objid
->oid_partition_id
);
62 p
= xdr_decode_hyper(p
, &objid
->oid_object_id
);
66 * struct pnfs_osd_opaque_cred {
69 * }; // xdr size [variable]
70 * The return pointers are from the xdr buffer
73 _osd_xdr_decode_opaque_cred(struct pnfs_osd_opaque_cred
*opaque_cred
,
74 struct xdr_stream
*xdr
)
76 __be32
*p
= xdr_inline_decode(xdr
, 1);
81 opaque_cred
->cred_len
= be32_to_cpu(*p
++);
83 p
= xdr_inline_decode(xdr
, opaque_cred
->cred_len
);
87 opaque_cred
->cred
= p
;
92 * struct pnfs_osd_object_cred {
93 * struct pnfs_osd_objid oc_object_id;
96 * struct pnfs_osd_opaque_cred oc_cap_key
97 * struct pnfs_osd_opaque_cred oc_cap;
98 * }; // xdr size 32 + 4 + 4 + [variable] + [variable]
101 _osd_xdr_decode_object_cred(struct pnfs_osd_object_cred
*comp
,
102 struct xdr_stream
*xdr
)
104 __be32
*p
= xdr_inline_decode(xdr
, 32 + 4 + 4);
110 p
= _osd_xdr_decode_objid(p
, &comp
->oc_object_id
);
111 comp
->oc_osd_version
= be32_to_cpup(p
++);
112 comp
->oc_cap_key_sec
= be32_to_cpup(p
);
114 ret
= _osd_xdr_decode_opaque_cred(&comp
->oc_cap_key
, xdr
);
118 ret
= _osd_xdr_decode_opaque_cred(&comp
->oc_cap
, xdr
);
123 * struct pnfs_osd_data_map {
125 * u64 odm_stripe_unit;
126 * u32 odm_group_width;
127 * u32 odm_group_depth;
128 * u32 odm_mirror_cnt;
129 * u32 odm_raid_algorithm;
130 * }; // xdr size 4 + 8 + 4 + 4 + 4 + 4
133 _osd_data_map_xdr_sz(void)
135 return 4 + 8 + 4 + 4 + 4 + 4;
139 _osd_xdr_decode_data_map(__be32
*p
, struct pnfs_osd_data_map
*data_map
)
141 data_map
->odm_num_comps
= be32_to_cpup(p
++);
142 p
= xdr_decode_hyper(p
, &data_map
->odm_stripe_unit
);
143 data_map
->odm_group_width
= be32_to_cpup(p
++);
144 data_map
->odm_group_depth
= be32_to_cpup(p
++);
145 data_map
->odm_mirror_cnt
= be32_to_cpup(p
++);
146 data_map
->odm_raid_algorithm
= be32_to_cpup(p
++);
147 dprintk("%s: odm_num_comps=%u odm_stripe_unit=%llu odm_group_width=%u "
148 "odm_group_depth=%u odm_mirror_cnt=%u odm_raid_algorithm=%u\n",
150 data_map
->odm_num_comps
,
151 (unsigned long long)data_map
->odm_stripe_unit
,
152 data_map
->odm_group_width
,
153 data_map
->odm_group_depth
,
154 data_map
->odm_mirror_cnt
,
155 data_map
->odm_raid_algorithm
);
159 int pnfs_osd_xdr_decode_layout_map(struct pnfs_osd_layout
*layout
,
160 struct pnfs_osd_xdr_decode_layout_iter
*iter
, struct xdr_stream
*xdr
)
164 memset(iter
, 0, sizeof(*iter
));
166 p
= xdr_inline_decode(xdr
, _osd_data_map_xdr_sz() + 4 + 4);
170 p
= _osd_xdr_decode_data_map(p
, &layout
->olo_map
);
171 layout
->olo_comps_index
= be32_to_cpup(p
++);
172 layout
->olo_num_comps
= be32_to_cpup(p
++);
173 dprintk("%s: olo_comps_index=%d olo_num_comps=%d\n", __func__
,
174 layout
->olo_comps_index
, layout
->olo_num_comps
);
176 iter
->total_comps
= layout
->olo_num_comps
;
180 bool pnfs_osd_xdr_decode_layout_comp(struct pnfs_osd_object_cred
*comp
,
181 struct pnfs_osd_xdr_decode_layout_iter
*iter
, struct xdr_stream
*xdr
,
184 BUG_ON(iter
->decoded_comps
> iter
->total_comps
);
185 if (iter
->decoded_comps
== iter
->total_comps
)
188 *err
= _osd_xdr_decode_object_cred(comp
, xdr
);
189 if (unlikely(*err
)) {
190 dprintk("%s: _osd_xdr_decode_object_cred=>%d decoded_comps=%d "
191 "total_comps=%d\n", __func__
, *err
,
192 iter
->decoded_comps
, iter
->total_comps
);
193 return false; /* stop the loop */
195 dprintk("%s: dev(%llx:%llx) par=0x%llx obj=0x%llx "
196 "key_len=%u cap_len=%u\n",
198 _DEVID_LO(&comp
->oc_object_id
.oid_device_id
),
199 _DEVID_HI(&comp
->oc_object_id
.oid_device_id
),
200 comp
->oc_object_id
.oid_partition_id
,
201 comp
->oc_object_id
.oid_object_id
,
202 comp
->oc_cap_key
.cred_len
, comp
->oc_cap
.cred_len
);
204 iter
->decoded_comps
++;
209 * Get Device Information Decoding
211 * Note: since Device Information is currently done synchronously, all
212 * variable strings fields are left inside the rpc buffer and are only
213 * pointed to by the pnfs_osd_deviceaddr members. So the read buffer
214 * should not be freed while the returned information is in use.
217 *struct nfs4_string {
220 *}; // size [variable]
221 * NOTE: Returned string points to inside the XDR buffer
224 __read_u8_opaque(__be32
*p
, struct nfs4_string
*str
)
226 str
->len
= be32_to_cpup(p
++);
227 str
->data
= (char *)p
;
229 p
+= XDR_QUADLEN(str
->len
);
234 * struct pnfs_osd_targetid {
236 * struct nfs4_string oti_scsi_device_id;
237 * };// size 4 + [variable]
240 __read_targetid(__be32
*p
, struct pnfs_osd_targetid
* targetid
)
244 oti_type
= be32_to_cpup(p
++);
245 targetid
->oti_type
= oti_type
;
248 case OBJ_TARGET_SCSI_NAME
:
249 case OBJ_TARGET_SCSI_DEVICE_ID
:
250 p
= __read_u8_opaque(p
, &targetid
->oti_scsi_device_id
);
257 * struct pnfs_osd_net_addr {
258 * struct nfs4_string r_netid;
259 * struct nfs4_string r_addr;
263 __read_net_addr(__be32
*p
, struct pnfs_osd_net_addr
* netaddr
)
265 p
= __read_u8_opaque(p
, &netaddr
->r_netid
);
266 p
= __read_u8_opaque(p
, &netaddr
->r_addr
);
272 * struct pnfs_osd_targetaddr {
274 * struct pnfs_osd_net_addr ota_netaddr;
278 __read_targetaddr(__be32
*p
, struct pnfs_osd_targetaddr
*targetaddr
)
282 ota_available
= be32_to_cpup(p
++);
283 targetaddr
->ota_available
= ota_available
;
286 p
= __read_net_addr(p
, &targetaddr
->ota_netaddr
);
293 * struct pnfs_osd_deviceaddr {
294 * struct pnfs_osd_targetid oda_targetid;
295 * struct pnfs_osd_targetaddr oda_targetaddr;
297 * struct nfs4_string oda_systemid;
298 * struct pnfs_osd_object_cred oda_root_obj_cred;
299 * struct nfs4_string oda_osdname;
303 /* We need this version for the pnfs_osd_xdr_decode_deviceaddr which does
304 * not have an xdr_stream
307 __read_opaque_cred(__be32
*p
,
308 struct pnfs_osd_opaque_cred
*opaque_cred
)
310 opaque_cred
->cred_len
= be32_to_cpu(*p
++);
311 opaque_cred
->cred
= p
;
312 return p
+ XDR_QUADLEN(opaque_cred
->cred_len
);
316 __read_object_cred(__be32
*p
, struct pnfs_osd_object_cred
*comp
)
318 p
= _osd_xdr_decode_objid(p
, &comp
->oc_object_id
);
319 comp
->oc_osd_version
= be32_to_cpup(p
++);
320 comp
->oc_cap_key_sec
= be32_to_cpup(p
++);
322 p
= __read_opaque_cred(p
, &comp
->oc_cap_key
);
323 p
= __read_opaque_cred(p
, &comp
->oc_cap
);
327 void pnfs_osd_xdr_decode_deviceaddr(
328 struct pnfs_osd_deviceaddr
*deviceaddr
, __be32
*p
)
330 p
= __read_targetid(p
, &deviceaddr
->oda_targetid
);
332 p
= __read_targetaddr(p
, &deviceaddr
->oda_targetaddr
);
334 p
= xdr_decode_opaque_fixed(p
, deviceaddr
->oda_lun
,
335 sizeof(deviceaddr
->oda_lun
));
337 p
= __read_u8_opaque(p
, &deviceaddr
->oda_systemid
);
339 p
= __read_object_cred(p
, &deviceaddr
->oda_root_obj_cred
);
341 p
= __read_u8_opaque(p
, &deviceaddr
->oda_osdname
);
343 /* libosd likes this terminated in dbg. It's last, so no problems */
344 deviceaddr
->oda_osdname
.data
[deviceaddr
->oda_osdname
.len
] = 0;
348 * struct pnfs_osd_layoutupdate {
351 * u32 olu_ioerr_flag;
352 * }; xdr size 4 + 8 + 4
355 pnfs_osd_xdr_encode_layoutupdate(struct xdr_stream
*xdr
,
356 struct pnfs_osd_layoutupdate
*lou
)
358 __be32
*p
= xdr_reserve_space(xdr
, 4 + 8 + 4);
363 *p
++ = cpu_to_be32(lou
->dsu_valid
);
365 p
= xdr_encode_hyper(p
, lou
->dsu_delta
);
366 *p
++ = cpu_to_be32(lou
->olu_ioerr_flag
);
371 * struct pnfs_osd_objid {
372 * struct nfs4_deviceid oid_device_id;
373 * u64 oid_partition_id;
375 * }; // xdr size 32 bytes
377 static inline __be32
*
378 pnfs_osd_xdr_encode_objid(__be32
*p
, struct pnfs_osd_objid
*object_id
)
380 p
= xdr_encode_opaque_fixed(p
, &object_id
->oid_device_id
.data
,
381 sizeof(object_id
->oid_device_id
.data
));
382 p
= xdr_encode_hyper(p
, object_id
->oid_partition_id
);
383 p
= xdr_encode_hyper(p
, object_id
->oid_object_id
);
389 * struct pnfs_osd_ioerr {
390 * struct pnfs_osd_objid oer_component;
391 * u64 oer_comp_offset;
392 * u64 oer_comp_length;
395 * }; // xdr size 32 + 24 bytes
397 void pnfs_osd_xdr_encode_ioerr(__be32
*p
, struct pnfs_osd_ioerr
*ioerr
)
399 p
= pnfs_osd_xdr_encode_objid(p
, &ioerr
->oer_component
);
400 p
= xdr_encode_hyper(p
, ioerr
->oer_comp_offset
);
401 p
= xdr_encode_hyper(p
, ioerr
->oer_comp_length
);
402 *p
++ = cpu_to_be32(ioerr
->oer_iswrite
);
403 *p
= cpu_to_be32(ioerr
->oer_errno
);
406 __be32
*pnfs_osd_xdr_ioerr_reserve_space(struct xdr_stream
*xdr
)
410 p
= xdr_reserve_space(xdr
, 32 + 24);
412 dprintk("%s: out of xdr space\n", __func__
);