1/*
2 *  pNFS-osd on-the-wire data structures
3 *
4 *  Copyright (C) 2007 Panasas Inc. [year of first publication]
5 *  All rights reserved.
6 *
7 *  Benny Halevy <bhalevy@panasas.com>
8 *  Boaz Harrosh <ooo@electrozaur.com>
9 *
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.
13 *
14 *  Redistribution and use in source and binary forms, with or without
15 *  modification, are permitted provided that the following conditions
16 *  are met:
17 *
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.
26 *
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.
38 */
39#ifndef __PNFS_OSD_XDR_H__
40#define __PNFS_OSD_XDR_H__
41
42#include <linux/nfs_fs.h>
43
44/*
45 * draft-ietf-nfsv4-minorversion-22
46 * draft-ietf-nfsv4-pnfs-obj-12
47 */
48
49/* Layout Structure */
50
51enum pnfs_osd_raid_algorithm4 {
52	PNFS_OSD_RAID_0		= 1,
53	PNFS_OSD_RAID_4		= 2,
54	PNFS_OSD_RAID_5		= 3,
55	PNFS_OSD_RAID_PQ	= 4     /* Reed-Solomon P+Q */
56};
57
58/*   struct pnfs_osd_data_map4 {
59 *       uint32_t                    odm_num_comps;
60 *       length4                     odm_stripe_unit;
61 *       uint32_t                    odm_group_width;
62 *       uint32_t                    odm_group_depth;
63 *       uint32_t                    odm_mirror_cnt;
64 *       pnfs_osd_raid_algorithm4    odm_raid_algorithm;
65 *   };
66 */
67struct pnfs_osd_data_map {
68	u32	odm_num_comps;
69	u64	odm_stripe_unit;
70	u32	odm_group_width;
71	u32	odm_group_depth;
72	u32	odm_mirror_cnt;
73	u32	odm_raid_algorithm;
74};
75
76/*   struct pnfs_osd_objid4 {
77 *       deviceid4       oid_device_id;
78 *       uint64_t        oid_partition_id;
79 *       uint64_t        oid_object_id;
80 *   };
81 */
82struct pnfs_osd_objid {
83	struct nfs4_deviceid	oid_device_id;
84	u64			oid_partition_id;
85	u64			oid_object_id;
86};
87
88/* For printout. I use:
89 * kprint("dev(%llx:%llx)", _DEVID_LO(pointer), _DEVID_HI(pointer));
90 * BE style
91 */
92#define _DEVID_LO(oid_device_id) \
93	(unsigned long long)be64_to_cpup((__be64 *)(oid_device_id)->data)
94
95#define _DEVID_HI(oid_device_id) \
96	(unsigned long long)be64_to_cpup(((__be64 *)(oid_device_id)->data) + 1)
97
98enum pnfs_osd_version {
99	PNFS_OSD_MISSING              = 0,
100	PNFS_OSD_VERSION_1            = 1,
101	PNFS_OSD_VERSION_2            = 2
102};
103
104struct pnfs_osd_opaque_cred {
105	u32 cred_len;
106	void *cred;
107};
108
109enum pnfs_osd_cap_key_sec {
110	PNFS_OSD_CAP_KEY_SEC_NONE     = 0,
111	PNFS_OSD_CAP_KEY_SEC_SSV      = 1,
112};
113
114/*   struct pnfs_osd_object_cred4 {
115 *       pnfs_osd_objid4         oc_object_id;
116 *       pnfs_osd_version4       oc_osd_version;
117 *       pnfs_osd_cap_key_sec4   oc_cap_key_sec;
118 *       opaque                  oc_capability_key<>;
119 *       opaque                  oc_capability<>;
120 *   };
121 */
122struct pnfs_osd_object_cred {
123	struct pnfs_osd_objid		oc_object_id;
124	u32				oc_osd_version;
125	u32				oc_cap_key_sec;
126	struct pnfs_osd_opaque_cred	oc_cap_key;
127	struct pnfs_osd_opaque_cred	oc_cap;
128};
129
130/*   struct pnfs_osd_layout4 {
131 *       pnfs_osd_data_map4      olo_map;
132 *       uint32_t                olo_comps_index;
133 *       pnfs_osd_object_cred4   olo_components<>;
134 *   };
135 */
136struct pnfs_osd_layout {
137	struct pnfs_osd_data_map	olo_map;
138	u32				olo_comps_index;
139	u32				olo_num_comps;
140	struct pnfs_osd_object_cred	*olo_comps;
141};
142
143/* Device Address */
144enum pnfs_osd_targetid_type {
145	OBJ_TARGET_ANON = 1,
146	OBJ_TARGET_SCSI_NAME = 2,
147	OBJ_TARGET_SCSI_DEVICE_ID = 3,
148};
149
150/*   union pnfs_osd_targetid4 switch (pnfs_osd_targetid_type4 oti_type) {
151 *       case OBJ_TARGET_SCSI_NAME:
152 *           string              oti_scsi_name<>;
153 *
154 *       case OBJ_TARGET_SCSI_DEVICE_ID:
155 *           opaque              oti_scsi_device_id<>;
156 *
157 *       default:
158 *           void;
159 *   };
160 *
161 *   union pnfs_osd_targetaddr4 switch (bool ota_available) {
162 *       case TRUE:
163 *           netaddr4            ota_netaddr;
164 *       case FALSE:
165 *           void;
166 *   };
167 *
168 *   struct pnfs_osd_deviceaddr4 {
169 *       pnfs_osd_targetid4      oda_targetid;
170 *       pnfs_osd_targetaddr4    oda_targetaddr;
171 *       uint64_t                oda_lun;
172 *       opaque                  oda_systemid<>;
173 *       pnfs_osd_object_cred4   oda_root_obj_cred;
174 *       opaque                  oda_osdname<>;
175 *   };
176 */
177struct pnfs_osd_targetid {
178	u32				oti_type;
179	struct nfs4_string		oti_scsi_device_id;
180};
181
182/*   struct netaddr4 {
183 *       // see struct rpcb in RFC1833
184 *       string r_netid<>;    // network id
185 *       string r_addr<>;     // universal address
186 *   };
187 */
188struct pnfs_osd_net_addr {
189	struct nfs4_string	r_netid;
190	struct nfs4_string	r_addr;
191};
192
193struct pnfs_osd_targetaddr {
194	u32				ota_available;
195	struct pnfs_osd_net_addr	ota_netaddr;
196};
197
198struct pnfs_osd_deviceaddr {
199	struct pnfs_osd_targetid	oda_targetid;
200	struct pnfs_osd_targetaddr	oda_targetaddr;
201	u8				oda_lun[8];
202	struct nfs4_string		oda_systemid;
203	struct pnfs_osd_object_cred	oda_root_obj_cred;
204	struct nfs4_string		oda_osdname;
205};
206
207/* LAYOUTCOMMIT: layoutupdate */
208
209/*   union pnfs_osd_deltaspaceused4 switch (bool dsu_valid) {
210 *       case TRUE:
211 *           int64_t     dsu_delta;
212 *       case FALSE:
213 *           void;
214 *   };
215 *
216 *   struct pnfs_osd_layoutupdate4 {
217 *       pnfs_osd_deltaspaceused4    olu_delta_space_used;
218 *       bool                        olu_ioerr_flag;
219 *   };
220 */
221struct pnfs_osd_layoutupdate {
222	u32	dsu_valid;
223	s64	dsu_delta;
224	u32	olu_ioerr_flag;
225};
226
227/* LAYOUTRETURN: I/O Rrror Report */
228
229enum pnfs_osd_errno {
230	PNFS_OSD_ERR_EIO		= 1,
231	PNFS_OSD_ERR_NOT_FOUND		= 2,
232	PNFS_OSD_ERR_NO_SPACE		= 3,
233	PNFS_OSD_ERR_BAD_CRED		= 4,
234	PNFS_OSD_ERR_NO_ACCESS		= 5,
235	PNFS_OSD_ERR_UNREACHABLE	= 6,
236	PNFS_OSD_ERR_RESOURCE		= 7
237};
238
239/*   struct pnfs_osd_ioerr4 {
240 *       pnfs_osd_objid4     oer_component;
241 *       length4             oer_comp_offset;
242 *       length4             oer_comp_length;
243 *       bool                oer_iswrite;
244 *       pnfs_osd_errno4     oer_errno;
245 *   };
246 */
247struct pnfs_osd_ioerr {
248	struct pnfs_osd_objid	oer_component;
249	u64			oer_comp_offset;
250	u64			oer_comp_length;
251	u32			oer_iswrite;
252	u32			oer_errno;
253};
254
255/* OSD XDR Client API */
256/* Layout helpers */
257/* Layout decoding is done in two parts:
258 * 1. First Call pnfs_osd_xdr_decode_layout_map to read in only the header part
259 *    of the layout. @iter members need not be initialized.
260 *    Returned:
261 *             @layout members are set. (@layout->olo_comps set to NULL).
262 *
263 *             Zero on success, or negative error if passed xdr is broken.
264 *
265 * 2. 2nd Call pnfs_osd_xdr_decode_layout_comp() in a loop until it returns
266 *    false, to decode the next component.
267 *    Returned:
268 *       true if there is more to decode or false if we are done or error.
269 *
270 * Example:
271 *	struct pnfs_osd_xdr_decode_layout_iter iter;
272 *	struct pnfs_osd_layout layout;
273 *	struct pnfs_osd_object_cred comp;
274 *	int status;
275 *
276 *	status = pnfs_osd_xdr_decode_layout_map(&layout, &iter, xdr);
277 *	if (unlikely(status))
278 *		goto err;
279 *	while(pnfs_osd_xdr_decode_layout_comp(&comp, &iter, xdr, &status)) {
280 *		// All of @comp strings point to inside the xdr_buffer
281 *		// or scrach buffer. Copy them out to user memory eg.
282 *		copy_single_comp(dest_comp++, &comp);
283 *	}
284 *	if (unlikely(status))
285 *		goto err;
286 */
287
288struct pnfs_osd_xdr_decode_layout_iter {
289	unsigned total_comps;
290	unsigned decoded_comps;
291};
292
293extern int pnfs_osd_xdr_decode_layout_map(struct pnfs_osd_layout *layout,
294	struct pnfs_osd_xdr_decode_layout_iter *iter, struct xdr_stream *xdr);
295
296extern bool pnfs_osd_xdr_decode_layout_comp(struct pnfs_osd_object_cred *comp,
297	struct pnfs_osd_xdr_decode_layout_iter *iter, struct xdr_stream *xdr,
298	int *err);
299
300/* Device Info helpers */
301
302/* Note: All strings inside @deviceaddr point to space inside @p.
303 * @p should stay valid while @deviceaddr is in use.
304 */
305extern void pnfs_osd_xdr_decode_deviceaddr(
306	struct pnfs_osd_deviceaddr *deviceaddr, __be32 *p);
307
308/* layoutupdate (layout_commit) xdr helpers */
309extern int
310pnfs_osd_xdr_encode_layoutupdate(struct xdr_stream *xdr,
311				 struct pnfs_osd_layoutupdate *lou);
312
313/* osd_ioerror encoding (layout_return) */
314extern __be32 *pnfs_osd_xdr_ioerr_reserve_space(struct xdr_stream *xdr);
315extern void pnfs_osd_xdr_encode_ioerr(__be32 *p, struct pnfs_osd_ioerr *ioerr);
316
317#endif /* __PNFS_OSD_XDR_H__ */
318