aboutsummaryrefslogtreecommitdiffstats
path: root/fs/lockd/clntlock.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/lockd/clntlock.c')
-rw-r--r--fs/lockd/clntlock.c55
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 */
150static 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
167static 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 */
178void 150void
179nlmclnt_recovery(struct nlm_host *host, u32 newstate) 151nlmclnt_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
210restart: 181restart:
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) {