Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

pnfs-obj: pnfs_osd XDR client implementation

* Add the fs/nfs/objlayout/pnfs_osd_xdr_cli.c file, which will
include the XDR encode/decode implementations for the pNFS
client objlayout driver.

[Wrong type in comments]
Signed-off-by: Boaz Harrosh <bharrosh@panasas.com>
Signed-off-by: Benny Halevy <bhalevy@panasas.com>

+413 -1
+1 -1
fs/nfs/objlayout/Kbuild
··· 1 1 # 2 2 # Makefile for the pNFS Objects Layout Driver kernel module 3 3 # 4 - objlayoutdriver-y := objio_osd.o 4 + objlayoutdriver-y := objio_osd.o pnfs_osd_xdr_cli.o 5 5 obj-$(CONFIG_PNFS_OBJLAYOUT) += objlayoutdriver.o
+412
fs/nfs/objlayout/pnfs_osd_xdr_cli.c
··· 1 + /* 2 + * Object-Based pNFS Layout XDR layer 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 + 40 + #include <linux/pnfs_osd_xdr.h> 41 + 42 + #define NFSDBG_FACILITY NFSDBG_PNFS_LD 43 + 44 + /* 45 + * The following implementation is based on RFC5664 46 + */ 47 + 48 + /* 49 + * struct pnfs_osd_objid { 50 + * struct nfs4_deviceid oid_device_id; 51 + * u64 oid_partition_id; 52 + * u64 oid_object_id; 53 + * }; // xdr size 32 bytes 54 + */ 55 + static __be32 * 56 + _osd_xdr_decode_objid(__be32 *p, struct pnfs_osd_objid *objid) 57 + { 58 + p = xdr_decode_opaque_fixed(p, objid->oid_device_id.data, 59 + sizeof(objid->oid_device_id.data)); 60 + 61 + p = xdr_decode_hyper(p, &objid->oid_partition_id); 62 + p = xdr_decode_hyper(p, &objid->oid_object_id); 63 + return p; 64 + } 65 + /* 66 + * struct pnfs_osd_opaque_cred { 67 + * u32 cred_len; 68 + * void *cred; 69 + * }; // xdr size [variable] 70 + * The return pointers are from the xdr buffer 71 + */ 72 + static int 73 + _osd_xdr_decode_opaque_cred(struct pnfs_osd_opaque_cred *opaque_cred, 74 + struct xdr_stream *xdr) 75 + { 76 + __be32 *p = xdr_inline_decode(xdr, 1); 77 + 78 + if (!p) 79 + return -EINVAL; 80 + 81 + opaque_cred->cred_len = be32_to_cpu(*p++); 82 + 83 + p = xdr_inline_decode(xdr, opaque_cred->cred_len); 84 + if (!p) 85 + return -EINVAL; 86 + 87 + opaque_cred->cred = p; 88 + return 0; 89 + } 90 + 91 + /* 92 + * struct pnfs_osd_object_cred { 93 + * struct pnfs_osd_objid oc_object_id; 94 + * u32 oc_osd_version; 95 + * u32 oc_cap_key_sec; 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] 99 + */ 100 + static int 101 + _osd_xdr_decode_object_cred(struct pnfs_osd_object_cred *comp, 102 + struct xdr_stream *xdr) 103 + { 104 + __be32 *p = xdr_inline_decode(xdr, 32 + 4 + 4); 105 + int ret; 106 + 107 + if (!p) 108 + return -EIO; 109 + 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); 113 + 114 + ret = _osd_xdr_decode_opaque_cred(&comp->oc_cap_key, xdr); 115 + if (unlikely(ret)) 116 + return ret; 117 + 118 + ret = _osd_xdr_decode_opaque_cred(&comp->oc_cap, xdr); 119 + return ret; 120 + } 121 + 122 + /* 123 + * struct pnfs_osd_data_map { 124 + * u32 odm_num_comps; 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 131 + */ 132 + static inline int 133 + _osd_data_map_xdr_sz(void) 134 + { 135 + return 4 + 8 + 4 + 4 + 4 + 4; 136 + } 137 + 138 + static __be32 * 139 + _osd_xdr_decode_data_map(__be32 *p, struct pnfs_osd_data_map *data_map) 140 + { 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", 149 + __func__, 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); 156 + return p; 157 + } 158 + 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) 161 + { 162 + __be32 *p; 163 + 164 + memset(iter, 0, sizeof(*iter)); 165 + 166 + p = xdr_inline_decode(xdr, _osd_data_map_xdr_sz() + 4 + 4); 167 + if (unlikely(!p)) 168 + return -EINVAL; 169 + 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; 174 + return 0; 175 + } 176 + 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, 179 + int *err) 180 + { 181 + BUG_ON(iter->decoded_comps > iter->total_comps); 182 + if (iter->decoded_comps == iter->total_comps) 183 + return false; 184 + 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 */ 191 + } 192 + dprintk("%s: dev(%llx:%llx) par=0x%llx obj=0x%llx " 193 + "key_len=%u cap_len=%u\n", 194 + __func__, 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); 200 + 201 + iter->decoded_comps++; 202 + return true; 203 + } 204 + 205 + /* 206 + * Get Device Information Decoding 207 + * 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. 212 + */ 213 + /* 214 + *struct nfs4_string { 215 + * unsigned int len; 216 + * char *data; 217 + *}; // size [variable] 218 + * NOTE: Returned string points to inside the XDR buffer 219 + */ 220 + static __be32 * 221 + __read_u8_opaque(__be32 *p, struct nfs4_string *str) 222 + { 223 + str->len = be32_to_cpup(p++); 224 + str->data = (char *)p; 225 + 226 + p += XDR_QUADLEN(str->len); 227 + return p; 228 + } 229 + 230 + /* 231 + * struct pnfs_osd_targetid { 232 + * u32 oti_type; 233 + * struct nfs4_string oti_scsi_device_id; 234 + * };// size 4 + [variable] 235 + */ 236 + static __be32 * 237 + __read_targetid(__be32 *p, struct pnfs_osd_targetid* targetid) 238 + { 239 + u32 oti_type; 240 + 241 + oti_type = be32_to_cpup(p++); 242 + targetid->oti_type = oti_type; 243 + 244 + switch (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); 248 + } 249 + 250 + return p; 251 + } 252 + 253 + /* 254 + * struct pnfs_osd_net_addr { 255 + * struct nfs4_string r_netid; 256 + * struct nfs4_string r_addr; 257 + * }; 258 + */ 259 + static __be32 * 260 + __read_net_addr(__be32 *p, struct pnfs_osd_net_addr* netaddr) 261 + { 262 + p = __read_u8_opaque(p, &netaddr->r_netid); 263 + p = __read_u8_opaque(p, &netaddr->r_addr); 264 + 265 + return p; 266 + } 267 + 268 + /* 269 + * struct pnfs_osd_targetaddr { 270 + * u32 ota_available; 271 + * struct pnfs_osd_net_addr ota_netaddr; 272 + * }; 273 + */ 274 + static __be32 * 275 + __read_targetaddr(__be32 *p, struct pnfs_osd_targetaddr *targetaddr) 276 + { 277 + u32 ota_available; 278 + 279 + ota_available = be32_to_cpup(p++); 280 + targetaddr->ota_available = ota_available; 281 + 282 + if (ota_available) 283 + p = __read_net_addr(p, &targetaddr->ota_netaddr); 284 + 285 + 286 + return p; 287 + } 288 + 289 + /* 290 + * struct pnfs_osd_deviceaddr { 291 + * struct pnfs_osd_targetid oda_targetid; 292 + * struct pnfs_osd_targetaddr oda_targetaddr; 293 + * u8 oda_lun[8]; 294 + * struct nfs4_string oda_systemid; 295 + * struct pnfs_osd_object_cred oda_root_obj_cred; 296 + * struct nfs4_string oda_osdname; 297 + * }; 298 + */ 299 + 300 + /* We need this version for the pnfs_osd_xdr_decode_deviceaddr which does 301 + * not have an xdr_stream 302 + */ 303 + static __be32 * 304 + __read_opaque_cred(__be32 *p, 305 + struct pnfs_osd_opaque_cred *opaque_cred) 306 + { 307 + opaque_cred->cred_len = be32_to_cpu(*p++); 308 + opaque_cred->cred = p; 309 + return p + XDR_QUADLEN(opaque_cred->cred_len); 310 + } 311 + 312 + static __be32 * 313 + __read_object_cred(__be32 *p, struct pnfs_osd_object_cred *comp) 314 + { 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++); 318 + 319 + p = __read_opaque_cred(p, &comp->oc_cap_key); 320 + p = __read_opaque_cred(p, &comp->oc_cap); 321 + return p; 322 + } 323 + 324 + void pnfs_osd_xdr_decode_deviceaddr( 325 + struct pnfs_osd_deviceaddr *deviceaddr, __be32 *p) 326 + { 327 + p = __read_targetid(p, &deviceaddr->oda_targetid); 328 + 329 + p = __read_targetaddr(p, &deviceaddr->oda_targetaddr); 330 + 331 + p = xdr_decode_opaque_fixed(p, deviceaddr->oda_lun, 332 + sizeof(deviceaddr->oda_lun)); 333 + 334 + p = __read_u8_opaque(p, &deviceaddr->oda_systemid); 335 + 336 + p = __read_object_cred(p, &deviceaddr->oda_root_obj_cred); 337 + 338 + p = __read_u8_opaque(p, &deviceaddr->oda_osdname); 339 + 340 + /* libosd likes this terminated in dbg. It's last, so no problems */ 341 + deviceaddr->oda_osdname.data[deviceaddr->oda_osdname.len] = 0; 342 + } 343 + 344 + /* 345 + * struct pnfs_osd_layoutupdate { 346 + * u32 dsu_valid; 347 + * s64 dsu_delta; 348 + * u32 olu_ioerr_flag; 349 + * }; xdr size 4 + 8 + 4 350 + */ 351 + int 352 + pnfs_osd_xdr_encode_layoutupdate(struct xdr_stream *xdr, 353 + struct pnfs_osd_layoutupdate *lou) 354 + { 355 + __be32 *p = xdr_reserve_space(xdr, 4 + 8 + 4); 356 + 357 + if (!p) 358 + return -E2BIG; 359 + 360 + *p++ = cpu_to_be32(lou->dsu_valid); 361 + if (lou->dsu_valid) 362 + p = xdr_encode_hyper(p, lou->dsu_delta); 363 + *p++ = cpu_to_be32(lou->olu_ioerr_flag); 364 + return 0; 365 + } 366 + 367 + /* 368 + * struct pnfs_osd_objid { 369 + * struct nfs4_deviceid oid_device_id; 370 + * u64 oid_partition_id; 371 + * u64 oid_object_id; 372 + * }; // xdr size 32 bytes 373 + */ 374 + static inline __be32 * 375 + pnfs_osd_xdr_encode_objid(__be32 *p, struct pnfs_osd_objid *object_id) 376 + { 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); 381 + 382 + return p; 383 + } 384 + 385 + /* 386 + * struct pnfs_osd_ioerr { 387 + * struct pnfs_osd_objid oer_component; 388 + * u64 oer_comp_offset; 389 + * u64 oer_comp_length; 390 + * u32 oer_iswrite; 391 + * u32 oer_errno; 392 + * }; // xdr size 32 + 24 bytes 393 + */ 394 + void pnfs_osd_xdr_encode_ioerr(__be32 *p, struct pnfs_osd_ioerr *ioerr) 395 + { 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); 401 + } 402 + 403 + __be32 *pnfs_osd_xdr_ioerr_reserve_space(struct xdr_stream *xdr) 404 + { 405 + __be32 *p; 406 + 407 + p = xdr_reserve_space(xdr, 32 + 24); 408 + if (unlikely(!p)) 409 + dprintk("%s: out of xdr space\n", __func__); 410 + 411 + return p; 412 + }