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 1582 status = nfs4_cld_state_init(net); 1583 if (status) 1584 return status; 1585 1586 status = __nfsd4_init_cld_pipe(net); 1587 if (status) 1588 goto err_shutdown; 1589 nn->cld_net->cn_tfm = crypto_alloc_shash("sha256", 0, 0); 1590 if (IS_ERR(nn->cld_net->cn_tfm)) { 1591 status = PTR_ERR(nn->cld_net->cn_tfm); 1592 goto err_remove; 1593 } 1594 1595 /* 1596 * rpc pipe upcalls take 30 seconds to time out, so we don't want to 1597 * queue an upcall unless we know that nfsdcld is running (because we 1598 * want this to fail fast so that nfsd4_client_tracking_init() can try 1599 * the next client tracking method). nfsdcld should already be running 1600 * before nfsd is started, so the wait here is for nfsdcld to open the 1601 * pipefs file we just created. 1602 */ 1603 while (!(running = cld_running(nn)) && retries--) 1604 msleep(100); 1605 1606 if (!running) { 1607 status = -ETIMEDOUT; 1608 goto err_remove; 1609 } 1610 1611 status = nfsd4_cld_get_version(nn); 1612 if (status == -EOPNOTSUPP) 1613 pr_warn("NFSD: nfsdcld GetVersion upcall failed. Please upgrade nfsdcld.\n"); 1614 1615 status = nfsd4_cld_grace_start(nn); 1616 if (status) { 1617 if (status == -EOPNOTSUPP) 1618 pr_warn("NFSD: nfsdcld GraceStart upcall failed. Please upgrade nfsdcld.\n"); 1619 nfs4_release_reclaim(nn); 1620 goto err_remove; 1621 } else 1622 printk("NFSD: Using nfsdcld client tracking operations.\n"); 1623 return 0; 1624 1625 err_remove: 1626 nfsd4_remove_cld_pipe(net); 1627 err_shutdown: 1628 nfs4_cld_state_shutdown(net); 1629 return status; 1630 } 1631 1632 static void 1633 nfsd4_cld_tracking_exit(struct net *net) 1634 { 1635 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 1636 1637 nfs4_release_reclaim(nn); 1638 nfsd4_remove_cld_pipe(net); 1639 nfs4_cld_state_shutdown(net); 1640 } 1641 1642 /* For older nfsdcld's */ 1643 static const struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops_v0 = { 1644 .init = nfsd4_init_cld_pipe, 1645 .exit = nfsd4_remove_cld_pipe, 1646 .create = nfsd4_cld_create, 1647 .remove = nfsd4_cld_remove, 1648 .check = nfsd4_cld_check_v0, 1649 .grace_done = nfsd4_cld_grace_done_v0, 1650 .version = 1, 1651 .msglen = sizeof(struct cld_msg), 1652 }; 1653 1654 /* For newer nfsdcld's */ 1655 static const struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops = { 1656 .init = nfsd4_cld_tracking_init, 1657 .exit = nfsd4_cld_tracking_exit, 1658 .create = nfsd4_cld_create, 1659 .remove = nfsd4_cld_remove, 1660 .check = nfsd4_cld_check, 1661 .grace_done = nfsd4_cld_grace_done, 1662 .version = 1, 1663 .msglen = sizeof(struct cld_msg), 1664 }; 1665 1666 /* v2 create/check ops include the principal, if available */ 1667 static const struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops_v2 = { 1668 .init = nfsd4_cld_tracking_init, 1669 .exit = nfsd4_cld_tracking_exit, 1670 .create = nfsd4_cld_create_v2, 1671 .remove = nfsd4_cld_remove, 1672 .check = nfsd4_cld_check_v2, 1673 .grace_done = nfsd4_cld_grace_done, 1674 .version = 2, 1675 .msglen = sizeof(struct cld_msg_v2), 1676 }; 1677 1678 /* upcall via usermodehelper */ 1679 static char cltrack_prog[PATH_MAX] = "/sbin/nfsdcltrack"; 1680 module_param_string(cltrack_prog, cltrack_prog, sizeof(cltrack_prog), 1681 S_IRUGO|S_IWUSR); 1682 MODULE_PARM_DESC(cltrack_prog, "Path to the nfsdcltrack upcall program"); 1683 1684 static bool cltrack_legacy_disable; 1685 module_param(cltrack_legacy_disable, bool, S_IRUGO|S_IWUSR); 1686 MODULE_PARM_DESC(cltrack_legacy_disable, 1687 "Disable legacy recoverydir conversion. Default: false"); 1688 1689 #define LEGACY_TOPDIR_ENV_PREFIX "NFSDCLTRACK_LEGACY_TOPDIR=" 1690 #define LEGACY_RECDIR_ENV_PREFIX "NFSDCLTRACK_LEGACY_RECDIR=" 1691 #define HAS_SESSION_ENV_PREFIX "NFSDCLTRACK_CLIENT_HAS_SESSION=" 1692 #define GRACE_START_ENV_PREFIX "NFSDCLTRACK_GRACE_START=" 1693 1694 static char * 1695 nfsd4_cltrack_legacy_topdir(void) 1696 { 1697 int copied; 1698 size_t len; 1699 char *result; 1700 1701 if (cltrack_legacy_disable) 1702 return NULL; 1703 1704 len = strlen(LEGACY_TOPDIR_ENV_PREFIX) + 1705 strlen(nfs4_recoverydir()) + 1; 1706 1707 result = kmalloc(len, GFP_KERNEL); 1708 if (!result) 1709 return result; 1710 1711 copied = snprintf(result, len, LEGACY_TOPDIR_ENV_PREFIX "%s", 1712 nfs4_recoverydir()); 1713 if (copied >= len) { 1714 /* just return nothing if output was truncated */ 1715 kfree(result); 1716 return NULL; 1717 } 1718 1719 return result; 1720 } 1721 1722 static char * 1723 nfsd4_cltrack_legacy_recdir(const struct xdr_netobj *name) 1724 { 1725 int copied; 1726 size_t len; 1727 char *result; 1728 1729 if (cltrack_legacy_disable) 1730 return NULL; 1731 1732 /* +1 is for '/' between "topdir" and "recdir" */ 1733 len = strlen(LEGACY_RECDIR_ENV_PREFIX) + 1734 strlen(nfs4_recoverydir()) + 1 + HEXDIR_LEN; 1735 1736 result = kmalloc(len, GFP_KERNEL); 1737 if (!result) 1738 return result; 1739 1740 copied = snprintf(result, len, LEGACY_RECDIR_ENV_PREFIX "%s/", 1741 nfs4_recoverydir()); 1742 if (copied > (len - HEXDIR_LEN)) { 1743 /* just return nothing if output will be truncated */ 1744 kfree(result); 1745 return NULL; 1746 } 1747 1748 copied = nfs4_make_rec_clidname(result + copied, name); 1749 if (copied) { 1750 kfree(result); 1751 return NULL; 1752 } 1753 1754 return result; 1755 } 1756 1757 static char * 1758 nfsd4_cltrack_client_has_session(struct nfs4_client *clp) 1759 { 1760 int copied; 1761 size_t len; 1762 char *result; 1763 1764 /* prefix + Y/N character + terminating NULL */ 1765 len = strlen(HAS_SESSION_ENV_PREFIX) + 1 + 1; 1766 1767 result = kmalloc(len, GFP_KERNEL); 1768 if (!result) 1769 return result; 1770 1771 copied = snprintf(result, len, HAS_SESSION_ENV_PREFIX "%c", 1772 clp->cl_minorversion ? 'Y' : 'N'); 1773 if (copied >= len) { 1774 /* just return nothing if output was truncated */ 1775 kfree(result); 1776 return NULL; 1777 } 1778 1779 return result; 1780 } 1781 1782 static char * 1783 nfsd4_cltrack_grace_start(time_t grace_start) 1784 { 1785 int copied; 1786 size_t len; 1787 char *result; 1788 1789 /* prefix + max width of int64_t string + terminating NULL */ 1790 len = strlen(GRACE_START_ENV_PREFIX) + 22 + 1; 1791 1792 result = kmalloc(len, GFP_KERNEL); 1793 if (!result) 1794 return result; 1795 1796 copied = snprintf(result, len, GRACE_START_ENV_PREFIX "%ld", 1797 grace_start); 1798 if (copied >= len) { 1799 /* just return nothing if output was truncated */ 1800 kfree(result); 1801 return NULL; 1802 } 1803 1804 return result; 1805 } 1806 1807 static int 1808 nfsd4_umh_cltrack_upcall(char *cmd, char *arg, char *env0, char *env1) 1809 { 1810 char *envp[3]; 1811 char *argv[4]; 1812 int ret; 1813 1814 if (unlikely(!cltrack_prog[0])) { 1815 dprintk("%s: cltrack_prog is disabled\n", __func__); 1816 return -EACCES; 1817 } 1818 1819 dprintk("%s: cmd: %s\n", __func__, cmd); 1820 dprintk("%s: arg: %s\n", __func__, arg ? arg : "(null)"); 1821 dprintk("%s: env0: %s\n", __func__, env0 ? env0 : "(null)"); 1822 dprintk("%s: env1: %s\n", __func__, env1 ? env1 : "(null)"); 1823 1824 envp[0] = env0; 1825 envp[1] = env1; 1826 envp[2] = NULL; 1827 1828 argv[0] = (char *)cltrack_prog; 1829 argv[1] = cmd; 1830 argv[2] = arg; 1831 argv[3] = NULL; 1832 1833 ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC); 1834 /* 1835 * Disable the upcall mechanism if we're getting an ENOENT or EACCES 1836 * error. The admin can re-enable it on the fly by using sysfs 1837 * once the problem has been fixed. 1838 */ 1839 if (ret == -ENOENT || ret == -EACCES) { 1840 dprintk("NFSD: %s was not found or isn't executable (%d). " 1841 "Setting cltrack_prog to blank string!", 1842 cltrack_prog, ret); 1843 cltrack_prog[0] = '\0'; 1844 } 1845 dprintk("%s: %s return value: %d\n", __func__, cltrack_prog, ret); 1846 1847 return ret; 1848 } 1849 1850 static char * 1851 bin_to_hex_dup(const unsigned char *src, int srclen) 1852 { 1853 int i; 1854 char *buf, *hex; 1855 1856 /* +1 for terminating NULL */ 1857 buf = kmalloc((srclen * 2) + 1, GFP_KERNEL); 1858 if (!buf) 1859 return buf; 1860 1861 hex = buf; 1862 for (i = 0; i < srclen; i++) { 1863 sprintf(hex, "%2.2x", *src++); 1864 hex += 2; 1865 } 1866 return buf; 1867 } 1868 1869 static int 1870 nfsd4_umh_cltrack_init(struct net *net) 1871 { 1872 int ret; 1873 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 1874 char *grace_start = nfsd4_cltrack_grace_start(nn->boot_time); 1875 1876 /* XXX: The usermode helper s not working in container yet. */ 1877 if (net != &init_net) { 1878 pr_warn("NFSD: attempt to initialize umh client tracking in a container ignored.\n"); 1879 kfree(grace_start); 1880 return -EINVAL; 1881 } 1882 1883 ret = nfsd4_umh_cltrack_upcall("init", NULL, grace_start, NULL); 1884 kfree(grace_start); 1885 if (!ret) 1886 printk("NFSD: Using UMH upcall client tracking operations.\n"); 1887 return ret; 1888 } 1889 1890 static void 1891 nfsd4_cltrack_upcall_lock(struct nfs4_client *clp) 1892 { 1893 wait_on_bit_lock(&clp->cl_flags, NFSD4_CLIENT_UPCALL_LOCK, 1894 TASK_UNINTERRUPTIBLE); 1895 } 1896 1897 static void 1898 nfsd4_cltrack_upcall_unlock(struct nfs4_client *clp) 1899 { 1900 smp_mb__before_atomic(); 1901 clear_bit(NFSD4_CLIENT_UPCALL_LOCK, &clp->cl_flags); 1902 smp_mb__after_atomic(); 1903 wake_up_bit(&clp->cl_flags, NFSD4_CLIENT_UPCALL_LOCK); 1904 } 1905 1906 static void 1907 nfsd4_umh_cltrack_create(struct nfs4_client *clp) 1908 { 1909 char *hexid, *has_session, *grace_start; 1910 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 1911 1912 /* 1913 * With v4.0 clients, there's little difference in outcome between a 1914 * create and check operation, and we can end up calling into this 1915 * function multiple times per client (once for each openowner). So, 1916 * for v4.0 clients skip upcalling once the client has been recorded 1917 * on stable storage. 1918 * 1919 * For v4.1+ clients, the outcome of the two operations is different, 1920 * so we must ensure that we upcall for the create operation. v4.1+ 1921 * clients call this on RECLAIM_COMPLETE though, so we should only end 1922 * up doing a single create upcall per client. 1923 */ 1924 if (clp->cl_minorversion == 0 && 1925 test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 1926 return; 1927 1928 hexid = bin_to_hex_dup(clp->cl_name.data, clp->cl_name.len); 1929 if (!hexid) { 1930 dprintk("%s: can't allocate memory for upcall!\n", __func__); 1931 return; 1932 } 1933 1934 has_session = nfsd4_cltrack_client_has_session(clp); 1935 grace_start = nfsd4_cltrack_grace_start(nn->boot_time); 1936 1937 nfsd4_cltrack_upcall_lock(clp); 1938 if (!nfsd4_umh_cltrack_upcall("create", hexid, has_session, grace_start)) 1939 set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); 1940 nfsd4_cltrack_upcall_unlock(clp); 1941 1942 kfree(has_session); 1943 kfree(grace_start); 1944 kfree(hexid); 1945 } 1946 1947 static void 1948 nfsd4_umh_cltrack_remove(struct nfs4_client *clp) 1949 { 1950 char *hexid; 1951 1952 if (!test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 1953 return; 1954 1955 hexid = bin_to_hex_dup(clp->cl_name.data, clp->cl_name.len); 1956 if (!hexid) { 1957 dprintk("%s: can't allocate memory for upcall!\n", __func__); 1958 return; 1959 } 1960 1961 nfsd4_cltrack_upcall_lock(clp); 1962 if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags) && 1963 nfsd4_umh_cltrack_upcall("remove", hexid, NULL, NULL) == 0) 1964 clear_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); 1965 nfsd4_cltrack_upcall_unlock(clp); 1966 1967 kfree(hexid); 1968 } 1969 1970 static int 1971 nfsd4_umh_cltrack_check(struct nfs4_client *clp) 1972 { 1973 int ret; 1974 char *hexid, *has_session, *legacy; 1975 1976 if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 1977 return 0; 1978 1979 hexid = bin_to_hex_dup(clp->cl_name.data, clp->cl_name.len); 1980 if (!hexid) { 1981 dprintk("%s: can't allocate memory for upcall!\n", __func__); 1982 return -ENOMEM; 1983 } 1984 1985 has_session = nfsd4_cltrack_client_has_session(clp); 1986 legacy = nfsd4_cltrack_legacy_recdir(&clp->cl_name); 1987 1988 nfsd4_cltrack_upcall_lock(clp); 1989 if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) { 1990 ret = 0; 1991 } else { 1992 ret = nfsd4_umh_cltrack_upcall("check", hexid, has_session, legacy); 1993 if (ret == 0) 1994 set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); 1995 } 1996 nfsd4_cltrack_upcall_unlock(clp); 1997 kfree(has_session); 1998 kfree(legacy); 1999 kfree(hexid); 2000 2001 return ret; 2002 } 2003 2004 static void 2005 nfsd4_umh_cltrack_grace_done(struct nfsd_net *nn) 2006 { 2007 char *legacy; 2008 char timestr[22]; /* FIXME: better way to determine max size? */ 2009 2010 sprintf(timestr, "%ld", nn->boot_time); 2011 legacy = nfsd4_cltrack_legacy_topdir(); 2012 nfsd4_umh_cltrack_upcall("gracedone", timestr, legacy, NULL); 2013 kfree(legacy); 2014 } 2015 2016 static const struct nfsd4_client_tracking_ops nfsd4_umh_tracking_ops = { 2017 .init = nfsd4_umh_cltrack_init, 2018 .exit = NULL, 2019 .create = nfsd4_umh_cltrack_create, 2020 .remove = nfsd4_umh_cltrack_remove, 2021 .check = nfsd4_umh_cltrack_check, 2022 .grace_done = nfsd4_umh_cltrack_grace_done, 2023 .version = 1, 2024 .msglen = 0, 2025 }; 2026 2027 int 2028 nfsd4_client_tracking_init(struct net *net) 2029 { 2030 int status; 2031 struct path path; 2032 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 2033 2034 /* just run the init if it the method is already decided */ 2035 if (nn->client_tracking_ops) 2036 goto do_init; 2037 2038 /* First, try to use nfsdcld */ 2039 nn->client_tracking_ops = &nfsd4_cld_tracking_ops; 2040 status = nn->client_tracking_ops->init(net); 2041 if (!status) 2042 return status; 2043 if (status != -ETIMEDOUT) { 2044 nn->client_tracking_ops = &nfsd4_cld_tracking_ops_v0; 2045 status = nn->client_tracking_ops->init(net); 2046 if (!status) 2047 return status; 2048 } 2049 2050 /* 2051 * Next, try the UMH upcall. 2052 */ 2053 nn->client_tracking_ops = &nfsd4_umh_tracking_ops; 2054 status = nn->client_tracking_ops->init(net); 2055 if (!status) 2056 return status; 2057 2058 /* 2059 * Finally, See if the recoverydir exists and is a directory. 2060 * If it is, then use the legacy ops. 2061 */ 2062 nn->client_tracking_ops = &nfsd4_legacy_tracking_ops; 2063 status = kern_path(nfs4_recoverydir(), LOOKUP_FOLLOW, &path); 2064 if (!status) { 2065 status = d_is_dir(path.dentry); 2066 path_put(&path); 2067 if (!status) { 2068 status = -EINVAL; 2069 goto out; 2070 } 2071 } 2072 2073 do_init: 2074 status = nn->client_tracking_ops->init(net); 2075 out: 2076 if (status) { 2077 printk(KERN_WARNING "NFSD: Unable to initialize client " 2078 "recovery tracking! (%d)\n", status); 2079 nn->client_tracking_ops = NULL; 2080 } 2081 return status; 2082 } 2083 2084 void 2085 nfsd4_client_tracking_exit(struct net *net) 2086 { 2087 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 2088 2089 if (nn->client_tracking_ops) { 2090 if (nn->client_tracking_ops->exit) 2091 nn->client_tracking_ops->exit(net); 2092 nn->client_tracking_ops = NULL; 2093 } 2094 } 2095 2096 void 2097 nfsd4_client_record_create(struct nfs4_client *clp) 2098 { 2099 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 2100 2101 if (nn->client_tracking_ops) 2102 nn->client_tracking_ops->create(clp); 2103 } 2104 2105 void 2106 nfsd4_client_record_remove(struct nfs4_client *clp) 2107 { 2108 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 2109 2110 if (nn->client_tracking_ops) 2111 nn->client_tracking_ops->remove(clp); 2112 } 2113 2114 int 2115 nfsd4_client_record_check(struct nfs4_client *clp) 2116 { 2117 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 2118 2119 if (nn->client_tracking_ops) 2120 return nn->client_tracking_ops->check(clp); 2121 2122 return -EOPNOTSUPP; 2123 } 2124 2125 void 2126 nfsd4_record_grace_done(struct nfsd_net *nn) 2127 { 2128 if (nn->client_tracking_ops) 2129 nn->client_tracking_ops->grace_done(nn); 2130 } 2131 2132 static int 2133 rpc_pipefs_event(struct notifier_block *nb, unsigned long event, void *ptr) 2134 { 2135 struct super_block *sb = ptr; 2136 struct net *net = sb->s_fs_info; 2137 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 2138 struct cld_net *cn = nn->cld_net; 2139 struct dentry *dentry; 2140 int ret = 0; 2141 2142 if (!try_module_get(THIS_MODULE)) 2143 return 0; 2144 2145 if (!cn) { 2146 module_put(THIS_MODULE); 2147 return 0; 2148 } 2149 2150 switch (event) { 2151 case RPC_PIPEFS_MOUNT: 2152 dentry = nfsd4_cld_register_sb(sb, cn->cn_pipe); 2153 if (IS_ERR(dentry)) { 2154 ret = PTR_ERR(dentry); 2155 break; 2156 } 2157 cn->cn_pipe->dentry = dentry; 2158 break; 2159 case RPC_PIPEFS_UMOUNT: 2160 if (cn->cn_pipe->dentry) 2161 nfsd4_cld_unregister_sb(cn->cn_pipe); 2162 break; 2163 default: 2164 ret = -ENOTSUPP; 2165 break; 2166 } 2167 module_put(THIS_MODULE); 2168 return ret; 2169 } 2170 2171 static struct notifier_block nfsd4_cld_block = { 2172 .notifier_call = rpc_pipefs_event, 2173 }; 2174 2175 int 2176 register_cld_notifier(void) 2177 { 2178 return rpc_pipefs_notifier_register(&nfsd4_cld_block); 2179 } 2180 2181 void 2182 unregister_cld_notifier(void) 2183 { 2184 rpc_pipefs_notifier_unregister(&nfsd4_cld_block); 2185 } 2186