diff options
| -rw-r--r-- | fs/lockd/grace.c | 16 | ||||
| -rw-r--r-- | fs/lockd/host.c | 92 | ||||
| -rw-r--r-- | fs/lockd/netns.h | 7 | ||||
| -rw-r--r-- | fs/lockd/svc.c | 43 | ||||
| -rw-r--r-- | fs/lockd/svc4proc.c | 13 | ||||
| -rw-r--r-- | fs/lockd/svclock.c | 16 | ||||
| -rw-r--r-- | fs/lockd/svcproc.c | 15 | ||||
| -rw-r--r-- | fs/lockd/svcsubs.c | 19 | ||||
| -rw-r--r-- | fs/locks.c | 28 | ||||
| -rw-r--r-- | fs/nfs/callback_xdr.c | 4 | ||||
| -rw-r--r-- | fs/nfsd/export.c | 10 | ||||
| -rw-r--r-- | fs/nfsd/netns.h | 4 | ||||
| -rw-r--r-- | fs/nfsd/nfs4callback.c | 1 | ||||
| -rw-r--r-- | fs/nfsd/nfs4idmap.c | 4 | ||||
| -rw-r--r-- | fs/nfsd/nfs4proc.c | 18 | ||||
| -rw-r--r-- | fs/nfsd/nfs4state.c | 201 | ||||
| -rw-r--r-- | fs/nfsd/nfs4xdr.c | 2 | ||||
| -rw-r--r-- | fs/nfsd/nfsctl.c | 8 | ||||
| -rw-r--r-- | fs/nfsd/nfsd.h | 13 | ||||
| -rw-r--r-- | fs/nfsd/nfssvc.c | 24 | ||||
| -rw-r--r-- | fs/nfsd/state.h | 5 | ||||
| -rw-r--r-- | fs/nfsd/vfs.c | 10 | ||||
| -rw-r--r-- | include/linux/fs.h | 5 | ||||
| -rw-r--r-- | include/linux/lockd/lockd.h | 6 | ||||
| -rw-r--r-- | include/linux/sunrpc/cache.h | 34 | ||||
| -rw-r--r-- | include/linux/sunrpc/svc.h | 2 | ||||
| -rw-r--r-- | net/sunrpc/cache.c | 5 |
27 files changed, 368 insertions, 237 deletions
diff --git a/fs/lockd/grace.c b/fs/lockd/grace.c index 183cc1f0af1c..6d1ee7204c88 100644 --- a/fs/lockd/grace.c +++ b/fs/lockd/grace.c | |||
| @@ -4,8 +4,10 @@ | |||
| 4 | 4 | ||
| 5 | #include <linux/module.h> | 5 | #include <linux/module.h> |
| 6 | #include <linux/lockd/bind.h> | 6 | #include <linux/lockd/bind.h> |
| 7 | #include <net/net_namespace.h> | ||
| 8 | |||
| 9 | #include "netns.h" | ||
| 7 | 10 | ||
| 8 | static LIST_HEAD(grace_list); | ||
| 9 | static DEFINE_SPINLOCK(grace_lock); | 11 | static DEFINE_SPINLOCK(grace_lock); |
| 10 | 12 | ||
| 11 | /** | 13 | /** |
| @@ -19,10 +21,12 @@ static DEFINE_SPINLOCK(grace_lock); | |||
| 19 | * | 21 | * |
| 20 | * This function is called to start a grace period. | 22 | * This function is called to start a grace period. |
| 21 | */ | 23 | */ |
| 22 | void locks_start_grace(struct lock_manager *lm) | 24 | void locks_start_grace(struct net *net, struct lock_manager *lm) |
| 23 | { | 25 | { |
| 26 | struct lockd_net *ln = net_generic(net, lockd_net_id); | ||
| 27 | |||
| 24 | spin_lock(&grace_lock); | 28 | spin_lock(&grace_lock); |
| 25 | list_add(&lm->list, &grace_list); | 29 | list_add(&lm->list, &ln->grace_list); |
| 26 | spin_unlock(&grace_lock); | 30 | spin_unlock(&grace_lock); |
| 27 | } | 31 | } |
| 28 | EXPORT_SYMBOL_GPL(locks_start_grace); | 32 | EXPORT_SYMBOL_GPL(locks_start_grace); |
| @@ -52,8 +56,10 @@ EXPORT_SYMBOL_GPL(locks_end_grace); | |||
| 52 | * to answer ordinary lock requests, and when they should accept only | 56 | * to answer ordinary lock requests, and when they should accept only |
| 53 | * lock reclaims. | 57 | * lock reclaims. |
| 54 | */ | 58 | */ |
| 55 | int locks_in_grace(void) | 59 | int locks_in_grace(struct net *net) |
| 56 | { | 60 | { |
| 57 | return !list_empty(&grace_list); | 61 | struct lockd_net *ln = net_generic(net, lockd_net_id); |
| 62 | |||
| 63 | return !list_empty(&ln->grace_list); | ||
| 58 | } | 64 | } |
| 59 | EXPORT_SYMBOL_GPL(locks_in_grace); | 65 | EXPORT_SYMBOL_GPL(locks_in_grace); |
diff --git a/fs/lockd/host.c b/fs/lockd/host.c index eb75ca7c2d6e..f9b22e58f78f 100644 --- a/fs/lockd/host.c +++ b/fs/lockd/host.c | |||
| @@ -21,6 +21,8 @@ | |||
| 21 | 21 | ||
| 22 | #include <net/ipv6.h> | 22 | #include <net/ipv6.h> |
| 23 | 23 | ||
| 24 | #include "netns.h" | ||
| 25 | |||
| 24 | #define NLMDBG_FACILITY NLMDBG_HOSTCACHE | 26 | #define NLMDBG_FACILITY NLMDBG_HOSTCACHE |
| 25 | #define NLM_HOST_NRHASH 32 | 27 | #define NLM_HOST_NRHASH 32 |
| 26 | #define NLM_HOST_REBIND (60 * HZ) | 28 | #define NLM_HOST_REBIND (60 * HZ) |
| @@ -41,11 +43,10 @@ static struct hlist_head nlm_client_hosts[NLM_HOST_NRHASH]; | |||
| 41 | hlist_for_each_entry_safe((host), (pos), (next), \ | 43 | hlist_for_each_entry_safe((host), (pos), (next), \ |
| 42 | (chain), h_hash) | 44 | (chain), h_hash) |
| 43 | 45 | ||
| 44 | static unsigned long next_gc; | ||
| 45 | static unsigned long nrhosts; | 46 | static unsigned long nrhosts; |
| 46 | static DEFINE_MUTEX(nlm_host_mutex); | 47 | static DEFINE_MUTEX(nlm_host_mutex); |
| 47 | 48 | ||
| 48 | static void nlm_gc_hosts(void); | 49 | static void nlm_gc_hosts(struct net *net); |
| 49 | 50 | ||
| 50 | struct nlm_lookup_host_info { | 51 | struct nlm_lookup_host_info { |
| 51 | const int server; /* search for server|client */ | 52 | const int server; /* search for server|client */ |
| @@ -172,6 +173,7 @@ out: | |||
| 172 | static void nlm_destroy_host_locked(struct nlm_host *host) | 173 | static void nlm_destroy_host_locked(struct nlm_host *host) |
| 173 | { | 174 | { |
| 174 | struct rpc_clnt *clnt; | 175 | struct rpc_clnt *clnt; |
| 176 | struct lockd_net *ln = net_generic(host->net, lockd_net_id); | ||
| 175 | 177 | ||
| 176 | dprintk("lockd: destroy host %s\n", host->h_name); | 178 | dprintk("lockd: destroy host %s\n", host->h_name); |
| 177 | 179 | ||
| @@ -188,6 +190,7 @@ static void nlm_destroy_host_locked(struct nlm_host *host) | |||
| 188 | rpc_shutdown_client(clnt); | 190 | rpc_shutdown_client(clnt); |
| 189 | kfree(host); | 191 | kfree(host); |
| 190 | 192 | ||
| 193 | ln->nrhosts--; | ||
| 191 | nrhosts--; | 194 | nrhosts--; |
| 192 | } | 195 | } |
| 193 | 196 | ||
| @@ -228,6 +231,7 @@ struct nlm_host *nlmclnt_lookup_host(const struct sockaddr *sap, | |||
| 228 | struct hlist_node *pos; | 231 | struct hlist_node *pos; |
| 229 | struct nlm_host *host; | 232 | struct nlm_host *host; |
| 230 | struct nsm_handle *nsm = NULL; | 233 | struct nsm_handle *nsm = NULL; |
| 234 | struct lockd_net *ln = net_generic(net, lockd_net_id); | ||
| 231 | 235 | ||
| 232 | dprintk("lockd: %s(host='%s', vers=%u, proto=%s)\n", __func__, | 236 | dprintk("lockd: %s(host='%s', vers=%u, proto=%s)\n", __func__, |
| 233 | (hostname ? hostname : "<none>"), version, | 237 | (hostname ? hostname : "<none>"), version, |
| @@ -262,6 +266,7 @@ struct nlm_host *nlmclnt_lookup_host(const struct sockaddr *sap, | |||
| 262 | goto out; | 266 | goto out; |
| 263 | 267 | ||
| 264 | hlist_add_head(&host->h_hash, chain); | 268 | hlist_add_head(&host->h_hash, chain); |
| 269 | ln->nrhosts++; | ||
| 265 | nrhosts++; | 270 | nrhosts++; |
| 266 | 271 | ||
| 267 | dprintk("lockd: %s created host %s (%s)\n", __func__, | 272 | dprintk("lockd: %s created host %s (%s)\n", __func__, |
| @@ -326,7 +331,7 @@ struct nlm_host *nlmsvc_lookup_host(const struct svc_rqst *rqstp, | |||
| 326 | struct nsm_handle *nsm = NULL; | 331 | struct nsm_handle *nsm = NULL; |
| 327 | struct sockaddr *src_sap = svc_daddr(rqstp); | 332 | struct sockaddr *src_sap = svc_daddr(rqstp); |
| 328 | size_t src_len = rqstp->rq_daddrlen; | 333 | size_t src_len = rqstp->rq_daddrlen; |
| 329 | struct net *net = rqstp->rq_xprt->xpt_net; | 334 | struct net *net = SVC_NET(rqstp); |
| 330 | struct nlm_lookup_host_info ni = { | 335 | struct nlm_lookup_host_info ni = { |
| 331 | .server = 1, | 336 | .server = 1, |
| 332 | .sap = svc_addr(rqstp), | 337 | .sap = svc_addr(rqstp), |
| @@ -337,6 +342,7 @@ struct nlm_host *nlmsvc_lookup_host(const struct svc_rqst *rqstp, | |||
| 337 | .hostname_len = hostname_len, | 342 | .hostname_len = hostname_len, |
| 338 | .net = net, | 343 | .net = net, |
| 339 | }; | 344 | }; |
| 345 | struct lockd_net *ln = net_generic(net, lockd_net_id); | ||
| 340 | 346 | ||
| 341 | dprintk("lockd: %s(host='%*s', vers=%u, proto=%s)\n", __func__, | 347 | dprintk("lockd: %s(host='%*s', vers=%u, proto=%s)\n", __func__, |
| 342 | (int)hostname_len, hostname, rqstp->rq_vers, | 348 | (int)hostname_len, hostname, rqstp->rq_vers, |
| @@ -344,8 +350,8 @@ struct nlm_host *nlmsvc_lookup_host(const struct svc_rqst *rqstp, | |||
| 344 | 350 | ||
| 345 | mutex_lock(&nlm_host_mutex); | 351 | mutex_lock(&nlm_host_mutex); |
| 346 | 352 | ||
| 347 | if (time_after_eq(jiffies, next_gc)) | 353 | if (time_after_eq(jiffies, ln->next_gc)) |
| 348 | nlm_gc_hosts(); | 354 | nlm_gc_hosts(net); |
| 349 | 355 | ||
| 350 | chain = &nlm_server_hosts[nlm_hash_address(ni.sap)]; | 356 | chain = &nlm_server_hosts[nlm_hash_address(ni.sap)]; |
| 351 | hlist_for_each_entry(host, pos, chain, h_hash) { | 357 | hlist_for_each_entry(host, pos, chain, h_hash) { |
| @@ -382,6 +388,7 @@ struct nlm_host *nlmsvc_lookup_host(const struct svc_rqst *rqstp, | |||
| 382 | memcpy(nlm_srcaddr(host), src_sap, src_len); | 388 | memcpy(nlm_srcaddr(host), src_sap, src_len); |
| 383 | host->h_srcaddrlen = src_len; | 389 | host->h_srcaddrlen = src_len; |
| 384 | hlist_add_head(&host->h_hash, chain); | 390 | hlist_add_head(&host->h_hash, chain); |
| 391 | ln->nrhosts++; | ||
| 385 | nrhosts++; | 392 | nrhosts++; |
| 386 | 393 | ||
| 387 | dprintk("lockd: %s created host %s (%s)\n", | 394 | dprintk("lockd: %s created host %s (%s)\n", |
| @@ -565,6 +572,35 @@ void nlm_host_rebooted(const struct nlm_reboot *info) | |||
| 565 | nsm_release(nsm); | 572 | nsm_release(nsm); |
| 566 | } | 573 | } |
| 567 | 574 | ||
| 575 | static void nlm_complain_hosts(struct net *net) | ||
| 576 | { | ||
| 577 | struct hlist_head *chain; | ||
| 578 | struct hlist_node *pos; | ||
| 579 | struct nlm_host *host; | ||
| 580 | |||
| 581 | if (net) { | ||
| 582 | struct lockd_net *ln = net_generic(net, lockd_net_id); | ||
| 583 | |||
| 584 | if (ln->nrhosts == 0) | ||
| 585 | return; | ||
| 586 | printk(KERN_WARNING "lockd: couldn't shutdown host module for net %p!\n", net); | ||
| 587 | dprintk("lockd: %lu hosts left in net %p:\n", ln->nrhosts, net); | ||
| 588 | } else { | ||
| 589 | if (nrhosts == 0) | ||
| 590 | return; | ||
| 591 | printk(KERN_WARNING "lockd: couldn't shutdown host module!\n"); | ||
| 592 | dprintk("lockd: %lu hosts left:\n", nrhosts); | ||
| 593 | } | ||
| 594 | |||
| 595 | for_each_host(host, pos, chain, nlm_server_hosts) { | ||
| 596 | if (net && host->net != net) | ||
| 597 | continue; | ||
| 598 | dprintk(" %s (cnt %d use %d exp %ld net %p)\n", | ||
| 599 | host->h_name, atomic_read(&host->h_count), | ||
| 600 | host->h_inuse, host->h_expires, host->net); | ||
| 601 | } | ||
| 602 | } | ||
| 603 | |||
| 568 | void | 604 | void |
| 569 | nlm_shutdown_hosts_net(struct net *net) | 605 | nlm_shutdown_hosts_net(struct net *net) |
| 570 | { | 606 | { |
| @@ -572,11 +608,10 @@ nlm_shutdown_hosts_net(struct net *net) | |||
| 572 | struct hlist_node *pos; | 608 | struct hlist_node *pos; |
| 573 | struct nlm_host *host; | 609 | struct nlm_host *host; |
| 574 | 610 | ||
| 575 | dprintk("lockd: shutting down host module\n"); | ||
| 576 | mutex_lock(&nlm_host_mutex); | 611 | mutex_lock(&nlm_host_mutex); |
| 577 | 612 | ||
| 578 | /* First, make all hosts eligible for gc */ | 613 | /* First, make all hosts eligible for gc */ |
| 579 | dprintk("lockd: nuking all hosts...\n"); | 614 | dprintk("lockd: nuking all hosts in net %p...\n", net); |
| 580 | for_each_host(host, pos, chain, nlm_server_hosts) { | 615 | for_each_host(host, pos, chain, nlm_server_hosts) { |
| 581 | if (net && host->net != net) | 616 | if (net && host->net != net) |
| 582 | continue; | 617 | continue; |
| @@ -588,8 +623,10 @@ nlm_shutdown_hosts_net(struct net *net) | |||
| 588 | } | 623 | } |
| 589 | 624 | ||
| 590 | /* Then, perform a garbage collection pass */ | 625 | /* Then, perform a garbage collection pass */ |
| 591 | nlm_gc_hosts(); | 626 | nlm_gc_hosts(net); |
| 592 | mutex_unlock(&nlm_host_mutex); | 627 | mutex_unlock(&nlm_host_mutex); |
| 628 | |||
| 629 | nlm_complain_hosts(net); | ||
| 593 | } | 630 | } |
| 594 | 631 | ||
| 595 | /* | 632 | /* |
| @@ -599,22 +636,8 @@ nlm_shutdown_hosts_net(struct net *net) | |||
| 599 | void | 636 | void |
| 600 | nlm_shutdown_hosts(void) | 637 | nlm_shutdown_hosts(void) |
| 601 | { | 638 | { |
| 602 | struct hlist_head *chain; | 639 | dprintk("lockd: shutting down host module\n"); |
| 603 | struct hlist_node *pos; | ||
| 604 | struct nlm_host *host; | ||
| 605 | |||
| 606 | nlm_shutdown_hosts_net(NULL); | 640 | nlm_shutdown_hosts_net(NULL); |
| 607 | |||
| 608 | /* complain if any hosts are left */ | ||
| 609 | if (nrhosts != 0) { | ||
| 610 | printk(KERN_WARNING "lockd: couldn't shutdown host module!\n"); | ||
| 611 | dprintk("lockd: %lu hosts left:\n", nrhosts); | ||
| 612 | for_each_host(host, pos, chain, nlm_server_hosts) { | ||
| 613 | dprintk(" %s (cnt %d use %d exp %ld net %p)\n", | ||
| 614 | host->h_name, atomic_read(&host->h_count), | ||
| 615 | host->h_inuse, host->h_expires, host->net); | ||
| 616 | } | ||
| 617 | } | ||
| 618 | } | 641 | } |
| 619 | 642 | ||
| 620 | /* | 643 | /* |
| @@ -623,30 +646,39 @@ nlm_shutdown_hosts(void) | |||
| 623 | * mark & sweep for resources held by remote clients. | 646 | * mark & sweep for resources held by remote clients. |
| 624 | */ | 647 | */ |
| 625 | static void | 648 | static void |
| 626 | nlm_gc_hosts(void) | 649 | nlm_gc_hosts(struct net *net) |
| 627 | { | 650 | { |
| 628 | struct hlist_head *chain; | 651 | struct hlist_head *chain; |
| 629 | struct hlist_node *pos, *next; | 652 | struct hlist_node *pos, *next; |
| 630 | struct nlm_host *host; | 653 | struct nlm_host *host; |
| 631 | 654 | ||
| 632 | dprintk("lockd: host garbage collection\n"); | 655 | dprintk("lockd: host garbage collection for net %p\n", net); |
| 633 | for_each_host(host, pos, chain, nlm_server_hosts) | 656 | for_each_host(host, pos, chain, nlm_server_hosts) { |
| 657 | if (net && host->net != net) | ||
| 658 | continue; | ||
| 634 | host->h_inuse = 0; | 659 | host->h_inuse = 0; |
| 660 | } | ||
| 635 | 661 | ||
| 636 | /* Mark all hosts that hold locks, blocks or shares */ | 662 | /* Mark all hosts that hold locks, blocks or shares */ |
| 637 | nlmsvc_mark_resources(); | 663 | nlmsvc_mark_resources(net); |
| 638 | 664 | ||
| 639 | for_each_host_safe(host, pos, next, chain, nlm_server_hosts) { | 665 | for_each_host_safe(host, pos, next, chain, nlm_server_hosts) { |
| 666 | if (net && host->net != net) | ||
| 667 | continue; | ||
| 640 | if (atomic_read(&host->h_count) || host->h_inuse | 668 | if (atomic_read(&host->h_count) || host->h_inuse |
| 641 | || time_before(jiffies, host->h_expires)) { | 669 | || time_before(jiffies, host->h_expires)) { |
| 642 | dprintk("nlm_gc_hosts skipping %s " | 670 | dprintk("nlm_gc_hosts skipping %s " |
| 643 | "(cnt %d use %d exp %ld)\n", | 671 | "(cnt %d use %d exp %ld net %p)\n", |
| 644 | host->h_name, atomic_read(&host->h_count), | 672 | host->h_name, atomic_read(&host->h_count), |
| 645 | host->h_inuse, host->h_expires); | 673 | host->h_inuse, host->h_expires, host->net); |
| 646 | continue; | 674 | continue; |
| 647 | } | 675 | } |
| 648 | nlm_destroy_host_locked(host); | 676 | nlm_destroy_host_locked(host); |
| 649 | } | 677 | } |
| 650 | 678 | ||
| 651 | next_gc = jiffies + NLM_HOST_COLLECT; | 679 | if (net) { |
| 680 | struct lockd_net *ln = net_generic(net, lockd_net_id); | ||
| 681 | |||
| 682 | ln->next_gc = jiffies + NLM_HOST_COLLECT; | ||
| 683 | } | ||
| 652 | } | 684 | } |
diff --git a/fs/lockd/netns.h b/fs/lockd/netns.h index ce227e0fbc5c..4eee248ba96e 100644 --- a/fs/lockd/netns.h +++ b/fs/lockd/netns.h | |||
| @@ -1,10 +1,17 @@ | |||
| 1 | #ifndef __LOCKD_NETNS_H__ | 1 | #ifndef __LOCKD_NETNS_H__ |
| 2 | #define __LOCKD_NETNS_H__ | 2 | #define __LOCKD_NETNS_H__ |
| 3 | 3 | ||
| 4 | #include <linux/fs.h> | ||
| 4 | #include <net/netns/generic.h> | 5 | #include <net/netns/generic.h> |
| 5 | 6 | ||
| 6 | struct lockd_net { | 7 | struct lockd_net { |
| 7 | unsigned int nlmsvc_users; | 8 | unsigned int nlmsvc_users; |
| 9 | unsigned long next_gc; | ||
| 10 | unsigned long nrhosts; | ||
| 11 | |||
| 12 | struct delayed_work grace_period_end; | ||
| 13 | struct lock_manager lockd_manager; | ||
| 14 | struct list_head grace_list; | ||
| 8 | }; | 15 | }; |
| 9 | 16 | ||
| 10 | extern int lockd_net_id; | 17 | extern int lockd_net_id; |
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c index 80938fda67e0..31a63f87b806 100644 --- a/fs/lockd/svc.c +++ b/fs/lockd/svc.c | |||
| @@ -87,32 +87,36 @@ static unsigned long get_lockd_grace_period(void) | |||
| 87 | return nlm_timeout * 5 * HZ; | 87 | return nlm_timeout * 5 * HZ; |
| 88 | } | 88 | } |
| 89 | 89 | ||
| 90 | static struct lock_manager lockd_manager = { | 90 | static void grace_ender(struct work_struct *grace) |
| 91 | }; | ||
| 92 | |||
| 93 | static void grace_ender(struct work_struct *not_used) | ||
| 94 | { | 91 | { |
| 95 | locks_end_grace(&lockd_manager); | 92 | struct delayed_work *dwork = container_of(grace, struct delayed_work, |
| 96 | } | 93 | work); |
| 94 | struct lockd_net *ln = container_of(dwork, struct lockd_net, | ||
| 95 | grace_period_end); | ||
| 97 | 96 | ||
| 98 | static DECLARE_DELAYED_WORK(grace_period_end, grace_ender); | 97 | locks_end_grace(&ln->lockd_manager); |
| 98 | } | ||
| 99 | 99 | ||
| 100 | static void set_grace_period(void) | 100 | static void set_grace_period(struct net *net) |
| 101 | { | 101 | { |
| 102 | unsigned long grace_period = get_lockd_grace_period(); | 102 | unsigned long grace_period = get_lockd_grace_period(); |
| 103 | struct lockd_net *ln = net_generic(net, lockd_net_id); | ||
| 103 | 104 | ||
| 104 | locks_start_grace(&lockd_manager); | 105 | locks_start_grace(net, &ln->lockd_manager); |
| 105 | cancel_delayed_work_sync(&grace_period_end); | 106 | cancel_delayed_work_sync(&ln->grace_period_end); |
| 106 | schedule_delayed_work(&grace_period_end, grace_period); | 107 | schedule_delayed_work(&ln->grace_period_end, grace_period); |
| 107 | } | 108 | } |
| 108 | 109 | ||
| 109 | static void restart_grace(void) | 110 | static void restart_grace(void) |
| 110 | { | 111 | { |
| 111 | if (nlmsvc_ops) { | 112 | if (nlmsvc_ops) { |
| 112 | cancel_delayed_work_sync(&grace_period_end); | 113 | struct net *net = &init_net; |
| 113 | locks_end_grace(&lockd_manager); | 114 | struct lockd_net *ln = net_generic(net, lockd_net_id); |
| 115 | |||
| 116 | cancel_delayed_work_sync(&ln->grace_period_end); | ||
| 117 | locks_end_grace(&ln->lockd_manager); | ||
| 114 | nlmsvc_invalidate_all(); | 118 | nlmsvc_invalidate_all(); |
| 115 | set_grace_period(); | 119 | set_grace_period(net); |
| 116 | } | 120 | } |
| 117 | } | 121 | } |
| 118 | 122 | ||
| @@ -137,8 +141,6 @@ lockd(void *vrqstp) | |||
| 137 | nlm_timeout = LOCKD_DFLT_TIMEO; | 141 | nlm_timeout = LOCKD_DFLT_TIMEO; |
| 138 | nlmsvc_timeout = nlm_timeout * HZ; | 142 | nlmsvc_timeout = nlm_timeout * HZ; |
| 139 | 143 | ||
| 140 | set_grace_period(); | ||
| 141 | |||
| 142 | /* | 144 | /* |
| 143 | * The main request loop. We don't terminate until the last | 145 | * The main request loop. We don't terminate until the last |
| 144 | * NFS mount or NFS daemon has gone away. | 146 | * NFS mount or NFS daemon has gone away. |
| @@ -184,8 +186,6 @@ lockd(void *vrqstp) | |||
| 184 | svc_process(rqstp); | 186 | svc_process(rqstp); |
| 185 | } | 187 | } |
| 186 | flush_signals(current); | 188 | flush_signals(current); |
| 187 | cancel_delayed_work_sync(&grace_period_end); | ||
| 188 | locks_end_grace(&lockd_manager); | ||
| 189 | if (nlmsvc_ops) | 189 | if (nlmsvc_ops) |
| 190 | nlmsvc_invalidate_all(); | 190 | nlmsvc_invalidate_all(); |
| 191 | nlm_shutdown_hosts(); | 191 | nlm_shutdown_hosts(); |
| @@ -266,6 +266,7 @@ static int lockd_up_net(struct svc_serv *serv, struct net *net) | |||
| 266 | error = make_socks(serv, net); | 266 | error = make_socks(serv, net); |
| 267 | if (error < 0) | 267 | if (error < 0) |
| 268 | goto err_socks; | 268 | goto err_socks; |
| 269 | set_grace_period(net); | ||
| 269 | dprintk("lockd_up_net: per-net data created; net=%p\n", net); | 270 | dprintk("lockd_up_net: per-net data created; net=%p\n", net); |
| 270 | return 0; | 271 | return 0; |
| 271 | 272 | ||
| @@ -283,6 +284,8 @@ static void lockd_down_net(struct svc_serv *serv, struct net *net) | |||
| 283 | if (ln->nlmsvc_users) { | 284 | if (ln->nlmsvc_users) { |
| 284 | if (--ln->nlmsvc_users == 0) { | 285 | if (--ln->nlmsvc_users == 0) { |
| 285 | nlm_shutdown_hosts_net(net); | 286 | nlm_shutdown_hosts_net(net); |
| 287 | cancel_delayed_work_sync(&ln->grace_period_end); | ||
| 288 | locks_end_grace(&ln->lockd_manager); | ||
| 286 | svc_shutdown_net(serv, net); | 289 | svc_shutdown_net(serv, net); |
| 287 | dprintk("lockd_down_net: per-net data destroyed; net=%p\n", net); | 290 | dprintk("lockd_down_net: per-net data destroyed; net=%p\n", net); |
| 288 | } | 291 | } |
| @@ -589,6 +592,10 @@ module_param(nlm_max_connections, uint, 0644); | |||
| 589 | 592 | ||
| 590 | static int lockd_init_net(struct net *net) | 593 | static int lockd_init_net(struct net *net) |
| 591 | { | 594 | { |
| 595 | struct lockd_net *ln = net_generic(net, lockd_net_id); | ||
| 596 | |||
| 597 | INIT_DELAYED_WORK(&ln->grace_period_end, grace_ender); | ||
| 598 | INIT_LIST_HEAD(&ln->grace_list); | ||
| 592 | return 0; | 599 | return 0; |
| 593 | } | 600 | } |
| 594 | 601 | ||
diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c index 9a41fdc19511..4a43d253c045 100644 --- a/fs/lockd/svc4proc.c +++ b/fs/lockd/svc4proc.c | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | #include <linux/time.h> | 11 | #include <linux/time.h> |
| 12 | #include <linux/lockd/lockd.h> | 12 | #include <linux/lockd/lockd.h> |
| 13 | #include <linux/lockd/share.h> | 13 | #include <linux/lockd/share.h> |
| 14 | #include <linux/sunrpc/svc_xprt.h> | ||
| 14 | 15 | ||
| 15 | #define NLMDBG_FACILITY NLMDBG_CLIENT | 16 | #define NLMDBG_FACILITY NLMDBG_CLIENT |
| 16 | 17 | ||
| @@ -151,7 +152,7 @@ nlm4svc_proc_cancel(struct svc_rqst *rqstp, struct nlm_args *argp, | |||
| 151 | resp->cookie = argp->cookie; | 152 | resp->cookie = argp->cookie; |
| 152 | 153 | ||
| 153 | /* Don't accept requests during grace period */ | 154 | /* Don't accept requests during grace period */ |
| 154 | if (locks_in_grace()) { | 155 | if (locks_in_grace(SVC_NET(rqstp))) { |
| 155 | resp->status = nlm_lck_denied_grace_period; | 156 | resp->status = nlm_lck_denied_grace_period; |
| 156 | return rpc_success; | 157 | return rpc_success; |
| 157 | } | 158 | } |
| @@ -161,7 +162,7 @@ nlm4svc_proc_cancel(struct svc_rqst *rqstp, struct nlm_args *argp, | |||
| 161 | return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; | 162 | return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; |
| 162 | 163 | ||
| 163 | /* Try to cancel request. */ | 164 | /* Try to cancel request. */ |
| 164 | resp->status = nlmsvc_cancel_blocked(file, &argp->lock); | 165 | resp->status = nlmsvc_cancel_blocked(SVC_NET(rqstp), file, &argp->lock); |
| 165 | 166 | ||
| 166 | dprintk("lockd: CANCEL status %d\n", ntohl(resp->status)); | 167 | dprintk("lockd: CANCEL status %d\n", ntohl(resp->status)); |
| 167 | nlmsvc_release_host(host); | 168 | nlmsvc_release_host(host); |
| @@ -184,7 +185,7 @@ nlm4svc_proc_unlock(struct svc_rqst *rqstp, struct nlm_args *argp, | |||
| 184 | resp->cookie = argp->cookie; | 185 | resp->cookie = argp->cookie; |
| 185 | 186 | ||
| 186 | /* Don't accept new lock requests during grace period */ | 187 | /* Don't accept new lock requests during grace period */ |
| 187 | if (locks_in_grace()) { | 188 | if (locks_in_grace(SVC_NET(rqstp))) { |
| 188 | resp->status = nlm_lck_denied_grace_period; | 189 | resp->status = nlm_lck_denied_grace_period; |
| 189 | return rpc_success; | 190 | return rpc_success; |
| 190 | } | 191 | } |
| @@ -194,7 +195,7 @@ nlm4svc_proc_unlock(struct svc_rqst *rqstp, struct nlm_args *argp, | |||
| 194 | return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; | 195 | return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; |
| 195 | 196 | ||
| 196 | /* Now try to remove the lock */ | 197 | /* Now try to remove the lock */ |
| 197 | resp->status = nlmsvc_unlock(file, &argp->lock); | 198 | resp->status = nlmsvc_unlock(SVC_NET(rqstp), file, &argp->lock); |
| 198 | 199 | ||
| 199 | dprintk("lockd: UNLOCK status %d\n", ntohl(resp->status)); | 200 | dprintk("lockd: UNLOCK status %d\n", ntohl(resp->status)); |
| 200 | nlmsvc_release_host(host); | 201 | nlmsvc_release_host(host); |
| @@ -321,7 +322,7 @@ nlm4svc_proc_share(struct svc_rqst *rqstp, struct nlm_args *argp, | |||
| 321 | resp->cookie = argp->cookie; | 322 | resp->cookie = argp->cookie; |
| 322 | 323 | ||
| 323 | /* Don't accept new lock requests during grace period */ | 324 | /* Don't accept new lock requests during grace period */ |
| 324 | if (locks_in_grace() && !argp->reclaim) { | 325 | if (locks_in_grace(SVC_NET(rqstp)) && !argp->reclaim) { |
| 325 | resp->status = nlm_lck_denied_grace_period; | 326 | resp->status = nlm_lck_denied_grace_period; |
| 326 | return rpc_success; | 327 | return rpc_success; |
| 327 | } | 328 | } |
| @@ -354,7 +355,7 @@ nlm4svc_proc_unshare(struct svc_rqst *rqstp, struct nlm_args *argp, | |||
| 354 | resp->cookie = argp->cookie; | 355 | resp->cookie = argp->cookie; |
| 355 | 356 | ||
| 356 | /* Don't accept requests during grace period */ | 357 | /* Don't accept requests during grace period */ |
| 357 | if (locks_in_grace()) { | 358 | if (locks_in_grace(SVC_NET(rqstp))) { |
| 358 | resp->status = nlm_lck_denied_grace_period; | 359 | resp->status = nlm_lck_denied_grace_period; |
| 359 | return rpc_success; | 360 | return rpc_success; |
| 360 | } | 361 | } |
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c index e46353f41a42..afe4488c33d8 100644 --- a/fs/lockd/svclock.c +++ b/fs/lockd/svclock.c | |||
| @@ -26,7 +26,7 @@ | |||
| 26 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
| 27 | #include <linux/sched.h> | 27 | #include <linux/sched.h> |
| 28 | #include <linux/sunrpc/clnt.h> | 28 | #include <linux/sunrpc/clnt.h> |
| 29 | #include <linux/sunrpc/svc.h> | 29 | #include <linux/sunrpc/svc_xprt.h> |
| 30 | #include <linux/lockd/nlm.h> | 30 | #include <linux/lockd/nlm.h> |
| 31 | #include <linux/lockd/lockd.h> | 31 | #include <linux/lockd/lockd.h> |
| 32 | #include <linux/kthread.h> | 32 | #include <linux/kthread.h> |
| @@ -447,11 +447,11 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file, | |||
| 447 | goto out; | 447 | goto out; |
| 448 | } | 448 | } |
| 449 | 449 | ||
| 450 | if (locks_in_grace() && !reclaim) { | 450 | if (locks_in_grace(SVC_NET(rqstp)) && !reclaim) { |
| 451 | ret = nlm_lck_denied_grace_period; | 451 | ret = nlm_lck_denied_grace_period; |
| 452 | goto out; | 452 | goto out; |
| 453 | } | 453 | } |
| 454 | if (reclaim && !locks_in_grace()) { | 454 | if (reclaim && !locks_in_grace(SVC_NET(rqstp))) { |
| 455 | ret = nlm_lck_denied_grace_period; | 455 | ret = nlm_lck_denied_grace_period; |
| 456 | goto out; | 456 | goto out; |
| 457 | } | 457 | } |
| @@ -559,7 +559,7 @@ nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file, | |||
| 559 | goto out; | 559 | goto out; |
| 560 | } | 560 | } |
| 561 | 561 | ||
| 562 | if (locks_in_grace()) { | 562 | if (locks_in_grace(SVC_NET(rqstp))) { |
| 563 | ret = nlm_lck_denied_grace_period; | 563 | ret = nlm_lck_denied_grace_period; |
| 564 | goto out; | 564 | goto out; |
| 565 | } | 565 | } |
| @@ -603,7 +603,7 @@ out: | |||
| 603 | * must be removed. | 603 | * must be removed. |
| 604 | */ | 604 | */ |
| 605 | __be32 | 605 | __be32 |
| 606 | nlmsvc_unlock(struct nlm_file *file, struct nlm_lock *lock) | 606 | nlmsvc_unlock(struct net *net, struct nlm_file *file, struct nlm_lock *lock) |
| 607 | { | 607 | { |
| 608 | int error; | 608 | int error; |
| 609 | 609 | ||
| @@ -615,7 +615,7 @@ nlmsvc_unlock(struct nlm_file *file, struct nlm_lock *lock) | |||
| 615 | (long long)lock->fl.fl_end); | 615 | (long long)lock->fl.fl_end); |
| 616 | 616 | ||
| 617 | /* First, cancel any lock that might be there */ | 617 | /* First, cancel any lock that might be there */ |
| 618 | nlmsvc_cancel_blocked(file, lock); | 618 | nlmsvc_cancel_blocked(net, file, lock); |
| 619 | 619 | ||
| 620 | lock->fl.fl_type = F_UNLCK; | 620 | lock->fl.fl_type = F_UNLCK; |
| 621 | error = vfs_lock_file(file->f_file, F_SETLK, &lock->fl, NULL); | 621 | 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) | |||
| 631 | * The calling procedure must check whether the file can be closed. | 631 | * The calling procedure must check whether the file can be closed. |
| 632 | */ | 632 | */ |
| 633 | __be32 | 633 | __be32 |
| 634 | nlmsvc_cancel_blocked(struct nlm_file *file, struct nlm_lock *lock) | 634 | nlmsvc_cancel_blocked(struct net *net, struct nlm_file *file, struct nlm_lock *lock) |
| 635 | { | 635 | { |
| 636 | struct nlm_block *block; | 636 | struct nlm_block *block; |
| 637 | int status = 0; | 637 | int status = 0; |
| @@ -643,7 +643,7 @@ nlmsvc_cancel_blocked(struct nlm_file *file, struct nlm_lock *lock) | |||
| 643 | (long long)lock->fl.fl_start, | 643 | (long long)lock->fl.fl_start, |
| 644 | (long long)lock->fl.fl_end); | 644 | (long long)lock->fl.fl_end); |
| 645 | 645 | ||
| 646 | if (locks_in_grace()) | 646 | if (locks_in_grace(net)) |
| 647 | return nlm_lck_denied_grace_period; | 647 | return nlm_lck_denied_grace_period; |
| 648 | 648 | ||
| 649 | mutex_lock(&file->f_mutex); | 649 | mutex_lock(&file->f_mutex); |
diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c index d27aab11f324..de8f2caa2235 100644 --- a/fs/lockd/svcproc.c +++ b/fs/lockd/svcproc.c | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | #include <linux/time.h> | 11 | #include <linux/time.h> |
| 12 | #include <linux/lockd/lockd.h> | 12 | #include <linux/lockd/lockd.h> |
| 13 | #include <linux/lockd/share.h> | 13 | #include <linux/lockd/share.h> |
| 14 | #include <linux/sunrpc/svc_xprt.h> | ||
| 14 | 15 | ||
| 15 | #define NLMDBG_FACILITY NLMDBG_CLIENT | 16 | #define NLMDBG_FACILITY NLMDBG_CLIENT |
| 16 | 17 | ||
| @@ -175,13 +176,14 @@ nlmsvc_proc_cancel(struct svc_rqst *rqstp, struct nlm_args *argp, | |||
| 175 | { | 176 | { |
| 176 | struct nlm_host *host; | 177 | struct nlm_host *host; |
| 177 | struct nlm_file *file; | 178 | struct nlm_file *file; |
| 179 | struct net *net = SVC_NET(rqstp); | ||
| 178 | 180 | ||
| 179 | dprintk("lockd: CANCEL called\n"); | 181 | dprintk("lockd: CANCEL called\n"); |
| 180 | 182 | ||
| 181 | resp->cookie = argp->cookie; | 183 | resp->cookie = argp->cookie; |
| 182 | 184 | ||
| 183 | /* Don't accept requests during grace period */ | 185 | /* Don't accept requests during grace period */ |
| 184 | if (locks_in_grace()) { | 186 | if (locks_in_grace(net)) { |
| 185 | resp->status = nlm_lck_denied_grace_period; | 187 | resp->status = nlm_lck_denied_grace_period; |
| 186 | return rpc_success; | 188 | return rpc_success; |
| 187 | } | 189 | } |
| @@ -191,7 +193,7 @@ nlmsvc_proc_cancel(struct svc_rqst *rqstp, struct nlm_args *argp, | |||
| 191 | return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; | 193 | return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; |
| 192 | 194 | ||
| 193 | /* Try to cancel request. */ | 195 | /* Try to cancel request. */ |
| 194 | resp->status = cast_status(nlmsvc_cancel_blocked(file, &argp->lock)); | 196 | resp->status = cast_status(nlmsvc_cancel_blocked(net, file, &argp->lock)); |
| 195 | 197 | ||
| 196 | dprintk("lockd: CANCEL status %d\n", ntohl(resp->status)); | 198 | dprintk("lockd: CANCEL status %d\n", ntohl(resp->status)); |
| 197 | nlmsvc_release_host(host); | 199 | nlmsvc_release_host(host); |
| @@ -208,13 +210,14 @@ nlmsvc_proc_unlock(struct svc_rqst *rqstp, struct nlm_args *argp, | |||
| 208 | { | 210 | { |
| 209 | struct nlm_host *host; | 211 | struct nlm_host *host; |
| 210 | struct nlm_file *file; | 212 | struct nlm_file *file; |
| 213 | struct net *net = SVC_NET(rqstp); | ||
| 211 | 214 | ||
| 212 | dprintk("lockd: UNLOCK called\n"); | 215 | dprintk("lockd: UNLOCK called\n"); |
| 213 | 216 | ||
| 214 | resp->cookie = argp->cookie; | 217 | resp->cookie = argp->cookie; |
| 215 | 218 | ||
| 216 | /* Don't accept new lock requests during grace period */ | 219 | /* Don't accept new lock requests during grace period */ |
| 217 | if (locks_in_grace()) { | 220 | if (locks_in_grace(net)) { |
| 218 | resp->status = nlm_lck_denied_grace_period; | 221 | resp->status = nlm_lck_denied_grace_period; |
| 219 | return rpc_success; | 222 | return rpc_success; |
| 220 | } | 223 | } |
| @@ -224,7 +227,7 @@ nlmsvc_proc_unlock(struct svc_rqst *rqstp, struct nlm_args *argp, | |||
| 224 | return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; | 227 | return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; |
| 225 | 228 | ||
| 226 | /* Now try to remove the lock */ | 229 | /* Now try to remove the lock */ |
| 227 | resp->status = cast_status(nlmsvc_unlock(file, &argp->lock)); | 230 | resp->status = cast_status(nlmsvc_unlock(net, file, &argp->lock)); |
| 228 | 231 | ||
| 229 | dprintk("lockd: UNLOCK status %d\n", ntohl(resp->status)); | 232 | dprintk("lockd: UNLOCK status %d\n", ntohl(resp->status)); |
| 230 | nlmsvc_release_host(host); | 233 | nlmsvc_release_host(host); |
| @@ -361,7 +364,7 @@ nlmsvc_proc_share(struct svc_rqst *rqstp, struct nlm_args *argp, | |||
| 361 | resp->cookie = argp->cookie; | 364 | resp->cookie = argp->cookie; |
| 362 | 365 | ||
| 363 | /* Don't accept new lock requests during grace period */ | 366 | /* Don't accept new lock requests during grace period */ |
| 364 | if (locks_in_grace() && !argp->reclaim) { | 367 | if (locks_in_grace(SVC_NET(rqstp)) && !argp->reclaim) { |
| 365 | resp->status = nlm_lck_denied_grace_period; | 368 | resp->status = nlm_lck_denied_grace_period; |
| 366 | return rpc_success; | 369 | return rpc_success; |
| 367 | } | 370 | } |
| @@ -394,7 +397,7 @@ nlmsvc_proc_unshare(struct svc_rqst *rqstp, struct nlm_args *argp, | |||
| 394 | resp->cookie = argp->cookie; | 397 | resp->cookie = argp->cookie; |
| 395 | 398 | ||
| 396 | /* Don't accept requests during grace period */ | 399 | /* Don't accept requests during grace period */ |
| 397 | if (locks_in_grace()) { | 400 | if (locks_in_grace(SVC_NET(rqstp))) { |
| 398 | resp->status = nlm_lck_denied_grace_period; | 401 | resp->status = nlm_lck_denied_grace_period; |
| 399 | return rpc_success; | 402 | return rpc_success; |
| 400 | } | 403 | } |
diff --git a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c index 2240d384d787..0deb5f6c9dd4 100644 --- a/fs/lockd/svcsubs.c +++ b/fs/lockd/svcsubs.c | |||
| @@ -309,7 +309,8 @@ nlm_release_file(struct nlm_file *file) | |||
| 309 | * Helpers function for resource traversal | 309 | * Helpers function for resource traversal |
| 310 | * | 310 | * |
| 311 | * nlmsvc_mark_host: | 311 | * nlmsvc_mark_host: |
| 312 | * used by the garbage collector; simply sets h_inuse. | 312 | * used by the garbage collector; simply sets h_inuse only for those |
| 313 | * hosts, which passed network check. | ||
| 313 | * Always returns 0. | 314 | * Always returns 0. |
| 314 | * | 315 | * |
| 315 | * nlmsvc_same_host: | 316 | * nlmsvc_same_host: |
| @@ -320,12 +321,15 @@ nlm_release_file(struct nlm_file *file) | |||
| 320 | * returns 1 iff the host is a client. | 321 | * returns 1 iff the host is a client. |
| 321 | * Used by nlmsvc_invalidate_all | 322 | * Used by nlmsvc_invalidate_all |
| 322 | */ | 323 | */ |
| 324 | |||
| 323 | static int | 325 | static int |
| 324 | nlmsvc_mark_host(void *data, struct nlm_host *dummy) | 326 | nlmsvc_mark_host(void *data, struct nlm_host *hint) |
| 325 | { | 327 | { |
| 326 | struct nlm_host *host = data; | 328 | struct nlm_host *host = data; |
| 327 | 329 | ||
| 328 | host->h_inuse = 1; | 330 | if ((hint->net == NULL) || |
| 331 | (host->net == hint->net)) | ||
| 332 | host->h_inuse = 1; | ||
| 329 | return 0; | 333 | return 0; |
| 330 | } | 334 | } |
| 331 | 335 | ||
| @@ -358,10 +362,13 @@ nlmsvc_is_client(void *data, struct nlm_host *dummy) | |||
| 358 | * Mark all hosts that still hold resources | 362 | * Mark all hosts that still hold resources |
| 359 | */ | 363 | */ |
| 360 | void | 364 | void |
| 361 | nlmsvc_mark_resources(void) | 365 | nlmsvc_mark_resources(struct net *net) |
| 362 | { | 366 | { |
| 363 | dprintk("lockd: nlmsvc_mark_resources\n"); | 367 | struct nlm_host hint; |
| 364 | nlm_traverse_files(NULL, nlmsvc_mark_host, NULL); | 368 | |
| 369 | dprintk("lockd: nlmsvc_mark_resources for net %p\n", net); | ||
| 370 | hint.net = net; | ||
| 371 | nlm_traverse_files(&hint, nlmsvc_mark_host, NULL); | ||
| 365 | } | 372 | } |
| 366 | 373 | ||
| 367 | /* | 374 | /* |
diff --git a/fs/locks.c b/fs/locks.c index 82c353304f9e..cdcf219a7391 100644 --- a/fs/locks.c +++ b/fs/locks.c | |||
| @@ -427,18 +427,8 @@ static void lease_break_callback(struct file_lock *fl) | |||
| 427 | kill_fasync(&fl->fl_fasync, SIGIO, POLL_MSG); | 427 | kill_fasync(&fl->fl_fasync, SIGIO, POLL_MSG); |
| 428 | } | 428 | } |
| 429 | 429 | ||
| 430 | static void lease_release_private_callback(struct file_lock *fl) | ||
| 431 | { | ||
| 432 | if (!fl->fl_file) | ||
| 433 | return; | ||
| 434 | |||
| 435 | f_delown(fl->fl_file); | ||
| 436 | fl->fl_file->f_owner.signum = 0; | ||
| 437 | } | ||
| 438 | |||
| 439 | static const struct lock_manager_operations lease_manager_ops = { | 430 | static const struct lock_manager_operations lease_manager_ops = { |
| 440 | .lm_break = lease_break_callback, | 431 | .lm_break = lease_break_callback, |
| 441 | .lm_release_private = lease_release_private_callback, | ||
| 442 | .lm_change = lease_modify, | 432 | .lm_change = lease_modify, |
| 443 | }; | 433 | }; |
| 444 | 434 | ||
| @@ -580,12 +570,6 @@ static void locks_delete_lock(struct file_lock **thisfl_p) | |||
| 580 | fl->fl_next = NULL; | 570 | fl->fl_next = NULL; |
| 581 | list_del_init(&fl->fl_link); | 571 | list_del_init(&fl->fl_link); |
| 582 | 572 | ||
| 583 | fasync_helper(0, fl->fl_file, 0, &fl->fl_fasync); | ||
| 584 | if (fl->fl_fasync != NULL) { | ||
| 585 | printk(KERN_ERR "locks_delete_lock: fasync == %p\n", fl->fl_fasync); | ||
| 586 | fl->fl_fasync = NULL; | ||
| 587 | } | ||
| 588 | |||
| 589 | if (fl->fl_nspid) { | 573 | if (fl->fl_nspid) { |
| 590 | put_pid(fl->fl_nspid); | 574 | put_pid(fl->fl_nspid); |
| 591 | fl->fl_nspid = NULL; | 575 | fl->fl_nspid = NULL; |
| @@ -1155,8 +1139,18 @@ int lease_modify(struct file_lock **before, int arg) | |||
| 1155 | return error; | 1139 | return error; |
| 1156 | lease_clear_pending(fl, arg); | 1140 | lease_clear_pending(fl, arg); |
| 1157 | locks_wake_up_blocks(fl); | 1141 | locks_wake_up_blocks(fl); |
| 1158 | if (arg == F_UNLCK) | 1142 | if (arg == F_UNLCK) { |
| 1143 | struct file *filp = fl->fl_file; | ||
| 1144 | |||
| 1145 | f_delown(filp); | ||
| 1146 | filp->f_owner.signum = 0; | ||
| 1147 | fasync_helper(0, fl->fl_file, 0, &fl->fl_fasync); | ||
| 1148 | if (fl->fl_fasync != NULL) { | ||
| 1149 | printk(KERN_ERR "locks_delete_lock: fasync == %p\n", fl->fl_fasync); | ||
| 1150 | fl->fl_fasync = NULL; | ||
| 1151 | } | ||
| 1159 | locks_delete_lock(before); | 1152 | locks_delete_lock(before); |
| 1153 | } | ||
| 1160 | return 0; | 1154 | return 0; |
| 1161 | } | 1155 | } |
| 1162 | 1156 | ||
diff --git a/fs/nfs/callback_xdr.c b/fs/nfs/callback_xdr.c index e64b01d2a338..742ff4ffced7 100644 --- a/fs/nfs/callback_xdr.c +++ b/fs/nfs/callback_xdr.c | |||
| @@ -863,7 +863,7 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *r | |||
| 863 | .drc_status = 0, | 863 | .drc_status = 0, |
| 864 | .clp = NULL, | 864 | .clp = NULL, |
| 865 | .slotid = NFS4_NO_SLOT, | 865 | .slotid = NFS4_NO_SLOT, |
| 866 | .net = rqstp->rq_xprt->xpt_net, | 866 | .net = SVC_NET(rqstp), |
| 867 | }; | 867 | }; |
| 868 | unsigned int nops = 0; | 868 | unsigned int nops = 0; |
| 869 | 869 | ||
| @@ -879,7 +879,7 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *r | |||
| 879 | return rpc_garbage_args; | 879 | return rpc_garbage_args; |
| 880 | 880 | ||
| 881 | if (hdr_arg.minorversion == 0) { | 881 | if (hdr_arg.minorversion == 0) { |
| 882 | cps.clp = nfs4_find_client_ident(rqstp->rq_xprt->xpt_net, hdr_arg.cb_ident); | 882 | cps.clp = nfs4_find_client_ident(SVC_NET(rqstp), hdr_arg.cb_ident); |
| 883 | if (!cps.clp || !check_gss_callback_principal(cps.clp, rqstp)) | 883 | if (!cps.clp || !check_gss_callback_principal(cps.clp, rqstp)) |
| 884 | return rpc_drop_reply; | 884 | return rpc_drop_reply; |
| 885 | } | 885 | } |
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index ba233499b9a5..a3946cf13fc8 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c | |||
| @@ -398,7 +398,7 @@ fsloc_parse(char **mesg, char *buf, struct nfsd4_fs_locations *fsloc) | |||
| 398 | int migrated, i, err; | 398 | int migrated, i, err; |
| 399 | 399 | ||
| 400 | /* listsize */ | 400 | /* listsize */ |
| 401 | err = get_int(mesg, &fsloc->locations_count); | 401 | err = get_uint(mesg, &fsloc->locations_count); |
| 402 | if (err) | 402 | if (err) |
| 403 | return err; | 403 | return err; |
| 404 | if (fsloc->locations_count > MAX_FS_LOCATIONS) | 404 | if (fsloc->locations_count > MAX_FS_LOCATIONS) |
| @@ -456,7 +456,7 @@ static int secinfo_parse(char **mesg, char *buf, struct svc_export *exp) | |||
| 456 | return -EINVAL; | 456 | return -EINVAL; |
| 457 | 457 | ||
| 458 | for (f = exp->ex_flavors; f < exp->ex_flavors + listsize; f++) { | 458 | for (f = exp->ex_flavors; f < exp->ex_flavors + listsize; f++) { |
| 459 | err = get_int(mesg, &f->pseudoflavor); | 459 | err = get_uint(mesg, &f->pseudoflavor); |
| 460 | if (err) | 460 | if (err) |
| 461 | return err; | 461 | return err; |
| 462 | /* | 462 | /* |
| @@ -465,7 +465,7 @@ static int secinfo_parse(char **mesg, char *buf, struct svc_export *exp) | |||
| 465 | * problem at export time instead of when a client fails | 465 | * problem at export time instead of when a client fails |
| 466 | * to authenticate. | 466 | * to authenticate. |
| 467 | */ | 467 | */ |
| 468 | err = get_int(mesg, &f->flags); | 468 | err = get_uint(mesg, &f->flags); |
| 469 | if (err) | 469 | if (err) |
| 470 | return err; | 470 | return err; |
| 471 | /* Only some flags are allowed to differ between flavors: */ | 471 | /* Only some flags are allowed to differ between flavors: */ |
| @@ -929,7 +929,7 @@ struct svc_export * | |||
| 929 | rqst_exp_get_by_name(struct svc_rqst *rqstp, struct path *path) | 929 | rqst_exp_get_by_name(struct svc_rqst *rqstp, struct path *path) |
| 930 | { | 930 | { |
| 931 | struct svc_export *gssexp, *exp = ERR_PTR(-ENOENT); | 931 | struct svc_export *gssexp, *exp = ERR_PTR(-ENOENT); |
| 932 | struct nfsd_net *nn = net_generic(rqstp->rq_xprt->xpt_net, nfsd_net_id); | 932 | struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id); |
| 933 | struct cache_detail *cd = nn->svc_export_cache; | 933 | struct cache_detail *cd = nn->svc_export_cache; |
| 934 | 934 | ||
| 935 | if (rqstp->rq_client == NULL) | 935 | if (rqstp->rq_client == NULL) |
| @@ -960,7 +960,7 @@ struct svc_export * | |||
| 960 | rqst_exp_find(struct svc_rqst *rqstp, int fsid_type, u32 *fsidv) | 960 | rqst_exp_find(struct svc_rqst *rqstp, int fsid_type, u32 *fsidv) |
| 961 | { | 961 | { |
| 962 | struct svc_export *gssexp, *exp = ERR_PTR(-ENOENT); | 962 | struct svc_export *gssexp, *exp = ERR_PTR(-ENOENT); |
| 963 | struct nfsd_net *nn = net_generic(rqstp->rq_xprt->xpt_net, nfsd_net_id); | 963 | struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id); |
| 964 | struct cache_detail *cd = nn->svc_export_cache; | 964 | struct cache_detail *cd = nn->svc_export_cache; |
| 965 | 965 | ||
| 966 | if (rqstp->rq_client == NULL) | 966 | if (rqstp->rq_client == NULL) |
diff --git a/fs/nfsd/netns.h b/fs/nfsd/netns.h index 39365636b244..65c2431ea32f 100644 --- a/fs/nfsd/netns.h +++ b/fs/nfsd/netns.h | |||
| @@ -34,6 +34,10 @@ struct nfsd_net { | |||
| 34 | 34 | ||
| 35 | struct cache_detail *idtoname_cache; | 35 | struct cache_detail *idtoname_cache; |
| 36 | struct cache_detail *nametoid_cache; | 36 | struct cache_detail *nametoid_cache; |
| 37 | |||
| 38 | struct lock_manager nfsd4_manager; | ||
| 39 | bool grace_ended; | ||
| 40 | time_t boot_time; | ||
| 37 | }; | 41 | }; |
| 38 | 42 | ||
| 39 | extern int nfsd_net_id; | 43 | extern int nfsd_net_id; |
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c index a5fd6b982f27..cbaf4f8bb7b7 100644 --- a/fs/nfsd/nfs4callback.c +++ b/fs/nfsd/nfs4callback.c | |||
| @@ -756,7 +756,6 @@ static void do_probe_callback(struct nfs4_client *clp) | |||
| 756 | */ | 756 | */ |
| 757 | void nfsd4_probe_callback(struct nfs4_client *clp) | 757 | void nfsd4_probe_callback(struct nfs4_client *clp) |
| 758 | { | 758 | { |
| 759 | /* XXX: atomicity? Also, should we be using cl_flags? */ | ||
| 760 | clp->cl_cb_state = NFSD4_CB_UNKNOWN; | 759 | clp->cl_cb_state = NFSD4_CB_UNKNOWN; |
| 761 | set_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_flags); | 760 | set_bit(NFSD4_CLIENT_CB_UPDATE, &clp->cl_flags); |
| 762 | do_probe_callback(clp); | 761 | do_probe_callback(clp); |
diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c index dae36f1dee95..fdc91a6fc9c4 100644 --- a/fs/nfsd/nfs4idmap.c +++ b/fs/nfsd/nfs4idmap.c | |||
| @@ -546,7 +546,7 @@ idmap_name_to_id(struct svc_rqst *rqstp, int type, const char *name, u32 namelen | |||
| 546 | .type = type, | 546 | .type = type, |
| 547 | }; | 547 | }; |
| 548 | int ret; | 548 | int ret; |
| 549 | struct nfsd_net *nn = net_generic(rqstp->rq_xprt->xpt_net, nfsd_net_id); | 549 | struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id); |
| 550 | 550 | ||
| 551 | if (namelen + 1 > sizeof(key.name)) | 551 | if (namelen + 1 > sizeof(key.name)) |
| 552 | return nfserr_badowner; | 552 | return nfserr_badowner; |
| @@ -571,7 +571,7 @@ idmap_id_to_name(struct svc_rqst *rqstp, int type, uid_t id, char *name) | |||
| 571 | .type = type, | 571 | .type = type, |
| 572 | }; | 572 | }; |
| 573 | int ret; | 573 | int ret; |
| 574 | struct nfsd_net *nn = net_generic(rqstp->rq_xprt->xpt_net, nfsd_net_id); | 574 | struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id); |
| 575 | 575 | ||
| 576 | strlcpy(key.authname, rqst_authname(rqstp), sizeof(key.authname)); | 576 | strlcpy(key.authname, rqst_authname(rqstp), sizeof(key.authname)); |
| 577 | ret = idmap_lookup(rqstp, idtoname_lookup, &key, nn->idtoname_cache, &item); | 577 | ret = idmap_lookup(rqstp, idtoname_lookup, &key, nn->idtoname_cache, &item); |
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index 987e719fbae8..c9c1c0a25417 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c | |||
| @@ -354,10 +354,10 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
| 354 | /* Openowner is now set, so sequence id will get bumped. Now we need | 354 | /* Openowner is now set, so sequence id will get bumped. Now we need |
| 355 | * these checks before we do any creates: */ | 355 | * these checks before we do any creates: */ |
| 356 | status = nfserr_grace; | 356 | status = nfserr_grace; |
| 357 | if (locks_in_grace() && open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS) | 357 | if (locks_in_grace(SVC_NET(rqstp)) && open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS) |
| 358 | goto out; | 358 | goto out; |
| 359 | status = nfserr_no_grace; | 359 | status = nfserr_no_grace; |
| 360 | if (!locks_in_grace() && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS) | 360 | if (!locks_in_grace(SVC_NET(rqstp)) && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS) |
| 361 | goto out; | 361 | goto out; |
| 362 | 362 | ||
| 363 | switch (open->op_claim_type) { | 363 | switch (open->op_claim_type) { |
| @@ -686,7 +686,8 @@ nfsd4_read(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
| 686 | 686 | ||
| 687 | nfs4_lock_state(); | 687 | nfs4_lock_state(); |
| 688 | /* check stateid */ | 688 | /* check stateid */ |
| 689 | if ((status = nfs4_preprocess_stateid_op(cstate, &read->rd_stateid, | 689 | if ((status = nfs4_preprocess_stateid_op(SVC_NET(rqstp), |
| 690 | cstate, &read->rd_stateid, | ||
| 690 | RD_STATE, &read->rd_filp))) { | 691 | RD_STATE, &read->rd_filp))) { |
| 691 | dprintk("NFSD: nfsd4_read: couldn't process stateid!\n"); | 692 | dprintk("NFSD: nfsd4_read: couldn't process stateid!\n"); |
| 692 | goto out; | 693 | goto out; |
| @@ -741,7 +742,7 @@ nfsd4_remove(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
| 741 | { | 742 | { |
| 742 | __be32 status; | 743 | __be32 status; |
| 743 | 744 | ||
| 744 | if (locks_in_grace()) | 745 | if (locks_in_grace(SVC_NET(rqstp))) |
| 745 | return nfserr_grace; | 746 | return nfserr_grace; |
| 746 | status = nfsd_unlink(rqstp, &cstate->current_fh, 0, | 747 | status = nfsd_unlink(rqstp, &cstate->current_fh, 0, |
| 747 | remove->rm_name, remove->rm_namelen); | 748 | remove->rm_name, remove->rm_namelen); |
| @@ -760,8 +761,8 @@ nfsd4_rename(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
| 760 | 761 | ||
| 761 | if (!cstate->save_fh.fh_dentry) | 762 | if (!cstate->save_fh.fh_dentry) |
| 762 | return status; | 763 | return status; |
| 763 | if (locks_in_grace() && !(cstate->save_fh.fh_export->ex_flags | 764 | if (locks_in_grace(SVC_NET(rqstp)) && |
| 764 | & NFSEXP_NOSUBTREECHECK)) | 765 | !(cstate->save_fh.fh_export->ex_flags & NFSEXP_NOSUBTREECHECK)) |
| 765 | return nfserr_grace; | 766 | return nfserr_grace; |
| 766 | status = nfsd_rename(rqstp, &cstate->save_fh, rename->rn_sname, | 767 | status = nfsd_rename(rqstp, &cstate->save_fh, rename->rn_sname, |
| 767 | rename->rn_snamelen, &cstate->current_fh, | 768 | rename->rn_snamelen, &cstate->current_fh, |
| @@ -845,7 +846,7 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
| 845 | 846 | ||
| 846 | if (setattr->sa_iattr.ia_valid & ATTR_SIZE) { | 847 | if (setattr->sa_iattr.ia_valid & ATTR_SIZE) { |
| 847 | nfs4_lock_state(); | 848 | nfs4_lock_state(); |
| 848 | status = nfs4_preprocess_stateid_op(cstate, | 849 | status = nfs4_preprocess_stateid_op(SVC_NET(rqstp), cstate, |
| 849 | &setattr->sa_stateid, WR_STATE, NULL); | 850 | &setattr->sa_stateid, WR_STATE, NULL); |
| 850 | nfs4_unlock_state(); | 851 | nfs4_unlock_state(); |
| 851 | if (status) { | 852 | if (status) { |
| @@ -890,7 +891,8 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
| 890 | return nfserr_inval; | 891 | return nfserr_inval; |
| 891 | 892 | ||
| 892 | nfs4_lock_state(); | 893 | nfs4_lock_state(); |
| 893 | status = nfs4_preprocess_stateid_op(cstate, stateid, WR_STATE, &filp); | 894 | status = nfs4_preprocess_stateid_op(SVC_NET(rqstp), |
| 895 | cstate, stateid, WR_STATE, &filp); | ||
| 894 | if (filp) | 896 | if (filp) |
| 895 | get_file(filp); | 897 | get_file(filp); |
| 896 | nfs4_unlock_state(); | 898 | nfs4_unlock_state(); |
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 94effd5bc4a1..cc894eda385a 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
| @@ -38,18 +38,21 @@ | |||
| 38 | #include <linux/namei.h> | 38 | #include <linux/namei.h> |
| 39 | #include <linux/swap.h> | 39 | #include <linux/swap.h> |
| 40 | #include <linux/pagemap.h> | 40 | #include <linux/pagemap.h> |
| 41 | #include <linux/ratelimit.h> | ||
| 41 | #include <linux/sunrpc/svcauth_gss.h> | 42 | #include <linux/sunrpc/svcauth_gss.h> |
| 42 | #include <linux/sunrpc/clnt.h> | 43 | #include <linux/sunrpc/clnt.h> |
| 43 | #include "xdr4.h" | 44 | #include "xdr4.h" |
| 44 | #include "vfs.h" | 45 | #include "vfs.h" |
| 45 | #include "current_stateid.h" | 46 | #include "current_stateid.h" |
| 47 | #include "fault_inject.h" | ||
| 48 | |||
| 49 | #include "netns.h" | ||
| 46 | 50 | ||
| 47 | #define NFSDDBG_FACILITY NFSDDBG_PROC | 51 | #define NFSDDBG_FACILITY NFSDDBG_PROC |
| 48 | 52 | ||
| 49 | /* Globals */ | 53 | /* Globals */ |
| 50 | time_t nfsd4_lease = 90; /* default lease time */ | 54 | time_t nfsd4_lease = 90; /* default lease time */ |
| 51 | time_t nfsd4_grace = 90; | 55 | time_t nfsd4_grace = 90; |
| 52 | static time_t boot_time; | ||
| 53 | 56 | ||
| 54 | #define all_ones {{~0,~0},~0} | 57 | #define all_ones {{~0,~0},~0} |
| 55 | static const stateid_t one_stateid = { | 58 | static const stateid_t one_stateid = { |
| @@ -862,6 +865,11 @@ static __be32 nfsd4_new_conn(struct svc_rqst *rqstp, struct nfsd4_session *ses, | |||
| 862 | if (ret) | 865 | if (ret) |
| 863 | /* oops; xprt is already down: */ | 866 | /* oops; xprt is already down: */ |
| 864 | nfsd4_conn_lost(&conn->cn_xpt_user); | 867 | nfsd4_conn_lost(&conn->cn_xpt_user); |
| 868 | if (ses->se_client->cl_cb_state == NFSD4_CB_DOWN && | ||
| 869 | dir & NFS4_CDFC4_BACK) { | ||
| 870 | /* callback channel may be back up */ | ||
| 871 | nfsd4_probe_callback(ses->se_client); | ||
| 872 | } | ||
| 865 | return nfs_ok; | 873 | return nfs_ok; |
| 866 | } | 874 | } |
| 867 | 875 | ||
| @@ -1047,12 +1055,12 @@ renew_client(struct nfs4_client *clp) | |||
| 1047 | 1055 | ||
| 1048 | /* SETCLIENTID and SETCLIENTID_CONFIRM Helper functions */ | 1056 | /* SETCLIENTID and SETCLIENTID_CONFIRM Helper functions */ |
| 1049 | static int | 1057 | static int |
| 1050 | STALE_CLIENTID(clientid_t *clid) | 1058 | STALE_CLIENTID(clientid_t *clid, struct nfsd_net *nn) |
| 1051 | { | 1059 | { |
| 1052 | if (clid->cl_boot == boot_time) | 1060 | if (clid->cl_boot == nn->boot_time) |
| 1053 | return 0; | 1061 | return 0; |
| 1054 | dprintk("NFSD stale clientid (%08x/%08x) boot_time %08lx\n", | 1062 | dprintk("NFSD stale clientid (%08x/%08x) boot_time %08lx\n", |
| 1055 | clid->cl_boot, clid->cl_id, boot_time); | 1063 | clid->cl_boot, clid->cl_id, nn->boot_time); |
| 1056 | return 1; | 1064 | return 1; |
| 1057 | } | 1065 | } |
| 1058 | 1066 | ||
| @@ -1215,7 +1223,7 @@ static bool groups_equal(struct group_info *g1, struct group_info *g2) | |||
| 1215 | return true; | 1223 | return true; |
| 1216 | } | 1224 | } |
| 1217 | 1225 | ||
| 1218 | static int | 1226 | static bool |
| 1219 | same_creds(struct svc_cred *cr1, struct svc_cred *cr2) | 1227 | same_creds(struct svc_cred *cr1, struct svc_cred *cr2) |
| 1220 | { | 1228 | { |
| 1221 | if ((cr1->cr_flavor != cr2->cr_flavor) | 1229 | if ((cr1->cr_flavor != cr2->cr_flavor) |
| @@ -1227,14 +1235,15 @@ same_creds(struct svc_cred *cr1, struct svc_cred *cr2) | |||
| 1227 | return true; | 1235 | return true; |
| 1228 | if (!cr1->cr_principal || !cr2->cr_principal) | 1236 | if (!cr1->cr_principal || !cr2->cr_principal) |
| 1229 | return false; | 1237 | return false; |
| 1230 | return 0 == strcmp(cr1->cr_principal, cr1->cr_principal); | 1238 | return 0 == strcmp(cr1->cr_principal, cr2->cr_principal); |
| 1231 | } | 1239 | } |
| 1232 | 1240 | ||
| 1233 | static void gen_clid(struct nfs4_client *clp) | 1241 | static void gen_clid(struct nfs4_client *clp) |
| 1234 | { | 1242 | { |
| 1235 | static u32 current_clientid = 1; | 1243 | static u32 current_clientid = 1; |
| 1244 | struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id); | ||
| 1236 | 1245 | ||
| 1237 | clp->cl_clientid.cl_boot = boot_time; | 1246 | clp->cl_clientid.cl_boot = nn->boot_time; |
| 1238 | clp->cl_clientid.cl_id = current_clientid++; | 1247 | clp->cl_clientid.cl_id = current_clientid++; |
| 1239 | } | 1248 | } |
| 1240 | 1249 | ||
| @@ -2217,8 +2226,9 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, | |||
| 2217 | nfs4_verifier confirm = setclientid_confirm->sc_confirm; | 2226 | nfs4_verifier confirm = setclientid_confirm->sc_confirm; |
| 2218 | clientid_t * clid = &setclientid_confirm->sc_clientid; | 2227 | clientid_t * clid = &setclientid_confirm->sc_clientid; |
| 2219 | __be32 status; | 2228 | __be32 status; |
| 2229 | struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id); | ||
| 2220 | 2230 | ||
| 2221 | if (STALE_CLIENTID(clid)) | 2231 | if (STALE_CLIENTID(clid, nn)) |
| 2222 | return nfserr_stale_clientid; | 2232 | return nfserr_stale_clientid; |
| 2223 | nfs4_lock_state(); | 2233 | nfs4_lock_state(); |
| 2224 | 2234 | ||
| @@ -2577,8 +2587,9 @@ nfsd4_process_open1(struct nfsd4_compound_state *cstate, | |||
| 2577 | unsigned int strhashval; | 2587 | unsigned int strhashval; |
| 2578 | struct nfs4_openowner *oo = NULL; | 2588 | struct nfs4_openowner *oo = NULL; |
| 2579 | __be32 status; | 2589 | __be32 status; |
| 2590 | struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id); | ||
| 2580 | 2591 | ||
| 2581 | if (STALE_CLIENTID(&open->op_clientid)) | 2592 | if (STALE_CLIENTID(&open->op_clientid, nn)) |
| 2582 | return nfserr_stale_clientid; | 2593 | return nfserr_stale_clientid; |
| 2583 | /* | 2594 | /* |
| 2584 | * In case we need it later, after we've already created the | 2595 | * 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) | |||
| 2876 | * Attempt to hand out a delegation. | 2887 | * Attempt to hand out a delegation. |
| 2877 | */ | 2888 | */ |
| 2878 | static void | 2889 | static void |
| 2879 | nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_ol_stateid *stp) | 2890 | nfs4_open_delegation(struct net *net, struct svc_fh *fh, |
| 2891 | struct nfsd4_open *open, struct nfs4_ol_stateid *stp) | ||
| 2880 | { | 2892 | { |
| 2881 | struct nfs4_delegation *dp; | 2893 | struct nfs4_delegation *dp; |
| 2882 | struct nfs4_openowner *oo = container_of(stp->st_stateowner, struct nfs4_openowner, oo_owner); | 2894 | 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_ | |||
| 2897 | case NFS4_OPEN_CLAIM_NULL: | 2909 | case NFS4_OPEN_CLAIM_NULL: |
| 2898 | /* Let's not give out any delegations till everyone's | 2910 | /* Let's not give out any delegations till everyone's |
| 2899 | * had the chance to reclaim theirs.... */ | 2911 | * had the chance to reclaim theirs.... */ |
| 2900 | if (locks_in_grace()) | 2912 | if (locks_in_grace(net)) |
| 2901 | goto out; | 2913 | goto out; |
| 2902 | if (!cb_up || !(oo->oo_flags & NFS4_OO_CONFIRMED)) | 2914 | if (!cb_up || !(oo->oo_flags & NFS4_OO_CONFIRMED)) |
| 2903 | goto out; | 2915 | goto out; |
| @@ -3007,14 +3019,12 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf | |||
| 3007 | status = nfs4_get_vfs_file(rqstp, fp, current_fh, open); | 3019 | status = nfs4_get_vfs_file(rqstp, fp, current_fh, open); |
| 3008 | if (status) | 3020 | if (status) |
| 3009 | goto out; | 3021 | goto out; |
| 3022 | status = nfsd4_truncate(rqstp, current_fh, open); | ||
| 3023 | if (status) | ||
| 3024 | goto out; | ||
| 3010 | stp = open->op_stp; | 3025 | stp = open->op_stp; |
| 3011 | open->op_stp = NULL; | 3026 | open->op_stp = NULL; |
| 3012 | init_open_stateid(stp, fp, open); | 3027 | init_open_stateid(stp, fp, open); |
| 3013 | status = nfsd4_truncate(rqstp, current_fh, open); | ||
| 3014 | if (status) { | ||
| 3015 | release_open_stateid(stp); | ||
| 3016 | goto out; | ||
| 3017 | } | ||
| 3018 | } | 3028 | } |
| 3019 | update_stateid(&stp->st_stid.sc_stateid); | 3029 | update_stateid(&stp->st_stid.sc_stateid); |
| 3020 | memcpy(&open->op_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t)); | 3030 | 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 | |||
| 3033 | * Attempt to hand out a delegation. No error return, because the | 3043 | * Attempt to hand out a delegation. No error return, because the |
| 3034 | * OPEN succeeds even if we fail. | 3044 | * OPEN succeeds even if we fail. |
| 3035 | */ | 3045 | */ |
| 3036 | nfs4_open_delegation(current_fh, open, stp); | 3046 | nfs4_open_delegation(SVC_NET(rqstp), current_fh, open, stp); |
| 3037 | nodeleg: | 3047 | nodeleg: |
| 3038 | status = nfs_ok; | 3048 | status = nfs_ok; |
| 3039 | 3049 | ||
| @@ -3087,12 +3097,13 @@ nfsd4_renew(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
| 3087 | { | 3097 | { |
| 3088 | struct nfs4_client *clp; | 3098 | struct nfs4_client *clp; |
| 3089 | __be32 status; | 3099 | __be32 status; |
| 3100 | struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id); | ||
| 3090 | 3101 | ||
| 3091 | nfs4_lock_state(); | 3102 | nfs4_lock_state(); |
| 3092 | dprintk("process_renew(%08x/%08x): starting\n", | 3103 | dprintk("process_renew(%08x/%08x): starting\n", |
| 3093 | clid->cl_boot, clid->cl_id); | 3104 | clid->cl_boot, clid->cl_id); |
| 3094 | status = nfserr_stale_clientid; | 3105 | status = nfserr_stale_clientid; |
| 3095 | if (STALE_CLIENTID(clid)) | 3106 | if (STALE_CLIENTID(clid, nn)) |
| 3096 | goto out; | 3107 | goto out; |
| 3097 | clp = find_confirmed_client(clid); | 3108 | clp = find_confirmed_client(clid); |
| 3098 | status = nfserr_expired; | 3109 | status = nfserr_expired; |
| @@ -3111,22 +3122,19 @@ out: | |||
| 3111 | return status; | 3122 | return status; |
| 3112 | } | 3123 | } |
| 3113 | 3124 | ||
| 3114 | static struct lock_manager nfsd4_manager = { | ||
| 3115 | }; | ||
| 3116 | |||
| 3117 | static bool grace_ended; | ||
| 3118 | |||
| 3119 | static void | 3125 | static void |
| 3120 | nfsd4_end_grace(void) | 3126 | nfsd4_end_grace(struct net *net) |
| 3121 | { | 3127 | { |
| 3128 | struct nfsd_net *nn = net_generic(net, nfsd_net_id); | ||
| 3129 | |||
| 3122 | /* do nothing if grace period already ended */ | 3130 | /* do nothing if grace period already ended */ |
| 3123 | if (grace_ended) | 3131 | if (nn->grace_ended) |
| 3124 | return; | 3132 | return; |
| 3125 | 3133 | ||
| 3126 | dprintk("NFSD: end of grace period\n"); | 3134 | dprintk("NFSD: end of grace period\n"); |
| 3127 | grace_ended = true; | 3135 | nn->grace_ended = true; |
| 3128 | nfsd4_record_grace_done(&init_net, boot_time); | 3136 | nfsd4_record_grace_done(net, nn->boot_time); |
| 3129 | locks_end_grace(&nfsd4_manager); | 3137 | locks_end_grace(&nn->nfsd4_manager); |
| 3130 | /* | 3138 | /* |
| 3131 | * Now that every NFSv4 client has had the chance to recover and | 3139 | * Now that every NFSv4 client has had the chance to recover and |
| 3132 | * to see the (possibly new, possibly shorter) lease time, we | 3140 | * to see the (possibly new, possibly shorter) lease time, we |
| @@ -3149,7 +3157,7 @@ nfs4_laundromat(void) | |||
| 3149 | nfs4_lock_state(); | 3157 | nfs4_lock_state(); |
| 3150 | 3158 | ||
| 3151 | dprintk("NFSD: laundromat service - starting\n"); | 3159 | dprintk("NFSD: laundromat service - starting\n"); |
| 3152 | nfsd4_end_grace(); | 3160 | nfsd4_end_grace(&init_net); |
| 3153 | INIT_LIST_HEAD(&reaplist); | 3161 | INIT_LIST_HEAD(&reaplist); |
| 3154 | spin_lock(&client_lock); | 3162 | spin_lock(&client_lock); |
| 3155 | list_for_each_safe(pos, next, &client_lru) { | 3163 | 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 | |||
| 3231 | } | 3239 | } |
| 3232 | 3240 | ||
| 3233 | static int | 3241 | static int |
| 3234 | STALE_STATEID(stateid_t *stateid) | 3242 | STALE_STATEID(stateid_t *stateid, struct nfsd_net *nn) |
| 3235 | { | 3243 | { |
| 3236 | if (stateid->si_opaque.so_clid.cl_boot == boot_time) | 3244 | if (stateid->si_opaque.so_clid.cl_boot == nn->boot_time) |
| 3237 | return 0; | 3245 | return 0; |
| 3238 | dprintk("NFSD: stale stateid " STATEID_FMT "!\n", | 3246 | dprintk("NFSD: stale stateid " STATEID_FMT "!\n", |
| 3239 | STATEID_VAL(stateid)); | 3247 | STATEID_VAL(stateid)); |
| @@ -3273,11 +3281,11 @@ out: | |||
| 3273 | } | 3281 | } |
| 3274 | 3282 | ||
| 3275 | static inline __be32 | 3283 | static inline __be32 |
| 3276 | check_special_stateids(svc_fh *current_fh, stateid_t *stateid, int flags) | 3284 | check_special_stateids(struct net *net, svc_fh *current_fh, stateid_t *stateid, int flags) |
| 3277 | { | 3285 | { |
| 3278 | if (ONE_STATEID(stateid) && (flags & RD_STATE)) | 3286 | if (ONE_STATEID(stateid) && (flags & RD_STATE)) |
| 3279 | return nfs_ok; | 3287 | return nfs_ok; |
| 3280 | else if (locks_in_grace()) { | 3288 | else if (locks_in_grace(net)) { |
| 3281 | /* Answer in remaining cases depends on existence of | 3289 | /* Answer in remaining cases depends on existence of |
| 3282 | * conflicting state; so we must wait out the grace period. */ | 3290 | * conflicting state; so we must wait out the grace period. */ |
| 3283 | return nfserr_grace; | 3291 | return nfserr_grace; |
| @@ -3294,9 +3302,9 @@ check_special_stateids(svc_fh *current_fh, stateid_t *stateid, int flags) | |||
| 3294 | * that are not able to provide mandatory locking. | 3302 | * that are not able to provide mandatory locking. |
| 3295 | */ | 3303 | */ |
| 3296 | static inline int | 3304 | static inline int |
| 3297 | grace_disallows_io(struct inode *inode) | 3305 | grace_disallows_io(struct net *net, struct inode *inode) |
| 3298 | { | 3306 | { |
| 3299 | return locks_in_grace() && mandatory_lock(inode); | 3307 | return locks_in_grace(net) && mandatory_lock(inode); |
| 3300 | } | 3308 | } |
| 3301 | 3309 | ||
| 3302 | /* Returns true iff a is later than b: */ | 3310 | /* 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 | |||
| 3333 | return nfserr_old_stateid; | 3341 | return nfserr_old_stateid; |
| 3334 | } | 3342 | } |
| 3335 | 3343 | ||
| 3336 | __be32 nfs4_validate_stateid(struct nfs4_client *cl, stateid_t *stateid) | 3344 | static __be32 nfsd4_validate_stateid(struct nfs4_client *cl, stateid_t *stateid) |
| 3337 | { | 3345 | { |
| 3338 | struct nfs4_stid *s; | 3346 | struct nfs4_stid *s; |
| 3339 | struct nfs4_ol_stateid *ols; | 3347 | struct nfs4_ol_stateid *ols; |
| 3340 | __be32 status; | 3348 | __be32 status; |
| 3341 | 3349 | ||
| 3342 | if (STALE_STATEID(stateid)) | 3350 | if (ZERO_STATEID(stateid) || ONE_STATEID(stateid)) |
| 3343 | return nfserr_stale_stateid; | 3351 | return nfserr_bad_stateid; |
| 3344 | 3352 | /* Client debugging aid. */ | |
| 3353 | if (!same_clid(&stateid->si_opaque.so_clid, &cl->cl_clientid)) { | ||
| 3354 | char addr_str[INET6_ADDRSTRLEN]; | ||
| 3355 | rpc_ntop((struct sockaddr *)&cl->cl_addr, addr_str, | ||
| 3356 | sizeof(addr_str)); | ||
| 3357 | pr_warn_ratelimited("NFSD: client %s testing state ID " | ||
| 3358 | "with incorrect client ID\n", addr_str); | ||
| 3359 | return nfserr_bad_stateid; | ||
| 3360 | } | ||
| 3345 | s = find_stateid(cl, stateid); | 3361 | s = find_stateid(cl, stateid); |
| 3346 | if (!s) | 3362 | if (!s) |
| 3347 | return nfserr_stale_stateid; | 3363 | return nfserr_bad_stateid; |
| 3348 | status = check_stateid_generation(stateid, &s->sc_stateid, 1); | 3364 | status = check_stateid_generation(stateid, &s->sc_stateid, 1); |
| 3349 | if (status) | 3365 | if (status) |
| 3350 | return status; | 3366 | return status; |
| @@ -3360,10 +3376,11 @@ __be32 nfs4_validate_stateid(struct nfs4_client *cl, stateid_t *stateid) | |||
| 3360 | static __be32 nfsd4_lookup_stateid(stateid_t *stateid, unsigned char typemask, struct nfs4_stid **s) | 3376 | static __be32 nfsd4_lookup_stateid(stateid_t *stateid, unsigned char typemask, struct nfs4_stid **s) |
| 3361 | { | 3377 | { |
| 3362 | struct nfs4_client *cl; | 3378 | struct nfs4_client *cl; |
| 3379 | struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id); | ||
| 3363 | 3380 | ||
| 3364 | if (ZERO_STATEID(stateid) || ONE_STATEID(stateid)) | 3381 | if (ZERO_STATEID(stateid) || ONE_STATEID(stateid)) |
| 3365 | return nfserr_bad_stateid; | 3382 | return nfserr_bad_stateid; |
| 3366 | if (STALE_STATEID(stateid)) | 3383 | if (STALE_STATEID(stateid, nn)) |
| 3367 | return nfserr_stale_stateid; | 3384 | return nfserr_stale_stateid; |
| 3368 | cl = find_confirmed_client(&stateid->si_opaque.so_clid); | 3385 | cl = find_confirmed_client(&stateid->si_opaque.so_clid); |
| 3369 | if (!cl) | 3386 | if (!cl) |
| @@ -3379,7 +3396,7 @@ static __be32 nfsd4_lookup_stateid(stateid_t *stateid, unsigned char typemask, s | |||
| 3379 | * Checks for stateid operations | 3396 | * Checks for stateid operations |
| 3380 | */ | 3397 | */ |
| 3381 | __be32 | 3398 | __be32 |
| 3382 | nfs4_preprocess_stateid_op(struct nfsd4_compound_state *cstate, | 3399 | nfs4_preprocess_stateid_op(struct net *net, struct nfsd4_compound_state *cstate, |
| 3383 | stateid_t *stateid, int flags, struct file **filpp) | 3400 | stateid_t *stateid, int flags, struct file **filpp) |
| 3384 | { | 3401 | { |
| 3385 | struct nfs4_stid *s; | 3402 | struct nfs4_stid *s; |
| @@ -3392,11 +3409,11 @@ nfs4_preprocess_stateid_op(struct nfsd4_compound_state *cstate, | |||
| 3392 | if (filpp) | 3409 | if (filpp) |
| 3393 | *filpp = NULL; | 3410 | *filpp = NULL; |
| 3394 | 3411 | ||
| 3395 | if (grace_disallows_io(ino)) | 3412 | if (grace_disallows_io(net, ino)) |
| 3396 | return nfserr_grace; | 3413 | return nfserr_grace; |
| 3397 | 3414 | ||
| 3398 | if (ZERO_STATEID(stateid) || ONE_STATEID(stateid)) | 3415 | if (ZERO_STATEID(stateid) || ONE_STATEID(stateid)) |
| 3399 | return check_special_stateids(current_fh, stateid, flags); | 3416 | return check_special_stateids(net, current_fh, stateid, flags); |
| 3400 | 3417 | ||
| 3401 | status = nfsd4_lookup_stateid(stateid, NFS4_DELEG_STID|NFS4_OPEN_STID|NFS4_LOCK_STID, &s); | 3418 | status = nfsd4_lookup_stateid(stateid, NFS4_DELEG_STID|NFS4_OPEN_STID|NFS4_LOCK_STID, &s); |
| 3402 | if (status) | 3419 | if (status) |
| @@ -3463,7 +3480,8 @@ nfsd4_test_stateid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
| 3463 | 3480 | ||
| 3464 | nfs4_lock_state(); | 3481 | nfs4_lock_state(); |
| 3465 | list_for_each_entry(stateid, &test_stateid->ts_stateid_list, ts_id_list) | 3482 | list_for_each_entry(stateid, &test_stateid->ts_stateid_list, ts_id_list) |
| 3466 | stateid->ts_id_status = nfs4_validate_stateid(cl, &stateid->ts_id_stateid); | 3483 | stateid->ts_id_status = |
| 3484 | nfsd4_validate_stateid(cl, &stateid->ts_id_stateid); | ||
| 3467 | nfs4_unlock_state(); | 3485 | nfs4_unlock_state(); |
| 3468 | 3486 | ||
| 3469 | return nfs_ok; | 3487 | return nfs_ok; |
| @@ -3750,12 +3768,19 @@ nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
| 3750 | nfsd4_close_open_stateid(stp); | 3768 | nfsd4_close_open_stateid(stp); |
| 3751 | oo->oo_last_closed_stid = stp; | 3769 | oo->oo_last_closed_stid = stp; |
| 3752 | 3770 | ||
| 3753 | /* place unused nfs4_stateowners on so_close_lru list to be | 3771 | if (list_empty(&oo->oo_owner.so_stateids)) { |
| 3754 | * released by the laundromat service after the lease period | 3772 | if (cstate->minorversion) { |
| 3755 | * to enable us to handle CLOSE replay | 3773 | release_openowner(oo); |
| 3756 | */ | 3774 | cstate->replay_owner = NULL; |
| 3757 | if (list_empty(&oo->oo_owner.so_stateids)) | 3775 | } else { |
| 3758 | move_to_close_lru(oo); | 3776 | /* |
| 3777 | * In the 4.0 case we need to keep the owners around a | ||
| 3778 | * little while to handle CLOSE replay. | ||
| 3779 | */ | ||
| 3780 | if (list_empty(&oo->oo_owner.so_stateids)) | ||
| 3781 | move_to_close_lru(oo); | ||
| 3782 | } | ||
| 3783 | } | ||
| 3759 | out: | 3784 | out: |
| 3760 | if (!cstate->replay_owner) | 3785 | if (!cstate->replay_owner) |
| 3761 | nfs4_unlock_state(); | 3786 | nfs4_unlock_state(); |
| @@ -4027,6 +4052,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
| 4027 | bool new_state = false; | 4052 | bool new_state = false; |
| 4028 | int lkflg; | 4053 | int lkflg; |
| 4029 | int err; | 4054 | int err; |
| 4055 | struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id); | ||
| 4030 | 4056 | ||
| 4031 | dprintk("NFSD: nfsd4_lock: start=%Ld length=%Ld\n", | 4057 | dprintk("NFSD: nfsd4_lock: start=%Ld length=%Ld\n", |
| 4032 | (long long) lock->lk_offset, | 4058 | (long long) lock->lk_offset, |
| @@ -4044,11 +4070,6 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
| 4044 | nfs4_lock_state(); | 4070 | nfs4_lock_state(); |
| 4045 | 4071 | ||
| 4046 | if (lock->lk_is_new) { | 4072 | if (lock->lk_is_new) { |
| 4047 | /* | ||
| 4048 | * Client indicates that this is a new lockowner. | ||
| 4049 | * Use open owner and open stateid to create lock owner and | ||
| 4050 | * lock stateid. | ||
| 4051 | */ | ||
| 4052 | struct nfs4_ol_stateid *open_stp = NULL; | 4073 | struct nfs4_ol_stateid *open_stp = NULL; |
| 4053 | 4074 | ||
| 4054 | if (nfsd4_has_session(cstate)) | 4075 | if (nfsd4_has_session(cstate)) |
| @@ -4058,7 +4079,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
| 4058 | sizeof(clientid_t)); | 4079 | sizeof(clientid_t)); |
| 4059 | 4080 | ||
| 4060 | status = nfserr_stale_clientid; | 4081 | status = nfserr_stale_clientid; |
| 4061 | if (STALE_CLIENTID(&lock->lk_new_clientid)) | 4082 | if (STALE_CLIENTID(&lock->lk_new_clientid, nn)) |
| 4062 | goto out; | 4083 | goto out; |
| 4063 | 4084 | ||
| 4064 | /* validate and update open stateid and open seqid */ | 4085 | /* validate and update open stateid and open seqid */ |
| @@ -4075,17 +4096,13 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
| 4075 | goto out; | 4096 | goto out; |
| 4076 | status = lookup_or_create_lock_state(cstate, open_stp, lock, | 4097 | status = lookup_or_create_lock_state(cstate, open_stp, lock, |
| 4077 | &lock_stp, &new_state); | 4098 | &lock_stp, &new_state); |
| 4078 | if (status) | 4099 | } else |
| 4079 | goto out; | ||
| 4080 | } else { | ||
| 4081 | /* lock (lock owner + lock stateid) already exists */ | ||
| 4082 | status = nfs4_preprocess_seqid_op(cstate, | 4100 | status = nfs4_preprocess_seqid_op(cstate, |
| 4083 | lock->lk_old_lock_seqid, | 4101 | lock->lk_old_lock_seqid, |
| 4084 | &lock->lk_old_lock_stateid, | 4102 | &lock->lk_old_lock_stateid, |
| 4085 | NFS4_LOCK_STID, &lock_stp); | 4103 | NFS4_LOCK_STID, &lock_stp); |
| 4086 | if (status) | 4104 | if (status) |
| 4087 | goto out; | 4105 | goto out; |
| 4088 | } | ||
| 4089 | lock_sop = lockowner(lock_stp->st_stateowner); | 4106 | lock_sop = lockowner(lock_stp->st_stateowner); |
| 4090 | 4107 | ||
| 4091 | lkflg = setlkflg(lock->lk_type); | 4108 | lkflg = setlkflg(lock->lk_type); |
| @@ -4094,10 +4111,10 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
| 4094 | goto out; | 4111 | goto out; |
| 4095 | 4112 | ||
| 4096 | status = nfserr_grace; | 4113 | status = nfserr_grace; |
| 4097 | if (locks_in_grace() && !lock->lk_reclaim) | 4114 | if (locks_in_grace(SVC_NET(rqstp)) && !lock->lk_reclaim) |
| 4098 | goto out; | 4115 | goto out; |
| 4099 | status = nfserr_no_grace; | 4116 | status = nfserr_no_grace; |
| 4100 | if (!locks_in_grace() && lock->lk_reclaim) | 4117 | if (!locks_in_grace(SVC_NET(rqstp)) && lock->lk_reclaim) |
| 4101 | goto out; | 4118 | goto out; |
| 4102 | 4119 | ||
| 4103 | locks_init_lock(&file_lock); | 4120 | locks_init_lock(&file_lock); |
| @@ -4196,8 +4213,9 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
| 4196 | struct file_lock file_lock; | 4213 | struct file_lock file_lock; |
| 4197 | struct nfs4_lockowner *lo; | 4214 | struct nfs4_lockowner *lo; |
| 4198 | __be32 status; | 4215 | __be32 status; |
| 4216 | struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id); | ||
| 4199 | 4217 | ||
| 4200 | if (locks_in_grace()) | 4218 | if (locks_in_grace(SVC_NET(rqstp))) |
| 4201 | return nfserr_grace; | 4219 | return nfserr_grace; |
| 4202 | 4220 | ||
| 4203 | if (check_lock_length(lockt->lt_offset, lockt->lt_length)) | 4221 | 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, | |||
| 4206 | nfs4_lock_state(); | 4224 | nfs4_lock_state(); |
| 4207 | 4225 | ||
| 4208 | status = nfserr_stale_clientid; | 4226 | status = nfserr_stale_clientid; |
| 4209 | if (!nfsd4_has_session(cstate) && STALE_CLIENTID(&lockt->lt_clientid)) | 4227 | if (!nfsd4_has_session(cstate) && STALE_CLIENTID(&lockt->lt_clientid, nn)) |
| 4210 | goto out; | 4228 | goto out; |
| 4211 | 4229 | ||
| 4212 | if ((status = fh_verify(rqstp, &cstate->current_fh, S_IFREG, 0))) | 4230 | if ((status = fh_verify(rqstp, &cstate->current_fh, S_IFREG, 0))) |
| @@ -4355,6 +4373,7 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp, | |||
| 4355 | struct list_head matches; | 4373 | struct list_head matches; |
| 4356 | unsigned int hashval = ownerstr_hashval(clid->cl_id, owner); | 4374 | unsigned int hashval = ownerstr_hashval(clid->cl_id, owner); |
| 4357 | __be32 status; | 4375 | __be32 status; |
| 4376 | struct nfsd_net *nn = net_generic(&init_net, nfsd_net_id); | ||
| 4358 | 4377 | ||
| 4359 | dprintk("nfsd4_release_lockowner clientid: (%08x/%08x):\n", | 4378 | dprintk("nfsd4_release_lockowner clientid: (%08x/%08x):\n", |
| 4360 | clid->cl_boot, clid->cl_id); | 4379 | clid->cl_boot, clid->cl_id); |
| @@ -4362,7 +4381,7 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp, | |||
| 4362 | /* XXX check for lease expiration */ | 4381 | /* XXX check for lease expiration */ |
| 4363 | 4382 | ||
| 4364 | status = nfserr_stale_clientid; | 4383 | status = nfserr_stale_clientid; |
| 4365 | if (STALE_CLIENTID(clid)) | 4384 | if (STALE_CLIENTID(clid, nn)) |
| 4366 | return status; | 4385 | return status; |
| 4367 | 4386 | ||
| 4368 | nfs4_lock_state(); | 4387 | nfs4_lock_state(); |
| @@ -4564,7 +4583,7 @@ void nfsd_forget_openowners(u64 num) | |||
| 4564 | printk(KERN_INFO "NFSD: Forgot %d open owners", count); | 4583 | printk(KERN_INFO "NFSD: Forgot %d open owners", count); |
| 4565 | } | 4584 | } |
| 4566 | 4585 | ||
| 4567 | int nfsd_process_n_delegations(u64 num, void (*deleg_func)(struct nfs4_delegation *)) | 4586 | int nfsd_process_n_delegations(u64 num, struct list_head *list) |
| 4568 | { | 4587 | { |
| 4569 | int i, count = 0; | 4588 | int i, count = 0; |
| 4570 | struct nfs4_file *fp, *fnext; | 4589 | struct nfs4_file *fp, *fnext; |
| @@ -4573,7 +4592,7 @@ int nfsd_process_n_delegations(u64 num, void (*deleg_func)(struct nfs4_delegatio | |||
| 4573 | for (i = 0; i < FILE_HASH_SIZE; i++) { | 4592 | for (i = 0; i < FILE_HASH_SIZE; i++) { |
| 4574 | list_for_each_entry_safe(fp, fnext, &file_hashtbl[i], fi_hash) { | 4593 | list_for_each_entry_safe(fp, fnext, &file_hashtbl[i], fi_hash) { |
| 4575 | list_for_each_entry_safe(dp, dnext, &fp->fi_delegations, dl_perfile) { | 4594 | list_for_each_entry_safe(dp, dnext, &fp->fi_delegations, dl_perfile) { |
| 4576 | deleg_func(dp); | 4595 | list_move(&dp->dl_recall_lru, list); |
| 4577 | if (++count == num) | 4596 | if (++count == num) |
| 4578 | return count; | 4597 | return count; |
| 4579 | } | 4598 | } |
| @@ -4586,9 +4605,16 @@ int nfsd_process_n_delegations(u64 num, void (*deleg_func)(struct nfs4_delegatio | |||
| 4586 | void nfsd_forget_delegations(u64 num) | 4605 | void nfsd_forget_delegations(u64 num) |
| 4587 | { | 4606 | { |
| 4588 | unsigned int count; | 4607 | unsigned int count; |
| 4608 | LIST_HEAD(victims); | ||
| 4609 | struct nfs4_delegation *dp, *dnext; | ||
| 4610 | |||
| 4611 | spin_lock(&recall_lock); | ||
| 4612 | count = nfsd_process_n_delegations(num, &victims); | ||
| 4613 | spin_unlock(&recall_lock); | ||
| 4589 | 4614 | ||
| 4590 | nfs4_lock_state(); | 4615 | nfs4_lock_state(); |
| 4591 | count = nfsd_process_n_delegations(num, unhash_delegation); | 4616 | list_for_each_entry_safe(dp, dnext, &victims, dl_recall_lru) |
| 4617 | unhash_delegation(dp); | ||
| 4592 | nfs4_unlock_state(); | 4618 | nfs4_unlock_state(); |
| 4593 | 4619 | ||
| 4594 | printk(KERN_INFO "NFSD: Forgot %d delegations", count); | 4620 | printk(KERN_INFO "NFSD: Forgot %d delegations", count); |
| @@ -4597,12 +4623,16 @@ void nfsd_forget_delegations(u64 num) | |||
| 4597 | void nfsd_recall_delegations(u64 num) | 4623 | void nfsd_recall_delegations(u64 num) |
| 4598 | { | 4624 | { |
| 4599 | unsigned int count; | 4625 | unsigned int count; |
| 4626 | LIST_HEAD(victims); | ||
| 4627 | struct nfs4_delegation *dp, *dnext; | ||
| 4600 | 4628 | ||
| 4601 | nfs4_lock_state(); | ||
| 4602 | spin_lock(&recall_lock); | 4629 | spin_lock(&recall_lock); |
| 4603 | count = nfsd_process_n_delegations(num, nfsd_break_one_deleg); | 4630 | count = nfsd_process_n_delegations(num, &victims); |
| 4631 | list_for_each_entry_safe(dp, dnext, &victims, dl_recall_lru) { | ||
| 4632 | list_del(&dp->dl_recall_lru); | ||
| 4633 | nfsd_break_one_deleg(dp); | ||
| 4634 | } | ||
| 4604 | spin_unlock(&recall_lock); | 4635 | spin_unlock(&recall_lock); |
| 4605 | nfs4_unlock_state(); | ||
| 4606 | 4636 | ||
| 4607 | printk(KERN_INFO "NFSD: Recalled %d delegations", count); | 4637 | printk(KERN_INFO "NFSD: Recalled %d delegations", count); |
| 4608 | } | 4638 | } |
| @@ -4665,6 +4695,8 @@ set_max_delegations(void) | |||
| 4665 | int | 4695 | int |
| 4666 | nfs4_state_start(void) | 4696 | nfs4_state_start(void) |
| 4667 | { | 4697 | { |
| 4698 | struct net *net = &init_net; | ||
| 4699 | struct nfsd_net *nn = net_generic(net, nfsd_net_id); | ||
| 4668 | int ret; | 4700 | int ret; |
| 4669 | 4701 | ||
| 4670 | /* | 4702 | /* |
| @@ -4674,11 +4706,11 @@ nfs4_state_start(void) | |||
| 4674 | * to that instead and then do most of the rest of this on a per-net | 4706 | * to that instead and then do most of the rest of this on a per-net |
| 4675 | * basis. | 4707 | * basis. |
| 4676 | */ | 4708 | */ |
| 4677 | get_net(&init_net); | 4709 | get_net(net); |
| 4678 | nfsd4_client_tracking_init(&init_net); | 4710 | nfsd4_client_tracking_init(net); |
| 4679 | boot_time = get_seconds(); | 4711 | nn->boot_time = get_seconds(); |
| 4680 | locks_start_grace(&nfsd4_manager); | 4712 | locks_start_grace(net, &nn->nfsd4_manager); |
| 4681 | grace_ended = false; | 4713 | nn->grace_ended = false; |
| 4682 | printk(KERN_INFO "NFSD: starting %ld-second grace period\n", | 4714 | printk(KERN_INFO "NFSD: starting %ld-second grace period\n", |
| 4683 | nfsd4_grace); | 4715 | nfsd4_grace); |
| 4684 | ret = set_callback_cred(); | 4716 | ret = set_callback_cred(); |
| @@ -4700,8 +4732,8 @@ nfs4_state_start(void) | |||
| 4700 | out_free_laundry: | 4732 | out_free_laundry: |
| 4701 | destroy_workqueue(laundry_wq); | 4733 | destroy_workqueue(laundry_wq); |
| 4702 | out_recovery: | 4734 | out_recovery: |
| 4703 | nfsd4_client_tracking_exit(&init_net); | 4735 | nfsd4_client_tracking_exit(net); |
| 4704 | put_net(&init_net); | 4736 | put_net(net); |
| 4705 | return ret; | 4737 | return ret; |
| 4706 | } | 4738 | } |
| 4707 | 4739 | ||
| @@ -4742,9 +4774,12 @@ __nfs4_state_shutdown(void) | |||
| 4742 | void | 4774 | void |
| 4743 | nfs4_state_shutdown(void) | 4775 | nfs4_state_shutdown(void) |
| 4744 | { | 4776 | { |
| 4777 | struct net *net = &init_net; | ||
| 4778 | struct nfsd_net *nn = net_generic(net, nfsd_net_id); | ||
| 4779 | |||
| 4745 | cancel_delayed_work_sync(&laundromat_work); | 4780 | cancel_delayed_work_sync(&laundromat_work); |
| 4746 | destroy_workqueue(laundry_wq); | 4781 | destroy_workqueue(laundry_wq); |
| 4747 | locks_end_grace(&nfsd4_manager); | 4782 | locks_end_grace(&nn->nfsd4_manager); |
| 4748 | nfs4_lock_state(); | 4783 | nfs4_lock_state(); |
| 4749 | __nfs4_state_shutdown(); | 4784 | __nfs4_state_shutdown(); |
| 4750 | nfs4_unlock_state(); | 4785 | nfs4_unlock_state(); |
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 4949667c84ea..6322df36031f 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c | |||
| @@ -2259,7 +2259,7 @@ out_acl: | |||
| 2259 | if (bmval0 & FATTR4_WORD0_CASE_INSENSITIVE) { | 2259 | if (bmval0 & FATTR4_WORD0_CASE_INSENSITIVE) { |
| 2260 | if ((buflen -= 4) < 0) | 2260 | if ((buflen -= 4) < 0) |
| 2261 | goto out_resource; | 2261 | goto out_resource; |
| 2262 | WRITE32(1); | 2262 | WRITE32(0); |
| 2263 | } | 2263 | } |
| 2264 | if (bmval0 & FATTR4_WORD0_CASE_PRESERVING) { | 2264 | if (bmval0 & FATTR4_WORD0_CASE_PRESERVING) { |
| 2265 | if ((buflen -= 4) < 0) | 2265 | if ((buflen -= 4) < 0) |
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index c55298ed5772..fa49cff5ee65 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c | |||
| @@ -673,9 +673,7 @@ static ssize_t __write_ports_addfd(char *buf) | |||
| 673 | 673 | ||
| 674 | err = svc_addsock(nfsd_serv, fd, buf, SIMPLE_TRANSACTION_LIMIT); | 674 | err = svc_addsock(nfsd_serv, fd, buf, SIMPLE_TRANSACTION_LIMIT); |
| 675 | if (err < 0) { | 675 | if (err < 0) { |
| 676 | if (nfsd_serv->sv_nrthreads == 1) | 676 | nfsd_destroy(net); |
| 677 | svc_shutdown_net(nfsd_serv, net); | ||
| 678 | svc_destroy(nfsd_serv); | ||
| 679 | return err; | 677 | return err; |
| 680 | } | 678 | } |
| 681 | 679 | ||
| @@ -744,9 +742,7 @@ out_close: | |||
| 744 | svc_xprt_put(xprt); | 742 | svc_xprt_put(xprt); |
| 745 | } | 743 | } |
| 746 | out_err: | 744 | out_err: |
| 747 | if (nfsd_serv->sv_nrthreads == 1) | 745 | nfsd_destroy(net); |
| 748 | svc_shutdown_net(nfsd_serv, net); | ||
| 749 | svc_destroy(nfsd_serv); | ||
| 750 | return err; | 746 | return err; |
| 751 | } | 747 | } |
| 752 | 748 | ||
diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h index 1671429ffa66..2244222368ab 100644 --- a/fs/nfsd/nfsd.h +++ b/fs/nfsd/nfsd.h | |||
| @@ -72,6 +72,19 @@ int nfsd_nrthreads(void); | |||
| 72 | int nfsd_nrpools(void); | 72 | int nfsd_nrpools(void); |
| 73 | int nfsd_get_nrthreads(int n, int *); | 73 | int nfsd_get_nrthreads(int n, int *); |
| 74 | int nfsd_set_nrthreads(int n, int *); | 74 | int nfsd_set_nrthreads(int n, int *); |
| 75 | int nfsd_pool_stats_open(struct inode *, struct file *); | ||
| 76 | int nfsd_pool_stats_release(struct inode *, struct file *); | ||
| 77 | |||
| 78 | static inline void nfsd_destroy(struct net *net) | ||
| 79 | { | ||
| 80 | int destroy = (nfsd_serv->sv_nrthreads == 1); | ||
| 81 | |||
| 82 | if (destroy) | ||
| 83 | svc_shutdown_net(nfsd_serv, net); | ||
| 84 | svc_destroy(nfsd_serv); | ||
| 85 | if (destroy) | ||
| 86 | nfsd_serv = NULL; | ||
| 87 | } | ||
| 75 | 88 | ||
| 76 | #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) | 89 | #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) |
| 77 | #ifdef CONFIG_NFSD_V2_ACL | 90 | #ifdef CONFIG_NFSD_V2_ACL |
diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index ee709fc8f58b..240473cb708f 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c | |||
| @@ -254,8 +254,6 @@ static void nfsd_shutdown(void) | |||
| 254 | 254 | ||
| 255 | static void nfsd_last_thread(struct svc_serv *serv, struct net *net) | 255 | static void nfsd_last_thread(struct svc_serv *serv, struct net *net) |
| 256 | { | 256 | { |
| 257 | /* When last nfsd thread exits we need to do some clean-up */ | ||
| 258 | nfsd_serv = NULL; | ||
| 259 | nfsd_shutdown(); | 257 | nfsd_shutdown(); |
| 260 | 258 | ||
| 261 | svc_rpcb_cleanup(serv, net); | 259 | svc_rpcb_cleanup(serv, net); |
| @@ -332,6 +330,7 @@ static int nfsd_get_default_max_blksize(void) | |||
| 332 | int nfsd_create_serv(void) | 330 | int nfsd_create_serv(void) |
| 333 | { | 331 | { |
| 334 | int error; | 332 | int error; |
| 333 | struct net *net = current->nsproxy->net_ns; | ||
| 335 | 334 | ||
| 336 | WARN_ON(!mutex_is_locked(&nfsd_mutex)); | 335 | WARN_ON(!mutex_is_locked(&nfsd_mutex)); |
| 337 | if (nfsd_serv) { | 336 | if (nfsd_serv) { |
| @@ -346,7 +345,7 @@ int nfsd_create_serv(void) | |||
| 346 | if (nfsd_serv == NULL) | 345 | if (nfsd_serv == NULL) |
| 347 | return -ENOMEM; | 346 | return -ENOMEM; |
| 348 | 347 | ||
| 349 | error = svc_bind(nfsd_serv, current->nsproxy->net_ns); | 348 | error = svc_bind(nfsd_serv, net); |
| 350 | if (error < 0) { | 349 | if (error < 0) { |
| 351 | svc_destroy(nfsd_serv); | 350 | svc_destroy(nfsd_serv); |
| 352 | return error; | 351 | return error; |
| @@ -427,11 +426,7 @@ int nfsd_set_nrthreads(int n, int *nthreads) | |||
| 427 | if (err) | 426 | if (err) |
| 428 | break; | 427 | break; |
| 429 | } | 428 | } |
| 430 | 429 | nfsd_destroy(net); | |
| 431 | if (nfsd_serv->sv_nrthreads == 1) | ||
| 432 | svc_shutdown_net(nfsd_serv, net); | ||
| 433 | svc_destroy(nfsd_serv); | ||
| 434 | |||
| 435 | return err; | 430 | return err; |
| 436 | } | 431 | } |
| 437 | 432 | ||
| @@ -478,9 +473,7 @@ out_shutdown: | |||
| 478 | if (error < 0 && !nfsd_up_before) | 473 | if (error < 0 && !nfsd_up_before) |
| 479 | nfsd_shutdown(); | 474 | nfsd_shutdown(); |
| 480 | out_destroy: | 475 | out_destroy: |
| 481 | if (nfsd_serv->sv_nrthreads == 1) | 476 | nfsd_destroy(net); /* Release server */ |
| 482 | svc_shutdown_net(nfsd_serv, net); | ||
| 483 | svc_destroy(nfsd_serv); /* Release server */ | ||
| 484 | out: | 477 | out: |
| 485 | mutex_unlock(&nfsd_mutex); | 478 | mutex_unlock(&nfsd_mutex); |
| 486 | return error; | 479 | return error; |
| @@ -563,12 +556,13 @@ nfsd(void *vrqstp) | |||
| 563 | nfsdstats.th_cnt --; | 556 | nfsdstats.th_cnt --; |
| 564 | 557 | ||
| 565 | out: | 558 | out: |
| 566 | if (rqstp->rq_server->sv_nrthreads == 1) | 559 | rqstp->rq_server = NULL; |
| 567 | svc_shutdown_net(rqstp->rq_server, &init_net); | ||
| 568 | 560 | ||
| 569 | /* Release the thread */ | 561 | /* Release the thread */ |
| 570 | svc_exit_thread(rqstp); | 562 | svc_exit_thread(rqstp); |
| 571 | 563 | ||
| 564 | nfsd_destroy(&init_net); | ||
| 565 | |||
| 572 | /* Release module */ | 566 | /* Release module */ |
| 573 | mutex_unlock(&nfsd_mutex); | 567 | mutex_unlock(&nfsd_mutex); |
| 574 | module_put_and_exit(0); | 568 | module_put_and_exit(0); |
| @@ -682,9 +676,7 @@ int nfsd_pool_stats_release(struct inode *inode, struct file *file) | |||
| 682 | 676 | ||
| 683 | mutex_lock(&nfsd_mutex); | 677 | mutex_lock(&nfsd_mutex); |
| 684 | /* this function really, really should have been called svc_put() */ | 678 | /* this function really, really should have been called svc_put() */ |
| 685 | if (nfsd_serv->sv_nrthreads == 1) | 679 | nfsd_destroy(net); |
| 686 | svc_shutdown_net(nfsd_serv, net); | ||
| 687 | svc_destroy(nfsd_serv); | ||
| 688 | mutex_unlock(&nfsd_mutex); | 680 | mutex_unlock(&nfsd_mutex); |
| 689 | return ret; | 681 | return ret; |
| 690 | } | 682 | } |
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index 849091e16ea6..e6173147f982 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h | |||
| @@ -450,8 +450,10 @@ static inline struct nfs4_ol_stateid *openlockstateid(struct nfs4_stid *s) | |||
| 450 | #define WR_STATE 0x00000020 | 450 | #define WR_STATE 0x00000020 |
| 451 | 451 | ||
| 452 | struct nfsd4_compound_state; | 452 | struct nfsd4_compound_state; |
| 453 | struct nfsd_net; | ||
| 453 | 454 | ||
| 454 | extern __be32 nfs4_preprocess_stateid_op(struct nfsd4_compound_state *cstate, | 455 | extern __be32 nfs4_preprocess_stateid_op(struct net *net, |
| 456 | struct nfsd4_compound_state *cstate, | ||
| 455 | stateid_t *stateid, int flags, struct file **filp); | 457 | stateid_t *stateid, int flags, struct file **filp); |
| 456 | extern void nfs4_lock_state(void); | 458 | extern void nfs4_lock_state(void); |
| 457 | extern void nfs4_unlock_state(void); | 459 | extern void nfs4_unlock_state(void); |
| @@ -475,7 +477,6 @@ extern __be32 nfs4_make_rec_clidname(char *clidname, struct xdr_netobj *clname); | |||
| 475 | extern int nfs4_client_to_reclaim(const char *name); | 477 | extern int nfs4_client_to_reclaim(const char *name); |
| 476 | extern int nfs4_has_reclaimed_state(const char *name, bool use_exchange_id); | 478 | extern int nfs4_has_reclaimed_state(const char *name, bool use_exchange_id); |
| 477 | extern void release_session_client(struct nfsd4_session *); | 479 | extern void release_session_client(struct nfsd4_session *); |
| 478 | extern __be32 nfs4_validate_stateid(struct nfs4_client *, stateid_t *); | ||
| 479 | extern void nfsd4_purge_closed_stateid(struct nfs4_stateowner *); | 480 | extern void nfsd4_purge_closed_stateid(struct nfs4_stateowner *); |
| 480 | 481 | ||
| 481 | /* nfs4recover operations */ | 482 | /* nfs4recover operations */ |
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 4700a0a929d7..702f64e820c3 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
| @@ -757,8 +757,16 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type, | |||
| 757 | * If we get here, then the client has already done an "open", | 757 | * If we get here, then the client has already done an "open", |
| 758 | * and (hopefully) checked permission - so allow OWNER_OVERRIDE | 758 | * and (hopefully) checked permission - so allow OWNER_OVERRIDE |
| 759 | * in case a chmod has now revoked permission. | 759 | * in case a chmod has now revoked permission. |
| 760 | * | ||
| 761 | * Arguably we should also allow the owner override for | ||
| 762 | * directories, but we never have and it doesn't seem to have | ||
| 763 | * caused anyone a problem. If we were to change this, note | ||
| 764 | * also that our filldir callbacks would need a variant of | ||
| 765 | * lookup_one_len that doesn't check permissions. | ||
| 760 | */ | 766 | */ |
| 761 | err = fh_verify(rqstp, fhp, type, may_flags | NFSD_MAY_OWNER_OVERRIDE); | 767 | if (type == S_IFREG) |
| 768 | may_flags |= NFSD_MAY_OWNER_OVERRIDE; | ||
| 769 | err = fh_verify(rqstp, fhp, type, may_flags); | ||
| 762 | if (err) | 770 | if (err) |
| 763 | goto out; | 771 | goto out; |
| 764 | 772 | ||
diff --git a/include/linux/fs.h b/include/linux/fs.h index 8fabb037a48d..b178f9e91e23 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
| @@ -1163,9 +1163,10 @@ struct lock_manager { | |||
| 1163 | struct list_head list; | 1163 | struct list_head list; |
| 1164 | }; | 1164 | }; |
| 1165 | 1165 | ||
| 1166 | void locks_start_grace(struct lock_manager *); | 1166 | struct net; |
| 1167 | void locks_start_grace(struct net *, struct lock_manager *); | ||
| 1167 | void locks_end_grace(struct lock_manager *); | 1168 | void locks_end_grace(struct lock_manager *); |
| 1168 | int locks_in_grace(void); | 1169 | int locks_in_grace(struct net *); |
| 1169 | 1170 | ||
| 1170 | /* that will die - we need it for nfs_lock_info */ | 1171 | /* that will die - we need it for nfs_lock_info */ |
| 1171 | #include <linux/nfs_fs_i.h> | 1172 | #include <linux/nfs_fs_i.h> |
diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h index f04ce6ac6d04..f5a051a79273 100644 --- a/include/linux/lockd/lockd.h +++ b/include/linux/lockd/lockd.h | |||
| @@ -262,11 +262,11 @@ typedef int (*nlm_host_match_fn_t)(void *cur, struct nlm_host *ref); | |||
| 262 | __be32 nlmsvc_lock(struct svc_rqst *, struct nlm_file *, | 262 | __be32 nlmsvc_lock(struct svc_rqst *, struct nlm_file *, |
| 263 | struct nlm_host *, struct nlm_lock *, int, | 263 | struct nlm_host *, struct nlm_lock *, int, |
| 264 | struct nlm_cookie *, int); | 264 | struct nlm_cookie *, int); |
| 265 | __be32 nlmsvc_unlock(struct nlm_file *, struct nlm_lock *); | 265 | __be32 nlmsvc_unlock(struct net *net, struct nlm_file *, struct nlm_lock *); |
| 266 | __be32 nlmsvc_testlock(struct svc_rqst *, struct nlm_file *, | 266 | __be32 nlmsvc_testlock(struct svc_rqst *, struct nlm_file *, |
| 267 | struct nlm_host *, struct nlm_lock *, | 267 | struct nlm_host *, struct nlm_lock *, |
| 268 | struct nlm_lock *, struct nlm_cookie *); | 268 | struct nlm_lock *, struct nlm_cookie *); |
| 269 | __be32 nlmsvc_cancel_blocked(struct nlm_file *, struct nlm_lock *); | 269 | __be32 nlmsvc_cancel_blocked(struct net *net, struct nlm_file *, struct nlm_lock *); |
| 270 | unsigned long nlmsvc_retry_blocked(void); | 270 | unsigned long nlmsvc_retry_blocked(void); |
| 271 | void nlmsvc_traverse_blocks(struct nlm_host *, struct nlm_file *, | 271 | void nlmsvc_traverse_blocks(struct nlm_host *, struct nlm_file *, |
| 272 | nlm_host_match_fn_t match); | 272 | nlm_host_match_fn_t match); |
| @@ -279,7 +279,7 @@ void nlmsvc_release_call(struct nlm_rqst *); | |||
| 279 | __be32 nlm_lookup_file(struct svc_rqst *, struct nlm_file **, | 279 | __be32 nlm_lookup_file(struct svc_rqst *, struct nlm_file **, |
| 280 | struct nfs_fh *); | 280 | struct nfs_fh *); |
| 281 | void nlm_release_file(struct nlm_file *); | 281 | void nlm_release_file(struct nlm_file *); |
| 282 | void nlmsvc_mark_resources(void); | 282 | void nlmsvc_mark_resources(struct net *); |
| 283 | void nlmsvc_free_host_resources(struct nlm_host *); | 283 | void nlmsvc_free_host_resources(struct nlm_host *); |
| 284 | void nlmsvc_invalidate_all(void); | 284 | void nlmsvc_invalidate_all(void); |
| 285 | 285 | ||
diff --git a/include/linux/sunrpc/cache.h b/include/linux/sunrpc/cache.h index f5fd6160dbca..f792794f6634 100644 --- a/include/linux/sunrpc/cache.h +++ b/include/linux/sunrpc/cache.h | |||
| @@ -217,14 +217,32 @@ extern int qword_get(char **bpp, char *dest, int bufsize); | |||
| 217 | static inline int get_int(char **bpp, int *anint) | 217 | static inline int get_int(char **bpp, int *anint) |
| 218 | { | 218 | { |
| 219 | char buf[50]; | 219 | char buf[50]; |
| 220 | char *ep; | 220 | int len = qword_get(bpp, buf, sizeof(buf)); |
| 221 | int rv; | 221 | |
| 222 | int len = qword_get(bpp, buf, 50); | 222 | if (len < 0) |
| 223 | if (len < 0) return -EINVAL; | 223 | return -EINVAL; |
| 224 | if (len ==0) return -ENOENT; | 224 | if (len == 0) |
| 225 | rv = simple_strtol(buf, &ep, 0); | 225 | return -ENOENT; |
| 226 | if (*ep) return -EINVAL; | 226 | |
| 227 | *anint = rv; | 227 | if (kstrtoint(buf, 0, anint)) |
| 228 | return -EINVAL; | ||
| 229 | |||
| 230 | return 0; | ||
| 231 | } | ||
| 232 | |||
| 233 | static inline int get_uint(char **bpp, unsigned int *anint) | ||
| 234 | { | ||
| 235 | char buf[50]; | ||
| 236 | int len = qword_get(bpp, buf, sizeof(buf)); | ||
| 237 | |||
| 238 | if (len < 0) | ||
| 239 | return -EINVAL; | ||
| 240 | if (len == 0) | ||
| 241 | return -ENOENT; | ||
| 242 | |||
| 243 | if (kstrtouint(buf, 0, anint)) | ||
| 244 | return -EINVAL; | ||
| 245 | |||
| 228 | return 0; | 246 | return 0; |
| 229 | } | 247 | } |
| 230 | 248 | ||
diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h index 40e0a273faea..d83db800fe02 100644 --- a/include/linux/sunrpc/svc.h +++ b/include/linux/sunrpc/svc.h | |||
| @@ -278,6 +278,8 @@ struct svc_rqst { | |||
| 278 | struct task_struct *rq_task; /* service thread */ | 278 | struct task_struct *rq_task; /* service thread */ |
| 279 | }; | 279 | }; |
| 280 | 280 | ||
| 281 | #define SVC_NET(svc_rqst) (svc_rqst->rq_xprt->xpt_net) | ||
| 282 | |||
| 281 | /* | 283 | /* |
| 282 | * Rigorous type checking on sockaddr type conversions | 284 | * Rigorous type checking on sockaddr type conversions |
| 283 | */ | 285 | */ |
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index 47ad2666fdf6..2afd2a84dc35 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c | |||
| @@ -1349,8 +1349,11 @@ static int c_show(struct seq_file *m, void *p) | |||
| 1349 | if (cache_check(cd, cp, NULL)) | 1349 | if (cache_check(cd, cp, NULL)) |
| 1350 | /* cache_check does a cache_put on failure */ | 1350 | /* cache_check does a cache_put on failure */ |
| 1351 | seq_printf(m, "# "); | 1351 | seq_printf(m, "# "); |
| 1352 | else | 1352 | else { |
| 1353 | if (cache_is_expired(cd, cp)) | ||
| 1354 | seq_printf(m, "# "); | ||
| 1353 | cache_put(cp, cd); | 1355 | cache_put(cp, cd); |
| 1356 | } | ||
| 1354 | 1357 | ||
| 1355 | return cd->cache_show(m, cd, cp); | 1358 | return cd->cache_show(m, cd, cp); |
| 1356 | } | 1359 | } |
