Back to home page

OSCL-LXR

 
 

    


0001 /*
0002 *  Copyright (c) 2004 The Regents of the University of Michigan.
0003 *  Copyright (c) 2012 Jeff Layton <jlayton@redhat.com>
0004 *  All rights reserved.
0005 *
0006 *  Andy Adamson <andros@citi.umich.edu>
0007 *
0008 *  Redistribution and use in source and binary forms, with or without
0009 *  modification, are permitted provided that the following conditions
0010 *  are met:
0011 *
0012 *  1. Redistributions of source code must retain the above copyright
0013 *     notice, this list of conditions and the following disclaimer.
0014 *  2. Redistributions in binary form must reproduce the above copyright
0015 *     notice, this list of conditions and the following disclaimer in the
0016 *     documentation and/or other materials provided with the distribution.
0017 *  3. Neither the name of the University nor the names of its
0018 *     contributors may be used to endorse or promote products derived
0019 *     from this software without specific prior written permission.
0020 *
0021 *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
0022 *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
0023 *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
0024 *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
0025 *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0026 *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0027 *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
0028 *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
0029 *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
0030 *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
0031 *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0032 *
0033 */
0034 
0035 #include <crypto/hash.h>
0036 #include <linux/file.h>
0037 #include <linux/slab.h>
0038 #include <linux/namei.h>
0039 #include <linux/sched.h>
0040 #include <linux/fs.h>
0041 #include <linux/module.h>
0042 #include <net/net_namespace.h>
0043 #include <linux/sunrpc/rpc_pipe_fs.h>
0044 #include <linux/sunrpc/clnt.h>
0045 #include <linux/nfsd/cld.h>
0046 
0047 #include "nfsd.h"
0048 #include "state.h"
0049 #include "vfs.h"
0050 #include "netns.h"
0051 
0052 #define NFSDDBG_FACILITY                NFSDDBG_PROC
0053 
0054 /* Declarations */
0055 struct nfsd4_client_tracking_ops {
0056     int (*init)(struct net *);
0057     void (*exit)(struct net *);
0058     void (*create)(struct nfs4_client *);
0059     void (*remove)(struct nfs4_client *);
0060     int (*check)(struct nfs4_client *);
0061     void (*grace_done)(struct nfsd_net *);
0062     uint8_t version;
0063     size_t msglen;
0064 };
0065 
0066 static const struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops;
0067 static const struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops_v2;
0068 
0069 /* Globals */
0070 static char user_recovery_dirname[PATH_MAX] = "/var/lib/nfs/v4recovery";
0071 
0072 static int
0073 nfs4_save_creds(const struct cred **original_creds)
0074 {
0075     struct cred *new;
0076 
0077     new = prepare_creds();
0078     if (!new)
0079         return -ENOMEM;
0080 
0081     new->fsuid = GLOBAL_ROOT_UID;
0082     new->fsgid = GLOBAL_ROOT_GID;
0083     *original_creds = override_creds(new);
0084     put_cred(new);
0085     return 0;
0086 }
0087 
0088 static void
0089 nfs4_reset_creds(const struct cred *original)
0090 {
0091     revert_creds(original);
0092 }
0093 
0094 static void
0095 md5_to_hex(char *out, char *md5)
0096 {
0097     int i;
0098 
0099     for (i=0; i<16; i++) {
0100         unsigned char c = md5[i];
0101 
0102         *out++ = '0' + ((c&0xf0)>>4) + (c>=0xa0)*('a'-'9'-1);
0103         *out++ = '0' + (c&0x0f) + ((c&0x0f)>=0x0a)*('a'-'9'-1);
0104     }
0105     *out = '\0';
0106 }
0107 
0108 static int
0109 nfs4_make_rec_clidname(char *dname, const struct xdr_netobj *clname)
0110 {
0111     struct xdr_netobj cksum;
0112     struct crypto_shash *tfm;
0113     int status;
0114 
0115     dprintk("NFSD: nfs4_make_rec_clidname for %.*s\n",
0116             clname->len, clname->data);
0117     tfm = crypto_alloc_shash("md5", 0, 0);
0118     if (IS_ERR(tfm)) {
0119         status = PTR_ERR(tfm);
0120         goto out_no_tfm;
0121     }
0122 
0123     cksum.len = crypto_shash_digestsize(tfm);
0124     cksum.data = kmalloc(cksum.len, GFP_KERNEL);
0125     if (cksum.data == NULL) {
0126         status = -ENOMEM;
0127         goto out;
0128     }
0129 
0130     status = crypto_shash_tfm_digest(tfm, clname->data, clname->len,
0131                      cksum.data);
0132     if (status)
0133         goto out;
0134 
0135     md5_to_hex(dname, cksum.data);
0136 
0137     status = 0;
0138 out:
0139     kfree(cksum.data);
0140     crypto_free_shash(tfm);
0141 out_no_tfm:
0142     return status;
0143 }
0144 
0145 /*
0146  * If we had an error generating the recdir name for the legacy tracker
0147  * then warn the admin. If the error doesn't appear to be transient,
0148  * then disable recovery tracking.
0149  */
0150 static void
0151 legacy_recdir_name_error(struct nfs4_client *clp, int error)
0152 {
0153     printk(KERN_ERR "NFSD: unable to generate recoverydir "
0154             "name (%d).\n", error);
0155 
0156     /*
0157      * if the algorithm just doesn't exist, then disable the recovery
0158      * tracker altogether. The crypto libs will generally return this if
0159      * FIPS is enabled as well.
0160      */
0161     if (error == -ENOENT) {
0162         printk(KERN_ERR "NFSD: disabling legacy clientid tracking. "
0163             "Reboot recovery will not function correctly!\n");
0164         nfsd4_client_tracking_exit(clp->net);
0165     }
0166 }
0167 
0168 static void
0169 __nfsd4_create_reclaim_record_grace(struct nfs4_client *clp,
0170         const char *dname, int len, struct nfsd_net *nn)
0171 {
0172     struct xdr_netobj name;
0173     struct xdr_netobj princhash = { .len = 0, .data = NULL };
0174     struct nfs4_client_reclaim *crp;
0175 
0176     name.data = kmemdup(dname, len, GFP_KERNEL);
0177     if (!name.data) {
0178         dprintk("%s: failed to allocate memory for name.data!\n",
0179             __func__);
0180         return;
0181     }
0182     name.len = len;
0183     crp = nfs4_client_to_reclaim(name, princhash, nn);
0184     if (!crp) {
0185         kfree(name.data);
0186         return;
0187     }
0188     crp->cr_clp = clp;
0189 }
0190 
0191 static void
0192 nfsd4_create_clid_dir(struct nfs4_client *clp)
0193 {
0194     const struct cred *original_cred;
0195     char dname[HEXDIR_LEN];
0196     struct dentry *dir, *dentry;
0197     int status;
0198     struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
0199 
0200     if (test_and_set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
0201         return;
0202     if (!nn->rec_file)
0203         return;
0204 
0205     status = nfs4_make_rec_clidname(dname, &clp->cl_name);
0206     if (status)
0207         return legacy_recdir_name_error(clp, status);
0208 
0209     status = nfs4_save_creds(&original_cred);
0210     if (status < 0)
0211         return;
0212 
0213     status = mnt_want_write_file(nn->rec_file);
0214     if (status)
0215         goto out_creds;
0216 
0217     dir = nn->rec_file->f_path.dentry;
0218     /* lock the parent */
0219     inode_lock(d_inode(dir));
0220 
0221     dentry = lookup_one_len(dname, dir, HEXDIR_LEN-1);
0222     if (IS_ERR(dentry)) {
0223         status = PTR_ERR(dentry);
0224         goto out_unlock;
0225     }
0226     if (d_really_is_positive(dentry))
0227         /*
0228          * In the 4.1 case, where we're called from
0229          * reclaim_complete(), records from the previous reboot
0230          * may still be left, so this is OK.
0231          *
0232          * In the 4.0 case, we should never get here; but we may
0233          * as well be forgiving and just succeed silently.
0234          */
0235         goto out_put;
0236     status = vfs_mkdir(&init_user_ns, d_inode(dir), dentry, S_IRWXU);
0237 out_put:
0238     dput(dentry);
0239 out_unlock:
0240     inode_unlock(d_inode(dir));
0241     if (status == 0) {
0242         if (nn->in_grace)
0243             __nfsd4_create_reclaim_record_grace(clp, dname,
0244                     HEXDIR_LEN, nn);
0245         vfs_fsync(nn->rec_file, 0);
0246     } else {
0247         printk(KERN_ERR "NFSD: failed to write recovery record"
0248                 " (err %d); please check that %s exists"
0249                 " and is writeable", status,
0250                 user_recovery_dirname);
0251     }
0252     mnt_drop_write_file(nn->rec_file);
0253 out_creds:
0254     nfs4_reset_creds(original_cred);
0255 }
0256 
0257 typedef int (recdir_func)(struct dentry *, struct dentry *, struct nfsd_net *);
0258 
0259 struct name_list {
0260     char name[HEXDIR_LEN];
0261     struct list_head list;
0262 };
0263 
0264 struct nfs4_dir_ctx {
0265     struct dir_context ctx;
0266     struct list_head names;
0267 };
0268 
0269 static int
0270 nfsd4_build_namelist(struct dir_context *__ctx, const char *name, int namlen,
0271         loff_t offset, u64 ino, unsigned int d_type)
0272 {
0273     struct nfs4_dir_ctx *ctx =
0274         container_of(__ctx, struct nfs4_dir_ctx, ctx);
0275     struct name_list *entry;
0276 
0277     if (namlen != HEXDIR_LEN - 1)
0278         return 0;
0279     entry = kmalloc(sizeof(struct name_list), GFP_KERNEL);
0280     if (entry == NULL)
0281         return -ENOMEM;
0282     memcpy(entry->name, name, HEXDIR_LEN - 1);
0283     entry->name[HEXDIR_LEN - 1] = '\0';
0284     list_add(&entry->list, &ctx->names);
0285     return 0;
0286 }
0287 
0288 static int
0289 nfsd4_list_rec_dir(recdir_func *f, struct nfsd_net *nn)
0290 {
0291     const struct cred *original_cred;
0292     struct dentry *dir = nn->rec_file->f_path.dentry;
0293     struct nfs4_dir_ctx ctx = {
0294         .ctx.actor = nfsd4_build_namelist,
0295         .names = LIST_HEAD_INIT(ctx.names)
0296     };
0297     struct name_list *entry, *tmp;
0298     int status;
0299 
0300     status = nfs4_save_creds(&original_cred);
0301     if (status < 0)
0302         return status;
0303 
0304     status = vfs_llseek(nn->rec_file, 0, SEEK_SET);
0305     if (status < 0) {
0306         nfs4_reset_creds(original_cred);
0307         return status;
0308     }
0309 
0310     status = iterate_dir(nn->rec_file, &ctx.ctx);
0311     inode_lock_nested(d_inode(dir), I_MUTEX_PARENT);
0312 
0313     list_for_each_entry_safe(entry, tmp, &ctx.names, list) {
0314         if (!status) {
0315             struct dentry *dentry;
0316             dentry = lookup_one_len(entry->name, dir, HEXDIR_LEN-1);
0317             if (IS_ERR(dentry)) {
0318                 status = PTR_ERR(dentry);
0319                 break;
0320             }
0321             status = f(dir, dentry, nn);
0322             dput(dentry);
0323         }
0324         list_del(&entry->list);
0325         kfree(entry);
0326     }
0327     inode_unlock(d_inode(dir));
0328     nfs4_reset_creds(original_cred);
0329 
0330     list_for_each_entry_safe(entry, tmp, &ctx.names, list) {
0331         dprintk("NFSD: %s. Left entry %s\n", __func__, entry->name);
0332         list_del(&entry->list);
0333         kfree(entry);
0334     }
0335     return status;
0336 }
0337 
0338 static int
0339 nfsd4_unlink_clid_dir(char *name, int namlen, struct nfsd_net *nn)
0340 {
0341     struct dentry *dir, *dentry;
0342     int status;
0343 
0344     dprintk("NFSD: nfsd4_unlink_clid_dir. name %.*s\n", namlen, name);
0345 
0346     dir = nn->rec_file->f_path.dentry;
0347     inode_lock_nested(d_inode(dir), I_MUTEX_PARENT);
0348     dentry = lookup_one_len(name, dir, namlen);
0349     if (IS_ERR(dentry)) {
0350         status = PTR_ERR(dentry);
0351         goto out_unlock;
0352     }
0353     status = -ENOENT;
0354     if (d_really_is_negative(dentry))
0355         goto out;
0356     status = vfs_rmdir(&init_user_ns, d_inode(dir), dentry);
0357 out:
0358     dput(dentry);
0359 out_unlock:
0360     inode_unlock(d_inode(dir));
0361     return status;
0362 }
0363 
0364 static void
0365 __nfsd4_remove_reclaim_record_grace(const char *dname, int len,
0366         struct nfsd_net *nn)
0367 {
0368     struct xdr_netobj name;
0369     struct nfs4_client_reclaim *crp;
0370 
0371     name.data = kmemdup(dname, len, GFP_KERNEL);
0372     if (!name.data) {
0373         dprintk("%s: failed to allocate memory for name.data!\n",
0374             __func__);
0375         return;
0376     }
0377     name.len = len;
0378     crp = nfsd4_find_reclaim_client(name, nn);
0379     kfree(name.data);
0380     if (crp)
0381         nfs4_remove_reclaim_record(crp, nn);
0382 }
0383 
0384 static void
0385 nfsd4_remove_clid_dir(struct nfs4_client *clp)
0386 {
0387     const struct cred *original_cred;
0388     char dname[HEXDIR_LEN];
0389     int status;
0390     struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
0391 
0392     if (!nn->rec_file || !test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
0393         return;
0394 
0395     status = nfs4_make_rec_clidname(dname, &clp->cl_name);
0396     if (status)
0397         return legacy_recdir_name_error(clp, status);
0398 
0399     status = mnt_want_write_file(nn->rec_file);
0400     if (status)
0401         goto out;
0402     clear_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
0403 
0404     status = nfs4_save_creds(&original_cred);
0405     if (status < 0)
0406         goto out_drop_write;
0407 
0408     status = nfsd4_unlink_clid_dir(dname, HEXDIR_LEN-1, nn);
0409     nfs4_reset_creds(original_cred);
0410     if (status == 0) {
0411         vfs_fsync(nn->rec_file, 0);
0412         if (nn->in_grace)
0413             __nfsd4_remove_reclaim_record_grace(dname,
0414                     HEXDIR_LEN, nn);
0415     }
0416 out_drop_write:
0417     mnt_drop_write_file(nn->rec_file);
0418 out:
0419     if (status)
0420         printk("NFSD: Failed to remove expired client state directory"
0421                 " %.*s\n", HEXDIR_LEN, dname);
0422 }
0423 
0424 static int
0425 purge_old(struct dentry *parent, struct dentry *child, struct nfsd_net *nn)
0426 {
0427     int status;
0428     struct xdr_netobj name;
0429 
0430     if (child->d_name.len != HEXDIR_LEN - 1) {
0431         printk("%s: illegal name %pd in recovery directory\n",
0432                 __func__, child);
0433         /* Keep trying; maybe the others are OK: */
0434         return 0;
0435     }
0436     name.data = kmemdup_nul(child->d_name.name, child->d_name.len, GFP_KERNEL);
0437     if (!name.data) {
0438         dprintk("%s: failed to allocate memory for name.data!\n",
0439             __func__);
0440         goto out;
0441     }
0442     name.len = HEXDIR_LEN;
0443     if (nfs4_has_reclaimed_state(name, nn))
0444         goto out_free;
0445 
0446     status = vfs_rmdir(&init_user_ns, d_inode(parent), child);
0447     if (status)
0448         printk("failed to remove client recovery directory %pd\n",
0449                 child);
0450 out_free:
0451     kfree(name.data);
0452 out:
0453     /* Keep trying, success or failure: */
0454     return 0;
0455 }
0456 
0457 static void
0458 nfsd4_recdir_purge_old(struct nfsd_net *nn)
0459 {
0460     int status;
0461 
0462     nn->in_grace = false;
0463     if (!nn->rec_file)
0464         return;
0465     status = mnt_want_write_file(nn->rec_file);
0466     if (status)
0467         goto out;
0468     status = nfsd4_list_rec_dir(purge_old, nn);
0469     if (status == 0)
0470         vfs_fsync(nn->rec_file, 0);
0471     mnt_drop_write_file(nn->rec_file);
0472 out:
0473     nfs4_release_reclaim(nn);
0474     if (status)
0475         printk("nfsd4: failed to purge old clients from recovery"
0476             " directory %pD\n", nn->rec_file);
0477 }
0478 
0479 static int
0480 load_recdir(struct dentry *parent, struct dentry *child, struct nfsd_net *nn)
0481 {
0482     struct xdr_netobj name;
0483     struct xdr_netobj princhash = { .len = 0, .data = NULL };
0484 
0485     if (child->d_name.len != HEXDIR_LEN - 1) {
0486         printk("%s: illegal name %pd in recovery directory\n",
0487                 __func__, child);
0488         /* Keep trying; maybe the others are OK: */
0489         return 0;
0490     }
0491     name.data = kmemdup_nul(child->d_name.name, child->d_name.len, GFP_KERNEL);
0492     if (!name.data) {
0493         dprintk("%s: failed to allocate memory for name.data!\n",
0494             __func__);
0495         goto out;
0496     }
0497     name.len = HEXDIR_LEN;
0498     if (!nfs4_client_to_reclaim(name, princhash, nn))
0499         kfree(name.data);
0500 out:
0501     return 0;
0502 }
0503 
0504 static int
0505 nfsd4_recdir_load(struct net *net) {
0506     int status;
0507     struct nfsd_net *nn =  net_generic(net, nfsd_net_id);
0508 
0509     if (!nn->rec_file)
0510         return 0;
0511 
0512     status = nfsd4_list_rec_dir(load_recdir, nn);
0513     if (status)
0514         printk("nfsd4: failed loading clients from recovery"
0515             " directory %pD\n", nn->rec_file);
0516     return status;
0517 }
0518 
0519 /*
0520  * Hold reference to the recovery directory.
0521  */
0522 
0523 static int
0524 nfsd4_init_recdir(struct net *net)
0525 {
0526     struct nfsd_net *nn = net_generic(net, nfsd_net_id);
0527     const struct cred *original_cred;
0528     int status;
0529 
0530     printk("NFSD: Using %s as the NFSv4 state recovery directory\n",
0531             user_recovery_dirname);
0532 
0533     BUG_ON(nn->rec_file);
0534 
0535     status = nfs4_save_creds(&original_cred);
0536     if (status < 0) {
0537         printk("NFSD: Unable to change credentials to find recovery"
0538                " directory: error %d\n",
0539                status);
0540         return status;
0541     }
0542 
0543     nn->rec_file = filp_open(user_recovery_dirname, O_RDONLY | O_DIRECTORY, 0);
0544     if (IS_ERR(nn->rec_file)) {
0545         printk("NFSD: unable to find recovery directory %s\n",
0546                 user_recovery_dirname);
0547         status = PTR_ERR(nn->rec_file);
0548         nn->rec_file = NULL;
0549     }
0550 
0551     nfs4_reset_creds(original_cred);
0552     if (!status)
0553         nn->in_grace = true;
0554     return status;
0555 }
0556 
0557 static void
0558 nfsd4_shutdown_recdir(struct net *net)
0559 {
0560     struct nfsd_net *nn = net_generic(net, nfsd_net_id);
0561 
0562     if (!nn->rec_file)
0563         return;
0564     fput(nn->rec_file);
0565     nn->rec_file = NULL;
0566 }
0567 
0568 static int
0569 nfs4_legacy_state_init(struct net *net)
0570 {
0571     struct nfsd_net *nn = net_generic(net, nfsd_net_id);
0572     int i;
0573 
0574     nn->reclaim_str_hashtbl = kmalloc_array(CLIENT_HASH_SIZE,
0575                         sizeof(struct list_head),
0576                         GFP_KERNEL);
0577     if (!nn->reclaim_str_hashtbl)
0578         return -ENOMEM;
0579 
0580     for (i = 0; i < CLIENT_HASH_SIZE; i++)
0581         INIT_LIST_HEAD(&nn->reclaim_str_hashtbl[i]);
0582     nn->reclaim_str_hashtbl_size = 0;
0583 
0584     return 0;
0585 }
0586 
0587 static void
0588 nfs4_legacy_state_shutdown(struct net *net)
0589 {
0590     struct nfsd_net *nn = net_generic(net, nfsd_net_id);
0591 
0592     kfree(nn->reclaim_str_hashtbl);
0593 }
0594 
0595 static int
0596 nfsd4_load_reboot_recovery_data(struct net *net)
0597 {
0598     int status;
0599 
0600     status = nfsd4_init_recdir(net);
0601     if (status)
0602         return status;
0603 
0604     status = nfsd4_recdir_load(net);
0605     if (status)
0606         nfsd4_shutdown_recdir(net);
0607 
0608     return status;
0609 }
0610 
0611 static int
0612 nfsd4_legacy_tracking_init(struct net *net)
0613 {
0614     int status;
0615 
0616     /* XXX: The legacy code won't work in a container */
0617     if (net != &init_net) {
0618         pr_warn("NFSD: attempt to initialize legacy client tracking in a container ignored.\n");
0619         return -EINVAL;
0620     }
0621 
0622     status = nfs4_legacy_state_init(net);
0623     if (status)
0624         return status;
0625 
0626     status = nfsd4_load_reboot_recovery_data(net);
0627     if (status)
0628         goto err;
0629     pr_info("NFSD: Using legacy client tracking operations.\n");
0630     return 0;
0631 
0632 err:
0633     nfs4_legacy_state_shutdown(net);
0634     return status;
0635 }
0636 
0637 static void
0638 nfsd4_legacy_tracking_exit(struct net *net)
0639 {
0640     struct nfsd_net *nn = net_generic(net, nfsd_net_id);
0641 
0642     nfs4_release_reclaim(nn);
0643     nfsd4_shutdown_recdir(net);
0644     nfs4_legacy_state_shutdown(net);
0645 }
0646 
0647 /*
0648  * Change the NFSv4 recovery directory to recdir.
0649  */
0650 int
0651 nfs4_reset_recoverydir(char *recdir)
0652 {
0653     int status;
0654     struct path path;
0655 
0656     status = kern_path(recdir, LOOKUP_FOLLOW, &path);
0657     if (status)
0658         return status;
0659     status = -ENOTDIR;
0660     if (d_is_dir(path.dentry)) {
0661         strcpy(user_recovery_dirname, recdir);
0662         status = 0;
0663     }
0664     path_put(&path);
0665     return status;
0666 }
0667 
0668 char *
0669 nfs4_recoverydir(void)
0670 {
0671     return user_recovery_dirname;
0672 }
0673 
0674 static int
0675 nfsd4_check_legacy_client(struct nfs4_client *clp)
0676 {
0677     int status;
0678     char dname[HEXDIR_LEN];
0679     struct nfs4_client_reclaim *crp;
0680     struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
0681     struct xdr_netobj name;
0682 
0683     /* did we already find that this client is stable? */
0684     if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
0685         return 0;
0686 
0687     status = nfs4_make_rec_clidname(dname, &clp->cl_name);
0688     if (status) {
0689         legacy_recdir_name_error(clp, status);
0690         return status;
0691     }
0692 
0693     /* look for it in the reclaim hashtable otherwise */
0694     name.data = kmemdup(dname, HEXDIR_LEN, GFP_KERNEL);
0695     if (!name.data) {
0696         dprintk("%s: failed to allocate memory for name.data!\n",
0697             __func__);
0698         goto out_enoent;
0699     }
0700     name.len = HEXDIR_LEN;
0701     crp = nfsd4_find_reclaim_client(name, nn);
0702     kfree(name.data);
0703     if (crp) {
0704         set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
0705         crp->cr_clp = clp;
0706         return 0;
0707     }
0708 
0709 out_enoent:
0710     return -ENOENT;
0711 }
0712 
0713 static const struct nfsd4_client_tracking_ops nfsd4_legacy_tracking_ops = {
0714     .init       = nfsd4_legacy_tracking_init,
0715     .exit       = nfsd4_legacy_tracking_exit,
0716     .create     = nfsd4_create_clid_dir,
0717     .remove     = nfsd4_remove_clid_dir,
0718     .check      = nfsd4_check_legacy_client,
0719     .grace_done = nfsd4_recdir_purge_old,
0720     .version    = 1,
0721     .msglen     = 0,
0722 };
0723 
0724 /* Globals */
0725 #define NFSD_PIPE_DIR       "nfsd"
0726 #define NFSD_CLD_PIPE       "cld"
0727 
0728 /* per-net-ns structure for holding cld upcall info */
0729 struct cld_net {
0730     struct rpc_pipe     *cn_pipe;
0731     spinlock_t       cn_lock;
0732     struct list_head     cn_list;
0733     unsigned int         cn_xid;
0734     bool             cn_has_legacy;
0735     struct crypto_shash *cn_tfm;
0736 };
0737 
0738 struct cld_upcall {
0739     struct list_head     cu_list;
0740     struct cld_net      *cu_net;
0741     struct completion    cu_done;
0742     union {
0743         struct cld_msg_hdr   cu_hdr;
0744         struct cld_msg       cu_msg;
0745         struct cld_msg_v2    cu_msg_v2;
0746     } cu_u;
0747 };
0748 
0749 static int
0750 __cld_pipe_upcall(struct rpc_pipe *pipe, void *cmsg, struct nfsd_net *nn)
0751 {
0752     int ret;
0753     struct rpc_pipe_msg msg;
0754     struct cld_upcall *cup = container_of(cmsg, struct cld_upcall, cu_u);
0755 
0756     memset(&msg, 0, sizeof(msg));
0757     msg.data = cmsg;
0758     msg.len = nn->client_tracking_ops->msglen;
0759 
0760     ret = rpc_queue_upcall(pipe, &msg);
0761     if (ret < 0) {
0762         goto out;
0763     }
0764 
0765     wait_for_completion(&cup->cu_done);
0766 
0767     if (msg.errno < 0)
0768         ret = msg.errno;
0769 out:
0770     return ret;
0771 }
0772 
0773 static int
0774 cld_pipe_upcall(struct rpc_pipe *pipe, void *cmsg, struct nfsd_net *nn)
0775 {
0776     int ret;
0777 
0778     /*
0779      * -EAGAIN occurs when pipe is closed and reopened while there are
0780      *  upcalls queued.
0781      */
0782     do {
0783         ret = __cld_pipe_upcall(pipe, cmsg, nn);
0784     } while (ret == -EAGAIN);
0785 
0786     return ret;
0787 }
0788 
0789 static ssize_t
0790 __cld_pipe_inprogress_downcall(const struct cld_msg_v2 __user *cmsg,
0791         struct nfsd_net *nn)
0792 {
0793     uint8_t cmd, princhashlen;
0794     struct xdr_netobj name, princhash = { .len = 0, .data = NULL };
0795     uint16_t namelen;
0796     struct cld_net *cn = nn->cld_net;
0797 
0798     if (get_user(cmd, &cmsg->cm_cmd)) {
0799         dprintk("%s: error when copying cmd from userspace", __func__);
0800         return -EFAULT;
0801     }
0802     if (cmd == Cld_GraceStart) {
0803         if (nn->client_tracking_ops->version >= 2) {
0804             const struct cld_clntinfo __user *ci;
0805 
0806             ci = &cmsg->cm_u.cm_clntinfo;
0807             if (get_user(namelen, &ci->cc_name.cn_len))
0808                 return -EFAULT;
0809             name.data = memdup_user(&ci->cc_name.cn_id, namelen);
0810             if (IS_ERR_OR_NULL(name.data))
0811                 return -EFAULT;
0812             name.len = namelen;
0813             get_user(princhashlen, &ci->cc_princhash.cp_len);
0814             if (princhashlen > 0) {
0815                 princhash.data = memdup_user(
0816                         &ci->cc_princhash.cp_data,
0817                         princhashlen);
0818                 if (IS_ERR_OR_NULL(princhash.data))
0819                     return -EFAULT;
0820                 princhash.len = princhashlen;
0821             } else
0822                 princhash.len = 0;
0823         } else {
0824             const struct cld_name __user *cnm;
0825 
0826             cnm = &cmsg->cm_u.cm_name;
0827             if (get_user(namelen, &cnm->cn_len))
0828                 return -EFAULT;
0829             name.data = memdup_user(&cnm->cn_id, namelen);
0830             if (IS_ERR_OR_NULL(name.data))
0831                 return -EFAULT;
0832             name.len = namelen;
0833         }
0834         if (name.len > 5 && memcmp(name.data, "hash:", 5) == 0) {
0835             name.len = name.len - 5;
0836             memmove(name.data, name.data + 5, name.len);
0837             cn->cn_has_legacy = true;
0838         }
0839         if (!nfs4_client_to_reclaim(name, princhash, nn)) {
0840             kfree(name.data);
0841             kfree(princhash.data);
0842             return -EFAULT;
0843         }
0844         return nn->client_tracking_ops->msglen;
0845     }
0846     return -EFAULT;
0847 }
0848 
0849 static ssize_t
0850 cld_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
0851 {
0852     struct cld_upcall *tmp, *cup;
0853     struct cld_msg_hdr __user *hdr = (struct cld_msg_hdr __user *)src;
0854     struct cld_msg_v2 __user *cmsg = (struct cld_msg_v2 __user *)src;
0855     uint32_t xid;
0856     struct nfsd_net *nn = net_generic(file_inode(filp)->i_sb->s_fs_info,
0857                         nfsd_net_id);
0858     struct cld_net *cn = nn->cld_net;
0859     int16_t status;
0860 
0861     if (mlen != nn->client_tracking_ops->msglen) {
0862         dprintk("%s: got %zu bytes, expected %zu\n", __func__, mlen,
0863             nn->client_tracking_ops->msglen);
0864         return -EINVAL;
0865     }
0866 
0867     /* copy just the xid so we can try to find that */
0868     if (copy_from_user(&xid, &hdr->cm_xid, sizeof(xid)) != 0) {
0869         dprintk("%s: error when copying xid from userspace", __func__);
0870         return -EFAULT;
0871     }
0872 
0873     /*
0874      * copy the status so we know whether to remove the upcall from the
0875      * list (for -EINPROGRESS, we just want to make sure the xid is
0876      * valid, not remove the upcall from the list)
0877      */
0878     if (get_user(status, &hdr->cm_status)) {
0879         dprintk("%s: error when copying status from userspace", __func__);
0880         return -EFAULT;
0881     }
0882 
0883     /* walk the list and find corresponding xid */
0884     cup = NULL;
0885     spin_lock(&cn->cn_lock);
0886     list_for_each_entry(tmp, &cn->cn_list, cu_list) {
0887         if (get_unaligned(&tmp->cu_u.cu_hdr.cm_xid) == xid) {
0888             cup = tmp;
0889             if (status != -EINPROGRESS)
0890                 list_del_init(&cup->cu_list);
0891             break;
0892         }
0893     }
0894     spin_unlock(&cn->cn_lock);
0895 
0896     /* couldn't find upcall? */
0897     if (!cup) {
0898         dprintk("%s: couldn't find upcall -- xid=%u\n", __func__, xid);
0899         return -EINVAL;
0900     }
0901 
0902     if (status == -EINPROGRESS)
0903         return __cld_pipe_inprogress_downcall(cmsg, nn);
0904 
0905     if (copy_from_user(&cup->cu_u.cu_msg_v2, src, mlen) != 0)
0906         return -EFAULT;
0907 
0908     complete(&cup->cu_done);
0909     return mlen;
0910 }
0911 
0912 static void
0913 cld_pipe_destroy_msg(struct rpc_pipe_msg *msg)
0914 {
0915     struct cld_msg *cmsg = msg->data;
0916     struct cld_upcall *cup = container_of(cmsg, struct cld_upcall,
0917                          cu_u.cu_msg);
0918 
0919     /* errno >= 0 means we got a downcall */
0920     if (msg->errno >= 0)
0921         return;
0922 
0923     complete(&cup->cu_done);
0924 }
0925 
0926 static const struct rpc_pipe_ops cld_upcall_ops = {
0927     .upcall     = rpc_pipe_generic_upcall,
0928     .downcall   = cld_pipe_downcall,
0929     .destroy_msg    = cld_pipe_destroy_msg,
0930 };
0931 
0932 static struct dentry *
0933 nfsd4_cld_register_sb(struct super_block *sb, struct rpc_pipe *pipe)
0934 {
0935     struct dentry *dir, *dentry;
0936 
0937     dir = rpc_d_lookup_sb(sb, NFSD_PIPE_DIR);
0938     if (dir == NULL)
0939         return ERR_PTR(-ENOENT);
0940     dentry = rpc_mkpipe_dentry(dir, NFSD_CLD_PIPE, NULL, pipe);
0941     dput(dir);
0942     return dentry;
0943 }
0944 
0945 static void
0946 nfsd4_cld_unregister_sb(struct rpc_pipe *pipe)
0947 {
0948     if (pipe->dentry)
0949         rpc_unlink(pipe->dentry);
0950 }
0951 
0952 static struct dentry *
0953 nfsd4_cld_register_net(struct net *net, struct rpc_pipe *pipe)
0954 {
0955     struct super_block *sb;
0956     struct dentry *dentry;
0957 
0958     sb = rpc_get_sb_net(net);
0959     if (!sb)
0960         return NULL;
0961     dentry = nfsd4_cld_register_sb(sb, pipe);
0962     rpc_put_sb_net(net);
0963     return dentry;
0964 }
0965 
0966 static void
0967 nfsd4_cld_unregister_net(struct net *net, struct rpc_pipe *pipe)
0968 {
0969     struct super_block *sb;
0970 
0971     sb = rpc_get_sb_net(net);
0972     if (sb) {
0973         nfsd4_cld_unregister_sb(pipe);
0974         rpc_put_sb_net(net);
0975     }
0976 }
0977 
0978 /* Initialize rpc_pipefs pipe for communication with client tracking daemon */
0979 static int
0980 __nfsd4_init_cld_pipe(struct net *net)
0981 {
0982     int ret;
0983     struct dentry *dentry;
0984     struct nfsd_net *nn = net_generic(net, nfsd_net_id);
0985     struct cld_net *cn;
0986 
0987     if (nn->cld_net)
0988         return 0;
0989 
0990     cn = kzalloc(sizeof(*cn), GFP_KERNEL);
0991     if (!cn) {
0992         ret = -ENOMEM;
0993         goto err;
0994     }
0995 
0996     cn->cn_pipe = rpc_mkpipe_data(&cld_upcall_ops, RPC_PIPE_WAIT_FOR_OPEN);
0997     if (IS_ERR(cn->cn_pipe)) {
0998         ret = PTR_ERR(cn->cn_pipe);
0999         goto err;
1000     }
1001     spin_lock_init(&cn->cn_lock);
1002     INIT_LIST_HEAD(&cn->cn_list);
1003 
1004     dentry = nfsd4_cld_register_net(net, cn->cn_pipe);
1005     if (IS_ERR(dentry)) {
1006         ret = PTR_ERR(dentry);
1007         goto err_destroy_data;
1008     }
1009 
1010     cn->cn_pipe->dentry = dentry;
1011     cn->cn_has_legacy = false;
1012     nn->cld_net = cn;
1013     return 0;
1014 
1015 err_destroy_data:
1016     rpc_destroy_pipe_data(cn->cn_pipe);
1017 err:
1018     kfree(cn);
1019     printk(KERN_ERR "NFSD: unable to create nfsdcld upcall pipe (%d)\n",
1020             ret);
1021     return ret;
1022 }
1023 
1024 static int
1025 nfsd4_init_cld_pipe(struct net *net)
1026 {
1027     int status;
1028 
1029     status = __nfsd4_init_cld_pipe(net);
1030     if (!status)
1031         pr_info("NFSD: Using old nfsdcld client tracking operations.\n");
1032     return status;
1033 }
1034 
1035 static void
1036 nfsd4_remove_cld_pipe(struct net *net)
1037 {
1038     struct nfsd_net *nn = net_generic(net, nfsd_net_id);
1039     struct cld_net *cn = nn->cld_net;
1040 
1041     nfsd4_cld_unregister_net(net, cn->cn_pipe);
1042     rpc_destroy_pipe_data(cn->cn_pipe);
1043     if (cn->cn_tfm)
1044         crypto_free_shash(cn->cn_tfm);
1045     kfree(nn->cld_net);
1046     nn->cld_net = NULL;
1047 }
1048 
1049 static struct cld_upcall *
1050 alloc_cld_upcall(struct nfsd_net *nn)
1051 {
1052     struct cld_upcall *new, *tmp;
1053     struct cld_net *cn = nn->cld_net;
1054 
1055     new = kzalloc(sizeof(*new), GFP_KERNEL);
1056     if (!new)
1057         return new;
1058 
1059     /* FIXME: hard cap on number in flight? */
1060 restart_search:
1061     spin_lock(&cn->cn_lock);
1062     list_for_each_entry(tmp, &cn->cn_list, cu_list) {
1063         if (tmp->cu_u.cu_msg.cm_xid == cn->cn_xid) {
1064             cn->cn_xid++;
1065             spin_unlock(&cn->cn_lock);
1066             goto restart_search;
1067         }
1068     }
1069     init_completion(&new->cu_done);
1070     new->cu_u.cu_msg.cm_vers = nn->client_tracking_ops->version;
1071     put_unaligned(cn->cn_xid++, &new->cu_u.cu_msg.cm_xid);
1072     new->cu_net = cn;
1073     list_add(&new->cu_list, &cn->cn_list);
1074     spin_unlock(&cn->cn_lock);
1075 
1076     dprintk("%s: allocated xid %u\n", __func__, new->cu_u.cu_msg.cm_xid);
1077 
1078     return new;
1079 }
1080 
1081 static void
1082 free_cld_upcall(struct cld_upcall *victim)
1083 {
1084     struct cld_net *cn = victim->cu_net;
1085 
1086     spin_lock(&cn->cn_lock);
1087     list_del(&victim->cu_list);
1088     spin_unlock(&cn->cn_lock);
1089     kfree(victim);
1090 }
1091 
1092 /* Ask daemon to create a new record */
1093 static void
1094 nfsd4_cld_create(struct nfs4_client *clp)
1095 {
1096     int ret;
1097     struct cld_upcall *cup;
1098     struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
1099     struct cld_net *cn = nn->cld_net;
1100 
1101     /* Don't upcall if it's already stored */
1102     if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
1103         return;
1104 
1105     cup = alloc_cld_upcall(nn);
1106     if (!cup) {
1107         ret = -ENOMEM;
1108         goto out_err;
1109     }
1110 
1111     cup->cu_u.cu_msg.cm_cmd = Cld_Create;
1112     cup->cu_u.cu_msg.cm_u.cm_name.cn_len = clp->cl_name.len;
1113     memcpy(cup->cu_u.cu_msg.cm_u.cm_name.cn_id, clp->cl_name.data,
1114             clp->cl_name.len);
1115 
1116     ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn);
1117     if (!ret) {
1118         ret = cup->cu_u.cu_msg.cm_status;
1119         set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
1120     }
1121 
1122     free_cld_upcall(cup);
1123 out_err:
1124     if (ret)
1125         printk(KERN_ERR "NFSD: Unable to create client "
1126                 "record on stable storage: %d\n", ret);
1127 }
1128 
1129 /* Ask daemon to create a new record */
1130 static void
1131 nfsd4_cld_create_v2(struct nfs4_client *clp)
1132 {
1133     int ret;
1134     struct cld_upcall *cup;
1135     struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
1136     struct cld_net *cn = nn->cld_net;
1137     struct cld_msg_v2 *cmsg;
1138     struct crypto_shash *tfm = cn->cn_tfm;
1139     struct xdr_netobj cksum;
1140     char *principal = NULL;
1141 
1142     /* Don't upcall if it's already stored */
1143     if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
1144         return;
1145 
1146     cup = alloc_cld_upcall(nn);
1147     if (!cup) {
1148         ret = -ENOMEM;
1149         goto out_err;
1150     }
1151 
1152     cmsg = &cup->cu_u.cu_msg_v2;
1153     cmsg->cm_cmd = Cld_Create;
1154     cmsg->cm_u.cm_clntinfo.cc_name.cn_len = clp->cl_name.len;
1155     memcpy(cmsg->cm_u.cm_clntinfo.cc_name.cn_id, clp->cl_name.data,
1156             clp->cl_name.len);
1157     if (clp->cl_cred.cr_raw_principal)
1158         principal = clp->cl_cred.cr_raw_principal;
1159     else if (clp->cl_cred.cr_principal)
1160         principal = clp->cl_cred.cr_principal;
1161     if (principal) {
1162         cksum.len = crypto_shash_digestsize(tfm);
1163         cksum.data = kmalloc(cksum.len, GFP_KERNEL);
1164         if (cksum.data == NULL) {
1165             ret = -ENOMEM;
1166             goto out;
1167         }
1168         ret = crypto_shash_tfm_digest(tfm, principal, strlen(principal),
1169                           cksum.data);
1170         if (ret) {
1171             kfree(cksum.data);
1172             goto out;
1173         }
1174         cmsg->cm_u.cm_clntinfo.cc_princhash.cp_len = cksum.len;
1175         memcpy(cmsg->cm_u.cm_clntinfo.cc_princhash.cp_data,
1176                cksum.data, cksum.len);
1177         kfree(cksum.data);
1178     } else
1179         cmsg->cm_u.cm_clntinfo.cc_princhash.cp_len = 0;
1180 
1181     ret = cld_pipe_upcall(cn->cn_pipe, cmsg, nn);
1182     if (!ret) {
1183         ret = cmsg->cm_status;
1184         set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
1185     }
1186 
1187 out:
1188     free_cld_upcall(cup);
1189 out_err:
1190     if (ret)
1191         pr_err("NFSD: Unable to create client record on stable storage: %d\n",
1192                 ret);
1193 }
1194 
1195 /* Ask daemon to create a new record */
1196 static void
1197 nfsd4_cld_remove(struct nfs4_client *clp)
1198 {
1199     int ret;
1200     struct cld_upcall *cup;
1201     struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
1202     struct cld_net *cn = nn->cld_net;
1203 
1204     /* Don't upcall if it's already removed */
1205     if (!test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
1206         return;
1207 
1208     cup = alloc_cld_upcall(nn);
1209     if (!cup) {
1210         ret = -ENOMEM;
1211         goto out_err;
1212     }
1213 
1214     cup->cu_u.cu_msg.cm_cmd = Cld_Remove;
1215     cup->cu_u.cu_msg.cm_u.cm_name.cn_len = clp->cl_name.len;
1216     memcpy(cup->cu_u.cu_msg.cm_u.cm_name.cn_id, clp->cl_name.data,
1217             clp->cl_name.len);
1218 
1219     ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn);
1220     if (!ret) {
1221         ret = cup->cu_u.cu_msg.cm_status;
1222         clear_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
1223     }
1224 
1225     free_cld_upcall(cup);
1226 out_err:
1227     if (ret)
1228         printk(KERN_ERR "NFSD: Unable to remove client "
1229                 "record from stable storage: %d\n", ret);
1230 }
1231 
1232 /*
1233  * For older nfsdcld's that do not allow us to "slurp" the clients
1234  * from the tracking database during startup.
1235  *
1236  * Check for presence of a record, and update its timestamp
1237  */
1238 static int
1239 nfsd4_cld_check_v0(struct nfs4_client *clp)
1240 {
1241     int ret;
1242     struct cld_upcall *cup;
1243     struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
1244     struct cld_net *cn = nn->cld_net;
1245 
1246     /* Don't upcall if one was already stored during this grace pd */
1247     if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
1248         return 0;
1249 
1250     cup = alloc_cld_upcall(nn);
1251     if (!cup) {
1252         printk(KERN_ERR "NFSD: Unable to check client record on "
1253                 "stable storage: %d\n", -ENOMEM);
1254         return -ENOMEM;
1255     }
1256 
1257     cup->cu_u.cu_msg.cm_cmd = Cld_Check;
1258     cup->cu_u.cu_msg.cm_u.cm_name.cn_len = clp->cl_name.len;
1259     memcpy(cup->cu_u.cu_msg.cm_u.cm_name.cn_id, clp->cl_name.data,
1260             clp->cl_name.len);
1261 
1262     ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn);
1263     if (!ret) {
1264         ret = cup->cu_u.cu_msg.cm_status;
1265         set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
1266     }
1267 
1268     free_cld_upcall(cup);
1269     return ret;
1270 }
1271 
1272 /*
1273  * For newer nfsdcld's that allow us to "slurp" the clients
1274  * from the tracking database during startup.
1275  *
1276  * Check for presence of a record in the reclaim_str_hashtbl
1277  */
1278 static int
1279 nfsd4_cld_check(struct nfs4_client *clp)
1280 {
1281     struct nfs4_client_reclaim *crp;
1282     struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
1283     struct cld_net *cn = nn->cld_net;
1284     int status;
1285     char dname[HEXDIR_LEN];
1286     struct xdr_netobj name;
1287 
1288     /* did we already find that this client is stable? */
1289     if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
1290         return 0;
1291 
1292     /* look for it in the reclaim hashtable otherwise */
1293     crp = nfsd4_find_reclaim_client(clp->cl_name, nn);
1294     if (crp)
1295         goto found;
1296 
1297     if (cn->cn_has_legacy) {
1298         status = nfs4_make_rec_clidname(dname, &clp->cl_name);
1299         if (status)
1300             return -ENOENT;
1301 
1302         name.data = kmemdup(dname, HEXDIR_LEN, GFP_KERNEL);
1303         if (!name.data) {
1304             dprintk("%s: failed to allocate memory for name.data!\n",
1305                 __func__);
1306             return -ENOENT;
1307         }
1308         name.len = HEXDIR_LEN;
1309         crp = nfsd4_find_reclaim_client(name, nn);
1310         kfree(name.data);
1311         if (crp)
1312             goto found;
1313 
1314     }
1315     return -ENOENT;
1316 found:
1317     crp->cr_clp = clp;
1318     return 0;
1319 }
1320 
1321 static int
1322 nfsd4_cld_check_v2(struct nfs4_client *clp)
1323 {
1324     struct nfs4_client_reclaim *crp;
1325     struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
1326     struct cld_net *cn = nn->cld_net;
1327     int status;
1328     char dname[HEXDIR_LEN];
1329     struct xdr_netobj name;
1330     struct crypto_shash *tfm = cn->cn_tfm;
1331     struct xdr_netobj cksum;
1332     char *principal = NULL;
1333 
1334     /* did we already find that this client is stable? */
1335     if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
1336         return 0;
1337 
1338     /* look for it in the reclaim hashtable otherwise */
1339     crp = nfsd4_find_reclaim_client(clp->cl_name, nn);
1340     if (crp)
1341         goto found;
1342 
1343     if (cn->cn_has_legacy) {
1344         status = nfs4_make_rec_clidname(dname, &clp->cl_name);
1345         if (status)
1346             return -ENOENT;
1347 
1348         name.data = kmemdup(dname, HEXDIR_LEN, GFP_KERNEL);
1349         if (!name.data) {
1350             dprintk("%s: failed to allocate memory for name.data\n",
1351                     __func__);
1352             return -ENOENT;
1353         }
1354         name.len = HEXDIR_LEN;
1355         crp = nfsd4_find_reclaim_client(name, nn);
1356         kfree(name.data);
1357         if (crp)
1358             goto found;
1359 
1360     }
1361     return -ENOENT;
1362 found:
1363     if (crp->cr_princhash.len) {
1364         if (clp->cl_cred.cr_raw_principal)
1365             principal = clp->cl_cred.cr_raw_principal;
1366         else if (clp->cl_cred.cr_principal)
1367             principal = clp->cl_cred.cr_principal;
1368         if (principal == NULL)
1369             return -ENOENT;
1370         cksum.len = crypto_shash_digestsize(tfm);
1371         cksum.data = kmalloc(cksum.len, GFP_KERNEL);
1372         if (cksum.data == NULL)
1373             return -ENOENT;
1374         status = crypto_shash_tfm_digest(tfm, principal,
1375                          strlen(principal), cksum.data);
1376         if (status) {
1377             kfree(cksum.data);
1378             return -ENOENT;
1379         }
1380         if (memcmp(crp->cr_princhash.data, cksum.data,
1381                 crp->cr_princhash.len)) {
1382             kfree(cksum.data);
1383             return -ENOENT;
1384         }
1385         kfree(cksum.data);
1386     }
1387     crp->cr_clp = clp;
1388     return 0;
1389 }
1390 
1391 static int
1392 nfsd4_cld_grace_start(struct nfsd_net *nn)
1393 {
1394     int ret;
1395     struct cld_upcall *cup;
1396     struct cld_net *cn = nn->cld_net;
1397 
1398     cup = alloc_cld_upcall(nn);
1399     if (!cup) {
1400         ret = -ENOMEM;
1401         goto out_err;
1402     }
1403 
1404     cup->cu_u.cu_msg.cm_cmd = Cld_GraceStart;
1405     ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn);
1406     if (!ret)
1407         ret = cup->cu_u.cu_msg.cm_status;
1408 
1409     free_cld_upcall(cup);
1410 out_err:
1411     if (ret)
1412         dprintk("%s: Unable to get clients from userspace: %d\n",
1413             __func__, ret);
1414     return ret;
1415 }
1416 
1417 /* For older nfsdcld's that need cm_gracetime */
1418 static void
1419 nfsd4_cld_grace_done_v0(struct nfsd_net *nn)
1420 {
1421     int ret;
1422     struct cld_upcall *cup;
1423     struct cld_net *cn = nn->cld_net;
1424 
1425     cup = alloc_cld_upcall(nn);
1426     if (!cup) {
1427         ret = -ENOMEM;
1428         goto out_err;
1429     }
1430 
1431     cup->cu_u.cu_msg.cm_cmd = Cld_GraceDone;
1432     cup->cu_u.cu_msg.cm_u.cm_gracetime = nn->boot_time;
1433     ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn);
1434     if (!ret)
1435         ret = cup->cu_u.cu_msg.cm_status;
1436 
1437     free_cld_upcall(cup);
1438 out_err:
1439     if (ret)
1440         printk(KERN_ERR "NFSD: Unable to end grace period: %d\n", ret);
1441 }
1442 
1443 /*
1444  * For newer nfsdcld's that do not need cm_gracetime.  We also need to call
1445  * nfs4_release_reclaim() to clear out the reclaim_str_hashtbl.
1446  */
1447 static void
1448 nfsd4_cld_grace_done(struct nfsd_net *nn)
1449 {
1450     int ret;
1451     struct cld_upcall *cup;
1452     struct cld_net *cn = nn->cld_net;
1453 
1454     cup = alloc_cld_upcall(nn);
1455     if (!cup) {
1456         ret = -ENOMEM;
1457         goto out_err;
1458     }
1459 
1460     cup->cu_u.cu_msg.cm_cmd = Cld_GraceDone;
1461     ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn);
1462     if (!ret)
1463         ret = cup->cu_u.cu_msg.cm_status;
1464 
1465     free_cld_upcall(cup);
1466 out_err:
1467     nfs4_release_reclaim(nn);
1468     if (ret)
1469         printk(KERN_ERR "NFSD: Unable to end grace period: %d\n", ret);
1470 }
1471 
1472 static int
1473 nfs4_cld_state_init(struct net *net)
1474 {
1475     struct nfsd_net *nn = net_generic(net, nfsd_net_id);
1476     int i;
1477 
1478     nn->reclaim_str_hashtbl = kmalloc_array(CLIENT_HASH_SIZE,
1479                         sizeof(struct list_head),
1480                         GFP_KERNEL);
1481     if (!nn->reclaim_str_hashtbl)
1482         return -ENOMEM;
1483 
1484     for (i = 0; i < CLIENT_HASH_SIZE; i++)
1485         INIT_LIST_HEAD(&nn->reclaim_str_hashtbl[i]);
1486     nn->reclaim_str_hashtbl_size = 0;
1487     nn->track_reclaim_completes = true;
1488     atomic_set(&nn->nr_reclaim_complete, 0);
1489 
1490     return 0;
1491 }
1492 
1493 static void
1494 nfs4_cld_state_shutdown(struct net *net)
1495 {
1496     struct nfsd_net *nn = net_generic(net, nfsd_net_id);
1497 
1498     nn->track_reclaim_completes = false;
1499     kfree(nn->reclaim_str_hashtbl);
1500 }
1501 
1502 static bool
1503 cld_running(struct nfsd_net *nn)
1504 {
1505     struct cld_net *cn = nn->cld_net;
1506     struct rpc_pipe *pipe = cn->cn_pipe;
1507 
1508     return pipe->nreaders || pipe->nwriters;
1509 }
1510 
1511 static int
1512 nfsd4_cld_get_version(struct nfsd_net *nn)
1513 {
1514     int ret = 0;
1515     struct cld_upcall *cup;
1516     struct cld_net *cn = nn->cld_net;
1517     uint8_t version;
1518 
1519     cup = alloc_cld_upcall(nn);
1520     if (!cup) {
1521         ret = -ENOMEM;
1522         goto out_err;
1523     }
1524     cup->cu_u.cu_msg.cm_cmd = Cld_GetVersion;
1525     ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_u.cu_msg, nn);
1526     if (!ret) {
1527         ret = cup->cu_u.cu_msg.cm_status;
1528         if (ret)
1529             goto out_free;
1530         version = cup->cu_u.cu_msg.cm_u.cm_version;
1531         dprintk("%s: userspace returned version %u\n",
1532                 __func__, version);
1533         if (version < 1)
1534             version = 1;
1535         else if (version > CLD_UPCALL_VERSION)
1536             version = CLD_UPCALL_VERSION;
1537 
1538         switch (version) {
1539         case 1:
1540             nn->client_tracking_ops = &nfsd4_cld_tracking_ops;
1541             break;
1542         case 2:
1543             nn->client_tracking_ops = &nfsd4_cld_tracking_ops_v2;
1544             break;
1545         default:
1546             break;
1547         }
1548     }
1549 out_free:
1550     free_cld_upcall(cup);
1551 out_err:
1552     if (ret)
1553         dprintk("%s: Unable to get version from userspace: %d\n",
1554             __func__, ret);
1555     return ret;
1556 }
1557 
1558 static int
1559 nfsd4_cld_tracking_init(struct net *net)
1560 {
1561     int status;
1562     struct nfsd_net *nn = net_generic(net, nfsd_net_id);
1563     bool running;
1564     int retries = 10;
1565     struct crypto_shash *tfm;
1566 
1567     status = nfs4_cld_state_init(net);
1568     if (status)
1569         return status;
1570 
1571     status = __nfsd4_init_cld_pipe(net);
1572     if (status)
1573         goto err_shutdown;
1574 
1575     /*
1576      * rpc pipe upcalls take 30 seconds to time out, so we don't want to
1577      * queue an upcall unless we know that nfsdcld is running (because we
1578      * want this to fail fast so that nfsd4_client_tracking_init() can try
1579      * the next client tracking method).  nfsdcld should already be running
1580      * before nfsd is started, so the wait here is for nfsdcld to open the
1581      * pipefs file we just created.
1582      */
1583     while (!(running = cld_running(nn)) && retries--)
1584         msleep(100);
1585 
1586     if (!running) {
1587         status = -ETIMEDOUT;
1588         goto err_remove;
1589     }
1590     tfm = crypto_alloc_shash("sha256", 0, 0);
1591     if (IS_ERR(tfm)) {
1592         status = PTR_ERR(tfm);
1593         goto err_remove;
1594     }
1595     nn->cld_net->cn_tfm = tfm;
1596 
1597     status = nfsd4_cld_get_version(nn);
1598     if (status == -EOPNOTSUPP)
1599         pr_warn("NFSD: nfsdcld GetVersion upcall failed. Please upgrade nfsdcld.\n");
1600 
1601     status = nfsd4_cld_grace_start(nn);
1602     if (status) {
1603         if (status == -EOPNOTSUPP)
1604             pr_warn("NFSD: nfsdcld GraceStart upcall failed. Please upgrade nfsdcld.\n");
1605         nfs4_release_reclaim(nn);
1606         goto err_remove;
1607     } else
1608         pr_info("NFSD: Using nfsdcld client tracking operations.\n");
1609     return 0;
1610 
1611 err_remove:
1612     nfsd4_remove_cld_pipe(net);
1613 err_shutdown:
1614     nfs4_cld_state_shutdown(net);
1615     return status;
1616 }
1617 
1618 static void
1619 nfsd4_cld_tracking_exit(struct net *net)
1620 {
1621     struct nfsd_net *nn = net_generic(net, nfsd_net_id);
1622 
1623     nfs4_release_reclaim(nn);
1624     nfsd4_remove_cld_pipe(net);
1625     nfs4_cld_state_shutdown(net);
1626 }
1627 
1628 /* For older nfsdcld's */
1629 static const struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops_v0 = {
1630     .init       = nfsd4_init_cld_pipe,
1631     .exit       = nfsd4_remove_cld_pipe,
1632     .create     = nfsd4_cld_create,
1633     .remove     = nfsd4_cld_remove,
1634     .check      = nfsd4_cld_check_v0,
1635     .grace_done = nfsd4_cld_grace_done_v0,
1636     .version    = 1,
1637     .msglen     = sizeof(struct cld_msg),
1638 };
1639 
1640 /* For newer nfsdcld's */
1641 static const struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops = {
1642     .init       = nfsd4_cld_tracking_init,
1643     .exit       = nfsd4_cld_tracking_exit,
1644     .create     = nfsd4_cld_create,
1645     .remove     = nfsd4_cld_remove,
1646     .check      = nfsd4_cld_check,
1647     .grace_done = nfsd4_cld_grace_done,
1648     .version    = 1,
1649     .msglen     = sizeof(struct cld_msg),
1650 };
1651 
1652 /* v2 create/check ops include the principal, if available */
1653 static const struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops_v2 = {
1654     .init       = nfsd4_cld_tracking_init,
1655     .exit       = nfsd4_cld_tracking_exit,
1656     .create     = nfsd4_cld_create_v2,
1657     .remove     = nfsd4_cld_remove,
1658     .check      = nfsd4_cld_check_v2,
1659     .grace_done = nfsd4_cld_grace_done,
1660     .version    = 2,
1661     .msglen     = sizeof(struct cld_msg_v2),
1662 };
1663 
1664 /* upcall via usermodehelper */
1665 static char cltrack_prog[PATH_MAX] = "/sbin/nfsdcltrack";
1666 module_param_string(cltrack_prog, cltrack_prog, sizeof(cltrack_prog),
1667             S_IRUGO|S_IWUSR);
1668 MODULE_PARM_DESC(cltrack_prog, "Path to the nfsdcltrack upcall program");
1669 
1670 static bool cltrack_legacy_disable;
1671 module_param(cltrack_legacy_disable, bool, S_IRUGO|S_IWUSR);
1672 MODULE_PARM_DESC(cltrack_legacy_disable,
1673         "Disable legacy recoverydir conversion. Default: false");
1674 
1675 #define LEGACY_TOPDIR_ENV_PREFIX "NFSDCLTRACK_LEGACY_TOPDIR="
1676 #define LEGACY_RECDIR_ENV_PREFIX "NFSDCLTRACK_LEGACY_RECDIR="
1677 #define HAS_SESSION_ENV_PREFIX "NFSDCLTRACK_CLIENT_HAS_SESSION="
1678 #define GRACE_START_ENV_PREFIX "NFSDCLTRACK_GRACE_START="
1679 
1680 static char *
1681 nfsd4_cltrack_legacy_topdir(void)
1682 {
1683     int copied;
1684     size_t len;
1685     char *result;
1686 
1687     if (cltrack_legacy_disable)
1688         return NULL;
1689 
1690     len = strlen(LEGACY_TOPDIR_ENV_PREFIX) +
1691         strlen(nfs4_recoverydir()) + 1;
1692 
1693     result = kmalloc(len, GFP_KERNEL);
1694     if (!result)
1695         return result;
1696 
1697     copied = snprintf(result, len, LEGACY_TOPDIR_ENV_PREFIX "%s",
1698                 nfs4_recoverydir());
1699     if (copied >= len) {
1700         /* just return nothing if output was truncated */
1701         kfree(result);
1702         return NULL;
1703     }
1704 
1705     return result;
1706 }
1707 
1708 static char *
1709 nfsd4_cltrack_legacy_recdir(const struct xdr_netobj *name)
1710 {
1711     int copied;
1712     size_t len;
1713     char *result;
1714 
1715     if (cltrack_legacy_disable)
1716         return NULL;
1717 
1718     /* +1 is for '/' between "topdir" and "recdir" */
1719     len = strlen(LEGACY_RECDIR_ENV_PREFIX) +
1720         strlen(nfs4_recoverydir()) + 1 + HEXDIR_LEN;
1721 
1722     result = kmalloc(len, GFP_KERNEL);
1723     if (!result)
1724         return result;
1725 
1726     copied = snprintf(result, len, LEGACY_RECDIR_ENV_PREFIX "%s/",
1727                 nfs4_recoverydir());
1728     if (copied > (len - HEXDIR_LEN)) {
1729         /* just return nothing if output will be truncated */
1730         kfree(result);
1731         return NULL;
1732     }
1733 
1734     copied = nfs4_make_rec_clidname(result + copied, name);
1735     if (copied) {
1736         kfree(result);
1737         return NULL;
1738     }
1739 
1740     return result;
1741 }
1742 
1743 static char *
1744 nfsd4_cltrack_client_has_session(struct nfs4_client *clp)
1745 {
1746     int copied;
1747     size_t len;
1748     char *result;
1749 
1750     /* prefix + Y/N character + terminating NULL */
1751     len = strlen(HAS_SESSION_ENV_PREFIX) + 1 + 1;
1752 
1753     result = kmalloc(len, GFP_KERNEL);
1754     if (!result)
1755         return result;
1756 
1757     copied = snprintf(result, len, HAS_SESSION_ENV_PREFIX "%c",
1758                 clp->cl_minorversion ? 'Y' : 'N');
1759     if (copied >= len) {
1760         /* just return nothing if output was truncated */
1761         kfree(result);
1762         return NULL;
1763     }
1764 
1765     return result;
1766 }
1767 
1768 static char *
1769 nfsd4_cltrack_grace_start(time64_t grace_start)
1770 {
1771     int copied;
1772     size_t len;
1773     char *result;
1774 
1775     /* prefix + max width of int64_t string + terminating NULL */
1776     len = strlen(GRACE_START_ENV_PREFIX) + 22 + 1;
1777 
1778     result = kmalloc(len, GFP_KERNEL);
1779     if (!result)
1780         return result;
1781 
1782     copied = snprintf(result, len, GRACE_START_ENV_PREFIX "%lld",
1783                 grace_start);
1784     if (copied >= len) {
1785         /* just return nothing if output was truncated */
1786         kfree(result);
1787         return NULL;
1788     }
1789 
1790     return result;
1791 }
1792 
1793 static int
1794 nfsd4_umh_cltrack_upcall(char *cmd, char *arg, char *env0, char *env1)
1795 {
1796     char *envp[3];
1797     char *argv[4];
1798     int ret;
1799 
1800     if (unlikely(!cltrack_prog[0])) {
1801         dprintk("%s: cltrack_prog is disabled\n", __func__);
1802         return -EACCES;
1803     }
1804 
1805     dprintk("%s: cmd: %s\n", __func__, cmd);
1806     dprintk("%s: arg: %s\n", __func__, arg ? arg : "(null)");
1807     dprintk("%s: env0: %s\n", __func__, env0 ? env0 : "(null)");
1808     dprintk("%s: env1: %s\n", __func__, env1 ? env1 : "(null)");
1809 
1810     envp[0] = env0;
1811     envp[1] = env1;
1812     envp[2] = NULL;
1813 
1814     argv[0] = (char *)cltrack_prog;
1815     argv[1] = cmd;
1816     argv[2] = arg;
1817     argv[3] = NULL;
1818 
1819     ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);
1820     /*
1821      * Disable the upcall mechanism if we're getting an ENOENT or EACCES
1822      * error. The admin can re-enable it on the fly by using sysfs
1823      * once the problem has been fixed.
1824      */
1825     if (ret == -ENOENT || ret == -EACCES) {
1826         dprintk("NFSD: %s was not found or isn't executable (%d). "
1827             "Setting cltrack_prog to blank string!",
1828             cltrack_prog, ret);
1829         cltrack_prog[0] = '\0';
1830     }
1831     dprintk("%s: %s return value: %d\n", __func__, cltrack_prog, ret);
1832 
1833     return ret;
1834 }
1835 
1836 static char *
1837 bin_to_hex_dup(const unsigned char *src, int srclen)
1838 {
1839     char *buf;
1840 
1841     /* +1 for terminating NULL */
1842     buf = kzalloc((srclen * 2) + 1, GFP_KERNEL);
1843     if (!buf)
1844         return buf;
1845 
1846     bin2hex(buf, src, srclen);
1847     return buf;
1848 }
1849 
1850 static int
1851 nfsd4_umh_cltrack_init(struct net *net)
1852 {
1853     int ret;
1854     struct nfsd_net *nn = net_generic(net, nfsd_net_id);
1855     char *grace_start = nfsd4_cltrack_grace_start(nn->boot_time);
1856 
1857     /* XXX: The usermode helper s not working in container yet. */
1858     if (net != &init_net) {
1859         pr_warn("NFSD: attempt to initialize umh client tracking in a container ignored.\n");
1860         kfree(grace_start);
1861         return -EINVAL;
1862     }
1863 
1864     ret = nfsd4_umh_cltrack_upcall("init", NULL, grace_start, NULL);
1865     kfree(grace_start);
1866     if (!ret)
1867         pr_info("NFSD: Using UMH upcall client tracking operations.\n");
1868     return ret;
1869 }
1870 
1871 static void
1872 nfsd4_cltrack_upcall_lock(struct nfs4_client *clp)
1873 {
1874     wait_on_bit_lock(&clp->cl_flags, NFSD4_CLIENT_UPCALL_LOCK,
1875              TASK_UNINTERRUPTIBLE);
1876 }
1877 
1878 static void
1879 nfsd4_cltrack_upcall_unlock(struct nfs4_client *clp)
1880 {
1881     smp_mb__before_atomic();
1882     clear_bit(NFSD4_CLIENT_UPCALL_LOCK, &clp->cl_flags);
1883     smp_mb__after_atomic();
1884     wake_up_bit(&clp->cl_flags, NFSD4_CLIENT_UPCALL_LOCK);
1885 }
1886 
1887 static void
1888 nfsd4_umh_cltrack_create(struct nfs4_client *clp)
1889 {
1890     char *hexid, *has_session, *grace_start;
1891     struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
1892 
1893     /*
1894      * With v4.0 clients, there's little difference in outcome between a
1895      * create and check operation, and we can end up calling into this
1896      * function multiple times per client (once for each openowner). So,
1897      * for v4.0 clients skip upcalling once the client has been recorded
1898      * on stable storage.
1899      *
1900      * For v4.1+ clients, the outcome of the two operations is different,
1901      * so we must ensure that we upcall for the create operation. v4.1+
1902      * clients call this on RECLAIM_COMPLETE though, so we should only end
1903      * up doing a single create upcall per client.
1904      */
1905     if (clp->cl_minorversion == 0 &&
1906         test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
1907         return;
1908 
1909     hexid = bin_to_hex_dup(clp->cl_name.data, clp->cl_name.len);
1910     if (!hexid) {
1911         dprintk("%s: can't allocate memory for upcall!\n", __func__);
1912         return;
1913     }
1914 
1915     has_session = nfsd4_cltrack_client_has_session(clp);
1916     grace_start = nfsd4_cltrack_grace_start(nn->boot_time);
1917 
1918     nfsd4_cltrack_upcall_lock(clp);
1919     if (!nfsd4_umh_cltrack_upcall("create", hexid, has_session, grace_start))
1920         set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
1921     nfsd4_cltrack_upcall_unlock(clp);
1922 
1923     kfree(has_session);
1924     kfree(grace_start);
1925     kfree(hexid);
1926 }
1927 
1928 static void
1929 nfsd4_umh_cltrack_remove(struct nfs4_client *clp)
1930 {
1931     char *hexid;
1932 
1933     if (!test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
1934         return;
1935 
1936     hexid = bin_to_hex_dup(clp->cl_name.data, clp->cl_name.len);
1937     if (!hexid) {
1938         dprintk("%s: can't allocate memory for upcall!\n", __func__);
1939         return;
1940     }
1941 
1942     nfsd4_cltrack_upcall_lock(clp);
1943     if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags) &&
1944         nfsd4_umh_cltrack_upcall("remove", hexid, NULL, NULL) == 0)
1945         clear_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
1946     nfsd4_cltrack_upcall_unlock(clp);
1947 
1948     kfree(hexid);
1949 }
1950 
1951 static int
1952 nfsd4_umh_cltrack_check(struct nfs4_client *clp)
1953 {
1954     int ret;
1955     char *hexid, *has_session, *legacy;
1956 
1957     if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
1958         return 0;
1959 
1960     hexid = bin_to_hex_dup(clp->cl_name.data, clp->cl_name.len);
1961     if (!hexid) {
1962         dprintk("%s: can't allocate memory for upcall!\n", __func__);
1963         return -ENOMEM;
1964     }
1965 
1966     has_session = nfsd4_cltrack_client_has_session(clp);
1967     legacy = nfsd4_cltrack_legacy_recdir(&clp->cl_name);
1968 
1969     nfsd4_cltrack_upcall_lock(clp);
1970     if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) {
1971         ret = 0;
1972     } else {
1973         ret = nfsd4_umh_cltrack_upcall("check", hexid, has_session, legacy);
1974         if (ret == 0)
1975             set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
1976     }
1977     nfsd4_cltrack_upcall_unlock(clp);
1978     kfree(has_session);
1979     kfree(legacy);
1980     kfree(hexid);
1981 
1982     return ret;
1983 }
1984 
1985 static void
1986 nfsd4_umh_cltrack_grace_done(struct nfsd_net *nn)
1987 {
1988     char *legacy;
1989     char timestr[22]; /* FIXME: better way to determine max size? */
1990 
1991     sprintf(timestr, "%lld", nn->boot_time);
1992     legacy = nfsd4_cltrack_legacy_topdir();
1993     nfsd4_umh_cltrack_upcall("gracedone", timestr, legacy, NULL);
1994     kfree(legacy);
1995 }
1996 
1997 static const struct nfsd4_client_tracking_ops nfsd4_umh_tracking_ops = {
1998     .init       = nfsd4_umh_cltrack_init,
1999     .exit       = NULL,
2000     .create     = nfsd4_umh_cltrack_create,
2001     .remove     = nfsd4_umh_cltrack_remove,
2002     .check      = nfsd4_umh_cltrack_check,
2003     .grace_done = nfsd4_umh_cltrack_grace_done,
2004     .version    = 1,
2005     .msglen     = 0,
2006 };
2007 
2008 int
2009 nfsd4_client_tracking_init(struct net *net)
2010 {
2011     int status;
2012     struct path path;
2013     struct nfsd_net *nn = net_generic(net, nfsd_net_id);
2014 
2015     /* just run the init if it the method is already decided */
2016     if (nn->client_tracking_ops)
2017         goto do_init;
2018 
2019     /* First, try to use nfsdcld */
2020     nn->client_tracking_ops = &nfsd4_cld_tracking_ops;
2021     status = nn->client_tracking_ops->init(net);
2022     if (!status)
2023         return status;
2024     if (status != -ETIMEDOUT) {
2025         nn->client_tracking_ops = &nfsd4_cld_tracking_ops_v0;
2026         status = nn->client_tracking_ops->init(net);
2027         if (!status)
2028             return status;
2029     }
2030 
2031     /*
2032      * Next, try the UMH upcall.
2033      */
2034     nn->client_tracking_ops = &nfsd4_umh_tracking_ops;
2035     status = nn->client_tracking_ops->init(net);
2036     if (!status)
2037         return status;
2038 
2039     /*
2040      * Finally, See if the recoverydir exists and is a directory.
2041      * If it is, then use the legacy ops.
2042      */
2043     nn->client_tracking_ops = &nfsd4_legacy_tracking_ops;
2044     status = kern_path(nfs4_recoverydir(), LOOKUP_FOLLOW, &path);
2045     if (!status) {
2046         status = d_is_dir(path.dentry);
2047         path_put(&path);
2048         if (!status) {
2049             status = -EINVAL;
2050             goto out;
2051         }
2052     }
2053 
2054 do_init:
2055     status = nn->client_tracking_ops->init(net);
2056 out:
2057     if (status) {
2058         printk(KERN_WARNING "NFSD: Unable to initialize client "
2059                     "recovery tracking! (%d)\n", status);
2060         nn->client_tracking_ops = NULL;
2061     }
2062     return status;
2063 }
2064 
2065 void
2066 nfsd4_client_tracking_exit(struct net *net)
2067 {
2068     struct nfsd_net *nn = net_generic(net, nfsd_net_id);
2069 
2070     if (nn->client_tracking_ops) {
2071         if (nn->client_tracking_ops->exit)
2072             nn->client_tracking_ops->exit(net);
2073         nn->client_tracking_ops = NULL;
2074     }
2075 }
2076 
2077 void
2078 nfsd4_client_record_create(struct nfs4_client *clp)
2079 {
2080     struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
2081 
2082     if (nn->client_tracking_ops)
2083         nn->client_tracking_ops->create(clp);
2084 }
2085 
2086 void
2087 nfsd4_client_record_remove(struct nfs4_client *clp)
2088 {
2089     struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
2090 
2091     if (nn->client_tracking_ops)
2092         nn->client_tracking_ops->remove(clp);
2093 }
2094 
2095 int
2096 nfsd4_client_record_check(struct nfs4_client *clp)
2097 {
2098     struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
2099 
2100     if (nn->client_tracking_ops)
2101         return nn->client_tracking_ops->check(clp);
2102 
2103     return -EOPNOTSUPP;
2104 }
2105 
2106 void
2107 nfsd4_record_grace_done(struct nfsd_net *nn)
2108 {
2109     if (nn->client_tracking_ops)
2110         nn->client_tracking_ops->grace_done(nn);
2111 }
2112 
2113 static int
2114 rpc_pipefs_event(struct notifier_block *nb, unsigned long event, void *ptr)
2115 {
2116     struct super_block *sb = ptr;
2117     struct net *net = sb->s_fs_info;
2118     struct nfsd_net *nn = net_generic(net, nfsd_net_id);
2119     struct cld_net *cn = nn->cld_net;
2120     struct dentry *dentry;
2121     int ret = 0;
2122 
2123     if (!try_module_get(THIS_MODULE))
2124         return 0;
2125 
2126     if (!cn) {
2127         module_put(THIS_MODULE);
2128         return 0;
2129     }
2130 
2131     switch (event) {
2132     case RPC_PIPEFS_MOUNT:
2133         dentry = nfsd4_cld_register_sb(sb, cn->cn_pipe);
2134         if (IS_ERR(dentry)) {
2135             ret = PTR_ERR(dentry);
2136             break;
2137         }
2138         cn->cn_pipe->dentry = dentry;
2139         break;
2140     case RPC_PIPEFS_UMOUNT:
2141         if (cn->cn_pipe->dentry)
2142             nfsd4_cld_unregister_sb(cn->cn_pipe);
2143         break;
2144     default:
2145         ret = -ENOTSUPP;
2146         break;
2147     }
2148     module_put(THIS_MODULE);
2149     return ret;
2150 }
2151 
2152 static struct notifier_block nfsd4_cld_block = {
2153     .notifier_call = rpc_pipefs_event,
2154 };
2155 
2156 int
2157 register_cld_notifier(void)
2158 {
2159     WARN_ON(!nfsd_net_id);
2160     return rpc_pipefs_notifier_register(&nfsd4_cld_block);
2161 }
2162 
2163 void
2164 unregister_cld_notifier(void)
2165 {
2166     rpc_pipefs_notifier_unregister(&nfsd4_cld_block);
2167 }