mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-11-18 23:54:26 +08:00
Merge branch 'nfsd-next' of git://linux-nfs.org/~bfields/linux
Pull nfsd changes from J. Bruce Fields: "This has been an unusually quiet cycle--mostly bugfixes and cleanup. The one large piece is Stanislav's work to containerize the server's grace period--but that in itself is just one more step in a not-yet-complete project to allow fully containerized nfs service. There are a number of outstanding delegation, container, v4 state, and gss patches that aren't quite ready yet; 3.7 may be wilder." * 'nfsd-next' of git://linux-nfs.org/~bfields/linux: (35 commits) NFSd: make boot_time variable per network namespace NFSd: make grace end flag per network namespace Lockd: move grace period management from lockd() to per-net functions LockD: pass actual network namespace to grace period management functions LockD: manage grace list per network namespace SUNRPC: service request network namespace helper introduced NFSd: make nfsd4_manager allocated per network namespace context. LockD: make lockd manager allocated per network namespace LockD: manage grace period per network namespace Lockd: add more debug to host shutdown functions Lockd: host complaining function introduced LockD: manage used host count per networks namespace LockD: manage garbage collection timeout per networks namespace LockD: make garbage collector network namespace aware. LockD: mark host per network namespace on garbage collect nfsd4: fix missing fault_inject.h include locks: move lease-specific code out of locks_delete_lock locks: prevent side-effects of locks_release_private before file_lock is initialized NFSd: set nfsd_serv to NULL after service destruction NFSd: introduce nfsd_destroy() helper ...
This commit is contained in:
commit
08843b79fb
@ -4,8 +4,10 @@
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/lockd/bind.h>
|
||||
#include <net/net_namespace.h>
|
||||
|
||||
#include "netns.h"
|
||||
|
||||
static LIST_HEAD(grace_list);
|
||||
static DEFINE_SPINLOCK(grace_lock);
|
||||
|
||||
/**
|
||||
@ -19,10 +21,12 @@ static DEFINE_SPINLOCK(grace_lock);
|
||||
*
|
||||
* This function is called to start a grace period.
|
||||
*/
|
||||
void locks_start_grace(struct lock_manager *lm)
|
||||
void locks_start_grace(struct net *net, struct lock_manager *lm)
|
||||
{
|
||||
struct lockd_net *ln = net_generic(net, lockd_net_id);
|
||||
|
||||
spin_lock(&grace_lock);
|
||||
list_add(&lm->list, &grace_list);
|
||||
list_add(&lm->list, &ln->grace_list);
|
||||
spin_unlock(&grace_lock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(locks_start_grace);
|
||||
@ -52,8 +56,10 @@ EXPORT_SYMBOL_GPL(locks_end_grace);
|
||||
* to answer ordinary lock requests, and when they should accept only
|
||||
* lock reclaims.
|
||||
*/
|
||||
int locks_in_grace(void)
|
||||
int locks_in_grace(struct net *net)
|
||||
{
|
||||
return !list_empty(&grace_list);
|
||||
struct lockd_net *ln = net_generic(net, lockd_net_id);
|
||||
|
||||
return !list_empty(&ln->grace_list);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(locks_in_grace);
|
||||
|
@ -21,6 +21,8 @@
|
||||
|
||||
#include <net/ipv6.h>
|
||||
|
||||
#include "netns.h"
|
||||
|
||||
#define NLMDBG_FACILITY NLMDBG_HOSTCACHE
|
||||
#define NLM_HOST_NRHASH 32
|
||||
#define NLM_HOST_REBIND (60 * HZ)
|
||||
@ -41,11 +43,10 @@ static struct hlist_head nlm_client_hosts[NLM_HOST_NRHASH];
|
||||
hlist_for_each_entry_safe((host), (pos), (next), \
|
||||
(chain), h_hash)
|
||||
|
||||
static unsigned long next_gc;
|
||||
static unsigned long nrhosts;
|
||||
static DEFINE_MUTEX(nlm_host_mutex);
|
||||
|
||||
static void nlm_gc_hosts(void);
|
||||
static void nlm_gc_hosts(struct net *net);
|
||||
|
||||
struct nlm_lookup_host_info {
|
||||
const int server; /* search for server|client */
|
||||
@ -172,6 +173,7 @@ out:
|
||||
static void nlm_destroy_host_locked(struct nlm_host *host)
|
||||
{
|
||||
struct rpc_clnt *clnt;
|
||||
struct lockd_net *ln = net_generic(host->net, lockd_net_id);
|
||||
|
||||
dprintk("lockd: destroy host %s\n", host->h_name);
|
||||
|
||||
@ -188,6 +190,7 @@ static void nlm_destroy_host_locked(struct nlm_host *host)
|
||||
rpc_shutdown_client(clnt);
|
||||
kfree(host);
|
||||
|
||||
ln->nrhosts--;
|
||||
nrhosts--;
|
||||
}
|
||||
|
||||
@ -228,6 +231,7 @@ struct nlm_host *nlmclnt_lookup_host(const struct sockaddr *sap,
|
||||
struct hlist_node *pos;
|
||||
struct nlm_host *host;
|
||||
struct nsm_handle *nsm = NULL;
|
||||
struct lockd_net *ln = net_generic(net, lockd_net_id);
|
||||
|
||||
dprintk("lockd: %s(host='%s', vers=%u, proto=%s)\n", __func__,
|
||||
(hostname ? hostname : "<none>"), version,
|
||||
@ -262,6 +266,7 @@ struct nlm_host *nlmclnt_lookup_host(const struct sockaddr *sap,
|
||||
goto out;
|
||||
|
||||
hlist_add_head(&host->h_hash, chain);
|
||||
ln->nrhosts++;
|
||||
nrhosts++;
|
||||
|
||||
dprintk("lockd: %s created host %s (%s)\n", __func__,
|
||||
@ -326,7 +331,7 @@ struct nlm_host *nlmsvc_lookup_host(const struct svc_rqst *rqstp,
|
||||
struct nsm_handle *nsm = NULL;
|
||||
struct sockaddr *src_sap = svc_daddr(rqstp);
|
||||
size_t src_len = rqstp->rq_daddrlen;
|
||||
struct net *net = rqstp->rq_xprt->xpt_net;
|
||||
struct net *net = SVC_NET(rqstp);
|
||||
struct nlm_lookup_host_info ni = {
|
||||
.server = 1,
|
||||
.sap = svc_addr(rqstp),
|
||||
@ -337,6 +342,7 @@ struct nlm_host *nlmsvc_lookup_host(const struct svc_rqst *rqstp,
|
||||
.hostname_len = hostname_len,
|
||||
.net = net,
|
||||
};
|
||||
struct lockd_net *ln = net_generic(net, lockd_net_id);
|
||||
|
||||
dprintk("lockd: %s(host='%*s', vers=%u, proto=%s)\n", __func__,
|
||||
(int)hostname_len, hostname, rqstp->rq_vers,
|
||||
@ -344,8 +350,8 @@ struct nlm_host *nlmsvc_lookup_host(const struct svc_rqst *rqstp,
|
||||
|
||||
mutex_lock(&nlm_host_mutex);
|
||||
|
||||
if (time_after_eq(jiffies, next_gc))
|
||||
nlm_gc_hosts();
|
||||
if (time_after_eq(jiffies, ln->next_gc))
|
||||
nlm_gc_hosts(net);
|
||||
|
||||
chain = &nlm_server_hosts[nlm_hash_address(ni.sap)];
|
||||
hlist_for_each_entry(host, pos, chain, h_hash) {
|
||||
@ -382,6 +388,7 @@ struct nlm_host *nlmsvc_lookup_host(const struct svc_rqst *rqstp,
|
||||
memcpy(nlm_srcaddr(host), src_sap, src_len);
|
||||
host->h_srcaddrlen = src_len;
|
||||
hlist_add_head(&host->h_hash, chain);
|
||||
ln->nrhosts++;
|
||||
nrhosts++;
|
||||
|
||||
dprintk("lockd: %s created host %s (%s)\n",
|
||||
@ -565,6 +572,35 @@ void nlm_host_rebooted(const struct nlm_reboot *info)
|
||||
nsm_release(nsm);
|
||||
}
|
||||
|
||||
static void nlm_complain_hosts(struct net *net)
|
||||
{
|
||||
struct hlist_head *chain;
|
||||
struct hlist_node *pos;
|
||||
struct nlm_host *host;
|
||||
|
||||
if (net) {
|
||||
struct lockd_net *ln = net_generic(net, lockd_net_id);
|
||||
|
||||
if (ln->nrhosts == 0)
|
||||
return;
|
||||
printk(KERN_WARNING "lockd: couldn't shutdown host module for net %p!\n", net);
|
||||
dprintk("lockd: %lu hosts left in net %p:\n", ln->nrhosts, net);
|
||||
} else {
|
||||
if (nrhosts == 0)
|
||||
return;
|
||||
printk(KERN_WARNING "lockd: couldn't shutdown host module!\n");
|
||||
dprintk("lockd: %lu hosts left:\n", nrhosts);
|
||||
}
|
||||
|
||||
for_each_host(host, pos, chain, nlm_server_hosts) {
|
||||
if (net && host->net != net)
|
||||
continue;
|
||||
dprintk(" %s (cnt %d use %d exp %ld net %p)\n",
|
||||
host->h_name, atomic_read(&host->h_count),
|
||||
host->h_inuse, host->h_expires, host->net);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nlm_shutdown_hosts_net(struct net *net)
|
||||
{
|
||||
@ -572,11 +608,10 @@ nlm_shutdown_hosts_net(struct net *net)
|
||||
struct hlist_node *pos;
|
||||
struct nlm_host *host;
|
||||
|
||||
dprintk("lockd: shutting down host module\n");
|
||||
mutex_lock(&nlm_host_mutex);
|
||||
|
||||
/* First, make all hosts eligible for gc */
|
||||
dprintk("lockd: nuking all hosts...\n");
|
||||
dprintk("lockd: nuking all hosts in net %p...\n", net);
|
||||
for_each_host(host, pos, chain, nlm_server_hosts) {
|
||||
if (net && host->net != net)
|
||||
continue;
|
||||
@ -588,8 +623,10 @@ nlm_shutdown_hosts_net(struct net *net)
|
||||
}
|
||||
|
||||
/* Then, perform a garbage collection pass */
|
||||
nlm_gc_hosts();
|
||||
nlm_gc_hosts(net);
|
||||
mutex_unlock(&nlm_host_mutex);
|
||||
|
||||
nlm_complain_hosts(net);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -599,22 +636,8 @@ nlm_shutdown_hosts_net(struct net *net)
|
||||
void
|
||||
nlm_shutdown_hosts(void)
|
||||
{
|
||||
struct hlist_head *chain;
|
||||
struct hlist_node *pos;
|
||||
struct nlm_host *host;
|
||||
|
||||
dprintk("lockd: shutting down host module\n");
|
||||
nlm_shutdown_hosts_net(NULL);
|
||||
|
||||
/* complain if any hosts are left */
|
||||
if (nrhosts != 0) {
|
||||
printk(KERN_WARNING "lockd: couldn't shutdown host module!\n");
|
||||
dprintk("lockd: %lu hosts left:\n", nrhosts);
|
||||
for_each_host(host, pos, chain, nlm_server_hosts) {
|
||||
dprintk(" %s (cnt %d use %d exp %ld net %p)\n",
|
||||
host->h_name, atomic_read(&host->h_count),
|
||||
host->h_inuse, host->h_expires, host->net);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -623,30 +646,39 @@ nlm_shutdown_hosts(void)
|
||||
* mark & sweep for resources held by remote clients.
|
||||
*/
|
||||
static void
|
||||
nlm_gc_hosts(void)
|
||||
nlm_gc_hosts(struct net *net)
|
||||
{
|
||||
struct hlist_head *chain;
|
||||
struct hlist_node *pos, *next;
|
||||
struct nlm_host *host;
|
||||
|
||||
dprintk("lockd: host garbage collection\n");
|
||||
for_each_host(host, pos, chain, nlm_server_hosts)
|
||||
dprintk("lockd: host garbage collection for net %p\n", net);
|
||||
for_each_host(host, pos, chain, nlm_server_hosts) {
|
||||
if (net && host->net != net)
|
||||
continue;
|
||||
host->h_inuse = 0;
|
||||
}
|
||||
|
||||
/* Mark all hosts that hold locks, blocks or shares */
|
||||
nlmsvc_mark_resources();
|
||||
nlmsvc_mark_resources(net);
|
||||
|
||||
for_each_host_safe(host, pos, next, chain, nlm_server_hosts) {
|
||||
if (net && host->net != net)
|
||||
continue;
|
||||
if (atomic_read(&host->h_count) || host->h_inuse
|
||||
|| time_before(jiffies, host->h_expires)) {
|
||||
dprintk("nlm_gc_hosts skipping %s "
|
||||
"(cnt %d use %d exp %ld)\n",
|
||||
"(cnt %d use %d exp %ld net %p)\n",
|
||||
host->h_name, atomic_read(&host->h_count),
|
||||
host->h_inuse, host->h_expires);
|
||||
host->h_inuse, host->h_expires, host->net);
|
||||
continue;
|
||||
}
|
||||
nlm_destroy_host_locked(host);
|
||||
}
|
||||
|
||||
next_gc = jiffies + NLM_HOST_COLLECT;
|
||||
if (net) {
|
||||
struct lockd_net *ln = net_generic(net, lockd_net_id);
|
||||
|
||||
ln->next_gc = jiffies + NLM_HOST_COLLECT;
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,17 @@
|
||||
#ifndef __LOCKD_NETNS_H__
|
||||
#define __LOCKD_NETNS_H__
|
||||
|
||||
#include <linux/fs.h>
|
||||
#include <net/netns/generic.h>
|
||||
|
||||
struct lockd_net {
|
||||
unsigned int nlmsvc_users;
|
||||
unsigned long next_gc;
|
||||
unsigned long nrhosts;
|
||||
|
||||
struct delayed_work grace_period_end;
|
||||
struct lock_manager lockd_manager;
|
||||
struct list_head grace_list;
|
||||
};
|
||||
|
||||
extern int lockd_net_id;
|
||||
|
@ -87,32 +87,36 @@ static unsigned long get_lockd_grace_period(void)
|
||||
return nlm_timeout * 5 * HZ;
|
||||
}
|
||||
|
||||
static struct lock_manager lockd_manager = {
|
||||
};
|
||||
|
||||
static void grace_ender(struct work_struct *not_used)
|
||||
static void grace_ender(struct work_struct *grace)
|
||||
{
|
||||
locks_end_grace(&lockd_manager);
|
||||
struct delayed_work *dwork = container_of(grace, struct delayed_work,
|
||||
work);
|
||||
struct lockd_net *ln = container_of(dwork, struct lockd_net,
|
||||
grace_period_end);
|
||||
|
||||
locks_end_grace(&ln->lockd_manager);
|
||||
}
|
||||
|
||||
static DECLARE_DELAYED_WORK(grace_period_end, grace_ender);
|
||||
|
||||
static void set_grace_period(void)
|
||||
static void set_grace_period(struct net *net)
|
||||
{
|
||||
unsigned long grace_period = get_lockd_grace_period();
|
||||
struct lockd_net *ln = net_generic(net, lockd_net_id);
|
||||
|
||||
locks_start_grace(&lockd_manager);
|
||||
cancel_delayed_work_sync(&grace_period_end);
|
||||
schedule_delayed_work(&grace_period_end, grace_period);
|
||||
locks_start_grace(net, &ln->lockd_manager);
|
||||
cancel_delayed_work_sync(&ln->grace_period_end);
|
||||
schedule_delayed_work(&ln->grace_period_end, grace_period);
|
||||
}
|
||||
|
||||
static void restart_grace(void)
|
||||
{
|
||||
if (nlmsvc_ops) {
|
||||
cancel_delayed_work_sync(&grace_period_end);
|
||||
locks_end_grace(&lockd_manager);
|
||||
struct net *net = &init_net;
|
||||
struct lockd_net *ln = net_generic(net, lockd_net_id);
|
||||
|
||||
cancel_delayed_work_sync(&ln->grace_period_end);
|
||||
locks_end_grace(&ln->lockd_manager);
|
||||
nlmsvc_invalidate_all();
|
||||
set_grace_period();
|
||||
set_grace_period(net);
|
||||
}
|
||||
}
|
||||
|
||||
@ -137,8 +141,6 @@ lockd(void *vrqstp)
|
||||
nlm_timeout = LOCKD_DFLT_TIMEO;
|
||||
nlmsvc_timeout = nlm_timeout * HZ;
|
||||
|
||||
set_grace_period();
|
||||
|
||||
/*
|
||||
* The main request loop. We don't terminate until the last
|
||||
* NFS mount or NFS daemon has gone away.
|
||||
@ -184,8 +186,6 @@ lockd(void *vrqstp)
|
||||
svc_process(rqstp);
|
||||
}
|
||||
flush_signals(current);
|
||||
cancel_delayed_work_sync(&grace_period_end);
|
||||
locks_end_grace(&lockd_manager);
|
||||
if (nlmsvc_ops)
|
||||
nlmsvc_invalidate_all();
|
||||
nlm_shutdown_hosts();
|
||||
@ -266,6 +266,7 @@ static int lockd_up_net(struct svc_serv *serv, struct net *net)
|
||||
error = make_socks(serv, net);
|
||||
if (error < 0)
|
||||
goto err_socks;
|
||||
set_grace_period(net);
|
||||
dprintk("lockd_up_net: per-net data created; net=%p\n", net);
|
||||
return 0;
|
||||
|
||||
@ -283,6 +284,8 @@ static void lockd_down_net(struct svc_serv *serv, struct net *net)
|
||||
if (ln->nlmsvc_users) {
|
||||
if (--ln->nlmsvc_users == 0) {
|
||||
nlm_shutdown_hosts_net(net);
|
||||
cancel_delayed_work_sync(&ln->grace_period_end);
|
||||
locks_end_grace(&ln->lockd_manager);
|
||||
svc_shutdown_net(serv, net);
|
||||
dprintk("lockd_down_net: per-net data destroyed; net=%p\n", net);
|
||||
}
|
||||
@ -589,6 +592,10 @@ module_param(nlm_max_connections, uint, 0644);
|
||||
|
||||
static int lockd_init_net(struct net *net)
|
||||
{
|
||||
struct lockd_net *ln = net_generic(net, lockd_net_id);
|
||||
|
||||
INIT_DELAYED_WORK(&ln->grace_period_end, grace_ender);
|
||||
INIT_LIST_HEAD(&ln->grace_list);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <linux/time.h>
|
||||
#include <linux/lockd/lockd.h>
|
||||
#include <linux/lockd/share.h>
|
||||
#include <linux/sunrpc/svc_xprt.h>
|
||||
|
||||
#define NLMDBG_FACILITY NLMDBG_CLIENT
|
||||
|
||||
@ -151,7 +152,7 @@ nlm4svc_proc_cancel(struct svc_rqst *rqstp, struct nlm_args *argp,
|
||||
resp->cookie = argp->cookie;
|
||||
|
||||
/* Don't accept requests during grace period */
|
||||
if (locks_in_grace()) {
|
||||
if (locks_in_grace(SVC_NET(rqstp))) {
|
||||
resp->status = nlm_lck_denied_grace_period;
|
||||
return rpc_success;
|
||||
}
|
||||
@ -161,7 +162,7 @@ nlm4svc_proc_cancel(struct svc_rqst *rqstp, struct nlm_args *argp,
|
||||
return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
|
||||
|
||||
/* Try to cancel request. */
|
||||
resp->status = nlmsvc_cancel_blocked(file, &argp->lock);
|
||||
resp->status = nlmsvc_cancel_blocked(SVC_NET(rqstp), file, &argp->lock);
|
||||
|
||||
dprintk("lockd: CANCEL status %d\n", ntohl(resp->status));
|
||||
nlmsvc_release_host(host);
|
||||
@ -184,7 +185,7 @@ nlm4svc_proc_unlock(struct svc_rqst *rqstp, struct nlm_args *argp,
|
||||
resp->cookie = argp->cookie;
|
||||
|
||||
/* Don't accept new lock requests during grace period */
|
||||
if (locks_in_grace()) {
|
||||
if (locks_in_grace(SVC_NET(rqstp))) {
|
||||
resp->status = nlm_lck_denied_grace_period;
|
||||
return rpc_success;
|
||||
}
|
||||
@ -194,7 +195,7 @@ nlm4svc_proc_unlock(struct svc_rqst *rqstp, struct nlm_args *argp,
|
||||
return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
|
||||
|
||||
/* Now try to remove the lock */
|
||||
resp->status = nlmsvc_unlock(file, &argp->lock);
|
||||
resp->status = nlmsvc_unlock(SVC_NET(rqstp), file, &argp->lock);
|
||||
|
||||
dprintk("lockd: UNLOCK status %d\n", ntohl(resp->status));
|
||||
nlmsvc_release_host(host);
|
||||
@ -321,7 +322,7 @@ nlm4svc_proc_share(struct svc_rqst *rqstp, struct nlm_args *argp,
|
||||
resp->cookie = argp->cookie;
|
||||
|
||||
/* Don't accept new lock requests during grace period */
|
||||
if (locks_in_grace() && !argp->reclaim) {
|
||||
if (locks_in_grace(SVC_NET(rqstp)) && !argp->reclaim) {
|
||||
resp->status = nlm_lck_denied_grace_period;
|
||||
return rpc_success;
|
||||
}
|
||||
@ -354,7 +355,7 @@ nlm4svc_proc_unshare(struct svc_rqst *rqstp, struct nlm_args *argp,
|
||||
resp->cookie = argp->cookie;
|
||||
|
||||
/* Don't accept requests during grace period */
|
||||
if (locks_in_grace()) {
|
||||
if (locks_in_grace(SVC_NET(rqstp))) {
|
||||
resp->status = nlm_lck_denied_grace_period;
|
||||
return rpc_success;
|
||||
}
|
||||
|
@ -26,7 +26,7 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/sunrpc/clnt.h>
|
||||
#include <linux/sunrpc/svc.h>
|
||||
#include <linux/sunrpc/svc_xprt.h>
|
||||
#include <linux/lockd/nlm.h>
|
||||
#include <linux/lockd/lockd.h>
|
||||
#include <linux/kthread.h>
|
||||
@ -447,11 +447,11 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (locks_in_grace() && !reclaim) {
|
||||
if (locks_in_grace(SVC_NET(rqstp)) && !reclaim) {
|
||||
ret = nlm_lck_denied_grace_period;
|
||||
goto out;
|
||||
}
|
||||
if (reclaim && !locks_in_grace()) {
|
||||
if (reclaim && !locks_in_grace(SVC_NET(rqstp))) {
|
||||
ret = nlm_lck_denied_grace_period;
|
||||
goto out;
|
||||
}
|
||||
@ -559,7 +559,7 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (locks_in_grace()) {
|
||||
if (locks_in_grace(SVC_NET(rqstp))) {
|
||||
ret = nlm_lck_denied_grace_period;
|
||||
goto out;
|
||||
}
|
||||
@ -603,7 +603,7 @@ out:
|
||||
* must be removed.
|
||||
*/
|
||||
__be32
|
||||
nlmsvc_unlock(struct nlm_file *file, struct nlm_lock *lock)
|
||||
nlmsvc_unlock(struct net *net, struct nlm_file *file, struct nlm_lock *lock)
|
||||
{
|
||||
int error;
|
||||
|
||||
@ -615,7 +615,7 @@ nlmsvc_unlock(struct nlm_file *file, struct nlm_lock *lock)
|
||||
(long long)lock->fl.fl_end);
|
||||
|
||||
/* First, cancel any lock that might be there */
|
||||
nlmsvc_cancel_blocked(file, lock);
|
||||
nlmsvc_cancel_blocked(net, file, lock);
|
||||
|
||||
lock->fl.fl_type = F_UNLCK;
|
||||
error = vfs_lock_file(file->f_file, F_SETLK, &lock->fl, NULL);
|
||||
@ -631,7 +631,7 @@ nlmsvc_unlock(struct nlm_file *file, struct nlm_lock *lock)
|
||||
* The calling procedure must check whether the file can be closed.
|
||||
*/
|
||||
__be32
|
||||
nlmsvc_cancel_blocked(struct nlm_file *file, struct nlm_lock *lock)
|
||||
nlmsvc_cancel_blocked(struct net *net, struct nlm_file *file, struct nlm_lock *lock)
|
||||
{
|
||||
struct nlm_block *block;
|
||||
int status = 0;
|
||||
@ -643,7 +643,7 @@ nlmsvc_cancel_blocked(struct nlm_file *file, struct nlm_lock *lock)
|
||||
(long long)lock->fl.fl_start,
|
||||
(long long)lock->fl.fl_end);
|
||||
|
||||
if (locks_in_grace())
|
||||
if (locks_in_grace(net))
|
||||
return nlm_lck_denied_grace_period;
|
||||
|
||||
mutex_lock(&file->f_mutex);
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <linux/time.h>
|
||||
#include <linux/lockd/lockd.h>
|
||||
#include <linux/lockd/share.h>
|
||||
#include <linux/sunrpc/svc_xprt.h>
|
||||
|
||||
#define NLMDBG_FACILITY NLMDBG_CLIENT
|
||||
|
||||
@ -175,13 +176,14 @@ nlmsvc_proc_cancel(struct svc_rqst *rqstp, struct nlm_args *argp,
|
||||
{
|
||||
struct nlm_host *host;
|
||||
struct nlm_file *file;
|
||||
struct net *net = SVC_NET(rqstp);
|
||||
|
||||
dprintk("lockd: CANCEL called\n");
|
||||
|
||||
resp->cookie = argp->cookie;
|
||||
|
||||
/* Don't accept requests during grace period */
|
||||
if (locks_in_grace()) {
|
||||
if (locks_in_grace(net)) {
|
||||
resp->status = nlm_lck_denied_grace_period;
|
||||
return rpc_success;
|
||||
}
|
||||
@ -191,7 +193,7 @@ nlmsvc_proc_cancel(struct svc_rqst *rqstp, struct nlm_args *argp,
|
||||
return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
|
||||
|
||||
/* Try to cancel request. */
|
||||
resp->status = cast_status(nlmsvc_cancel_blocked(file, &argp->lock));
|
||||
resp->status = cast_status(nlmsvc_cancel_blocked(net, file, &argp->lock));
|
||||
|
||||
dprintk("lockd: CANCEL status %d\n", ntohl(resp->status));
|
||||
nlmsvc_release_host(host);
|
||||
@ -208,13 +210,14 @@ nlmsvc_proc_unlock(struct svc_rqst *rqstp, struct nlm_args *argp,
|
||||
{
|
||||
struct nlm_host *host;
|
||||
struct nlm_file *file;
|
||||
struct net *net = SVC_NET(rqstp);
|
||||
|
||||
dprintk("lockd: UNLOCK called\n");
|
||||
|
||||
resp->cookie = argp->cookie;
|
||||
|
||||
/* Don't accept new lock requests during grace period */
|
||||
if (locks_in_grace()) {
|
||||
if (locks_in_grace(net)) {
|
||||
resp->status = nlm_lck_denied_grace_period;
|
||||
return rpc_success;
|
||||
}
|
||||
@ -224,7 +227,7 @@ nlmsvc_proc_unlock(struct svc_rqst *rqstp, struct nlm_args *argp,
|
||||
return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
|
||||
|
||||
/* Now try to remove the lock */
|
||||
resp->status = cast_status(nlmsvc_unlock(file, &argp->lock));
|
||||
resp->status = cast_status(nlmsvc_unlock(net, file, &argp->lock));
|
||||
|
||||
dprintk("lockd: UNLOCK status %d\n", ntohl(resp->status));
|
||||
nlmsvc_release_host(host);
|
||||
@ -361,7 +364,7 @@ nlmsvc_proc_share(struct svc_rqst *rqstp, struct nlm_args *argp,
|
||||
resp->cookie = argp->cookie;
|
||||
|
||||
/* Don't accept new lock requests during grace period */
|
||||
if (locks_in_grace() && !argp->reclaim) {
|
||||
if (locks_in_grace(SVC_NET(rqstp)) && !argp->reclaim) {
|
||||
resp->status = nlm_lck_denied_grace_period;
|
||||
return rpc_success;
|
||||
}
|
||||
@ -394,7 +397,7 @@ nlmsvc_proc_unshare(struct svc_rqst *rqstp, struct nlm_args *argp,
|
||||
resp->cookie = argp->cookie;
|
||||
|
||||
/* Don't accept requests during grace period */
|
||||
if (locks_in_grace()) {
|
||||
if (locks_in_grace(SVC_NET(rqstp))) {
|
||||
resp->status = nlm_lck_denied_grace_period;
|
||||
return rpc_success;
|
||||
}
|
||||
|
@ -309,7 +309,8 @@ nlm_release_file(struct nlm_file *file)
|
||||
* Helpers function for resource traversal
|
||||
*
|
||||
* nlmsvc_mark_host:
|
||||
* used by the garbage collector; simply sets h_inuse.
|
||||
* used by the garbage collector; simply sets h_inuse only for those
|
||||
* hosts, which passed network check.
|
||||
* Always returns 0.
|
||||
*
|
||||
* nlmsvc_same_host:
|
||||
@ -320,12 +321,15 @@ nlm_release_file(struct nlm_file *file)
|
||||
* returns 1 iff the host is a client.
|
||||
* Used by nlmsvc_invalidate_all
|
||||
*/
|
||||
|
||||
static int
|
||||
nlmsvc_mark_host(void *data, struct nlm_host *dummy)
|
||||
nlmsvc_mark_host(void *data, struct nlm_host *hint)
|
||||
{
|
||||
struct nlm_host *host = data;
|
||||
|
||||
host->h_inuse = 1;
|
||||
if ((hint->net == NULL) ||
|
||||
(host->net == hint->net))
|
||||
host->h_inuse = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -358,10 +362,13 @@ nlmsvc_is_client(void *data, struct nlm_host *dummy)
|
||||
* Mark all hosts that still hold resources
|
||||
*/
|
||||
void
|
||||
nlmsvc_mark_resources(void)
|
||||
nlmsvc_mark_resources(struct net *net)
|
||||
{
|
||||
dprintk("lockd: nlmsvc_mark_resources\n");
|
||||
nlm_traverse_files(NULL, nlmsvc_mark_host, NULL);
|
||||
struct nlm_host hint;
|
||||
|
||||
dprintk("lockd: nlmsvc_mark_resources for net %p\n", net);
|
||||
hint.net = net;
|
||||
nlm_traverse_files(&hint, nlmsvc_mark_host, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
|
28
fs/locks.c
28
fs/locks.c
@ -427,18 +427,8 @@ static void lease_break_callback(struct file_lock *fl)
|
||||
kill_fasync(&fl->fl_fasync, SIGIO, POLL_MSG);
|
||||
}
|
||||
|
||||
static void lease_release_private_callback(struct file_lock *fl)
|
||||
{
|
||||
if (!fl->fl_file)
|
||||
return;
|
||||
|
||||
f_delown(fl->fl_file);
|
||||
fl->fl_file->f_owner.signum = 0;
|
||||
}
|
||||
|
||||
static const struct lock_manager_operations lease_manager_ops = {
|
||||
.lm_break = lease_break_callback,
|
||||
.lm_release_private = lease_release_private_callback,
|
||||
.lm_change = lease_modify,
|
||||
};
|
||||
|
||||
@ -580,12 +570,6 @@ static void locks_delete_lock(struct file_lock **thisfl_p)
|
||||
fl->fl_next = NULL;
|
||||
list_del_init(&fl->fl_link);
|
||||
|
||||
fasync_helper(0, fl->fl_file, 0, &fl->fl_fasync);
|
||||
if (fl->fl_fasync != NULL) {
|
||||
printk(KERN_ERR "locks_delete_lock: fasync == %p\n", fl->fl_fasync);
|
||||
fl->fl_fasync = NULL;
|
||||
}
|
||||
|
||||
if (fl->fl_nspid) {
|
||||
put_pid(fl->fl_nspid);
|
||||
fl->fl_nspid = NULL;
|
||||
@ -1155,8 +1139,18 @@ int lease_modify(struct file_lock **before, int arg)
|
||||
return error;
|
||||
lease_clear_pending(fl, arg);
|
||||
locks_wake_up_blocks(fl);
|
||||
if (arg == F_UNLCK)
|
||||
if (arg == F_UNLCK) {
|
||||
struct file *filp = fl->fl_file;
|
||||
|
||||
f_delown(filp);
|
||||
filp->f_owner.signum = 0;
|
||||
fasync_helper(0, fl->fl_file, 0, &fl->fl_fasync);
|
||||
if (fl->fl_fasync != NULL) {
|
||||
printk(KERN_ERR "locks_delete_lock: fasync == %p\n", fl->fl_fasync);
|
||||
fl->fl_fasync = NULL;
|
||||
}
|
||||
locks_delete_lock(before);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -863,7 +863,7 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *r
|
||||
.drc_status = 0,
|
||||
.clp = NULL,
|
||||
.slotid = NFS4_NO_SLOT,
|
||||
.net = rqstp->rq_xprt->xpt_net,
|
||||
.net = SVC_NET(rqstp),
|
||||
};
|
||||
unsigned int nops = 0;
|
||||
|
||||
@ -879,7 +879,7 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *r
|
||||
return rpc_garbage_args;
|
||||
|
||||
if (hdr_arg.minorversion == 0) {
|
||||
cps.clp = nfs4_find_client_ident(rqstp->rq_xprt->xpt_net, hdr_arg.cb_ident);
|
||||
cps.clp = nfs4_find_client_ident(SVC_NET(rqstp), hdr_arg.cb_ident);
|
||||
if (!cps.clp || !check_gss_callback_principal(cps.clp, rqstp))
|
||||
return rpc_drop_reply;
|
||||
}
|
||||
|
@ -398,7 +398,7 @@ fsloc_parse(char **mesg, char *buf, struct nfsd4_fs_locations *fsloc)
|
||||
int migrated, i, err;
|
||||
|
||||
/* listsize */
|
||||
err = get_int(mesg, &fsloc->locations_count);
|
||||
err = get_uint(mesg, &fsloc->locations_count);
|
||||
if (err)
|
||||
return err;
|
||||
if (fsloc->locations_count > MAX_FS_LOCATIONS)
|
||||
@ -456,7 +456,7 @@ static int secinfo_parse(char **mesg, char *buf, struct svc_export *exp)
|
||||
return -EINVAL;
|
||||
|
||||
for (f = exp->ex_flavors; f < exp->ex_flavors + listsize; f++) {
|
||||
err = get_int(mesg, &f->pseudoflavor);
|
||||
err = get_uint(mesg, &f->pseudoflavor);
|
||||
if (err)
|
||||
return err;
|
||||
/*
|
||||
@ -465,7 +465,7 @@ static int secinfo_parse(char **mesg, char *buf, struct svc_export *exp)
|
||||
* problem at export time instead of when a client fails
|
||||
* to authenticate.
|
||||
*/
|
||||
err = get_int(mesg, &f->flags);
|
||||
err = get_uint(mesg, &f->flags);
|
||||
if (err)
|
||||
return err;
|
||||
/* Only some flags are allowed to differ between flavors: */
|
||||
@ -929,7 +929,7 @@ struct svc_export *
|
||||
rqst_exp_get_by_name(struct svc_rqst *rqstp, struct path *path)
|
||||
{
|
||||
struct svc_export *gssexp, *exp = ERR_PTR(-ENOENT);
|
||||
struct nfsd_net *nn = net_generic(rqstp->rq_xprt->xpt_net, nfsd_net_id);
|
||||
struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
|
||||
struct cache_detail *cd = nn->svc_export_cache;
|
||||
|
||||
if (rqstp->rq_client == NULL)
|
||||
@ -960,7 +960,7 @@ struct svc_export *
|
||||
rqst_exp_find(struct svc_rqst *rqstp, int fsid_type, u32 *fsidv)
|
||||
{
|
||||
struct svc_export *gssexp, *exp = ERR_PTR(-ENOENT);
|
||||
struct nfsd_net *nn = net_generic(rqstp->rq_xprt->xpt_net, nfsd_net_id);
|
||||
struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
|
||||
struct cache_detail *cd = nn->svc_export_cache;
|
||||
|
||||
if (rqstp->rq_client == NULL)
|
||||
|
@ -34,6 +34,10 @@ struct nfsd_net {
|
||||
|
||||
struct cache_detail *idtoname_cache;
|
||||
struct cache_detail *nametoid_cache;
|
||||
|
||||
struct lock_manager nfsd4_manager;
|
||||
bool grace_ended;
|
||||
time_t boot_time;
|
||||
};
|
||||
|
||||
extern int nfsd_net_id;
|
||||
|
@ -756,7 +756,6 @@ static void do_probe_callback(struct nfs4_client *clp)
|
||||
*/
|
||||
void nfsd4_probe_callback(struct nfs4_client *clp)
|
||||
{
|
||||
/* XXX: atomicity? Also, should we be using cl_flags? */
|
||||
clp->cl_cb_state = NFSD4_CB_UNKNOWN;
|
||||
set_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_flags);
|
||||
do_probe_callback(clp);
|
||||
|
@ -546,7 +546,7 @@ idmap_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen
|
||||
.type = type,
|
||||
};
|
||||
int ret;
|
||||
struct nfsd_net *nn = net_generic(rqstp->rq_xprt->xpt_net, nfsd_net_id);
|
||||
struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
|
||||
|
||||
if (namelen + 1 > sizeof(key.name))
|
||||
return nfserr_badowner;
|
||||
@ -571,7 +571,7 @@ idmap_id_to_name(struct svc_rqst *rqstp, int type, uid_t id, char *name)
|
||||
.type = type,
|
||||
};
|
||||
int ret;
|
||||
struct nfsd_net *nn = net_generic(rqstp->rq_xprt->xpt_net, nfsd_net_id);
|
||||
struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
|
||||
|
||||
strlcpy(key.authname, rqst_authname(rqstp), sizeof(key.authname));
|
||||
ret = idmap_lookup(rqstp, idtoname_lookup, &key, nn->idtoname_cache, &item);
|
||||
|
@ -354,10 +354,10 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||
/* Openowner is now set, so sequence id will get bumped. Now we need
|
||||
* these checks before we do any creates: */
|
||||
status = nfserr_grace;
|
||||
if (locks_in_grace() && open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
|
||||
if (locks_in_grace(SVC_NET(rqstp)) && open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS)
|
||||
goto out;
|
||||
status = nfserr_no_grace;
|
||||
if (!locks_in_grace() && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
|
||||
if (!locks_in_grace(SVC_NET(rqstp)) && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS)
|
||||
goto out;
|
||||
|
||||
switch (open->op_claim_type) {
|
||||
@ -686,7 +686,8 @@ nfsd4_read(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||
|
||||
nfs4_lock_state();
|
||||
/* check stateid */
|
||||
if ((status = nfs4_preprocess_stateid_op(cstate, &read->rd_stateid,
|
||||
if ((status = nfs4_preprocess_stateid_op(SVC_NET(rqstp),
|
||||
cstate, &read->rd_stateid,
|
||||
RD_STATE, &read->rd_filp))) {
|
||||
dprintk("NFSD: nfsd4_read: couldn't process stateid!\n");
|
||||
goto out;
|
||||
@ -741,7 +742,7 @@ nfsd4_remove(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||
{
|
||||
__be32 status;
|
||||
|
||||
if (locks_in_grace())
|
||||
if (locks_in_grace(SVC_NET(rqstp)))
|
||||
return nfserr_grace;
|
||||
status = nfsd_unlink(rqstp, &cstate->current_fh, 0,
|
||||
remove->rm_name, remove->rm_namelen);
|
||||
@ -760,8 +761,8 @@ nfsd4_rename(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||
|
||||
if (!cstate->save_fh.fh_dentry)
|
||||
return status;
|
||||
if (locks_in_grace() && !(cstate->save_fh.fh_export->ex_flags
|
||||
& NFSEXP_NOSUBTREECHECK))
|
||||
if (locks_in_grace(SVC_NET(rqstp)) &&
|
||||
!(cstate->save_fh.fh_export->ex_flags & NFSEXP_NOSUBTREECHECK))
|
||||
return nfserr_grace;
|
||||
status = nfsd_rename(rqstp, &cstate->save_fh, rename->rn_sname,
|
||||
rename->rn_snamelen, &cstate->current_fh,
|
||||
@ -845,7 +846,7 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||
|
||||
if (setattr->sa_iattr.ia_valid & ATTR_SIZE) {
|
||||
nfs4_lock_state();
|
||||
status = nfs4_preprocess_stateid_op(cstate,
|
||||
status = nfs4_preprocess_stateid_op(SVC_NET(rqstp), cstate,
|
||||
&setattr->sa_stateid, WR_STATE, NULL);
|
||||
nfs4_unlock_state();
|
||||
if (status) {
|
||||
@ -890,7 +891,8 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||
return nfserr_inval;
|
||||
|
||||
nfs4_lock_state();
|
||||
status = nfs4_preprocess_stateid_op(cstate, stateid, WR_STATE, &filp);
|
||||
status = nfs4_preprocess_stateid_op(SVC_NET(rqstp),
|
||||
cstate, stateid, WR_STATE, &filp);
|
||||
if (filp)
|
||||
get_file(filp);
|
||||
nfs4_unlock_state();
|
||||
|
@ -38,18 +38,21 @@
|
||||
#include <linux/namei.h>
|
||||
#include <linux/swap.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/ratelimit.h>
|
||||
#include <linux/sunrpc/svcauth_gss.h>
|
||||
#include <linux/sunrpc/clnt.h>
|
||||
#include "xdr4.h"
|
||||
#include "vfs.h"
|
||||
#include "current_stateid.h"
|
||||
#include "fault_inject.h"
|
||||
|
||||
#include "netns.h"
|
||||
|
||||
#define NFSDDBG_FACILITY NFSDDBG_PROC
|
||||
|
||||
/* Globals */
|
||||
time_t nfsd4_lease = 90; /* default lease time */
|
||||
time_t nfsd4_grace = 90;
|
||||
static time_t boot_time;
|
||||
|
||||
#define all_ones {{~0,~0},~0}
|
||||
static const stateid_t one_stateid = {
|
||||
@ -862,6 +865,11 @@ static __be32 nfsd4_new_conn(struct svc_rqst *rqstp, struct nfsd4_session *ses,
|
||||
if (ret)
|
||||
/* oops; xprt is already down: */
|
||||
nfsd4_conn_lost(&conn->cn_xpt_user);
|
||||
if (ses->se_client->cl_cb_state == NFSD4_CB_DOWN &&
|
||||
dir & NFS4_CDFC4_BACK) {
|
||||
/* callback channel may be back up */
|
||||
nfsd4_probe_callback(ses->se_client);
|
||||
}
|
||||
return nfs_ok;
|
||||
}
|
||||
|
||||
@ -1047,12 +1055,12 @@ renew_client(struct nfs4_client *clp)
|
||||
|
||||
/* SETCLIENTID and SETCLIENTID_CONFIRM Helper functions */
|
||||
static int
|
||||
STALE_CLIENTID(clientid_t *clid)
|
||||
STALE_CLIENTID(clientid_t *clid, struct nfsd_net *nn)
|
||||
{
|
||||
if (clid->cl_boot == boot_time)
|
||||
if (clid->cl_boot == nn->boot_time)
|
||||
return 0;
|
||||
dprintk("NFSD stale clientid (%08x/%08x) boot_time %08lx\n",
|
||||
clid->cl_boot, clid->cl_id, boot_time);
|
||||
clid->cl_boot, clid->cl_id, nn->boot_time);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -1215,7 +1223,7 @@ static bool groups_equal(struct group_info *g1, struct group_info *g2)
|
||||
return true;
|
||||
}
|
||||
|
||||
static int
|
||||
static bool
|
||||
same_creds(struct svc_cred *cr1, struct svc_cred *cr2)
|
||||
{
|
||||
if ((cr1->cr_flavor != cr2->cr_flavor)
|
||||
@ -1227,14 +1235,15 @@ same_creds(struct svc_cred *cr1, struct svc_cred *cr2)
|
||||
return true;
|
||||
if (!cr1->cr_principal || !cr2->cr_principal)
|
||||
return false;
|
||||
return 0 == strcmp(cr1->cr_principal, cr1->cr_principal);
|
||||
return 0 == strcmp(cr1->cr_principal, cr2->cr_principal);
|
||||
}
|
||||
|
||||
static void gen_clid(struct nfs4_client *clp)
|
||||
{
|
||||
static u32 current_clientid = 1;
|
||||
struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
|
||||
|
||||
clp->cl_clientid.cl_boot = boot_time;
|
||||
clp->cl_clientid.cl_boot = nn->boot_time;
|
||||
clp->cl_clientid.cl_id = current_clientid++;
|
||||
}
|
||||
|
||||
@ -2217,8 +2226,9 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
|
||||
nfs4_verifier confirm = setclientid_confirm->sc_confirm;
|
||||
clientid_t * clid = &setclientid_confirm->sc_clientid;
|
||||
__be32 status;
|
||||
struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
|
||||
|
||||
if (STALE_CLIENTID(clid))
|
||||
if (STALE_CLIENTID(clid, nn))
|
||||
return nfserr_stale_clientid;
|
||||
nfs4_lock_state();
|
||||
|
||||
@ -2577,8 +2587,9 @@ nfsd4_process_open1(struct nfsd4_compound_state *cstate,
|
||||
unsigned int strhashval;
|
||||
struct nfs4_openowner *oo = NULL;
|
||||
__be32 status;
|
||||
struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
|
||||
|
||||
if (STALE_CLIENTID(&open->op_clientid))
|
||||
if (STALE_CLIENTID(&open->op_clientid, nn))
|
||||
return nfserr_stale_clientid;
|
||||
/*
|
||||
* In case we need it later, after we've already created the
|
||||
@ -2876,7 +2887,8 @@ static void nfsd4_open_deleg_none_ext(struct nfsd4_open *open, int status)
|
||||
* Attempt to hand out a delegation.
|
||||
*/
|
||||
static void
|
||||
nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_ol_stateid *stp)
|
||||
nfs4_open_delegation(struct net *net, struct svc_fh *fh,
|
||||
struct nfsd4_open *open, struct nfs4_ol_stateid *stp)
|
||||
{
|
||||
struct nfs4_delegation *dp;
|
||||
struct nfs4_openowner *oo = container_of(stp->st_stateowner, struct nfs4_openowner, oo_owner);
|
||||
@ -2897,7 +2909,7 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_ol_
|
||||
case NFS4_OPEN_CLAIM_NULL:
|
||||
/* Let's not give out any delegations till everyone's
|
||||
* had the chance to reclaim theirs.... */
|
||||
if (locks_in_grace())
|
||||
if (locks_in_grace(net))
|
||||
goto out;
|
||||
if (!cb_up || !(oo->oo_flags & NFS4_OO_CONFIRMED))
|
||||
goto out;
|
||||
@ -3005,16 +3017,14 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
|
||||
goto out;
|
||||
} else {
|
||||
status = nfs4_get_vfs_file(rqstp, fp, current_fh, open);
|
||||
if (status)
|
||||
goto out;
|
||||
status = nfsd4_truncate(rqstp, current_fh, open);
|
||||
if (status)
|
||||
goto out;
|
||||
stp = open->op_stp;
|
||||
open->op_stp = NULL;
|
||||
init_open_stateid(stp, fp, open);
|
||||
status = nfsd4_truncate(rqstp, current_fh, open);
|
||||
if (status) {
|
||||
release_open_stateid(stp);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
update_stateid(&stp->st_stid.sc_stateid);
|
||||
memcpy(&open->op_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t));
|
||||
@ -3033,7 +3043,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
|
||||
* Attempt to hand out a delegation. No error return, because the
|
||||
* OPEN succeeds even if we fail.
|
||||
*/
|
||||
nfs4_open_delegation(current_fh, open, stp);
|
||||
nfs4_open_delegation(SVC_NET(rqstp), current_fh, open, stp);
|
||||
nodeleg:
|
||||
status = nfs_ok;
|
||||
|
||||
@ -3087,12 +3097,13 @@ nfsd4_renew(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||
{
|
||||
struct nfs4_client *clp;
|
||||
__be32 status;
|
||||
struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
|
||||
|
||||
nfs4_lock_state();
|
||||
dprintk("process_renew(%08x/%08x): starting\n",
|
||||
clid->cl_boot, clid->cl_id);
|
||||
status = nfserr_stale_clientid;
|
||||
if (STALE_CLIENTID(clid))
|
||||
if (STALE_CLIENTID(clid, nn))
|
||||
goto out;
|
||||
clp = find_confirmed_client(clid);
|
||||
status = nfserr_expired;
|
||||
@ -3111,22 +3122,19 @@ out:
|
||||
return status;
|
||||
}
|
||||
|
||||
static struct lock_manager nfsd4_manager = {
|
||||
};
|
||||
|
||||
static bool grace_ended;
|
||||
|
||||
static void
|
||||
nfsd4_end_grace(void)
|
||||
nfsd4_end_grace(struct net *net)
|
||||
{
|
||||
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
|
||||
|
||||
/* do nothing if grace period already ended */
|
||||
if (grace_ended)
|
||||
if (nn->grace_ended)
|
||||
return;
|
||||
|
||||
dprintk("NFSD: end of grace period\n");
|
||||
grace_ended = true;
|
||||
nfsd4_record_grace_done(&init_net, boot_time);
|
||||
locks_end_grace(&nfsd4_manager);
|
||||
nn->grace_ended = true;
|
||||
nfsd4_record_grace_done(net, nn->boot_time);
|
||||
locks_end_grace(&nn->nfsd4_manager);
|
||||
/*
|
||||
* Now that every NFSv4 client has had the chance to recover and
|
||||
* to see the (possibly new, possibly shorter) lease time, we
|
||||
@ -3149,7 +3157,7 @@ nfs4_laundromat(void)
|
||||
nfs4_lock_state();
|
||||
|
||||
dprintk("NFSD: laundromat service - starting\n");
|
||||
nfsd4_end_grace();
|
||||
nfsd4_end_grace(&init_net);
|
||||
INIT_LIST_HEAD(&reaplist);
|
||||
spin_lock(&client_lock);
|
||||
list_for_each_safe(pos, next, &client_lru) {
|
||||
@ -3231,9 +3239,9 @@ static inline __be32 nfs4_check_fh(struct svc_fh *fhp, struct nfs4_ol_stateid *s
|
||||
}
|
||||
|
||||
static int
|
||||
STALE_STATEID(stateid_t *stateid)
|
||||
STALE_STATEID(stateid_t *stateid, struct nfsd_net *nn)
|
||||
{
|
||||
if (stateid->si_opaque.so_clid.cl_boot == boot_time)
|
||||
if (stateid->si_opaque.so_clid.cl_boot == nn->boot_time)
|
||||
return 0;
|
||||
dprintk("NFSD: stale stateid " STATEID_FMT "!\n",
|
||||
STATEID_VAL(stateid));
|
||||
@ -3273,11 +3281,11 @@ out:
|
||||
}
|
||||
|
||||
static inline __be32
|
||||
check_special_stateids(svc_fh *current_fh, stateid_t *stateid, int flags)
|
||||
check_special_stateids(struct net *net, svc_fh *current_fh, stateid_t *stateid, int flags)
|
||||
{
|
||||
if (ONE_STATEID(stateid) && (flags & RD_STATE))
|
||||
return nfs_ok;
|
||||
else if (locks_in_grace()) {
|
||||
else if (locks_in_grace(net)) {
|
||||
/* Answer in remaining cases depends on existence of
|
||||
* conflicting state; so we must wait out the grace period. */
|
||||
return nfserr_grace;
|
||||
@ -3294,9 +3302,9 @@ check_special_stateids(svc_fh *current_fh, stateid_t *stateid, int flags)
|
||||
* that are not able to provide mandatory locking.
|
||||
*/
|
||||
static inline int
|
||||
grace_disallows_io(struct inode *inode)
|
||||
grace_disallows_io(struct net *net, struct inode *inode)
|
||||
{
|
||||
return locks_in_grace() && mandatory_lock(inode);
|
||||
return locks_in_grace(net) && mandatory_lock(inode);
|
||||
}
|
||||
|
||||
/* Returns true iff a is later than b: */
|
||||
@ -3333,18 +3341,26 @@ static __be32 check_stateid_generation(stateid_t *in, stateid_t *ref, bool has_s
|
||||
return nfserr_old_stateid;
|
||||
}
|
||||
|
||||
__be32 nfs4_validate_stateid(struct nfs4_client *cl, stateid_t *stateid)
|
||||
static __be32 nfsd4_validate_stateid(struct nfs4_client *cl, stateid_t *stateid)
|
||||
{
|
||||
struct nfs4_stid *s;
|
||||
struct nfs4_ol_stateid *ols;
|
||||
__be32 status;
|
||||
|
||||
if (STALE_STATEID(stateid))
|
||||
return nfserr_stale_stateid;
|
||||
|
||||
if (ZERO_STATEID(stateid) || ONE_STATEID(stateid))
|
||||
return nfserr_bad_stateid;
|
||||
/* Client debugging aid. */
|
||||
if (!same_clid(&stateid->si_opaque.so_clid, &cl->cl_clientid)) {
|
||||
char addr_str[INET6_ADDRSTRLEN];
|
||||
rpc_ntop((struct sockaddr *)&cl->cl_addr, addr_str,
|
||||
sizeof(addr_str));
|
||||
pr_warn_ratelimited("NFSD: client %s testing state ID "
|
||||
"with incorrect client ID\n", addr_str);
|
||||
return nfserr_bad_stateid;
|
||||
}
|
||||
s = find_stateid(cl, stateid);
|
||||
if (!s)
|
||||
return nfserr_stale_stateid;
|
||||
return nfserr_bad_stateid;
|
||||
status = check_stateid_generation(stateid, &s->sc_stateid, 1);
|
||||
if (status)
|
||||
return status;
|
||||
@ -3360,10 +3376,11 @@ __be32 nfs4_validate_stateid(struct nfs4_client *cl, stateid_t *stateid)
|
||||
static __be32 nfsd4_lookup_stateid(stateid_t *stateid, unsigned char typemask, struct nfs4_stid **s)
|
||||
{
|
||||
struct nfs4_client *cl;
|
||||
struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
|
||||
|
||||
if (ZERO_STATEID(stateid) || ONE_STATEID(stateid))
|
||||
return nfserr_bad_stateid;
|
||||
if (STALE_STATEID(stateid))
|
||||
if (STALE_STATEID(stateid, nn))
|
||||
return nfserr_stale_stateid;
|
||||
cl = find_confirmed_client(&stateid->si_opaque.so_clid);
|
||||
if (!cl)
|
||||
@ -3379,7 +3396,7 @@ static __be32 nfsd4_lookup_stateid(stateid_t *stateid, unsigned char typemask, s
|
||||
* Checks for stateid operations
|
||||
*/
|
||||
__be32
|
||||
nfs4_preprocess_stateid_op(struct nfsd4_compound_state *cstate,
|
||||
nfs4_preprocess_stateid_op(struct net *net, struct nfsd4_compound_state *cstate,
|
||||
stateid_t *stateid, int flags, struct file **filpp)
|
||||
{
|
||||
struct nfs4_stid *s;
|
||||
@ -3392,11 +3409,11 @@ nfs4_preprocess_stateid_op(struct nfsd4_compound_state *cstate,
|
||||
if (filpp)
|
||||
*filpp = NULL;
|
||||
|
||||
if (grace_disallows_io(ino))
|
||||
if (grace_disallows_io(net, ino))
|
||||
return nfserr_grace;
|
||||
|
||||
if (ZERO_STATEID(stateid) || ONE_STATEID(stateid))
|
||||
return check_special_stateids(current_fh, stateid, flags);
|
||||
return check_special_stateids(net, current_fh, stateid, flags);
|
||||
|
||||
status = nfsd4_lookup_stateid(stateid, NFS4_DELEG_STID|NFS4_OPEN_STID|NFS4_LOCK_STID, &s);
|
||||
if (status)
|
||||
@ -3463,7 +3480,8 @@ nfsd4_test_stateid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||
|
||||
nfs4_lock_state();
|
||||
list_for_each_entry(stateid, &test_stateid->ts_stateid_list, ts_id_list)
|
||||
stateid->ts_id_status = nfs4_validate_stateid(cl, &stateid->ts_id_stateid);
|
||||
stateid->ts_id_status =
|
||||
nfsd4_validate_stateid(cl, &stateid->ts_id_stateid);
|
||||
nfs4_unlock_state();
|
||||
|
||||
return nfs_ok;
|
||||
@ -3750,12 +3768,19 @@ nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||
nfsd4_close_open_stateid(stp);
|
||||
oo->oo_last_closed_stid = stp;
|
||||
|
||||
/* place unused nfs4_stateowners on so_close_lru list to be
|
||||
* released by the laundromat service after the lease period
|
||||
* to enable us to handle CLOSE replay
|
||||
*/
|
||||
if (list_empty(&oo->oo_owner.so_stateids))
|
||||
move_to_close_lru(oo);
|
||||
if (list_empty(&oo->oo_owner.so_stateids)) {
|
||||
if (cstate->minorversion) {
|
||||
release_openowner(oo);
|
||||
cstate->replay_owner = NULL;
|
||||
} else {
|
||||
/*
|
||||
* In the 4.0 case we need to keep the owners around a
|
||||
* little while to handle CLOSE replay.
|
||||
*/
|
||||
if (list_empty(&oo->oo_owner.so_stateids))
|
||||
move_to_close_lru(oo);
|
||||
}
|
||||
}
|
||||
out:
|
||||
if (!cstate->replay_owner)
|
||||
nfs4_unlock_state();
|
||||
@ -4027,6 +4052,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||
bool new_state = false;
|
||||
int lkflg;
|
||||
int err;
|
||||
struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
|
||||
|
||||
dprintk("NFSD: nfsd4_lock: start=%Ld length=%Ld\n",
|
||||
(long long) lock->lk_offset,
|
||||
@ -4044,11 +4070,6 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||
nfs4_lock_state();
|
||||
|
||||
if (lock->lk_is_new) {
|
||||
/*
|
||||
* Client indicates that this is a new lockowner.
|
||||
* Use open owner and open stateid to create lock owner and
|
||||
* lock stateid.
|
||||
*/
|
||||
struct nfs4_ol_stateid *open_stp = NULL;
|
||||
|
||||
if (nfsd4_has_session(cstate))
|
||||
@ -4058,7 +4079,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||
sizeof(clientid_t));
|
||||
|
||||
status = nfserr_stale_clientid;
|
||||
if (STALE_CLIENTID(&lock->lk_new_clientid))
|
||||
if (STALE_CLIENTID(&lock->lk_new_clientid, nn))
|
||||
goto out;
|
||||
|
||||
/* validate and update open stateid and open seqid */
|
||||
@ -4075,17 +4096,13 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||
goto out;
|
||||
status = lookup_or_create_lock_state(cstate, open_stp, lock,
|
||||
&lock_stp, &new_state);
|
||||
if (status)
|
||||
goto out;
|
||||
} else {
|
||||
/* lock (lock owner + lock stateid) already exists */
|
||||
} else
|
||||
status = nfs4_preprocess_seqid_op(cstate,
|
||||
lock->lk_old_lock_seqid,
|
||||
&lock->lk_old_lock_stateid,
|
||||
NFS4_LOCK_STID, &lock_stp);
|
||||
if (status)
|
||||
goto out;
|
||||
}
|
||||
if (status)
|
||||
goto out;
|
||||
lock_sop = lockowner(lock_stp->st_stateowner);
|
||||
|
||||
lkflg = setlkflg(lock->lk_type);
|
||||
@ -4094,10 +4111,10 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||
goto out;
|
||||
|
||||
status = nfserr_grace;
|
||||
if (locks_in_grace() && !lock->lk_reclaim)
|
||||
if (locks_in_grace(SVC_NET(rqstp)) && !lock->lk_reclaim)
|
||||
goto out;
|
||||
status = nfserr_no_grace;
|
||||
if (!locks_in_grace() && lock->lk_reclaim)
|
||||
if (!locks_in_grace(SVC_NET(rqstp)) && lock->lk_reclaim)
|
||||
goto out;
|
||||
|
||||
locks_init_lock(&file_lock);
|
||||
@ -4196,8 +4213,9 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||
struct file_lock file_lock;
|
||||
struct nfs4_lockowner *lo;
|
||||
__be32 status;
|
||||
struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
|
||||
|
||||
if (locks_in_grace())
|
||||
if (locks_in_grace(SVC_NET(rqstp)))
|
||||
return nfserr_grace;
|
||||
|
||||
if (check_lock_length(lockt->lt_offset, lockt->lt_length))
|
||||
@ -4206,7 +4224,7 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
||||
nfs4_lock_state();
|
||||
|
||||
status = nfserr_stale_clientid;
|
||||
if (!nfsd4_has_session(cstate) && STALE_CLIENTID(&lockt->lt_clientid))
|
||||
if (!nfsd4_has_session(cstate) && STALE_CLIENTID(&lockt->lt_clientid, nn))
|
||||
goto out;
|
||||
|
||||
if ((status = fh_verify(rqstp, &cstate->current_fh, S_IFREG, 0)))
|
||||
@ -4355,6 +4373,7 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp,
|
||||
struct list_head matches;
|
||||
unsigned int hashval = ownerstr_hashval(clid->cl_id, owner);
|
||||
__be32 status;
|
||||
struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id);
|
||||
|
||||
dprintk("nfsd4_release_lockowner clientid: (%08x/%08x):\n",
|
||||
clid->cl_boot, clid->cl_id);
|
||||
@ -4362,7 +4381,7 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp,
|
||||
/* XXX check for lease expiration */
|
||||
|
||||
status = nfserr_stale_clientid;
|
||||
if (STALE_CLIENTID(clid))
|
||||
if (STALE_CLIENTID(clid, nn))
|
||||
return status;
|
||||
|
||||
nfs4_lock_state();
|
||||
@ -4564,7 +4583,7 @@ void nfsd_forget_openowners(u64 num)
|
||||
printk(KERN_INFO "NFSD: Forgot %d open owners", count);
|
||||
}
|
||||
|
||||
int nfsd_process_n_delegations(u64 num, void (*deleg_func)(struct nfs4_delegation *))
|
||||
int nfsd_process_n_delegations(u64 num, struct list_head *list)
|
||||
{
|
||||
int i, count = 0;
|
||||
struct nfs4_file *fp, *fnext;
|
||||
@ -4573,7 +4592,7 @@ int nfsd_process_n_delegations(u64 num, void (*deleg_func)(struct nfs4_delegatio
|
||||
for (i = 0; i < FILE_HASH_SIZE; i++) {
|
||||
list_for_each_entry_safe(fp, fnext, &file_hashtbl[i], fi_hash) {
|
||||
list_for_each_entry_safe(dp, dnext, &fp->fi_delegations, dl_perfile) {
|
||||
deleg_func(dp);
|
||||
list_move(&dp->dl_recall_lru, list);
|
||||
if (++count == num)
|
||||
return count;
|
||||
}
|
||||
@ -4586,9 +4605,16 @@ int nfsd_process_n_delegations(u64 num, void (*deleg_func)(struct nfs4_delegatio
|
||||
void nfsd_forget_delegations(u64 num)
|
||||
{
|
||||
unsigned int count;
|
||||
LIST_HEAD(victims);
|
||||
struct nfs4_delegation *dp, *dnext;
|
||||
|
||||
spin_lock(&recall_lock);
|
||||
count = nfsd_process_n_delegations(num, &victims);
|
||||
spin_unlock(&recall_lock);
|
||||
|
||||
nfs4_lock_state();
|
||||
count = nfsd_process_n_delegations(num, unhash_delegation);
|
||||
list_for_each_entry_safe(dp, dnext, &victims, dl_recall_lru)
|
||||
unhash_delegation(dp);
|
||||
nfs4_unlock_state();
|
||||
|
||||
printk(KERN_INFO "NFSD: Forgot %d delegations", count);
|
||||
@ -4597,12 +4623,16 @@ void nfsd_forget_delegations(u64 num)
|
||||
void nfsd_recall_delegations(u64 num)
|
||||
{
|
||||
unsigned int count;
|
||||
LIST_HEAD(victims);
|
||||
struct nfs4_delegation *dp, *dnext;
|
||||
|
||||
nfs4_lock_state();
|
||||
spin_lock(&recall_lock);
|
||||
count = nfsd_process_n_delegations(num, nfsd_break_one_deleg);
|
||||
count = nfsd_process_n_delegations(num, &victims);
|
||||
list_for_each_entry_safe(dp, dnext, &victims, dl_recall_lru) {
|
||||
list_del(&dp->dl_recall_lru);
|
||||
nfsd_break_one_deleg(dp);
|
||||
}
|
||||
spin_unlock(&recall_lock);
|
||||
nfs4_unlock_state();
|
||||
|
||||
printk(KERN_INFO "NFSD: Recalled %d delegations", count);
|
||||
}
|
||||
@ -4665,6 +4695,8 @@ set_max_delegations(void)
|
||||
int
|
||||
nfs4_state_start(void)
|
||||
{
|
||||
struct net *net = &init_net;
|
||||
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
|
||||
int ret;
|
||||
|
||||
/*
|
||||
@ -4674,11 +4706,11 @@ nfs4_state_start(void)
|
||||
* to that instead and then do most of the rest of this on a per-net
|
||||
* basis.
|
||||
*/
|
||||
get_net(&init_net);
|
||||
nfsd4_client_tracking_init(&init_net);
|
||||
boot_time = get_seconds();
|
||||
locks_start_grace(&nfsd4_manager);
|
||||
grace_ended = false;
|
||||
get_net(net);
|
||||
nfsd4_client_tracking_init(net);
|
||||
nn->boot_time = get_seconds();
|
||||
locks_start_grace(net, &nn->nfsd4_manager);
|
||||
nn->grace_ended = false;
|
||||
printk(KERN_INFO "NFSD: starting %ld-second grace period\n",
|
||||
nfsd4_grace);
|
||||
ret = set_callback_cred();
|
||||
@ -4700,8 +4732,8 @@ nfs4_state_start(void)
|
||||
out_free_laundry:
|
||||
destroy_workqueue(laundry_wq);
|
||||
out_recovery:
|
||||
nfsd4_client_tracking_exit(&init_net);
|
||||
put_net(&init_net);
|
||||
nfsd4_client_tracking_exit(net);
|
||||
put_net(net);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -4742,9 +4774,12 @@ __nfs4_state_shutdown(void)
|
||||
void
|
||||
nfs4_state_shutdown(void)
|
||||
{
|
||||
struct net *net = &init_net;
|
||||
struct nfsd_net *nn = net_generic(net, nfsd_net_id);
|
||||
|
||||
cancel_delayed_work_sync(&laundromat_work);
|
||||
destroy_workqueue(laundry_wq);
|
||||
locks_end_grace(&nfsd4_manager);
|
||||
locks_end_grace(&nn->nfsd4_manager);
|
||||
nfs4_lock_state();
|
||||
__nfs4_state_shutdown();
|
||||
nfs4_unlock_state();
|
||||
|
@ -2259,7 +2259,7 @@ out_acl:
|
||||
if (bmval0 & FATTR4_WORD0_CASE_INSENSITIVE) {
|
||||
if ((buflen -= 4) < 0)
|
||||
goto out_resource;
|
||||
WRITE32(1);
|
||||
WRITE32(0);
|
||||
}
|
||||
if (bmval0 & FATTR4_WORD0_CASE_PRESERVING) {
|
||||
if ((buflen -= 4) < 0)
|
||||
|
@ -673,9 +673,7 @@ static ssize_t __write_ports_addfd(char *buf)
|
||||
|
||||
err = svc_addsock(nfsd_serv, fd, buf, SIMPLE_TRANSACTION_LIMIT);
|
||||
if (err < 0) {
|
||||
if (nfsd_serv->sv_nrthreads == 1)
|
||||
svc_shutdown_net(nfsd_serv, net);
|
||||
svc_destroy(nfsd_serv);
|
||||
nfsd_destroy(net);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -744,9 +742,7 @@ out_close:
|
||||
svc_xprt_put(xprt);
|
||||
}
|
||||
out_err:
|
||||
if (nfsd_serv->sv_nrthreads == 1)
|
||||
svc_shutdown_net(nfsd_serv, net);
|
||||
svc_destroy(nfsd_serv);
|
||||
nfsd_destroy(net);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -72,6 +72,19 @@ int nfsd_nrthreads(void);
|
||||
int nfsd_nrpools(void);
|
||||
int nfsd_get_nrthreads(int n, int *);
|
||||
int nfsd_set_nrthreads(int n, int *);
|
||||
int nfsd_pool_stats_open(struct inode *, struct file *);
|
||||
int nfsd_pool_stats_release(struct inode *, struct file *);
|
||||
|
||||
static inline void nfsd_destroy(struct net *net)
|
||||
{
|
||||
int destroy = (nfsd_serv->sv_nrthreads == 1);
|
||||
|
||||
if (destroy)
|
||||
svc_shutdown_net(nfsd_serv, net);
|
||||
svc_destroy(nfsd_serv);
|
||||
if (destroy)
|
||||
nfsd_serv = NULL;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL)
|
||||
#ifdef CONFIG_NFSD_V2_ACL
|
||||
|
@ -254,8 +254,6 @@ static void nfsd_shutdown(void)
|
||||
|
||||
static void nfsd_last_thread(struct svc_serv *serv, struct net *net)
|
||||
{
|
||||
/* When last nfsd thread exits we need to do some clean-up */
|
||||
nfsd_serv = NULL;
|
||||
nfsd_shutdown();
|
||||
|
||||
svc_rpcb_cleanup(serv, net);
|
||||
@ -332,6 +330,7 @@ static int nfsd_get_default_max_blksize(void)
|
||||
int nfsd_create_serv(void)
|
||||
{
|
||||
int error;
|
||||
struct net *net = current->nsproxy->net_ns;
|
||||
|
||||
WARN_ON(!mutex_is_locked(&nfsd_mutex));
|
||||
if (nfsd_serv) {
|
||||
@ -346,7 +345,7 @@ int nfsd_create_serv(void)
|
||||
if (nfsd_serv == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
error = svc_bind(nfsd_serv, current->nsproxy->net_ns);
|
||||
error = svc_bind(nfsd_serv, net);
|
||||
if (error < 0) {
|
||||
svc_destroy(nfsd_serv);
|
||||
return error;
|
||||
@ -427,11 +426,7 @@ int nfsd_set_nrthreads(int n, int *nthreads)
|
||||
if (err)
|
||||
break;
|
||||
}
|
||||
|
||||
if (nfsd_serv->sv_nrthreads == 1)
|
||||
svc_shutdown_net(nfsd_serv, net);
|
||||
svc_destroy(nfsd_serv);
|
||||
|
||||
nfsd_destroy(net);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -478,9 +473,7 @@ out_shutdown:
|
||||
if (error < 0 && !nfsd_up_before)
|
||||
nfsd_shutdown();
|
||||
out_destroy:
|
||||
if (nfsd_serv->sv_nrthreads == 1)
|
||||
svc_shutdown_net(nfsd_serv, net);
|
||||
svc_destroy(nfsd_serv); /* Release server */
|
||||
nfsd_destroy(net); /* Release server */
|
||||
out:
|
||||
mutex_unlock(&nfsd_mutex);
|
||||
return error;
|
||||
@ -563,12 +556,13 @@ nfsd(void *vrqstp)
|
||||
nfsdstats.th_cnt --;
|
||||
|
||||
out:
|
||||
if (rqstp->rq_server->sv_nrthreads == 1)
|
||||
svc_shutdown_net(rqstp->rq_server, &init_net);
|
||||
rqstp->rq_server = NULL;
|
||||
|
||||
/* Release the thread */
|
||||
svc_exit_thread(rqstp);
|
||||
|
||||
nfsd_destroy(&init_net);
|
||||
|
||||
/* Release module */
|
||||
mutex_unlock(&nfsd_mutex);
|
||||
module_put_and_exit(0);
|
||||
@ -682,9 +676,7 @@ int nfsd_pool_stats_release(struct inode *inode, struct file *file)
|
||||
|
||||
mutex_lock(&nfsd_mutex);
|
||||
/* this function really, really should have been called svc_put() */
|
||||
if (nfsd_serv->sv_nrthreads == 1)
|
||||
svc_shutdown_net(nfsd_serv, net);
|
||||
svc_destroy(nfsd_serv);
|
||||
nfsd_destroy(net);
|
||||
mutex_unlock(&nfsd_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
@ -450,8 +450,10 @@ static inline struct nfs4_ol_stateid *openlockstateid(struct nfs4_stid *s)
|
||||
#define WR_STATE 0x00000020
|
||||
|
||||
struct nfsd4_compound_state;
|
||||
struct nfsd_net;
|
||||
|
||||
extern __be32 nfs4_preprocess_stateid_op(struct nfsd4_compound_state *cstate,
|
||||
extern __be32 nfs4_preprocess_stateid_op(struct net *net,
|
||||
struct nfsd4_compound_state *cstate,
|
||||
stateid_t *stateid, int flags, struct file **filp);
|
||||
extern void nfs4_lock_state(void);
|
||||
extern void nfs4_unlock_state(void);
|
||||
@ -475,7 +477,6 @@ extern __be32 nfs4_make_rec_clidname(char *clidname, struct xdr_netobj *clname);
|
||||
extern int nfs4_client_to_reclaim(const char *name);
|
||||
extern int nfs4_has_reclaimed_state(const char *name, bool use_exchange_id);
|
||||
extern void release_session_client(struct nfsd4_session *);
|
||||
extern __be32 nfs4_validate_stateid(struct nfs4_client *, stateid_t *);
|
||||
extern void nfsd4_purge_closed_stateid(struct nfs4_stateowner *);
|
||||
|
||||
/* nfs4recover operations */
|
||||
|
@ -757,8 +757,16 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type,
|
||||
* If we get here, then the client has already done an "open",
|
||||
* and (hopefully) checked permission - so allow OWNER_OVERRIDE
|
||||
* in case a chmod has now revoked permission.
|
||||
*
|
||||
* Arguably we should also allow the owner override for
|
||||
* directories, but we never have and it doesn't seem to have
|
||||
* caused anyone a problem. If we were to change this, note
|
||||
* also that our filldir callbacks would need a variant of
|
||||
* lookup_one_len that doesn't check permissions.
|
||||
*/
|
||||
err = fh_verify(rqstp, fhp, type, may_flags | NFSD_MAY_OWNER_OVERRIDE);
|
||||
if (type == S_IFREG)
|
||||
may_flags |= NFSD_MAY_OWNER_OVERRIDE;
|
||||
err = fh_verify(rqstp, fhp, type, may_flags);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
|
@ -1163,9 +1163,10 @@ struct lock_manager {
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
void locks_start_grace(struct lock_manager *);
|
||||
struct net;
|
||||
void locks_start_grace(struct net *, struct lock_manager *);
|
||||
void locks_end_grace(struct lock_manager *);
|
||||
int locks_in_grace(void);
|
||||
int locks_in_grace(struct net *);
|
||||
|
||||
/* that will die - we need it for nfs_lock_info */
|
||||
#include <linux/nfs_fs_i.h>
|
||||
|
@ -262,11 +262,11 @@ typedef int (*nlm_host_match_fn_t)(void *cur, struct nlm_host *ref);
|
||||
__be32 nlmsvc_lock(struct svc_rqst *, struct nlm_file *,
|
||||
struct nlm_host *, struct nlm_lock *, int,
|
||||
struct nlm_cookie *, int);
|
||||
__be32 nlmsvc_unlock(struct nlm_file *, struct nlm_lock *);
|
||||
__be32 nlmsvc_unlock(struct net *net, struct nlm_file *, struct nlm_lock *);
|
||||
__be32 nlmsvc_testlock(struct svc_rqst *, struct nlm_file *,
|
||||
struct nlm_host *, struct nlm_lock *,
|
||||
struct nlm_lock *, struct nlm_cookie *);
|
||||
__be32 nlmsvc_cancel_blocked(struct nlm_file *, struct nlm_lock *);
|
||||
__be32 nlmsvc_cancel_blocked(struct net *net, struct nlm_file *, struct nlm_lock *);
|
||||
unsigned long nlmsvc_retry_blocked(void);
|
||||
void nlmsvc_traverse_blocks(struct nlm_host *, struct nlm_file *,
|
||||
nlm_host_match_fn_t match);
|
||||
@ -279,7 +279,7 @@ void nlmsvc_release_call(struct nlm_rqst *);
|
||||
__be32 nlm_lookup_file(struct svc_rqst *, struct nlm_file **,
|
||||
struct nfs_fh *);
|
||||
void nlm_release_file(struct nlm_file *);
|
||||
void nlmsvc_mark_resources(void);
|
||||
void nlmsvc_mark_resources(struct net *);
|
||||
void nlmsvc_free_host_resources(struct nlm_host *);
|
||||
void nlmsvc_invalidate_all(void);
|
||||
|
||||
|
@ -217,14 +217,32 @@ extern int qword_get(char **bpp, char *dest, int bufsize);
|
||||
static inline int get_int(char **bpp, int *anint)
|
||||
{
|
||||
char buf[50];
|
||||
char *ep;
|
||||
int rv;
|
||||
int len = qword_get(bpp, buf, 50);
|
||||
if (len < 0) return -EINVAL;
|
||||
if (len ==0) return -ENOENT;
|
||||
rv = simple_strtol(buf, &ep, 0);
|
||||
if (*ep) return -EINVAL;
|
||||
*anint = rv;
|
||||
int len = qword_get(bpp, buf, sizeof(buf));
|
||||
|
||||
if (len < 0)
|
||||
return -EINVAL;
|
||||
if (len == 0)
|
||||
return -ENOENT;
|
||||
|
||||
if (kstrtoint(buf, 0, anint))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int get_uint(char **bpp, unsigned int *anint)
|
||||
{
|
||||
char buf[50];
|
||||
int len = qword_get(bpp, buf, sizeof(buf));
|
||||
|
||||
if (len < 0)
|
||||
return -EINVAL;
|
||||
if (len == 0)
|
||||
return -ENOENT;
|
||||
|
||||
if (kstrtouint(buf, 0, anint))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -278,6 +278,8 @@ struct svc_rqst {
|
||||
struct task_struct *rq_task; /* service thread */
|
||||
};
|
||||
|
||||
#define SVC_NET(svc_rqst) (svc_rqst->rq_xprt->xpt_net)
|
||||
|
||||
/*
|
||||
* Rigorous type checking on sockaddr type conversions
|
||||
*/
|
||||
|
@ -1349,8 +1349,11 @@ static int c_show(struct seq_file *m, void *p)
|
||||
if (cache_check(cd, cp, NULL))
|
||||
/* cache_check does a cache_put on failure */
|
||||
seq_printf(m, "# ");
|
||||
else
|
||||
else {
|
||||
if (cache_is_expired(cd, cp))
|
||||
seq_printf(m, "# ");
|
||||
cache_put(cp, cd);
|
||||
}
|
||||
|
||||
return cd->cache_show(m, cd, cp);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user