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