diff options
Diffstat (limited to 'fs/lockd/clntlock.c')
-rw-r--r-- | fs/lockd/clntlock.c | 39 |
1 files changed, 25 insertions, 14 deletions
diff --git a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c index bce744468708..52774feab93f 100644 --- a/fs/lockd/clntlock.c +++ b/fs/lockd/clntlock.c | |||
@@ -147,11 +147,10 @@ u32 nlmclnt_grant(const struct sockaddr_in *addr, const struct nlm_lock *lock) | |||
147 | * Someone has sent us an SM_NOTIFY. Ensure we bind to the new port number, | 147 | * Someone has sent us an SM_NOTIFY. Ensure we bind to the new port number, |
148 | * that we mark locks for reclaiming, and that we bump the pseudo NSM state. | 148 | * that we mark locks for reclaiming, and that we bump the pseudo NSM state. |
149 | */ | 149 | */ |
150 | static inline | 150 | static void nlmclnt_prepare_reclaim(struct nlm_host *host) |
151 | void nlmclnt_prepare_reclaim(struct nlm_host *host, u32 newstate) | ||
152 | { | 151 | { |
152 | down_write(&host->h_rwsem); | ||
153 | host->h_monitored = 0; | 153 | host->h_monitored = 0; |
154 | host->h_nsmstate = newstate; | ||
155 | host->h_state++; | 154 | host->h_state++; |
156 | host->h_nextrebind = 0; | 155 | host->h_nextrebind = 0; |
157 | nlm_rebind_host(host); | 156 | nlm_rebind_host(host); |
@@ -164,6 +163,13 @@ void nlmclnt_prepare_reclaim(struct nlm_host *host, u32 newstate) | |||
164 | dprintk("NLM: reclaiming locks for host %s", host->h_name); | 163 | dprintk("NLM: reclaiming locks for host %s", host->h_name); |
165 | } | 164 | } |
166 | 165 | ||
166 | static void nlmclnt_finish_reclaim(struct nlm_host *host) | ||
167 | { | ||
168 | host->h_reclaiming = 0; | ||
169 | up_write(&host->h_rwsem); | ||
170 | dprintk("NLM: done reclaiming locks for host %s", host->h_name); | ||
171 | } | ||
172 | |||
167 | /* | 173 | /* |
168 | * Reclaim all locks on server host. We do this by spawning a separate | 174 | * Reclaim all locks on server host. We do this by spawning a separate |
169 | * reclaimer thread. | 175 | * reclaimer thread. |
@@ -171,12 +177,10 @@ void nlmclnt_prepare_reclaim(struct nlm_host *host, u32 newstate) | |||
171 | void | 177 | void |
172 | nlmclnt_recovery(struct nlm_host *host, u32 newstate) | 178 | nlmclnt_recovery(struct nlm_host *host, u32 newstate) |
173 | { | 179 | { |
174 | if (host->h_reclaiming++) { | 180 | if (host->h_nsmstate == newstate) |
175 | if (host->h_nsmstate == newstate) | 181 | return; |
176 | return; | 182 | host->h_nsmstate = newstate; |
177 | nlmclnt_prepare_reclaim(host, newstate); | 183 | if (!host->h_reclaiming++) { |
178 | } else { | ||
179 | nlmclnt_prepare_reclaim(host, newstate); | ||
180 | nlm_get_host(host); | 184 | nlm_get_host(host); |
181 | __module_get(THIS_MODULE); | 185 | __module_get(THIS_MODULE); |
182 | if (kernel_thread(reclaimer, host, CLONE_KERNEL) < 0) | 186 | if (kernel_thread(reclaimer, host, CLONE_KERNEL) < 0) |
@@ -190,6 +194,7 @@ reclaimer(void *ptr) | |||
190 | struct nlm_host *host = (struct nlm_host *) ptr; | 194 | struct nlm_host *host = (struct nlm_host *) ptr; |
191 | struct nlm_wait *block; | 195 | struct nlm_wait *block; |
192 | struct file_lock *fl, *next; | 196 | struct file_lock *fl, *next; |
197 | u32 nsmstate; | ||
193 | 198 | ||
194 | daemonize("%s-reclaim", host->h_name); | 199 | daemonize("%s-reclaim", host->h_name); |
195 | allow_signal(SIGKILL); | 200 | allow_signal(SIGKILL); |
@@ -199,19 +204,25 @@ reclaimer(void *ptr) | |||
199 | lock_kernel(); | 204 | lock_kernel(); |
200 | lockd_up(); | 205 | lockd_up(); |
201 | 206 | ||
207 | nlmclnt_prepare_reclaim(host); | ||
202 | /* First, reclaim all locks that have been marked. */ | 208 | /* First, reclaim all locks that have been marked. */ |
203 | restart: | 209 | restart: |
210 | nsmstate = host->h_nsmstate; | ||
204 | list_for_each_entry_safe(fl, next, &host->h_reclaim, fl_u.nfs_fl.list) { | 211 | list_for_each_entry_safe(fl, next, &host->h_reclaim, fl_u.nfs_fl.list) { |
205 | list_del_init(&fl->fl_u.nfs_fl.list); | 212 | list_del_init(&fl->fl_u.nfs_fl.list); |
206 | 213 | ||
207 | if (signalled()) | 214 | if (signalled()) |
208 | continue; | 215 | continue; |
209 | if (nlmclnt_reclaim(host, fl) == 0) | 216 | if (nlmclnt_reclaim(host, fl) != 0) |
210 | list_add_tail(&fl->fl_u.nfs_fl.list, &host->h_granted); | 217 | continue; |
211 | goto restart; | 218 | list_add_tail(&fl->fl_u.nfs_fl.list, &host->h_granted); |
219 | if (host->h_nsmstate != nsmstate) { | ||
220 | /* Argh! The server rebooted again! */ | ||
221 | list_splice_init(&host->h_granted, &host->h_reclaim); | ||
222 | goto restart; | ||
223 | } | ||
212 | } | 224 | } |
213 | 225 | nlmclnt_finish_reclaim(host); | |
214 | host->h_reclaiming = 0; | ||
215 | 226 | ||
216 | /* Now, wake up all processes that sleep on a blocked lock */ | 227 | /* Now, wake up all processes that sleep on a blocked lock */ |
217 | list_for_each_entry(block, &nlm_blocked, b_list) { | 228 | list_for_each_entry(block, &nlm_blocked, b_list) { |