diff options
Diffstat (limited to 'fs/lockd/svclock.c')
-rw-r--r-- | fs/lockd/svclock.c | 207 |
1 files changed, 93 insertions, 114 deletions
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c index 93c00ee7189d..7e219b938552 100644 --- a/fs/lockd/svclock.c +++ b/fs/lockd/svclock.c | |||
@@ -40,7 +40,7 @@ | |||
40 | 40 | ||
41 | static void nlmsvc_release_block(struct nlm_block *block); | 41 | static void nlmsvc_release_block(struct nlm_block *block); |
42 | static void nlmsvc_insert_block(struct nlm_block *block, unsigned long); | 42 | static void nlmsvc_insert_block(struct nlm_block *block, unsigned long); |
43 | static int nlmsvc_remove_block(struct nlm_block *block); | 43 | static void nlmsvc_remove_block(struct nlm_block *block); |
44 | 44 | ||
45 | static int nlmsvc_setgrantargs(struct nlm_rqst *call, struct nlm_lock *lock); | 45 | static int nlmsvc_setgrantargs(struct nlm_rqst *call, struct nlm_lock *lock); |
46 | static void nlmsvc_freegrantargs(struct nlm_rqst *call); | 46 | static void nlmsvc_freegrantargs(struct nlm_rqst *call); |
@@ -49,7 +49,7 @@ static const struct rpc_call_ops nlmsvc_grant_ops; | |||
49 | /* | 49 | /* |
50 | * The list of blocked locks to retry | 50 | * The list of blocked locks to retry |
51 | */ | 51 | */ |
52 | static struct nlm_block * nlm_blocked; | 52 | static LIST_HEAD(nlm_blocked); |
53 | 53 | ||
54 | /* | 54 | /* |
55 | * Insert a blocked lock into the global list | 55 | * Insert a blocked lock into the global list |
@@ -57,48 +57,44 @@ static struct nlm_block * nlm_blocked; | |||
57 | static void | 57 | static void |
58 | nlmsvc_insert_block(struct nlm_block *block, unsigned long when) | 58 | nlmsvc_insert_block(struct nlm_block *block, unsigned long when) |
59 | { | 59 | { |
60 | struct nlm_block **bp, *b; | 60 | struct nlm_block *b; |
61 | struct list_head *pos; | ||
61 | 62 | ||
62 | dprintk("lockd: nlmsvc_insert_block(%p, %ld)\n", block, when); | 63 | dprintk("lockd: nlmsvc_insert_block(%p, %ld)\n", block, when); |
63 | kref_get(&block->b_count); | 64 | if (list_empty(&block->b_list)) { |
64 | if (block->b_queued) | 65 | kref_get(&block->b_count); |
65 | nlmsvc_remove_block(block); | 66 | } else { |
66 | bp = &nlm_blocked; | 67 | list_del_init(&block->b_list); |
68 | } | ||
69 | |||
70 | pos = &nlm_blocked; | ||
67 | if (when != NLM_NEVER) { | 71 | if (when != NLM_NEVER) { |
68 | if ((when += jiffies) == NLM_NEVER) | 72 | if ((when += jiffies) == NLM_NEVER) |
69 | when ++; | 73 | when ++; |
70 | while ((b = *bp) && time_before_eq(b->b_when,when) && b->b_when != NLM_NEVER) | 74 | list_for_each(pos, &nlm_blocked) { |
71 | bp = &b->b_next; | 75 | b = list_entry(pos, struct nlm_block, b_list); |
72 | } else | 76 | if (time_after(b->b_when,when) || b->b_when == NLM_NEVER) |
73 | while ((b = *bp) != 0) | 77 | break; |
74 | bp = &b->b_next; | 78 | } |
79 | /* On normal exit from the loop, pos == &nlm_blocked, | ||
80 | * so we will be adding to the end of the list - good | ||
81 | */ | ||
82 | } | ||
75 | 83 | ||
76 | block->b_queued = 1; | 84 | list_add_tail(&block->b_list, pos); |
77 | block->b_when = when; | 85 | block->b_when = when; |
78 | block->b_next = b; | ||
79 | *bp = block; | ||
80 | } | 86 | } |
81 | 87 | ||
82 | /* | 88 | /* |
83 | * Remove a block from the global list | 89 | * Remove a block from the global list |
84 | */ | 90 | */ |
85 | static int | 91 | static inline void |
86 | nlmsvc_remove_block(struct nlm_block *block) | 92 | nlmsvc_remove_block(struct nlm_block *block) |
87 | { | 93 | { |
88 | struct nlm_block **bp, *b; | 94 | if (!list_empty(&block->b_list)) { |
89 | 95 | list_del_init(&block->b_list); | |
90 | if (!block->b_queued) | 96 | nlmsvc_release_block(block); |
91 | return 1; | ||
92 | for (bp = &nlm_blocked; (b = *bp) != 0; bp = &b->b_next) { | ||
93 | if (b == block) { | ||
94 | *bp = block->b_next; | ||
95 | block->b_queued = 0; | ||
96 | nlmsvc_release_block(block); | ||
97 | return 1; | ||
98 | } | ||
99 | } | 97 | } |
100 | |||
101 | return 0; | ||
102 | } | 98 | } |
103 | 99 | ||
104 | /* | 100 | /* |
@@ -107,14 +103,14 @@ nlmsvc_remove_block(struct nlm_block *block) | |||
107 | static struct nlm_block * | 103 | static struct nlm_block * |
108 | nlmsvc_lookup_block(struct nlm_file *file, struct nlm_lock *lock) | 104 | nlmsvc_lookup_block(struct nlm_file *file, struct nlm_lock *lock) |
109 | { | 105 | { |
110 | struct nlm_block **head, *block; | 106 | struct nlm_block *block; |
111 | struct file_lock *fl; | 107 | struct file_lock *fl; |
112 | 108 | ||
113 | dprintk("lockd: nlmsvc_lookup_block f=%p pd=%d %Ld-%Ld ty=%d\n", | 109 | dprintk("lockd: nlmsvc_lookup_block f=%p pd=%d %Ld-%Ld ty=%d\n", |
114 | file, lock->fl.fl_pid, | 110 | file, lock->fl.fl_pid, |
115 | (long long)lock->fl.fl_start, | 111 | (long long)lock->fl.fl_start, |
116 | (long long)lock->fl.fl_end, lock->fl.fl_type); | 112 | (long long)lock->fl.fl_end, lock->fl.fl_type); |
117 | for (head = &nlm_blocked; (block = *head) != 0; head = &block->b_next) { | 113 | list_for_each_entry(block, &nlm_blocked, b_list) { |
118 | fl = &block->b_call->a_args.lock.fl; | 114 | fl = &block->b_call->a_args.lock.fl; |
119 | dprintk("lockd: check f=%p pd=%d %Ld-%Ld ty=%d cookie=%s\n", | 115 | dprintk("lockd: check f=%p pd=%d %Ld-%Ld ty=%d cookie=%s\n", |
120 | block->b_file, fl->fl_pid, | 116 | block->b_file, fl->fl_pid, |
@@ -143,20 +139,20 @@ static inline int nlm_cookie_match(struct nlm_cookie *a, struct nlm_cookie *b) | |||
143 | * Find a block with a given NLM cookie. | 139 | * Find a block with a given NLM cookie. |
144 | */ | 140 | */ |
145 | static inline struct nlm_block * | 141 | static inline struct nlm_block * |
146 | nlmsvc_find_block(struct nlm_cookie *cookie, struct sockaddr_in *sin) | 142 | nlmsvc_find_block(struct nlm_cookie *cookie) |
147 | { | 143 | { |
148 | struct nlm_block *block; | 144 | struct nlm_block *block; |
149 | 145 | ||
150 | for (block = nlm_blocked; block; block = block->b_next) { | 146 | list_for_each_entry(block, &nlm_blocked, b_list) { |
151 | dprintk("cookie: head of blocked queue %p, block %p\n", | 147 | if (nlm_cookie_match(&block->b_call->a_args.cookie,cookie)) |
152 | nlm_blocked, block); | 148 | goto found; |
153 | if (nlm_cookie_match(&block->b_call->a_args.cookie,cookie) | ||
154 | && nlm_cmp_addr(sin, &block->b_host->h_addr)) | ||
155 | break; | ||
156 | } | 149 | } |
157 | 150 | ||
158 | if (block != NULL) | 151 | return NULL; |
159 | kref_get(&block->b_count); | 152 | |
153 | found: | ||
154 | dprintk("nlmsvc_find_block(%s): block=%p\n", nlmdbg_cookie2a(cookie), block); | ||
155 | kref_get(&block->b_count); | ||
160 | return block; | 156 | return block; |
161 | } | 157 | } |
162 | 158 | ||
@@ -169,6 +165,11 @@ nlmsvc_find_block(struct nlm_cookie *cookie, struct sockaddr_in *sin) | |||
169 | * request, but (as I found out later) that's because some implementations | 165 | * request, but (as I found out later) that's because some implementations |
170 | * do just this. Never mind the standards comittees, they support our | 166 | * do just this. Never mind the standards comittees, they support our |
171 | * logging industries. | 167 | * logging industries. |
168 | * | ||
169 | * 10 years later: I hope we can safely ignore these old and broken | ||
170 | * clients by now. Let's fix this so we can uniquely identify an incoming | ||
171 | * GRANTED_RES message by cookie, without having to rely on the client's IP | ||
172 | * address. --okir | ||
172 | */ | 173 | */ |
173 | static inline struct nlm_block * | 174 | static inline struct nlm_block * |
174 | nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_file *file, | 175 | nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_file *file, |
@@ -179,7 +180,7 @@ nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_file *file, | |||
179 | struct nlm_rqst *call = NULL; | 180 | struct nlm_rqst *call = NULL; |
180 | 181 | ||
181 | /* Create host handle for callback */ | 182 | /* Create host handle for callback */ |
182 | host = nlmsvc_lookup_host(rqstp); | 183 | host = nlmsvc_lookup_host(rqstp, lock->caller, lock->len); |
183 | if (host == NULL) | 184 | if (host == NULL) |
184 | return NULL; | 185 | return NULL; |
185 | 186 | ||
@@ -192,6 +193,8 @@ nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_file *file, | |||
192 | if (block == NULL) | 193 | if (block == NULL) |
193 | goto failed; | 194 | goto failed; |
194 | kref_init(&block->b_count); | 195 | kref_init(&block->b_count); |
196 | INIT_LIST_HEAD(&block->b_list); | ||
197 | INIT_LIST_HEAD(&block->b_flist); | ||
195 | 198 | ||
196 | if (!nlmsvc_setgrantargs(call, lock)) | 199 | if (!nlmsvc_setgrantargs(call, lock)) |
197 | goto failed_free; | 200 | goto failed_free; |
@@ -199,7 +202,7 @@ nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_file *file, | |||
199 | /* Set notifier function for VFS, and init args */ | 202 | /* Set notifier function for VFS, and init args */ |
200 | call->a_args.lock.fl.fl_flags |= FL_SLEEP; | 203 | call->a_args.lock.fl.fl_flags |= FL_SLEEP; |
201 | call->a_args.lock.fl.fl_lmops = &nlmsvc_lock_operations; | 204 | call->a_args.lock.fl.fl_lmops = &nlmsvc_lock_operations; |
202 | call->a_args.cookie = *cookie; /* see above */ | 205 | nlmclnt_next_cookie(&call->a_args.cookie); |
203 | 206 | ||
204 | dprintk("lockd: created block %p...\n", block); | 207 | dprintk("lockd: created block %p...\n", block); |
205 | 208 | ||
@@ -210,8 +213,7 @@ nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_file *file, | |||
210 | file->f_count++; | 213 | file->f_count++; |
211 | 214 | ||
212 | /* Add to file's list of blocks */ | 215 | /* Add to file's list of blocks */ |
213 | block->b_fnext = file->f_blocks; | 216 | list_add(&block->b_flist, &file->f_blocks); |
214 | file->f_blocks = block; | ||
215 | 217 | ||
216 | /* Set up RPC arguments for callback */ | 218 | /* Set up RPC arguments for callback */ |
217 | block->b_call = call; | 219 | block->b_call = call; |
@@ -248,19 +250,13 @@ static void nlmsvc_free_block(struct kref *kref) | |||
248 | { | 250 | { |
249 | struct nlm_block *block = container_of(kref, struct nlm_block, b_count); | 251 | struct nlm_block *block = container_of(kref, struct nlm_block, b_count); |
250 | struct nlm_file *file = block->b_file; | 252 | struct nlm_file *file = block->b_file; |
251 | struct nlm_block **bp; | ||
252 | 253 | ||
253 | dprintk("lockd: freeing block %p...\n", block); | 254 | dprintk("lockd: freeing block %p...\n", block); |
254 | 255 | ||
255 | down(&file->f_sema); | ||
256 | /* Remove block from file's list of blocks */ | 256 | /* Remove block from file's list of blocks */ |
257 | for (bp = &file->f_blocks; *bp; bp = &(*bp)->b_fnext) { | 257 | mutex_lock(&file->f_mutex); |
258 | if (*bp == block) { | 258 | list_del_init(&block->b_flist); |
259 | *bp = block->b_fnext; | 259 | mutex_unlock(&file->f_mutex); |
260 | break; | ||
261 | } | ||
262 | } | ||
263 | up(&file->f_sema); | ||
264 | 260 | ||
265 | nlmsvc_freegrantargs(block->b_call); | 261 | nlmsvc_freegrantargs(block->b_call); |
266 | nlm_release_call(block->b_call); | 262 | nlm_release_call(block->b_call); |
@@ -274,47 +270,32 @@ static void nlmsvc_release_block(struct nlm_block *block) | |||
274 | kref_put(&block->b_count, nlmsvc_free_block); | 270 | kref_put(&block->b_count, nlmsvc_free_block); |
275 | } | 271 | } |
276 | 272 | ||
277 | static void nlmsvc_act_mark(struct nlm_host *host, struct nlm_file *file) | 273 | /* |
278 | { | 274 | * Loop over all blocks and delete blocks held by |
279 | struct nlm_block *block; | 275 | * a matching host. |
280 | 276 | */ | |
281 | down(&file->f_sema); | 277 | void nlmsvc_traverse_blocks(struct nlm_host *host, |
282 | for (block = file->f_blocks; block != NULL; block = block->b_fnext) | 278 | struct nlm_file *file, |
283 | block->b_host->h_inuse = 1; | 279 | nlm_host_match_fn_t match) |
284 | up(&file->f_sema); | ||
285 | } | ||
286 | |||
287 | static void nlmsvc_act_unlock(struct nlm_host *host, struct nlm_file *file) | ||
288 | { | 280 | { |
289 | struct nlm_block *block; | 281 | struct nlm_block *block, *next; |
290 | 282 | ||
291 | restart: | 283 | restart: |
292 | down(&file->f_sema); | 284 | mutex_lock(&file->f_mutex); |
293 | for (block = file->f_blocks; block != NULL; block = block->b_fnext) { | 285 | list_for_each_entry_safe(block, next, &file->f_blocks, b_flist) { |
294 | if (host != NULL && host != block->b_host) | 286 | if (!match(block->b_host, host)) |
295 | continue; | 287 | continue; |
296 | if (!block->b_queued) | 288 | /* Do not destroy blocks that are not on |
289 | * the global retry list - why? */ | ||
290 | if (list_empty(&block->b_list)) | ||
297 | continue; | 291 | continue; |
298 | kref_get(&block->b_count); | 292 | kref_get(&block->b_count); |
299 | up(&file->f_sema); | 293 | mutex_unlock(&file->f_mutex); |
300 | nlmsvc_unlink_block(block); | 294 | nlmsvc_unlink_block(block); |
301 | nlmsvc_release_block(block); | 295 | nlmsvc_release_block(block); |
302 | goto restart; | 296 | goto restart; |
303 | } | 297 | } |
304 | up(&file->f_sema); | 298 | mutex_unlock(&file->f_mutex); |
305 | } | ||
306 | |||
307 | /* | ||
308 | * Loop over all blocks and perform the action specified. | ||
309 | * (NLM_ACT_CHECK handled by nlmsvc_inspect_file). | ||
310 | */ | ||
311 | void | ||
312 | nlmsvc_traverse_blocks(struct nlm_host *host, struct nlm_file *file, int action) | ||
313 | { | ||
314 | if (action == NLM_ACT_MARK) | ||
315 | nlmsvc_act_mark(host, file); | ||
316 | else | ||
317 | nlmsvc_act_unlock(host, file); | ||
318 | } | 299 | } |
319 | 300 | ||
320 | /* | 301 | /* |
@@ -353,13 +334,13 @@ static void nlmsvc_freegrantargs(struct nlm_rqst *call) | |||
353 | * Attempt to establish a lock, and if it can't be granted, block it | 334 | * Attempt to establish a lock, and if it can't be granted, block it |
354 | * if required. | 335 | * if required. |
355 | */ | 336 | */ |
356 | u32 | 337 | __be32 |
357 | nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file, | 338 | nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file, |
358 | struct nlm_lock *lock, int wait, struct nlm_cookie *cookie) | 339 | struct nlm_lock *lock, int wait, struct nlm_cookie *cookie) |
359 | { | 340 | { |
360 | struct nlm_block *block, *newblock = NULL; | 341 | struct nlm_block *block, *newblock = NULL; |
361 | int error; | 342 | int error; |
362 | u32 ret; | 343 | __be32 ret; |
363 | 344 | ||
364 | dprintk("lockd: nlmsvc_lock(%s/%ld, ty=%d, pi=%d, %Ld-%Ld, bl=%d)\n", | 345 | dprintk("lockd: nlmsvc_lock(%s/%ld, ty=%d, pi=%d, %Ld-%Ld, bl=%d)\n", |
365 | file->f_file->f_dentry->d_inode->i_sb->s_id, | 346 | file->f_file->f_dentry->d_inode->i_sb->s_id, |
@@ -373,7 +354,7 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file, | |||
373 | lock->fl.fl_flags &= ~FL_SLEEP; | 354 | lock->fl.fl_flags &= ~FL_SLEEP; |
374 | again: | 355 | again: |
375 | /* Lock file against concurrent access */ | 356 | /* Lock file against concurrent access */ |
376 | down(&file->f_sema); | 357 | mutex_lock(&file->f_mutex); |
377 | /* Get existing block (in case client is busy-waiting) */ | 358 | /* Get existing block (in case client is busy-waiting) */ |
378 | block = nlmsvc_lookup_block(file, lock); | 359 | block = nlmsvc_lookup_block(file, lock); |
379 | if (block == NULL) { | 360 | if (block == NULL) { |
@@ -411,10 +392,10 @@ again: | |||
411 | 392 | ||
412 | /* If we don't have a block, create and initialize it. Then | 393 | /* If we don't have a block, create and initialize it. Then |
413 | * retry because we may have slept in kmalloc. */ | 394 | * retry because we may have slept in kmalloc. */ |
414 | /* We have to release f_sema as nlmsvc_create_block may try to | 395 | /* We have to release f_mutex as nlmsvc_create_block may try to |
415 | * to claim it while doing host garbage collection */ | 396 | * to claim it while doing host garbage collection */ |
416 | if (newblock == NULL) { | 397 | if (newblock == NULL) { |
417 | up(&file->f_sema); | 398 | mutex_unlock(&file->f_mutex); |
418 | dprintk("lockd: blocking on this lock (allocating).\n"); | 399 | dprintk("lockd: blocking on this lock (allocating).\n"); |
419 | if (!(newblock = nlmsvc_create_block(rqstp, file, lock, cookie))) | 400 | if (!(newblock = nlmsvc_create_block(rqstp, file, lock, cookie))) |
420 | return nlm_lck_denied_nolocks; | 401 | return nlm_lck_denied_nolocks; |
@@ -424,7 +405,7 @@ again: | |||
424 | /* Append to list of blocked */ | 405 | /* Append to list of blocked */ |
425 | nlmsvc_insert_block(newblock, NLM_NEVER); | 406 | nlmsvc_insert_block(newblock, NLM_NEVER); |
426 | out: | 407 | out: |
427 | up(&file->f_sema); | 408 | mutex_unlock(&file->f_mutex); |
428 | nlmsvc_release_block(newblock); | 409 | nlmsvc_release_block(newblock); |
429 | nlmsvc_release_block(block); | 410 | nlmsvc_release_block(block); |
430 | dprintk("lockd: nlmsvc_lock returned %u\n", ret); | 411 | dprintk("lockd: nlmsvc_lock returned %u\n", ret); |
@@ -434,7 +415,7 @@ out: | |||
434 | /* | 415 | /* |
435 | * Test for presence of a conflicting lock. | 416 | * Test for presence of a conflicting lock. |
436 | */ | 417 | */ |
437 | u32 | 418 | __be32 |
438 | nlmsvc_testlock(struct nlm_file *file, struct nlm_lock *lock, | 419 | nlmsvc_testlock(struct nlm_file *file, struct nlm_lock *lock, |
439 | struct nlm_lock *conflock) | 420 | struct nlm_lock *conflock) |
440 | { | 421 | { |
@@ -451,6 +432,7 @@ nlmsvc_testlock(struct nlm_file *file, struct nlm_lock *lock, | |||
451 | (long long)conflock->fl.fl_start, | 432 | (long long)conflock->fl.fl_start, |
452 | (long long)conflock->fl.fl_end); | 433 | (long long)conflock->fl.fl_end); |
453 | conflock->caller = "somehost"; /* FIXME */ | 434 | conflock->caller = "somehost"; /* FIXME */ |
435 | conflock->len = strlen(conflock->caller); | ||
454 | conflock->oh.len = 0; /* don't return OH info */ | 436 | conflock->oh.len = 0; /* don't return OH info */ |
455 | conflock->svid = conflock->fl.fl_pid; | 437 | conflock->svid = conflock->fl.fl_pid; |
456 | return nlm_lck_denied; | 438 | return nlm_lck_denied; |
@@ -466,7 +448,7 @@ nlmsvc_testlock(struct nlm_file *file, struct nlm_lock *lock, | |||
466 | * afterwards. In this case the block will still be there, and hence | 448 | * afterwards. In this case the block will still be there, and hence |
467 | * must be removed. | 449 | * must be removed. |
468 | */ | 450 | */ |
469 | u32 | 451 | __be32 |
470 | nlmsvc_unlock(struct nlm_file *file, struct nlm_lock *lock) | 452 | nlmsvc_unlock(struct nlm_file *file, struct nlm_lock *lock) |
471 | { | 453 | { |
472 | int error; | 454 | int error; |
@@ -494,7 +476,7 @@ nlmsvc_unlock(struct nlm_file *file, struct nlm_lock *lock) | |||
494 | * be in progress. | 476 | * be in progress. |
495 | * The calling procedure must check whether the file can be closed. | 477 | * The calling procedure must check whether the file can be closed. |
496 | */ | 478 | */ |
497 | u32 | 479 | __be32 |
498 | nlmsvc_cancel_blocked(struct nlm_file *file, struct nlm_lock *lock) | 480 | nlmsvc_cancel_blocked(struct nlm_file *file, struct nlm_lock *lock) |
499 | { | 481 | { |
500 | struct nlm_block *block; | 482 | struct nlm_block *block; |
@@ -507,9 +489,9 @@ nlmsvc_cancel_blocked(struct nlm_file *file, struct nlm_lock *lock) | |||
507 | (long long)lock->fl.fl_start, | 489 | (long long)lock->fl.fl_start, |
508 | (long long)lock->fl.fl_end); | 490 | (long long)lock->fl.fl_end); |
509 | 491 | ||
510 | down(&file->f_sema); | 492 | mutex_lock(&file->f_mutex); |
511 | block = nlmsvc_lookup_block(file, lock); | 493 | block = nlmsvc_lookup_block(file, lock); |
512 | up(&file->f_sema); | 494 | mutex_unlock(&file->f_mutex); |
513 | if (block != NULL) { | 495 | if (block != NULL) { |
514 | status = nlmsvc_unlink_block(block); | 496 | status = nlmsvc_unlink_block(block); |
515 | nlmsvc_release_block(block); | 497 | nlmsvc_release_block(block); |
@@ -527,10 +509,10 @@ nlmsvc_cancel_blocked(struct nlm_file *file, struct nlm_lock *lock) | |||
527 | static void | 509 | static void |
528 | nlmsvc_notify_blocked(struct file_lock *fl) | 510 | nlmsvc_notify_blocked(struct file_lock *fl) |
529 | { | 511 | { |
530 | struct nlm_block **bp, *block; | 512 | struct nlm_block *block; |
531 | 513 | ||
532 | dprintk("lockd: VFS unblock notification for block %p\n", fl); | 514 | dprintk("lockd: VFS unblock notification for block %p\n", fl); |
533 | for (bp = &nlm_blocked; (block = *bp) != 0; bp = &block->b_next) { | 515 | list_for_each_entry(block, &nlm_blocked, b_list) { |
534 | if (nlm_compare_locks(&block->b_call->a_args.lock.fl, fl)) { | 516 | if (nlm_compare_locks(&block->b_call->a_args.lock.fl, fl)) { |
535 | nlmsvc_insert_block(block, 0); | 517 | nlmsvc_insert_block(block, 0); |
536 | svc_wake_up(block->b_daemon); | 518 | svc_wake_up(block->b_daemon); |
@@ -663,17 +645,14 @@ static const struct rpc_call_ops nlmsvc_grant_ops = { | |||
663 | * block. | 645 | * block. |
664 | */ | 646 | */ |
665 | void | 647 | void |
666 | nlmsvc_grant_reply(struct svc_rqst *rqstp, struct nlm_cookie *cookie, u32 status) | 648 | nlmsvc_grant_reply(struct nlm_cookie *cookie, u32 status) |
667 | { | 649 | { |
668 | struct nlm_block *block; | 650 | struct nlm_block *block; |
669 | struct nlm_file *file; | ||
670 | 651 | ||
671 | dprintk("grant_reply: looking for cookie %x, host (%08x), s=%d \n", | 652 | dprintk("grant_reply: looking for cookie %x, s=%d \n", |
672 | *(unsigned int *)(cookie->data), | 653 | *(unsigned int *)(cookie->data), status); |
673 | ntohl(rqstp->rq_addr.sin_addr.s_addr), status); | 654 | if (!(block = nlmsvc_find_block(cookie))) |
674 | if (!(block = nlmsvc_find_block(cookie, &rqstp->rq_addr))) | ||
675 | return; | 655 | return; |
676 | file = block->b_file; | ||
677 | 656 | ||
678 | if (block) { | 657 | if (block) { |
679 | if (status == NLM_LCK_DENIED_GRACE_PERIOD) { | 658 | if (status == NLM_LCK_DENIED_GRACE_PERIOD) { |
@@ -696,16 +675,19 @@ nlmsvc_grant_reply(struct svc_rqst *rqstp, struct nlm_cookie *cookie, u32 status | |||
696 | unsigned long | 675 | unsigned long |
697 | nlmsvc_retry_blocked(void) | 676 | nlmsvc_retry_blocked(void) |
698 | { | 677 | { |
699 | struct nlm_block *block; | 678 | unsigned long timeout = MAX_SCHEDULE_TIMEOUT; |
679 | struct nlm_block *block; | ||
680 | |||
681 | while (!list_empty(&nlm_blocked)) { | ||
682 | block = list_entry(nlm_blocked.next, struct nlm_block, b_list); | ||
700 | 683 | ||
701 | dprintk("nlmsvc_retry_blocked(%p, when=%ld)\n", | ||
702 | nlm_blocked, | ||
703 | nlm_blocked? nlm_blocked->b_when : 0); | ||
704 | while ((block = nlm_blocked) != 0) { | ||
705 | if (block->b_when == NLM_NEVER) | 684 | if (block->b_when == NLM_NEVER) |
706 | break; | 685 | break; |
707 | if (time_after(block->b_when,jiffies)) | 686 | if (time_after(block->b_when,jiffies)) { |
687 | timeout = block->b_when - jiffies; | ||
708 | break; | 688 | break; |
689 | } | ||
690 | |||
709 | dprintk("nlmsvc_retry_blocked(%p, when=%ld)\n", | 691 | dprintk("nlmsvc_retry_blocked(%p, when=%ld)\n", |
710 | block, block->b_when); | 692 | block, block->b_when); |
711 | kref_get(&block->b_count); | 693 | kref_get(&block->b_count); |
@@ -713,8 +695,5 @@ nlmsvc_retry_blocked(void) | |||
713 | nlmsvc_release_block(block); | 695 | nlmsvc_release_block(block); |
714 | } | 696 | } |
715 | 697 | ||
716 | if ((block = nlm_blocked) && block->b_when != NLM_NEVER) | 698 | return timeout; |
717 | return (block->b_when - jiffies); | ||
718 | |||
719 | return MAX_SCHEDULE_TIMEOUT; | ||
720 | } | 699 | } |