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