1 /* 2 * linux/fs/nfsd/nfs4callback.c 3 * 4 * Copyright (c) 2001 The Regents of the University of Michigan. 5 * All rights reserved. 6 * 7 * Kendrick Smith <kmsmith@umich.edu> 8 * Andy Adamson <andros@umich.edu> 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. Neither the name of the University nor the names of its 20 * contributors may be used to endorse or promote products derived 21 * from this software without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 24 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 25 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 26 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 30 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34 */ 35 36 #include <linux/module.h> 37 #include <linux/list.h> 38 #include <linux/inet.h> 39 #include <linux/errno.h> 40 #include <linux/delay.h> 41 #include <linux/sched.h> 42 #include <linux/kthread.h> 43 #include <linux/sunrpc/xdr.h> 44 #include <linux/sunrpc/svc.h> 45 #include <linux/sunrpc/clnt.h> 46 #include <linux/sunrpc/svcsock.h> 47 #include <linux/nfsd/nfsd.h> 48 #include <linux/nfsd/state.h> 49 #include <linux/sunrpc/sched.h> 50 #include <linux/nfs4.h> 51 #include <linux/sunrpc/xprtsock.h> 52 53 #define NFSDDBG_FACILITY NFSDDBG_PROC 54 55 #define NFSPROC4_CB_NULL 0 56 #define NFSPROC4_CB_COMPOUND 1 57 #define NFS4_STATEID_SIZE 16 58 59 /* Index of predefined Linux callback client operations */ 60 61 enum { 62 NFSPROC4_CLNT_CB_NULL = 0, 63 NFSPROC4_CLNT_CB_RECALL, 64 NFSPROC4_CLNT_CB_SEQUENCE, 65 }; 66 67 enum nfs_cb_opnum4 { 68 OP_CB_RECALL = 4, 69 OP_CB_SEQUENCE = 11, 70 }; 71 72 #define NFS4_MAXTAGLEN 20 73 74 #define NFS4_enc_cb_null_sz 0 75 #define NFS4_dec_cb_null_sz 0 76 #define cb_compound_enc_hdr_sz 4 77 #define cb_compound_dec_hdr_sz (3 + (NFS4_MAXTAGLEN >> 2)) 78 #define sessionid_sz (NFS4_MAX_SESSIONID_LEN >> 2) 79 #define cb_sequence_enc_sz (sessionid_sz + 4 + \ 80 1 /* no referring calls list yet */) 81 #define cb_sequence_dec_sz (op_dec_sz + sessionid_sz + 4) 82 83 #define op_enc_sz 1 84 #define op_dec_sz 2 85 #define enc_nfs4_fh_sz (1 + (NFS4_FHSIZE >> 2)) 86 #define enc_stateid_sz (NFS4_STATEID_SIZE >> 2) 87 #define NFS4_enc_cb_recall_sz (cb_compound_enc_hdr_sz + \ 88 cb_sequence_enc_sz + \ 89 1 + enc_stateid_sz + \ 90 enc_nfs4_fh_sz) 91 92 #define NFS4_dec_cb_recall_sz (cb_compound_dec_hdr_sz + \ 93 cb_sequence_dec_sz + \ 94 op_dec_sz) 95 96 struct nfs4_rpc_args { 97 void *args_op; 98 struct nfsd4_cb_sequence args_seq; 99 }; 100 101 /* 102 * Generic encode routines from fs/nfs/nfs4xdr.c 103 */ 104 static inline __be32 * 105 xdr_writemem(__be32 *p, const void *ptr, int nbytes) 106 { 107 int tmp = XDR_QUADLEN(nbytes); 108 if (!tmp) 109 return p; 110 p[tmp-1] = 0; 111 memcpy(p, ptr, nbytes); 112 return p + tmp; 113 } 114 115 #define WRITE32(n) *p++ = htonl(n) 116 #define WRITEMEM(ptr,nbytes) do { \ 117 p = xdr_writemem(p, ptr, nbytes); \ 118 } while (0) 119 #define RESERVE_SPACE(nbytes) do { \ 120 p = xdr_reserve_space(xdr, nbytes); \ 121 if (!p) dprintk("NFSD: RESERVE_SPACE(%d) failed in function %s\n", (int) (nbytes), __func__); \ 122 BUG_ON(!p); \ 123 } while (0) 124 125 /* 126 * Generic decode routines from fs/nfs/nfs4xdr.c 127 */ 128 #define DECODE_TAIL \ 129 status = 0; \ 130 out: \ 131 return status; \ 132 xdr_error: \ 133 dprintk("NFSD: xdr error! (%s:%d)\n", __FILE__, __LINE__); \ 134 status = -EIO; \ 135 goto out 136 137 #define READ32(x) (x) = ntohl(*p++) 138 #define READ64(x) do { \ 139 (x) = (u64)ntohl(*p++) << 32; \ 140 (x) |= ntohl(*p++); \ 141 } while (0) 142 #define READTIME(x) do { \ 143 p++; \ 144 (x.tv_sec) = ntohl(*p++); \ 145 (x.tv_nsec) = ntohl(*p++); \ 146 } while (0) 147 #define READ_BUF(nbytes) do { \ 148 p = xdr_inline_decode(xdr, nbytes); \ 149 if (!p) { \ 150 dprintk("NFSD: %s: reply buffer overflowed in line %d.\n", \ 151 __func__, __LINE__); \ 152 return -EIO; \ 153 } \ 154 } while (0) 155 156 struct nfs4_cb_compound_hdr { 157 /* args */ 158 u32 ident; /* minorversion 0 only */ 159 u32 nops; 160 __be32 *nops_p; 161 u32 minorversion; 162 /* res */ 163 int status; 164 u32 taglen; 165 char *tag; 166 }; 167 168 static struct { 169 int stat; 170 int errno; 171 } nfs_cb_errtbl[] = { 172 { NFS4_OK, 0 }, 173 { NFS4ERR_PERM, EPERM }, 174 { NFS4ERR_NOENT, ENOENT }, 175 { NFS4ERR_IO, EIO }, 176 { NFS4ERR_NXIO, ENXIO }, 177 { NFS4ERR_ACCESS, EACCES }, 178 { NFS4ERR_EXIST, EEXIST }, 179 { NFS4ERR_XDEV, EXDEV }, 180 { NFS4ERR_NOTDIR, ENOTDIR }, 181 { NFS4ERR_ISDIR, EISDIR }, 182 { NFS4ERR_INVAL, EINVAL }, 183 { NFS4ERR_FBIG, EFBIG }, 184 { NFS4ERR_NOSPC, ENOSPC }, 185 { NFS4ERR_ROFS, EROFS }, 186 { NFS4ERR_MLINK, EMLINK }, 187 { NFS4ERR_NAMETOOLONG, ENAMETOOLONG }, 188 { NFS4ERR_NOTEMPTY, ENOTEMPTY }, 189 { NFS4ERR_DQUOT, EDQUOT }, 190 { NFS4ERR_STALE, ESTALE }, 191 { NFS4ERR_BADHANDLE, EBADHANDLE }, 192 { NFS4ERR_BAD_COOKIE, EBADCOOKIE }, 193 { NFS4ERR_NOTSUPP, ENOTSUPP }, 194 { NFS4ERR_TOOSMALL, ETOOSMALL }, 195 { NFS4ERR_SERVERFAULT, ESERVERFAULT }, 196 { NFS4ERR_BADTYPE, EBADTYPE }, 197 { NFS4ERR_LOCKED, EAGAIN }, 198 { NFS4ERR_RESOURCE, EREMOTEIO }, 199 { NFS4ERR_SYMLINK, ELOOP }, 200 { NFS4ERR_OP_ILLEGAL, EOPNOTSUPP }, 201 { NFS4ERR_DEADLOCK, EDEADLK }, 202 { -1, EIO } 203 }; 204 205 static int 206 nfs_cb_stat_to_errno(int stat) 207 { 208 int i; 209 for (i = 0; nfs_cb_errtbl[i].stat != -1; i++) { 210 if (nfs_cb_errtbl[i].stat == stat) 211 return nfs_cb_errtbl[i].errno; 212 } 213 /* If we cannot translate the error, the recovery routines should 214 * handle it. 215 * Note: remaining NFSv4 error codes have values > 10000, so should 216 * not conflict with native Linux error codes. 217 */ 218 return stat; 219 } 220 221 /* 222 * XDR encode 223 */ 224 225 static void 226 encode_cb_compound_hdr(struct xdr_stream *xdr, struct nfs4_cb_compound_hdr *hdr) 227 { 228 __be32 * p; 229 230 RESERVE_SPACE(16); 231 WRITE32(0); /* tag length is always 0 */ 232 WRITE32(hdr->minorversion); 233 WRITE32(hdr->ident); 234 hdr->nops_p = p; 235 WRITE32(hdr->nops); 236 } 237 238 static void encode_cb_nops(struct nfs4_cb_compound_hdr *hdr) 239 { 240 *hdr->nops_p = htonl(hdr->nops); 241 } 242 243 static void 244 encode_cb_recall(struct xdr_stream *xdr, struct nfs4_delegation *dp, 245 struct nfs4_cb_compound_hdr *hdr) 246 { 247 __be32 *p; 248 int len = dp->dl_fh.fh_size; 249 250 RESERVE_SPACE(12+sizeof(dp->dl_stateid) + len); 251 WRITE32(OP_CB_RECALL); 252 WRITE32(dp->dl_stateid.si_generation); 253 WRITEMEM(&dp->dl_stateid.si_opaque, sizeof(stateid_opaque_t)); 254 WRITE32(0); /* truncate optimization not implemented */ 255 WRITE32(len); 256 WRITEMEM(&dp->dl_fh.fh_base, len); 257 hdr->nops++; 258 } 259 260 static void 261 encode_cb_sequence(struct xdr_stream *xdr, struct nfsd4_cb_sequence *args, 262 struct nfs4_cb_compound_hdr *hdr) 263 { 264 __be32 *p; 265 266 if (hdr->minorversion == 0) 267 return; 268 269 RESERVE_SPACE(1 + NFS4_MAX_SESSIONID_LEN + 20); 270 271 WRITE32(OP_CB_SEQUENCE); 272 WRITEMEM(args->cbs_clp->cl_sessionid.data, NFS4_MAX_SESSIONID_LEN); 273 WRITE32(args->cbs_clp->cl_cb_seq_nr); 274 WRITE32(0); /* slotid, always 0 */ 275 WRITE32(0); /* highest slotid always 0 */ 276 WRITE32(0); /* cachethis always 0 */ 277 WRITE32(0); /* FIXME: support referring_call_lists */ 278 hdr->nops++; 279 } 280 281 static int 282 nfs4_xdr_enc_cb_null(struct rpc_rqst *req, __be32 *p) 283 { 284 struct xdr_stream xdrs, *xdr = &xdrs; 285 286 xdr_init_encode(&xdrs, &req->rq_snd_buf, p); 287 RESERVE_SPACE(0); 288 return 0; 289 } 290 291 static int 292 nfs4_xdr_enc_cb_recall(struct rpc_rqst *req, __be32 *p, 293 struct nfs4_rpc_args *rpc_args) 294 { 295 struct xdr_stream xdr; 296 struct nfs4_delegation *args = rpc_args->args_op; 297 struct nfs4_cb_compound_hdr hdr = { 298 .ident = args->dl_ident, 299 .minorversion = rpc_args->args_seq.cbs_minorversion, 300 }; 301 302 xdr_init_encode(&xdr, &req->rq_snd_buf, p); 303 encode_cb_compound_hdr(&xdr, &hdr); 304 encode_cb_sequence(&xdr, &rpc_args->args_seq, &hdr); 305 encode_cb_recall(&xdr, args, &hdr); 306 encode_cb_nops(&hdr); 307 return 0; 308 } 309 310 311 static int 312 decode_cb_compound_hdr(struct xdr_stream *xdr, struct nfs4_cb_compound_hdr *hdr){ 313 __be32 *p; 314 315 READ_BUF(8); 316 READ32(hdr->status); 317 READ32(hdr->taglen); 318 READ_BUF(hdr->taglen + 4); 319 hdr->tag = (char *)p; 320 p += XDR_QUADLEN(hdr->taglen); 321 READ32(hdr->nops); 322 return 0; 323 } 324 325 static int 326 decode_cb_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected) 327 { 328 __be32 *p; 329 u32 op; 330 int32_t nfserr; 331 332 READ_BUF(8); 333 READ32(op); 334 if (op != expected) { 335 dprintk("NFSD: decode_cb_op_hdr: Callback server returned " 336 " operation %d but we issued a request for %d\n", 337 op, expected); 338 return -EIO; 339 } 340 READ32(nfserr); 341 if (nfserr != NFS_OK) 342 return -nfs_cb_stat_to_errno(nfserr); 343 return 0; 344 } 345 346 /* 347 * Our current back channel implmentation supports a single backchannel 348 * with a single slot. 349 */ 350 static int 351 decode_cb_sequence(struct xdr_stream *xdr, struct nfsd4_cb_sequence *res, 352 struct rpc_rqst *rqstp) 353 { 354 struct nfs4_sessionid id; 355 int status; 356 u32 dummy; 357 __be32 *p; 358 359 if (res->cbs_minorversion == 0) 360 return 0; 361 362 status = decode_cb_op_hdr(xdr, OP_CB_SEQUENCE); 363 if (status) 364 return status; 365 366 /* 367 * If the server returns different values for sessionID, slotID or 368 * sequence number, the server is looney tunes. 369 */ 370 status = -ESERVERFAULT; 371 372 READ_BUF(NFS4_MAX_SESSIONID_LEN + 16); 373 memcpy(id.data, p, NFS4_MAX_SESSIONID_LEN); 374 p += XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN); 375 if (memcmp(id.data, res->cbs_clp->cl_sessionid.data, 376 NFS4_MAX_SESSIONID_LEN)) { 377 dprintk("%s Invalid session id\n", __func__); 378 goto out; 379 } 380 READ32(dummy); 381 if (dummy != res->cbs_clp->cl_cb_seq_nr) { 382 dprintk("%s Invalid sequence number\n", __func__); 383 goto out; 384 } 385 READ32(dummy); /* slotid must be 0 */ 386 if (dummy != 0) { 387 dprintk("%s Invalid slotid\n", __func__); 388 goto out; 389 } 390 /* FIXME: process highest slotid and target highest slotid */ 391 status = 0; 392 out: 393 return status; 394 } 395 396 397 static int 398 nfs4_xdr_dec_cb_null(struct rpc_rqst *req, __be32 *p) 399 { 400 return 0; 401 } 402 403 static int 404 nfs4_xdr_dec_cb_recall(struct rpc_rqst *rqstp, __be32 *p, 405 struct nfsd4_cb_sequence *seq) 406 { 407 struct xdr_stream xdr; 408 struct nfs4_cb_compound_hdr hdr; 409 int status; 410 411 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p); 412 status = decode_cb_compound_hdr(&xdr, &hdr); 413 if (status) 414 goto out; 415 if (seq) { 416 status = decode_cb_sequence(&xdr, seq, rqstp); 417 if (status) 418 goto out; 419 } 420 status = decode_cb_op_hdr(&xdr, OP_CB_RECALL); 421 out: 422 return status; 423 } 424 425 /* 426 * RPC procedure tables 427 */ 428 #define PROC(proc, call, argtype, restype) \ 429 [NFSPROC4_CLNT_##proc] = { \ 430 .p_proc = NFSPROC4_CB_##call, \ 431 .p_encode = (kxdrproc_t) nfs4_xdr_##argtype, \ 432 .p_decode = (kxdrproc_t) nfs4_xdr_##restype, \ 433 .p_arglen = NFS4_##argtype##_sz, \ 434 .p_replen = NFS4_##restype##_sz, \ 435 .p_statidx = NFSPROC4_CB_##call, \ 436 .p_name = #proc, \ 437 } 438 439 static struct rpc_procinfo nfs4_cb_procedures[] = { 440 PROC(CB_NULL, NULL, enc_cb_null, dec_cb_null), 441 PROC(CB_RECALL, COMPOUND, enc_cb_recall, dec_cb_recall), 442 }; 443 444 static struct rpc_version nfs_cb_version4 = { 445 .number = 1, 446 .nrprocs = ARRAY_SIZE(nfs4_cb_procedures), 447 .procs = nfs4_cb_procedures 448 }; 449 450 static struct rpc_version * nfs_cb_version[] = { 451 NULL, 452 &nfs_cb_version4, 453 }; 454 455 static struct rpc_program cb_program; 456 457 static struct rpc_stat cb_stats = { 458 .program = &cb_program 459 }; 460 461 #define NFS4_CALLBACK 0x40000000 462 static struct rpc_program cb_program = { 463 .name = "nfs4_cb", 464 .number = NFS4_CALLBACK, 465 .nrvers = ARRAY_SIZE(nfs_cb_version), 466 .version = nfs_cb_version, 467 .stats = &cb_stats, 468 .pipe_dir_name = "/nfsd4_cb", 469 }; 470 471 static int max_cb_time(void) 472 { 473 return max(NFSD_LEASE_TIME/10, (time_t)1) * HZ; 474 } 475 476 /* Reference counting, callback cleanup, etc., all look racy as heck. 477 * And why is cb_set an atomic? */ 478 479 int setup_callback_client(struct nfs4_client *clp) 480 { 481 struct nfs4_cb_conn *cb = &clp->cl_cb_conn; 482 struct rpc_timeout timeparms = { 483 .to_initval = max_cb_time(), 484 .to_retries = 0, 485 }; 486 struct rpc_create_args args = { 487 .protocol = XPRT_TRANSPORT_TCP, 488 .address = (struct sockaddr *) &cb->cb_addr, 489 .addrsize = cb->cb_addrlen, 490 .timeout = &timeparms, 491 .program = &cb_program, 492 .prognumber = cb->cb_prog, 493 .version = nfs_cb_version[1]->number, 494 .authflavor = clp->cl_flavor, 495 .flags = (RPC_CLNT_CREATE_NOPING | RPC_CLNT_CREATE_QUIET), 496 .client_name = clp->cl_principal, 497 }; 498 struct rpc_clnt *client; 499 500 if (!clp->cl_principal && (clp->cl_flavor >= RPC_AUTH_GSS_KRB5)) 501 return -EINVAL; 502 if (cb->cb_minorversion) { 503 args.bc_xprt = clp->cl_cb_xprt; 504 args.protocol = XPRT_TRANSPORT_BC_TCP; 505 } 506 /* Create RPC client */ 507 client = rpc_create(&args); 508 if (IS_ERR(client)) { 509 dprintk("NFSD: couldn't create callback client: %ld\n", 510 PTR_ERR(client)); 511 return PTR_ERR(client); 512 } 513 cb->cb_client = client; 514 return 0; 515 516 } 517 518 static void warn_no_callback_path(struct nfs4_client *clp, int reason) 519 { 520 dprintk("NFSD: warning: no callback path to client %.*s: error %d\n", 521 (int)clp->cl_name.len, clp->cl_name.data, reason); 522 } 523 524 static void nfsd4_cb_probe_done(struct rpc_task *task, void *calldata) 525 { 526 struct nfs4_client *clp = calldata; 527 528 if (task->tk_status) 529 warn_no_callback_path(clp, task->tk_status); 530 else 531 atomic_set(&clp->cl_cb_conn.cb_set, 1); 532 put_nfs4_client(clp); 533 } 534 535 static const struct rpc_call_ops nfsd4_cb_probe_ops = { 536 .rpc_call_done = nfsd4_cb_probe_done, 537 }; 538 539 static struct rpc_cred *callback_cred; 540 541 int set_callback_cred(void) 542 { 543 callback_cred = rpc_lookup_machine_cred(); 544 if (!callback_cred) 545 return -ENOMEM; 546 return 0; 547 } 548 549 550 void do_probe_callback(struct nfs4_client *clp) 551 { 552 struct nfs4_cb_conn *cb = &clp->cl_cb_conn; 553 struct rpc_message msg = { 554 .rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL], 555 .rpc_argp = clp, 556 .rpc_cred = callback_cred 557 }; 558 int status; 559 560 status = rpc_call_async(cb->cb_client, &msg, RPC_TASK_SOFT, 561 &nfsd4_cb_probe_ops, (void *)clp); 562 if (status) { 563 warn_no_callback_path(clp, status); 564 put_nfs4_client(clp); 565 } 566 } 567 568 /* 569 * Set up the callback client and put a NFSPROC4_CB_NULL on the wire... 570 */ 571 void 572 nfsd4_probe_callback(struct nfs4_client *clp) 573 { 574 int status; 575 576 BUG_ON(atomic_read(&clp->cl_cb_conn.cb_set)); 577 578 status = setup_callback_client(clp); 579 if (status) { 580 warn_no_callback_path(clp, status); 581 return; 582 } 583 584 /* the task holds a reference to the nfs4_client struct */ 585 atomic_inc(&clp->cl_count); 586 587 do_probe_callback(clp); 588 } 589 590 /* 591 * There's currently a single callback channel slot. 592 * If the slot is available, then mark it busy. Otherwise, set the 593 * thread for sleeping on the callback RPC wait queue. 594 */ 595 static int nfsd41_cb_setup_sequence(struct nfs4_client *clp, 596 struct rpc_task *task) 597 { 598 struct nfs4_rpc_args *args = task->tk_msg.rpc_argp; 599 u32 *ptr = (u32 *)clp->cl_sessionid.data; 600 int status = 0; 601 602 dprintk("%s: %u:%u:%u:%u\n", __func__, 603 ptr[0], ptr[1], ptr[2], ptr[3]); 604 605 if (test_and_set_bit(0, &clp->cl_cb_slot_busy) != 0) { 606 rpc_sleep_on(&clp->cl_cb_waitq, task, NULL); 607 dprintk("%s slot is busy\n", __func__); 608 status = -EAGAIN; 609 goto out; 610 } 611 612 /* 613 * We'll need the clp during XDR encoding and decoding, 614 * and the sequence during decoding to verify the reply 615 */ 616 args->args_seq.cbs_clp = clp; 617 task->tk_msg.rpc_resp = &args->args_seq; 618 619 out: 620 dprintk("%s status=%d\n", __func__, status); 621 return status; 622 } 623 624 /* 625 * TODO: cb_sequence should support referring call lists, cachethis, multiple 626 * slots, and mark callback channel down on communication errors. 627 */ 628 static void nfsd4_cb_prepare(struct rpc_task *task, void *calldata) 629 { 630 struct nfs4_delegation *dp = calldata; 631 struct nfs4_client *clp = dp->dl_client; 632 struct nfs4_rpc_args *args = task->tk_msg.rpc_argp; 633 u32 minorversion = clp->cl_cb_conn.cb_minorversion; 634 int status = 0; 635 636 args->args_seq.cbs_minorversion = minorversion; 637 if (minorversion) { 638 status = nfsd41_cb_setup_sequence(clp, task); 639 if (status) { 640 if (status != -EAGAIN) { 641 /* terminate rpc task */ 642 task->tk_status = status; 643 task->tk_action = NULL; 644 } 645 return; 646 } 647 } 648 rpc_call_start(task); 649 } 650 651 static void nfsd4_cb_done(struct rpc_task *task, void *calldata) 652 { 653 struct nfs4_delegation *dp = calldata; 654 struct nfs4_client *clp = dp->dl_client; 655 656 dprintk("%s: minorversion=%d\n", __func__, 657 clp->cl_cb_conn.cb_minorversion); 658 659 if (clp->cl_cb_conn.cb_minorversion) { 660 /* No need for lock, access serialized in nfsd4_cb_prepare */ 661 ++clp->cl_cb_seq_nr; 662 clear_bit(0, &clp->cl_cb_slot_busy); 663 rpc_wake_up_next(&clp->cl_cb_waitq); 664 dprintk("%s: freed slot, new seqid=%d\n", __func__, 665 clp->cl_cb_seq_nr); 666 667 /* We're done looking into the sequence information */ 668 task->tk_msg.rpc_resp = NULL; 669 } 670 } 671 672 static void nfsd4_cb_recall_done(struct rpc_task *task, void *calldata) 673 { 674 struct nfs4_delegation *dp = calldata; 675 struct nfs4_client *clp = dp->dl_client; 676 677 nfsd4_cb_done(task, calldata); 678 679 switch (task->tk_status) { 680 case -EIO: 681 /* Network partition? */ 682 atomic_set(&clp->cl_cb_conn.cb_set, 0); 683 warn_no_callback_path(clp, task->tk_status); 684 case -EBADHANDLE: 685 case -NFS4ERR_BAD_STATEID: 686 /* Race: client probably got cb_recall 687 * before open reply granting delegation */ 688 break; 689 default: 690 /* success, or error we can't handle */ 691 goto done; 692 } 693 if (dp->dl_retries--) { 694 rpc_delay(task, 2*HZ); 695 task->tk_status = 0; 696 rpc_restart_call(task); 697 return; 698 } else { 699 atomic_set(&clp->cl_cb_conn.cb_set, 0); 700 warn_no_callback_path(clp, task->tk_status); 701 } 702 done: 703 kfree(task->tk_msg.rpc_argp); 704 } 705 706 static void nfsd4_cb_recall_release(void *calldata) 707 { 708 struct nfs4_delegation *dp = calldata; 709 struct nfs4_client *clp = dp->dl_client; 710 711 nfs4_put_delegation(dp); 712 put_nfs4_client(clp); 713 } 714 715 static const struct rpc_call_ops nfsd4_cb_recall_ops = { 716 .rpc_call_prepare = nfsd4_cb_prepare, 717 .rpc_call_done = nfsd4_cb_recall_done, 718 .rpc_release = nfsd4_cb_recall_release, 719 }; 720 721 /* 722 * called with dp->dl_count inc'ed. 723 */ 724 void 725 nfsd4_cb_recall(struct nfs4_delegation *dp) 726 { 727 struct nfs4_client *clp = dp->dl_client; 728 struct rpc_clnt *clnt = clp->cl_cb_conn.cb_client; 729 struct nfs4_rpc_args *args; 730 struct rpc_message msg = { 731 .rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_RECALL], 732 .rpc_cred = callback_cred 733 }; 734 int status = -ENOMEM; 735 736 args = kzalloc(sizeof(*args), GFP_KERNEL); 737 if (!args) 738 goto out; 739 args->args_op = dp; 740 msg.rpc_argp = args; 741 dp->dl_retries = 1; 742 status = rpc_call_async(clnt, &msg, RPC_TASK_SOFT, 743 &nfsd4_cb_recall_ops, dp); 744 out: 745 if (status) { 746 kfree(args); 747 put_nfs4_client(clp); 748 nfs4_put_delegation(dp); 749 } 750 } 751