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