root/fs/nfsd/nfs4recover.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. nfs4_save_creds
  2. nfs4_reset_creds
  3. md5_to_hex
  4. nfs4_make_rec_clidname
  5. legacy_recdir_name_error
  6. __nfsd4_create_reclaim_record_grace
  7. nfsd4_create_clid_dir
  8. nfsd4_build_namelist
  9. nfsd4_list_rec_dir
  10. nfsd4_unlink_clid_dir
  11. __nfsd4_remove_reclaim_record_grace
  12. nfsd4_remove_clid_dir
  13. purge_old
  14. nfsd4_recdir_purge_old
  15. load_recdir
  16. nfsd4_recdir_load
  17. nfsd4_init_recdir
  18. nfsd4_shutdown_recdir
  19. nfs4_legacy_state_init
  20. nfs4_legacy_state_shutdown
  21. nfsd4_load_reboot_recovery_data
  22. nfsd4_legacy_tracking_init
  23. nfsd4_legacy_tracking_exit
  24. nfs4_reset_recoverydir
  25. nfs4_recoverydir
  26. nfsd4_check_legacy_client
  27. __cld_pipe_upcall
  28. cld_pipe_upcall
  29. __cld_pipe_inprogress_downcall
  30. cld_pipe_downcall
  31. cld_pipe_destroy_msg
  32. nfsd4_cld_register_sb
  33. nfsd4_cld_unregister_sb
  34. nfsd4_cld_register_net
  35. nfsd4_cld_unregister_net
  36. __nfsd4_init_cld_pipe
  37. nfsd4_init_cld_pipe
  38. nfsd4_remove_cld_pipe
  39. alloc_cld_upcall
  40. free_cld_upcall
  41. nfsd4_cld_create
  42. nfsd4_cld_create_v2
  43. nfsd4_cld_remove
  44. nfsd4_cld_check_v0
  45. nfsd4_cld_check
  46. nfsd4_cld_check_v2
  47. nfsd4_cld_grace_start
  48. nfsd4_cld_grace_done_v0
  49. nfsd4_cld_grace_done
  50. nfs4_cld_state_init
  51. nfs4_cld_state_shutdown
  52. cld_running
  53. nfsd4_cld_get_version
  54. nfsd4_cld_tracking_init
  55. nfsd4_cld_tracking_exit
  56. nfsd4_cltrack_legacy_topdir
  57. nfsd4_cltrack_legacy_recdir
  58. nfsd4_cltrack_client_has_session
  59. nfsd4_cltrack_grace_start
  60. nfsd4_umh_cltrack_upcall
  61. bin_to_hex_dup
  62. nfsd4_umh_cltrack_init
  63. nfsd4_cltrack_upcall_lock
  64. nfsd4_cltrack_upcall_unlock
  65. nfsd4_umh_cltrack_create
  66. nfsd4_umh_cltrack_remove
  67. nfsd4_umh_cltrack_check
  68. nfsd4_umh_cltrack_grace_done
  69. nfsd4_client_tracking_init
  70. nfsd4_client_tracking_exit
  71. nfsd4_client_record_create
  72. nfsd4_client_record_remove
  73. nfsd4_client_record_check
  74. nfsd4_record_grace_done
  75. rpc_pipefs_event
  76. register_cld_notifier
  77. unregister_cld_notifier

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

/* [<][>][^][v][top][bottom][index][help] */