aboutsummaryrefslogtreecommitdiffstats
path: root/fs/lockd
diff options
context:
space:
mode:
authorJ. Bruce Fields <bfields@citi.umich.edu>2007-09-06 12:34:25 -0400
committerJ. Bruce Fields <bfields@citi.umich.edu>2008-10-03 16:19:02 -0400
commitaf558e33bedab672f5cfd3260bce7445e353fe21 (patch)
treeeb89187b6c12640a00584bd35be035ba332e4af3 /fs/lockd
parentd5b337b4877f7c4e1d761434ee04d045b0201e03 (diff)
nfsd: common grace period control
Rewrite grace period code to unify management of grace period across lockd and nfsd. The current code has lockd and nfsd cooperate to compute a grace period which is satisfactory to them both, and then individually enforce it. This creates a slight race condition, since the enforcement is not coordinated. It's also more complicated than necessary. Here instead we have lockd and nfsd each inform common code when they enter the grace period, and when they're ready to leave the grace period, and allow normal locking only after both of them are ready to leave. We also expect the locks_start_grace()/locks_end_grace() interface here to be simpler to build on for future cluster/high-availability work, which may require (for example) putting individual filesystems into grace, or enforcing grace periods across multiple cluster nodes. Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Diffstat (limited to 'fs/lockd')
-rw-r--r--fs/lockd/Makefile2
-rw-r--r--fs/lockd/grace.c59
-rw-r--r--fs/lockd/svc.c20
-rw-r--r--fs/lockd/svc4proc.c12
-rw-r--r--fs/lockd/svcproc.c12
5 files changed, 77 insertions, 28 deletions
diff --git a/fs/lockd/Makefile b/fs/lockd/Makefile
index 7725a0a9a555..97f6073ab339 100644
--- a/fs/lockd/Makefile
+++ b/fs/lockd/Makefile
@@ -5,6 +5,6 @@
5obj-$(CONFIG_LOCKD) += lockd.o 5obj-$(CONFIG_LOCKD) += lockd.o
6 6
7lockd-objs-y := clntlock.o clntproc.o host.o svc.o svclock.o svcshare.o \ 7lockd-objs-y := clntlock.o clntproc.o host.o svc.o svclock.o svcshare.o \
8 svcproc.o svcsubs.o mon.o xdr.o 8 svcproc.o svcsubs.o mon.o xdr.o grace.o
9lockd-objs-$(CONFIG_LOCKD_V4) += xdr4.o svc4proc.o 9lockd-objs-$(CONFIG_LOCKD_V4) += xdr4.o svc4proc.o
10lockd-objs := $(lockd-objs-y) 10lockd-objs := $(lockd-objs-y)
diff --git a/fs/lockd/grace.c b/fs/lockd/grace.c
new file mode 100644
index 000000000000..183cc1f0af1c
--- /dev/null
+++ b/fs/lockd/grace.c
@@ -0,0 +1,59 @@
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
8static LIST_HEAD(grace_list);
9static DEFINE_SPINLOCK(grace_lock);
10
11/**
12 * locks_start_grace
13 * @lm: who this grace period is for
14 *
15 * A grace period is a period during which locks should not be given
16 * out. Currently grace periods are only enforced by the two lock
17 * managers (lockd and nfsd), using the locks_in_grace() function to
18 * check when they are in a grace period.
19 *
20 * This function is called to start a grace period.
21 */
22void locks_start_grace(struct lock_manager *lm)
23{
24 spin_lock(&grace_lock);
25 list_add(&lm->list, &grace_list);
26 spin_unlock(&grace_lock);
27}
28EXPORT_SYMBOL_GPL(locks_start_grace);
29
30/**
31 * locks_end_grace
32 * @lm: who this grace period is for
33 *
34 * Call this function to state that the given lock manager is ready to
35 * resume regular locking. The grace period will not end until all lock
36 * managers that called locks_start_grace() also call locks_end_grace().
37 * Note that callers count on it being safe to call this more than once,
38 * and the second call should be a no-op.
39 */
40void locks_end_grace(struct lock_manager *lm)
41{
42 spin_lock(&grace_lock);
43 list_del_init(&lm->list);
44 spin_unlock(&grace_lock);
45}
46EXPORT_SYMBOL_GPL(locks_end_grace);
47
48/**
49 * locks_in_grace
50 *
51 * Lock managers call this function to determine when it is OK for them
52 * to answer ordinary lock requests, and when they should accept only
53 * lock reclaims.
54 */
55int locks_in_grace(void)
56{
57 return !list_empty(&grace_list);
58}
59EXPORT_SYMBOL_GPL(locks_in_grace);
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index f345ef7fb8ae..f013aed11533 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -51,7 +51,6 @@ static DEFINE_MUTEX(nlmsvc_mutex);
51static unsigned int nlmsvc_users; 51static unsigned int nlmsvc_users;
52static struct task_struct *nlmsvc_task; 52static struct task_struct *nlmsvc_task;
53static struct svc_rqst *nlmsvc_rqst; 53static struct svc_rqst *nlmsvc_rqst;
54int nlmsvc_grace_period;
55unsigned long nlmsvc_timeout; 54unsigned long nlmsvc_timeout;
56 55
57/* 56/*
@@ -85,30 +84,21 @@ static unsigned long get_lockd_grace_period(void)
85 return nlm_timeout * 5 * HZ; 84 return nlm_timeout * 5 * HZ;
86} 85}
87 86
88unsigned long get_nfs_grace_period(void) 87static struct lock_manager lockd_manager = {
89{ 88};
90 unsigned long lockdgrace = get_lockd_grace_period();
91 unsigned long nfsdgrace = 0;
92
93 if (nlmsvc_ops)
94 nfsdgrace = nlmsvc_ops->get_grace_period();
95
96 return max(lockdgrace, nfsdgrace);
97}
98EXPORT_SYMBOL(get_nfs_grace_period);
99 89
100static void grace_ender(struct work_struct *not_used) 90static void grace_ender(struct work_struct *not_used)
101{ 91{
102 nlmsvc_grace_period = 0; 92 locks_end_grace(&lockd_manager);
103} 93}
104 94
105static DECLARE_DELAYED_WORK(grace_period_end, grace_ender); 95static DECLARE_DELAYED_WORK(grace_period_end, grace_ender);
106 96
107static void set_grace_period(void) 97static void set_grace_period(void)
108{ 98{
109 unsigned long grace_period = get_nfs_grace_period() + jiffies; 99 unsigned long grace_period = get_lockd_grace_period();
110 100
111 nlmsvc_grace_period = 1; 101 locks_start_grace(&lockd_manager);
112 cancel_delayed_work_sync(&grace_period_end); 102 cancel_delayed_work_sync(&grace_period_end);
113 schedule_delayed_work(&grace_period_end, grace_period); 103 schedule_delayed_work(&grace_period_end, grace_period);
114} 104}
diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c
index 4a714f64515b..7ca617367b3e 100644
--- a/fs/lockd/svc4proc.c
+++ b/fs/lockd/svc4proc.c
@@ -89,7 +89,7 @@ nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp,
89 resp->cookie = argp->cookie; 89 resp->cookie = argp->cookie;
90 90
91 /* Don't accept test requests during grace period */ 91 /* Don't accept test requests during grace period */
92 if (nlmsvc_grace_period) { 92 if (locks_in_grace()) {
93 resp->status = nlm_lck_denied_grace_period; 93 resp->status = nlm_lck_denied_grace_period;
94 return rc; 94 return rc;
95 } 95 }
@@ -123,7 +123,7 @@ nlm4svc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp,
123 resp->cookie = argp->cookie; 123 resp->cookie = argp->cookie;
124 124
125 /* Don't accept new lock requests during grace period */ 125 /* Don't accept new lock requests during grace period */
126 if (nlmsvc_grace_period && !argp->reclaim) { 126 if (locks_in_grace() && !argp->reclaim) {
127 resp->status = nlm_lck_denied_grace_period; 127 resp->status = nlm_lck_denied_grace_period;
128 return rc; 128 return rc;
129 } 129 }
@@ -169,7 +169,7 @@ nlm4svc_proc_cancel(struct svc_rqst *rqstp, struct nlm_args *argp,
169 resp->cookie = argp->cookie; 169 resp->cookie = argp->cookie;
170 170
171 /* Don't accept requests during grace period */ 171 /* Don't accept requests during grace period */
172 if (nlmsvc_grace_period) { 172 if (locks_in_grace()) {
173 resp->status = nlm_lck_denied_grace_period; 173 resp->status = nlm_lck_denied_grace_period;
174 return rpc_success; 174 return rpc_success;
175 } 175 }
@@ -202,7 +202,7 @@ nlm4svc_proc_unlock(struct svc_rqst *rqstp, struct nlm_args *argp,
202 resp->cookie = argp->cookie; 202 resp->cookie = argp->cookie;
203 203
204 /* Don't accept new lock requests during grace period */ 204 /* Don't accept new lock requests during grace period */
205 if (nlmsvc_grace_period) { 205 if (locks_in_grace()) {
206 resp->status = nlm_lck_denied_grace_period; 206 resp->status = nlm_lck_denied_grace_period;
207 return rpc_success; 207 return rpc_success;
208 } 208 }
@@ -341,7 +341,7 @@ nlm4svc_proc_share(struct svc_rqst *rqstp, struct nlm_args *argp,
341 resp->cookie = argp->cookie; 341 resp->cookie = argp->cookie;
342 342
343 /* Don't accept new lock requests during grace period */ 343 /* Don't accept new lock requests during grace period */
344 if (nlmsvc_grace_period && !argp->reclaim) { 344 if (locks_in_grace() && !argp->reclaim) {
345 resp->status = nlm_lck_denied_grace_period; 345 resp->status = nlm_lck_denied_grace_period;
346 return rpc_success; 346 return rpc_success;
347 } 347 }
@@ -374,7 +374,7 @@ nlm4svc_proc_unshare(struct svc_rqst *rqstp, struct nlm_args *argp,
374 resp->cookie = argp->cookie; 374 resp->cookie = argp->cookie;
375 375
376 /* Don't accept requests during grace period */ 376 /* Don't accept requests during grace period */
377 if (nlmsvc_grace_period) { 377 if (locks_in_grace()) {
378 resp->status = nlm_lck_denied_grace_period; 378 resp->status = nlm_lck_denied_grace_period;
379 return rpc_success; 379 return rpc_success;
380 } 380 }
diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c
index 76262c1986f2..1b013e198804 100644
--- a/fs/lockd/svcproc.c
+++ b/fs/lockd/svcproc.c
@@ -118,7 +118,7 @@ nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp,
118 resp->cookie = argp->cookie; 118 resp->cookie = argp->cookie;
119 119
120 /* Don't accept test requests during grace period */ 120 /* Don't accept test requests during grace period */
121 if (nlmsvc_grace_period) { 121 if (locks_in_grace()) {
122 resp->status = nlm_lck_denied_grace_period; 122 resp->status = nlm_lck_denied_grace_period;
123 return rc; 123 return rc;
124 } 124 }
@@ -153,7 +153,7 @@ nlmsvc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp,
153 resp->cookie = argp->cookie; 153 resp->cookie = argp->cookie;
154 154
155 /* Don't accept new lock requests during grace period */ 155 /* Don't accept new lock requests during grace period */
156 if (nlmsvc_grace_period && !argp->reclaim) { 156 if (locks_in_grace() && !argp->reclaim) {
157 resp->status = nlm_lck_denied_grace_period; 157 resp->status = nlm_lck_denied_grace_period;
158 return rc; 158 return rc;
159 } 159 }
@@ -199,7 +199,7 @@ nlmsvc_proc_cancel(struct svc_rqst *rqstp, struct nlm_args *argp,
199 resp->cookie = argp->cookie; 199 resp->cookie = argp->cookie;
200 200
201 /* Don't accept requests during grace period */ 201 /* Don't accept requests during grace period */
202 if (nlmsvc_grace_period) { 202 if (locks_in_grace()) {
203 resp->status = nlm_lck_denied_grace_period; 203 resp->status = nlm_lck_denied_grace_period;
204 return rpc_success; 204 return rpc_success;
205 } 205 }
@@ -232,7 +232,7 @@ nlmsvc_proc_unlock(struct svc_rqst *rqstp, struct nlm_args *argp,
232 resp->cookie = argp->cookie; 232 resp->cookie = argp->cookie;
233 233
234 /* Don't accept new lock requests during grace period */ 234 /* Don't accept new lock requests during grace period */
235 if (nlmsvc_grace_period) { 235 if (locks_in_grace()) {
236 resp->status = nlm_lck_denied_grace_period; 236 resp->status = nlm_lck_denied_grace_period;
237 return rpc_success; 237 return rpc_success;
238 } 238 }
@@ -373,7 +373,7 @@ nlmsvc_proc_share(struct svc_rqst *rqstp, struct nlm_args *argp,
373 resp->cookie = argp->cookie; 373 resp->cookie = argp->cookie;
374 374
375 /* Don't accept new lock requests during grace period */ 375 /* Don't accept new lock requests during grace period */
376 if (nlmsvc_grace_period && !argp->reclaim) { 376 if (locks_in_grace() && !argp->reclaim) {
377 resp->status = nlm_lck_denied_grace_period; 377 resp->status = nlm_lck_denied_grace_period;
378 return rpc_success; 378 return rpc_success;
379 } 379 }
@@ -406,7 +406,7 @@ nlmsvc_proc_unshare(struct svc_rqst *rqstp, struct nlm_args *argp,
406 resp->cookie = argp->cookie; 406 resp->cookie = argp->cookie;
407 407
408 /* Don't accept requests during grace period */ 408 /* Don't accept requests during grace period */
409 if (nlmsvc_grace_period) { 409 if (locks_in_grace()) {
410 resp->status = nlm_lck_denied_grace_period; 410 resp->status = nlm_lck_denied_grace_period;
411 return rpc_success; 411 return rpc_success;
412 } 412 }