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 net *, time_t); 62 }; 63 64 /* Globals */ 65 static struct file *rec_file; 66 static char user_recovery_dirname[PATH_MAX] = "/var/lib/nfs/v4recovery"; 67 static struct nfsd4_client_tracking_ops *client_tracking_ops; 68 69 static int 70 nfs4_save_creds(const struct cred **original_creds) 71 { 72 struct cred *new; 73 74 new = prepare_creds(); 75 if (!new) 76 return -ENOMEM; 77 78 new->fsuid = 0; 79 new->fsgid = 0; 80 *original_creds = override_creds(new); 81 put_cred(new); 82 return 0; 83 } 84 85 static void 86 nfs4_reset_creds(const struct cred *original) 87 { 88 revert_creds(original); 89 } 90 91 static void 92 md5_to_hex(char *out, char *md5) 93 { 94 int i; 95 96 for (i=0; i<16; i++) { 97 unsigned char c = md5[i]; 98 99 *out++ = '0' + ((c&0xf0)>>4) + (c>=0xa0)*('a'-'9'-1); 100 *out++ = '0' + (c&0x0f) + ((c&0x0f)>=0x0a)*('a'-'9'-1); 101 } 102 *out = '\0'; 103 } 104 105 __be32 106 nfs4_make_rec_clidname(char *dname, struct xdr_netobj *clname) 107 { 108 struct xdr_netobj cksum; 109 struct hash_desc desc; 110 struct scatterlist sg; 111 __be32 status = nfserr_jukebox; 112 113 dprintk("NFSD: nfs4_make_rec_clidname for %.*s\n", 114 clname->len, clname->data); 115 desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP; 116 desc.tfm = crypto_alloc_hash("md5", 0, CRYPTO_ALG_ASYNC); 117 if (IS_ERR(desc.tfm)) 118 goto out_no_tfm; 119 cksum.len = crypto_hash_digestsize(desc.tfm); 120 cksum.data = kmalloc(cksum.len, GFP_KERNEL); 121 if (cksum.data == NULL) 122 goto out; 123 124 sg_init_one(&sg, clname->data, clname->len); 125 126 if (crypto_hash_digest(&desc, &sg, sg.length, cksum.data)) 127 goto out; 128 129 md5_to_hex(dname, cksum.data); 130 131 status = nfs_ok; 132 out: 133 kfree(cksum.data); 134 crypto_free_hash(desc.tfm); 135 out_no_tfm: 136 return status; 137 } 138 139 static void 140 nfsd4_create_clid_dir(struct nfs4_client *clp) 141 { 142 const struct cred *original_cred; 143 char *dname = clp->cl_recdir; 144 struct dentry *dir, *dentry; 145 int status; 146 147 dprintk("NFSD: nfsd4_create_clid_dir for \"%s\"\n", dname); 148 149 if (test_and_set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 150 return; 151 if (!rec_file) 152 return; 153 status = nfs4_save_creds(&original_cred); 154 if (status < 0) 155 return; 156 157 status = mnt_want_write_file(rec_file); 158 if (status) 159 return; 160 161 dir = rec_file->f_path.dentry; 162 /* lock the parent */ 163 mutex_lock(&dir->d_inode->i_mutex); 164 165 dentry = lookup_one_len(dname, dir, HEXDIR_LEN-1); 166 if (IS_ERR(dentry)) { 167 status = PTR_ERR(dentry); 168 goto out_unlock; 169 } 170 if (dentry->d_inode) 171 /* 172 * In the 4.1 case, where we're called from 173 * reclaim_complete(), records from the previous reboot 174 * may still be left, so this is OK. 175 * 176 * In the 4.0 case, we should never get here; but we may 177 * as well be forgiving and just succeed silently. 178 */ 179 goto out_put; 180 status = vfs_mkdir(dir->d_inode, dentry, S_IRWXU); 181 out_put: 182 dput(dentry); 183 out_unlock: 184 mutex_unlock(&dir->d_inode->i_mutex); 185 if (status == 0) 186 vfs_fsync(rec_file, 0); 187 else 188 printk(KERN_ERR "NFSD: failed to write recovery record" 189 " (err %d); please check that %s exists" 190 " and is writeable", status, 191 user_recovery_dirname); 192 mnt_drop_write_file(rec_file); 193 nfs4_reset_creds(original_cred); 194 } 195 196 typedef int (recdir_func)(struct dentry *, struct dentry *); 197 198 struct name_list { 199 char name[HEXDIR_LEN]; 200 struct list_head list; 201 }; 202 203 static int 204 nfsd4_build_namelist(void *arg, const char *name, int namlen, 205 loff_t offset, u64 ino, unsigned int d_type) 206 { 207 struct list_head *names = arg; 208 struct name_list *entry; 209 210 if (namlen != HEXDIR_LEN - 1) 211 return 0; 212 entry = kmalloc(sizeof(struct name_list), GFP_KERNEL); 213 if (entry == NULL) 214 return -ENOMEM; 215 memcpy(entry->name, name, HEXDIR_LEN - 1); 216 entry->name[HEXDIR_LEN - 1] = '\0'; 217 list_add(&entry->list, names); 218 return 0; 219 } 220 221 static int 222 nfsd4_list_rec_dir(recdir_func *f) 223 { 224 const struct cred *original_cred; 225 struct dentry *dir = rec_file->f_path.dentry; 226 LIST_HEAD(names); 227 int status; 228 229 status = nfs4_save_creds(&original_cred); 230 if (status < 0) 231 return status; 232 233 status = vfs_llseek(rec_file, 0, SEEK_SET); 234 if (status < 0) { 235 nfs4_reset_creds(original_cred); 236 return status; 237 } 238 239 status = vfs_readdir(rec_file, nfsd4_build_namelist, &names); 240 mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT); 241 while (!list_empty(&names)) { 242 struct name_list *entry; 243 entry = list_entry(names.next, struct name_list, list); 244 if (!status) { 245 struct dentry *dentry; 246 dentry = lookup_one_len(entry->name, dir, HEXDIR_LEN-1); 247 if (IS_ERR(dentry)) { 248 status = PTR_ERR(dentry); 249 break; 250 } 251 status = f(dir, dentry); 252 dput(dentry); 253 } 254 list_del(&entry->list); 255 kfree(entry); 256 } 257 mutex_unlock(&dir->d_inode->i_mutex); 258 nfs4_reset_creds(original_cred); 259 return status; 260 } 261 262 static int 263 nfsd4_unlink_clid_dir(char *name, int namlen) 264 { 265 struct dentry *dir, *dentry; 266 int status; 267 268 dprintk("NFSD: nfsd4_unlink_clid_dir. name %.*s\n", namlen, name); 269 270 dir = rec_file->f_path.dentry; 271 mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT); 272 dentry = lookup_one_len(name, dir, namlen); 273 if (IS_ERR(dentry)) { 274 status = PTR_ERR(dentry); 275 goto out_unlock; 276 } 277 status = -ENOENT; 278 if (!dentry->d_inode) 279 goto out; 280 status = vfs_rmdir(dir->d_inode, dentry); 281 out: 282 dput(dentry); 283 out_unlock: 284 mutex_unlock(&dir->d_inode->i_mutex); 285 return status; 286 } 287 288 static void 289 nfsd4_remove_clid_dir(struct nfs4_client *clp) 290 { 291 const struct cred *original_cred; 292 int status; 293 294 if (!rec_file || !test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 295 return; 296 297 status = mnt_want_write_file(rec_file); 298 if (status) 299 goto out; 300 clear_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); 301 302 status = nfs4_save_creds(&original_cred); 303 if (status < 0) 304 goto out; 305 306 status = nfsd4_unlink_clid_dir(clp->cl_recdir, HEXDIR_LEN-1); 307 nfs4_reset_creds(original_cred); 308 if (status == 0) 309 vfs_fsync(rec_file, 0); 310 mnt_drop_write_file(rec_file); 311 out: 312 if (status) 313 printk("NFSD: Failed to remove expired client state directory" 314 " %.*s\n", HEXDIR_LEN, clp->cl_recdir); 315 } 316 317 static int 318 purge_old(struct dentry *parent, struct dentry *child) 319 { 320 int status; 321 322 if (nfs4_has_reclaimed_state(child->d_name.name, false)) 323 return 0; 324 325 status = vfs_rmdir(parent->d_inode, child); 326 if (status) 327 printk("failed to remove client recovery directory %s\n", 328 child->d_name.name); 329 /* Keep trying, success or failure: */ 330 return 0; 331 } 332 333 static void 334 nfsd4_recdir_purge_old(struct net *net, time_t boot_time) 335 { 336 int status; 337 338 if (!rec_file) 339 return; 340 status = mnt_want_write_file(rec_file); 341 if (status) 342 goto out; 343 status = nfsd4_list_rec_dir(purge_old); 344 if (status == 0) 345 vfs_fsync(rec_file, 0); 346 mnt_drop_write_file(rec_file); 347 out: 348 if (status) 349 printk("nfsd4: failed to purge old clients from recovery" 350 " directory %s\n", rec_file->f_path.dentry->d_name.name); 351 } 352 353 static int 354 load_recdir(struct dentry *parent, struct dentry *child) 355 { 356 if (child->d_name.len != HEXDIR_LEN - 1) { 357 printk("nfsd4: illegal name %s in recovery directory\n", 358 child->d_name.name); 359 /* Keep trying; maybe the others are OK: */ 360 return 0; 361 } 362 nfs4_client_to_reclaim(child->d_name.name); 363 return 0; 364 } 365 366 static int 367 nfsd4_recdir_load(void) { 368 int status; 369 370 if (!rec_file) 371 return 0; 372 373 status = nfsd4_list_rec_dir(load_recdir); 374 if (status) 375 printk("nfsd4: failed loading clients from recovery" 376 " directory %s\n", rec_file->f_path.dentry->d_name.name); 377 return status; 378 } 379 380 /* 381 * Hold reference to the recovery directory. 382 */ 383 384 static int 385 nfsd4_init_recdir(void) 386 { 387 const struct cred *original_cred; 388 int status; 389 390 printk("NFSD: Using %s as the NFSv4 state recovery directory\n", 391 user_recovery_dirname); 392 393 BUG_ON(rec_file); 394 395 status = nfs4_save_creds(&original_cred); 396 if (status < 0) { 397 printk("NFSD: Unable to change credentials to find recovery" 398 " directory: error %d\n", 399 status); 400 return status; 401 } 402 403 rec_file = filp_open(user_recovery_dirname, O_RDONLY | O_DIRECTORY, 0); 404 if (IS_ERR(rec_file)) { 405 printk("NFSD: unable to find recovery directory %s\n", 406 user_recovery_dirname); 407 status = PTR_ERR(rec_file); 408 rec_file = NULL; 409 } 410 411 nfs4_reset_creds(original_cred); 412 return status; 413 } 414 415 static int 416 nfsd4_load_reboot_recovery_data(struct net *net) 417 { 418 int status; 419 420 /* XXX: The legacy code won't work in a container */ 421 if (net != &init_net) { 422 WARN(1, KERN_ERR "NFSD: attempt to initialize legacy client " 423 "tracking in a container!\n"); 424 return -EINVAL; 425 } 426 427 nfs4_lock_state(); 428 status = nfsd4_init_recdir(); 429 if (!status) 430 status = nfsd4_recdir_load(); 431 nfs4_unlock_state(); 432 if (status) 433 printk(KERN_ERR "NFSD: Failure reading reboot recovery data\n"); 434 return status; 435 } 436 437 static void 438 nfsd4_shutdown_recdir(void) 439 { 440 if (!rec_file) 441 return; 442 fput(rec_file); 443 rec_file = NULL; 444 } 445 446 static void 447 nfsd4_legacy_tracking_exit(struct net *net) 448 { 449 nfs4_release_reclaim(); 450 nfsd4_shutdown_recdir(); 451 } 452 453 /* 454 * Change the NFSv4 recovery directory to recdir. 455 */ 456 int 457 nfs4_reset_recoverydir(char *recdir) 458 { 459 int status; 460 struct path path; 461 462 status = kern_path(recdir, LOOKUP_FOLLOW, &path); 463 if (status) 464 return status; 465 status = -ENOTDIR; 466 if (S_ISDIR(path.dentry->d_inode->i_mode)) { 467 strcpy(user_recovery_dirname, recdir); 468 status = 0; 469 } 470 path_put(&path); 471 return status; 472 } 473 474 char * 475 nfs4_recoverydir(void) 476 { 477 return user_recovery_dirname; 478 } 479 480 static int 481 nfsd4_check_legacy_client(struct nfs4_client *clp) 482 { 483 /* did we already find that this client is stable? */ 484 if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 485 return 0; 486 487 /* look for it in the reclaim hashtable otherwise */ 488 if (nfsd4_find_reclaim_client(clp)) { 489 set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); 490 return 0; 491 } 492 493 return -ENOENT; 494 } 495 496 static struct nfsd4_client_tracking_ops nfsd4_legacy_tracking_ops = { 497 .init = nfsd4_load_reboot_recovery_data, 498 .exit = nfsd4_legacy_tracking_exit, 499 .create = nfsd4_create_clid_dir, 500 .remove = nfsd4_remove_clid_dir, 501 .check = nfsd4_check_legacy_client, 502 .grace_done = nfsd4_recdir_purge_old, 503 }; 504 505 /* Globals */ 506 #define NFSD_PIPE_DIR "nfsd" 507 #define NFSD_CLD_PIPE "cld" 508 509 /* per-net-ns structure for holding cld upcall info */ 510 struct cld_net { 511 struct rpc_pipe *cn_pipe; 512 spinlock_t cn_lock; 513 struct list_head cn_list; 514 unsigned int cn_xid; 515 }; 516 517 struct cld_upcall { 518 struct list_head cu_list; 519 struct cld_net *cu_net; 520 struct task_struct *cu_task; 521 struct cld_msg cu_msg; 522 }; 523 524 static int 525 __cld_pipe_upcall(struct rpc_pipe *pipe, struct cld_msg *cmsg) 526 { 527 int ret; 528 struct rpc_pipe_msg msg; 529 530 memset(&msg, 0, sizeof(msg)); 531 msg.data = cmsg; 532 msg.len = sizeof(*cmsg); 533 534 /* 535 * Set task state before we queue the upcall. That prevents 536 * wake_up_process in the downcall from racing with schedule. 537 */ 538 set_current_state(TASK_UNINTERRUPTIBLE); 539 ret = rpc_queue_upcall(pipe, &msg); 540 if (ret < 0) { 541 set_current_state(TASK_RUNNING); 542 goto out; 543 } 544 545 schedule(); 546 set_current_state(TASK_RUNNING); 547 548 if (msg.errno < 0) 549 ret = msg.errno; 550 out: 551 return ret; 552 } 553 554 static int 555 cld_pipe_upcall(struct rpc_pipe *pipe, struct cld_msg *cmsg) 556 { 557 int ret; 558 559 /* 560 * -EAGAIN occurs when pipe is closed and reopened while there are 561 * upcalls queued. 562 */ 563 do { 564 ret = __cld_pipe_upcall(pipe, cmsg); 565 } while (ret == -EAGAIN); 566 567 return ret; 568 } 569 570 static ssize_t 571 cld_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) 572 { 573 struct cld_upcall *tmp, *cup; 574 struct cld_msg __user *cmsg = (struct cld_msg __user *)src; 575 uint32_t xid; 576 struct nfsd_net *nn = net_generic(filp->f_dentry->d_sb->s_fs_info, 577 nfsd_net_id); 578 struct cld_net *cn = nn->cld_net; 579 580 if (mlen != sizeof(*cmsg)) { 581 dprintk("%s: got %zu bytes, expected %zu\n", __func__, mlen, 582 sizeof(*cmsg)); 583 return -EINVAL; 584 } 585 586 /* copy just the xid so we can try to find that */ 587 if (copy_from_user(&xid, &cmsg->cm_xid, sizeof(xid)) != 0) { 588 dprintk("%s: error when copying xid from userspace", __func__); 589 return -EFAULT; 590 } 591 592 /* walk the list and find corresponding xid */ 593 cup = NULL; 594 spin_lock(&cn->cn_lock); 595 list_for_each_entry(tmp, &cn->cn_list, cu_list) { 596 if (get_unaligned(&tmp->cu_msg.cm_xid) == xid) { 597 cup = tmp; 598 list_del_init(&cup->cu_list); 599 break; 600 } 601 } 602 spin_unlock(&cn->cn_lock); 603 604 /* couldn't find upcall? */ 605 if (!cup) { 606 dprintk("%s: couldn't find upcall -- xid=%u\n", __func__, xid); 607 return -EINVAL; 608 } 609 610 if (copy_from_user(&cup->cu_msg, src, mlen) != 0) 611 return -EFAULT; 612 613 wake_up_process(cup->cu_task); 614 return mlen; 615 } 616 617 static void 618 cld_pipe_destroy_msg(struct rpc_pipe_msg *msg) 619 { 620 struct cld_msg *cmsg = msg->data; 621 struct cld_upcall *cup = container_of(cmsg, struct cld_upcall, 622 cu_msg); 623 624 /* errno >= 0 means we got a downcall */ 625 if (msg->errno >= 0) 626 return; 627 628 wake_up_process(cup->cu_task); 629 } 630 631 static const struct rpc_pipe_ops cld_upcall_ops = { 632 .upcall = rpc_pipe_generic_upcall, 633 .downcall = cld_pipe_downcall, 634 .destroy_msg = cld_pipe_destroy_msg, 635 }; 636 637 static struct dentry * 638 nfsd4_cld_register_sb(struct super_block *sb, struct rpc_pipe *pipe) 639 { 640 struct dentry *dir, *dentry; 641 642 dir = rpc_d_lookup_sb(sb, NFSD_PIPE_DIR); 643 if (dir == NULL) 644 return ERR_PTR(-ENOENT); 645 dentry = rpc_mkpipe_dentry(dir, NFSD_CLD_PIPE, NULL, pipe); 646 dput(dir); 647 return dentry; 648 } 649 650 static void 651 nfsd4_cld_unregister_sb(struct rpc_pipe *pipe) 652 { 653 if (pipe->dentry) 654 rpc_unlink(pipe->dentry); 655 } 656 657 static struct dentry * 658 nfsd4_cld_register_net(struct net *net, struct rpc_pipe *pipe) 659 { 660 struct super_block *sb; 661 struct dentry *dentry; 662 663 sb = rpc_get_sb_net(net); 664 if (!sb) 665 return NULL; 666 dentry = nfsd4_cld_register_sb(sb, pipe); 667 rpc_put_sb_net(net); 668 return dentry; 669 } 670 671 static void 672 nfsd4_cld_unregister_net(struct net *net, struct rpc_pipe *pipe) 673 { 674 struct super_block *sb; 675 676 sb = rpc_get_sb_net(net); 677 if (sb) { 678 nfsd4_cld_unregister_sb(pipe); 679 rpc_put_sb_net(net); 680 } 681 } 682 683 /* Initialize rpc_pipefs pipe for communication with client tracking daemon */ 684 static int 685 nfsd4_init_cld_pipe(struct net *net) 686 { 687 int ret; 688 struct dentry *dentry; 689 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 690 struct cld_net *cn; 691 692 if (nn->cld_net) 693 return 0; 694 695 cn = kzalloc(sizeof(*cn), GFP_KERNEL); 696 if (!cn) { 697 ret = -ENOMEM; 698 goto err; 699 } 700 701 cn->cn_pipe = rpc_mkpipe_data(&cld_upcall_ops, RPC_PIPE_WAIT_FOR_OPEN); 702 if (IS_ERR(cn->cn_pipe)) { 703 ret = PTR_ERR(cn->cn_pipe); 704 goto err; 705 } 706 spin_lock_init(&cn->cn_lock); 707 INIT_LIST_HEAD(&cn->cn_list); 708 709 dentry = nfsd4_cld_register_net(net, cn->cn_pipe); 710 if (IS_ERR(dentry)) { 711 ret = PTR_ERR(dentry); 712 goto err_destroy_data; 713 } 714 715 cn->cn_pipe->dentry = dentry; 716 nn->cld_net = cn; 717 return 0; 718 719 err_destroy_data: 720 rpc_destroy_pipe_data(cn->cn_pipe); 721 err: 722 kfree(cn); 723 printk(KERN_ERR "NFSD: unable to create nfsdcld upcall pipe (%d)\n", 724 ret); 725 return ret; 726 } 727 728 static void 729 nfsd4_remove_cld_pipe(struct net *net) 730 { 731 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 732 struct cld_net *cn = nn->cld_net; 733 734 nfsd4_cld_unregister_net(net, cn->cn_pipe); 735 rpc_destroy_pipe_data(cn->cn_pipe); 736 kfree(nn->cld_net); 737 nn->cld_net = NULL; 738 } 739 740 static struct cld_upcall * 741 alloc_cld_upcall(struct cld_net *cn) 742 { 743 struct cld_upcall *new, *tmp; 744 745 new = kzalloc(sizeof(*new), GFP_KERNEL); 746 if (!new) 747 return new; 748 749 /* FIXME: hard cap on number in flight? */ 750 restart_search: 751 spin_lock(&cn->cn_lock); 752 list_for_each_entry(tmp, &cn->cn_list, cu_list) { 753 if (tmp->cu_msg.cm_xid == cn->cn_xid) { 754 cn->cn_xid++; 755 spin_unlock(&cn->cn_lock); 756 goto restart_search; 757 } 758 } 759 new->cu_task = current; 760 new->cu_msg.cm_vers = CLD_UPCALL_VERSION; 761 put_unaligned(cn->cn_xid++, &new->cu_msg.cm_xid); 762 new->cu_net = cn; 763 list_add(&new->cu_list, &cn->cn_list); 764 spin_unlock(&cn->cn_lock); 765 766 dprintk("%s: allocated xid %u\n", __func__, new->cu_msg.cm_xid); 767 768 return new; 769 } 770 771 static void 772 free_cld_upcall(struct cld_upcall *victim) 773 { 774 struct cld_net *cn = victim->cu_net; 775 776 spin_lock(&cn->cn_lock); 777 list_del(&victim->cu_list); 778 spin_unlock(&cn->cn_lock); 779 kfree(victim); 780 } 781 782 /* Ask daemon to create a new record */ 783 static void 784 nfsd4_cld_create(struct nfs4_client *clp) 785 { 786 int ret; 787 struct cld_upcall *cup; 788 /* FIXME: determine net from clp */ 789 struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id); 790 struct cld_net *cn = nn->cld_net; 791 792 /* Don't upcall if it's already stored */ 793 if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 794 return; 795 796 cup = alloc_cld_upcall(cn); 797 if (!cup) { 798 ret = -ENOMEM; 799 goto out_err; 800 } 801 802 cup->cu_msg.cm_cmd = Cld_Create; 803 cup->cu_msg.cm_u.cm_name.cn_len = clp->cl_name.len; 804 memcpy(cup->cu_msg.cm_u.cm_name.cn_id, clp->cl_name.data, 805 clp->cl_name.len); 806 807 ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_msg); 808 if (!ret) { 809 ret = cup->cu_msg.cm_status; 810 set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); 811 } 812 813 free_cld_upcall(cup); 814 out_err: 815 if (ret) 816 printk(KERN_ERR "NFSD: Unable to create client " 817 "record on stable storage: %d\n", ret); 818 } 819 820 /* Ask daemon to create a new record */ 821 static void 822 nfsd4_cld_remove(struct nfs4_client *clp) 823 { 824 int ret; 825 struct cld_upcall *cup; 826 /* FIXME: determine net from clp */ 827 struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id); 828 struct cld_net *cn = nn->cld_net; 829 830 /* Don't upcall if it's already removed */ 831 if (!test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 832 return; 833 834 cup = alloc_cld_upcall(cn); 835 if (!cup) { 836 ret = -ENOMEM; 837 goto out_err; 838 } 839 840 cup->cu_msg.cm_cmd = Cld_Remove; 841 cup->cu_msg.cm_u.cm_name.cn_len = clp->cl_name.len; 842 memcpy(cup->cu_msg.cm_u.cm_name.cn_id, clp->cl_name.data, 843 clp->cl_name.len); 844 845 ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_msg); 846 if (!ret) { 847 ret = cup->cu_msg.cm_status; 848 clear_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); 849 } 850 851 free_cld_upcall(cup); 852 out_err: 853 if (ret) 854 printk(KERN_ERR "NFSD: Unable to remove client " 855 "record from stable storage: %d\n", ret); 856 } 857 858 /* Check for presence of a record, and update its timestamp */ 859 static int 860 nfsd4_cld_check(struct nfs4_client *clp) 861 { 862 int ret; 863 struct cld_upcall *cup; 864 /* FIXME: determine net from clp */ 865 struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id); 866 struct cld_net *cn = nn->cld_net; 867 868 /* Don't upcall if one was already stored during this grace pd */ 869 if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 870 return 0; 871 872 cup = alloc_cld_upcall(cn); 873 if (!cup) { 874 printk(KERN_ERR "NFSD: Unable to check client record on " 875 "stable storage: %d\n", -ENOMEM); 876 return -ENOMEM; 877 } 878 879 cup->cu_msg.cm_cmd = Cld_Check; 880 cup->cu_msg.cm_u.cm_name.cn_len = clp->cl_name.len; 881 memcpy(cup->cu_msg.cm_u.cm_name.cn_id, clp->cl_name.data, 882 clp->cl_name.len); 883 884 ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_msg); 885 if (!ret) { 886 ret = cup->cu_msg.cm_status; 887 set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); 888 } 889 890 free_cld_upcall(cup); 891 return ret; 892 } 893 894 static void 895 nfsd4_cld_grace_done(struct net *net, time_t boot_time) 896 { 897 int ret; 898 struct cld_upcall *cup; 899 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 900 struct cld_net *cn = nn->cld_net; 901 902 cup = alloc_cld_upcall(cn); 903 if (!cup) { 904 ret = -ENOMEM; 905 goto out_err; 906 } 907 908 cup->cu_msg.cm_cmd = Cld_GraceDone; 909 cup->cu_msg.cm_u.cm_gracetime = (int64_t)boot_time; 910 ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_msg); 911 if (!ret) 912 ret = cup->cu_msg.cm_status; 913 914 free_cld_upcall(cup); 915 out_err: 916 if (ret) 917 printk(KERN_ERR "NFSD: Unable to end grace period: %d\n", ret); 918 } 919 920 static struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops = { 921 .init = nfsd4_init_cld_pipe, 922 .exit = nfsd4_remove_cld_pipe, 923 .create = nfsd4_cld_create, 924 .remove = nfsd4_cld_remove, 925 .check = nfsd4_cld_check, 926 .grace_done = nfsd4_cld_grace_done, 927 }; 928 929 int 930 nfsd4_client_tracking_init(struct net *net) 931 { 932 int status; 933 struct path path; 934 935 if (!client_tracking_ops) { 936 client_tracking_ops = &nfsd4_cld_tracking_ops; 937 status = kern_path(nfs4_recoverydir(), LOOKUP_FOLLOW, &path); 938 if (!status) { 939 if (S_ISDIR(path.dentry->d_inode->i_mode)) 940 client_tracking_ops = 941 &nfsd4_legacy_tracking_ops; 942 path_put(&path); 943 } 944 } 945 946 status = client_tracking_ops->init(net); 947 if (status) { 948 printk(KERN_WARNING "NFSD: Unable to initialize client " 949 "recovery tracking! (%d)\n", status); 950 client_tracking_ops = NULL; 951 } 952 return status; 953 } 954 955 void 956 nfsd4_client_tracking_exit(struct net *net) 957 { 958 if (client_tracking_ops) { 959 client_tracking_ops->exit(net); 960 client_tracking_ops = NULL; 961 } 962 } 963 964 void 965 nfsd4_client_record_create(struct nfs4_client *clp) 966 { 967 if (client_tracking_ops) 968 client_tracking_ops->create(clp); 969 } 970 971 void 972 nfsd4_client_record_remove(struct nfs4_client *clp) 973 { 974 if (client_tracking_ops) 975 client_tracking_ops->remove(clp); 976 } 977 978 int 979 nfsd4_client_record_check(struct nfs4_client *clp) 980 { 981 if (client_tracking_ops) 982 return client_tracking_ops->check(clp); 983 984 return -EOPNOTSUPP; 985 } 986 987 void 988 nfsd4_record_grace_done(struct net *net, time_t boot_time) 989 { 990 if (client_tracking_ops) 991 client_tracking_ops->grace_done(net, boot_time); 992 } 993 994 static int 995 rpc_pipefs_event(struct notifier_block *nb, unsigned long event, void *ptr) 996 { 997 struct super_block *sb = ptr; 998 struct net *net = sb->s_fs_info; 999 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 1000 struct cld_net *cn = nn->cld_net; 1001 struct dentry *dentry; 1002 int ret = 0; 1003 1004 if (!try_module_get(THIS_MODULE)) 1005 return 0; 1006 1007 if (!cn) { 1008 module_put(THIS_MODULE); 1009 return 0; 1010 } 1011 1012 switch (event) { 1013 case RPC_PIPEFS_MOUNT: 1014 dentry = nfsd4_cld_register_sb(sb, cn->cn_pipe); 1015 if (IS_ERR(dentry)) { 1016 ret = PTR_ERR(dentry); 1017 break; 1018 } 1019 cn->cn_pipe->dentry = dentry; 1020 break; 1021 case RPC_PIPEFS_UMOUNT: 1022 if (cn->cn_pipe->dentry) 1023 nfsd4_cld_unregister_sb(cn->cn_pipe); 1024 break; 1025 default: 1026 ret = -ENOTSUPP; 1027 break; 1028 } 1029 module_put(THIS_MODULE); 1030 return ret; 1031 } 1032 1033 static struct notifier_block nfsd4_cld_block = { 1034 .notifier_call = rpc_pipefs_event, 1035 }; 1036 1037 int 1038 register_cld_notifier(void) 1039 { 1040 return rpc_pipefs_notifier_register(&nfsd4_cld_block); 1041 } 1042 1043 void 1044 unregister_cld_notifier(void) 1045 { 1046 rpc_pipefs_notifier_unregister(&nfsd4_cld_block); 1047 } 1048