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

Configure Feed

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

at v2.6.35 589 lines 14 kB view raw
1/* 2 * linux/fs/lockd/xdr4.c 3 * 4 * XDR support for lockd and the lock client. 5 * 6 * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> 7 * Copyright (C) 1999, Trond Myklebust <trond.myklebust@fys.uio.no> 8 */ 9 10#include <linux/types.h> 11#include <linux/sched.h> 12#include <linux/nfs.h> 13 14#include <linux/sunrpc/xdr.h> 15#include <linux/sunrpc/clnt.h> 16#include <linux/sunrpc/svc.h> 17#include <linux/sunrpc/stats.h> 18#include <linux/lockd/lockd.h> 19 20#define NLMDBG_FACILITY NLMDBG_XDR 21 22static inline loff_t 23s64_to_loff_t(__s64 offset) 24{ 25 return (loff_t)offset; 26} 27 28 29static inline s64 30loff_t_to_s64(loff_t offset) 31{ 32 s64 res; 33 if (offset > NLM4_OFFSET_MAX) 34 res = NLM4_OFFSET_MAX; 35 else if (offset < -NLM4_OFFSET_MAX) 36 res = -NLM4_OFFSET_MAX; 37 else 38 res = offset; 39 return res; 40} 41 42/* 43 * XDR functions for basic NLM types 44 */ 45static __be32 * 46nlm4_decode_cookie(__be32 *p, struct nlm_cookie *c) 47{ 48 unsigned int len; 49 50 len = ntohl(*p++); 51 52 if(len==0) 53 { 54 c->len=4; 55 memset(c->data, 0, 4); /* hockeypux brain damage */ 56 } 57 else if(len<=NLM_MAXCOOKIELEN) 58 { 59 c->len=len; 60 memcpy(c->data, p, len); 61 p+=XDR_QUADLEN(len); 62 } 63 else 64 { 65 dprintk("lockd: bad cookie size %d (only cookies under " 66 "%d bytes are supported.)\n", 67 len, NLM_MAXCOOKIELEN); 68 return NULL; 69 } 70 return p; 71} 72 73static __be32 * 74nlm4_encode_cookie(__be32 *p, struct nlm_cookie *c) 75{ 76 *p++ = htonl(c->len); 77 memcpy(p, c->data, c->len); 78 p+=XDR_QUADLEN(c->len); 79 return p; 80} 81 82static __be32 * 83nlm4_decode_fh(__be32 *p, struct nfs_fh *f) 84{ 85 memset(f->data, 0, sizeof(f->data)); 86 f->size = ntohl(*p++); 87 if (f->size > NFS_MAXFHSIZE) { 88 dprintk("lockd: bad fhandle size %d (should be <=%d)\n", 89 f->size, NFS_MAXFHSIZE); 90 return NULL; 91 } 92 memcpy(f->data, p, f->size); 93 return p + XDR_QUADLEN(f->size); 94} 95 96static __be32 * 97nlm4_encode_fh(__be32 *p, struct nfs_fh *f) 98{ 99 *p++ = htonl(f->size); 100 if (f->size) p[XDR_QUADLEN(f->size)-1] = 0; /* don't leak anything */ 101 memcpy(p, f->data, f->size); 102 return p + XDR_QUADLEN(f->size); 103} 104 105/* 106 * Encode and decode owner handle 107 */ 108static __be32 * 109nlm4_decode_oh(__be32 *p, struct xdr_netobj *oh) 110{ 111 return xdr_decode_netobj(p, oh); 112} 113 114static __be32 * 115nlm4_encode_oh(__be32 *p, struct xdr_netobj *oh) 116{ 117 return xdr_encode_netobj(p, oh); 118} 119 120static __be32 * 121nlm4_decode_lock(__be32 *p, struct nlm_lock *lock) 122{ 123 struct file_lock *fl = &lock->fl; 124 __u64 len, start; 125 __s64 end; 126 127 if (!(p = xdr_decode_string_inplace(p, &lock->caller, 128 &lock->len, NLM_MAXSTRLEN)) 129 || !(p = nlm4_decode_fh(p, &lock->fh)) 130 || !(p = nlm4_decode_oh(p, &lock->oh))) 131 return NULL; 132 lock->svid = ntohl(*p++); 133 134 locks_init_lock(fl); 135 fl->fl_owner = current->files; 136 fl->fl_pid = (pid_t)lock->svid; 137 fl->fl_flags = FL_POSIX; 138 fl->fl_type = F_RDLCK; /* as good as anything else */ 139 p = xdr_decode_hyper(p, &start); 140 p = xdr_decode_hyper(p, &len); 141 end = start + len - 1; 142 143 fl->fl_start = s64_to_loff_t(start); 144 145 if (len == 0 || end < 0) 146 fl->fl_end = OFFSET_MAX; 147 else 148 fl->fl_end = s64_to_loff_t(end); 149 return p; 150} 151 152/* 153 * Encode a lock as part of an NLM call 154 */ 155static __be32 * 156nlm4_encode_lock(__be32 *p, struct nlm_lock *lock) 157{ 158 struct file_lock *fl = &lock->fl; 159 __s64 start, len; 160 161 if (!(p = xdr_encode_string(p, lock->caller)) 162 || !(p = nlm4_encode_fh(p, &lock->fh)) 163 || !(p = nlm4_encode_oh(p, &lock->oh))) 164 return NULL; 165 166 if (fl->fl_start > NLM4_OFFSET_MAX 167 || (fl->fl_end > NLM4_OFFSET_MAX && fl->fl_end != OFFSET_MAX)) 168 return NULL; 169 170 *p++ = htonl(lock->svid); 171 172 start = loff_t_to_s64(fl->fl_start); 173 if (fl->fl_end == OFFSET_MAX) 174 len = 0; 175 else 176 len = loff_t_to_s64(fl->fl_end - fl->fl_start + 1); 177 178 p = xdr_encode_hyper(p, start); 179 p = xdr_encode_hyper(p, len); 180 181 return p; 182} 183 184/* 185 * Encode result of a TEST/TEST_MSG call 186 */ 187static __be32 * 188nlm4_encode_testres(__be32 *p, struct nlm_res *resp) 189{ 190 s64 start, len; 191 192 dprintk("xdr: before encode_testres (p %p resp %p)\n", p, resp); 193 if (!(p = nlm4_encode_cookie(p, &resp->cookie))) 194 return NULL; 195 *p++ = resp->status; 196 197 if (resp->status == nlm_lck_denied) { 198 struct file_lock *fl = &resp->lock.fl; 199 200 *p++ = (fl->fl_type == F_RDLCK)? xdr_zero : xdr_one; 201 *p++ = htonl(resp->lock.svid); 202 203 /* Encode owner handle. */ 204 if (!(p = xdr_encode_netobj(p, &resp->lock.oh))) 205 return NULL; 206 207 start = loff_t_to_s64(fl->fl_start); 208 if (fl->fl_end == OFFSET_MAX) 209 len = 0; 210 else 211 len = loff_t_to_s64(fl->fl_end - fl->fl_start + 1); 212 213 p = xdr_encode_hyper(p, start); 214 p = xdr_encode_hyper(p, len); 215 dprintk("xdr: encode_testres (status %u pid %d type %d start %Ld end %Ld)\n", 216 resp->status, (int)resp->lock.svid, fl->fl_type, 217 (long long)fl->fl_start, (long long)fl->fl_end); 218 } 219 220 dprintk("xdr: after encode_testres (p %p resp %p)\n", p, resp); 221 return p; 222} 223 224 225/* 226 * First, the server side XDR functions 227 */ 228int 229nlm4svc_decode_testargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp) 230{ 231 u32 exclusive; 232 233 if (!(p = nlm4_decode_cookie(p, &argp->cookie))) 234 return 0; 235 236 exclusive = ntohl(*p++); 237 if (!(p = nlm4_decode_lock(p, &argp->lock))) 238 return 0; 239 if (exclusive) 240 argp->lock.fl.fl_type = F_WRLCK; 241 242 return xdr_argsize_check(rqstp, p); 243} 244 245int 246nlm4svc_encode_testres(struct svc_rqst *rqstp, __be32 *p, struct nlm_res *resp) 247{ 248 if (!(p = nlm4_encode_testres(p, resp))) 249 return 0; 250 return xdr_ressize_check(rqstp, p); 251} 252 253int 254nlm4svc_decode_lockargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp) 255{ 256 u32 exclusive; 257 258 if (!(p = nlm4_decode_cookie(p, &argp->cookie))) 259 return 0; 260 argp->block = ntohl(*p++); 261 exclusive = ntohl(*p++); 262 if (!(p = nlm4_decode_lock(p, &argp->lock))) 263 return 0; 264 if (exclusive) 265 argp->lock.fl.fl_type = F_WRLCK; 266 argp->reclaim = ntohl(*p++); 267 argp->state = ntohl(*p++); 268 argp->monitor = 1; /* monitor client by default */ 269 270 return xdr_argsize_check(rqstp, p); 271} 272 273int 274nlm4svc_decode_cancargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp) 275{ 276 u32 exclusive; 277 278 if (!(p = nlm4_decode_cookie(p, &argp->cookie))) 279 return 0; 280 argp->block = ntohl(*p++); 281 exclusive = ntohl(*p++); 282 if (!(p = nlm4_decode_lock(p, &argp->lock))) 283 return 0; 284 if (exclusive) 285 argp->lock.fl.fl_type = F_WRLCK; 286 return xdr_argsize_check(rqstp, p); 287} 288 289int 290nlm4svc_decode_unlockargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp) 291{ 292 if (!(p = nlm4_decode_cookie(p, &argp->cookie)) 293 || !(p = nlm4_decode_lock(p, &argp->lock))) 294 return 0; 295 argp->lock.fl.fl_type = F_UNLCK; 296 return xdr_argsize_check(rqstp, p); 297} 298 299int 300nlm4svc_decode_shareargs(struct svc_rqst *rqstp, __be32 *p, nlm_args *argp) 301{ 302 struct nlm_lock *lock = &argp->lock; 303 304 memset(lock, 0, sizeof(*lock)); 305 locks_init_lock(&lock->fl); 306 lock->svid = ~(u32) 0; 307 lock->fl.fl_pid = (pid_t)lock->svid; 308 309 if (!(p = nlm4_decode_cookie(p, &argp->cookie)) 310 || !(p = xdr_decode_string_inplace(p, &lock->caller, 311 &lock->len, NLM_MAXSTRLEN)) 312 || !(p = nlm4_decode_fh(p, &lock->fh)) 313 || !(p = nlm4_decode_oh(p, &lock->oh))) 314 return 0; 315 argp->fsm_mode = ntohl(*p++); 316 argp->fsm_access = ntohl(*p++); 317 return xdr_argsize_check(rqstp, p); 318} 319 320int 321nlm4svc_encode_shareres(struct svc_rqst *rqstp, __be32 *p, struct nlm_res *resp) 322{ 323 if (!(p = nlm4_encode_cookie(p, &resp->cookie))) 324 return 0; 325 *p++ = resp->status; 326 *p++ = xdr_zero; /* sequence argument */ 327 return xdr_ressize_check(rqstp, p); 328} 329 330int 331nlm4svc_encode_res(struct svc_rqst *rqstp, __be32 *p, struct nlm_res *resp) 332{ 333 if (!(p = nlm4_encode_cookie(p, &resp->cookie))) 334 return 0; 335 *p++ = resp->status; 336 return xdr_ressize_check(rqstp, p); 337} 338 339int 340nlm4svc_decode_notify(struct svc_rqst *rqstp, __be32 *p, struct nlm_args *argp) 341{ 342 struct nlm_lock *lock = &argp->lock; 343 344 if (!(p = xdr_decode_string_inplace(p, &lock->caller, 345 &lock->len, NLM_MAXSTRLEN))) 346 return 0; 347 argp->state = ntohl(*p++); 348 return xdr_argsize_check(rqstp, p); 349} 350 351int 352nlm4svc_decode_reboot(struct svc_rqst *rqstp, __be32 *p, struct nlm_reboot *argp) 353{ 354 if (!(p = xdr_decode_string_inplace(p, &argp->mon, &argp->len, SM_MAXSTRLEN))) 355 return 0; 356 argp->state = ntohl(*p++); 357 memcpy(&argp->priv.data, p, sizeof(argp->priv.data)); 358 p += XDR_QUADLEN(SM_PRIV_SIZE); 359 return xdr_argsize_check(rqstp, p); 360} 361 362int 363nlm4svc_decode_res(struct svc_rqst *rqstp, __be32 *p, struct nlm_res *resp) 364{ 365 if (!(p = nlm4_decode_cookie(p, &resp->cookie))) 366 return 0; 367 resp->status = *p++; 368 return xdr_argsize_check(rqstp, p); 369} 370 371int 372nlm4svc_decode_void(struct svc_rqst *rqstp, __be32 *p, void *dummy) 373{ 374 return xdr_argsize_check(rqstp, p); 375} 376 377int 378nlm4svc_encode_void(struct svc_rqst *rqstp, __be32 *p, void *dummy) 379{ 380 return xdr_ressize_check(rqstp, p); 381} 382 383/* 384 * Now, the client side XDR functions 385 */ 386#ifdef NLMCLNT_SUPPORT_SHARES 387static int 388nlm4clt_decode_void(struct rpc_rqst *req, __be32 *p, void *ptr) 389{ 390 return 0; 391} 392#endif 393 394static int 395nlm4clt_encode_testargs(struct rpc_rqst *req, __be32 *p, nlm_args *argp) 396{ 397 struct nlm_lock *lock = &argp->lock; 398 399 if (!(p = nlm4_encode_cookie(p, &argp->cookie))) 400 return -EIO; 401 *p++ = (lock->fl.fl_type == F_WRLCK)? xdr_one : xdr_zero; 402 if (!(p = nlm4_encode_lock(p, lock))) 403 return -EIO; 404 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 405 return 0; 406} 407 408static int 409nlm4clt_decode_testres(struct rpc_rqst *req, __be32 *p, struct nlm_res *resp) 410{ 411 if (!(p = nlm4_decode_cookie(p, &resp->cookie))) 412 return -EIO; 413 resp->status = *p++; 414 if (resp->status == nlm_lck_denied) { 415 struct file_lock *fl = &resp->lock.fl; 416 u32 excl; 417 __u64 start, len; 418 __s64 end; 419 420 memset(&resp->lock, 0, sizeof(resp->lock)); 421 locks_init_lock(fl); 422 excl = ntohl(*p++); 423 resp->lock.svid = ntohl(*p++); 424 fl->fl_pid = (pid_t)resp->lock.svid; 425 if (!(p = nlm4_decode_oh(p, &resp->lock.oh))) 426 return -EIO; 427 428 fl->fl_flags = FL_POSIX; 429 fl->fl_type = excl? F_WRLCK : F_RDLCK; 430 p = xdr_decode_hyper(p, &start); 431 p = xdr_decode_hyper(p, &len); 432 end = start + len - 1; 433 434 fl->fl_start = s64_to_loff_t(start); 435 if (len == 0 || end < 0) 436 fl->fl_end = OFFSET_MAX; 437 else 438 fl->fl_end = s64_to_loff_t(end); 439 } 440 return 0; 441} 442 443 444static int 445nlm4clt_encode_lockargs(struct rpc_rqst *req, __be32 *p, nlm_args *argp) 446{ 447 struct nlm_lock *lock = &argp->lock; 448 449 if (!(p = nlm4_encode_cookie(p, &argp->cookie))) 450 return -EIO; 451 *p++ = argp->block? xdr_one : xdr_zero; 452 *p++ = (lock->fl.fl_type == F_WRLCK)? xdr_one : xdr_zero; 453 if (!(p = nlm4_encode_lock(p, lock))) 454 return -EIO; 455 *p++ = argp->reclaim? xdr_one : xdr_zero; 456 *p++ = htonl(argp->state); 457 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 458 return 0; 459} 460 461static int 462nlm4clt_encode_cancargs(struct rpc_rqst *req, __be32 *p, nlm_args *argp) 463{ 464 struct nlm_lock *lock = &argp->lock; 465 466 if (!(p = nlm4_encode_cookie(p, &argp->cookie))) 467 return -EIO; 468 *p++ = argp->block? xdr_one : xdr_zero; 469 *p++ = (lock->fl.fl_type == F_WRLCK)? xdr_one : xdr_zero; 470 if (!(p = nlm4_encode_lock(p, lock))) 471 return -EIO; 472 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 473 return 0; 474} 475 476static int 477nlm4clt_encode_unlockargs(struct rpc_rqst *req, __be32 *p, nlm_args *argp) 478{ 479 struct nlm_lock *lock = &argp->lock; 480 481 if (!(p = nlm4_encode_cookie(p, &argp->cookie))) 482 return -EIO; 483 if (!(p = nlm4_encode_lock(p, lock))) 484 return -EIO; 485 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 486 return 0; 487} 488 489static int 490nlm4clt_encode_res(struct rpc_rqst *req, __be32 *p, struct nlm_res *resp) 491{ 492 if (!(p = nlm4_encode_cookie(p, &resp->cookie))) 493 return -EIO; 494 *p++ = resp->status; 495 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 496 return 0; 497} 498 499static int 500nlm4clt_encode_testres(struct rpc_rqst *req, __be32 *p, struct nlm_res *resp) 501{ 502 if (!(p = nlm4_encode_testres(p, resp))) 503 return -EIO; 504 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 505 return 0; 506} 507 508static int 509nlm4clt_decode_res(struct rpc_rqst *req, __be32 *p, struct nlm_res *resp) 510{ 511 if (!(p = nlm4_decode_cookie(p, &resp->cookie))) 512 return -EIO; 513 resp->status = *p++; 514 return 0; 515} 516 517#if (NLMCLNT_OHSIZE > XDR_MAX_NETOBJ) 518# error "NLM host name cannot be larger than XDR_MAX_NETOBJ!" 519#endif 520 521#if (NLMCLNT_OHSIZE > NLM_MAXSTRLEN) 522# error "NLM host name cannot be larger than NLM's maximum string length!" 523#endif 524 525/* 526 * Buffer requirements for NLM 527 */ 528#define NLM4_void_sz 0 529#define NLM4_cookie_sz 1+XDR_QUADLEN(NLM_MAXCOOKIELEN) 530#define NLM4_caller_sz 1+XDR_QUADLEN(NLMCLNT_OHSIZE) 531#define NLM4_owner_sz 1+XDR_QUADLEN(NLMCLNT_OHSIZE) 532#define NLM4_fhandle_sz 1+XDR_QUADLEN(NFS3_FHSIZE) 533#define NLM4_lock_sz 5+NLM4_caller_sz+NLM4_owner_sz+NLM4_fhandle_sz 534#define NLM4_holder_sz 6+NLM4_owner_sz 535 536#define NLM4_testargs_sz NLM4_cookie_sz+1+NLM4_lock_sz 537#define NLM4_lockargs_sz NLM4_cookie_sz+4+NLM4_lock_sz 538#define NLM4_cancargs_sz NLM4_cookie_sz+2+NLM4_lock_sz 539#define NLM4_unlockargs_sz NLM4_cookie_sz+NLM4_lock_sz 540 541#define NLM4_testres_sz NLM4_cookie_sz+1+NLM4_holder_sz 542#define NLM4_res_sz NLM4_cookie_sz+1 543#define NLM4_norep_sz 0 544 545/* 546 * For NLM, a void procedure really returns nothing 547 */ 548#define nlm4clt_decode_norep NULL 549 550#define PROC(proc, argtype, restype) \ 551[NLMPROC_##proc] = { \ 552 .p_proc = NLMPROC_##proc, \ 553 .p_encode = (kxdrproc_t) nlm4clt_encode_##argtype, \ 554 .p_decode = (kxdrproc_t) nlm4clt_decode_##restype, \ 555 .p_arglen = NLM4_##argtype##_sz, \ 556 .p_replen = NLM4_##restype##_sz, \ 557 .p_statidx = NLMPROC_##proc, \ 558 .p_name = #proc, \ 559 } 560 561static struct rpc_procinfo nlm4_procedures[] = { 562 PROC(TEST, testargs, testres), 563 PROC(LOCK, lockargs, res), 564 PROC(CANCEL, cancargs, res), 565 PROC(UNLOCK, unlockargs, res), 566 PROC(GRANTED, testargs, res), 567 PROC(TEST_MSG, testargs, norep), 568 PROC(LOCK_MSG, lockargs, norep), 569 PROC(CANCEL_MSG, cancargs, norep), 570 PROC(UNLOCK_MSG, unlockargs, norep), 571 PROC(GRANTED_MSG, testargs, norep), 572 PROC(TEST_RES, testres, norep), 573 PROC(LOCK_RES, res, norep), 574 PROC(CANCEL_RES, res, norep), 575 PROC(UNLOCK_RES, res, norep), 576 PROC(GRANTED_RES, res, norep), 577#ifdef NLMCLNT_SUPPORT_SHARES 578 PROC(SHARE, shareargs, shareres), 579 PROC(UNSHARE, shareargs, shareres), 580 PROC(NM_LOCK, lockargs, res), 581 PROC(FREE_ALL, notify, void), 582#endif 583}; 584 585struct rpc_version nlm_version4 = { 586 .number = 4, 587 .nrprocs = 24, 588 .procs = nlm4_procedures, 589};