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