1 /* 2 * Copyright (c) 2004 The Regents of the University of Michigan. 3 * Copyright (c) 2012 Jeff Layton <jlayton@redhat.com> 4 * All rights reserved. 5 * 6 * Andy Adamson <andros@citi.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 35 #include <crypto/md5.h> 36 #include <crypto/sha2.h> 37 #include <linux/file.h> 38 #include <linux/slab.h> 39 #include <linux/namei.h> 40 #include <linux/sched.h> 41 #include <linux/fs.h> 42 #include <linux/hex.h> 43 #include <linux/module.h> 44 #include <linux/umh.h> 45 #include <net/net_namespace.h> 46 #include <linux/sunrpc/rpc_pipe_fs.h> 47 #include <linux/sunrpc/clnt.h> 48 #include <linux/nfsd/cld.h> 49 50 #include "nfsd.h" 51 #include "nfs4ctl.h" 52 #include "state.h" 53 #include "vfs.h" 54 #include "netns.h" 55 56 #define NFSDDBG_FACILITY NFSDDBG_PROC 57 58 /* Declarations */ 59 struct nfsd4_client_tracking_ops { 60 int (*init)(struct net *); 61 void (*exit)(struct net *); 62 void (*create)(struct nfs4_client *); 63 void (*remove)(struct nfs4_client *); 64 int (*check)(struct nfs4_client *); 65 void (*grace_done)(struct nfsd_net *); 66 uint8_t version; 67 size_t msglen; 68 }; 69 70 static const struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops; 71 static const struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops_v2; 72 73 #ifdef CONFIG_NFSD_LEGACY_CLIENT_TRACKING 74 /* Globals */ 75 static char user_recovery_dirname[PATH_MAX] = "/var/lib/nfs/v4recovery"; 76 77 static int 78 nfs4_save_creds(const struct cred **original_creds) 79 { 80 struct cred *new; 81 82 new = prepare_creds(); 83 if (!new) 84 return -ENOMEM; 85 86 new->fsuid = GLOBAL_ROOT_UID; 87 new->fsgid = GLOBAL_ROOT_GID; 88 *original_creds = override_creds(new); 89 return 0; 90 } 91 92 static void 93 nfs4_reset_creds(const struct cred *original) 94 { 95 put_cred(revert_creds(original)); 96 } 97 98 static void 99 nfs4_make_rec_clidname(char dname[HEXDIR_LEN], const struct xdr_netobj *clname) 100 { 101 u8 digest[MD5_DIGEST_SIZE]; 102 103 dprintk("NFSD: nfs4_make_rec_clidname for %.*s\n", 104 clname->len, clname->data); 105 106 md5(clname->data, clname->len, digest); 107 108 static_assert(HEXDIR_LEN == 2 * MD5_DIGEST_SIZE + 1); 109 sprintf(dname, "%*phN", MD5_DIGEST_SIZE, digest); 110 } 111 112 static void 113 __nfsd4_create_reclaim_record_grace(struct nfs4_client *clp, 114 char *dname, struct nfsd_net *nn) 115 { 116 struct xdr_netobj name = { .len = strlen(dname), .data = dname }; 117 struct xdr_netobj princhash = { .len = 0, .data = NULL }; 118 struct nfs4_client_reclaim *crp; 119 120 crp = nfs4_client_to_reclaim(name, princhash, nn); 121 crp->cr_clp = clp; 122 } 123 124 static void 125 nfsd4_create_clid_dir(struct nfs4_client *clp) 126 { 127 const struct cred *original_cred; 128 char dname[HEXDIR_LEN]; 129 struct dentry *dir, *dentry; 130 int status; 131 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 132 133 if (test_and_set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 134 return; 135 if (!nn->rec_file) 136 return; 137 138 nfs4_make_rec_clidname(dname, &clp->cl_name); 139 140 status = nfs4_save_creds(&original_cred); 141 if (status < 0) 142 return; 143 144 status = mnt_want_write_file(nn->rec_file); 145 if (status) 146 goto out_creds; 147 148 dir = nn->rec_file->f_path.dentry; 149 150 dentry = start_creating(&nop_mnt_idmap, dir, &QSTR(dname)); 151 if (IS_ERR(dentry)) { 152 status = PTR_ERR(dentry); 153 goto out; 154 } 155 if (d_really_is_positive(dentry)) 156 /* 157 * In the 4.1 case, where we're called from 158 * reclaim_complete(), records from the previous reboot 159 * may still be left, so this is OK. 160 * 161 * In the 4.0 case, we should never get here; but we may 162 * as well be forgiving and just succeed silently. 163 */ 164 goto out_end; 165 dentry = vfs_mkdir(&nop_mnt_idmap, d_inode(dir), dentry, 0700, NULL); 166 if (IS_ERR(dentry)) 167 status = PTR_ERR(dentry); 168 out_end: 169 end_creating(dentry); 170 out: 171 if (status == 0) { 172 if (test_bit(NFSD_NET_IN_GRACE, &nn->flags)) 173 __nfsd4_create_reclaim_record_grace(clp, dname, nn); 174 vfs_fsync(nn->rec_file, 0); 175 } else { 176 printk(KERN_ERR "NFSD: failed to write recovery record" 177 " (err %d); please check that %s exists" 178 " and is writeable", status, 179 user_recovery_dirname); 180 } 181 mnt_drop_write_file(nn->rec_file); 182 out_creds: 183 nfs4_reset_creds(original_cred); 184 } 185 186 typedef int (recdir_func)(struct dentry *, char *, struct nfsd_net *); 187 188 struct name_list { 189 char name[HEXDIR_LEN]; 190 struct list_head list; 191 }; 192 193 struct nfs4_dir_ctx { 194 struct dir_context ctx; 195 struct list_head names; 196 }; 197 198 static bool 199 nfsd4_build_namelist(struct dir_context *__ctx, const char *name, int namlen, 200 loff_t offset, u64 ino, unsigned int d_type) 201 { 202 struct nfs4_dir_ctx *ctx = 203 container_of(__ctx, struct nfs4_dir_ctx, ctx); 204 struct name_list *entry; 205 206 if (namlen != HEXDIR_LEN - 1) 207 return true; 208 entry = kmalloc_obj(struct name_list); 209 if (entry == NULL) 210 return false; 211 memcpy(entry->name, name, HEXDIR_LEN - 1); 212 entry->name[HEXDIR_LEN - 1] = '\0'; 213 list_add(&entry->list, &ctx->names); 214 return true; 215 } 216 217 static int 218 nfsd4_list_rec_dir(recdir_func *f, struct nfsd_net *nn) 219 { 220 const struct cred *original_cred; 221 struct dentry *dir = nn->rec_file->f_path.dentry; 222 struct nfs4_dir_ctx ctx = { 223 .ctx.actor = nfsd4_build_namelist, 224 .names = LIST_HEAD_INIT(ctx.names) 225 }; 226 struct name_list *entry, *tmp; 227 int status; 228 229 status = nfs4_save_creds(&original_cred); 230 if (status < 0) 231 return status; 232 233 status = vfs_llseek(nn->rec_file, 0, SEEK_SET); 234 if (status < 0) { 235 nfs4_reset_creds(original_cred); 236 return status; 237 } 238 239 status = iterate_dir(nn->rec_file, &ctx.ctx); 240 241 list_for_each_entry_safe(entry, tmp, &ctx.names, list) { 242 if (!status) 243 status = f(dir, entry->name, nn); 244 245 list_del(&entry->list); 246 kfree(entry); 247 } 248 nfs4_reset_creds(original_cred); 249 250 list_for_each_entry_safe(entry, tmp, &ctx.names, list) { 251 dprintk("NFSD: %s. Left entry %s\n", __func__, entry->name); 252 list_del(&entry->list); 253 kfree(entry); 254 } 255 return status; 256 } 257 258 static int 259 nfsd4_unlink_clid_dir(char *name, struct nfsd_net *nn) 260 { 261 struct dentry *dir, *dentry; 262 int status; 263 264 dprintk("NFSD: nfsd4_unlink_clid_dir. name %s\n", name); 265 266 dir = nn->rec_file->f_path.dentry; 267 dentry = start_removing(&nop_mnt_idmap, dir, &QSTR(name)); 268 if (IS_ERR(dentry)) 269 return PTR_ERR(dentry); 270 271 status = vfs_rmdir(&nop_mnt_idmap, d_inode(dir), dentry, NULL); 272 end_removing(dentry); 273 return status; 274 } 275 276 static void 277 __nfsd4_remove_reclaim_record_grace(const char *dname, int len, 278 struct nfsd_net *nn) 279 { 280 struct xdr_netobj name; 281 struct nfs4_client_reclaim *crp; 282 283 name.data = kmemdup(dname, len, GFP_KERNEL); 284 if (!name.data) { 285 dprintk("%s: failed to allocate memory for name.data!\n", 286 __func__); 287 return; 288 } 289 name.len = len; 290 down_write(&nn->reclaim_str_hashtbl_lock); 291 crp = nfsd4_find_reclaim_client(name, nn); 292 if (crp) 293 nfs4_remove_reclaim_record(crp, nn); 294 up_write(&nn->reclaim_str_hashtbl_lock); 295 kfree(name.data); 296 } 297 298 static void 299 nfsd4_remove_clid_dir(struct nfs4_client *clp) 300 { 301 const struct cred *original_cred; 302 char dname[HEXDIR_LEN]; 303 int status; 304 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 305 306 if (!nn->rec_file || !test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 307 return; 308 309 nfs4_make_rec_clidname(dname, &clp->cl_name); 310 311 status = mnt_want_write_file(nn->rec_file); 312 if (status) 313 goto out; 314 clear_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); 315 316 status = nfs4_save_creds(&original_cred); 317 if (status < 0) 318 goto out_drop_write; 319 320 status = nfsd4_unlink_clid_dir(dname, nn); 321 nfs4_reset_creds(original_cred); 322 if (status == 0) { 323 vfs_fsync(nn->rec_file, 0); 324 if (test_bit(NFSD_NET_IN_GRACE, &nn->flags)) 325 __nfsd4_remove_reclaim_record_grace(dname, 326 HEXDIR_LEN, nn); 327 } 328 out_drop_write: 329 mnt_drop_write_file(nn->rec_file); 330 out: 331 if (status) 332 printk("NFSD: Failed to remove expired client state directory" 333 " %.*s\n", HEXDIR_LEN, dname); 334 } 335 336 static int 337 purge_old(struct dentry *parent, char *cname, struct nfsd_net *nn) 338 { 339 int status; 340 struct dentry *child; 341 struct xdr_netobj name; 342 343 if (strlen(cname) != HEXDIR_LEN - 1) { 344 printk("%s: illegal name %s in recovery directory\n", 345 __func__, cname); 346 /* Keep trying; maybe the others are OK: */ 347 return 0; 348 } 349 name.data = kstrdup(cname, GFP_KERNEL); 350 if (!name.data) { 351 dprintk("%s: failed to allocate memory for name.data!\n", 352 __func__); 353 goto out; 354 } 355 name.len = HEXDIR_LEN; 356 if (nfs4_has_reclaimed_state(name, nn)) 357 goto out_free; 358 359 child = start_removing_noperm(parent, &QSTR(cname)); 360 if (!IS_ERR(child)) { 361 status = vfs_rmdir(&nop_mnt_idmap, d_inode(parent), child, NULL); 362 if (status) 363 printk("failed to remove client recovery directory %pd\n", 364 child); 365 } 366 end_removing(child); 367 368 out_free: 369 kfree(name.data); 370 out: 371 /* Keep trying, success or failure: */ 372 return 0; 373 } 374 375 static void 376 nfsd4_recdir_purge_old(struct nfsd_net *nn) 377 { 378 int status; 379 380 clear_bit(NFSD_NET_IN_GRACE, &nn->flags); 381 if (!nn->rec_file) 382 return; 383 status = mnt_want_write_file(nn->rec_file); 384 if (status) 385 goto out; 386 status = nfsd4_list_rec_dir(purge_old, nn); 387 if (status == 0) 388 vfs_fsync(nn->rec_file, 0); 389 mnt_drop_write_file(nn->rec_file); 390 out: 391 nfs4_release_reclaim(nn); 392 if (status) 393 printk("nfsd4: failed to purge old clients from recovery" 394 " directory %pD\n", nn->rec_file); 395 } 396 397 static int 398 load_recdir(struct dentry *parent, char *cname, struct nfsd_net *nn) 399 { 400 struct xdr_netobj name = { .len = HEXDIR_LEN, .data = cname }; 401 struct xdr_netobj princhash = { .len = 0, .data = NULL }; 402 403 if (strlen(cname) != HEXDIR_LEN - 1) { 404 printk("%s: illegal name %s in recovery directory\n", 405 __func__, cname); 406 /* Keep trying; maybe the others are OK: */ 407 return 0; 408 } 409 nfs4_client_to_reclaim(name, princhash, nn); 410 return 0; 411 } 412 413 static int 414 nfsd4_recdir_load(struct net *net) { 415 int status; 416 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 417 418 if (!nn->rec_file) 419 return 0; 420 421 status = nfsd4_list_rec_dir(load_recdir, nn); 422 if (status) 423 printk("nfsd4: failed loading clients from recovery" 424 " directory %pD\n", nn->rec_file); 425 return status; 426 } 427 428 /* 429 * Hold reference to the recovery directory. 430 */ 431 432 static int 433 nfsd4_init_recdir(struct net *net) 434 { 435 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 436 const struct cred *original_cred; 437 int status; 438 439 printk("NFSD: Using %s as the NFSv4 state recovery directory\n", 440 user_recovery_dirname); 441 442 BUG_ON(nn->rec_file); 443 444 status = nfs4_save_creds(&original_cred); 445 if (status < 0) { 446 printk("NFSD: Unable to change credentials to find recovery" 447 " directory: error %d\n", 448 status); 449 return status; 450 } 451 452 nn->rec_file = filp_open(user_recovery_dirname, O_RDONLY | O_DIRECTORY, 0); 453 if (IS_ERR(nn->rec_file)) { 454 printk("NFSD: unable to find recovery directory %s\n", 455 user_recovery_dirname); 456 status = PTR_ERR(nn->rec_file); 457 nn->rec_file = NULL; 458 } 459 460 nfs4_reset_creds(original_cred); 461 if (!status) 462 set_bit(NFSD_NET_IN_GRACE, &nn->flags); 463 return status; 464 } 465 466 static void 467 nfsd4_shutdown_recdir(struct net *net) 468 { 469 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 470 471 if (!nn->rec_file) 472 return; 473 fput(nn->rec_file); 474 nn->rec_file = NULL; 475 } 476 477 static int 478 nfs4_legacy_state_init(struct net *net) 479 { 480 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 481 int i; 482 483 nn->reclaim_str_hashtbl = kmalloc_objs(struct list_head, 484 CLIENT_HASH_SIZE); 485 if (!nn->reclaim_str_hashtbl) 486 return -ENOMEM; 487 488 for (i = 0; i < CLIENT_HASH_SIZE; i++) 489 INIT_LIST_HEAD(&nn->reclaim_str_hashtbl[i]); 490 nn->reclaim_str_hashtbl_size = 0; 491 init_rwsem(&nn->reclaim_str_hashtbl_lock); 492 493 return 0; 494 } 495 496 static void 497 nfs4_legacy_state_shutdown(struct net *net) 498 { 499 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 500 501 kfree(nn->reclaim_str_hashtbl); 502 } 503 504 static int 505 nfsd4_load_reboot_recovery_data(struct net *net) 506 { 507 int status; 508 509 status = nfsd4_init_recdir(net); 510 if (status) 511 return status; 512 513 status = nfsd4_recdir_load(net); 514 if (status) 515 nfsd4_shutdown_recdir(net); 516 517 return status; 518 } 519 520 static int 521 nfsd4_legacy_tracking_init(struct net *net) 522 { 523 int status; 524 525 /* XXX: The legacy code won't work in a container */ 526 if (net != &init_net) { 527 pr_warn("NFSD: attempt to initialize legacy client tracking in a container ignored.\n"); 528 return -EINVAL; 529 } 530 531 status = nfs4_legacy_state_init(net); 532 if (status) 533 return status; 534 535 status = nfsd4_load_reboot_recovery_data(net); 536 if (status) 537 goto err; 538 pr_info("NFSD: Using legacy client tracking operations.\n"); 539 return 0; 540 541 err: 542 nfs4_legacy_state_shutdown(net); 543 return status; 544 } 545 546 static void 547 nfsd4_legacy_tracking_exit(struct net *net) 548 { 549 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 550 551 nfs4_release_reclaim(nn); 552 nfsd4_shutdown_recdir(net); 553 nfs4_legacy_state_shutdown(net); 554 } 555 556 /* 557 * Change the NFSv4 recovery directory to recdir. 558 */ 559 int 560 nfs4_reset_recoverydir(char *recdir) 561 { 562 int status; 563 struct path path; 564 565 status = kern_path(recdir, LOOKUP_FOLLOW, &path); 566 if (status) 567 return status; 568 status = -ENOTDIR; 569 if (d_is_dir(path.dentry)) { 570 strscpy(user_recovery_dirname, recdir, 571 sizeof(user_recovery_dirname)); 572 status = 0; 573 } 574 path_put(&path); 575 return status; 576 } 577 578 char * 579 nfs4_recoverydir(void) 580 { 581 return user_recovery_dirname; 582 } 583 584 static int 585 nfsd4_check_legacy_client(struct nfs4_client *clp) 586 { 587 char dname[HEXDIR_LEN]; 588 struct nfs4_client_reclaim *crp; 589 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 590 struct xdr_netobj name; 591 592 /* did we already find that this client is stable? */ 593 if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 594 return 0; 595 596 nfs4_make_rec_clidname(dname, &clp->cl_name); 597 598 /* look for it in the reclaim hashtable otherwise */ 599 name.data = kmemdup(dname, HEXDIR_LEN, GFP_KERNEL); 600 if (!name.data) { 601 dprintk("%s: failed to allocate memory for name.data!\n", 602 __func__); 603 goto out_enoent; 604 } 605 name.len = HEXDIR_LEN; 606 down_read(&nn->reclaim_str_hashtbl_lock); 607 crp = nfsd4_find_reclaim_client(name, nn); 608 if (crp) { 609 set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); 610 crp->cr_clp = clp; 611 } 612 up_read(&nn->reclaim_str_hashtbl_lock); 613 kfree(name.data); 614 if (crp) 615 return 0; 616 617 out_enoent: 618 return -ENOENT; 619 } 620 621 static const struct nfsd4_client_tracking_ops nfsd4_legacy_tracking_ops = { 622 .init = nfsd4_legacy_tracking_init, 623 .exit = nfsd4_legacy_tracking_exit, 624 .create = nfsd4_create_clid_dir, 625 .remove = nfsd4_remove_clid_dir, 626 .check = nfsd4_check_legacy_client, 627 .grace_done = nfsd4_recdir_purge_old, 628 .version = 1, 629 .msglen = 0, 630 }; 631 #endif /* CONFIG_NFSD_LEGACY_CLIENT_TRACKING */ 632 633 /* Globals */ 634 #define NFSD_PIPE_DIR "nfsd" 635 #define NFSD_CLD_PIPE "cld" 636 637 /* per-net-ns structure for holding cld upcall info */ 638 struct cld_net { 639 struct rpc_pipe *cn_pipe; 640 spinlock_t cn_lock; 641 struct list_head cn_list; 642 unsigned int cn_xid; 643 #ifdef CONFIG_NFSD_LEGACY_CLIENT_TRACKING 644 bool cn_has_legacy; 645 #endif 646 }; 647 648 struct cld_upcall { 649 struct list_head cu_list; 650 struct cld_net *cu_net; 651 struct completion cu_done; 652 /* daemon has read the whole upcall; protected by cn_lock */ 653 bool cu_inflight; 654 struct rpc_pipe_msg cu_pipe_msg; 655 union { 656 struct cld_msg_hdr cu_hdr; 657 struct cld_msg cu_msg; 658 struct cld_msg_v2 cu_msg_v2; 659 } cu_u; 660 }; 661 662 static int 663 __cld_pipe_upcall(struct rpc_pipe *pipe, void *cmsg, struct nfsd_net *nn) 664 { 665 int ret; 666 struct cld_upcall *cup = container_of(cmsg, struct cld_upcall, cu_u); 667 struct rpc_pipe_msg *msg = &cup->cu_pipe_msg; 668 669 memset(msg, 0, sizeof(*msg)); 670 msg->data = cmsg; 671 msg->len = nn->client_tracking_ops->msglen; 672 673 ret = rpc_queue_upcall(pipe, msg); 674 if (ret < 0) { 675 goto out; 676 } 677 678 wait_for_completion(&cup->cu_done); 679 680 if (msg->errno < 0) 681 ret = msg->errno; 682 out: 683 return ret; 684 } 685 686 static int 687 cld_pipe_upcall(struct rpc_pipe *pipe, void *cmsg, struct nfsd_net *nn) 688 { 689 int ret; 690 691 /* 692 * -EAGAIN occurs when pipe is closed and reopened while there are 693 * upcalls queued. 694 */ 695 do { 696 ret = __cld_pipe_upcall(pipe, cmsg, nn); 697 } while (ret == -EAGAIN); 698 699 return ret; 700 } 701 702 static ssize_t 703 __cld_pipe_inprogress_downcall(const struct cld_msg_v2 __user *cmsg, 704 struct nfsd_net *nn) 705 { 706 uint8_t cmd, princhashlen; 707 struct xdr_netobj name, princhash = { .len = 0, .data = NULL }; 708 char *namecopy __free(kfree) = NULL; 709 char *princhashcopy __free(kfree) = NULL; 710 uint16_t namelen; 711 712 if (get_user(cmd, &cmsg->cm_cmd)) { 713 dprintk("%s: error when copying cmd from userspace", __func__); 714 return -EFAULT; 715 } 716 if (cmd == Cld_GraceStart) { 717 if (nn->client_tracking_ops->version >= 2) { 718 const struct cld_clntinfo __user *ci; 719 720 ci = &cmsg->cm_u.cm_clntinfo; 721 if (get_user(namelen, &ci->cc_name.cn_len)) 722 return -EFAULT; 723 if (namelen == 0 || namelen > NFS4_OPAQUE_LIMIT) { 724 dprintk("%s: invalid namelen (%u)", __func__, namelen); 725 return -EINVAL; 726 } 727 namecopy = memdup_user(&ci->cc_name.cn_id, namelen); 728 if (IS_ERR(namecopy)) 729 return PTR_ERR(namecopy); 730 name.data = namecopy; 731 name.len = namelen; 732 if (get_user(princhashlen, &ci->cc_princhash.cp_len)) 733 return -EFAULT; 734 if (princhashlen > SHA256_DIGEST_SIZE) { 735 dprintk("%s: invalid princhashlen (%u)", 736 __func__, princhashlen); 737 return -EINVAL; 738 } 739 if (princhashlen > 0) { 740 princhashcopy = memdup_user( 741 &ci->cc_princhash.cp_data, 742 princhashlen); 743 if (IS_ERR(princhashcopy)) 744 return PTR_ERR(princhashcopy); 745 princhash.data = princhashcopy; 746 princhash.len = princhashlen; 747 } else 748 princhash.len = 0; 749 } else { 750 const struct cld_name __user *cnm; 751 752 cnm = &cmsg->cm_u.cm_name; 753 if (get_user(namelen, &cnm->cn_len)) 754 return -EFAULT; 755 if (namelen == 0 || namelen > NFS4_OPAQUE_LIMIT) { 756 dprintk("%s: invalid namelen (%u)", __func__, namelen); 757 return -EINVAL; 758 } 759 namecopy = memdup_user(&cnm->cn_id, namelen); 760 if (IS_ERR(namecopy)) 761 return PTR_ERR(namecopy); 762 name.data = namecopy; 763 name.len = namelen; 764 } 765 #ifdef CONFIG_NFSD_LEGACY_CLIENT_TRACKING 766 if (name.len > 5 && memcmp(name.data, "hash:", 5) == 0) { 767 struct cld_net *cn = nn->cld_net; 768 769 name.len = name.len - 5; 770 name.data = name.data + 5; 771 cn->cn_has_legacy = true; 772 } 773 #endif 774 if (!nfs4_client_to_reclaim(name, princhash, nn)) 775 return -EFAULT; 776 return nn->client_tracking_ops->msglen; 777 } 778 return -EFAULT; 779 } 780 781 static ssize_t 782 cld_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) 783 { 784 struct cld_upcall *tmp, *cup; 785 struct cld_msg_hdr __user *hdr = (struct cld_msg_hdr __user *)src; 786 struct cld_msg_v2 __user *cmsg = (struct cld_msg_v2 __user *)src; 787 uint32_t xid; 788 struct nfsd_net *nn = net_generic(file_inode(filp)->i_sb->s_fs_info, 789 nfsd_net_id); 790 struct cld_net *cn = nn->cld_net; 791 int16_t status; 792 793 if (mlen != nn->client_tracking_ops->msglen) { 794 dprintk("%s: got %zu bytes, expected %zu\n", __func__, mlen, 795 nn->client_tracking_ops->msglen); 796 return -EINVAL; 797 } 798 799 /* copy just the xid so we can try to find that */ 800 if (copy_from_user(&xid, &hdr->cm_xid, sizeof(xid)) != 0) { 801 dprintk("%s: error when copying xid from userspace", __func__); 802 return -EFAULT; 803 } 804 805 /* 806 * copy the status so we know whether to remove the upcall from the 807 * list (for -EINPROGRESS, we just want to make sure the xid is 808 * valid, not remove the upcall from the list) 809 */ 810 if (get_user(status, &hdr->cm_status)) { 811 dprintk("%s: error when copying status from userspace", __func__); 812 return -EFAULT; 813 } 814 815 /* walk the list and find corresponding xid */ 816 cup = NULL; 817 spin_lock(&cn->cn_lock); 818 list_for_each_entry(tmp, &cn->cn_list, cu_list) { 819 if (get_unaligned(&tmp->cu_u.cu_hdr.cm_xid) == xid) { 820 /* 821 * Completing now would return the waiter 822 * while its message is still queued on the 823 * pipe. 824 */ 825 if (!tmp->cu_inflight) 826 break; 827 cup = tmp; 828 if (status != -EINPROGRESS) 829 list_del_init(&cup->cu_list); 830 break; 831 } 832 } 833 spin_unlock(&cn->cn_lock); 834 835 /* no upcall to complete? */ 836 if (!cup) { 837 dprintk("%s: no completable upcall -- xid=%u\n", __func__, xid); 838 return -EINVAL; 839 } 840 841 if (status == -EINPROGRESS) 842 return __cld_pipe_inprogress_downcall(cmsg, nn); 843 844 if (copy_from_user(&cup->cu_u.cu_msg_v2, src, mlen) != 0) { 845 cup->cu_pipe_msg.errno = -EFAULT; 846 complete(&cup->cu_done); 847 return -EFAULT; 848 } 849 850 complete(&cup->cu_done); 851 return mlen; 852 } 853 854 static void 855 cld_pipe_destroy_msg(struct rpc_pipe_msg *msg) 856 { 857 struct cld_upcall *cup = container_of(msg, struct cld_upcall, 858 cu_pipe_msg); 859 struct cld_net *cn = cup->cu_net; 860 861 /* 862 * errno >= 0 means the daemon read the whole message and a 863 * downcall will complete the upcall. 864 */ 865 spin_lock(&cn->cn_lock); 866 cup->cu_inflight = msg->errno >= 0; 867 spin_unlock(&cn->cn_lock); 868 869 if (msg->errno >= 0) 870 return; 871 872 complete(&cup->cu_done); 873 } 874 875 /* 876 * An upcall the daemon has consumed is off every pipe list, so the 877 * purge in rpc_pipe_release() and rpc_close_pipes() cannot reach it. 878 * Release its waiter here instead; no downcall can arrive now. 879 */ 880 static void 881 cld_release_pipe(struct inode *inode) 882 { 883 struct nfsd_net *nn = net_generic(inode->i_sb->s_fs_info, nfsd_net_id); 884 struct cld_net *cn = nn->cld_net; 885 struct cld_upcall *cup; 886 887 spin_lock(&cn->cn_lock); 888 list_for_each_entry(cup, &cn->cn_list, cu_list) { 889 if (!cup->cu_inflight) 890 continue; 891 cup->cu_inflight = false; 892 cup->cu_pipe_msg.errno = -EPIPE; 893 complete(&cup->cu_done); 894 } 895 spin_unlock(&cn->cn_lock); 896 } 897 898 static const struct rpc_pipe_ops cld_upcall_ops = { 899 .upcall = rpc_pipe_generic_upcall, 900 .downcall = cld_pipe_downcall, 901 .destroy_msg = cld_pipe_destroy_msg, 902 .release_pipe = cld_release_pipe, 903 }; 904 905 static int 906 nfsd4_cld_register_sb(struct super_block *sb, struct rpc_pipe *pipe) 907 { 908 struct dentry *dir; 909 int err; 910 911 dir = rpc_d_lookup_sb(sb, NFSD_PIPE_DIR); 912 if (dir == NULL) 913 return -ENOENT; 914 err = rpc_mkpipe_dentry(dir, NFSD_CLD_PIPE, NULL, pipe); 915 dput(dir); 916 return err; 917 } 918 919 static int 920 nfsd4_cld_register_net(struct net *net, struct rpc_pipe *pipe) 921 { 922 struct super_block *sb; 923 int err; 924 925 sb = rpc_get_sb_net(net); 926 if (!sb) 927 return 0; 928 err = nfsd4_cld_register_sb(sb, pipe); 929 rpc_put_sb_net(net); 930 return err; 931 } 932 933 static void 934 nfsd4_cld_unregister_net(struct net *net, struct rpc_pipe *pipe) 935 { 936 struct super_block *sb; 937 938 sb = rpc_get_sb_net(net); 939 if (sb) { 940 rpc_unlink(pipe); 941 rpc_put_sb_net(net); 942 } 943 } 944 945 /* Initialize rpc_pipefs pipe for communication with client tracking daemon */ 946 static int 947 __nfsd4_init_cld_pipe(struct net *net) 948 { 949 int ret; 950 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 951 struct cld_net *cn; 952 953 if (nn->cld_net) 954 return 0; 955 956 cn = kzalloc_obj(*cn); 957 if (!cn) { 958 ret = -ENOMEM; 959 goto err; 960 } 961 962 cn->cn_pipe = rpc_mkpipe_data(&cld_upcall_ops, RPC_PIPE_WAIT_FOR_OPEN); 963 if (IS_ERR(cn->cn_pipe)) { 964 ret = PTR_ERR(cn->cn_pipe); 965 goto err; 966 } 967 spin_lock_init(&cn->cn_lock); 968 INIT_LIST_HEAD(&cn->cn_list); 969 #ifdef CONFIG_NFSD_LEGACY_CLIENT_TRACKING 970 cn->cn_has_legacy = false; 971 #endif 972 973 /* 974 * The pipe's methods reach @cn through nn->cld_net, so set 975 * it before the pipe can be opened. 976 */ 977 nn->cld_net = cn; 978 979 ret = nfsd4_cld_register_net(net, cn->cn_pipe); 980 if (unlikely(ret)) 981 goto err_destroy_data; 982 983 return 0; 984 985 err_destroy_data: 986 nn->cld_net = NULL; 987 rpc_destroy_pipe_data(cn->cn_pipe); 988 err: 989 kfree(cn); 990 printk(KERN_ERR "NFSD: unable to create nfsdcld upcall pipe (%d)\n", 991 ret); 992 return ret; 993 } 994 995 static int 996 nfsd4_init_cld_pipe(struct net *net) 997 { 998 int status; 999 1000 status = __nfsd4_init_cld_pipe(net); 1001 if (!status) 1002 pr_info("NFSD: Using old nfsdcld client tracking operations.\n"); 1003 return status; 1004 } 1005 1006 static void 1007 nfsd4_remove_cld_pipe(struct net *net) 1008 { 1009 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 1010 struct cld_net *cn = nn->cld_net; 1011 1012 nfsd4_cld_unregister_net(net, cn->cn_pipe); 1013 rpc_destroy_pipe_data(cn->cn_pipe); 1014 kfree(nn->cld_net); 1015 nn->cld_net = NULL; 1016 } 1017 1018 static struct cld_upcall * 1019 alloc_cld_upcall(struct nfsd_net *nn) 1020 { 1021 struct cld_upcall *new, *tmp; 1022 struct cld_net *cn = nn->cld_net; 1023 1024 new = kzalloc_obj(*new); 1025 if (!new) 1026 return new; 1027 1028 /* FIXME: hard cap on number in flight? */ 1029 restart_search: 1030 spin_lock(&cn->cn_lock); 1031 list_for_each_entry(tmp, &cn->cn_list, cu_list) { 1032 if (tmp->cu_u.cu_msg.cm_xid == cn->cn_xid) { 1033 cn->cn_xid++; 1034 spin_unlock(&cn->cn_lock); 1035 goto restart_search; 1036 } 1037 } 1038 init_completion(&new->cu_done); 1039 new->cu_u.cu_msg.cm_vers = nn->client_tracking_ops->version; 1040 put_unaligned(cn->cn_xid++, &new->cu_u.cu_msg.cm_xid); 1041 new->cu_net = cn; 1042 list_add(&new->cu_list, &cn->cn_list); 1043 spin_unlock(&cn->cn_lock); 1044 1045 dprintk("%s: allocated xid %u\n", __func__, new->cu_u.cu_msg.cm_xid); 1046 1047 return new; 1048 } 1049 1050 static void 1051 free_cld_upcall(struct cld_upcall *victim) 1052 { 1053 struct cld_net *cn = victim->cu_net; 1054 1055 spin_lock(&cn->cn_lock); 1056 list_del(&victim->cu_list); 1057 spin_unlock(&cn->cn_lock); 1058 kfree(victim); 1059 } 1060 1061 /* Ask daemon to create a new record */ 1062 static void 1063 nfsd4_cld_create(struct nfs4_client *clp) 1064 { 1065 int ret; 1066 struct cld_upcall *cup; 1067 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 1068 struct cld_net *cn = nn->cld_net; 1069 1070 /* Don't upcall if it's already stored */ 1071 if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 1072 return; 1073 1074 cup = alloc_cld_upcall(nn); 1075 if (!cup) { 1076 ret = -ENOMEM; 1077 goto out_err; 1078 } 1079 1080 cup->cu_u.cu_msg.cm_cmd = Cld_Create; 1081 cup->cu_u.cu_msg.cm_u.cm_name.cn_len = clp->cl_name.len; 1082 memcpy(cup->cu_u.cu_msg.cm_u.cm_name.cn_id, clp->cl_name.data, 1083 clp->cl_name.len); 1084 1085 ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn); 1086 if (!ret) { 1087 ret = cup->cu_u.cu_msg.cm_status; 1088 set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); 1089 } 1090 1091 free_cld_upcall(cup); 1092 out_err: 1093 if (ret) 1094 printk(KERN_ERR "NFSD: Unable to create client " 1095 "record on stable storage: %d\n", ret); 1096 } 1097 1098 /* Ask daemon to create a new record */ 1099 static void 1100 nfsd4_cld_create_v2(struct nfs4_client *clp) 1101 { 1102 int ret; 1103 struct cld_upcall *cup; 1104 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 1105 struct cld_net *cn = nn->cld_net; 1106 struct cld_msg_v2 *cmsg; 1107 char *principal = NULL; 1108 1109 /* Don't upcall if it's already stored */ 1110 if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 1111 return; 1112 1113 cup = alloc_cld_upcall(nn); 1114 if (!cup) { 1115 ret = -ENOMEM; 1116 goto out_err; 1117 } 1118 1119 cmsg = &cup->cu_u.cu_msg_v2; 1120 cmsg->cm_cmd = Cld_Create; 1121 cmsg->cm_u.cm_clntinfo.cc_name.cn_len = clp->cl_name.len; 1122 memcpy(cmsg->cm_u.cm_clntinfo.cc_name.cn_id, clp->cl_name.data, 1123 clp->cl_name.len); 1124 if (clp->cl_cred.cr_raw_principal) 1125 principal = clp->cl_cred.cr_raw_principal; 1126 else if (clp->cl_cred.cr_principal) 1127 principal = clp->cl_cred.cr_principal; 1128 if (principal) { 1129 sha256(principal, strlen(principal), 1130 cmsg->cm_u.cm_clntinfo.cc_princhash.cp_data); 1131 cmsg->cm_u.cm_clntinfo.cc_princhash.cp_len = SHA256_DIGEST_SIZE; 1132 } else 1133 cmsg->cm_u.cm_clntinfo.cc_princhash.cp_len = 0; 1134 1135 ret = cld_pipe_upcall(cn->cn_pipe, cmsg, nn); 1136 if (!ret) { 1137 ret = cmsg->cm_status; 1138 set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); 1139 } 1140 1141 free_cld_upcall(cup); 1142 out_err: 1143 if (ret) 1144 pr_err("NFSD: Unable to create client record on stable storage: %d\n", 1145 ret); 1146 } 1147 1148 /* Ask daemon to create a new record */ 1149 static void 1150 nfsd4_cld_remove(struct nfs4_client *clp) 1151 { 1152 int ret; 1153 struct cld_upcall *cup; 1154 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 1155 struct cld_net *cn = nn->cld_net; 1156 1157 /* Don't upcall if it's already removed */ 1158 if (!test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 1159 return; 1160 1161 cup = alloc_cld_upcall(nn); 1162 if (!cup) { 1163 ret = -ENOMEM; 1164 goto out_err; 1165 } 1166 1167 cup->cu_u.cu_msg.cm_cmd = Cld_Remove; 1168 cup->cu_u.cu_msg.cm_u.cm_name.cn_len = clp->cl_name.len; 1169 memcpy(cup->cu_u.cu_msg.cm_u.cm_name.cn_id, clp->cl_name.data, 1170 clp->cl_name.len); 1171 1172 ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn); 1173 if (!ret) { 1174 ret = cup->cu_u.cu_msg.cm_status; 1175 clear_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); 1176 } 1177 1178 free_cld_upcall(cup); 1179 out_err: 1180 if (ret) 1181 printk(KERN_ERR "NFSD: Unable to remove client " 1182 "record from stable storage: %d\n", ret); 1183 } 1184 1185 /* 1186 * For older nfsdcld's that do not allow us to "slurp" the clients 1187 * from the tracking database during startup. 1188 * 1189 * Check for presence of a record, and update its timestamp 1190 */ 1191 static int 1192 nfsd4_cld_check_v0(struct nfs4_client *clp) 1193 { 1194 int ret; 1195 struct cld_upcall *cup; 1196 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 1197 struct cld_net *cn = nn->cld_net; 1198 1199 /* Don't upcall if one was already stored during this grace pd */ 1200 if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 1201 return 0; 1202 1203 cup = alloc_cld_upcall(nn); 1204 if (!cup) { 1205 printk(KERN_ERR "NFSD: Unable to check client record on " 1206 "stable storage: %d\n", -ENOMEM); 1207 return -ENOMEM; 1208 } 1209 1210 cup->cu_u.cu_msg.cm_cmd = Cld_Check; 1211 cup->cu_u.cu_msg.cm_u.cm_name.cn_len = clp->cl_name.len; 1212 memcpy(cup->cu_u.cu_msg.cm_u.cm_name.cn_id, clp->cl_name.data, 1213 clp->cl_name.len); 1214 1215 ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn); 1216 if (!ret) { 1217 ret = cup->cu_u.cu_msg.cm_status; 1218 set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); 1219 } 1220 1221 free_cld_upcall(cup); 1222 return ret; 1223 } 1224 1225 /* 1226 * For newer nfsdcld's that allow us to "slurp" the clients 1227 * from the tracking database during startup. 1228 * 1229 * Check for presence of a record in the reclaim_str_hashtbl 1230 */ 1231 static int 1232 nfsd4_cld_check(struct nfs4_client *clp) 1233 { 1234 struct nfs4_client_reclaim *crp; 1235 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 1236 1237 /* did we already find that this client is stable? */ 1238 if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 1239 return 0; 1240 1241 /* look for it in the reclaim hashtable otherwise */ 1242 down_read(&nn->reclaim_str_hashtbl_lock); 1243 crp = nfsd4_find_reclaim_client(clp->cl_name, nn); 1244 if (crp) 1245 goto found; 1246 1247 #ifdef CONFIG_NFSD_LEGACY_CLIENT_TRACKING 1248 if (nn->cld_net->cn_has_legacy) { 1249 char dname[HEXDIR_LEN]; 1250 struct xdr_netobj name; 1251 1252 nfs4_make_rec_clidname(dname, &clp->cl_name); 1253 1254 name.data = kmemdup(dname, HEXDIR_LEN, GFP_KERNEL); 1255 if (!name.data) { 1256 dprintk("%s: failed to allocate memory for name.data!\n", 1257 __func__); 1258 up_read(&nn->reclaim_str_hashtbl_lock); 1259 return -ENOENT; 1260 } 1261 name.len = HEXDIR_LEN; 1262 crp = nfsd4_find_reclaim_client(name, nn); 1263 kfree(name.data); 1264 if (crp) 1265 goto found; 1266 1267 } 1268 #endif 1269 up_read(&nn->reclaim_str_hashtbl_lock); 1270 return -ENOENT; 1271 found: 1272 crp->cr_clp = clp; 1273 up_read(&nn->reclaim_str_hashtbl_lock); 1274 return 0; 1275 } 1276 1277 static int 1278 nfsd4_cld_check_v2(struct nfs4_client *clp) 1279 { 1280 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 1281 #ifdef CONFIG_NFSD_LEGACY_CLIENT_TRACKING 1282 struct cld_net *cn = nn->cld_net; 1283 #endif 1284 struct nfs4_client_reclaim *crp; 1285 unsigned int princhashlen; 1286 char *principal = NULL; 1287 1288 /* did we already find that this client is stable? */ 1289 if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 1290 return 0; 1291 1292 /* look for it in the reclaim hashtable otherwise */ 1293 down_read(&nn->reclaim_str_hashtbl_lock); 1294 crp = nfsd4_find_reclaim_client(clp->cl_name, nn); 1295 if (crp) 1296 goto found; 1297 1298 #ifdef CONFIG_NFSD_LEGACY_CLIENT_TRACKING 1299 if (cn->cn_has_legacy) { 1300 struct xdr_netobj name; 1301 char dname[HEXDIR_LEN]; 1302 1303 nfs4_make_rec_clidname(dname, &clp->cl_name); 1304 1305 name.data = kmemdup(dname, HEXDIR_LEN, GFP_KERNEL); 1306 if (!name.data) { 1307 dprintk("%s: failed to allocate memory for name.data\n", 1308 __func__); 1309 up_read(&nn->reclaim_str_hashtbl_lock); 1310 return -ENOENT; 1311 } 1312 name.len = HEXDIR_LEN; 1313 crp = nfsd4_find_reclaim_client(name, nn); 1314 kfree(name.data); 1315 if (crp) 1316 goto found; 1317 1318 } 1319 #endif 1320 up_read(&nn->reclaim_str_hashtbl_lock); 1321 return -ENOENT; 1322 found: 1323 princhashlen = crp->cr_princhash.len; 1324 if (princhashlen) { 1325 u8 digest[SHA256_DIGEST_SIZE]; 1326 u8 *pdata; 1327 1328 if (clp->cl_cred.cr_raw_principal) 1329 principal = clp->cl_cred.cr_raw_principal; 1330 else if (clp->cl_cred.cr_principal) 1331 principal = clp->cl_cred.cr_principal; 1332 if (principal == NULL) { 1333 up_read(&nn->reclaim_str_hashtbl_lock); 1334 return -ENOENT; 1335 } 1336 sha256(principal, strlen(principal), digest); 1337 pdata = crp->cr_princhash.data; 1338 if (memcmp(pdata, digest, princhashlen)) { 1339 up_read(&nn->reclaim_str_hashtbl_lock); 1340 return -ENOENT; 1341 } 1342 } 1343 crp->cr_clp = clp; 1344 up_read(&nn->reclaim_str_hashtbl_lock); 1345 return 0; 1346 } 1347 1348 static int 1349 nfsd4_cld_grace_start(struct nfsd_net *nn) 1350 { 1351 int ret; 1352 struct cld_upcall *cup; 1353 struct cld_net *cn = nn->cld_net; 1354 1355 cup = alloc_cld_upcall(nn); 1356 if (!cup) { 1357 ret = -ENOMEM; 1358 goto out_err; 1359 } 1360 1361 cup->cu_u.cu_msg.cm_cmd = Cld_GraceStart; 1362 ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn); 1363 if (!ret) 1364 ret = cup->cu_u.cu_msg.cm_status; 1365 1366 free_cld_upcall(cup); 1367 out_err: 1368 if (ret) 1369 dprintk("%s: Unable to get clients from userspace: %d\n", 1370 __func__, ret); 1371 return ret; 1372 } 1373 1374 /* For older nfsdcld's that need cm_gracetime */ 1375 static void 1376 nfsd4_cld_grace_done_v0(struct nfsd_net *nn) 1377 { 1378 int ret; 1379 struct cld_upcall *cup; 1380 struct cld_net *cn = nn->cld_net; 1381 1382 cup = alloc_cld_upcall(nn); 1383 if (!cup) { 1384 ret = -ENOMEM; 1385 goto out_err; 1386 } 1387 1388 cup->cu_u.cu_msg.cm_cmd = Cld_GraceDone; 1389 cup->cu_u.cu_msg.cm_u.cm_gracetime = nn->boot_time; 1390 ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn); 1391 if (!ret) 1392 ret = cup->cu_u.cu_msg.cm_status; 1393 1394 free_cld_upcall(cup); 1395 out_err: 1396 if (ret) 1397 printk(KERN_ERR "NFSD: Unable to end grace period: %d\n", ret); 1398 } 1399 1400 /* 1401 * For newer nfsdcld's that do not need cm_gracetime. We also need to call 1402 * nfs4_release_reclaim() to clear out the reclaim_str_hashtbl. 1403 */ 1404 static void 1405 nfsd4_cld_grace_done(struct nfsd_net *nn) 1406 { 1407 int ret; 1408 struct cld_upcall *cup; 1409 struct cld_net *cn = nn->cld_net; 1410 1411 cup = alloc_cld_upcall(nn); 1412 if (!cup) { 1413 ret = -ENOMEM; 1414 goto out_err; 1415 } 1416 1417 cup->cu_u.cu_msg.cm_cmd = Cld_GraceDone; 1418 ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn); 1419 if (!ret) 1420 ret = cup->cu_u.cu_msg.cm_status; 1421 1422 free_cld_upcall(cup); 1423 out_err: 1424 nfs4_release_reclaim(nn); 1425 if (ret) 1426 printk(KERN_ERR "NFSD: Unable to end grace period: %d\n", ret); 1427 } 1428 1429 static int 1430 nfs4_cld_state_init(struct net *net) 1431 { 1432 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 1433 int i; 1434 1435 nn->reclaim_str_hashtbl = kmalloc_objs(struct list_head, 1436 CLIENT_HASH_SIZE); 1437 if (!nn->reclaim_str_hashtbl) 1438 return -ENOMEM; 1439 1440 for (i = 0; i < CLIENT_HASH_SIZE; i++) 1441 INIT_LIST_HEAD(&nn->reclaim_str_hashtbl[i]); 1442 nn->reclaim_str_hashtbl_size = 0; 1443 init_rwsem(&nn->reclaim_str_hashtbl_lock); 1444 set_bit(NFSD_NET_TRACK_RECLAIM_COMPLETES, &nn->flags); 1445 atomic_set(&nn->nr_reclaim_complete, 0); 1446 1447 return 0; 1448 } 1449 1450 static void 1451 nfs4_cld_state_shutdown(struct net *net) 1452 { 1453 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 1454 1455 clear_bit(NFSD_NET_TRACK_RECLAIM_COMPLETES, &nn->flags); 1456 kfree(nn->reclaim_str_hashtbl); 1457 } 1458 1459 static bool 1460 cld_running(struct nfsd_net *nn) 1461 { 1462 struct cld_net *cn = nn->cld_net; 1463 struct rpc_pipe *pipe = cn->cn_pipe; 1464 1465 return pipe->nreaders || pipe->nwriters; 1466 } 1467 1468 static int 1469 nfsd4_cld_get_version(struct nfsd_net *nn) 1470 { 1471 int ret = 0; 1472 struct cld_upcall *cup; 1473 struct cld_net *cn = nn->cld_net; 1474 uint8_t version; 1475 1476 cup = alloc_cld_upcall(nn); 1477 if (!cup) { 1478 ret = -ENOMEM; 1479 goto out_err; 1480 } 1481 cup->cu_u.cu_msg.cm_cmd = Cld_GetVersion; 1482 ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn); 1483 if (!ret) { 1484 ret = cup->cu_u.cu_msg.cm_status; 1485 if (ret) 1486 goto out_free; 1487 version = cup->cu_u.cu_msg.cm_u.cm_version; 1488 dprintk("%s: userspace returned version %u\n", 1489 __func__, version); 1490 if (version < 1) 1491 version = 1; 1492 else if (version > CLD_UPCALL_VERSION) 1493 version = CLD_UPCALL_VERSION; 1494 1495 switch (version) { 1496 case 1: 1497 nn->client_tracking_ops = &nfsd4_cld_tracking_ops; 1498 break; 1499 case 2: 1500 nn->client_tracking_ops = &nfsd4_cld_tracking_ops_v2; 1501 break; 1502 default: 1503 break; 1504 } 1505 } 1506 out_free: 1507 free_cld_upcall(cup); 1508 out_err: 1509 if (ret) 1510 dprintk("%s: Unable to get version from userspace: %d\n", 1511 __func__, ret); 1512 return ret; 1513 } 1514 1515 static int 1516 nfsd4_cld_tracking_init(struct net *net) 1517 { 1518 int status; 1519 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 1520 bool running; 1521 int retries = 10; 1522 1523 status = nfs4_cld_state_init(net); 1524 if (status) 1525 return status; 1526 1527 status = __nfsd4_init_cld_pipe(net); 1528 if (status) 1529 goto err_shutdown; 1530 1531 /* 1532 * rpc pipe upcalls take 30 seconds to time out, so we don't want to 1533 * queue an upcall unless we know that nfsdcld is running (because we 1534 * want this to fail fast so that nfsd4_client_tracking_init() can try 1535 * the next client tracking method). nfsdcld should already be running 1536 * before nfsd is started, so the wait here is for nfsdcld to open the 1537 * pipefs file we just created. 1538 */ 1539 while (!(running = cld_running(nn)) && retries--) 1540 msleep(100); 1541 1542 if (!running) { 1543 status = -ETIMEDOUT; 1544 goto err_remove; 1545 } 1546 1547 status = nfsd4_cld_get_version(nn); 1548 if (status == -EOPNOTSUPP) 1549 pr_warn("NFSD: nfsdcld GetVersion upcall failed. Please upgrade nfsdcld.\n"); 1550 1551 status = nfsd4_cld_grace_start(nn); 1552 if (status) { 1553 if (status == -EOPNOTSUPP) 1554 pr_warn("NFSD: nfsdcld GraceStart upcall failed. Please upgrade nfsdcld.\n"); 1555 nfs4_release_reclaim(nn); 1556 goto err_remove; 1557 } else 1558 pr_info("NFSD: Using nfsdcld client tracking operations.\n"); 1559 return 0; 1560 1561 err_remove: 1562 nfsd4_remove_cld_pipe(net); 1563 err_shutdown: 1564 nfs4_cld_state_shutdown(net); 1565 return status; 1566 } 1567 1568 static void 1569 nfsd4_cld_tracking_exit(struct net *net) 1570 { 1571 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 1572 1573 nfs4_release_reclaim(nn); 1574 nfsd4_remove_cld_pipe(net); 1575 nfs4_cld_state_shutdown(net); 1576 } 1577 1578 /* For older nfsdcld's */ 1579 static const struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops_v0 = { 1580 .init = nfsd4_init_cld_pipe, 1581 .exit = nfsd4_remove_cld_pipe, 1582 .create = nfsd4_cld_create, 1583 .remove = nfsd4_cld_remove, 1584 .check = nfsd4_cld_check_v0, 1585 .grace_done = nfsd4_cld_grace_done_v0, 1586 .version = 1, 1587 .msglen = sizeof(struct cld_msg), 1588 }; 1589 1590 /* For newer nfsdcld's */ 1591 static const struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops = { 1592 .init = nfsd4_cld_tracking_init, 1593 .exit = nfsd4_cld_tracking_exit, 1594 .create = nfsd4_cld_create, 1595 .remove = nfsd4_cld_remove, 1596 .check = nfsd4_cld_check, 1597 .grace_done = nfsd4_cld_grace_done, 1598 .version = 1, 1599 .msglen = sizeof(struct cld_msg), 1600 }; 1601 1602 /* v2 create/check ops include the principal, if available */ 1603 static const struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops_v2 = { 1604 .init = nfsd4_cld_tracking_init, 1605 .exit = nfsd4_cld_tracking_exit, 1606 .create = nfsd4_cld_create_v2, 1607 .remove = nfsd4_cld_remove, 1608 .check = nfsd4_cld_check_v2, 1609 .grace_done = nfsd4_cld_grace_done, 1610 .version = 2, 1611 .msglen = sizeof(struct cld_msg_v2), 1612 }; 1613 1614 #ifdef CONFIG_NFSD_LEGACY_CLIENT_TRACKING 1615 /* upcall via usermodehelper */ 1616 static char cltrack_prog[PATH_MAX] = "/sbin/nfsdcltrack"; 1617 module_param_string(cltrack_prog, cltrack_prog, sizeof(cltrack_prog), 1618 S_IRUGO|S_IWUSR); 1619 MODULE_PARM_DESC(cltrack_prog, "Path to the nfsdcltrack upcall program"); 1620 1621 static bool cltrack_legacy_disable; 1622 module_param(cltrack_legacy_disable, bool, S_IRUGO|S_IWUSR); 1623 MODULE_PARM_DESC(cltrack_legacy_disable, 1624 "Disable legacy recoverydir conversion. Default: false"); 1625 1626 #define LEGACY_TOPDIR_ENV_PREFIX "NFSDCLTRACK_LEGACY_TOPDIR=" 1627 #define LEGACY_RECDIR_ENV_PREFIX "NFSDCLTRACK_LEGACY_RECDIR=" 1628 #define HAS_SESSION_ENV_PREFIX "NFSDCLTRACK_CLIENT_HAS_SESSION=" 1629 #define GRACE_START_ENV_PREFIX "NFSDCLTRACK_GRACE_START=" 1630 1631 static char * 1632 nfsd4_cltrack_legacy_topdir(void) 1633 { 1634 int copied; 1635 size_t len; 1636 char *result; 1637 1638 if (cltrack_legacy_disable) 1639 return NULL; 1640 1641 len = strlen(LEGACY_TOPDIR_ENV_PREFIX) + 1642 strlen(nfs4_recoverydir()) + 1; 1643 1644 result = kmalloc(len, GFP_KERNEL); 1645 if (!result) 1646 return result; 1647 1648 copied = snprintf(result, len, LEGACY_TOPDIR_ENV_PREFIX "%s", 1649 nfs4_recoverydir()); 1650 if (copied >= len) { 1651 /* just return nothing if output was truncated */ 1652 kfree(result); 1653 return NULL; 1654 } 1655 1656 return result; 1657 } 1658 1659 static char * 1660 nfsd4_cltrack_legacy_recdir(const struct xdr_netobj *name) 1661 { 1662 int copied; 1663 size_t len; 1664 char *result; 1665 1666 if (cltrack_legacy_disable) 1667 return NULL; 1668 1669 /* +1 is for '/' between "topdir" and "recdir" */ 1670 len = strlen(LEGACY_RECDIR_ENV_PREFIX) + 1671 strlen(nfs4_recoverydir()) + 1 + HEXDIR_LEN; 1672 1673 result = kmalloc(len, GFP_KERNEL); 1674 if (!result) 1675 return result; 1676 1677 copied = snprintf(result, len, LEGACY_RECDIR_ENV_PREFIX "%s/", 1678 nfs4_recoverydir()); 1679 if (copied > (len - HEXDIR_LEN)) { 1680 /* just return nothing if output will be truncated */ 1681 kfree(result); 1682 return NULL; 1683 } 1684 1685 nfs4_make_rec_clidname(result + copied, name); 1686 1687 return result; 1688 } 1689 1690 static char * 1691 nfsd4_cltrack_client_has_session(struct nfs4_client *clp) 1692 { 1693 int copied; 1694 size_t len; 1695 char *result; 1696 1697 /* prefix + Y/N character + terminating NULL */ 1698 len = strlen(HAS_SESSION_ENV_PREFIX) + 1 + 1; 1699 1700 result = kmalloc(len, GFP_KERNEL); 1701 if (!result) 1702 return result; 1703 1704 copied = snprintf(result, len, HAS_SESSION_ENV_PREFIX "%c", 1705 clp->cl_minorversion ? 'Y' : 'N'); 1706 if (copied >= len) { 1707 /* just return nothing if output was truncated */ 1708 kfree(result); 1709 return NULL; 1710 } 1711 1712 return result; 1713 } 1714 1715 static char * 1716 nfsd4_cltrack_grace_start(time64_t grace_start) 1717 { 1718 int copied; 1719 size_t len; 1720 char *result; 1721 1722 /* prefix + max width of int64_t string + terminating NULL */ 1723 len = strlen(GRACE_START_ENV_PREFIX) + 22 + 1; 1724 1725 result = kmalloc(len, GFP_KERNEL); 1726 if (!result) 1727 return result; 1728 1729 copied = snprintf(result, len, GRACE_START_ENV_PREFIX "%lld", 1730 grace_start); 1731 if (copied >= len) { 1732 /* just return nothing if output was truncated */ 1733 kfree(result); 1734 return NULL; 1735 } 1736 1737 return result; 1738 } 1739 1740 static int 1741 nfsd4_umh_cltrack_upcall(char *cmd, char *arg, char *env0, char *env1) 1742 { 1743 char *envp[3]; 1744 char *argv[4]; 1745 int ret; 1746 1747 if (unlikely(!cltrack_prog[0])) { 1748 dprintk("%s: cltrack_prog is disabled\n", __func__); 1749 return -EACCES; 1750 } 1751 1752 dprintk("%s: cmd: %s\n", __func__, cmd); 1753 dprintk("%s: arg: %s\n", __func__, arg ? arg : "(null)"); 1754 dprintk("%s: env0: %s\n", __func__, env0 ? env0 : "(null)"); 1755 dprintk("%s: env1: %s\n", __func__, env1 ? env1 : "(null)"); 1756 1757 envp[0] = env0; 1758 envp[1] = env1; 1759 envp[2] = NULL; 1760 1761 argv[0] = (char *)cltrack_prog; 1762 argv[1] = cmd; 1763 argv[2] = arg; 1764 argv[3] = NULL; 1765 1766 ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC); 1767 /* 1768 * Disable the upcall mechanism if we're getting an ENOENT or EACCES 1769 * error. The admin can re-enable it on the fly by using sysfs 1770 * once the problem has been fixed. 1771 */ 1772 if (ret == -ENOENT || ret == -EACCES) { 1773 dprintk("NFSD: %s was not found or isn't executable (%d). " 1774 "Setting cltrack_prog to blank string!", 1775 cltrack_prog, ret); 1776 cltrack_prog[0] = '\0'; 1777 } 1778 dprintk("%s: %s return value: %d\n", __func__, cltrack_prog, ret); 1779 1780 return ret; 1781 } 1782 1783 static char * 1784 bin_to_hex_dup(const unsigned char *src, int srclen) 1785 { 1786 char *buf; 1787 1788 /* +1 for terminating NULL */ 1789 buf = kzalloc((srclen * 2) + 1, GFP_KERNEL); 1790 if (!buf) 1791 return buf; 1792 1793 bin2hex(buf, src, srclen); 1794 return buf; 1795 } 1796 1797 static int 1798 nfsd4_umh_cltrack_init(struct net *net) 1799 { 1800 int ret; 1801 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 1802 char *grace_start = nfsd4_cltrack_grace_start(nn->boot_time); 1803 1804 /* XXX: The usermode helper s not working in container yet. */ 1805 if (net != &init_net) { 1806 pr_warn("NFSD: attempt to initialize umh client tracking in a container ignored.\n"); 1807 kfree(grace_start); 1808 return -EINVAL; 1809 } 1810 1811 ret = nfsd4_umh_cltrack_upcall("init", NULL, grace_start, NULL); 1812 kfree(grace_start); 1813 if (!ret) 1814 pr_info("NFSD: Using UMH upcall client tracking operations.\n"); 1815 return ret; 1816 } 1817 1818 static void 1819 nfsd4_cltrack_upcall_lock(struct nfs4_client *clp) 1820 { 1821 wait_on_bit_lock(&clp->cl_flags, NFSD4_CLIENT_UPCALL_LOCK, 1822 TASK_UNINTERRUPTIBLE); 1823 } 1824 1825 static void 1826 nfsd4_cltrack_upcall_unlock(struct nfs4_client *clp) 1827 { 1828 clear_and_wake_up_bit(NFSD4_CLIENT_UPCALL_LOCK, &clp->cl_flags); 1829 } 1830 1831 static void 1832 nfsd4_umh_cltrack_create(struct nfs4_client *clp) 1833 { 1834 char *hexid, *has_session, *grace_start; 1835 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 1836 1837 /* 1838 * With v4.0 clients, there's little difference in outcome between a 1839 * create and check operation, and we can end up calling into this 1840 * function multiple times per client (once for each openowner). So, 1841 * for v4.0 clients skip upcalling once the client has been recorded 1842 * on stable storage. 1843 * 1844 * For v4.1+ clients, the outcome of the two operations is different, 1845 * so we must ensure that we upcall for the create operation. v4.1+ 1846 * clients call this on RECLAIM_COMPLETE though, so we should only end 1847 * up doing a single create upcall per client. 1848 */ 1849 if (clp->cl_minorversion == 0 && 1850 test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 1851 return; 1852 1853 hexid = bin_to_hex_dup(clp->cl_name.data, clp->cl_name.len); 1854 if (!hexid) { 1855 dprintk("%s: can't allocate memory for upcall!\n", __func__); 1856 return; 1857 } 1858 1859 has_session = nfsd4_cltrack_client_has_session(clp); 1860 grace_start = nfsd4_cltrack_grace_start(nn->boot_time); 1861 1862 nfsd4_cltrack_upcall_lock(clp); 1863 if (!nfsd4_umh_cltrack_upcall("create", hexid, has_session, grace_start)) 1864 set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); 1865 nfsd4_cltrack_upcall_unlock(clp); 1866 1867 kfree(has_session); 1868 kfree(grace_start); 1869 kfree(hexid); 1870 } 1871 1872 static void 1873 nfsd4_umh_cltrack_remove(struct nfs4_client *clp) 1874 { 1875 char *hexid; 1876 1877 if (!test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 1878 return; 1879 1880 hexid = bin_to_hex_dup(clp->cl_name.data, clp->cl_name.len); 1881 if (!hexid) { 1882 dprintk("%s: can't allocate memory for upcall!\n", __func__); 1883 return; 1884 } 1885 1886 nfsd4_cltrack_upcall_lock(clp); 1887 if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags) && 1888 nfsd4_umh_cltrack_upcall("remove", hexid, NULL, NULL) == 0) 1889 clear_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); 1890 nfsd4_cltrack_upcall_unlock(clp); 1891 1892 kfree(hexid); 1893 } 1894 1895 static int 1896 nfsd4_umh_cltrack_check(struct nfs4_client *clp) 1897 { 1898 int ret; 1899 char *hexid, *has_session, *legacy; 1900 1901 if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 1902 return 0; 1903 1904 hexid = bin_to_hex_dup(clp->cl_name.data, clp->cl_name.len); 1905 if (!hexid) { 1906 dprintk("%s: can't allocate memory for upcall!\n", __func__); 1907 return -ENOMEM; 1908 } 1909 1910 has_session = nfsd4_cltrack_client_has_session(clp); 1911 legacy = nfsd4_cltrack_legacy_recdir(&clp->cl_name); 1912 1913 nfsd4_cltrack_upcall_lock(clp); 1914 if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) { 1915 ret = 0; 1916 } else { 1917 ret = nfsd4_umh_cltrack_upcall("check", hexid, has_session, legacy); 1918 if (ret == 0) 1919 set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); 1920 } 1921 nfsd4_cltrack_upcall_unlock(clp); 1922 kfree(has_session); 1923 kfree(legacy); 1924 kfree(hexid); 1925 1926 return ret; 1927 } 1928 1929 static void 1930 nfsd4_umh_cltrack_grace_done(struct nfsd_net *nn) 1931 { 1932 char *legacy; 1933 char timestr[22]; /* FIXME: better way to determine max size? */ 1934 1935 sprintf(timestr, "%lld", nn->boot_time); 1936 legacy = nfsd4_cltrack_legacy_topdir(); 1937 nfsd4_umh_cltrack_upcall("gracedone", timestr, legacy, NULL); 1938 kfree(legacy); 1939 } 1940 1941 static const struct nfsd4_client_tracking_ops nfsd4_umh_tracking_ops = { 1942 .init = nfsd4_umh_cltrack_init, 1943 .exit = NULL, 1944 .create = nfsd4_umh_cltrack_create, 1945 .remove = nfsd4_umh_cltrack_remove, 1946 .check = nfsd4_umh_cltrack_check, 1947 .grace_done = nfsd4_umh_cltrack_grace_done, 1948 .version = 1, 1949 .msglen = 0, 1950 }; 1951 1952 static inline int check_for_legacy_methods(int status, struct net *net) 1953 { 1954 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 1955 struct path path; 1956 1957 /* 1958 * Next, try the UMH upcall. 1959 */ 1960 nn->client_tracking_ops = &nfsd4_umh_tracking_ops; 1961 status = nn->client_tracking_ops->init(net); 1962 if (!status) 1963 return status; 1964 1965 /* 1966 * Finally, See if the recoverydir exists and is a directory. 1967 * If it is, then use the legacy ops. 1968 */ 1969 nn->client_tracking_ops = &nfsd4_legacy_tracking_ops; 1970 status = kern_path(nfs4_recoverydir(), LOOKUP_FOLLOW, &path); 1971 if (!status) { 1972 status = !d_is_dir(path.dentry); 1973 path_put(&path); 1974 if (status) 1975 return -ENOTDIR; 1976 } 1977 return status; 1978 } 1979 #else 1980 static inline int check_for_legacy_methods(int status, struct net *net) 1981 { 1982 return status; 1983 } 1984 #endif /* CONFIG_LEGACY_NFSD_CLIENT_TRACKING */ 1985 1986 int 1987 nfsd4_client_tracking_init(struct net *net) 1988 { 1989 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 1990 int status; 1991 1992 /* just run the init if it the method is already decided */ 1993 if (nn->client_tracking_ops) 1994 goto do_init; 1995 1996 /* First, try to use nfsdcld */ 1997 nn->client_tracking_ops = &nfsd4_cld_tracking_ops; 1998 status = nn->client_tracking_ops->init(net); 1999 if (!status) 2000 return status; 2001 if (status != -ETIMEDOUT) { 2002 nn->client_tracking_ops = &nfsd4_cld_tracking_ops_v0; 2003 status = nn->client_tracking_ops->init(net); 2004 if (!status) 2005 return status; 2006 } 2007 2008 status = check_for_legacy_methods(status, net); 2009 if (status) 2010 goto out; 2011 do_init: 2012 status = nn->client_tracking_ops->init(net); 2013 out: 2014 if (status) { 2015 pr_warn("NFSD: Unable to initialize client recovery tracking! (%d)\n", status); 2016 pr_warn("NFSD: Is nfsdcld running? If not, enable CONFIG_NFSD_LEGACY_CLIENT_TRACKING.\n"); 2017 nn->client_tracking_ops = NULL; 2018 } 2019 return status; 2020 } 2021 2022 void 2023 nfsd4_client_tracking_exit(struct net *net) 2024 { 2025 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 2026 2027 if (nn->client_tracking_ops) { 2028 if (nn->client_tracking_ops->exit) 2029 nn->client_tracking_ops->exit(net); 2030 nn->client_tracking_ops = NULL; 2031 } 2032 } 2033 2034 void 2035 nfsd4_client_record_create(struct nfs4_client *clp) 2036 { 2037 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 2038 2039 if (nn->client_tracking_ops) 2040 nn->client_tracking_ops->create(clp); 2041 } 2042 2043 void 2044 nfsd4_client_record_remove(struct nfs4_client *clp) 2045 { 2046 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 2047 2048 if (nn->client_tracking_ops) 2049 nn->client_tracking_ops->remove(clp); 2050 } 2051 2052 int 2053 nfsd4_client_record_check(struct nfs4_client *clp) 2054 { 2055 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 2056 2057 if (nn->client_tracking_ops) 2058 return nn->client_tracking_ops->check(clp); 2059 2060 return -EOPNOTSUPP; 2061 } 2062 2063 void 2064 nfsd4_record_grace_done(struct nfsd_net *nn) 2065 { 2066 if (nn->client_tracking_ops) 2067 nn->client_tracking_ops->grace_done(nn); 2068 } 2069 2070 static int 2071 rpc_pipefs_event(struct notifier_block *nb, unsigned long event, void *ptr) 2072 { 2073 struct super_block *sb = ptr; 2074 struct net *net = sb->s_fs_info; 2075 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 2076 struct cld_net *cn = nn->cld_net; 2077 int ret = 0; 2078 2079 if (!try_module_get(THIS_MODULE)) 2080 return 0; 2081 2082 if (!cn) { 2083 module_put(THIS_MODULE); 2084 return 0; 2085 } 2086 2087 switch (event) { 2088 case RPC_PIPEFS_MOUNT: 2089 ret = nfsd4_cld_register_sb(sb, cn->cn_pipe); 2090 break; 2091 case RPC_PIPEFS_UMOUNT: 2092 rpc_unlink(cn->cn_pipe); 2093 break; 2094 default: 2095 ret = -ENOTSUPP; 2096 break; 2097 } 2098 module_put(THIS_MODULE); 2099 return ret; 2100 } 2101 2102 static struct notifier_block nfsd4_cld_block = { 2103 .notifier_call = rpc_pipefs_event, 2104 }; 2105 2106 int 2107 register_cld_notifier(void) 2108 { 2109 WARN_ON(!nfsd_net_id); 2110 return rpc_pipefs_notifier_register(&nfsd4_cld_block); 2111 } 2112 2113 void 2114 unregister_cld_notifier(void) 2115 { 2116 rpc_pipefs_notifier_unregister(&nfsd4_cld_block); 2117 } 2118