]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge branch 'nfsd-next' of git://linux-nfs.org/~bfields/linux
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 31 Jul 2012 21:42:28 +0000 (14:42 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 31 Jul 2012 21:42:28 +0000 (14:42 -0700)
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
  ...

27 files changed:
fs/lockd/grace.c
fs/lockd/host.c
fs/lockd/netns.h
fs/lockd/svc.c
fs/lockd/svc4proc.c
fs/lockd/svclock.c
fs/lockd/svcproc.c
fs/lockd/svcsubs.c
fs/locks.c
fs/nfs/callback_xdr.c
fs/nfsd/export.c
fs/nfsd/netns.h
fs/nfsd/nfs4callback.c
fs/nfsd/nfs4idmap.c
fs/nfsd/nfs4proc.c
fs/nfsd/nfs4state.c
fs/nfsd/nfs4xdr.c
fs/nfsd/nfsctl.c
fs/nfsd/nfsd.h
fs/nfsd/nfssvc.c
fs/nfsd/state.h
fs/nfsd/vfs.c
include/linux/fs.h
include/linux/lockd/lockd.h
include/linux/sunrpc/cache.h
include/linux/sunrpc/svc.h
net/sunrpc/cache.c

index 183cc1f0af1cf6be225053e2032f47a063be25d3..6d1ee7204c889b347897b50590b620a658920020 100644 (file)
@@ -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);
index eb75ca7c2d6edd4782ad9f025b6115c78b3c9307..f9b22e58f78f053a05fffa2ec11feaa32bc2518a 100644 (file)
@@ -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;
+       }
 }
index ce227e0fbc5c192b0ccaaff7cc1640d33379adc1..4eee248ba96e441eb54e460130d3dde2f20d6ca1 100644 (file)
@@ -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;
index 80938fda67e0e6fde67999d3556820b87b6acd33..31a63f87b80602346cc78cfead614d35f620c9cd 100644 (file)
@@ -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);
 
-static DECLARE_DELAYED_WORK(grace_period_end, grace_ender);
+       locks_end_grace(&ln->lockd_manager);
+}
 
-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;
 }
 
index 9a41fdc19511ffb85cccab8fef5d42096bd08dca..4a43d253c045d0c50f1ddf63eabffc133774c314 100644 (file)
@@ -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;
        }
index e46353f41a4202ec2138998ab5449b833dc139db..afe4488c33d886a3c1bf58c1b827c05f09c3aa77 100644 (file)
@@ -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);
index d27aab11f32414ae165cec40083ef20f08de0466..de8f2caa22359f8fa11dbd178fc1e78c5f1cc7ef 100644 (file)
@@ -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;
        }
index 2240d384d7877042c44ba134489b431e9de10118..0deb5f6c9dd47170ee2b19390362f2549ab7cac9 100644 (file)
@@ -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);
 }
 
 /*
index 82c353304f9eeccab27b01b86379441df323deeb..cdcf219a7391a0c5097ad0e74fb3a5ea6debdc92 100644 (file)
@@ -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;
 }
 
index e64b01d2a338274a459bc9c56c60dacf282aad84..742ff4ffced78fe9071da9c15ee22f458bfde3ca 100644 (file)
@@ -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;
        }
index ba233499b9a5fc1b374bc7d79ad8f636f01135b0..a3946cf13fc8373d6234c64d4316505364914ca3 100644 (file)
@@ -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)
index 39365636b244fbfc7aaac3a794f83f87d7ea69a6..65c2431ea32fa6638cc34b8f240b351328bad751 100644 (file)
@@ -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;
index a5fd6b982f277ce648bbd528947964ea2ef63c73..cbaf4f8bb7b712be7e92db2a7bf102c1f8c2dc6f 100644 (file)
@@ -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);
index dae36f1dee95e68defce943bedf01efc46d61a54..fdc91a6fc9c4e3d50bea67386c463bd50d8c4c12 100644 (file)
@@ -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);
index 987e719fbae8c64f2776f914e7f4104ee04be492..c9c1c0a254170ebc1de0bc70cdcdcce6c8ff5b6d 100644 (file)
@@ -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();
index 94effd5bc4a107086ef53515ac2bb9dc39950b88..cc894eda385a48d0ecb98f2687ef566815648d75 100644 (file)
 #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();
index 4949667c84ea0c3d687a46faf0a455c410c39b6f..6322df36031f34c62f273f2d36630a472e991416 100644 (file)
@@ -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)
index c55298ed5772577e5afe3bd613c3e5a0df3b69dd..fa49cff5ee651b9aa0b16f9cb43804f616aedc4e 100644 (file)
@@ -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;
 }
 
index 1671429ffa66fa1db509fbb212a09ad80d49efa8..2244222368ab29cf4681d0d94012055bc5861f02 100644 (file)
@@ -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
index ee709fc8f58bc0b62a3f7ca64104630fe803b6d0..240473cb708ff8a726d2b881d9d7ec2b42339653 100644 (file)
@@ -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;
 }
index 849091e16ea6afd43e4ddd2dbd17962fdd87ad85..e6173147f9821c816527e0bde05289d392374af7 100644 (file)
@@ -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 */
index 4700a0a929d72baeb0c86024a1c5051e6d19cab5..702f64e820c301992afda8adecf6d06dc4746c22 100644 (file)
@@ -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;
 
index 8fabb037a48db40e8a490fc74c15ce907ad9059a..b178f9e91e23c473e39881c33ee3a36544cefa90 100644 (file)
@@ -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>
index f04ce6ac6d04fd84f65c533cb34b5748d2d6665f..f5a051a79273c7f3fcdb1a18f4c9e2522e68cc85 100644 (file)
@@ -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);
 
index f5fd6160dbca396835773609586e65071f9c78ab..f792794f66341a5888136e6697322f445ba62197 100644 (file)
@@ -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;
 }
 
index 40e0a273faea3c07470e19fd23673fda89543f9b..d83db800fe02eeabbfc96f76e56a2662cce7c0cf 100644 (file)
@@ -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
  */
index 47ad2666fdf6566f170b49e97097a285da29a231..2afd2a84dc35aa5cab139b38f82f5c5206e83728 100644 (file)
@@ -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);
 }