36 #include <linux/slab.h>
39 #include <linux/sched.h>
41 #include <linux/module.h>
52 #define NFSDDBG_FACILITY NFSDDBG_PROC
65 static struct file *rec_file;
66 static char user_recovery_dirname[
PATH_MAX] =
"/var/lib/nfs/v4recovery";
70 nfs4_save_creds(
const struct cred **original_creds)
86 nfs4_reset_creds(
const struct cred *original)
92 md5_to_hex(
char *
out,
char *md5)
96 for (i=0; i<16; i++) {
97 unsigned char c = md5[
i];
99 *out++ =
'0' + ((c&0xf0)>>4) + (c>=0xa0)*(
'a'-
'9'-1);
100 *out++ =
'0' + (c&0x0f) + ((c&0x0f)>=0x0a)*(
'a'-
'9'-1);
108 struct xdr_netobj cksum;
113 dprintk(
"NFSD: nfs4_make_rec_clidname for %.*s\n",
114 clname->len, clname->data);
117 if (IS_ERR(desc.
tfm))
119 cksum.len = crypto_hash_digestsize(desc.
tfm);
121 if (cksum.data ==
NULL)
126 if (crypto_hash_digest(&desc, &sg, sg.
length, cksum.data))
129 md5_to_hex(dname, cksum.data);
134 crypto_free_hash(desc.
tfm);
142 const struct cred *original_cred;
147 dprintk(
"NFSD: nfsd4_create_clid_dir for \"%s\"\n", dname);
153 status = nfs4_save_creds(&original_cred);
161 dir = rec_file->
f_path.dentry;
166 if (IS_ERR(dentry)) {
167 status = PTR_ERR(dentry);
189 " (err %d); please check that %s exists"
190 " and is writeable", status,
191 user_recovery_dirname);
193 nfs4_reset_creds(original_cred);
204 nfsd4_build_namelist(
void *
arg,
const char *
name,
int namlen,
217 list_add(&entry->
list, names);
224 const struct cred *original_cred;
225 struct dentry *dir = rec_file->
f_path.dentry;
229 status = nfs4_save_creds(&original_cred);
235 nfs4_reset_creds(original_cred);
239 status =
vfs_readdir(rec_file, nfsd4_build_namelist, &names);
241 while (!list_empty(&names)) {
245 struct dentry *dentry;
247 if (IS_ERR(dentry)) {
248 status = PTR_ERR(dentry);
251 status =
f(dir, dentry);
258 nfs4_reset_creds(original_cred);
263 nfsd4_unlink_clid_dir(
char *name,
int namlen)
265 struct dentry *dir, *dentry;
268 dprintk(
"NFSD: nfsd4_unlink_clid_dir. name %.*s\n", namlen, name);
270 dir = rec_file->
f_path.dentry;
273 if (IS_ERR(dentry)) {
274 status = PTR_ERR(dentry);
291 const struct cred *original_cred;
302 status = nfs4_save_creds(&original_cred);
307 nfs4_reset_creds(original_cred);
313 printk(
"NFSD: Failed to remove expired client state directory"
318 purge_old(
struct dentry *parent,
struct dentry *
child)
327 printk(
"failed to remove client recovery directory %s\n",
334 nfsd4_recdir_purge_old(
struct net *
net,
time_t boot_time)
343 status = nfsd4_list_rec_dir(purge_old);
349 printk(
"nfsd4: failed to purge old clients from recovery"
350 " directory %s\n", rec_file->
f_path.dentry->d_name.name);
354 load_recdir(
struct dentry *parent,
struct dentry *child)
357 printk(
"nfsd4: illegal name %s in recovery directory\n",
367 nfsd4_recdir_load(
void) {
373 status = nfsd4_list_rec_dir(load_recdir);
375 printk(
"nfsd4: failed loading clients from recovery"
376 " directory %s\n", rec_file->
f_path.dentry->d_name.name);
385 nfsd4_init_recdir(
void)
387 const struct cred *original_cred;
390 printk(
"NFSD: Using %s as the NFSv4 state recovery directory\n",
391 user_recovery_dirname);
395 status = nfs4_save_creds(&original_cred);
397 printk(
"NFSD: Unable to change credentials to find recovery"
398 " directory: error %d\n",
404 if (IS_ERR(rec_file)) {
405 printk(
"NFSD: unable to find recovery directory %s\n",
406 user_recovery_dirname);
407 status = PTR_ERR(rec_file);
411 nfs4_reset_creds(original_cred);
416 nfsd4_load_reboot_recovery_data(
struct net *net)
422 WARN(1,
KERN_ERR "NFSD: attempt to initialize legacy client "
423 "tracking in a container!\n");
428 status = nfsd4_init_recdir();
430 status = nfsd4_recdir_load();
438 nfsd4_shutdown_recdir(
void)
447 nfsd4_legacy_tracking_exit(
struct net *net)
450 nfsd4_shutdown_recdir();
467 strcpy(user_recovery_dirname, recdir);
477 return user_recovery_dirname;
497 .init = nfsd4_load_reboot_recovery_data,
498 .exit = nfsd4_legacy_tracking_exit,
499 .create = nfsd4_create_clid_dir,
500 .remove = nfsd4_remove_clid_dir,
501 .check = nfsd4_check_legacy_client,
502 .grace_done = nfsd4_recdir_purge_old,
506 #define NFSD_PIPE_DIR "nfsd"
507 #define NFSD_CLD_PIPE "cld"
525 __cld_pipe_upcall(
struct rpc_pipe *
pipe,
struct cld_msg *cmsg)
528 struct rpc_pipe_msg
msg;
532 msg.len =
sizeof(*cmsg);
555 cld_pipe_upcall(
struct rpc_pipe *pipe,
struct cld_msg *cmsg)
564 ret = __cld_pipe_upcall(pipe, cmsg);
571 cld_pipe_downcall(
struct file *filp,
const char __user *
src,
size_t mlen)
580 if (mlen !=
sizeof(*cmsg)) {
581 dprintk(
"%s: got %zu bytes, expected %zu\n", __func__, mlen,
588 dprintk(
"%s: error when copying xid from userspace", __func__);
606 dprintk(
"%s: couldn't find upcall -- xid=%u\n", __func__, xid);
618 cld_pipe_destroy_msg(
struct rpc_pipe_msg *
msg)
620 struct cld_msg *cmsg = msg->data;
631 static const struct rpc_pipe_ops cld_upcall_ops = {
633 .downcall = cld_pipe_downcall,
634 .destroy_msg = cld_pipe_destroy_msg,
637 static struct dentry *
638 nfsd4_cld_register_sb(
struct super_block *
sb,
struct rpc_pipe *pipe)
640 struct dentry *dir, *dentry;
651 nfsd4_cld_unregister_sb(
struct rpc_pipe *pipe)
657 static struct dentry *
658 nfsd4_cld_register_net(
struct net *net,
struct rpc_pipe *pipe)
661 struct dentry *dentry;
666 dentry = nfsd4_cld_register_sb(sb, pipe);
672 nfsd4_cld_unregister_net(
struct net *net,
struct rpc_pipe *pipe)
678 nfsd4_cld_unregister_sb(pipe);
685 nfsd4_init_cld_pipe(
struct net *net)
688 struct dentry *dentry;
709 dentry = nfsd4_cld_register_net(net, cn->
cn_pipe);
710 if (IS_ERR(dentry)) {
711 ret = PTR_ERR(dentry);
712 goto err_destroy_data;
723 printk(
KERN_ERR "NFSD: unable to create nfsdcld upcall pipe (%d)\n",
729 nfsd4_remove_cld_pipe(
struct net *net)
734 nfsd4_cld_unregister_net(net, cn->
cn_pipe);
741 alloc_cld_upcall(
struct cld_net *cn)
763 list_add(&new->cu_list, &cn->
cn_list);
766 dprintk(
"%s: allocated xid %u\n", __func__, new->cu_msg.cm_xid);
796 cup = alloc_cld_upcall(cn);
809 ret = cup->
cu_msg.cm_status;
813 free_cld_upcall(cup);
817 "record on stable storage: %d\n", ret);
834 cup = alloc_cld_upcall(cn);
847 ret = cup->
cu_msg.cm_status;
851 free_cld_upcall(cup);
855 "record from stable storage: %d\n", ret);
872 cup = alloc_cld_upcall(cn);
875 "stable storage: %d\n", -
ENOMEM);
886 ret = cup->
cu_msg.cm_status;
890 free_cld_upcall(cup);
895 nfsd4_cld_grace_done(
struct net *net,
time_t boot_time)
902 cup = alloc_cld_upcall(cn);
909 cup->
cu_msg.cm_u.cm_gracetime = (int64_t)boot_time;
912 ret = cup->
cu_msg.cm_status;
914 free_cld_upcall(cup);
921 .init = nfsd4_init_cld_pipe,
922 .exit = nfsd4_remove_cld_pipe,
923 .create = nfsd4_cld_create,
924 .remove = nfsd4_cld_remove,
925 .check = nfsd4_cld_check,
926 .grace_done = nfsd4_cld_grace_done,
935 if (!client_tracking_ops) {
936 client_tracking_ops = &nfsd4_cld_tracking_ops;
940 client_tracking_ops =
941 &nfsd4_legacy_tracking_ops;
946 status = client_tracking_ops->
init(net);
949 "recovery tracking! (%d)\n", status);
950 client_tracking_ops =
NULL;
958 if (client_tracking_ops) {
959 client_tracking_ops->
exit(net);
960 client_tracking_ops =
NULL;
967 if (client_tracking_ops)
968 client_tracking_ops->
create(clp);
974 if (client_tracking_ops)
975 client_tracking_ops->
remove(clp);
981 if (client_tracking_ops)
982 return client_tracking_ops->
check(clp);
990 if (client_tracking_ops)
991 client_tracking_ops->
grace_done(net, boot_time);
1001 struct dentry *dentry;
1013 case RPC_PIPEFS_MOUNT:
1014 dentry = nfsd4_cld_register_sb(sb, cn->
cn_pipe);
1015 if (IS_ERR(dentry)) {
1016 ret = PTR_ERR(dentry);
1021 case RPC_PIPEFS_UMOUNT:
1023 nfsd4_cld_unregister_sb(cn->
cn_pipe);
1034 .notifier_call = rpc_pipefs_event,