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 iter
->total_comps
= layout
->olo_num_comps
;
177 bool pnfs_osd_xdr_decode_layout_comp(struct pnfs_osd_object_cred
*comp
,
178 struct pnfs_osd_xdr_decode_layout_iter
*iter
, struct xdr_stream
*xdr
,
181 BUG_ON(iter
->decoded_comps
> iter
->total_comps
);
182 if (iter
->decoded_comps
== iter
->total_comps
)
185 *err
= _osd_xdr_decode_object_cred(comp
, xdr
);
186 if (unlikely(*err
)) {
187 dprintk("%s: _osd_xdr_decode_object_cred=>%d decoded_comps=%d "
188 "total_comps=%d\n", __func__
, *err
,
189 iter
->decoded_comps
, iter
->total_comps
);
190 return false; /* stop the loop */
192 dprintk("%s: dev(%llx:%llx) par=0x%llx obj=0x%llx "
193 "key_len=%u cap_len=%u\n",
195 _DEVID_LO(&comp
->oc_object_id
.oid_device_id
),
196 _DEVID_HI(&comp
->oc_object_id
.oid_device_id
),
197 comp
->oc_object_id
.oid_partition_id
,
198 comp
->oc_object_id
.oid_object_id
,
199 comp
->oc_cap_key
.cred_len
, comp
->oc_cap
.cred_len
);
201 iter
->decoded_comps
++;
206 * Get Device Information Decoding
208 * Note: since Device Information is currently done synchronously, all
209 * variable strings fields are left inside the rpc buffer and are only
210 * pointed to by the pnfs_osd_deviceaddr members. So the read buffer
211 * should not be freed while the returned information is in use.
214 *struct nfs4_string {
217 *}; // size [variable]
218 * NOTE: Returned string points to inside the XDR buffer
221 __read_u8_opaque(__be32
*p
, struct nfs4_string
*str
)
223 str
->len
= be32_to_cpup(p
++);
224 str
->data
= (char *)p
;
226 p
+= XDR_QUADLEN(str
->len
);
231 * struct pnfs_osd_targetid {
233 * struct nfs4_string oti_scsi_device_id;
234 * };// size 4 + [variable]
237 __read_targetid(__be32
*p
, struct pnfs_osd_targetid
* targetid
)
241 oti_type
= be32_to_cpup(p
++);
242 targetid
->oti_type
= oti_type
;
245 case OBJ_TARGET_SCSI_NAME
:
246 case OBJ_TARGET_SCSI_DEVICE_ID
:
247 p
= __read_u8_opaque(p
, &targetid
->oti_scsi_device_id
);
254 * struct pnfs_osd_net_addr {
255 * struct nfs4_string r_netid;
256 * struct nfs4_string r_addr;
260 __read_net_addr(__be32
*p
, struct pnfs_osd_net_addr
* netaddr
)
262 p
= __read_u8_opaque(p
, &netaddr
->r_netid
);
263 p
= __read_u8_opaque(p
, &netaddr
->r_addr
);
269 * struct pnfs_osd_targetaddr {
271 * struct pnfs_osd_net_addr ota_netaddr;
275 __read_targetaddr(__be32
*p
, struct pnfs_osd_targetaddr
*targetaddr
)
279 ota_available
= be32_to_cpup(p
++);
280 targetaddr
->ota_available
= ota_available
;
283 p
= __read_net_addr(p
, &targetaddr
->ota_netaddr
);
290 * struct pnfs_osd_deviceaddr {
291 * struct pnfs_osd_targetid oda_targetid;
292 * struct pnfs_osd_targetaddr oda_targetaddr;
294 * struct nfs4_string oda_systemid;
295 * struct pnfs_osd_object_cred oda_root_obj_cred;
296 * struct nfs4_string oda_osdname;
300 /* We need this version for the pnfs_osd_xdr_decode_deviceaddr which does
301 * not have an xdr_stream
304 __read_opaque_cred(__be32
*p
,
305 struct pnfs_osd_opaque_cred
*opaque_cred
)
307 opaque_cred
->cred_len
= be32_to_cpu(*p
++);
308 opaque_cred
->cred
= p
;
309 return p
+ XDR_QUADLEN(opaque_cred
->cred_len
);
313 __read_object_cred(__be32
*p
, struct pnfs_osd_object_cred
*comp
)
315 p
= _osd_xdr_decode_objid(p
, &comp
->oc_object_id
);
316 comp
->oc_osd_version
= be32_to_cpup(p
++);
317 comp
->oc_cap_key_sec
= be32_to_cpup(p
++);
319 p
= __read_opaque_cred(p
, &comp
->oc_cap_key
);
320 p
= __read_opaque_cred(p
, &comp
->oc_cap
);
324 void pnfs_osd_xdr_decode_deviceaddr(
325 struct pnfs_osd_deviceaddr
*deviceaddr
, __be32
*p
)
327 p
= __read_targetid(p
, &deviceaddr
->oda_targetid
);
329 p
= __read_targetaddr(p
, &deviceaddr
->oda_targetaddr
);
331 p
= xdr_decode_opaque_fixed(p
, deviceaddr
->oda_lun
,
332 sizeof(deviceaddr
->oda_lun
));
334 p
= __read_u8_opaque(p
, &deviceaddr
->oda_systemid
);
336 p
= __read_object_cred(p
, &deviceaddr
->oda_root_obj_cred
);
338 p
= __read_u8_opaque(p
, &deviceaddr
->oda_osdname
);
340 /* libosd likes this terminated in dbg. It's last, so no problems */
341 deviceaddr
->oda_osdname
.data
[deviceaddr
->oda_osdname
.len
] = 0;
345 * struct pnfs_osd_layoutupdate {
348 * u32 olu_ioerr_flag;
349 * }; xdr size 4 + 8 + 4
352 pnfs_osd_xdr_encode_layoutupdate(struct xdr_stream
*xdr
,
353 struct pnfs_osd_layoutupdate
*lou
)
355 __be32
*p
= xdr_reserve_space(xdr
, 4 + 8 + 4);
360 *p
++ = cpu_to_be32(lou
->dsu_valid
);
362 p
= xdr_encode_hyper(p
, lou
->dsu_delta
);
363 *p
++ = cpu_to_be32(lou
->olu_ioerr_flag
);
368 * struct pnfs_osd_objid {
369 * struct nfs4_deviceid oid_device_id;
370 * u64 oid_partition_id;
372 * }; // xdr size 32 bytes
374 static inline __be32
*
375 pnfs_osd_xdr_encode_objid(__be32
*p
, struct pnfs_osd_objid
*object_id
)
377 p
= xdr_encode_opaque_fixed(p
, &object_id
->oid_device_id
.data
,
378 sizeof(object_id
->oid_device_id
.data
));
379 p
= xdr_encode_hyper(p
, object_id
->oid_partition_id
);
380 p
= xdr_encode_hyper(p
, object_id
->oid_object_id
);
386 * struct pnfs_osd_ioerr {
387 * struct pnfs_osd_objid oer_component;
388 * u64 oer_comp_offset;
389 * u64 oer_comp_length;
392 * }; // xdr size 32 + 24 bytes
394 void pnfs_osd_xdr_encode_ioerr(__be32
*p
, struct pnfs_osd_ioerr
*ioerr
)
396 p
= pnfs_osd_xdr_encode_objid(p
, &ioerr
->oer_component
);
397 p
= xdr_encode_hyper(p
, ioerr
->oer_comp_offset
);
398 p
= xdr_encode_hyper(p
, ioerr
->oer_comp_length
);
399 *p
++ = cpu_to_be32(ioerr
->oer_iswrite
);
400 *p
= cpu_to_be32(ioerr
->oer_errno
);
403 __be32
*pnfs_osd_xdr_ioerr_reserve_space(struct xdr_stream
*xdr
)
407 p
= xdr_reserve_space(xdr
, 32 + 24);
409 dprintk("%s: out of xdr space\n", __func__
);