2 * Copyright (c) 2004 The Regents of the University of Michigan.
3 * Copyright (c) 2012 Jeff Layton <jlayton@redhat.com>
6 * Andy Adamson <andros@citi.umich.edu>
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
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.
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.
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>
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>
52 #define NFSDDBG_FACILITY NFSDDBG_PROC
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
*);
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
;
70 static char user_recovery_dirname
[PATH_MAX
] = "/var/lib/nfs/v4recovery";
73 nfs4_save_creds(const struct cred
**original_creds
)
77 new = prepare_creds();
81 new->fsuid
= GLOBAL_ROOT_UID
;
82 new->fsgid
= GLOBAL_ROOT_GID
;
83 *original_creds
= override_creds(new);
89 nfs4_reset_creds(const struct cred
*original
)
91 revert_creds(original
);
95 md5_to_hex(char *out
, char *md5
)
99 for (i
=0; i
<16; i
++) {
100 unsigned char c
= md5
[i
];
102 *out
++ = '0' + ((c
&0xf0)>>4) + (c
>=0xa0)*('a'-'9'-1);
103 *out
++ = '0' + (c
&0x0f) + ((c
&0x0f)>=0x0a)*('a'-'9'-1);
109 nfs4_make_rec_clidname(char *dname
, const struct xdr_netobj
*clname
)
111 struct xdr_netobj cksum
;
112 struct crypto_shash
*tfm
;
115 dprintk("NFSD: nfs4_make_rec_clidname for %.*s\n",
116 clname
->len
, clname
->data
);
117 tfm
= crypto_alloc_shash("md5", 0, 0);
119 status
= PTR_ERR(tfm
);
123 cksum
.len
= crypto_shash_digestsize(tfm
);
124 cksum
.data
= kmalloc(cksum
.len
, GFP_KERNEL
);
125 if (cksum
.data
== NULL
) {
131 SHASH_DESC_ON_STACK(desc
, tfm
);
135 status
= crypto_shash_digest(desc
, clname
->data
, clname
->len
,
137 shash_desc_zero(desc
);
143 md5_to_hex(dname
, cksum
.data
);
148 crypto_free_shash(tfm
);
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.
159 legacy_recdir_name_error(struct nfs4_client
*clp
, int error
)
161 printk(KERN_ERR
"NFSD: unable to generate recoverydir "
162 "name (%d).\n", error
);
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.
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
);
177 __nfsd4_create_reclaim_record_grace(struct nfs4_client
*clp
,
178 const char *dname
, int len
, struct nfsd_net
*nn
)
180 struct xdr_netobj name
;
181 struct xdr_netobj princhash
= { .len
= 0, .data
= NULL
};
182 struct nfs4_client_reclaim
*crp
;
184 name
.data
= kmemdup(dname
, len
, GFP_KERNEL
);
186 dprintk("%s: failed to allocate memory for name.data!\n",
191 crp
= nfs4_client_to_reclaim(name
, princhash
, nn
);
200 nfsd4_create_clid_dir(struct nfs4_client
*clp
)
202 const struct cred
*original_cred
;
203 char dname
[HEXDIR_LEN
];
204 struct dentry
*dir
, *dentry
;
206 struct nfsd_net
*nn
= net_generic(clp
->net
, nfsd_net_id
);
208 if (test_and_set_bit(NFSD4_CLIENT_STABLE
, &clp
->cl_flags
))
213 status
= nfs4_make_rec_clidname(dname
, &clp
->cl_name
);
215 return legacy_recdir_name_error(clp
, status
);
217 status
= nfs4_save_creds(&original_cred
);
221 status
= mnt_want_write_file(nn
->rec_file
);
225 dir
= nn
->rec_file
->f_path
.dentry
;
226 /* lock the parent */
227 inode_lock(d_inode(dir
));
229 dentry
= lookup_one_len(dname
, dir
, HEXDIR_LEN
-1);
230 if (IS_ERR(dentry
)) {
231 status
= PTR_ERR(dentry
);
234 if (d_really_is_positive(dentry
))
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.
240 * In the 4.0 case, we should never get here; but we may
241 * as well be forgiving and just succeed silently.
244 status
= vfs_mkdir(d_inode(dir
), dentry
, S_IRWXU
);
248 inode_unlock(d_inode(dir
));
251 __nfsd4_create_reclaim_record_grace(clp
, dname
,
253 vfs_fsync(nn
->rec_file
, 0);
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
);
260 mnt_drop_write_file(nn
->rec_file
);
262 nfs4_reset_creds(original_cred
);
265 typedef int (recdir_func
)(struct dentry
*, struct dentry
*, struct nfsd_net
*);
268 char name
[HEXDIR_LEN
];
269 struct list_head list
;
272 struct nfs4_dir_ctx
{
273 struct dir_context ctx
;
274 struct list_head names
;
278 nfsd4_build_namelist(struct dir_context
*__ctx
, const char *name
, int namlen
,
279 loff_t offset
, u64 ino
, unsigned int d_type
)
281 struct nfs4_dir_ctx
*ctx
=
282 container_of(__ctx
, struct nfs4_dir_ctx
, ctx
);
283 struct name_list
*entry
;
285 if (namlen
!= HEXDIR_LEN
- 1)
287 entry
= kmalloc(sizeof(struct name_list
), GFP_KERNEL
);
290 memcpy(entry
->name
, name
, HEXDIR_LEN
- 1);
291 entry
->name
[HEXDIR_LEN
- 1] = '\0';
292 list_add(&entry
->list
, &ctx
->names
);
297 nfsd4_list_rec_dir(recdir_func
*f
, struct nfsd_net
*nn
)
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
)
305 struct name_list
*entry
, *tmp
;
308 status
= nfs4_save_creds(&original_cred
);
312 status
= vfs_llseek(nn
->rec_file
, 0, SEEK_SET
);
314 nfs4_reset_creds(original_cred
);
318 status
= iterate_dir(nn
->rec_file
, &ctx
.ctx
);
319 inode_lock_nested(d_inode(dir
), I_MUTEX_PARENT
);
321 list_for_each_entry_safe(entry
, tmp
, &ctx
.names
, list
) {
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
);
329 status
= f(dir
, dentry
, nn
);
332 list_del(&entry
->list
);
335 inode_unlock(d_inode(dir
));
336 nfs4_reset_creds(original_cred
);
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
);
347 nfsd4_unlink_clid_dir(char *name
, int namlen
, struct nfsd_net
*nn
)
349 struct dentry
*dir
, *dentry
;
352 dprintk("NFSD: nfsd4_unlink_clid_dir. name %.*s\n", namlen
, name
);
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
);
362 if (d_really_is_negative(dentry
))
364 status
= vfs_rmdir(d_inode(dir
), dentry
);
368 inode_unlock(d_inode(dir
));
373 __nfsd4_remove_reclaim_record_grace(const char *dname
, int len
,
376 struct xdr_netobj name
;
377 struct nfs4_client_reclaim
*crp
;
379 name
.data
= kmemdup(dname
, len
, GFP_KERNEL
);
381 dprintk("%s: failed to allocate memory for name.data!\n",
386 crp
= nfsd4_find_reclaim_client(name
, nn
);
389 nfs4_remove_reclaim_record(crp
, nn
);
393 nfsd4_remove_clid_dir(struct nfs4_client
*clp
)
395 const struct cred
*original_cred
;
396 char dname
[HEXDIR_LEN
];
398 struct nfsd_net
*nn
= net_generic(clp
->net
, nfsd_net_id
);
400 if (!nn
->rec_file
|| !test_bit(NFSD4_CLIENT_STABLE
, &clp
->cl_flags
))
403 status
= nfs4_make_rec_clidname(dname
, &clp
->cl_name
);
405 return legacy_recdir_name_error(clp
, status
);
407 status
= mnt_want_write_file(nn
->rec_file
);
410 clear_bit(NFSD4_CLIENT_STABLE
, &clp
->cl_flags
);
412 status
= nfs4_save_creds(&original_cred
);
416 status
= nfsd4_unlink_clid_dir(dname
, HEXDIR_LEN
-1, nn
);
417 nfs4_reset_creds(original_cred
);
419 vfs_fsync(nn
->rec_file
, 0);
421 __nfsd4_remove_reclaim_record_grace(dname
,
425 mnt_drop_write_file(nn
->rec_file
);
428 printk("NFSD: Failed to remove expired client state directory"
429 " %.*s\n", HEXDIR_LEN
, dname
);
433 purge_old(struct dentry
*parent
, struct dentry
*child
, struct nfsd_net
*nn
)
436 struct xdr_netobj name
;
438 if (child
->d_name
.len
!= HEXDIR_LEN
- 1) {
439 printk("%s: illegal name %pd in recovery directory\n",
441 /* Keep trying; maybe the others are OK: */
444 name
.data
= kmemdup_nul(child
->d_name
.name
, child
->d_name
.len
, GFP_KERNEL
);
446 dprintk("%s: failed to allocate memory for name.data!\n",
450 name
.len
= HEXDIR_LEN
;
451 if (nfs4_has_reclaimed_state(name
, nn
))
454 status
= vfs_rmdir(d_inode(parent
), child
);
456 printk("failed to remove client recovery directory %pd\n",
461 /* Keep trying, success or failure: */
466 nfsd4_recdir_purge_old(struct nfsd_net
*nn
)
470 nn
->in_grace
= false;
473 status
= mnt_want_write_file(nn
->rec_file
);
476 status
= nfsd4_list_rec_dir(purge_old
, nn
);
478 vfs_fsync(nn
->rec_file
, 0);
479 mnt_drop_write_file(nn
->rec_file
);
481 nfs4_release_reclaim(nn
);
483 printk("nfsd4: failed to purge old clients from recovery"
484 " directory %pD\n", nn
->rec_file
);
488 load_recdir(struct dentry
*parent
, struct dentry
*child
, struct nfsd_net
*nn
)
490 struct xdr_netobj name
;
491 struct xdr_netobj princhash
= { .len
= 0, .data
= NULL
};
493 if (child
->d_name
.len
!= HEXDIR_LEN
- 1) {
494 printk("%s: illegal name %pd in recovery directory\n",
496 /* Keep trying; maybe the others are OK: */
499 name
.data
= kmemdup_nul(child
->d_name
.name
, child
->d_name
.len
, GFP_KERNEL
);
501 dprintk("%s: failed to allocate memory for name.data!\n",
505 name
.len
= HEXDIR_LEN
;
506 if (!nfs4_client_to_reclaim(name
, princhash
, nn
))
513 nfsd4_recdir_load(struct net
*net
) {
515 struct nfsd_net
*nn
= net_generic(net
, nfsd_net_id
);
520 status
= nfsd4_list_rec_dir(load_recdir
, nn
);
522 printk("nfsd4: failed loading clients from recovery"
523 " directory %pD\n", nn
->rec_file
);
528 * Hold reference to the recovery directory.
532 nfsd4_init_recdir(struct net
*net
)
534 struct nfsd_net
*nn
= net_generic(net
, nfsd_net_id
);
535 const struct cred
*original_cred
;
538 printk("NFSD: Using %s as the NFSv4 state recovery directory\n",
539 user_recovery_dirname
);
541 BUG_ON(nn
->rec_file
);
543 status
= nfs4_save_creds(&original_cred
);
545 printk("NFSD: Unable to change credentials to find recovery"
546 " directory: error %d\n",
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
);
559 nfs4_reset_creds(original_cred
);
566 nfsd4_shutdown_recdir(struct net
*net
)
568 struct nfsd_net
*nn
= net_generic(net
, nfsd_net_id
);
577 nfs4_legacy_state_init(struct net
*net
)
579 struct nfsd_net
*nn
= net_generic(net
, nfsd_net_id
);
582 nn
->reclaim_str_hashtbl
= kmalloc_array(CLIENT_HASH_SIZE
,
583 sizeof(struct list_head
),
585 if (!nn
->reclaim_str_hashtbl
)
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;
596 nfs4_legacy_state_shutdown(struct net
*net
)
598 struct nfsd_net
*nn
= net_generic(net
, nfsd_net_id
);
600 kfree(nn
->reclaim_str_hashtbl
);
604 nfsd4_load_reboot_recovery_data(struct net
*net
)
608 status
= nfsd4_init_recdir(net
);
612 status
= nfsd4_recdir_load(net
);
614 nfsd4_shutdown_recdir(net
);
620 nfsd4_legacy_tracking_init(struct net
*net
)
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");
630 status
= nfs4_legacy_state_init(net
);
634 status
= nfsd4_load_reboot_recovery_data(net
);
637 printk("NFSD: Using legacy client tracking operations.\n");
641 nfs4_legacy_state_shutdown(net
);
646 nfsd4_legacy_tracking_exit(struct net
*net
)
648 struct nfsd_net
*nn
= net_generic(net
, nfsd_net_id
);
650 nfs4_release_reclaim(nn
);
651 nfsd4_shutdown_recdir(net
);
652 nfs4_legacy_state_shutdown(net
);
656 * Change the NFSv4 recovery directory to recdir.
659 nfs4_reset_recoverydir(char *recdir
)
664 status
= kern_path(recdir
, LOOKUP_FOLLOW
, &path
);
668 if (d_is_dir(path
.dentry
)) {
669 strcpy(user_recovery_dirname
, recdir
);
677 nfs4_recoverydir(void)
679 return user_recovery_dirname
;
683 nfsd4_check_legacy_client(struct nfs4_client
*clp
)
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
;
691 /* did we already find that this client is stable? */
692 if (test_bit(NFSD4_CLIENT_STABLE
, &clp
->cl_flags
))
695 status
= nfs4_make_rec_clidname(dname
, &clp
->cl_name
);
697 legacy_recdir_name_error(clp
, status
);
701 /* look for it in the reclaim hashtable otherwise */
702 name
.data
= kmemdup(dname
, HEXDIR_LEN
, GFP_KERNEL
);
704 dprintk("%s: failed to allocate memory for name.data!\n",
708 name
.len
= HEXDIR_LEN
;
709 crp
= nfsd4_find_reclaim_client(name
, nn
);
712 set_bit(NFSD4_CLIENT_STABLE
, &clp
->cl_flags
);
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
,
733 #define NFSD_PIPE_DIR "nfsd"
734 #define NFSD_CLD_PIPE "cld"
736 /* per-net-ns structure for holding cld upcall info */
738 struct rpc_pipe
*cn_pipe
;
740 struct list_head cn_list
;
743 struct crypto_shash
*cn_tfm
;
747 struct list_head cu_list
;
748 struct cld_net
*cu_net
;
749 struct completion cu_done
;
751 struct cld_msg_hdr cu_hdr
;
752 struct cld_msg cu_msg
;
753 struct cld_msg_v2 cu_msg_v2
;
758 __cld_pipe_upcall(struct rpc_pipe
*pipe
, void *cmsg
)
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
,
766 memset(&msg
, 0, sizeof(msg
));
768 msg
.len
= nn
->client_tracking_ops
->msglen
;
770 ret
= rpc_queue_upcall(pipe
, &msg
);
775 wait_for_completion(&cup
->cu_done
);
784 cld_pipe_upcall(struct rpc_pipe
*pipe
, void *cmsg
)
789 * -EAGAIN occurs when pipe is closed and reopened while there are
793 ret
= __cld_pipe_upcall(pipe
, cmsg
);
794 } while (ret
== -EAGAIN
);
800 __cld_pipe_inprogress_downcall(const struct cld_msg_v2 __user
*cmsg
,
803 uint8_t cmd
, princhashlen
;
804 struct xdr_netobj name
, princhash
= { .len
= 0, .data
= NULL
};
806 struct cld_net
*cn
= nn
->cld_net
;
808 if (get_user(cmd
, &cmsg
->cm_cmd
)) {
809 dprintk("%s: error when copying cmd from userspace", __func__
);
812 if (cmd
== Cld_GraceStart
) {
813 if (nn
->client_tracking_ops
->version
>= 2) {
814 const struct cld_clntinfo __user
*ci
;
816 ci
= &cmsg
->cm_u
.cm_clntinfo
;
817 if (get_user(namelen
, &ci
->cc_name
.cn_len
))
819 name
.data
= memdup_user(&ci
->cc_name
.cn_id
, namelen
);
820 if (IS_ERR_OR_NULL(name
.data
))
823 get_user(princhashlen
, &ci
->cc_princhash
.cp_len
);
824 if (princhashlen
> 0) {
825 princhash
.data
= memdup_user(
826 &ci
->cc_princhash
.cp_data
,
828 if (IS_ERR_OR_NULL(princhash
.data
))
830 princhash
.len
= princhashlen
;
834 const struct cld_name __user
*cnm
;
836 cnm
= &cmsg
->cm_u
.cm_name
;
837 if (get_user(namelen
, &cnm
->cn_len
))
839 name
.data
= memdup_user(&cnm
->cn_id
, namelen
);
840 if (IS_ERR_OR_NULL(name
.data
))
844 if (name
.len
> 5 && memcmp(name
.data
, "hash:", 5) == 0) {
845 name
.len
= name
.len
- 5;
846 memmove(name
.data
, name
.data
+ 5, name
.len
);
847 cn
->cn_has_legacy
= true;
849 if (!nfs4_client_to_reclaim(name
, princhash
, nn
)) {
851 kfree(princhash
.data
);
854 return nn
->client_tracking_ops
->msglen
;
860 cld_pipe_downcall(struct file
*filp
, const char __user
*src
, size_t mlen
)
862 struct cld_upcall
*tmp
, *cup
;
863 struct cld_msg_hdr __user
*hdr
= (struct cld_msg_hdr __user
*)src
;
864 struct cld_msg_v2 __user
*cmsg
= (struct cld_msg_v2 __user
*)src
;
866 struct nfsd_net
*nn
= net_generic(file_inode(filp
)->i_sb
->s_fs_info
,
868 struct cld_net
*cn
= nn
->cld_net
;
871 if (mlen
!= nn
->client_tracking_ops
->msglen
) {
872 dprintk("%s: got %zu bytes, expected %zu\n", __func__
, mlen
,
873 nn
->client_tracking_ops
->msglen
);
877 /* copy just the xid so we can try to find that */
878 if (copy_from_user(&xid
, &hdr
->cm_xid
, sizeof(xid
)) != 0) {
879 dprintk("%s: error when copying xid from userspace", __func__
);
884 * copy the status so we know whether to remove the upcall from the
885 * list (for -EINPROGRESS, we just want to make sure the xid is
886 * valid, not remove the upcall from the list)
888 if (get_user(status
, &hdr
->cm_status
)) {
889 dprintk("%s: error when copying status from userspace", __func__
);
893 /* walk the list and find corresponding xid */
895 spin_lock(&cn
->cn_lock
);
896 list_for_each_entry(tmp
, &cn
->cn_list
, cu_list
) {
897 if (get_unaligned(&tmp
->cu_u
.cu_hdr
.cm_xid
) == xid
) {
899 if (status
!= -EINPROGRESS
)
900 list_del_init(&cup
->cu_list
);
904 spin_unlock(&cn
->cn_lock
);
906 /* couldn't find upcall? */
908 dprintk("%s: couldn't find upcall -- xid=%u\n", __func__
, xid
);
912 if (status
== -EINPROGRESS
)
913 return __cld_pipe_inprogress_downcall(cmsg
, nn
);
915 if (copy_from_user(&cup
->cu_u
.cu_msg_v2
, src
, mlen
) != 0)
918 complete(&cup
->cu_done
);
923 cld_pipe_destroy_msg(struct rpc_pipe_msg
*msg
)
925 struct cld_msg
*cmsg
= msg
->data
;
926 struct cld_upcall
*cup
= container_of(cmsg
, struct cld_upcall
,
929 /* errno >= 0 means we got a downcall */
933 complete(&cup
->cu_done
);
936 static const struct rpc_pipe_ops cld_upcall_ops
= {
937 .upcall
= rpc_pipe_generic_upcall
,
938 .downcall
= cld_pipe_downcall
,
939 .destroy_msg
= cld_pipe_destroy_msg
,
942 static struct dentry
*
943 nfsd4_cld_register_sb(struct super_block
*sb
, struct rpc_pipe
*pipe
)
945 struct dentry
*dir
, *dentry
;
947 dir
= rpc_d_lookup_sb(sb
, NFSD_PIPE_DIR
);
949 return ERR_PTR(-ENOENT
);
950 dentry
= rpc_mkpipe_dentry(dir
, NFSD_CLD_PIPE
, NULL
, pipe
);
956 nfsd4_cld_unregister_sb(struct rpc_pipe
*pipe
)
959 rpc_unlink(pipe
->dentry
);
962 static struct dentry
*
963 nfsd4_cld_register_net(struct net
*net
, struct rpc_pipe
*pipe
)
965 struct super_block
*sb
;
966 struct dentry
*dentry
;
968 sb
= rpc_get_sb_net(net
);
971 dentry
= nfsd4_cld_register_sb(sb
, pipe
);
977 nfsd4_cld_unregister_net(struct net
*net
, struct rpc_pipe
*pipe
)
979 struct super_block
*sb
;
981 sb
= rpc_get_sb_net(net
);
983 nfsd4_cld_unregister_sb(pipe
);
988 /* Initialize rpc_pipefs pipe for communication with client tracking daemon */
990 __nfsd4_init_cld_pipe(struct net
*net
)
993 struct dentry
*dentry
;
994 struct nfsd_net
*nn
= net_generic(net
, nfsd_net_id
);
1000 cn
= kzalloc(sizeof(*cn
), GFP_KERNEL
);
1006 cn
->cn_pipe
= rpc_mkpipe_data(&cld_upcall_ops
, RPC_PIPE_WAIT_FOR_OPEN
);
1007 if (IS_ERR(cn
->cn_pipe
)) {
1008 ret
= PTR_ERR(cn
->cn_pipe
);
1011 spin_lock_init(&cn
->cn_lock
);
1012 INIT_LIST_HEAD(&cn
->cn_list
);
1014 dentry
= nfsd4_cld_register_net(net
, cn
->cn_pipe
);
1015 if (IS_ERR(dentry
)) {
1016 ret
= PTR_ERR(dentry
);
1017 goto err_destroy_data
;
1020 cn
->cn_pipe
->dentry
= dentry
;
1021 cn
->cn_has_legacy
= false;
1026 rpc_destroy_pipe_data(cn
->cn_pipe
);
1029 printk(KERN_ERR
"NFSD: unable to create nfsdcld upcall pipe (%d)\n",
1035 nfsd4_init_cld_pipe(struct net
*net
)
1039 status
= __nfsd4_init_cld_pipe(net
);
1041 printk("NFSD: Using old nfsdcld client tracking operations.\n");
1046 nfsd4_remove_cld_pipe(struct net
*net
)
1048 struct nfsd_net
*nn
= net_generic(net
, nfsd_net_id
);
1049 struct cld_net
*cn
= nn
->cld_net
;
1051 nfsd4_cld_unregister_net(net
, cn
->cn_pipe
);
1052 rpc_destroy_pipe_data(cn
->cn_pipe
);
1054 crypto_free_shash(cn
->cn_tfm
);
1059 static struct cld_upcall
*
1060 alloc_cld_upcall(struct nfsd_net
*nn
)
1062 struct cld_upcall
*new, *tmp
;
1063 struct cld_net
*cn
= nn
->cld_net
;
1065 new = kzalloc(sizeof(*new), GFP_KERNEL
);
1069 /* FIXME: hard cap on number in flight? */
1071 spin_lock(&cn
->cn_lock
);
1072 list_for_each_entry(tmp
, &cn
->cn_list
, cu_list
) {
1073 if (tmp
->cu_u
.cu_msg
.cm_xid
== cn
->cn_xid
) {
1075 spin_unlock(&cn
->cn_lock
);
1076 goto restart_search
;
1079 init_completion(&new->cu_done
);
1080 new->cu_u
.cu_msg
.cm_vers
= nn
->client_tracking_ops
->version
;
1081 put_unaligned(cn
->cn_xid
++, &new->cu_u
.cu_msg
.cm_xid
);
1083 list_add(&new->cu_list
, &cn
->cn_list
);
1084 spin_unlock(&cn
->cn_lock
);
1086 dprintk("%s: allocated xid %u\n", __func__
, new->cu_u
.cu_msg
.cm_xid
);
1092 free_cld_upcall(struct cld_upcall
*victim
)
1094 struct cld_net
*cn
= victim
->cu_net
;
1096 spin_lock(&cn
->cn_lock
);
1097 list_del(&victim
->cu_list
);
1098 spin_unlock(&cn
->cn_lock
);
1102 /* Ask daemon to create a new record */
1104 nfsd4_cld_create(struct nfs4_client
*clp
)
1107 struct cld_upcall
*cup
;
1108 struct nfsd_net
*nn
= net_generic(clp
->net
, nfsd_net_id
);
1109 struct cld_net
*cn
= nn
->cld_net
;
1111 /* Don't upcall if it's already stored */
1112 if (test_bit(NFSD4_CLIENT_STABLE
, &clp
->cl_flags
))
1115 cup
= alloc_cld_upcall(nn
);
1121 cup
->cu_u
.cu_msg
.cm_cmd
= Cld_Create
;
1122 cup
->cu_u
.cu_msg
.cm_u
.cm_name
.cn_len
= clp
->cl_name
.len
;
1123 memcpy(cup
->cu_u
.cu_msg
.cm_u
.cm_name
.cn_id
, clp
->cl_name
.data
,
1126 ret
= cld_pipe_upcall(cn
->cn_pipe
, &cup
->cu_u
.cu_msg
);
1128 ret
= cup
->cu_u
.cu_msg
.cm_status
;
1129 set_bit(NFSD4_CLIENT_STABLE
, &clp
->cl_flags
);
1132 free_cld_upcall(cup
);
1135 printk(KERN_ERR
"NFSD: Unable to create client "
1136 "record on stable storage: %d\n", ret
);
1139 /* Ask daemon to create a new record */
1141 nfsd4_cld_create_v2(struct nfs4_client
*clp
)
1144 struct cld_upcall
*cup
;
1145 struct nfsd_net
*nn
= net_generic(clp
->net
, nfsd_net_id
);
1146 struct cld_net
*cn
= nn
->cld_net
;
1147 struct cld_msg_v2
*cmsg
;
1148 struct crypto_shash
*tfm
= cn
->cn_tfm
;
1149 struct xdr_netobj cksum
;
1150 char *principal
= NULL
;
1151 SHASH_DESC_ON_STACK(desc
, tfm
);
1153 /* Don't upcall if it's already stored */
1154 if (test_bit(NFSD4_CLIENT_STABLE
, &clp
->cl_flags
))
1157 cup
= alloc_cld_upcall(nn
);
1163 cmsg
= &cup
->cu_u
.cu_msg_v2
;
1164 cmsg
->cm_cmd
= Cld_Create
;
1165 cmsg
->cm_u
.cm_clntinfo
.cc_name
.cn_len
= clp
->cl_name
.len
;
1166 memcpy(cmsg
->cm_u
.cm_clntinfo
.cc_name
.cn_id
, clp
->cl_name
.data
,
1168 if (clp
->cl_cred
.cr_raw_principal
)
1169 principal
= clp
->cl_cred
.cr_raw_principal
;
1170 else if (clp
->cl_cred
.cr_principal
)
1171 principal
= clp
->cl_cred
.cr_principal
;
1174 cksum
.len
= crypto_shash_digestsize(tfm
);
1175 cksum
.data
= kmalloc(cksum
.len
, GFP_KERNEL
);
1176 if (cksum
.data
== NULL
) {
1180 ret
= crypto_shash_digest(desc
, principal
, strlen(principal
),
1182 shash_desc_zero(desc
);
1187 cmsg
->cm_u
.cm_clntinfo
.cc_princhash
.cp_len
= cksum
.len
;
1188 memcpy(cmsg
->cm_u
.cm_clntinfo
.cc_princhash
.cp_data
,
1189 cksum
.data
, cksum
.len
);
1192 cmsg
->cm_u
.cm_clntinfo
.cc_princhash
.cp_len
= 0;
1194 ret
= cld_pipe_upcall(cn
->cn_pipe
, cmsg
);
1196 ret
= cmsg
->cm_status
;
1197 set_bit(NFSD4_CLIENT_STABLE
, &clp
->cl_flags
);
1201 free_cld_upcall(cup
);
1204 pr_err("NFSD: Unable to create client record on stable storage: %d\n",
1208 /* Ask daemon to create a new record */
1210 nfsd4_cld_remove(struct nfs4_client
*clp
)
1213 struct cld_upcall
*cup
;
1214 struct nfsd_net
*nn
= net_generic(clp
->net
, nfsd_net_id
);
1215 struct cld_net
*cn
= nn
->cld_net
;
1217 /* Don't upcall if it's already removed */
1218 if (!test_bit(NFSD4_CLIENT_STABLE
, &clp
->cl_flags
))
1221 cup
= alloc_cld_upcall(nn
);
1227 cup
->cu_u
.cu_msg
.cm_cmd
= Cld_Remove
;
1228 cup
->cu_u
.cu_msg
.cm_u
.cm_name
.cn_len
= clp
->cl_name
.len
;
1229 memcpy(cup
->cu_u
.cu_msg
.cm_u
.cm_name
.cn_id
, clp
->cl_name
.data
,
1232 ret
= cld_pipe_upcall(cn
->cn_pipe
, &cup
->cu_u
.cu_msg
);
1234 ret
= cup
->cu_u
.cu_msg
.cm_status
;
1235 clear_bit(NFSD4_CLIENT_STABLE
, &clp
->cl_flags
);
1238 free_cld_upcall(cup
);
1241 printk(KERN_ERR
"NFSD: Unable to remove client "
1242 "record from stable storage: %d\n", ret
);
1246 * For older nfsdcld's that do not allow us to "slurp" the clients
1247 * from the tracking database during startup.
1249 * Check for presence of a record, and update its timestamp
1252 nfsd4_cld_check_v0(struct nfs4_client
*clp
)
1255 struct cld_upcall
*cup
;
1256 struct nfsd_net
*nn
= net_generic(clp
->net
, nfsd_net_id
);
1257 struct cld_net
*cn
= nn
->cld_net
;
1259 /* Don't upcall if one was already stored during this grace pd */
1260 if (test_bit(NFSD4_CLIENT_STABLE
, &clp
->cl_flags
))
1263 cup
= alloc_cld_upcall(nn
);
1265 printk(KERN_ERR
"NFSD: Unable to check client record on "
1266 "stable storage: %d\n", -ENOMEM
);
1270 cup
->cu_u
.cu_msg
.cm_cmd
= Cld_Check
;
1271 cup
->cu_u
.cu_msg
.cm_u
.cm_name
.cn_len
= clp
->cl_name
.len
;
1272 memcpy(cup
->cu_u
.cu_msg
.cm_u
.cm_name
.cn_id
, clp
->cl_name
.data
,
1275 ret
= cld_pipe_upcall(cn
->cn_pipe
, &cup
->cu_u
.cu_msg
);
1277 ret
= cup
->cu_u
.cu_msg
.cm_status
;
1278 set_bit(NFSD4_CLIENT_STABLE
, &clp
->cl_flags
);
1281 free_cld_upcall(cup
);
1286 * For newer nfsdcld's that allow us to "slurp" the clients
1287 * from the tracking database during startup.
1289 * Check for presence of a record in the reclaim_str_hashtbl
1292 nfsd4_cld_check(struct nfs4_client
*clp
)
1294 struct nfs4_client_reclaim
*crp
;
1295 struct nfsd_net
*nn
= net_generic(clp
->net
, nfsd_net_id
);
1296 struct cld_net
*cn
= nn
->cld_net
;
1298 char dname
[HEXDIR_LEN
];
1299 struct xdr_netobj name
;
1301 /* did we already find that this client is stable? */
1302 if (test_bit(NFSD4_CLIENT_STABLE
, &clp
->cl_flags
))
1305 /* look for it in the reclaim hashtable otherwise */
1306 crp
= nfsd4_find_reclaim_client(clp
->cl_name
, nn
);
1310 if (cn
->cn_has_legacy
) {
1311 status
= nfs4_make_rec_clidname(dname
, &clp
->cl_name
);
1315 name
.data
= kmemdup(dname
, HEXDIR_LEN
, GFP_KERNEL
);
1317 dprintk("%s: failed to allocate memory for name.data!\n",
1321 name
.len
= HEXDIR_LEN
;
1322 crp
= nfsd4_find_reclaim_client(name
, nn
);
1335 nfsd4_cld_check_v2(struct nfs4_client
*clp
)
1337 struct nfs4_client_reclaim
*crp
;
1338 struct nfsd_net
*nn
= net_generic(clp
->net
, nfsd_net_id
);
1339 struct cld_net
*cn
= nn
->cld_net
;
1341 char dname
[HEXDIR_LEN
];
1342 struct xdr_netobj name
;
1343 struct crypto_shash
*tfm
= cn
->cn_tfm
;
1344 struct xdr_netobj cksum
;
1345 char *principal
= NULL
;
1346 SHASH_DESC_ON_STACK(desc
, tfm
);
1348 /* did we already find that this client is stable? */
1349 if (test_bit(NFSD4_CLIENT_STABLE
, &clp
->cl_flags
))
1352 /* look for it in the reclaim hashtable otherwise */
1353 crp
= nfsd4_find_reclaim_client(clp
->cl_name
, nn
);
1357 if (cn
->cn_has_legacy
) {
1358 status
= nfs4_make_rec_clidname(dname
, &clp
->cl_name
);
1362 name
.data
= kmemdup(dname
, HEXDIR_LEN
, GFP_KERNEL
);
1364 dprintk("%s: failed to allocate memory for name.data\n",
1368 name
.len
= HEXDIR_LEN
;
1369 crp
= nfsd4_find_reclaim_client(name
, nn
);
1377 if (crp
->cr_princhash
.len
) {
1378 if (clp
->cl_cred
.cr_raw_principal
)
1379 principal
= clp
->cl_cred
.cr_raw_principal
;
1380 else if (clp
->cl_cred
.cr_principal
)
1381 principal
= clp
->cl_cred
.cr_principal
;
1382 if (principal
== NULL
)
1385 cksum
.len
= crypto_shash_digestsize(tfm
);
1386 cksum
.data
= kmalloc(cksum
.len
, GFP_KERNEL
);
1387 if (cksum
.data
== NULL
)
1389 status
= crypto_shash_digest(desc
, principal
, strlen(principal
),
1391 shash_desc_zero(desc
);
1396 if (memcmp(crp
->cr_princhash
.data
, cksum
.data
,
1397 crp
->cr_princhash
.len
)) {
1408 nfsd4_cld_grace_start(struct nfsd_net
*nn
)
1411 struct cld_upcall
*cup
;
1412 struct cld_net
*cn
= nn
->cld_net
;
1414 cup
= alloc_cld_upcall(nn
);
1420 cup
->cu_u
.cu_msg
.cm_cmd
= Cld_GraceStart
;
1421 ret
= cld_pipe_upcall(cn
->cn_pipe
, &cup
->cu_u
.cu_msg
);
1423 ret
= cup
->cu_u
.cu_msg
.cm_status
;
1425 free_cld_upcall(cup
);
1428 dprintk("%s: Unable to get clients from userspace: %d\n",
1433 /* For older nfsdcld's that need cm_gracetime */
1435 nfsd4_cld_grace_done_v0(struct nfsd_net
*nn
)
1438 struct cld_upcall
*cup
;
1439 struct cld_net
*cn
= nn
->cld_net
;
1441 cup
= alloc_cld_upcall(nn
);
1447 cup
->cu_u
.cu_msg
.cm_cmd
= Cld_GraceDone
;
1448 cup
->cu_u
.cu_msg
.cm_u
.cm_gracetime
= (int64_t)nn
->boot_time
;
1449 ret
= cld_pipe_upcall(cn
->cn_pipe
, &cup
->cu_u
.cu_msg
);
1451 ret
= cup
->cu_u
.cu_msg
.cm_status
;
1453 free_cld_upcall(cup
);
1456 printk(KERN_ERR
"NFSD: Unable to end grace period: %d\n", ret
);
1460 * For newer nfsdcld's that do not need cm_gracetime. We also need to call
1461 * nfs4_release_reclaim() to clear out the reclaim_str_hashtbl.
1464 nfsd4_cld_grace_done(struct nfsd_net
*nn
)
1467 struct cld_upcall
*cup
;
1468 struct cld_net
*cn
= nn
->cld_net
;
1470 cup
= alloc_cld_upcall(nn
);
1476 cup
->cu_u
.cu_msg
.cm_cmd
= Cld_GraceDone
;
1477 ret
= cld_pipe_upcall(cn
->cn_pipe
, &cup
->cu_u
.cu_msg
);
1479 ret
= cup
->cu_u
.cu_msg
.cm_status
;
1481 free_cld_upcall(cup
);
1483 nfs4_release_reclaim(nn
);
1485 printk(KERN_ERR
"NFSD: Unable to end grace period: %d\n", ret
);
1489 nfs4_cld_state_init(struct net
*net
)
1491 struct nfsd_net
*nn
= net_generic(net
, nfsd_net_id
);
1494 nn
->reclaim_str_hashtbl
= kmalloc_array(CLIENT_HASH_SIZE
,
1495 sizeof(struct list_head
),
1497 if (!nn
->reclaim_str_hashtbl
)
1500 for (i
= 0; i
< CLIENT_HASH_SIZE
; i
++)
1501 INIT_LIST_HEAD(&nn
->reclaim_str_hashtbl
[i
]);
1502 nn
->reclaim_str_hashtbl_size
= 0;
1503 nn
->track_reclaim_completes
= true;
1504 atomic_set(&nn
->nr_reclaim_complete
, 0);
1510 nfs4_cld_state_shutdown(struct net
*net
)
1512 struct nfsd_net
*nn
= net_generic(net
, nfsd_net_id
);
1514 nn
->track_reclaim_completes
= false;
1515 kfree(nn
->reclaim_str_hashtbl
);
1519 cld_running(struct nfsd_net
*nn
)
1521 struct cld_net
*cn
= nn
->cld_net
;
1522 struct rpc_pipe
*pipe
= cn
->cn_pipe
;
1524 return pipe
->nreaders
|| pipe
->nwriters
;
1528 nfsd4_cld_get_version(struct nfsd_net
*nn
)
1531 struct cld_upcall
*cup
;
1532 struct cld_net
*cn
= nn
->cld_net
;
1535 cup
= alloc_cld_upcall(nn
);
1540 cup
->cu_u
.cu_msg
.cm_cmd
= Cld_GetVersion
;
1541 ret
= cld_pipe_upcall(cn
->cn_pipe
, &cup
->cu_u
.cu_msg
);
1543 ret
= cup
->cu_u
.cu_msg
.cm_status
;
1546 version
= cup
->cu_u
.cu_msg
.cm_u
.cm_version
;
1547 dprintk("%s: userspace returned version %u\n",
1551 else if (version
> CLD_UPCALL_VERSION
)
1552 version
= CLD_UPCALL_VERSION
;
1556 nn
->client_tracking_ops
= &nfsd4_cld_tracking_ops
;
1559 nn
->client_tracking_ops
= &nfsd4_cld_tracking_ops_v2
;
1566 free_cld_upcall(cup
);
1569 dprintk("%s: Unable to get version from userspace: %d\n",
1575 nfsd4_cld_tracking_init(struct net
*net
)
1578 struct nfsd_net
*nn
= net_generic(net
, nfsd_net_id
);
1581 struct crypto_shash
*tfm
;
1583 status
= nfs4_cld_state_init(net
);
1587 status
= __nfsd4_init_cld_pipe(net
);
1592 * rpc pipe upcalls take 30 seconds to time out, so we don't want to
1593 * queue an upcall unless we know that nfsdcld is running (because we
1594 * want this to fail fast so that nfsd4_client_tracking_init() can try
1595 * the next client tracking method). nfsdcld should already be running
1596 * before nfsd is started, so the wait here is for nfsdcld to open the
1597 * pipefs file we just created.
1599 while (!(running
= cld_running(nn
)) && retries
--)
1603 status
= -ETIMEDOUT
;
1606 tfm
= crypto_alloc_shash("sha256", 0, 0);
1608 status
= PTR_ERR(tfm
);
1611 nn
->cld_net
->cn_tfm
= tfm
;
1613 status
= nfsd4_cld_get_version(nn
);
1614 if (status
== -EOPNOTSUPP
)
1615 pr_warn("NFSD: nfsdcld GetVersion upcall failed. Please upgrade nfsdcld.\n");
1617 status
= nfsd4_cld_grace_start(nn
);
1619 if (status
== -EOPNOTSUPP
)
1620 pr_warn("NFSD: nfsdcld GraceStart upcall failed. Please upgrade nfsdcld.\n");
1621 nfs4_release_reclaim(nn
);
1624 printk("NFSD: Using nfsdcld client tracking operations.\n");
1628 nfsd4_remove_cld_pipe(net
);
1630 nfs4_cld_state_shutdown(net
);
1635 nfsd4_cld_tracking_exit(struct net
*net
)
1637 struct nfsd_net
*nn
= net_generic(net
, nfsd_net_id
);
1639 nfs4_release_reclaim(nn
);
1640 nfsd4_remove_cld_pipe(net
);
1641 nfs4_cld_state_shutdown(net
);
1644 /* For older nfsdcld's */
1645 static const struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops_v0
= {
1646 .init
= nfsd4_init_cld_pipe
,
1647 .exit
= nfsd4_remove_cld_pipe
,
1648 .create
= nfsd4_cld_create
,
1649 .remove
= nfsd4_cld_remove
,
1650 .check
= nfsd4_cld_check_v0
,
1651 .grace_done
= nfsd4_cld_grace_done_v0
,
1653 .msglen
= sizeof(struct cld_msg
),
1656 /* For newer nfsdcld's */
1657 static const struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops
= {
1658 .init
= nfsd4_cld_tracking_init
,
1659 .exit
= nfsd4_cld_tracking_exit
,
1660 .create
= nfsd4_cld_create
,
1661 .remove
= nfsd4_cld_remove
,
1662 .check
= nfsd4_cld_check
,
1663 .grace_done
= nfsd4_cld_grace_done
,
1665 .msglen
= sizeof(struct cld_msg
),
1668 /* v2 create/check ops include the principal, if available */
1669 static const struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops_v2
= {
1670 .init
= nfsd4_cld_tracking_init
,
1671 .exit
= nfsd4_cld_tracking_exit
,
1672 .create
= nfsd4_cld_create_v2
,
1673 .remove
= nfsd4_cld_remove
,
1674 .check
= nfsd4_cld_check_v2
,
1675 .grace_done
= nfsd4_cld_grace_done
,
1677 .msglen
= sizeof(struct cld_msg_v2
),
1680 /* upcall via usermodehelper */
1681 static char cltrack_prog
[PATH_MAX
] = "/sbin/nfsdcltrack";
1682 module_param_string(cltrack_prog
, cltrack_prog
, sizeof(cltrack_prog
),
1684 MODULE_PARM_DESC(cltrack_prog
, "Path to the nfsdcltrack upcall program");
1686 static bool cltrack_legacy_disable
;
1687 module_param(cltrack_legacy_disable
, bool, S_IRUGO
|S_IWUSR
);
1688 MODULE_PARM_DESC(cltrack_legacy_disable
,
1689 "Disable legacy recoverydir conversion. Default: false");
1691 #define LEGACY_TOPDIR_ENV_PREFIX "NFSDCLTRACK_LEGACY_TOPDIR="
1692 #define LEGACY_RECDIR_ENV_PREFIX "NFSDCLTRACK_LEGACY_RECDIR="
1693 #define HAS_SESSION_ENV_PREFIX "NFSDCLTRACK_CLIENT_HAS_SESSION="
1694 #define GRACE_START_ENV_PREFIX "NFSDCLTRACK_GRACE_START="
1697 nfsd4_cltrack_legacy_topdir(void)
1703 if (cltrack_legacy_disable
)
1706 len
= strlen(LEGACY_TOPDIR_ENV_PREFIX
) +
1707 strlen(nfs4_recoverydir()) + 1;
1709 result
= kmalloc(len
, GFP_KERNEL
);
1713 copied
= snprintf(result
, len
, LEGACY_TOPDIR_ENV_PREFIX
"%s",
1714 nfs4_recoverydir());
1715 if (copied
>= len
) {
1716 /* just return nothing if output was truncated */
1725 nfsd4_cltrack_legacy_recdir(const struct xdr_netobj
*name
)
1731 if (cltrack_legacy_disable
)
1734 /* +1 is for '/' between "topdir" and "recdir" */
1735 len
= strlen(LEGACY_RECDIR_ENV_PREFIX
) +
1736 strlen(nfs4_recoverydir()) + 1 + HEXDIR_LEN
;
1738 result
= kmalloc(len
, GFP_KERNEL
);
1742 copied
= snprintf(result
, len
, LEGACY_RECDIR_ENV_PREFIX
"%s/",
1743 nfs4_recoverydir());
1744 if (copied
> (len
- HEXDIR_LEN
)) {
1745 /* just return nothing if output will be truncated */
1750 copied
= nfs4_make_rec_clidname(result
+ copied
, name
);
1760 nfsd4_cltrack_client_has_session(struct nfs4_client
*clp
)
1766 /* prefix + Y/N character + terminating NULL */
1767 len
= strlen(HAS_SESSION_ENV_PREFIX
) + 1 + 1;
1769 result
= kmalloc(len
, GFP_KERNEL
);
1773 copied
= snprintf(result
, len
, HAS_SESSION_ENV_PREFIX
"%c",
1774 clp
->cl_minorversion
? 'Y' : 'N');
1775 if (copied
>= len
) {
1776 /* just return nothing if output was truncated */
1785 nfsd4_cltrack_grace_start(time_t grace_start
)
1791 /* prefix + max width of int64_t string + terminating NULL */
1792 len
= strlen(GRACE_START_ENV_PREFIX
) + 22 + 1;
1794 result
= kmalloc(len
, GFP_KERNEL
);
1798 copied
= snprintf(result
, len
, GRACE_START_ENV_PREFIX
"%ld",
1800 if (copied
>= len
) {
1801 /* just return nothing if output was truncated */
1810 nfsd4_umh_cltrack_upcall(char *cmd
, char *arg
, char *env0
, char *env1
)
1816 if (unlikely(!cltrack_prog
[0])) {
1817 dprintk("%s: cltrack_prog is disabled\n", __func__
);
1821 dprintk("%s: cmd: %s\n", __func__
, cmd
);
1822 dprintk("%s: arg: %s\n", __func__
, arg
? arg
: "(null)");
1823 dprintk("%s: env0: %s\n", __func__
, env0
? env0
: "(null)");
1824 dprintk("%s: env1: %s\n", __func__
, env1
? env1
: "(null)");
1830 argv
[0] = (char *)cltrack_prog
;
1835 ret
= call_usermodehelper(argv
[0], argv
, envp
, UMH_WAIT_PROC
);
1837 * Disable the upcall mechanism if we're getting an ENOENT or EACCES
1838 * error. The admin can re-enable it on the fly by using sysfs
1839 * once the problem has been fixed.
1841 if (ret
== -ENOENT
|| ret
== -EACCES
) {
1842 dprintk("NFSD: %s was not found or isn't executable (%d). "
1843 "Setting cltrack_prog to blank string!",
1845 cltrack_prog
[0] = '\0';
1847 dprintk("%s: %s return value: %d\n", __func__
, cltrack_prog
, ret
);
1853 bin_to_hex_dup(const unsigned char *src
, int srclen
)
1857 /* +1 for terminating NULL */
1858 buf
= kzalloc((srclen
* 2) + 1, GFP_KERNEL
);
1862 bin2hex(buf
, src
, srclen
);
1867 nfsd4_umh_cltrack_init(struct net
*net
)
1870 struct nfsd_net
*nn
= net_generic(net
, nfsd_net_id
);
1871 char *grace_start
= nfsd4_cltrack_grace_start(nn
->boot_time
);
1873 /* XXX: The usermode helper s not working in container yet. */
1874 if (net
!= &init_net
) {
1875 pr_warn("NFSD: attempt to initialize umh client tracking in a container ignored.\n");
1880 ret
= nfsd4_umh_cltrack_upcall("init", NULL
, grace_start
, NULL
);
1883 printk("NFSD: Using UMH upcall client tracking operations.\n");
1888 nfsd4_cltrack_upcall_lock(struct nfs4_client
*clp
)
1890 wait_on_bit_lock(&clp
->cl_flags
, NFSD4_CLIENT_UPCALL_LOCK
,
1891 TASK_UNINTERRUPTIBLE
);
1895 nfsd4_cltrack_upcall_unlock(struct nfs4_client
*clp
)
1897 smp_mb__before_atomic();
1898 clear_bit(NFSD4_CLIENT_UPCALL_LOCK
, &clp
->cl_flags
);
1899 smp_mb__after_atomic();
1900 wake_up_bit(&clp
->cl_flags
, NFSD4_CLIENT_UPCALL_LOCK
);
1904 nfsd4_umh_cltrack_create(struct nfs4_client
*clp
)
1906 char *hexid
, *has_session
, *grace_start
;
1907 struct nfsd_net
*nn
= net_generic(clp
->net
, nfsd_net_id
);
1910 * With v4.0 clients, there's little difference in outcome between a
1911 * create and check operation, and we can end up calling into this
1912 * function multiple times per client (once for each openowner). So,
1913 * for v4.0 clients skip upcalling once the client has been recorded
1914 * on stable storage.
1916 * For v4.1+ clients, the outcome of the two operations is different,
1917 * so we must ensure that we upcall for the create operation. v4.1+
1918 * clients call this on RECLAIM_COMPLETE though, so we should only end
1919 * up doing a single create upcall per client.
1921 if (clp
->cl_minorversion
== 0 &&
1922 test_bit(NFSD4_CLIENT_STABLE
, &clp
->cl_flags
))
1925 hexid
= bin_to_hex_dup(clp
->cl_name
.data
, clp
->cl_name
.len
);
1927 dprintk("%s: can't allocate memory for upcall!\n", __func__
);
1931 has_session
= nfsd4_cltrack_client_has_session(clp
);
1932 grace_start
= nfsd4_cltrack_grace_start(nn
->boot_time
);
1934 nfsd4_cltrack_upcall_lock(clp
);
1935 if (!nfsd4_umh_cltrack_upcall("create", hexid
, has_session
, grace_start
))
1936 set_bit(NFSD4_CLIENT_STABLE
, &clp
->cl_flags
);
1937 nfsd4_cltrack_upcall_unlock(clp
);
1945 nfsd4_umh_cltrack_remove(struct nfs4_client
*clp
)
1949 if (!test_bit(NFSD4_CLIENT_STABLE
, &clp
->cl_flags
))
1952 hexid
= bin_to_hex_dup(clp
->cl_name
.data
, clp
->cl_name
.len
);
1954 dprintk("%s: can't allocate memory for upcall!\n", __func__
);
1958 nfsd4_cltrack_upcall_lock(clp
);
1959 if (test_bit(NFSD4_CLIENT_STABLE
, &clp
->cl_flags
) &&
1960 nfsd4_umh_cltrack_upcall("remove", hexid
, NULL
, NULL
) == 0)
1961 clear_bit(NFSD4_CLIENT_STABLE
, &clp
->cl_flags
);
1962 nfsd4_cltrack_upcall_unlock(clp
);
1968 nfsd4_umh_cltrack_check(struct nfs4_client
*clp
)
1971 char *hexid
, *has_session
, *legacy
;
1973 if (test_bit(NFSD4_CLIENT_STABLE
, &clp
->cl_flags
))
1976 hexid
= bin_to_hex_dup(clp
->cl_name
.data
, clp
->cl_name
.len
);
1978 dprintk("%s: can't allocate memory for upcall!\n", __func__
);
1982 has_session
= nfsd4_cltrack_client_has_session(clp
);
1983 legacy
= nfsd4_cltrack_legacy_recdir(&clp
->cl_name
);
1985 nfsd4_cltrack_upcall_lock(clp
);
1986 if (test_bit(NFSD4_CLIENT_STABLE
, &clp
->cl_flags
)) {
1989 ret
= nfsd4_umh_cltrack_upcall("check", hexid
, has_session
, legacy
);
1991 set_bit(NFSD4_CLIENT_STABLE
, &clp
->cl_flags
);
1993 nfsd4_cltrack_upcall_unlock(clp
);
2002 nfsd4_umh_cltrack_grace_done(struct nfsd_net
*nn
)
2005 char timestr
[22]; /* FIXME: better way to determine max size? */
2007 sprintf(timestr
, "%ld", nn
->boot_time
);
2008 legacy
= nfsd4_cltrack_legacy_topdir();
2009 nfsd4_umh_cltrack_upcall("gracedone", timestr
, legacy
, NULL
);
2013 static const struct nfsd4_client_tracking_ops nfsd4_umh_tracking_ops
= {
2014 .init
= nfsd4_umh_cltrack_init
,
2016 .create
= nfsd4_umh_cltrack_create
,
2017 .remove
= nfsd4_umh_cltrack_remove
,
2018 .check
= nfsd4_umh_cltrack_check
,
2019 .grace_done
= nfsd4_umh_cltrack_grace_done
,
2025 nfsd4_client_tracking_init(struct net
*net
)
2029 struct nfsd_net
*nn
= net_generic(net
, nfsd_net_id
);
2031 /* just run the init if it the method is already decided */
2032 if (nn
->client_tracking_ops
)
2035 /* First, try to use nfsdcld */
2036 nn
->client_tracking_ops
= &nfsd4_cld_tracking_ops
;
2037 status
= nn
->client_tracking_ops
->init(net
);
2040 if (status
!= -ETIMEDOUT
) {
2041 nn
->client_tracking_ops
= &nfsd4_cld_tracking_ops_v0
;
2042 status
= nn
->client_tracking_ops
->init(net
);
2048 * Next, try the UMH upcall.
2050 nn
->client_tracking_ops
= &nfsd4_umh_tracking_ops
;
2051 status
= nn
->client_tracking_ops
->init(net
);
2056 * Finally, See if the recoverydir exists and is a directory.
2057 * If it is, then use the legacy ops.
2059 nn
->client_tracking_ops
= &nfsd4_legacy_tracking_ops
;
2060 status
= kern_path(nfs4_recoverydir(), LOOKUP_FOLLOW
, &path
);
2062 status
= d_is_dir(path
.dentry
);
2071 status
= nn
->client_tracking_ops
->init(net
);
2074 printk(KERN_WARNING
"NFSD: Unable to initialize client "
2075 "recovery tracking! (%d)\n", status
);
2076 nn
->client_tracking_ops
= NULL
;
2082 nfsd4_client_tracking_exit(struct net
*net
)
2084 struct nfsd_net
*nn
= net_generic(net
, nfsd_net_id
);
2086 if (nn
->client_tracking_ops
) {
2087 if (nn
->client_tracking_ops
->exit
)
2088 nn
->client_tracking_ops
->exit(net
);
2089 nn
->client_tracking_ops
= NULL
;
2094 nfsd4_client_record_create(struct nfs4_client
*clp
)
2096 struct nfsd_net
*nn
= net_generic(clp
->net
, nfsd_net_id
);
2098 if (nn
->client_tracking_ops
)
2099 nn
->client_tracking_ops
->create(clp
);
2103 nfsd4_client_record_remove(struct nfs4_client
*clp
)
2105 struct nfsd_net
*nn
= net_generic(clp
->net
, nfsd_net_id
);
2107 if (nn
->client_tracking_ops
)
2108 nn
->client_tracking_ops
->remove(clp
);
2112 nfsd4_client_record_check(struct nfs4_client
*clp
)
2114 struct nfsd_net
*nn
= net_generic(clp
->net
, nfsd_net_id
);
2116 if (nn
->client_tracking_ops
)
2117 return nn
->client_tracking_ops
->check(clp
);
2123 nfsd4_record_grace_done(struct nfsd_net
*nn
)
2125 if (nn
->client_tracking_ops
)
2126 nn
->client_tracking_ops
->grace_done(nn
);
2130 rpc_pipefs_event(struct notifier_block
*nb
, unsigned long event
, void *ptr
)
2132 struct super_block
*sb
= ptr
;
2133 struct net
*net
= sb
->s_fs_info
;
2134 struct nfsd_net
*nn
= net_generic(net
, nfsd_net_id
);
2135 struct cld_net
*cn
= nn
->cld_net
;
2136 struct dentry
*dentry
;
2139 if (!try_module_get(THIS_MODULE
))
2143 module_put(THIS_MODULE
);
2148 case RPC_PIPEFS_MOUNT
:
2149 dentry
= nfsd4_cld_register_sb(sb
, cn
->cn_pipe
);
2150 if (IS_ERR(dentry
)) {
2151 ret
= PTR_ERR(dentry
);
2154 cn
->cn_pipe
->dentry
= dentry
;
2156 case RPC_PIPEFS_UMOUNT
:
2157 if (cn
->cn_pipe
->dentry
)
2158 nfsd4_cld_unregister_sb(cn
->cn_pipe
);
2164 module_put(THIS_MODULE
);
2168 static struct notifier_block nfsd4_cld_block
= {
2169 .notifier_call
= rpc_pipefs_event
,
2173 register_cld_notifier(void)
2175 return rpc_pipefs_notifier_register(&nfsd4_cld_block
);
2179 unregister_cld_notifier(void)
2181 rpc_pipefs_notifier_unregister(&nfsd4_cld_block
);