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 <linux/file.h> 36 #include <linux/slab.h> 37 #include <linux/namei.h> 38 #include <linux/crypto.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 }; 63 64 /* Globals */ 65 static char user_recovery_dirname[PATH_MAX] = "/var/lib/nfs/v4recovery"; 66 67 static int 68 nfs4_save_creds(const struct cred **original_creds) 69 { 70 struct cred *new; 71 72 new = prepare_creds(); 73 if (!new) 74 return -ENOMEM; 75 76 new->fsuid = GLOBAL_ROOT_UID; 77 new->fsgid = GLOBAL_ROOT_GID; 78 *original_creds = override_creds(new); 79 put_cred(new); 80 return 0; 81 } 82 83 static void 84 nfs4_reset_creds(const struct cred *original) 85 { 86 revert_creds(original); 87 } 88 89 static void 90 md5_to_hex(char *out, char *md5) 91 { 92 int i; 93 94 for (i=0; i<16; i++) { 95 unsigned char c = md5[i]; 96 97 *out++ = '0' + ((c&0xf0)>>4) + (c>=0xa0)*('a'-'9'-1); 98 *out++ = '0' + (c&0x0f) + ((c&0x0f)>=0x0a)*('a'-'9'-1); 99 } 100 *out = '\0'; 101 } 102 103 static int 104 nfs4_make_rec_clidname(char *dname, const struct xdr_netobj *clname) 105 { 106 struct xdr_netobj cksum; 107 struct hash_desc desc; 108 struct scatterlist sg; 109 int status; 110 111 dprintk("NFSD: nfs4_make_rec_clidname for %.*s\n", 112 clname->len, clname->data); 113 desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP; 114 desc.tfm = crypto_alloc_hash("md5", 0, CRYPTO_ALG_ASYNC); 115 if (IS_ERR(desc.tfm)) { 116 status = PTR_ERR(desc.tfm); 117 goto out_no_tfm; 118 } 119 120 cksum.len = crypto_hash_digestsize(desc.tfm); 121 cksum.data = kmalloc(cksum.len, GFP_KERNEL); 122 if (cksum.data == NULL) { 123 status = -ENOMEM; 124 goto out; 125 } 126 127 sg_init_one(&sg, clname->data, clname->len); 128 129 status = crypto_hash_digest(&desc, &sg, sg.length, cksum.data); 130 if (status) 131 goto out; 132 133 md5_to_hex(dname, cksum.data); 134 135 status = 0; 136 out: 137 kfree(cksum.data); 138 crypto_free_hash(desc.tfm); 139 out_no_tfm: 140 return status; 141 } 142 143 /* 144 * If we had an error generating the recdir name for the legacy tracker 145 * then warn the admin. If the error doesn't appear to be transient, 146 * then disable recovery tracking. 147 */ 148 static void 149 legacy_recdir_name_error(struct nfs4_client *clp, int error) 150 { 151 printk(KERN_ERR "NFSD: unable to generate recoverydir " 152 "name (%d).\n", error); 153 154 /* 155 * if the algorithm just doesn't exist, then disable the recovery 156 * tracker altogether. The crypto libs will generally return this if 157 * FIPS is enabled as well. 158 */ 159 if (error == -ENOENT) { 160 printk(KERN_ERR "NFSD: disabling legacy clientid tracking. " 161 "Reboot recovery will not function correctly!\n"); 162 nfsd4_client_tracking_exit(clp->net); 163 } 164 } 165 166 static void 167 nfsd4_create_clid_dir(struct nfs4_client *clp) 168 { 169 const struct cred *original_cred; 170 char dname[HEXDIR_LEN]; 171 struct dentry *dir, *dentry; 172 struct nfs4_client_reclaim *crp; 173 int status; 174 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 175 176 if (test_and_set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 177 return; 178 if (!nn->rec_file) 179 return; 180 181 status = nfs4_make_rec_clidname(dname, &clp->cl_name); 182 if (status) 183 return legacy_recdir_name_error(clp, status); 184 185 status = nfs4_save_creds(&original_cred); 186 if (status < 0) 187 return; 188 189 status = mnt_want_write_file(nn->rec_file); 190 if (status) 191 goto out_creds; 192 193 dir = nn->rec_file->f_path.dentry; 194 /* lock the parent */ 195 mutex_lock(&d_inode(dir)->i_mutex); 196 197 dentry = lookup_one_len(dname, dir, HEXDIR_LEN-1); 198 if (IS_ERR(dentry)) { 199 status = PTR_ERR(dentry); 200 goto out_unlock; 201 } 202 if (d_really_is_positive(dentry)) 203 /* 204 * In the 4.1 case, where we're called from 205 * reclaim_complete(), records from the previous reboot 206 * may still be left, so this is OK. 207 * 208 * In the 4.0 case, we should never get here; but we may 209 * as well be forgiving and just succeed silently. 210 */ 211 goto out_put; 212 status = vfs_mkdir(d_inode(dir), dentry, S_IRWXU); 213 out_put: 214 dput(dentry); 215 out_unlock: 216 mutex_unlock(&d_inode(dir)->i_mutex); 217 if (status == 0) { 218 if (nn->in_grace) { 219 crp = nfs4_client_to_reclaim(dname, nn); 220 if (crp) 221 crp->cr_clp = clp; 222 } 223 vfs_fsync(nn->rec_file, 0); 224 } else { 225 printk(KERN_ERR "NFSD: failed to write recovery record" 226 " (err %d); please check that %s exists" 227 " and is writeable", status, 228 user_recovery_dirname); 229 } 230 mnt_drop_write_file(nn->rec_file); 231 out_creds: 232 nfs4_reset_creds(original_cred); 233 } 234 235 typedef int (recdir_func)(struct dentry *, struct dentry *, struct nfsd_net *); 236 237 struct name_list { 238 char name[HEXDIR_LEN]; 239 struct list_head list; 240 }; 241 242 struct nfs4_dir_ctx { 243 struct dir_context ctx; 244 struct list_head names; 245 }; 246 247 static int 248 nfsd4_build_namelist(struct dir_context *__ctx, const char *name, int namlen, 249 loff_t offset, u64 ino, unsigned int d_type) 250 { 251 struct nfs4_dir_ctx *ctx = 252 container_of(__ctx, struct nfs4_dir_ctx, ctx); 253 struct name_list *entry; 254 255 if (namlen != HEXDIR_LEN - 1) 256 return 0; 257 entry = kmalloc(sizeof(struct name_list), GFP_KERNEL); 258 if (entry == NULL) 259 return -ENOMEM; 260 memcpy(entry->name, name, HEXDIR_LEN - 1); 261 entry->name[HEXDIR_LEN - 1] = '\0'; 262 list_add(&entry->list, &ctx->names); 263 return 0; 264 } 265 266 static int 267 nfsd4_list_rec_dir(recdir_func *f, struct nfsd_net *nn) 268 { 269 const struct cred *original_cred; 270 struct dentry *dir = nn->rec_file->f_path.dentry; 271 struct nfs4_dir_ctx ctx = { 272 .ctx.actor = nfsd4_build_namelist, 273 .names = LIST_HEAD_INIT(ctx.names) 274 }; 275 struct name_list *entry, *tmp; 276 int status; 277 278 status = nfs4_save_creds(&original_cred); 279 if (status < 0) 280 return status; 281 282 status = vfs_llseek(nn->rec_file, 0, SEEK_SET); 283 if (status < 0) { 284 nfs4_reset_creds(original_cred); 285 return status; 286 } 287 288 status = iterate_dir(nn->rec_file, &ctx.ctx); 289 mutex_lock_nested(&d_inode(dir)->i_mutex, I_MUTEX_PARENT); 290 291 list_for_each_entry_safe(entry, tmp, &ctx.names, list) { 292 if (!status) { 293 struct dentry *dentry; 294 dentry = lookup_one_len(entry->name, dir, HEXDIR_LEN-1); 295 if (IS_ERR(dentry)) { 296 status = PTR_ERR(dentry); 297 break; 298 } 299 status = f(dir, dentry, nn); 300 dput(dentry); 301 } 302 list_del(&entry->list); 303 kfree(entry); 304 } 305 mutex_unlock(&d_inode(dir)->i_mutex); 306 nfs4_reset_creds(original_cred); 307 308 list_for_each_entry_safe(entry, tmp, &ctx.names, list) { 309 dprintk("NFSD: %s. Left entry %s\n", __func__, entry->name); 310 list_del(&entry->list); 311 kfree(entry); 312 } 313 return status; 314 } 315 316 static int 317 nfsd4_unlink_clid_dir(char *name, int namlen, struct nfsd_net *nn) 318 { 319 struct dentry *dir, *dentry; 320 int status; 321 322 dprintk("NFSD: nfsd4_unlink_clid_dir. name %.*s\n", namlen, name); 323 324 dir = nn->rec_file->f_path.dentry; 325 mutex_lock_nested(&d_inode(dir)->i_mutex, I_MUTEX_PARENT); 326 dentry = lookup_one_len(name, dir, namlen); 327 if (IS_ERR(dentry)) { 328 status = PTR_ERR(dentry); 329 goto out_unlock; 330 } 331 status = -ENOENT; 332 if (d_really_is_negative(dentry)) 333 goto out; 334 status = vfs_rmdir(d_inode(dir), dentry); 335 out: 336 dput(dentry); 337 out_unlock: 338 mutex_unlock(&d_inode(dir)->i_mutex); 339 return status; 340 } 341 342 static void 343 nfsd4_remove_clid_dir(struct nfs4_client *clp) 344 { 345 const struct cred *original_cred; 346 struct nfs4_client_reclaim *crp; 347 char dname[HEXDIR_LEN]; 348 int status; 349 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 350 351 if (!nn->rec_file || !test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 352 return; 353 354 status = nfs4_make_rec_clidname(dname, &clp->cl_name); 355 if (status) 356 return legacy_recdir_name_error(clp, status); 357 358 status = mnt_want_write_file(nn->rec_file); 359 if (status) 360 goto out; 361 clear_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); 362 363 status = nfs4_save_creds(&original_cred); 364 if (status < 0) 365 goto out_drop_write; 366 367 status = nfsd4_unlink_clid_dir(dname, HEXDIR_LEN-1, nn); 368 nfs4_reset_creds(original_cred); 369 if (status == 0) { 370 vfs_fsync(nn->rec_file, 0); 371 if (nn->in_grace) { 372 /* remove reclaim record */ 373 crp = nfsd4_find_reclaim_client(dname, nn); 374 if (crp) 375 nfs4_remove_reclaim_record(crp, nn); 376 } 377 } 378 out_drop_write: 379 mnt_drop_write_file(nn->rec_file); 380 out: 381 if (status) 382 printk("NFSD: Failed to remove expired client state directory" 383 " %.*s\n", HEXDIR_LEN, dname); 384 } 385 386 static int 387 purge_old(struct dentry *parent, struct dentry *child, struct nfsd_net *nn) 388 { 389 int status; 390 391 if (nfs4_has_reclaimed_state(child->d_name.name, nn)) 392 return 0; 393 394 status = vfs_rmdir(d_inode(parent), child); 395 if (status) 396 printk("failed to remove client recovery directory %pd\n", 397 child); 398 /* Keep trying, success or failure: */ 399 return 0; 400 } 401 402 static void 403 nfsd4_recdir_purge_old(struct nfsd_net *nn) 404 { 405 int status; 406 407 nn->in_grace = false; 408 if (!nn->rec_file) 409 return; 410 status = mnt_want_write_file(nn->rec_file); 411 if (status) 412 goto out; 413 status = nfsd4_list_rec_dir(purge_old, nn); 414 if (status == 0) 415 vfs_fsync(nn->rec_file, 0); 416 mnt_drop_write_file(nn->rec_file); 417 out: 418 nfs4_release_reclaim(nn); 419 if (status) 420 printk("nfsd4: failed to purge old clients from recovery" 421 " directory %pD\n", nn->rec_file); 422 } 423 424 static int 425 load_recdir(struct dentry *parent, struct dentry *child, struct nfsd_net *nn) 426 { 427 if (child->d_name.len != HEXDIR_LEN - 1) { 428 printk("nfsd4: illegal name %pd in recovery directory\n", 429 child); 430 /* Keep trying; maybe the others are OK: */ 431 return 0; 432 } 433 nfs4_client_to_reclaim(child->d_name.name, nn); 434 return 0; 435 } 436 437 static int 438 nfsd4_recdir_load(struct net *net) { 439 int status; 440 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 441 442 if (!nn->rec_file) 443 return 0; 444 445 status = nfsd4_list_rec_dir(load_recdir, nn); 446 if (status) 447 printk("nfsd4: failed loading clients from recovery" 448 " directory %pD\n", nn->rec_file); 449 return status; 450 } 451 452 /* 453 * Hold reference to the recovery directory. 454 */ 455 456 static int 457 nfsd4_init_recdir(struct net *net) 458 { 459 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 460 const struct cred *original_cred; 461 int status; 462 463 printk("NFSD: Using %s as the NFSv4 state recovery directory\n", 464 user_recovery_dirname); 465 466 BUG_ON(nn->rec_file); 467 468 status = nfs4_save_creds(&original_cred); 469 if (status < 0) { 470 printk("NFSD: Unable to change credentials to find recovery" 471 " directory: error %d\n", 472 status); 473 return status; 474 } 475 476 nn->rec_file = filp_open(user_recovery_dirname, O_RDONLY | O_DIRECTORY, 0); 477 if (IS_ERR(nn->rec_file)) { 478 printk("NFSD: unable to find recovery directory %s\n", 479 user_recovery_dirname); 480 status = PTR_ERR(nn->rec_file); 481 nn->rec_file = NULL; 482 } 483 484 nfs4_reset_creds(original_cred); 485 if (!status) 486 nn->in_grace = true; 487 return status; 488 } 489 490 static void 491 nfsd4_shutdown_recdir(struct net *net) 492 { 493 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 494 495 if (!nn->rec_file) 496 return; 497 fput(nn->rec_file); 498 nn->rec_file = NULL; 499 } 500 501 static int 502 nfs4_legacy_state_init(struct net *net) 503 { 504 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 505 int i; 506 507 nn->reclaim_str_hashtbl = kmalloc(sizeof(struct list_head) * 508 CLIENT_HASH_SIZE, GFP_KERNEL); 509 if (!nn->reclaim_str_hashtbl) 510 return -ENOMEM; 511 512 for (i = 0; i < CLIENT_HASH_SIZE; i++) 513 INIT_LIST_HEAD(&nn->reclaim_str_hashtbl[i]); 514 nn->reclaim_str_hashtbl_size = 0; 515 516 return 0; 517 } 518 519 static void 520 nfs4_legacy_state_shutdown(struct net *net) 521 { 522 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 523 524 kfree(nn->reclaim_str_hashtbl); 525 } 526 527 static int 528 nfsd4_load_reboot_recovery_data(struct net *net) 529 { 530 int status; 531 532 status = nfsd4_init_recdir(net); 533 if (status) 534 return status; 535 536 status = nfsd4_recdir_load(net); 537 if (status) 538 nfsd4_shutdown_recdir(net); 539 540 return status; 541 } 542 543 static int 544 nfsd4_legacy_tracking_init(struct net *net) 545 { 546 int status; 547 548 /* XXX: The legacy code won't work in a container */ 549 if (net != &init_net) { 550 pr_warn("NFSD: attempt to initialize legacy client tracking in a container ignored.\n"); 551 return -EINVAL; 552 } 553 554 status = nfs4_legacy_state_init(net); 555 if (status) 556 return status; 557 558 status = nfsd4_load_reboot_recovery_data(net); 559 if (status) 560 goto err; 561 return 0; 562 563 err: 564 nfs4_legacy_state_shutdown(net); 565 return status; 566 } 567 568 static void 569 nfsd4_legacy_tracking_exit(struct net *net) 570 { 571 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 572 573 nfs4_release_reclaim(nn); 574 nfsd4_shutdown_recdir(net); 575 nfs4_legacy_state_shutdown(net); 576 } 577 578 /* 579 * Change the NFSv4 recovery directory to recdir. 580 */ 581 int 582 nfs4_reset_recoverydir(char *recdir) 583 { 584 int status; 585 struct path path; 586 587 status = kern_path(recdir, LOOKUP_FOLLOW, &path); 588 if (status) 589 return status; 590 status = -ENOTDIR; 591 if (d_is_dir(path.dentry)) { 592 strcpy(user_recovery_dirname, recdir); 593 status = 0; 594 } 595 path_put(&path); 596 return status; 597 } 598 599 char * 600 nfs4_recoverydir(void) 601 { 602 return user_recovery_dirname; 603 } 604 605 static int 606 nfsd4_check_legacy_client(struct nfs4_client *clp) 607 { 608 int status; 609 char dname[HEXDIR_LEN]; 610 struct nfs4_client_reclaim *crp; 611 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 612 613 /* did we already find that this client is stable? */ 614 if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 615 return 0; 616 617 status = nfs4_make_rec_clidname(dname, &clp->cl_name); 618 if (status) { 619 legacy_recdir_name_error(clp, status); 620 return status; 621 } 622 623 /* look for it in the reclaim hashtable otherwise */ 624 crp = nfsd4_find_reclaim_client(dname, nn); 625 if (crp) { 626 set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); 627 crp->cr_clp = clp; 628 return 0; 629 } 630 631 return -ENOENT; 632 } 633 634 static struct nfsd4_client_tracking_ops nfsd4_legacy_tracking_ops = { 635 .init = nfsd4_legacy_tracking_init, 636 .exit = nfsd4_legacy_tracking_exit, 637 .create = nfsd4_create_clid_dir, 638 .remove = nfsd4_remove_clid_dir, 639 .check = nfsd4_check_legacy_client, 640 .grace_done = nfsd4_recdir_purge_old, 641 }; 642 643 /* Globals */ 644 #define NFSD_PIPE_DIR "nfsd" 645 #define NFSD_CLD_PIPE "cld" 646 647 /* per-net-ns structure for holding cld upcall info */ 648 struct cld_net { 649 struct rpc_pipe *cn_pipe; 650 spinlock_t cn_lock; 651 struct list_head cn_list; 652 unsigned int cn_xid; 653 }; 654 655 struct cld_upcall { 656 struct list_head cu_list; 657 struct cld_net *cu_net; 658 struct task_struct *cu_task; 659 struct cld_msg cu_msg; 660 }; 661 662 static int 663 __cld_pipe_upcall(struct rpc_pipe *pipe, struct cld_msg *cmsg) 664 { 665 int ret; 666 struct rpc_pipe_msg msg; 667 668 memset(&msg, 0, sizeof(msg)); 669 msg.data = cmsg; 670 msg.len = sizeof(*cmsg); 671 672 /* 673 * Set task state before we queue the upcall. That prevents 674 * wake_up_process in the downcall from racing with schedule. 675 */ 676 set_current_state(TASK_UNINTERRUPTIBLE); 677 ret = rpc_queue_upcall(pipe, &msg); 678 if (ret < 0) { 679 set_current_state(TASK_RUNNING); 680 goto out; 681 } 682 683 schedule(); 684 685 if (msg.errno < 0) 686 ret = msg.errno; 687 out: 688 return ret; 689 } 690 691 static int 692 cld_pipe_upcall(struct rpc_pipe *pipe, struct cld_msg *cmsg) 693 { 694 int ret; 695 696 /* 697 * -EAGAIN occurs when pipe is closed and reopened while there are 698 * upcalls queued. 699 */ 700 do { 701 ret = __cld_pipe_upcall(pipe, cmsg); 702 } while (ret == -EAGAIN); 703 704 return ret; 705 } 706 707 static ssize_t 708 cld_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) 709 { 710 struct cld_upcall *tmp, *cup; 711 struct cld_msg __user *cmsg = (struct cld_msg __user *)src; 712 uint32_t xid; 713 struct nfsd_net *nn = net_generic(file_inode(filp)->i_sb->s_fs_info, 714 nfsd_net_id); 715 struct cld_net *cn = nn->cld_net; 716 717 if (mlen != sizeof(*cmsg)) { 718 dprintk("%s: got %zu bytes, expected %zu\n", __func__, mlen, 719 sizeof(*cmsg)); 720 return -EINVAL; 721 } 722 723 /* copy just the xid so we can try to find that */ 724 if (copy_from_user(&xid, &cmsg->cm_xid, sizeof(xid)) != 0) { 725 dprintk("%s: error when copying xid from userspace", __func__); 726 return -EFAULT; 727 } 728 729 /* walk the list and find corresponding xid */ 730 cup = NULL; 731 spin_lock(&cn->cn_lock); 732 list_for_each_entry(tmp, &cn->cn_list, cu_list) { 733 if (get_unaligned(&tmp->cu_msg.cm_xid) == xid) { 734 cup = tmp; 735 list_del_init(&cup->cu_list); 736 break; 737 } 738 } 739 spin_unlock(&cn->cn_lock); 740 741 /* couldn't find upcall? */ 742 if (!cup) { 743 dprintk("%s: couldn't find upcall -- xid=%u\n", __func__, xid); 744 return -EINVAL; 745 } 746 747 if (copy_from_user(&cup->cu_msg, src, mlen) != 0) 748 return -EFAULT; 749 750 wake_up_process(cup->cu_task); 751 return mlen; 752 } 753 754 static void 755 cld_pipe_destroy_msg(struct rpc_pipe_msg *msg) 756 { 757 struct cld_msg *cmsg = msg->data; 758 struct cld_upcall *cup = container_of(cmsg, struct cld_upcall, 759 cu_msg); 760 761 /* errno >= 0 means we got a downcall */ 762 if (msg->errno >= 0) 763 return; 764 765 wake_up_process(cup->cu_task); 766 } 767 768 static const struct rpc_pipe_ops cld_upcall_ops = { 769 .upcall = rpc_pipe_generic_upcall, 770 .downcall = cld_pipe_downcall, 771 .destroy_msg = cld_pipe_destroy_msg, 772 }; 773 774 static struct dentry * 775 nfsd4_cld_register_sb(struct super_block *sb, struct rpc_pipe *pipe) 776 { 777 struct dentry *dir, *dentry; 778 779 dir = rpc_d_lookup_sb(sb, NFSD_PIPE_DIR); 780 if (dir == NULL) 781 return ERR_PTR(-ENOENT); 782 dentry = rpc_mkpipe_dentry(dir, NFSD_CLD_PIPE, NULL, pipe); 783 dput(dir); 784 return dentry; 785 } 786 787 static void 788 nfsd4_cld_unregister_sb(struct rpc_pipe *pipe) 789 { 790 if (pipe->dentry) 791 rpc_unlink(pipe->dentry); 792 } 793 794 static struct dentry * 795 nfsd4_cld_register_net(struct net *net, struct rpc_pipe *pipe) 796 { 797 struct super_block *sb; 798 struct dentry *dentry; 799 800 sb = rpc_get_sb_net(net); 801 if (!sb) 802 return NULL; 803 dentry = nfsd4_cld_register_sb(sb, pipe); 804 rpc_put_sb_net(net); 805 return dentry; 806 } 807 808 static void 809 nfsd4_cld_unregister_net(struct net *net, struct rpc_pipe *pipe) 810 { 811 struct super_block *sb; 812 813 sb = rpc_get_sb_net(net); 814 if (sb) { 815 nfsd4_cld_unregister_sb(pipe); 816 rpc_put_sb_net(net); 817 } 818 } 819 820 /* Initialize rpc_pipefs pipe for communication with client tracking daemon */ 821 static int 822 nfsd4_init_cld_pipe(struct net *net) 823 { 824 int ret; 825 struct dentry *dentry; 826 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 827 struct cld_net *cn; 828 829 if (nn->cld_net) 830 return 0; 831 832 cn = kzalloc(sizeof(*cn), GFP_KERNEL); 833 if (!cn) { 834 ret = -ENOMEM; 835 goto err; 836 } 837 838 cn->cn_pipe = rpc_mkpipe_data(&cld_upcall_ops, RPC_PIPE_WAIT_FOR_OPEN); 839 if (IS_ERR(cn->cn_pipe)) { 840 ret = PTR_ERR(cn->cn_pipe); 841 goto err; 842 } 843 spin_lock_init(&cn->cn_lock); 844 INIT_LIST_HEAD(&cn->cn_list); 845 846 dentry = nfsd4_cld_register_net(net, cn->cn_pipe); 847 if (IS_ERR(dentry)) { 848 ret = PTR_ERR(dentry); 849 goto err_destroy_data; 850 } 851 852 cn->cn_pipe->dentry = dentry; 853 nn->cld_net = cn; 854 return 0; 855 856 err_destroy_data: 857 rpc_destroy_pipe_data(cn->cn_pipe); 858 err: 859 kfree(cn); 860 printk(KERN_ERR "NFSD: unable to create nfsdcld upcall pipe (%d)\n", 861 ret); 862 return ret; 863 } 864 865 static void 866 nfsd4_remove_cld_pipe(struct net *net) 867 { 868 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 869 struct cld_net *cn = nn->cld_net; 870 871 nfsd4_cld_unregister_net(net, cn->cn_pipe); 872 rpc_destroy_pipe_data(cn->cn_pipe); 873 kfree(nn->cld_net); 874 nn->cld_net = NULL; 875 } 876 877 static struct cld_upcall * 878 alloc_cld_upcall(struct cld_net *cn) 879 { 880 struct cld_upcall *new, *tmp; 881 882 new = kzalloc(sizeof(*new), GFP_KERNEL); 883 if (!new) 884 return new; 885 886 /* FIXME: hard cap on number in flight? */ 887 restart_search: 888 spin_lock(&cn->cn_lock); 889 list_for_each_entry(tmp, &cn->cn_list, cu_list) { 890 if (tmp->cu_msg.cm_xid == cn->cn_xid) { 891 cn->cn_xid++; 892 spin_unlock(&cn->cn_lock); 893 goto restart_search; 894 } 895 } 896 new->cu_task = current; 897 new->cu_msg.cm_vers = CLD_UPCALL_VERSION; 898 put_unaligned(cn->cn_xid++, &new->cu_msg.cm_xid); 899 new->cu_net = cn; 900 list_add(&new->cu_list, &cn->cn_list); 901 spin_unlock(&cn->cn_lock); 902 903 dprintk("%s: allocated xid %u\n", __func__, new->cu_msg.cm_xid); 904 905 return new; 906 } 907 908 static void 909 free_cld_upcall(struct cld_upcall *victim) 910 { 911 struct cld_net *cn = victim->cu_net; 912 913 spin_lock(&cn->cn_lock); 914 list_del(&victim->cu_list); 915 spin_unlock(&cn->cn_lock); 916 kfree(victim); 917 } 918 919 /* Ask daemon to create a new record */ 920 static void 921 nfsd4_cld_create(struct nfs4_client *clp) 922 { 923 int ret; 924 struct cld_upcall *cup; 925 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 926 struct cld_net *cn = nn->cld_net; 927 928 /* Don't upcall if it's already stored */ 929 if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 930 return; 931 932 cup = alloc_cld_upcall(cn); 933 if (!cup) { 934 ret = -ENOMEM; 935 goto out_err; 936 } 937 938 cup->cu_msg.cm_cmd = Cld_Create; 939 cup->cu_msg.cm_u.cm_name.cn_len = clp->cl_name.len; 940 memcpy(cup->cu_msg.cm_u.cm_name.cn_id, clp->cl_name.data, 941 clp->cl_name.len); 942 943 ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_msg); 944 if (!ret) { 945 ret = cup->cu_msg.cm_status; 946 set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); 947 } 948 949 free_cld_upcall(cup); 950 out_err: 951 if (ret) 952 printk(KERN_ERR "NFSD: Unable to create client " 953 "record on stable storage: %d\n", ret); 954 } 955 956 /* Ask daemon to create a new record */ 957 static void 958 nfsd4_cld_remove(struct nfs4_client *clp) 959 { 960 int ret; 961 struct cld_upcall *cup; 962 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 963 struct cld_net *cn = nn->cld_net; 964 965 /* Don't upcall if it's already removed */ 966 if (!test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 967 return; 968 969 cup = alloc_cld_upcall(cn); 970 if (!cup) { 971 ret = -ENOMEM; 972 goto out_err; 973 } 974 975 cup->cu_msg.cm_cmd = Cld_Remove; 976 cup->cu_msg.cm_u.cm_name.cn_len = clp->cl_name.len; 977 memcpy(cup->cu_msg.cm_u.cm_name.cn_id, clp->cl_name.data, 978 clp->cl_name.len); 979 980 ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_msg); 981 if (!ret) { 982 ret = cup->cu_msg.cm_status; 983 clear_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); 984 } 985 986 free_cld_upcall(cup); 987 out_err: 988 if (ret) 989 printk(KERN_ERR "NFSD: Unable to remove client " 990 "record from stable storage: %d\n", ret); 991 } 992 993 /* Check for presence of a record, and update its timestamp */ 994 static int 995 nfsd4_cld_check(struct nfs4_client *clp) 996 { 997 int ret; 998 struct cld_upcall *cup; 999 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 1000 struct cld_net *cn = nn->cld_net; 1001 1002 /* Don't upcall if one was already stored during this grace pd */ 1003 if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 1004 return 0; 1005 1006 cup = alloc_cld_upcall(cn); 1007 if (!cup) { 1008 printk(KERN_ERR "NFSD: Unable to check client record on " 1009 "stable storage: %d\n", -ENOMEM); 1010 return -ENOMEM; 1011 } 1012 1013 cup->cu_msg.cm_cmd = Cld_Check; 1014 cup->cu_msg.cm_u.cm_name.cn_len = clp->cl_name.len; 1015 memcpy(cup->cu_msg.cm_u.cm_name.cn_id, clp->cl_name.data, 1016 clp->cl_name.len); 1017 1018 ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_msg); 1019 if (!ret) { 1020 ret = cup->cu_msg.cm_status; 1021 set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); 1022 } 1023 1024 free_cld_upcall(cup); 1025 return ret; 1026 } 1027 1028 static void 1029 nfsd4_cld_grace_done(struct nfsd_net *nn) 1030 { 1031 int ret; 1032 struct cld_upcall *cup; 1033 struct cld_net *cn = nn->cld_net; 1034 1035 cup = alloc_cld_upcall(cn); 1036 if (!cup) { 1037 ret = -ENOMEM; 1038 goto out_err; 1039 } 1040 1041 cup->cu_msg.cm_cmd = Cld_GraceDone; 1042 cup->cu_msg.cm_u.cm_gracetime = (int64_t)nn->boot_time; 1043 ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_msg); 1044 if (!ret) 1045 ret = cup->cu_msg.cm_status; 1046 1047 free_cld_upcall(cup); 1048 out_err: 1049 if (ret) 1050 printk(KERN_ERR "NFSD: Unable to end grace period: %d\n", ret); 1051 } 1052 1053 static struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops = { 1054 .init = nfsd4_init_cld_pipe, 1055 .exit = nfsd4_remove_cld_pipe, 1056 .create = nfsd4_cld_create, 1057 .remove = nfsd4_cld_remove, 1058 .check = nfsd4_cld_check, 1059 .grace_done = nfsd4_cld_grace_done, 1060 }; 1061 1062 /* upcall via usermodehelper */ 1063 static char cltrack_prog[PATH_MAX] = "/sbin/nfsdcltrack"; 1064 module_param_string(cltrack_prog, cltrack_prog, sizeof(cltrack_prog), 1065 S_IRUGO|S_IWUSR); 1066 MODULE_PARM_DESC(cltrack_prog, "Path to the nfsdcltrack upcall program"); 1067 1068 static bool cltrack_legacy_disable; 1069 module_param(cltrack_legacy_disable, bool, S_IRUGO|S_IWUSR); 1070 MODULE_PARM_DESC(cltrack_legacy_disable, 1071 "Disable legacy recoverydir conversion. Default: false"); 1072 1073 #define LEGACY_TOPDIR_ENV_PREFIX "NFSDCLTRACK_LEGACY_TOPDIR=" 1074 #define LEGACY_RECDIR_ENV_PREFIX "NFSDCLTRACK_LEGACY_RECDIR=" 1075 #define HAS_SESSION_ENV_PREFIX "NFSDCLTRACK_CLIENT_HAS_SESSION=" 1076 #define GRACE_START_ENV_PREFIX "NFSDCLTRACK_GRACE_START=" 1077 1078 static char * 1079 nfsd4_cltrack_legacy_topdir(void) 1080 { 1081 int copied; 1082 size_t len; 1083 char *result; 1084 1085 if (cltrack_legacy_disable) 1086 return NULL; 1087 1088 len = strlen(LEGACY_TOPDIR_ENV_PREFIX) + 1089 strlen(nfs4_recoverydir()) + 1; 1090 1091 result = kmalloc(len, GFP_KERNEL); 1092 if (!result) 1093 return result; 1094 1095 copied = snprintf(result, len, LEGACY_TOPDIR_ENV_PREFIX "%s", 1096 nfs4_recoverydir()); 1097 if (copied >= len) { 1098 /* just return nothing if output was truncated */ 1099 kfree(result); 1100 return NULL; 1101 } 1102 1103 return result; 1104 } 1105 1106 static char * 1107 nfsd4_cltrack_legacy_recdir(const struct xdr_netobj *name) 1108 { 1109 int copied; 1110 size_t len; 1111 char *result; 1112 1113 if (cltrack_legacy_disable) 1114 return NULL; 1115 1116 /* +1 is for '/' between "topdir" and "recdir" */ 1117 len = strlen(LEGACY_RECDIR_ENV_PREFIX) + 1118 strlen(nfs4_recoverydir()) + 1 + HEXDIR_LEN; 1119 1120 result = kmalloc(len, GFP_KERNEL); 1121 if (!result) 1122 return result; 1123 1124 copied = snprintf(result, len, LEGACY_RECDIR_ENV_PREFIX "%s/", 1125 nfs4_recoverydir()); 1126 if (copied > (len - HEXDIR_LEN)) { 1127 /* just return nothing if output will be truncated */ 1128 kfree(result); 1129 return NULL; 1130 } 1131 1132 copied = nfs4_make_rec_clidname(result + copied, name); 1133 if (copied) { 1134 kfree(result); 1135 return NULL; 1136 } 1137 1138 return result; 1139 } 1140 1141 static char * 1142 nfsd4_cltrack_client_has_session(struct nfs4_client *clp) 1143 { 1144 int copied; 1145 size_t len; 1146 char *result; 1147 1148 /* prefix + Y/N character + terminating NULL */ 1149 len = strlen(HAS_SESSION_ENV_PREFIX) + 1 + 1; 1150 1151 result = kmalloc(len, GFP_KERNEL); 1152 if (!result) 1153 return result; 1154 1155 copied = snprintf(result, len, HAS_SESSION_ENV_PREFIX "%c", 1156 clp->cl_minorversion ? 'Y' : 'N'); 1157 if (copied >= len) { 1158 /* just return nothing if output was truncated */ 1159 kfree(result); 1160 return NULL; 1161 } 1162 1163 return result; 1164 } 1165 1166 static char * 1167 nfsd4_cltrack_grace_start(time_t grace_start) 1168 { 1169 int copied; 1170 size_t len; 1171 char *result; 1172 1173 /* prefix + max width of int64_t string + terminating NULL */ 1174 len = strlen(GRACE_START_ENV_PREFIX) + 22 + 1; 1175 1176 result = kmalloc(len, GFP_KERNEL); 1177 if (!result) 1178 return result; 1179 1180 copied = snprintf(result, len, GRACE_START_ENV_PREFIX "%ld", 1181 grace_start); 1182 if (copied >= len) { 1183 /* just return nothing if output was truncated */ 1184 kfree(result); 1185 return NULL; 1186 } 1187 1188 return result; 1189 } 1190 1191 static int 1192 nfsd4_umh_cltrack_upcall(char *cmd, char *arg, char *env0, char *env1) 1193 { 1194 char *envp[3]; 1195 char *argv[4]; 1196 int ret; 1197 1198 if (unlikely(!cltrack_prog[0])) { 1199 dprintk("%s: cltrack_prog is disabled\n", __func__); 1200 return -EACCES; 1201 } 1202 1203 dprintk("%s: cmd: %s\n", __func__, cmd); 1204 dprintk("%s: arg: %s\n", __func__, arg ? arg : "(null)"); 1205 dprintk("%s: env0: %s\n", __func__, env0 ? env0 : "(null)"); 1206 dprintk("%s: env1: %s\n", __func__, env1 ? env1 : "(null)"); 1207 1208 envp[0] = env0; 1209 envp[1] = env1; 1210 envp[2] = NULL; 1211 1212 argv[0] = (char *)cltrack_prog; 1213 argv[1] = cmd; 1214 argv[2] = arg; 1215 argv[3] = NULL; 1216 1217 ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC); 1218 /* 1219 * Disable the upcall mechanism if we're getting an ENOENT or EACCES 1220 * error. The admin can re-enable it on the fly by using sysfs 1221 * once the problem has been fixed. 1222 */ 1223 if (ret == -ENOENT || ret == -EACCES) { 1224 dprintk("NFSD: %s was not found or isn't executable (%d). " 1225 "Setting cltrack_prog to blank string!", 1226 cltrack_prog, ret); 1227 cltrack_prog[0] = '\0'; 1228 } 1229 dprintk("%s: %s return value: %d\n", __func__, cltrack_prog, ret); 1230 1231 return ret; 1232 } 1233 1234 static char * 1235 bin_to_hex_dup(const unsigned char *src, int srclen) 1236 { 1237 int i; 1238 char *buf, *hex; 1239 1240 /* +1 for terminating NULL */ 1241 buf = kmalloc((srclen * 2) + 1, GFP_KERNEL); 1242 if (!buf) 1243 return buf; 1244 1245 hex = buf; 1246 for (i = 0; i < srclen; i++) { 1247 sprintf(hex, "%2.2x", *src++); 1248 hex += 2; 1249 } 1250 return buf; 1251 } 1252 1253 static int 1254 nfsd4_umh_cltrack_init(struct net *net) 1255 { 1256 int ret; 1257 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 1258 char *grace_start = nfsd4_cltrack_grace_start(nn->boot_time); 1259 1260 /* XXX: The usermode helper s not working in container yet. */ 1261 if (net != &init_net) { 1262 pr_warn("NFSD: attempt to initialize umh client tracking in a container ignored.\n"); 1263 return -EINVAL; 1264 } 1265 1266 ret = nfsd4_umh_cltrack_upcall("init", NULL, grace_start, NULL); 1267 kfree(grace_start); 1268 return ret; 1269 } 1270 1271 static void 1272 nfsd4_cltrack_upcall_lock(struct nfs4_client *clp) 1273 { 1274 wait_on_bit_lock(&clp->cl_flags, NFSD4_CLIENT_UPCALL_LOCK, 1275 TASK_UNINTERRUPTIBLE); 1276 } 1277 1278 static void 1279 nfsd4_cltrack_upcall_unlock(struct nfs4_client *clp) 1280 { 1281 smp_mb__before_atomic(); 1282 clear_bit(NFSD4_CLIENT_UPCALL_LOCK, &clp->cl_flags); 1283 smp_mb__after_atomic(); 1284 wake_up_bit(&clp->cl_flags, NFSD4_CLIENT_UPCALL_LOCK); 1285 } 1286 1287 static void 1288 nfsd4_umh_cltrack_create(struct nfs4_client *clp) 1289 { 1290 char *hexid, *has_session, *grace_start; 1291 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 1292 1293 /* 1294 * With v4.0 clients, there's little difference in outcome between a 1295 * create and check operation, and we can end up calling into this 1296 * function multiple times per client (once for each openowner). So, 1297 * for v4.0 clients skip upcalling once the client has been recorded 1298 * on stable storage. 1299 * 1300 * For v4.1+ clients, the outcome of the two operations is different, 1301 * so we must ensure that we upcall for the create operation. v4.1+ 1302 * clients call this on RECLAIM_COMPLETE though, so we should only end 1303 * up doing a single create upcall per client. 1304 */ 1305 if (clp->cl_minorversion == 0 && 1306 test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 1307 return; 1308 1309 hexid = bin_to_hex_dup(clp->cl_name.data, clp->cl_name.len); 1310 if (!hexid) { 1311 dprintk("%s: can't allocate memory for upcall!\n", __func__); 1312 return; 1313 } 1314 1315 has_session = nfsd4_cltrack_client_has_session(clp); 1316 grace_start = nfsd4_cltrack_grace_start(nn->boot_time); 1317 1318 nfsd4_cltrack_upcall_lock(clp); 1319 if (!nfsd4_umh_cltrack_upcall("create", hexid, has_session, grace_start)) 1320 set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); 1321 nfsd4_cltrack_upcall_unlock(clp); 1322 1323 kfree(has_session); 1324 kfree(grace_start); 1325 kfree(hexid); 1326 } 1327 1328 static void 1329 nfsd4_umh_cltrack_remove(struct nfs4_client *clp) 1330 { 1331 char *hexid; 1332 1333 if (!test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 1334 return; 1335 1336 hexid = bin_to_hex_dup(clp->cl_name.data, clp->cl_name.len); 1337 if (!hexid) { 1338 dprintk("%s: can't allocate memory for upcall!\n", __func__); 1339 return; 1340 } 1341 1342 nfsd4_cltrack_upcall_lock(clp); 1343 if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags) && 1344 nfsd4_umh_cltrack_upcall("remove", hexid, NULL, NULL) == 0) 1345 clear_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); 1346 nfsd4_cltrack_upcall_unlock(clp); 1347 1348 kfree(hexid); 1349 } 1350 1351 static int 1352 nfsd4_umh_cltrack_check(struct nfs4_client *clp) 1353 { 1354 int ret; 1355 char *hexid, *has_session, *legacy; 1356 1357 if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 1358 return 0; 1359 1360 hexid = bin_to_hex_dup(clp->cl_name.data, clp->cl_name.len); 1361 if (!hexid) { 1362 dprintk("%s: can't allocate memory for upcall!\n", __func__); 1363 return -ENOMEM; 1364 } 1365 1366 has_session = nfsd4_cltrack_client_has_session(clp); 1367 legacy = nfsd4_cltrack_legacy_recdir(&clp->cl_name); 1368 1369 nfsd4_cltrack_upcall_lock(clp); 1370 if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) { 1371 ret = 0; 1372 } else { 1373 ret = nfsd4_umh_cltrack_upcall("check", hexid, has_session, legacy); 1374 if (ret == 0) 1375 set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); 1376 } 1377 nfsd4_cltrack_upcall_unlock(clp); 1378 kfree(has_session); 1379 kfree(legacy); 1380 kfree(hexid); 1381 1382 return ret; 1383 } 1384 1385 static void 1386 nfsd4_umh_cltrack_grace_done(struct nfsd_net *nn) 1387 { 1388 char *legacy; 1389 char timestr[22]; /* FIXME: better way to determine max size? */ 1390 1391 sprintf(timestr, "%ld", nn->boot_time); 1392 legacy = nfsd4_cltrack_legacy_topdir(); 1393 nfsd4_umh_cltrack_upcall("gracedone", timestr, legacy, NULL); 1394 kfree(legacy); 1395 } 1396 1397 static struct nfsd4_client_tracking_ops nfsd4_umh_tracking_ops = { 1398 .init = nfsd4_umh_cltrack_init, 1399 .exit = NULL, 1400 .create = nfsd4_umh_cltrack_create, 1401 .remove = nfsd4_umh_cltrack_remove, 1402 .check = nfsd4_umh_cltrack_check, 1403 .grace_done = nfsd4_umh_cltrack_grace_done, 1404 }; 1405 1406 int 1407 nfsd4_client_tracking_init(struct net *net) 1408 { 1409 int status; 1410 struct path path; 1411 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 1412 1413 /* just run the init if it the method is already decided */ 1414 if (nn->client_tracking_ops) 1415 goto do_init; 1416 1417 /* 1418 * First, try a UMH upcall. It should succeed or fail quickly, so 1419 * there's little harm in trying that first. 1420 */ 1421 nn->client_tracking_ops = &nfsd4_umh_tracking_ops; 1422 status = nn->client_tracking_ops->init(net); 1423 if (!status) 1424 return status; 1425 1426 /* 1427 * See if the recoverydir exists and is a directory. If it is, 1428 * then use the legacy ops. 1429 */ 1430 nn->client_tracking_ops = &nfsd4_legacy_tracking_ops; 1431 status = kern_path(nfs4_recoverydir(), LOOKUP_FOLLOW, &path); 1432 if (!status) { 1433 status = d_is_dir(path.dentry); 1434 path_put(&path); 1435 if (status) 1436 goto do_init; 1437 } 1438 1439 /* Finally, try to use nfsdcld */ 1440 nn->client_tracking_ops = &nfsd4_cld_tracking_ops; 1441 printk(KERN_WARNING "NFSD: the nfsdcld client tracking upcall will be " 1442 "removed in 3.10. Please transition to using " 1443 "nfsdcltrack.\n"); 1444 do_init: 1445 status = nn->client_tracking_ops->init(net); 1446 if (status) { 1447 printk(KERN_WARNING "NFSD: Unable to initialize client " 1448 "recovery tracking! (%d)\n", status); 1449 nn->client_tracking_ops = NULL; 1450 } 1451 return status; 1452 } 1453 1454 void 1455 nfsd4_client_tracking_exit(struct net *net) 1456 { 1457 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 1458 1459 if (nn->client_tracking_ops) { 1460 if (nn->client_tracking_ops->exit) 1461 nn->client_tracking_ops->exit(net); 1462 nn->client_tracking_ops = NULL; 1463 } 1464 } 1465 1466 void 1467 nfsd4_client_record_create(struct nfs4_client *clp) 1468 { 1469 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 1470 1471 if (nn->client_tracking_ops) 1472 nn->client_tracking_ops->create(clp); 1473 } 1474 1475 void 1476 nfsd4_client_record_remove(struct nfs4_client *clp) 1477 { 1478 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 1479 1480 if (nn->client_tracking_ops) 1481 nn->client_tracking_ops->remove(clp); 1482 } 1483 1484 int 1485 nfsd4_client_record_check(struct nfs4_client *clp) 1486 { 1487 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 1488 1489 if (nn->client_tracking_ops) 1490 return nn->client_tracking_ops->check(clp); 1491 1492 return -EOPNOTSUPP; 1493 } 1494 1495 void 1496 nfsd4_record_grace_done(struct nfsd_net *nn) 1497 { 1498 if (nn->client_tracking_ops) 1499 nn->client_tracking_ops->grace_done(nn); 1500 } 1501 1502 static int 1503 rpc_pipefs_event(struct notifier_block *nb, unsigned long event, void *ptr) 1504 { 1505 struct super_block *sb = ptr; 1506 struct net *net = sb->s_fs_info; 1507 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 1508 struct cld_net *cn = nn->cld_net; 1509 struct dentry *dentry; 1510 int ret = 0; 1511 1512 if (!try_module_get(THIS_MODULE)) 1513 return 0; 1514 1515 if (!cn) { 1516 module_put(THIS_MODULE); 1517 return 0; 1518 } 1519 1520 switch (event) { 1521 case RPC_PIPEFS_MOUNT: 1522 dentry = nfsd4_cld_register_sb(sb, cn->cn_pipe); 1523 if (IS_ERR(dentry)) { 1524 ret = PTR_ERR(dentry); 1525 break; 1526 } 1527 cn->cn_pipe->dentry = dentry; 1528 break; 1529 case RPC_PIPEFS_UMOUNT: 1530 if (cn->cn_pipe->dentry) 1531 nfsd4_cld_unregister_sb(cn->cn_pipe); 1532 break; 1533 default: 1534 ret = -ENOTSUPP; 1535 break; 1536 } 1537 module_put(THIS_MODULE); 1538 return ret; 1539 } 1540 1541 static struct notifier_block nfsd4_cld_block = { 1542 .notifier_call = rpc_pipefs_event, 1543 }; 1544 1545 int 1546 register_cld_notifier(void) 1547 { 1548 return rpc_pipefs_notifier_register(&nfsd4_cld_block); 1549 } 1550 1551 void 1552 unregister_cld_notifier(void) 1553 { 1554 rpc_pipefs_notifier_unregister(&nfsd4_cld_block); 1555 } 1556