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

Configure Feed

Select the types of activity you want to include in your feed.

at v3.7-rc1 605 lines 14 kB view raw
1/* 2 * linux/fs/lockd/clnt4xdr.c 3 * 4 * XDR functions to encode/decode NLM version 4 RPC arguments and results. 5 * 6 * NLM client-side only. 7 * 8 * Copyright (C) 2010, Oracle. All rights reserved. 9 */ 10 11#include <linux/types.h> 12#include <linux/sunrpc/xdr.h> 13#include <linux/sunrpc/clnt.h> 14#include <linux/sunrpc/stats.h> 15#include <linux/lockd/lockd.h> 16 17#define NLMDBG_FACILITY NLMDBG_XDR 18 19#if (NLMCLNT_OHSIZE > XDR_MAX_NETOBJ) 20# error "NLM host name cannot be larger than XDR_MAX_NETOBJ!" 21#endif 22 23#if (NLMCLNT_OHSIZE > NLM_MAXSTRLEN) 24# error "NLM host name cannot be larger than NLM's maximum string length!" 25#endif 26 27/* 28 * Declare the space requirements for NLM arguments and replies as 29 * number of 32bit-words 30 */ 31#define NLM4_void_sz (0) 32#define NLM4_cookie_sz (1+(NLM_MAXCOOKIELEN>>2)) 33#define NLM4_caller_sz (1+(NLMCLNT_OHSIZE>>2)) 34#define NLM4_owner_sz (1+(NLMCLNT_OHSIZE>>2)) 35#define NLM4_fhandle_sz (1+(NFS3_FHSIZE>>2)) 36#define NLM4_lock_sz (5+NLM4_caller_sz+NLM4_owner_sz+NLM4_fhandle_sz) 37#define NLM4_holder_sz (6+NLM4_owner_sz) 38 39#define NLM4_testargs_sz (NLM4_cookie_sz+1+NLM4_lock_sz) 40#define NLM4_lockargs_sz (NLM4_cookie_sz+4+NLM4_lock_sz) 41#define NLM4_cancargs_sz (NLM4_cookie_sz+2+NLM4_lock_sz) 42#define NLM4_unlockargs_sz (NLM4_cookie_sz+NLM4_lock_sz) 43 44#define NLM4_testres_sz (NLM4_cookie_sz+1+NLM4_holder_sz) 45#define NLM4_res_sz (NLM4_cookie_sz+1) 46#define NLM4_norep_sz (0) 47 48 49static s64 loff_t_to_s64(loff_t offset) 50{ 51 s64 res; 52 53 if (offset >= NLM4_OFFSET_MAX) 54 res = NLM4_OFFSET_MAX; 55 else if (offset <= -NLM4_OFFSET_MAX) 56 res = -NLM4_OFFSET_MAX; 57 else 58 res = offset; 59 return res; 60} 61 62static void nlm4_compute_offsets(const struct nlm_lock *lock, 63 u64 *l_offset, u64 *l_len) 64{ 65 const struct file_lock *fl = &lock->fl; 66 67 BUG_ON(fl->fl_start > NLM4_OFFSET_MAX); 68 BUG_ON(fl->fl_end > NLM4_OFFSET_MAX && 69 fl->fl_end != OFFSET_MAX); 70 71 *l_offset = loff_t_to_s64(fl->fl_start); 72 if (fl->fl_end == OFFSET_MAX) 73 *l_len = 0; 74 else 75 *l_len = loff_t_to_s64(fl->fl_end - fl->fl_start + 1); 76} 77 78/* 79 * Handle decode buffer overflows out-of-line. 80 */ 81static void print_overflow_msg(const char *func, const struct xdr_stream *xdr) 82{ 83 dprintk("lockd: %s prematurely hit the end of our receive buffer. " 84 "Remaining buffer length is %tu words.\n", 85 func, xdr->end - xdr->p); 86} 87 88 89/* 90 * Encode/decode NLMv4 basic data types 91 * 92 * Basic NLMv4 data types are defined in Appendix II, section 6.1.4 93 * of RFC 1813: "NFS Version 3 Protocol Specification" and in Chapter 94 * 10 of X/Open's "Protocols for Interworking: XNFS, Version 3W". 95 * 96 * Not all basic data types have their own encoding and decoding 97 * functions. For run-time efficiency, some data types are encoded 98 * or decoded inline. 99 */ 100 101static void encode_bool(struct xdr_stream *xdr, const int value) 102{ 103 __be32 *p; 104 105 p = xdr_reserve_space(xdr, 4); 106 *p = value ? xdr_one : xdr_zero; 107} 108 109static void encode_int32(struct xdr_stream *xdr, const s32 value) 110{ 111 __be32 *p; 112 113 p = xdr_reserve_space(xdr, 4); 114 *p = cpu_to_be32(value); 115} 116 117/* 118 * typedef opaque netobj<MAXNETOBJ_SZ> 119 */ 120static void encode_netobj(struct xdr_stream *xdr, 121 const u8 *data, const unsigned int length) 122{ 123 __be32 *p; 124 125 BUG_ON(length > XDR_MAX_NETOBJ); 126 p = xdr_reserve_space(xdr, 4 + length); 127 xdr_encode_opaque(p, data, length); 128} 129 130static int decode_netobj(struct xdr_stream *xdr, 131 struct xdr_netobj *obj) 132{ 133 u32 length; 134 __be32 *p; 135 136 p = xdr_inline_decode(xdr, 4); 137 if (unlikely(p == NULL)) 138 goto out_overflow; 139 length = be32_to_cpup(p++); 140 if (unlikely(length > XDR_MAX_NETOBJ)) 141 goto out_size; 142 obj->len = length; 143 obj->data = (u8 *)p; 144 return 0; 145out_size: 146 dprintk("NFS: returned netobj was too long: %u\n", length); 147 return -EIO; 148out_overflow: 149 print_overflow_msg(__func__, xdr); 150 return -EIO; 151} 152 153/* 154 * netobj cookie; 155 */ 156static void encode_cookie(struct xdr_stream *xdr, 157 const struct nlm_cookie *cookie) 158{ 159 BUG_ON(cookie->len > NLM_MAXCOOKIELEN); 160 encode_netobj(xdr, (u8 *)&cookie->data, cookie->len); 161} 162 163static int decode_cookie(struct xdr_stream *xdr, 164 struct nlm_cookie *cookie) 165{ 166 u32 length; 167 __be32 *p; 168 169 p = xdr_inline_decode(xdr, 4); 170 if (unlikely(p == NULL)) 171 goto out_overflow; 172 length = be32_to_cpup(p++); 173 /* apparently HPUX can return empty cookies */ 174 if (length == 0) 175 goto out_hpux; 176 if (length > NLM_MAXCOOKIELEN) 177 goto out_size; 178 p = xdr_inline_decode(xdr, length); 179 if (unlikely(p == NULL)) 180 goto out_overflow; 181 cookie->len = length; 182 memcpy(cookie->data, p, length); 183 return 0; 184out_hpux: 185 cookie->len = 4; 186 memset(cookie->data, 0, 4); 187 return 0; 188out_size: 189 dprintk("NFS: returned cookie was too long: %u\n", length); 190 return -EIO; 191out_overflow: 192 print_overflow_msg(__func__, xdr); 193 return -EIO; 194} 195 196/* 197 * netobj fh; 198 */ 199static void encode_fh(struct xdr_stream *xdr, const struct nfs_fh *fh) 200{ 201 BUG_ON(fh->size > NFS3_FHSIZE); 202 encode_netobj(xdr, (u8 *)&fh->data, fh->size); 203} 204 205/* 206 * enum nlm4_stats { 207 * NLM4_GRANTED = 0, 208 * NLM4_DENIED = 1, 209 * NLM4_DENIED_NOLOCKS = 2, 210 * NLM4_BLOCKED = 3, 211 * NLM4_DENIED_GRACE_PERIOD = 4, 212 * NLM4_DEADLCK = 5, 213 * NLM4_ROFS = 6, 214 * NLM4_STALE_FH = 7, 215 * NLM4_FBIG = 8, 216 * NLM4_FAILED = 9 217 * }; 218 * 219 * struct nlm4_stat { 220 * nlm4_stats stat; 221 * }; 222 * 223 * NB: we don't swap bytes for the NLM status values. The upper 224 * layers deal directly with the status value in network byte 225 * order. 226 */ 227static void encode_nlm4_stat(struct xdr_stream *xdr, 228 const __be32 stat) 229{ 230 __be32 *p; 231 232 BUG_ON(be32_to_cpu(stat) > NLM_FAILED); 233 p = xdr_reserve_space(xdr, 4); 234 *p = stat; 235} 236 237static int decode_nlm4_stat(struct xdr_stream *xdr, __be32 *stat) 238{ 239 __be32 *p; 240 241 p = xdr_inline_decode(xdr, 4); 242 if (unlikely(p == NULL)) 243 goto out_overflow; 244 if (unlikely(ntohl(*p) > ntohl(nlm4_failed))) 245 goto out_bad_xdr; 246 *stat = *p; 247 return 0; 248out_bad_xdr: 249 dprintk("%s: server returned invalid nlm4_stats value: %u\n", 250 __func__, be32_to_cpup(p)); 251 return -EIO; 252out_overflow: 253 print_overflow_msg(__func__, xdr); 254 return -EIO; 255} 256 257/* 258 * struct nlm4_holder { 259 * bool exclusive; 260 * int32 svid; 261 * netobj oh; 262 * uint64 l_offset; 263 * uint64 l_len; 264 * }; 265 */ 266static void encode_nlm4_holder(struct xdr_stream *xdr, 267 const struct nlm_res *result) 268{ 269 const struct nlm_lock *lock = &result->lock; 270 u64 l_offset, l_len; 271 __be32 *p; 272 273 encode_bool(xdr, lock->fl.fl_type == F_RDLCK); 274 encode_int32(xdr, lock->svid); 275 encode_netobj(xdr, lock->oh.data, lock->oh.len); 276 277 p = xdr_reserve_space(xdr, 4 + 4); 278 nlm4_compute_offsets(lock, &l_offset, &l_len); 279 p = xdr_encode_hyper(p, l_offset); 280 xdr_encode_hyper(p, l_len); 281} 282 283static int decode_nlm4_holder(struct xdr_stream *xdr, struct nlm_res *result) 284{ 285 struct nlm_lock *lock = &result->lock; 286 struct file_lock *fl = &lock->fl; 287 u64 l_offset, l_len; 288 u32 exclusive; 289 int error; 290 __be32 *p; 291 s32 end; 292 293 memset(lock, 0, sizeof(*lock)); 294 locks_init_lock(fl); 295 296 p = xdr_inline_decode(xdr, 4 + 4); 297 if (unlikely(p == NULL)) 298 goto out_overflow; 299 exclusive = be32_to_cpup(p++); 300 lock->svid = be32_to_cpup(p); 301 fl->fl_pid = (pid_t)lock->svid; 302 303 error = decode_netobj(xdr, &lock->oh); 304 if (unlikely(error)) 305 goto out; 306 307 p = xdr_inline_decode(xdr, 8 + 8); 308 if (unlikely(p == NULL)) 309 goto out_overflow; 310 311 fl->fl_flags = FL_POSIX; 312 fl->fl_type = exclusive != 0 ? F_WRLCK : F_RDLCK; 313 p = xdr_decode_hyper(p, &l_offset); 314 xdr_decode_hyper(p, &l_len); 315 end = l_offset + l_len - 1; 316 317 fl->fl_start = (loff_t)l_offset; 318 if (l_len == 0 || end < 0) 319 fl->fl_end = OFFSET_MAX; 320 else 321 fl->fl_end = (loff_t)end; 322 error = 0; 323out: 324 return error; 325out_overflow: 326 print_overflow_msg(__func__, xdr); 327 return -EIO; 328} 329 330/* 331 * string caller_name<LM_MAXSTRLEN>; 332 */ 333static void encode_caller_name(struct xdr_stream *xdr, const char *name) 334{ 335 /* NB: client-side does not set lock->len */ 336 u32 length = strlen(name); 337 __be32 *p; 338 339 BUG_ON(length > NLM_MAXSTRLEN); 340 p = xdr_reserve_space(xdr, 4 + length); 341 xdr_encode_opaque(p, name, length); 342} 343 344/* 345 * struct nlm4_lock { 346 * string caller_name<LM_MAXSTRLEN>; 347 * netobj fh; 348 * netobj oh; 349 * int32 svid; 350 * uint64 l_offset; 351 * uint64 l_len; 352 * }; 353 */ 354static void encode_nlm4_lock(struct xdr_stream *xdr, 355 const struct nlm_lock *lock) 356{ 357 u64 l_offset, l_len; 358 __be32 *p; 359 360 encode_caller_name(xdr, lock->caller); 361 encode_fh(xdr, &lock->fh); 362 encode_netobj(xdr, lock->oh.data, lock->oh.len); 363 364 p = xdr_reserve_space(xdr, 4 + 8 + 8); 365 *p++ = cpu_to_be32(lock->svid); 366 367 nlm4_compute_offsets(lock, &l_offset, &l_len); 368 p = xdr_encode_hyper(p, l_offset); 369 xdr_encode_hyper(p, l_len); 370} 371 372 373/* 374 * NLMv4 XDR encode functions 375 * 376 * NLMv4 argument types are defined in Appendix II of RFC 1813: 377 * "NFS Version 3 Protocol Specification" and Chapter 10 of X/Open's 378 * "Protocols for Interworking: XNFS, Version 3W". 379 */ 380 381/* 382 * struct nlm4_testargs { 383 * netobj cookie; 384 * bool exclusive; 385 * struct nlm4_lock alock; 386 * }; 387 */ 388static void nlm4_xdr_enc_testargs(struct rpc_rqst *req, 389 struct xdr_stream *xdr, 390 const struct nlm_args *args) 391{ 392 const struct nlm_lock *lock = &args->lock; 393 394 encode_cookie(xdr, &args->cookie); 395 encode_bool(xdr, lock->fl.fl_type == F_WRLCK); 396 encode_nlm4_lock(xdr, lock); 397} 398 399/* 400 * struct nlm4_lockargs { 401 * netobj cookie; 402 * bool block; 403 * bool exclusive; 404 * struct nlm4_lock alock; 405 * bool reclaim; 406 * int state; 407 * }; 408 */ 409static void nlm4_xdr_enc_lockargs(struct rpc_rqst *req, 410 struct xdr_stream *xdr, 411 const struct nlm_args *args) 412{ 413 const struct nlm_lock *lock = &args->lock; 414 415 encode_cookie(xdr, &args->cookie); 416 encode_bool(xdr, args->block); 417 encode_bool(xdr, lock->fl.fl_type == F_WRLCK); 418 encode_nlm4_lock(xdr, lock); 419 encode_bool(xdr, args->reclaim); 420 encode_int32(xdr, args->state); 421} 422 423/* 424 * struct nlm4_cancargs { 425 * netobj cookie; 426 * bool block; 427 * bool exclusive; 428 * struct nlm4_lock alock; 429 * }; 430 */ 431static void nlm4_xdr_enc_cancargs(struct rpc_rqst *req, 432 struct xdr_stream *xdr, 433 const struct nlm_args *args) 434{ 435 const struct nlm_lock *lock = &args->lock; 436 437 encode_cookie(xdr, &args->cookie); 438 encode_bool(xdr, args->block); 439 encode_bool(xdr, lock->fl.fl_type == F_WRLCK); 440 encode_nlm4_lock(xdr, lock); 441} 442 443/* 444 * struct nlm4_unlockargs { 445 * netobj cookie; 446 * struct nlm4_lock alock; 447 * }; 448 */ 449static void nlm4_xdr_enc_unlockargs(struct rpc_rqst *req, 450 struct xdr_stream *xdr, 451 const struct nlm_args *args) 452{ 453 const struct nlm_lock *lock = &args->lock; 454 455 encode_cookie(xdr, &args->cookie); 456 encode_nlm4_lock(xdr, lock); 457} 458 459/* 460 * struct nlm4_res { 461 * netobj cookie; 462 * nlm4_stat stat; 463 * }; 464 */ 465static void nlm4_xdr_enc_res(struct rpc_rqst *req, 466 struct xdr_stream *xdr, 467 const struct nlm_res *result) 468{ 469 encode_cookie(xdr, &result->cookie); 470 encode_nlm4_stat(xdr, result->status); 471} 472 473/* 474 * union nlm4_testrply switch (nlm4_stats stat) { 475 * case NLM4_DENIED: 476 * struct nlm4_holder holder; 477 * default: 478 * void; 479 * }; 480 * 481 * struct nlm4_testres { 482 * netobj cookie; 483 * nlm4_testrply test_stat; 484 * }; 485 */ 486static void nlm4_xdr_enc_testres(struct rpc_rqst *req, 487 struct xdr_stream *xdr, 488 const struct nlm_res *result) 489{ 490 encode_cookie(xdr, &result->cookie); 491 encode_nlm4_stat(xdr, result->status); 492 if (result->status == nlm_lck_denied) 493 encode_nlm4_holder(xdr, result); 494} 495 496 497/* 498 * NLMv4 XDR decode functions 499 * 500 * NLMv4 argument types are defined in Appendix II of RFC 1813: 501 * "NFS Version 3 Protocol Specification" and Chapter 10 of X/Open's 502 * "Protocols for Interworking: XNFS, Version 3W". 503 */ 504 505/* 506 * union nlm4_testrply switch (nlm4_stats stat) { 507 * case NLM4_DENIED: 508 * struct nlm4_holder holder; 509 * default: 510 * void; 511 * }; 512 * 513 * struct nlm4_testres { 514 * netobj cookie; 515 * nlm4_testrply test_stat; 516 * }; 517 */ 518static int decode_nlm4_testrply(struct xdr_stream *xdr, 519 struct nlm_res *result) 520{ 521 int error; 522 523 error = decode_nlm4_stat(xdr, &result->status); 524 if (unlikely(error)) 525 goto out; 526 if (result->status == nlm_lck_denied) 527 error = decode_nlm4_holder(xdr, result); 528out: 529 return error; 530} 531 532static int nlm4_xdr_dec_testres(struct rpc_rqst *req, 533 struct xdr_stream *xdr, 534 struct nlm_res *result) 535{ 536 int error; 537 538 error = decode_cookie(xdr, &result->cookie); 539 if (unlikely(error)) 540 goto out; 541 error = decode_nlm4_testrply(xdr, result); 542out: 543 return error; 544} 545 546/* 547 * struct nlm4_res { 548 * netobj cookie; 549 * nlm4_stat stat; 550 * }; 551 */ 552static int nlm4_xdr_dec_res(struct rpc_rqst *req, 553 struct xdr_stream *xdr, 554 struct nlm_res *result) 555{ 556 int error; 557 558 error = decode_cookie(xdr, &result->cookie); 559 if (unlikely(error)) 560 goto out; 561 error = decode_nlm4_stat(xdr, &result->status); 562out: 563 return error; 564} 565 566 567/* 568 * For NLM, a void procedure really returns nothing 569 */ 570#define nlm4_xdr_dec_norep NULL 571 572#define PROC(proc, argtype, restype) \ 573[NLMPROC_##proc] = { \ 574 .p_proc = NLMPROC_##proc, \ 575 .p_encode = (kxdreproc_t)nlm4_xdr_enc_##argtype, \ 576 .p_decode = (kxdrdproc_t)nlm4_xdr_dec_##restype, \ 577 .p_arglen = NLM4_##argtype##_sz, \ 578 .p_replen = NLM4_##restype##_sz, \ 579 .p_statidx = NLMPROC_##proc, \ 580 .p_name = #proc, \ 581 } 582 583static struct rpc_procinfo nlm4_procedures[] = { 584 PROC(TEST, testargs, testres), 585 PROC(LOCK, lockargs, res), 586 PROC(CANCEL, cancargs, res), 587 PROC(UNLOCK, unlockargs, res), 588 PROC(GRANTED, testargs, res), 589 PROC(TEST_MSG, testargs, norep), 590 PROC(LOCK_MSG, lockargs, norep), 591 PROC(CANCEL_MSG, cancargs, norep), 592 PROC(UNLOCK_MSG, unlockargs, norep), 593 PROC(GRANTED_MSG, testargs, norep), 594 PROC(TEST_RES, testres, norep), 595 PROC(LOCK_RES, res, norep), 596 PROC(CANCEL_RES, res, norep), 597 PROC(UNLOCK_RES, res, norep), 598 PROC(GRANTED_RES, res, norep), 599}; 600 601const struct rpc_version nlm_version4 = { 602 .number = 4, 603 .nrprocs = ARRAY_SIZE(nlm4_procedures), 604 .procs = nlm4_procedures, 605};