diff options
Diffstat (limited to 'fs/lockd/clntlock.c')
-rw-r--r-- | fs/lockd/clntlock.c | 55 |
1 files changed, 19 insertions, 36 deletions
diff --git a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c index 54e63ddef043..a4ab6dd7661f 100644 --- a/fs/lockd/clntlock.c +++ b/fs/lockd/clntlock.c | |||
@@ -144,43 +144,12 @@ u32 nlmclnt_grant(const struct sockaddr_in *addr, const struct nlm_lock *lock) | |||
144 | */ | 144 | */ |
145 | 145 | ||
146 | /* | 146 | /* |
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. | ||
149 | */ | ||
150 | static void nlmclnt_prepare_reclaim(struct nlm_host *host) | ||
151 | { | ||
152 | down_write(&host->h_rwsem); | ||
153 | if (host->h_nsmhandle) | ||
154 | host->h_nsmhandle->sm_monitored = 0; | ||
155 | host->h_state++; | ||
156 | host->h_nextrebind = 0; | ||
157 | nlm_rebind_host(host); | ||
158 | |||
159 | /* | ||
160 | * Mark the locks for reclaiming. | ||
161 | */ | ||
162 | list_splice_init(&host->h_granted, &host->h_reclaim); | ||
163 | |||
164 | dprintk("NLM: reclaiming locks for host %s\n", host->h_name); | ||
165 | } | ||
166 | |||
167 | static void nlmclnt_finish_reclaim(struct nlm_host *host) | ||
168 | { | ||
169 | host->h_reclaiming = 0; | ||
170 | up_write(&host->h_rwsem); | ||
171 | dprintk("NLM: done reclaiming locks for host %s", host->h_name); | ||
172 | } | ||
173 | |||
174 | /* | ||
175 | * Reclaim all locks on server host. We do this by spawning a separate | 147 | * Reclaim all locks on server host. We do this by spawning a separate |
176 | * reclaimer thread. | 148 | * reclaimer thread. |
177 | */ | 149 | */ |
178 | void | 150 | void |
179 | nlmclnt_recovery(struct nlm_host *host, u32 newstate) | 151 | nlmclnt_recovery(struct nlm_host *host) |
180 | { | 152 | { |
181 | if (host->h_nsmstate == newstate) | ||
182 | return; | ||
183 | host->h_nsmstate = newstate; | ||
184 | if (!host->h_reclaiming++) { | 153 | if (!host->h_reclaiming++) { |
185 | nlm_get_host(host); | 154 | nlm_get_host(host); |
186 | __module_get(THIS_MODULE); | 155 | __module_get(THIS_MODULE); |
@@ -200,18 +169,30 @@ reclaimer(void *ptr) | |||
200 | daemonize("%s-reclaim", host->h_name); | 169 | daemonize("%s-reclaim", host->h_name); |
201 | allow_signal(SIGKILL); | 170 | allow_signal(SIGKILL); |
202 | 171 | ||
172 | down_write(&host->h_rwsem); | ||
173 | |||
203 | /* This one ensures that our parent doesn't terminate while the | 174 | /* This one ensures that our parent doesn't terminate while the |
204 | * reclaim is in progress */ | 175 | * reclaim is in progress */ |
205 | lock_kernel(); | 176 | lock_kernel(); |
206 | lockd_up(0); /* note: this cannot fail as lockd is already running */ | 177 | lockd_up(0); /* note: this cannot fail as lockd is already running */ |
207 | 178 | ||
208 | nlmclnt_prepare_reclaim(host); | 179 | dprintk("lockd: reclaiming locks for host %s", host->h_name); |
209 | /* First, reclaim all locks that have been marked. */ | 180 | |
210 | restart: | 181 | restart: |
211 | nsmstate = host->h_nsmstate; | 182 | nsmstate = host->h_nsmstate; |
183 | |||
184 | /* Force a portmap getport - the peer's lockd will | ||
185 | * most likely end up on a different port. | ||
186 | */ | ||
187 | host->h_nextrebind = 0; | ||
188 | nlm_rebind_host(host); | ||
189 | |||
190 | /* First, reclaim all locks that have been granted. */ | ||
191 | list_splice_init(&host->h_granted, &host->h_reclaim); | ||
212 | list_for_each_entry_safe(fl, next, &host->h_reclaim, fl_u.nfs_fl.list) { | 192 | list_for_each_entry_safe(fl, next, &host->h_reclaim, fl_u.nfs_fl.list) { |
213 | list_del_init(&fl->fl_u.nfs_fl.list); | 193 | list_del_init(&fl->fl_u.nfs_fl.list); |
214 | 194 | ||
195 | /* Why are we leaking memory here? --okir */ | ||
215 | if (signalled()) | 196 | if (signalled()) |
216 | continue; | 197 | continue; |
217 | if (nlmclnt_reclaim(host, fl) != 0) | 198 | if (nlmclnt_reclaim(host, fl) != 0) |
@@ -219,11 +200,13 @@ restart: | |||
219 | list_add_tail(&fl->fl_u.nfs_fl.list, &host->h_granted); | 200 | list_add_tail(&fl->fl_u.nfs_fl.list, &host->h_granted); |
220 | if (host->h_nsmstate != nsmstate) { | 201 | if (host->h_nsmstate != nsmstate) { |
221 | /* Argh! The server rebooted again! */ | 202 | /* Argh! The server rebooted again! */ |
222 | list_splice_init(&host->h_granted, &host->h_reclaim); | ||
223 | goto restart; | 203 | goto restart; |
224 | } | 204 | } |
225 | } | 205 | } |
226 | nlmclnt_finish_reclaim(host); | 206 | |
207 | host->h_reclaiming = 0; | ||
208 | up_write(&host->h_rwsem); | ||
209 | dprintk("NLM: done reclaiming locks for host %s", host->h_name); | ||
227 | 210 | ||
228 | /* Now, wake up all processes that sleep on a blocked lock */ | 211 | /* Now, wake up all processes that sleep on a blocked lock */ |
229 | list_for_each_entry(block, &nlm_blocked, b_list) { | 212 | list_for_each_entry(block, &nlm_blocked, b_list) { |