diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-10-08 12:51:44 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-10-08 12:51:44 -0400 |
commit | 6dea0737bc5e160efc77f4c39d393b94fd2746dc (patch) | |
tree | 5f4021fa66f86a9cf0700bdefb8fcdfb370161df /fs/lockd | |
parent | 25641c0c8d72f3d235c022fd2c19181912c2ae8b (diff) | |
parent | 34549ab09e62db9703811c6ed4715f2ffa1fd7fb (diff) |
Merge branch 'for-3.18' of git://linux-nfs.org/~bfields/linux
Pull nfsd updates from Bruce Fields:
"Highlights:
- support the NFSv4.2 SEEK operation (allowing clients to support
SEEK_HOLE/SEEK_DATA), thanks to Anna.
- end the grace period early in a number of cases, mitigating a
long-standing annoyance, thanks to Jeff
- improve SMP scalability, thanks to Trond"
* 'for-3.18' of git://linux-nfs.org/~bfields/linux: (55 commits)
nfsd: eliminate "to_delegation" define
NFSD: Implement SEEK
NFSD: Add generic v4.2 infrastructure
svcrdma: advertise the correct max payload
nfsd: introduce nfsd4_callback_ops
nfsd: split nfsd4_callback initialization and use
nfsd: introduce a generic nfsd4_cb
nfsd: remove nfsd4_callback.cb_op
nfsd: do not clear rpc_resp in nfsd4_cb_done_sequence
nfsd: fix nfsd4_cb_recall_done error handling
nfsd4: clarify how grace period ends
nfsd4: stop grace_time update at end of grace period
nfsd: skip subsequent UMH "create" operations after the first one for v4.0 clients
nfsd: set and test NFSD4_CLIENT_STABLE bit to reduce nfsdcltrack upcalls
nfsd: serialize nfsdcltrack upcalls for a particular client
nfsd: pass extra info in env vars to upcalls to allow for early grace period end
nfsd: add a v4_end_grace file to /proc/fs/nfsd
lockd: add a /proc/fs/lockd/nlm_end_grace file
nfsd: reject reclaim request when client has already sent RECLAIM_COMPLETE
nfsd: remove redundant boot_time parm from grace_done client tracking op
...
Diffstat (limited to 'fs/lockd')
-rw-r--r-- | fs/lockd/Makefile | 3 | ||||
-rw-r--r-- | fs/lockd/grace.c | 65 | ||||
-rw-r--r-- | fs/lockd/netns.h | 1 | ||||
-rw-r--r-- | fs/lockd/procfs.c | 92 | ||||
-rw-r--r-- | fs/lockd/procfs.h | 28 | ||||
-rw-r--r-- | fs/lockd/svc.c | 16 |
6 files changed, 136 insertions, 69 deletions
diff --git a/fs/lockd/Makefile b/fs/lockd/Makefile index ca58d64374ca..9b320cc2a8cf 100644 --- a/fs/lockd/Makefile +++ b/fs/lockd/Makefile | |||
@@ -5,6 +5,7 @@ | |||
5 | obj-$(CONFIG_LOCKD) += lockd.o | 5 | obj-$(CONFIG_LOCKD) += lockd.o |
6 | 6 | ||
7 | lockd-objs-y := clntlock.o clntproc.o clntxdr.o host.o svc.o svclock.o \ | 7 | lockd-objs-y := clntlock.o clntproc.o clntxdr.o host.o svc.o svclock.o \ |
8 | svcshare.o svcproc.o svcsubs.o mon.o xdr.o grace.o | 8 | svcshare.o svcproc.o svcsubs.o mon.o xdr.o |
9 | lockd-objs-$(CONFIG_LOCKD_V4) += clnt4xdr.o xdr4.o svc4proc.o | 9 | lockd-objs-$(CONFIG_LOCKD_V4) += clnt4xdr.o xdr4.o svc4proc.o |
10 | lockd-objs-$(CONFIG_PROC_FS) += procfs.o | ||
10 | lockd-objs := $(lockd-objs-y) | 11 | lockd-objs := $(lockd-objs-y) |
diff --git a/fs/lockd/grace.c b/fs/lockd/grace.c deleted file mode 100644 index 6d1ee7204c88..000000000000 --- a/fs/lockd/grace.c +++ /dev/null | |||
@@ -1,65 +0,0 @@ | |||
1 | /* | ||
2 | * Common code for control of lockd and nfsv4 grace periods. | ||
3 | */ | ||
4 | |||
5 | #include <linux/module.h> | ||
6 | #include <linux/lockd/bind.h> | ||
7 | #include <net/net_namespace.h> | ||
8 | |||
9 | #include "netns.h" | ||
10 | |||
11 | static DEFINE_SPINLOCK(grace_lock); | ||
12 | |||
13 | /** | ||
14 | * locks_start_grace | ||
15 | * @lm: who this grace period is for | ||
16 | * | ||
17 | * A grace period is a period during which locks should not be given | ||
18 | * out. Currently grace periods are only enforced by the two lock | ||
19 | * managers (lockd and nfsd), using the locks_in_grace() function to | ||
20 | * check when they are in a grace period. | ||
21 | * | ||
22 | * This function is called to start a grace period. | ||
23 | */ | ||
24 | void locks_start_grace(struct net *net, struct lock_manager *lm) | ||
25 | { | ||
26 | struct lockd_net *ln = net_generic(net, lockd_net_id); | ||
27 | |||
28 | spin_lock(&grace_lock); | ||
29 | list_add(&lm->list, &ln->grace_list); | ||
30 | spin_unlock(&grace_lock); | ||
31 | } | ||
32 | EXPORT_SYMBOL_GPL(locks_start_grace); | ||
33 | |||
34 | /** | ||
35 | * locks_end_grace | ||
36 | * @lm: who this grace period is for | ||
37 | * | ||
38 | * Call this function to state that the given lock manager is ready to | ||
39 | * resume regular locking. The grace period will not end until all lock | ||
40 | * managers that called locks_start_grace() also call locks_end_grace(). | ||
41 | * Note that callers count on it being safe to call this more than once, | ||
42 | * and the second call should be a no-op. | ||
43 | */ | ||
44 | void locks_end_grace(struct lock_manager *lm) | ||
45 | { | ||
46 | spin_lock(&grace_lock); | ||
47 | list_del_init(&lm->list); | ||
48 | spin_unlock(&grace_lock); | ||
49 | } | ||
50 | EXPORT_SYMBOL_GPL(locks_end_grace); | ||
51 | |||
52 | /** | ||
53 | * locks_in_grace | ||
54 | * | ||
55 | * Lock managers call this function to determine when it is OK for them | ||
56 | * to answer ordinary lock requests, and when they should accept only | ||
57 | * lock reclaims. | ||
58 | */ | ||
59 | int locks_in_grace(struct net *net) | ||
60 | { | ||
61 | struct lockd_net *ln = net_generic(net, lockd_net_id); | ||
62 | |||
63 | return !list_empty(&ln->grace_list); | ||
64 | } | ||
65 | EXPORT_SYMBOL_GPL(locks_in_grace); | ||
diff --git a/fs/lockd/netns.h b/fs/lockd/netns.h index 5010b55628b4..097bfa3adb1c 100644 --- a/fs/lockd/netns.h +++ b/fs/lockd/netns.h | |||
@@ -11,7 +11,6 @@ struct lockd_net { | |||
11 | 11 | ||
12 | struct delayed_work grace_period_end; | 12 | struct delayed_work grace_period_end; |
13 | struct lock_manager lockd_manager; | 13 | struct lock_manager lockd_manager; |
14 | struct list_head grace_list; | ||
15 | 14 | ||
16 | spinlock_t nsm_clnt_lock; | 15 | spinlock_t nsm_clnt_lock; |
17 | unsigned int nsm_users; | 16 | unsigned int nsm_users; |
diff --git a/fs/lockd/procfs.c b/fs/lockd/procfs.c new file mode 100644 index 000000000000..2a0a98480e39 --- /dev/null +++ b/fs/lockd/procfs.c | |||
@@ -0,0 +1,92 @@ | |||
1 | /* | ||
2 | * Procfs support for lockd | ||
3 | * | ||
4 | * Copyright (c) 2014 Jeff Layton <jlayton@primarydata.com> | ||
5 | */ | ||
6 | |||
7 | #include <linux/fs.h> | ||
8 | #include <linux/proc_fs.h> | ||
9 | #include <linux/module.h> | ||
10 | #include <linux/nsproxy.h> | ||
11 | #include <net/net_namespace.h> | ||
12 | |||
13 | #include "netns.h" | ||
14 | #include "procfs.h" | ||
15 | |||
16 | /* | ||
17 | * We only allow strings that start with 'Y', 'y', or '1'. | ||
18 | */ | ||
19 | static ssize_t | ||
20 | nlm_end_grace_write(struct file *file, const char __user *buf, size_t size, | ||
21 | loff_t *pos) | ||
22 | { | ||
23 | char *data; | ||
24 | struct lockd_net *ln = net_generic(current->nsproxy->net_ns, | ||
25 | lockd_net_id); | ||
26 | |||
27 | if (size < 1) | ||
28 | return -EINVAL; | ||
29 | |||
30 | data = simple_transaction_get(file, buf, size); | ||
31 | if (IS_ERR(data)) | ||
32 | return PTR_ERR(data); | ||
33 | |||
34 | switch(data[0]) { | ||
35 | case 'Y': | ||
36 | case 'y': | ||
37 | case '1': | ||
38 | locks_end_grace(&ln->lockd_manager); | ||
39 | break; | ||
40 | default: | ||
41 | return -EINVAL; | ||
42 | } | ||
43 | |||
44 | return size; | ||
45 | } | ||
46 | |||
47 | static ssize_t | ||
48 | nlm_end_grace_read(struct file *file, char __user *buf, size_t size, | ||
49 | loff_t *pos) | ||
50 | { | ||
51 | struct lockd_net *ln = net_generic(current->nsproxy->net_ns, | ||
52 | lockd_net_id); | ||
53 | char resp[3]; | ||
54 | |||
55 | resp[0] = list_empty(&ln->lockd_manager.list) ? 'Y' : 'N'; | ||
56 | resp[1] = '\n'; | ||
57 | resp[2] = '\0'; | ||
58 | |||
59 | return simple_read_from_buffer(buf, size, pos, resp, sizeof(resp)); | ||
60 | } | ||
61 | |||
62 | static const struct file_operations lockd_end_grace_operations = { | ||
63 | .write = nlm_end_grace_write, | ||
64 | .read = nlm_end_grace_read, | ||
65 | .llseek = default_llseek, | ||
66 | .release = simple_transaction_release, | ||
67 | .owner = THIS_MODULE, | ||
68 | }; | ||
69 | |||
70 | int __init | ||
71 | lockd_create_procfs(void) | ||
72 | { | ||
73 | struct proc_dir_entry *entry; | ||
74 | |||
75 | entry = proc_mkdir("fs/lockd", NULL); | ||
76 | if (!entry) | ||
77 | return -ENOMEM; | ||
78 | entry = proc_create("nlm_end_grace", S_IRUGO|S_IWUSR, entry, | ||
79 | &lockd_end_grace_operations); | ||
80 | if (!entry) { | ||
81 | remove_proc_entry("fs/lockd", NULL); | ||
82 | return -ENOMEM; | ||
83 | } | ||
84 | return 0; | ||
85 | } | ||
86 | |||
87 | void __exit | ||
88 | lockd_remove_procfs(void) | ||
89 | { | ||
90 | remove_proc_entry("fs/lockd/nlm_end_grace", NULL); | ||
91 | remove_proc_entry("fs/lockd", NULL); | ||
92 | } | ||
diff --git a/fs/lockd/procfs.h b/fs/lockd/procfs.h new file mode 100644 index 000000000000..2257a1311027 --- /dev/null +++ b/fs/lockd/procfs.h | |||
@@ -0,0 +1,28 @@ | |||
1 | /* | ||
2 | * Procfs support for lockd | ||
3 | * | ||
4 | * Copyright (c) 2014 Jeff Layton <jlayton@primarydata.com> | ||
5 | */ | ||
6 | #ifndef _LOCKD_PROCFS_H | ||
7 | #define _LOCKD_PROCFS_H | ||
8 | |||
9 | #include <linux/kconfig.h> | ||
10 | |||
11 | #if IS_ENABLED(CONFIG_PROC_FS) | ||
12 | int lockd_create_procfs(void); | ||
13 | void lockd_remove_procfs(void); | ||
14 | #else | ||
15 | static inline int | ||
16 | lockd_create_procfs(void) | ||
17 | { | ||
18 | return 0; | ||
19 | } | ||
20 | |||
21 | static inline void | ||
22 | lockd_remove_procfs(void) | ||
23 | { | ||
24 | return; | ||
25 | } | ||
26 | #endif /* IS_ENABLED(CONFIG_PROC_FS) */ | ||
27 | |||
28 | #endif /* _LOCKD_PROCFS_H */ | ||
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c index ec9e082f9ecd..d1bb7ecfd201 100644 --- a/fs/lockd/svc.c +++ b/fs/lockd/svc.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/nfs.h> | 36 | #include <linux/nfs.h> |
37 | 37 | ||
38 | #include "netns.h" | 38 | #include "netns.h" |
39 | #include "procfs.h" | ||
39 | 40 | ||
40 | #define NLMDBG_FACILITY NLMDBG_SVC | 41 | #define NLMDBG_FACILITY NLMDBG_SVC |
41 | #define LOCKD_BUFSIZE (1024 + NLMSVC_XDRSIZE) | 42 | #define LOCKD_BUFSIZE (1024 + NLMSVC_XDRSIZE) |
@@ -304,13 +305,16 @@ static int lockd_start_svc(struct svc_serv *serv) | |||
304 | svc_sock_update_bufs(serv); | 305 | svc_sock_update_bufs(serv); |
305 | serv->sv_maxconn = nlm_max_connections; | 306 | serv->sv_maxconn = nlm_max_connections; |
306 | 307 | ||
307 | nlmsvc_task = kthread_run(lockd, nlmsvc_rqst, "%s", serv->sv_name); | 308 | nlmsvc_task = kthread_create(lockd, nlmsvc_rqst, "%s", serv->sv_name); |
308 | if (IS_ERR(nlmsvc_task)) { | 309 | if (IS_ERR(nlmsvc_task)) { |
309 | error = PTR_ERR(nlmsvc_task); | 310 | error = PTR_ERR(nlmsvc_task); |
310 | printk(KERN_WARNING | 311 | printk(KERN_WARNING |
311 | "lockd_up: kthread_run failed, error=%d\n", error); | 312 | "lockd_up: kthread_run failed, error=%d\n", error); |
312 | goto out_task; | 313 | goto out_task; |
313 | } | 314 | } |
315 | nlmsvc_rqst->rq_task = nlmsvc_task; | ||
316 | wake_up_process(nlmsvc_task); | ||
317 | |||
314 | dprintk("lockd_up: service started\n"); | 318 | dprintk("lockd_up: service started\n"); |
315 | return 0; | 319 | return 0; |
316 | 320 | ||
@@ -581,7 +585,7 @@ static int lockd_init_net(struct net *net) | |||
581 | struct lockd_net *ln = net_generic(net, lockd_net_id); | 585 | struct lockd_net *ln = net_generic(net, lockd_net_id); |
582 | 586 | ||
583 | INIT_DELAYED_WORK(&ln->grace_period_end, grace_ender); | 587 | INIT_DELAYED_WORK(&ln->grace_period_end, grace_ender); |
584 | INIT_LIST_HEAD(&ln->grace_list); | 588 | INIT_LIST_HEAD(&ln->lockd_manager.list); |
585 | spin_lock_init(&ln->nsm_clnt_lock); | 589 | spin_lock_init(&ln->nsm_clnt_lock); |
586 | return 0; | 590 | return 0; |
587 | } | 591 | } |
@@ -615,8 +619,15 @@ static int __init init_nlm(void) | |||
615 | err = register_pernet_subsys(&lockd_net_ops); | 619 | err = register_pernet_subsys(&lockd_net_ops); |
616 | if (err) | 620 | if (err) |
617 | goto err_pernet; | 621 | goto err_pernet; |
622 | |||
623 | err = lockd_create_procfs(); | ||
624 | if (err) | ||
625 | goto err_procfs; | ||
626 | |||
618 | return 0; | 627 | return 0; |
619 | 628 | ||
629 | err_procfs: | ||
630 | unregister_pernet_subsys(&lockd_net_ops); | ||
620 | err_pernet: | 631 | err_pernet: |
621 | #ifdef CONFIG_SYSCTL | 632 | #ifdef CONFIG_SYSCTL |
622 | unregister_sysctl_table(nlm_sysctl_table); | 633 | unregister_sysctl_table(nlm_sysctl_table); |
@@ -629,6 +640,7 @@ static void __exit exit_nlm(void) | |||
629 | { | 640 | { |
630 | /* FIXME: delete all NLM clients */ | 641 | /* FIXME: delete all NLM clients */ |
631 | nlm_shutdown_hosts(); | 642 | nlm_shutdown_hosts(); |
643 | lockd_remove_procfs(); | ||
632 | unregister_pernet_subsys(&lockd_net_ops); | 644 | unregister_pernet_subsys(&lockd_net_ops); |
633 | #ifdef CONFIG_SYSCTL | 645 | #ifdef CONFIG_SYSCTL |
634 | unregister_sysctl_table(nlm_sysctl_table); | 646 | unregister_sysctl_table(nlm_sysctl_table); |