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