diff options
author | J. Bruce Fields <bfields@citi.umich.edu> | 2007-09-06 12:34:25 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@citi.umich.edu> | 2008-10-03 16:19:02 -0400 |
commit | af558e33bedab672f5cfd3260bce7445e353fe21 (patch) | |
tree | eb89187b6c12640a00584bd35be035ba332e4af3 /fs/lockd | |
parent | d5b337b4877f7c4e1d761434ee04d045b0201e03 (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/Makefile | 2 | ||||
-rw-r--r-- | fs/lockd/grace.c | 59 | ||||
-rw-r--r-- | fs/lockd/svc.c | 20 | ||||
-rw-r--r-- | fs/lockd/svc4proc.c | 12 | ||||
-rw-r--r-- | fs/lockd/svcproc.c | 12 |
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 @@ | |||
5 | obj-$(CONFIG_LOCKD) += lockd.o | 5 | obj-$(CONFIG_LOCKD) += lockd.o |
6 | 6 | ||
7 | lockd-objs-y := clntlock.o clntproc.o host.o svc.o svclock.o svcshare.o \ | 7 | lockd-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 |
9 | lockd-objs-$(CONFIG_LOCKD_V4) += xdr4.o svc4proc.o | 9 | lockd-objs-$(CONFIG_LOCKD_V4) += xdr4.o svc4proc.o |
10 | lockd-objs := $(lockd-objs-y) | 10 | lockd-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 | |||
8 | static LIST_HEAD(grace_list); | ||
9 | static 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 | */ | ||
22 | void 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 | } | ||
28 | EXPORT_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 | */ | ||
40 | void 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 | } | ||
46 | EXPORT_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 | */ | ||
55 | int locks_in_grace(void) | ||
56 | { | ||
57 | return !list_empty(&grace_list); | ||
58 | } | ||
59 | EXPORT_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); | |||
51 | static unsigned int nlmsvc_users; | 51 | static unsigned int nlmsvc_users; |
52 | static struct task_struct *nlmsvc_task; | 52 | static struct task_struct *nlmsvc_task; |
53 | static struct svc_rqst *nlmsvc_rqst; | 53 | static struct svc_rqst *nlmsvc_rqst; |
54 | int nlmsvc_grace_period; | ||
55 | unsigned long nlmsvc_timeout; | 54 | unsigned 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 | ||
88 | unsigned long get_nfs_grace_period(void) | 87 | static 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 | } | ||
98 | EXPORT_SYMBOL(get_nfs_grace_period); | ||
99 | 89 | ||
100 | static void grace_ender(struct work_struct *not_used) | 90 | static 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 | ||
105 | static DECLARE_DELAYED_WORK(grace_period_end, grace_ender); | 95 | static DECLARE_DELAYED_WORK(grace_period_end, grace_ender); |
106 | 96 | ||
107 | static void set_grace_period(void) | 97 | static 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 | } |