...as advertised for 3.10. Cc: Stanislav Kinsbursky <skinsbursky@xxxxxxxxxxxxx> Signed-off-by: Jeff Layton <jlayton@xxxxxxxxxx> --- fs/nfsd/nfs4recover.c | 492 +---------------------------------------- fs/nfsd/nfsctl.c | 8 +- fs/nfsd/nfsd.h | 5 - include/uapi/linux/nfsd/Kbuild | 1 - include/uapi/linux/nfsd/cld.h | 56 ----- 5 files changed, 6 insertions(+), 556 deletions(-) delete mode 100644 include/uapi/linux/nfsd/cld.h diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c index 899ca26..4e7f47e 100644 --- a/fs/nfsd/nfs4recover.c +++ b/fs/nfsd/nfs4recover.c @@ -42,7 +42,6 @@ #include <net/net_namespace.h> #include <linux/sunrpc/rpc_pipe_fs.h> #include <linux/sunrpc/clnt.h> -#include <linux/nfsd/cld.h> #include "nfsd.h" #include "state.h" @@ -625,426 +624,6 @@ static struct nfsd4_client_tracking_ops nfsd4_legacy_tracking_ops = { .grace_done = nfsd4_recdir_purge_old, }; -/* Globals */ -#define NFSD_PIPE_DIR "nfsd" -#define NFSD_CLD_PIPE "cld" - -/* per-net-ns structure for holding cld upcall info */ -struct cld_net { - struct rpc_pipe *cn_pipe; - spinlock_t cn_lock; - struct list_head cn_list; - unsigned int cn_xid; -}; - -struct cld_upcall { - struct list_head cu_list; - struct cld_net *cu_net; - struct task_struct *cu_task; - struct cld_msg cu_msg; -}; - -static int -__cld_pipe_upcall(struct rpc_pipe *pipe, struct cld_msg *cmsg) -{ - int ret; - struct rpc_pipe_msg msg; - - memset(&msg, 0, sizeof(msg)); - msg.data = cmsg; - msg.len = sizeof(*cmsg); - - /* - * Set task state before we queue the upcall. That prevents - * wake_up_process in the downcall from racing with schedule. - */ - set_current_state(TASK_UNINTERRUPTIBLE); - ret = rpc_queue_upcall(pipe, &msg); - if (ret < 0) { - set_current_state(TASK_RUNNING); - goto out; - } - - schedule(); - set_current_state(TASK_RUNNING); - - if (msg.errno < 0) - ret = msg.errno; -out: - return ret; -} - -static int -cld_pipe_upcall(struct rpc_pipe *pipe, struct cld_msg *cmsg) -{ - int ret; - - /* - * -EAGAIN occurs when pipe is closed and reopened while there are - * upcalls queued. - */ - do { - ret = __cld_pipe_upcall(pipe, cmsg); - } while (ret == -EAGAIN); - - return ret; -} - -static ssize_t -cld_pipe_downcall(struct file *filp, const char __user *src, size_t mlen) -{ - struct cld_upcall *tmp, *cup; - struct cld_msg __user *cmsg = (struct cld_msg __user *)src; - uint32_t xid; - struct nfsd_net *nn = net_generic(filp->f_dentry->d_sb->s_fs_info, - nfsd_net_id); - struct cld_net *cn = nn->cld_net; - - if (mlen != sizeof(*cmsg)) { - dprintk("%s: got %zu bytes, expected %zu\n", __func__, mlen, - sizeof(*cmsg)); - return -EINVAL; - } - - /* copy just the xid so we can try to find that */ - if (copy_from_user(&xid, &cmsg->cm_xid, sizeof(xid)) != 0) { - dprintk("%s: error when copying xid from userspace", __func__); - return -EFAULT; - } - - /* walk the list and find corresponding xid */ - cup = NULL; - spin_lock(&cn->cn_lock); - list_for_each_entry(tmp, &cn->cn_list, cu_list) { - if (get_unaligned(&tmp->cu_msg.cm_xid) == xid) { - cup = tmp; - list_del_init(&cup->cu_list); - break; - } - } - spin_unlock(&cn->cn_lock); - - /* couldn't find upcall? */ - if (!cup) { - dprintk("%s: couldn't find upcall -- xid=%u\n", __func__, xid); - return -EINVAL; - } - - if (copy_from_user(&cup->cu_msg, src, mlen) != 0) - return -EFAULT; - - wake_up_process(cup->cu_task); - return mlen; -} - -static void -cld_pipe_destroy_msg(struct rpc_pipe_msg *msg) -{ - struct cld_msg *cmsg = msg->data; - struct cld_upcall *cup = container_of(cmsg, struct cld_upcall, - cu_msg); - - /* errno >= 0 means we got a downcall */ - if (msg->errno >= 0) - return; - - wake_up_process(cup->cu_task); -} - -static const struct rpc_pipe_ops cld_upcall_ops = { - .upcall = rpc_pipe_generic_upcall, - .downcall = cld_pipe_downcall, - .destroy_msg = cld_pipe_destroy_msg, -}; - -static struct dentry * -nfsd4_cld_register_sb(struct super_block *sb, struct rpc_pipe *pipe) -{ - struct dentry *dir, *dentry; - - dir = rpc_d_lookup_sb(sb, NFSD_PIPE_DIR); - if (dir == NULL) - return ERR_PTR(-ENOENT); - dentry = rpc_mkpipe_dentry(dir, NFSD_CLD_PIPE, NULL, pipe); - dput(dir); - return dentry; -} - -static void -nfsd4_cld_unregister_sb(struct rpc_pipe *pipe) -{ - if (pipe->dentry) - rpc_unlink(pipe->dentry); -} - -static struct dentry * -nfsd4_cld_register_net(struct net *net, struct rpc_pipe *pipe) -{ - struct super_block *sb; - struct dentry *dentry; - - sb = rpc_get_sb_net(net); - if (!sb) - return NULL; - dentry = nfsd4_cld_register_sb(sb, pipe); - rpc_put_sb_net(net); - return dentry; -} - -static void -nfsd4_cld_unregister_net(struct net *net, struct rpc_pipe *pipe) -{ - struct super_block *sb; - - sb = rpc_get_sb_net(net); - if (sb) { - nfsd4_cld_unregister_sb(pipe); - rpc_put_sb_net(net); - } -} - -/* Initialize rpc_pipefs pipe for communication with client tracking daemon */ -static int -nfsd4_init_cld_pipe(struct net *net) -{ - int ret; - struct dentry *dentry; - struct nfsd_net *nn = net_generic(net, nfsd_net_id); - struct cld_net *cn; - - if (nn->cld_net) - return 0; - - cn = kzalloc(sizeof(*cn), GFP_KERNEL); - if (!cn) { - ret = -ENOMEM; - goto err; - } - - cn->cn_pipe = rpc_mkpipe_data(&cld_upcall_ops, RPC_PIPE_WAIT_FOR_OPEN); - if (IS_ERR(cn->cn_pipe)) { - ret = PTR_ERR(cn->cn_pipe); - goto err; - } - spin_lock_init(&cn->cn_lock); - INIT_LIST_HEAD(&cn->cn_list); - - dentry = nfsd4_cld_register_net(net, cn->cn_pipe); - if (IS_ERR(dentry)) { - ret = PTR_ERR(dentry); - goto err_destroy_data; - } - - cn->cn_pipe->dentry = dentry; - nn->cld_net = cn; - return 0; - -err_destroy_data: - rpc_destroy_pipe_data(cn->cn_pipe); -err: - kfree(cn); - printk(KERN_ERR "NFSD: unable to create nfsdcld upcall pipe (%d)\n", - ret); - return ret; -} - -static void -nfsd4_remove_cld_pipe(struct net *net) -{ - struct nfsd_net *nn = net_generic(net, nfsd_net_id); - struct cld_net *cn = nn->cld_net; - - nfsd4_cld_unregister_net(net, cn->cn_pipe); - rpc_destroy_pipe_data(cn->cn_pipe); - kfree(nn->cld_net); - nn->cld_net = NULL; -} - -static struct cld_upcall * -alloc_cld_upcall(struct cld_net *cn) -{ - struct cld_upcall *new, *tmp; - - new = kzalloc(sizeof(*new), GFP_KERNEL); - if (!new) - return new; - - /* FIXME: hard cap on number in flight? */ -restart_search: - spin_lock(&cn->cn_lock); - list_for_each_entry(tmp, &cn->cn_list, cu_list) { - if (tmp->cu_msg.cm_xid == cn->cn_xid) { - cn->cn_xid++; - spin_unlock(&cn->cn_lock); - goto restart_search; - } - } - new->cu_task = current; - new->cu_msg.cm_vers = CLD_UPCALL_VERSION; - put_unaligned(cn->cn_xid++, &new->cu_msg.cm_xid); - new->cu_net = cn; - list_add(&new->cu_list, &cn->cn_list); - spin_unlock(&cn->cn_lock); - - dprintk("%s: allocated xid %u\n", __func__, new->cu_msg.cm_xid); - - return new; -} - -static void -free_cld_upcall(struct cld_upcall *victim) -{ - struct cld_net *cn = victim->cu_net; - - spin_lock(&cn->cn_lock); - list_del(&victim->cu_list); - spin_unlock(&cn->cn_lock); - kfree(victim); -} - -/* Ask daemon to create a new record */ -static void -nfsd4_cld_create(struct nfs4_client *clp) -{ - int ret; - struct cld_upcall *cup; - struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); - struct cld_net *cn = nn->cld_net; - - /* Don't upcall if it's already stored */ - if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) - return; - - cup = alloc_cld_upcall(cn); - if (!cup) { - ret = -ENOMEM; - goto out_err; - } - - cup->cu_msg.cm_cmd = Cld_Create; - cup->cu_msg.cm_u.cm_name.cn_len = clp->cl_name.len; - memcpy(cup->cu_msg.cm_u.cm_name.cn_id, clp->cl_name.data, - clp->cl_name.len); - - ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_msg); - if (!ret) { - ret = cup->cu_msg.cm_status; - set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); - } - - free_cld_upcall(cup); -out_err: - if (ret) - printk(KERN_ERR "NFSD: Unable to create client " - "record on stable storage: %d\n", ret); -} - -/* Ask daemon to create a new record */ -static void -nfsd4_cld_remove(struct nfs4_client *clp) -{ - int ret; - struct cld_upcall *cup; - struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); - struct cld_net *cn = nn->cld_net; - - /* Don't upcall if it's already removed */ - if (!test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) - return; - - cup = alloc_cld_upcall(cn); - if (!cup) { - ret = -ENOMEM; - goto out_err; - } - - cup->cu_msg.cm_cmd = Cld_Remove; - cup->cu_msg.cm_u.cm_name.cn_len = clp->cl_name.len; - memcpy(cup->cu_msg.cm_u.cm_name.cn_id, clp->cl_name.data, - clp->cl_name.len); - - ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_msg); - if (!ret) { - ret = cup->cu_msg.cm_status; - clear_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); - } - - free_cld_upcall(cup); -out_err: - if (ret) - printk(KERN_ERR "NFSD: Unable to remove client " - "record from stable storage: %d\n", ret); -} - -/* Check for presence of a record, and update its timestamp */ -static int -nfsd4_cld_check(struct nfs4_client *clp) -{ - int ret; - struct cld_upcall *cup; - struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); - struct cld_net *cn = nn->cld_net; - - /* Don't upcall if one was already stored during this grace pd */ - if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) - return 0; - - cup = alloc_cld_upcall(cn); - if (!cup) { - printk(KERN_ERR "NFSD: Unable to check client record on " - "stable storage: %d\n", -ENOMEM); - return -ENOMEM; - } - - cup->cu_msg.cm_cmd = Cld_Check; - cup->cu_msg.cm_u.cm_name.cn_len = clp->cl_name.len; - memcpy(cup->cu_msg.cm_u.cm_name.cn_id, clp->cl_name.data, - clp->cl_name.len); - - ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_msg); - if (!ret) { - ret = cup->cu_msg.cm_status; - set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); - } - - free_cld_upcall(cup); - return ret; -} - -static void -nfsd4_cld_grace_done(struct nfsd_net *nn, time_t boot_time) -{ - int ret; - struct cld_upcall *cup; - struct cld_net *cn = nn->cld_net; - - cup = alloc_cld_upcall(cn); - if (!cup) { - ret = -ENOMEM; - goto out_err; - } - - cup->cu_msg.cm_cmd = Cld_GraceDone; - cup->cu_msg.cm_u.cm_gracetime = (int64_t)boot_time; - ret = cld_pipe_upcall(cn->cn_pipe, &cup->cu_msg); - if (!ret) - ret = cup->cu_msg.cm_status; - - free_cld_upcall(cup); -out_err: - if (ret) - printk(KERN_ERR "NFSD: Unable to end grace period: %d\n", ret); -} - -static struct nfsd4_client_tracking_ops nfsd4_cld_tracking_ops = { - .init = nfsd4_init_cld_pipe, - .exit = nfsd4_remove_cld_pipe, - .create = nfsd4_cld_create, - .remove = nfsd4_cld_remove, - .check = nfsd4_cld_check, - .grace_done = nfsd4_cld_grace_done, -}; - /* upcall via usermodehelper */ static char cltrack_prog[PATH_MAX] = "/sbin/nfsdcltrack"; module_param_string(cltrack_prog, cltrack_prog, sizeof(cltrack_prog), @@ -1287,21 +866,14 @@ nfsd4_client_tracking_init(struct net *net) * then use the legacy ops. */ nn->client_tracking_ops = &nfsd4_legacy_tracking_ops; - status = kern_path(nfs4_recoverydir(), LOOKUP_FOLLOW, &path); - if (!status) { - status = S_ISDIR(path.dentry->d_inode->i_mode); - path_put(&path); - if (status) - goto do_init; - } + status = kern_path(nfs4_recoverydir(), + LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &path); + if (status) + goto out_err; - /* Finally, try to use nfsdcld */ - nn->client_tracking_ops = &nfsd4_cld_tracking_ops; - printk(KERN_WARNING "NFSD: the nfsdcld client tracking upcall will be " - "removed in 3.10. Please transition to using " - "nfsdcltrack.\n"); do_init: status = nn->client_tracking_ops->init(net); +out_err: if (status) { printk(KERN_WARNING "NFSD: Unable to initialize client " "recovery tracking! (%d)\n", status); @@ -1358,57 +930,3 @@ nfsd4_record_grace_done(struct nfsd_net *nn, time_t boot_time) nn->client_tracking_ops->grace_done(nn, boot_time); } -static int -rpc_pipefs_event(struct notifier_block *nb, unsigned long event, void *ptr) -{ - struct super_block *sb = ptr; - struct net *net = sb->s_fs_info; - struct nfsd_net *nn = net_generic(net, nfsd_net_id); - struct cld_net *cn = nn->cld_net; - struct dentry *dentry; - int ret = 0; - - if (!try_module_get(THIS_MODULE)) - return 0; - - if (!cn) { - module_put(THIS_MODULE); - return 0; - } - - switch (event) { - case RPC_PIPEFS_MOUNT: - dentry = nfsd4_cld_register_sb(sb, cn->cn_pipe); - if (IS_ERR(dentry)) { - ret = PTR_ERR(dentry); - break; - } - cn->cn_pipe->dentry = dentry; - break; - case RPC_PIPEFS_UMOUNT: - if (cn->cn_pipe->dentry) - nfsd4_cld_unregister_sb(cn->cn_pipe); - break; - default: - ret = -ENOTSUPP; - break; - } - module_put(THIS_MODULE); - return ret; -} - -static struct notifier_block nfsd4_cld_block = { - .notifier_call = rpc_pipefs_event, -}; - -int -register_cld_notifier(void) -{ - return rpc_pipefs_notifier_register(&nfsd4_cld_block); -} - -void -unregister_cld_notifier(void) -{ - rpc_pipefs_notifier_unregister(&nfsd4_cld_block); -} diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index a830f33..f0aeb93 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -1163,12 +1163,9 @@ static int __init init_nfsd(void) int retval; printk(KERN_INFO "Installing knfsd (copyright (C) 1996 okir@xxxxxxxxxxxx).\n"); - retval = register_cld_notifier(); - if (retval) - return retval; retval = register_pernet_subsys(&nfsd_net_ops); if (retval < 0) - goto out_unregister_notifier; + return retval; retval = nfsd4_init_slabs(); if (retval) goto out_unregister_pernet; @@ -1201,8 +1198,6 @@ out_free_slabs: nfsd4_free_slabs(); out_unregister_pernet: unregister_pernet_subsys(&nfsd_net_ops); -out_unregister_notifier: - unregister_cld_notifier(); return retval; } @@ -1217,7 +1212,6 @@ static void __exit exit_nfsd(void) nfsd_fault_inject_cleanup(); unregister_filesystem(&nfsd_fs_type); unregister_pernet_subsys(&nfsd_net_ops); - unregister_cld_notifier(); } MODULE_AUTHOR("Olaf Kirch <okir@xxxxxxxxxxxx>"); diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h index 07a473f..8eb2aac 100644 --- a/fs/nfsd/nfsd.h +++ b/fs/nfsd/nfsd.h @@ -365,17 +365,12 @@ static inline u32 nfsd_suppattrs2(u32 minorversion) NFSD_WRITEABLE_ATTRS_WORD2 extern int nfsd4_is_junction(struct dentry *dentry); -extern int register_cld_notifier(void); -extern void unregister_cld_notifier(void); #else /* CONFIG_NFSD_V4 */ static inline int nfsd4_is_junction(struct dentry *dentry) { return 0; } -#define register_cld_notifier() 0 -#define unregister_cld_notifier() do { } while(0) - #endif /* CONFIG_NFSD_V4 */ #endif /* LINUX_NFSD_NFSD_H */ diff --git a/include/uapi/linux/nfsd/Kbuild b/include/uapi/linux/nfsd/Kbuild index c11bc40..88589ac 100644 --- a/include/uapi/linux/nfsd/Kbuild +++ b/include/uapi/linux/nfsd/Kbuild @@ -1,5 +1,4 @@ # UAPI Header export list -header-y += cld.h header-y += debug.h header-y += export.h header-y += nfsfh.h diff --git a/include/uapi/linux/nfsd/cld.h b/include/uapi/linux/nfsd/cld.h deleted file mode 100644 index f14a9ab..0000000 --- a/include/uapi/linux/nfsd/cld.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Upcall description for nfsdcld communication - * - * Copyright (c) 2012 Red Hat, Inc. - * Author(s): Jeff Layton <jlayton@xxxxxxxxxx> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef _NFSD_CLD_H -#define _NFSD_CLD_H - -/* latest upcall version available */ -#define CLD_UPCALL_VERSION 1 - -/* defined by RFC3530 */ -#define NFS4_OPAQUE_LIMIT 1024 - -enum cld_command { - Cld_Create, /* create a record for this cm_id */ - Cld_Remove, /* remove record of this cm_id */ - Cld_Check, /* is this cm_id allowed? */ - Cld_GraceDone, /* grace period is complete */ -}; - -/* representation of long-form NFSv4 client ID */ -struct cld_name { - uint16_t cn_len; /* length of cm_id */ - unsigned char cn_id[NFS4_OPAQUE_LIMIT]; /* client-provided */ -} __attribute__((packed)); - -/* message struct for communication with userspace */ -struct cld_msg { - uint8_t cm_vers; /* upcall version */ - uint8_t cm_cmd; /* upcall command */ - int16_t cm_status; /* return code */ - uint32_t cm_xid; /* transaction id */ - union { - int64_t cm_gracetime; /* grace period start time */ - struct cld_name cm_name; - } __attribute__((packed)) cm_u; -} __attribute__((packed)); - -#endif /* !_NFSD_CLD_H */ -- 1.7.11.7 -- To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html