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