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