cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

nfs4recover.c (51597B)


      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 */
     55struct 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
     66static const struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops;
     67static const struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops_v2;
     68
     69/* Globals */
     70static char user_recovery_dirname[PATH_MAX] = "/var/lib/nfs/v4recovery";
     71
     72static int
     73nfs4_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
     88static void
     89nfs4_reset_creds(const struct cred *original)
     90{
     91	revert_creds(original);
     92}
     93
     94static void
     95md5_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
    108static int
    109nfs4_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	status = crypto_shash_tfm_digest(tfm, clname->data, clname->len,
    131					 cksum.data);
    132	if (status)
    133		goto out;
    134
    135	md5_to_hex(dname, cksum.data);
    136
    137	status = 0;
    138out:
    139	kfree(cksum.data);
    140	crypto_free_shash(tfm);
    141out_no_tfm:
    142	return status;
    143}
    144
    145/*
    146 * If we had an error generating the recdir name for the legacy tracker
    147 * then warn the admin. If the error doesn't appear to be transient,
    148 * then disable recovery tracking.
    149 */
    150static void
    151legacy_recdir_name_error(struct nfs4_client *clp, int error)
    152{
    153	printk(KERN_ERR "NFSD: unable to generate recoverydir "
    154			"name (%d).\n", error);
    155
    156	/*
    157	 * if the algorithm just doesn't exist, then disable the recovery
    158	 * tracker altogether. The crypto libs will generally return this if
    159	 * FIPS is enabled as well.
    160	 */
    161	if (error == -ENOENT) {
    162		printk(KERN_ERR "NFSD: disabling legacy clientid tracking. "
    163			"Reboot recovery will not function correctly!\n");
    164		nfsd4_client_tracking_exit(clp->net);
    165	}
    166}
    167
    168static void
    169__nfsd4_create_reclaim_record_grace(struct nfs4_client *clp,
    170		const char *dname, int len, struct nfsd_net *nn)
    171{
    172	struct xdr_netobj name;
    173	struct xdr_netobj princhash = { .len = 0, .data = NULL };
    174	struct nfs4_client_reclaim *crp;
    175
    176	name.data = kmemdup(dname, len, GFP_KERNEL);
    177	if (!name.data) {
    178		dprintk("%s: failed to allocate memory for name.data!\n",
    179			__func__);
    180		return;
    181	}
    182	name.len = len;
    183	crp = nfs4_client_to_reclaim(name, princhash, nn);
    184	if (!crp) {
    185		kfree(name.data);
    186		return;
    187	}
    188	crp->cr_clp = clp;
    189}
    190
    191static void
    192nfsd4_create_clid_dir(struct nfs4_client *clp)
    193{
    194	const struct cred *original_cred;
    195	char dname[HEXDIR_LEN];
    196	struct dentry *dir, *dentry;
    197	int status;
    198	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
    199
    200	if (test_and_set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
    201		return;
    202	if (!nn->rec_file)
    203		return;
    204
    205	status = nfs4_make_rec_clidname(dname, &clp->cl_name);
    206	if (status)
    207		return legacy_recdir_name_error(clp, status);
    208
    209	status = nfs4_save_creds(&original_cred);
    210	if (status < 0)
    211		return;
    212
    213	status = mnt_want_write_file(nn->rec_file);
    214	if (status)
    215		goto out_creds;
    216
    217	dir = nn->rec_file->f_path.dentry;
    218	/* lock the parent */
    219	inode_lock(d_inode(dir));
    220
    221	dentry = lookup_one_len(dname, dir, HEXDIR_LEN-1);
    222	if (IS_ERR(dentry)) {
    223		status = PTR_ERR(dentry);
    224		goto out_unlock;
    225	}
    226	if (d_really_is_positive(dentry))
    227		/*
    228		 * In the 4.1 case, where we're called from
    229		 * reclaim_complete(), records from the previous reboot
    230		 * may still be left, so this is OK.
    231		 *
    232		 * In the 4.0 case, we should never get here; but we may
    233		 * as well be forgiving and just succeed silently.
    234		 */
    235		goto out_put;
    236	status = vfs_mkdir(&init_user_ns, d_inode(dir), dentry, S_IRWXU);
    237out_put:
    238	dput(dentry);
    239out_unlock:
    240	inode_unlock(d_inode(dir));
    241	if (status == 0) {
    242		if (nn->in_grace)
    243			__nfsd4_create_reclaim_record_grace(clp, dname,
    244					HEXDIR_LEN, nn);
    245		vfs_fsync(nn->rec_file, 0);
    246	} else {
    247		printk(KERN_ERR "NFSD: failed to write recovery record"
    248				" (err %d); please check that %s exists"
    249				" and is writeable", status,
    250				user_recovery_dirname);
    251	}
    252	mnt_drop_write_file(nn->rec_file);
    253out_creds:
    254	nfs4_reset_creds(original_cred);
    255}
    256
    257typedef int (recdir_func)(struct dentry *, struct dentry *, struct nfsd_net *);
    258
    259struct name_list {
    260	char name[HEXDIR_LEN];
    261	struct list_head list;
    262};
    263
    264struct nfs4_dir_ctx {
    265	struct dir_context ctx;
    266	struct list_head names;
    267};
    268
    269static int
    270nfsd4_build_namelist(struct dir_context *__ctx, const char *name, int namlen,
    271		loff_t offset, u64 ino, unsigned int d_type)
    272{
    273	struct nfs4_dir_ctx *ctx =
    274		container_of(__ctx, struct nfs4_dir_ctx, ctx);
    275	struct name_list *entry;
    276
    277	if (namlen != HEXDIR_LEN - 1)
    278		return 0;
    279	entry = kmalloc(sizeof(struct name_list), GFP_KERNEL);
    280	if (entry == NULL)
    281		return -ENOMEM;
    282	memcpy(entry->name, name, HEXDIR_LEN - 1);
    283	entry->name[HEXDIR_LEN - 1] = '\0';
    284	list_add(&entry->list, &ctx->names);
    285	return 0;
    286}
    287
    288static int
    289nfsd4_list_rec_dir(recdir_func *f, struct nfsd_net *nn)
    290{
    291	const struct cred *original_cred;
    292	struct dentry *dir = nn->rec_file->f_path.dentry;
    293	struct nfs4_dir_ctx ctx = {
    294		.ctx.actor = nfsd4_build_namelist,
    295		.names = LIST_HEAD_INIT(ctx.names)
    296	};
    297	struct name_list *entry, *tmp;
    298	int status;
    299
    300	status = nfs4_save_creds(&original_cred);
    301	if (status < 0)
    302		return status;
    303
    304	status = vfs_llseek(nn->rec_file, 0, SEEK_SET);
    305	if (status < 0) {
    306		nfs4_reset_creds(original_cred);
    307		return status;
    308	}
    309
    310	status = iterate_dir(nn->rec_file, &ctx.ctx);
    311	inode_lock_nested(d_inode(dir), I_MUTEX_PARENT);
    312
    313	list_for_each_entry_safe(entry, tmp, &ctx.names, list) {
    314		if (!status) {
    315			struct dentry *dentry;
    316			dentry = lookup_one_len(entry->name, dir, HEXDIR_LEN-1);
    317			if (IS_ERR(dentry)) {
    318				status = PTR_ERR(dentry);
    319				break;
    320			}
    321			status = f(dir, dentry, nn);
    322			dput(dentry);
    323		}
    324		list_del(&entry->list);
    325		kfree(entry);
    326	}
    327	inode_unlock(d_inode(dir));
    328	nfs4_reset_creds(original_cred);
    329
    330	list_for_each_entry_safe(entry, tmp, &ctx.names, list) {
    331		dprintk("NFSD: %s. Left entry %s\n", __func__, entry->name);
    332		list_del(&entry->list);
    333		kfree(entry);
    334	}
    335	return status;
    336}
    337
    338static int
    339nfsd4_unlink_clid_dir(char *name, int namlen, struct nfsd_net *nn)
    340{
    341	struct dentry *dir, *dentry;
    342	int status;
    343
    344	dprintk("NFSD: nfsd4_unlink_clid_dir. name %.*s\n", namlen, name);
    345
    346	dir = nn->rec_file->f_path.dentry;
    347	inode_lock_nested(d_inode(dir), I_MUTEX_PARENT);
    348	dentry = lookup_one_len(name, dir, namlen);
    349	if (IS_ERR(dentry)) {
    350		status = PTR_ERR(dentry);
    351		goto out_unlock;
    352	}
    353	status = -ENOENT;
    354	if (d_really_is_negative(dentry))
    355		goto out;
    356	status = vfs_rmdir(&init_user_ns, d_inode(dir), dentry);
    357out:
    358	dput(dentry);
    359out_unlock:
    360	inode_unlock(d_inode(dir));
    361	return status;
    362}
    363
    364static void
    365__nfsd4_remove_reclaim_record_grace(const char *dname, int len,
    366		struct nfsd_net *nn)
    367{
    368	struct xdr_netobj name;
    369	struct nfs4_client_reclaim *crp;
    370
    371	name.data = kmemdup(dname, len, GFP_KERNEL);
    372	if (!name.data) {
    373		dprintk("%s: failed to allocate memory for name.data!\n",
    374			__func__);
    375		return;
    376	}
    377	name.len = len;
    378	crp = nfsd4_find_reclaim_client(name, nn);
    379	kfree(name.data);
    380	if (crp)
    381		nfs4_remove_reclaim_record(crp, nn);
    382}
    383
    384static void
    385nfsd4_remove_clid_dir(struct nfs4_client *clp)
    386{
    387	const struct cred *original_cred;
    388	char dname[HEXDIR_LEN];
    389	int status;
    390	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
    391
    392	if (!nn->rec_file || !test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
    393		return;
    394
    395	status = nfs4_make_rec_clidname(dname, &clp->cl_name);
    396	if (status)
    397		return legacy_recdir_name_error(clp, status);
    398
    399	status = mnt_want_write_file(nn->rec_file);
    400	if (status)
    401		goto out;
    402	clear_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
    403
    404	status = nfs4_save_creds(&original_cred);
    405	if (status < 0)
    406		goto out_drop_write;
    407
    408	status = nfsd4_unlink_clid_dir(dname, HEXDIR_LEN-1, nn);
    409	nfs4_reset_creds(original_cred);
    410	if (status == 0) {
    411		vfs_fsync(nn->rec_file, 0);
    412		if (nn->in_grace)
    413			__nfsd4_remove_reclaim_record_grace(dname,
    414					HEXDIR_LEN, nn);
    415	}
    416out_drop_write:
    417	mnt_drop_write_file(nn->rec_file);
    418out:
    419	if (status)
    420		printk("NFSD: Failed to remove expired client state directory"
    421				" %.*s\n", HEXDIR_LEN, dname);
    422}
    423
    424static int
    425purge_old(struct dentry *parent, struct dentry *child, struct nfsd_net *nn)
    426{
    427	int status;
    428	struct xdr_netobj name;
    429
    430	if (child->d_name.len != HEXDIR_LEN - 1) {
    431		printk("%s: illegal name %pd in recovery directory\n",
    432				__func__, child);
    433		/* Keep trying; maybe the others are OK: */
    434		return 0;
    435	}
    436	name.data = kmemdup_nul(child->d_name.name, child->d_name.len, GFP_KERNEL);
    437	if (!name.data) {
    438		dprintk("%s: failed to allocate memory for name.data!\n",
    439			__func__);
    440		goto out;
    441	}
    442	name.len = HEXDIR_LEN;
    443	if (nfs4_has_reclaimed_state(name, nn))
    444		goto out_free;
    445
    446	status = vfs_rmdir(&init_user_ns, d_inode(parent), child);
    447	if (status)
    448		printk("failed to remove client recovery directory %pd\n",
    449				child);
    450out_free:
    451	kfree(name.data);
    452out:
    453	/* Keep trying, success or failure: */
    454	return 0;
    455}
    456
    457static void
    458nfsd4_recdir_purge_old(struct nfsd_net *nn)
    459{
    460	int status;
    461
    462	nn->in_grace = false;
    463	if (!nn->rec_file)
    464		return;
    465	status = mnt_want_write_file(nn->rec_file);
    466	if (status)
    467		goto out;
    468	status = nfsd4_list_rec_dir(purge_old, nn);
    469	if (status == 0)
    470		vfs_fsync(nn->rec_file, 0);
    471	mnt_drop_write_file(nn->rec_file);
    472out:
    473	nfs4_release_reclaim(nn);
    474	if (status)
    475		printk("nfsd4: failed to purge old clients from recovery"
    476			" directory %pD\n", nn->rec_file);
    477}
    478
    479static int
    480load_recdir(struct dentry *parent, struct dentry *child, struct nfsd_net *nn)
    481{
    482	struct xdr_netobj name;
    483	struct xdr_netobj princhash = { .len = 0, .data = NULL };
    484
    485	if (child->d_name.len != HEXDIR_LEN - 1) {
    486		printk("%s: illegal name %pd in recovery directory\n",
    487				__func__, child);
    488		/* Keep trying; maybe the others are OK: */
    489		return 0;
    490	}
    491	name.data = kmemdup_nul(child->d_name.name, child->d_name.len, GFP_KERNEL);
    492	if (!name.data) {
    493		dprintk("%s: failed to allocate memory for name.data!\n",
    494			__func__);
    495		goto out;
    496	}
    497	name.len = HEXDIR_LEN;
    498	if (!nfs4_client_to_reclaim(name, princhash, nn))
    499		kfree(name.data);
    500out:
    501	return 0;
    502}
    503
    504static int
    505nfsd4_recdir_load(struct net *net) {
    506	int status;
    507	struct nfsd_net *nn =  net_generic(net, nfsd_net_id);
    508
    509	if (!nn->rec_file)
    510		return 0;
    511
    512	status = nfsd4_list_rec_dir(load_recdir, nn);
    513	if (status)
    514		printk("nfsd4: failed loading clients from recovery"
    515			" directory %pD\n", nn->rec_file);
    516	return status;
    517}
    518
    519/*
    520 * Hold reference to the recovery directory.
    521 */
    522
    523static int
    524nfsd4_init_recdir(struct net *net)
    525{
    526	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
    527	const struct cred *original_cred;
    528	int status;
    529
    530	printk("NFSD: Using %s as the NFSv4 state recovery directory\n",
    531			user_recovery_dirname);
    532
    533	BUG_ON(nn->rec_file);
    534
    535	status = nfs4_save_creds(&original_cred);
    536	if (status < 0) {
    537		printk("NFSD: Unable to change credentials to find recovery"
    538		       " directory: error %d\n",
    539		       status);
    540		return status;
    541	}
    542
    543	nn->rec_file = filp_open(user_recovery_dirname, O_RDONLY | O_DIRECTORY, 0);
    544	if (IS_ERR(nn->rec_file)) {
    545		printk("NFSD: unable to find recovery directory %s\n",
    546				user_recovery_dirname);
    547		status = PTR_ERR(nn->rec_file);
    548		nn->rec_file = NULL;
    549	}
    550
    551	nfs4_reset_creds(original_cred);
    552	if (!status)
    553		nn->in_grace = true;
    554	return status;
    555}
    556
    557static void
    558nfsd4_shutdown_recdir(struct net *net)
    559{
    560	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
    561
    562	if (!nn->rec_file)
    563		return;
    564	fput(nn->rec_file);
    565	nn->rec_file = NULL;
    566}
    567
    568static int
    569nfs4_legacy_state_init(struct net *net)
    570{
    571	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
    572	int i;
    573
    574	nn->reclaim_str_hashtbl = kmalloc_array(CLIENT_HASH_SIZE,
    575						sizeof(struct list_head),
    576						GFP_KERNEL);
    577	if (!nn->reclaim_str_hashtbl)
    578		return -ENOMEM;
    579
    580	for (i = 0; i < CLIENT_HASH_SIZE; i++)
    581		INIT_LIST_HEAD(&nn->reclaim_str_hashtbl[i]);
    582	nn->reclaim_str_hashtbl_size = 0;
    583
    584	return 0;
    585}
    586
    587static void
    588nfs4_legacy_state_shutdown(struct net *net)
    589{
    590	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
    591
    592	kfree(nn->reclaim_str_hashtbl);
    593}
    594
    595static int
    596nfsd4_load_reboot_recovery_data(struct net *net)
    597{
    598	int status;
    599
    600	status = nfsd4_init_recdir(net);
    601	if (status)
    602		return status;
    603
    604	status = nfsd4_recdir_load(net);
    605	if (status)
    606		nfsd4_shutdown_recdir(net);
    607
    608	return status;
    609}
    610
    611static int
    612nfsd4_legacy_tracking_init(struct net *net)
    613{
    614	int status;
    615
    616	/* XXX: The legacy code won't work in a container */
    617	if (net != &init_net) {
    618		pr_warn("NFSD: attempt to initialize legacy client tracking in a container ignored.\n");
    619		return -EINVAL;
    620	}
    621
    622	status = nfs4_legacy_state_init(net);
    623	if (status)
    624		return status;
    625
    626	status = nfsd4_load_reboot_recovery_data(net);
    627	if (status)
    628		goto err;
    629	pr_info("NFSD: Using legacy client tracking operations.\n");
    630	return 0;
    631
    632err:
    633	nfs4_legacy_state_shutdown(net);
    634	return status;
    635}
    636
    637static void
    638nfsd4_legacy_tracking_exit(struct net *net)
    639{
    640	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
    641
    642	nfs4_release_reclaim(nn);
    643	nfsd4_shutdown_recdir(net);
    644	nfs4_legacy_state_shutdown(net);
    645}
    646
    647/*
    648 * Change the NFSv4 recovery directory to recdir.
    649 */
    650int
    651nfs4_reset_recoverydir(char *recdir)
    652{
    653	int status;
    654	struct path path;
    655
    656	status = kern_path(recdir, LOOKUP_FOLLOW, &path);
    657	if (status)
    658		return status;
    659	status = -ENOTDIR;
    660	if (d_is_dir(path.dentry)) {
    661		strcpy(user_recovery_dirname, recdir);
    662		status = 0;
    663	}
    664	path_put(&path);
    665	return status;
    666}
    667
    668char *
    669nfs4_recoverydir(void)
    670{
    671	return user_recovery_dirname;
    672}
    673
    674static int
    675nfsd4_check_legacy_client(struct nfs4_client *clp)
    676{
    677	int status;
    678	char dname[HEXDIR_LEN];
    679	struct nfs4_client_reclaim *crp;
    680	struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
    681	struct xdr_netobj name;
    682
    683	/* did we already find that this client is stable? */
    684	if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
    685		return 0;
    686
    687	status = nfs4_make_rec_clidname(dname, &clp->cl_name);
    688	if (status) {
    689		legacy_recdir_name_error(clp, status);
    690		return status;
    691	}
    692
    693	/* look for it in the reclaim hashtable otherwise */
    694	name.data = kmemdup(dname, HEXDIR_LEN, GFP_KERNEL);
    695	if (!name.data) {
    696		dprintk("%s: failed to allocate memory for name.data!\n",
    697			__func__);
    698		goto out_enoent;
    699	}
    700	name.len = HEXDIR_LEN;
    701	crp = nfsd4_find_reclaim_client(name, nn);
    702	kfree(name.data);
    703	if (crp) {
    704		set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
    705		crp->cr_clp = clp;
    706		return 0;
    707	}
    708
    709out_enoent:
    710	return -ENOENT;
    711}
    712
    713static const struct nfsd4_client_tracking_ops nfsd4_legacy_tracking_ops = {
    714	.init		= nfsd4_legacy_tracking_init,
    715	.exit		= nfsd4_legacy_tracking_exit,
    716	.create		= nfsd4_create_clid_dir,
    717	.remove		= nfsd4_remove_clid_dir,
    718	.check		= nfsd4_check_legacy_client,
    719	.grace_done	= nfsd4_recdir_purge_old,
    720	.version	= 1,
    721	.msglen		= 0,
    722};
    723
    724/* Globals */
    725#define NFSD_PIPE_DIR		"nfsd"
    726#define NFSD_CLD_PIPE		"cld"
    727
    728/* per-net-ns structure for holding cld upcall info */
    729struct cld_net {
    730	struct rpc_pipe		*cn_pipe;
    731	spinlock_t		 cn_lock;
    732	struct list_head	 cn_list;
    733	unsigned int		 cn_xid;
    734	bool			 cn_has_legacy;
    735	struct crypto_shash	*cn_tfm;
    736};
    737
    738struct cld_upcall {
    739	struct list_head	 cu_list;
    740	struct cld_net		*cu_net;
    741	struct completion	 cu_done;
    742	union {
    743		struct cld_msg_hdr	 cu_hdr;
    744		struct cld_msg		 cu_msg;
    745		struct cld_msg_v2	 cu_msg_v2;
    746	} cu_u;
    747};
    748
    749static int
    750__cld_pipe_upcall(struct rpc_pipe *pipe, void *cmsg, struct nfsd_net *nn)
    751{
    752	int ret;
    753	struct rpc_pipe_msg msg;
    754	struct cld_upcall *cup = container_of(cmsg, struct cld_upcall, cu_u);
    755
    756	memset(&msg, 0, sizeof(msg));
    757	msg.data = cmsg;
    758	msg.len = nn->client_tracking_ops->msglen;
    759
    760	ret = rpc_queue_upcall(pipe, &msg);
    761	if (ret < 0) {
    762		goto out;
    763	}
    764
    765	wait_for_completion(&cup->cu_done);
    766
    767	if (msg.errno < 0)
    768		ret = msg.errno;
    769out:
    770	return ret;
    771}
    772
    773static int
    774cld_pipe_upcall(struct rpc_pipe *pipe, void *cmsg, struct nfsd_net *nn)
    775{
    776	int ret;
    777
    778	/*
    779	 * -EAGAIN occurs when pipe is closed and reopened while there are
    780	 *  upcalls queued.
    781	 */
    782	do {
    783		ret = __cld_pipe_upcall(pipe, cmsg, nn);
    784	} while (ret == -EAGAIN);
    785
    786	return ret;
    787}
    788
    789static ssize_t
    790__cld_pipe_inprogress_downcall(const struct cld_msg_v2 __user *cmsg,
    791		struct nfsd_net *nn)
    792{
    793	uint8_t cmd, princhashlen;
    794	struct xdr_netobj name, princhash = { .len = 0, .data = NULL };
    795	uint16_t namelen;
    796	struct cld_net *cn = nn->cld_net;
    797
    798	if (get_user(cmd, &cmsg->cm_cmd)) {
    799		dprintk("%s: error when copying cmd from userspace", __func__);
    800		return -EFAULT;
    801	}
    802	if (cmd == Cld_GraceStart) {
    803		if (nn->client_tracking_ops->version >= 2) {
    804			const struct cld_clntinfo __user *ci;
    805
    806			ci = &cmsg->cm_u.cm_clntinfo;
    807			if (get_user(namelen, &ci->cc_name.cn_len))
    808				return -EFAULT;
    809			name.data = memdup_user(&ci->cc_name.cn_id, namelen);
    810			if (IS_ERR_OR_NULL(name.data))
    811				return -EFAULT;
    812			name.len = namelen;
    813			get_user(princhashlen, &ci->cc_princhash.cp_len);
    814			if (princhashlen > 0) {
    815				princhash.data = memdup_user(
    816						&ci->cc_princhash.cp_data,
    817						princhashlen);
    818				if (IS_ERR_OR_NULL(princhash.data))
    819					return -EFAULT;
    820				princhash.len = princhashlen;
    821			} else
    822				princhash.len = 0;
    823		} else {
    824			const struct cld_name __user *cnm;
    825
    826			cnm = &cmsg->cm_u.cm_name;
    827			if (get_user(namelen, &cnm->cn_len))
    828				return -EFAULT;
    829			name.data = memdup_user(&cnm->cn_id, namelen);
    830			if (IS_ERR_OR_NULL(name.data))
    831				return -EFAULT;
    832			name.len = namelen;
    833		}
    834		if (name.len > 5 && memcmp(name.data, "hash:", 5) == 0) {
    835			name.len = name.len - 5;
    836			memmove(name.data, name.data + 5, name.len);
    837			cn->cn_has_legacy = true;
    838		}
    839		if (!nfs4_client_to_reclaim(name, princhash, nn)) {
    840			kfree(name.data);
    841			kfree(princhash.data);
    842			return -EFAULT;
    843		}
    844		return nn->client_tracking_ops->msglen;
    845	}
    846	return -EFAULT;
    847}
    848
    849static ssize_t
    850cld_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
    851{
    852	struct cld_upcall *tmp, *cup;
    853	struct cld_msg_hdr __user *hdr = (struct cld_msg_hdr __user *)src;
    854	struct cld_msg_v2 __user *cmsg = (struct cld_msg_v2 __user *)src;
    855	uint32_t xid;
    856	struct nfsd_net *nn = net_generic(file_inode(filp)->i_sb->s_fs_info,
    857						nfsd_net_id);
    858	struct cld_net *cn = nn->cld_net;
    859	int16_t status;
    860
    861	if (mlen != nn->client_tracking_ops->msglen) {
    862		dprintk("%s: got %zu bytes, expected %zu\n", __func__, mlen,
    863			nn->client_tracking_ops->msglen);
    864		return -EINVAL;
    865	}
    866
    867	/* copy just the xid so we can try to find that */
    868	if (copy_from_user(&xid, &hdr->cm_xid, sizeof(xid)) != 0) {
    869		dprintk("%s: error when copying xid from userspace", __func__);
    870		return -EFAULT;
    871	}
    872
    873	/*
    874	 * copy the status so we know whether to remove the upcall from the
    875	 * list (for -EINPROGRESS, we just want to make sure the xid is
    876	 * valid, not remove the upcall from the list)
    877	 */
    878	if (get_user(status, &hdr->cm_status)) {
    879		dprintk("%s: error when copying status from userspace", __func__);
    880		return -EFAULT;
    881	}
    882
    883	/* walk the list and find corresponding xid */
    884	cup = NULL;
    885	spin_lock(&cn->cn_lock);
    886	list_for_each_entry(tmp, &cn->cn_list, cu_list) {
    887		if (get_unaligned(&tmp->cu_u.cu_hdr.cm_xid) == xid) {
    888			cup = tmp;
    889			if (status != -EINPROGRESS)
    890				list_del_init(&cup->cu_list);
    891			break;
    892		}
    893	}
    894	spin_unlock(&cn->cn_lock);
    895
    896	/* couldn't find upcall? */
    897	if (!cup) {
    898		dprintk("%s: couldn't find upcall -- xid=%u\n", __func__, xid);
    899		return -EINVAL;
    900	}
    901
    902	if (status == -EINPROGRESS)
    903		return __cld_pipe_inprogress_downcall(cmsg, nn);
    904
    905	if (copy_from_user(&cup->cu_u.cu_msg_v2, src, mlen) != 0)
    906		return -EFAULT;
    907
    908	complete(&cup->cu_done);
    909	return mlen;
    910}
    911
    912static void
    913cld_pipe_destroy_msg(struct rpc_pipe_msg *msg)
    914{
    915	struct cld_msg *cmsg = msg->data;
    916	struct cld_upcall *cup = container_of(cmsg, struct cld_upcall,
    917						 cu_u.cu_msg);
    918
    919	/* errno >= 0 means we got a downcall */
    920	if (msg->errno >= 0)
    921		return;
    922
    923	complete(&cup->cu_done);
    924}
    925
    926static const struct rpc_pipe_ops cld_upcall_ops = {
    927	.upcall		= rpc_pipe_generic_upcall,
    928	.downcall	= cld_pipe_downcall,
    929	.destroy_msg	= cld_pipe_destroy_msg,
    930};
    931
    932static struct dentry *
    933nfsd4_cld_register_sb(struct super_block *sb, struct rpc_pipe *pipe)
    934{
    935	struct dentry *dir, *dentry;
    936
    937	dir = rpc_d_lookup_sb(sb, NFSD_PIPE_DIR);
    938	if (dir == NULL)
    939		return ERR_PTR(-ENOENT);
    940	dentry = rpc_mkpipe_dentry(dir, NFSD_CLD_PIPE, NULL, pipe);
    941	dput(dir);
    942	return dentry;
    943}
    944
    945static void
    946nfsd4_cld_unregister_sb(struct rpc_pipe *pipe)
    947{
    948	if (pipe->dentry)
    949		rpc_unlink(pipe->dentry);
    950}
    951
    952static struct dentry *
    953nfsd4_cld_register_net(struct net *net, struct rpc_pipe *pipe)
    954{
    955	struct super_block *sb;
    956	struct dentry *dentry;
    957
    958	sb = rpc_get_sb_net(net);
    959	if (!sb)
    960		return NULL;
    961	dentry = nfsd4_cld_register_sb(sb, pipe);
    962	rpc_put_sb_net(net);
    963	return dentry;
    964}
    965
    966static void
    967nfsd4_cld_unregister_net(struct net *net, struct rpc_pipe *pipe)
    968{
    969	struct super_block *sb;
    970
    971	sb = rpc_get_sb_net(net);
    972	if (sb) {
    973		nfsd4_cld_unregister_sb(pipe);
    974		rpc_put_sb_net(net);
    975	}
    976}
    977
    978/* Initialize rpc_pipefs pipe for communication with client tracking daemon */
    979static int
    980__nfsd4_init_cld_pipe(struct net *net)
    981{
    982	int ret;
    983	struct dentry *dentry;
    984	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
    985	struct cld_net *cn;
    986
    987	if (nn->cld_net)
    988		return 0;
    989
    990	cn = kzalloc(sizeof(*cn), GFP_KERNEL);
    991	if (!cn) {
    992		ret = -ENOMEM;
    993		goto err;
    994	}
    995
    996	cn->cn_pipe = rpc_mkpipe_data(&cld_upcall_ops, RPC_PIPE_WAIT_FOR_OPEN);
    997	if (IS_ERR(cn->cn_pipe)) {
    998		ret = PTR_ERR(cn->cn_pipe);
    999		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
   1015err_destroy_data:
   1016	rpc_destroy_pipe_data(cn->cn_pipe);
   1017err:
   1018	kfree(cn);
   1019	printk(KERN_ERR "NFSD: unable to create nfsdcld upcall pipe (%d)\n",
   1020			ret);
   1021	return ret;
   1022}
   1023
   1024static int
   1025nfsd4_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
   1035static void
   1036nfsd4_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
   1049static struct cld_upcall *
   1050alloc_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? */
   1060restart_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
   1081static void
   1082free_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 */
   1093static void
   1094nfsd4_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);
   1123out_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 */
   1130static void
   1131nfsd4_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
   1187out:
   1188	free_cld_upcall(cup);
   1189out_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 */
   1196static void
   1197nfsd4_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);
   1226out_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 */
   1238static int
   1239nfsd4_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 */
   1278static int
   1279nfsd4_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;
   1316found:
   1317	crp->cr_clp = clp;
   1318	return 0;
   1319}
   1320
   1321static int
   1322nfsd4_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;
   1362found:
   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
   1391static int
   1392nfsd4_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);
   1410out_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 */
   1418static void
   1419nfsd4_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);
   1438out_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 */
   1447static void
   1448nfsd4_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);
   1466out_err:
   1467	nfs4_release_reclaim(nn);
   1468	if (ret)
   1469		printk(KERN_ERR "NFSD: Unable to end grace period: %d\n", ret);
   1470}
   1471
   1472static int
   1473nfs4_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
   1493static void
   1494nfs4_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
   1502static bool
   1503cld_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
   1511static int
   1512nfsd4_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	}
   1549out_free:
   1550	free_cld_upcall(cup);
   1551out_err:
   1552	if (ret)
   1553		dprintk("%s: Unable to get version from userspace: %d\n",
   1554			__func__, ret);
   1555	return ret;
   1556}
   1557
   1558static int
   1559nfsd4_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
   1611err_remove:
   1612	nfsd4_remove_cld_pipe(net);
   1613err_shutdown:
   1614	nfs4_cld_state_shutdown(net);
   1615	return status;
   1616}
   1617
   1618static void
   1619nfsd4_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 */
   1629static 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 */
   1641static 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 */
   1653static 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 */
   1665static char cltrack_prog[PATH_MAX] = "/sbin/nfsdcltrack";
   1666module_param_string(cltrack_prog, cltrack_prog, sizeof(cltrack_prog),
   1667			S_IRUGO|S_IWUSR);
   1668MODULE_PARM_DESC(cltrack_prog, "Path to the nfsdcltrack upcall program");
   1669
   1670static bool cltrack_legacy_disable;
   1671module_param(cltrack_legacy_disable, bool, S_IRUGO|S_IWUSR);
   1672MODULE_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
   1680static char *
   1681nfsd4_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
   1708static char *
   1709nfsd4_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
   1743static char *
   1744nfsd4_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
   1768static char *
   1769nfsd4_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
   1793static int
   1794nfsd4_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
   1836static char *
   1837bin_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
   1850static int
   1851nfsd4_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
   1871static void
   1872nfsd4_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
   1878static void
   1879nfsd4_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
   1887static void
   1888nfsd4_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
   1928static void
   1929nfsd4_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
   1951static int
   1952nfsd4_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
   1985static void
   1986nfsd4_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
   1997static 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
   2008int
   2009nfsd4_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
   2054do_init:
   2055	status = nn->client_tracking_ops->init(net);
   2056out:
   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
   2065void
   2066nfsd4_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
   2077void
   2078nfsd4_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
   2086void
   2087nfsd4_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
   2095int
   2096nfsd4_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
   2106void
   2107nfsd4_record_grace_done(struct nfsd_net *nn)
   2108{
   2109	if (nn->client_tracking_ops)
   2110		nn->client_tracking_ops->grace_done(nn);
   2111}
   2112
   2113static int
   2114rpc_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
   2152static struct notifier_block nfsd4_cld_block = {
   2153	.notifier_call = rpc_pipefs_event,
   2154};
   2155
   2156int
   2157register_cld_notifier(void)
   2158{
   2159	WARN_ON(!nfsd_net_id);
   2160	return rpc_pipefs_notifier_register(&nfsd4_cld_block);
   2161}
   2162
   2163void
   2164unregister_cld_notifier(void)
   2165{
   2166	rpc_pipefs_notifier_unregister(&nfsd4_cld_block);
   2167}