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