1 /* 2 * linux/fs/lockd/svclock.c 3 * 4 * Handling of server-side locks, mostly of the blocked variety. 5 * This is the ugliest part of lockd because we tread on very thin ice. 6 * GRANT and CANCEL calls may get stuck, meet in mid-flight, etc. 7 * IMNSHO introducing the grant callback into the NLM protocol was one 8 * of the worst ideas Sun ever had. Except maybe for the idea of doing 9 * NFS file locking at all. 10 * 11 * I'm trying hard to avoid race conditions by protecting most accesses 12 * to a file's list of blocked locks through a semaphore. The global 13 * list of blocked locks is not protected in this fashion however. 14 * Therefore, some functions (such as the RPC callback for the async grant 15 * call) move blocked locks towards the head of the list *while some other 16 * process might be traversing it*. This should not be a problem in 17 * practice, because this will only cause functions traversing the list 18 * to visit some blocks twice. 19 * 20 * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de> 21 */ 22 23 #include <linux/config.h> 24 #include <linux/types.h> 25 #include <linux/errno.h> 26 #include <linux/kernel.h> 27 #include <linux/sched.h> 28 #include <linux/smp_lock.h> 29 #include <linux/sunrpc/clnt.h> 30 #include <linux/sunrpc/svc.h> 31 #include <linux/lockd/nlm.h> 32 #include <linux/lockd/lockd.h> 33 34 #define NLMDBG_FACILITY NLMDBG_SVCLOCK 35 36 #ifdef CONFIG_LOCKD_V4 37 #define nlm_deadlock nlm4_deadlock 38 #else 39 #define nlm_deadlock nlm_lck_denied 40 #endif 41 42 static void nlmsvc_release_block(struct nlm_block *block); 43 static void nlmsvc_insert_block(struct nlm_block *block, unsigned long); 44 static int nlmsvc_remove_block(struct nlm_block *block); 45 46 static int nlmsvc_setgrantargs(struct nlm_rqst *call, struct nlm_lock *lock); 47 static void nlmsvc_freegrantargs(struct nlm_rqst *call); 48 static const struct rpc_call_ops nlmsvc_grant_ops; 49 50 /* 51 * The list of blocked locks to retry 52 */ 53 static struct nlm_block * nlm_blocked; 54 55 /* 56 * Insert a blocked lock into the global list 57 */ 58 static void 59 nlmsvc_insert_block(struct nlm_block *block, unsigned long when) 60 { 61 struct nlm_block **bp, *b; 62 63 dprintk("lockd: nlmsvc_insert_block(%p, %ld)\n", block, when); 64 kref_get(&block->b_count); 65 if (block->b_queued) 66 nlmsvc_remove_block(block); 67 bp = &nlm_blocked; 68 if (when != NLM_NEVER) { 69 if ((when += jiffies) == NLM_NEVER) 70 when ++; 71 while ((b = *bp) && time_before_eq(b->b_when,when) && b->b_when != NLM_NEVER) 72 bp = &b->b_next; 73 } else 74 while ((b = *bp) != 0) 75 bp = &b->b_next; 76 77 block->b_queued = 1; 78 block->b_when = when; 79 block->b_next = b; 80 *bp = block; 81 } 82 83 /* 84 * Remove a block from the global list 85 */ 86 static int 87 nlmsvc_remove_block(struct nlm_block *block) 88 { 89 struct nlm_block **bp, *b; 90 91 if (!block->b_queued) 92 return 1; 93 for (bp = &nlm_blocked; (b = *bp) != 0; bp = &b->b_next) { 94 if (b == block) { 95 *bp = block->b_next; 96 block->b_queued = 0; 97 nlmsvc_release_block(block); 98 return 1; 99 } 100 } 101 102 return 0; 103 } 104 105 /* 106 * Find a block for a given lock 107 */ 108 static struct nlm_block * 109 nlmsvc_lookup_block(struct nlm_file *file, struct nlm_lock *lock) 110 { 111 struct nlm_block **head, *block; 112 struct file_lock *fl; 113 114 dprintk("lockd: nlmsvc_lookup_block f=%p pd=%d %Ld-%Ld ty=%d\n", 115 file, lock->fl.fl_pid, 116 (long long)lock->fl.fl_start, 117 (long long)lock->fl.fl_end, lock->fl.fl_type); 118 for (head = &nlm_blocked; (block = *head) != 0; head = &block->b_next) { 119 fl = &block->b_call->a_args.lock.fl; 120 dprintk("lockd: check f=%p pd=%d %Ld-%Ld ty=%d cookie=%s\n", 121 block->b_file, fl->fl_pid, 122 (long long)fl->fl_start, 123 (long long)fl->fl_end, fl->fl_type, 124 nlmdbg_cookie2a(&block->b_call->a_args.cookie)); 125 if (block->b_file == file && nlm_compare_locks(fl, &lock->fl)) { 126 kref_get(&block->b_count); 127 return block; 128 } 129 } 130 131 return NULL; 132 } 133 134 static inline int nlm_cookie_match(struct nlm_cookie *a, struct nlm_cookie *b) 135 { 136 if(a->len != b->len) 137 return 0; 138 if(memcmp(a->data,b->data,a->len)) 139 return 0; 140 return 1; 141 } 142 143 /* 144 * Find a block with a given NLM cookie. 145 */ 146 static inline struct nlm_block * 147 nlmsvc_find_block(struct nlm_cookie *cookie, struct sockaddr_in *sin) 148 { 149 struct nlm_block *block; 150 151 for (block = nlm_blocked; block; block = block->b_next) { 152 dprintk("cookie: head of blocked queue %p, block %p\n", 153 nlm_blocked, block); 154 if (nlm_cookie_match(&block->b_call->a_args.cookie,cookie) 155 && nlm_cmp_addr(sin, &block->b_host->h_addr)) 156 break; 157 } 158 159 if (block != NULL) 160 kref_get(&block->b_count); 161 return block; 162 } 163 164 /* 165 * Create a block and initialize it. 166 * 167 * Note: we explicitly set the cookie of the grant reply to that of 168 * the blocked lock request. The spec explicitly mentions that the client 169 * should _not_ rely on the callback containing the same cookie as the 170 * request, but (as I found out later) that's because some implementations 171 * do just this. Never mind the standards comittees, they support our 172 * logging industries. 173 */ 174 static inline struct nlm_block * 175 nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_file *file, 176 struct nlm_lock *lock, struct nlm_cookie *cookie) 177 { 178 struct nlm_block *block; 179 struct nlm_host *host; 180 struct nlm_rqst *call = NULL; 181 182 /* Create host handle for callback */ 183 host = nlmsvc_lookup_host(rqstp); 184 if (host == NULL) 185 return NULL; 186 187 call = nlm_alloc_call(host); 188 if (call == NULL) 189 return NULL; 190 191 /* Allocate memory for block, and initialize arguments */ 192 block = kzalloc(sizeof(*block), GFP_KERNEL); 193 if (block == NULL) 194 goto failed; 195 kref_init(&block->b_count); 196 197 if (!nlmsvc_setgrantargs(call, lock)) 198 goto failed_free; 199 200 /* Set notifier function for VFS, and init args */ 201 call->a_args.lock.fl.fl_flags |= FL_SLEEP; 202 call->a_args.lock.fl.fl_lmops = &nlmsvc_lock_operations; 203 call->a_args.cookie = *cookie; /* see above */ 204 205 dprintk("lockd: created block %p...\n", block); 206 207 /* Create and initialize the block */ 208 block->b_daemon = rqstp->rq_server; 209 block->b_host = host; 210 block->b_file = file; 211 file->f_count++; 212 213 /* Add to file's list of blocks */ 214 block->b_fnext = file->f_blocks; 215 file->f_blocks = block; 216 217 /* Set up RPC arguments for callback */ 218 block->b_call = call; 219 call->a_flags = RPC_TASK_ASYNC; 220 call->a_block = block; 221 222 return block; 223 224 failed_free: 225 kfree(block); 226 failed: 227 nlm_release_call(call); 228 return NULL; 229 } 230 231 /* 232 * Delete a block. If the lock was cancelled or the grant callback 233 * failed, unlock is set to 1. 234 * It is the caller's responsibility to check whether the file 235 * can be closed hereafter. 236 */ 237 static int nlmsvc_unlink_block(struct nlm_block *block) 238 { 239 int status; 240 dprintk("lockd: unlinking block %p...\n", block); 241 242 /* Remove block from list */ 243 status = posix_unblock_lock(block->b_file->f_file, &block->b_call->a_args.lock.fl); 244 nlmsvc_remove_block(block); 245 return status; 246 } 247 248 static void nlmsvc_free_block(struct kref *kref) 249 { 250 struct nlm_block *block = container_of(kref, struct nlm_block, b_count); 251 struct nlm_file *file = block->b_file; 252 struct nlm_block **bp; 253 254 dprintk("lockd: freeing block %p...\n", block); 255 256 down(&file->f_sema); 257 /* Remove block from file's list of blocks */ 258 for (bp = &file->f_blocks; *bp; bp = &(*bp)->b_fnext) { 259 if (*bp == block) { 260 *bp = block->b_fnext; 261 break; 262 } 263 } 264 up(&file->f_sema); 265 266 nlmsvc_freegrantargs(block->b_call); 267 nlm_release_call(block->b_call); 268 nlm_release_file(block->b_file); 269 kfree(block); 270 } 271 272 static void nlmsvc_release_block(struct nlm_block *block) 273 { 274 if (block != NULL) 275 kref_put(&block->b_count, nlmsvc_free_block); 276 } 277 278 static void nlmsvc_act_mark(struct nlm_host *host, struct nlm_file *file) 279 { 280 struct nlm_block *block; 281 282 down(&file->f_sema); 283 for (block = file->f_blocks; block != NULL; block = block->b_fnext) 284 block->b_host->h_inuse = 1; 285 up(&file->f_sema); 286 } 287 288 static void nlmsvc_act_unlock(struct nlm_host *host, struct nlm_file *file) 289 { 290 struct nlm_block *block; 291 292 restart: 293 down(&file->f_sema); 294 for (block = file->f_blocks; block != NULL; block = block->b_fnext) { 295 if (host != NULL && host != block->b_host) 296 continue; 297 if (!block->b_queued) 298 continue; 299 kref_get(&block->b_count); 300 up(&file->f_sema); 301 nlmsvc_unlink_block(block); 302 nlmsvc_release_block(block); 303 goto restart; 304 } 305 up(&file->f_sema); 306 } 307 308 /* 309 * Loop over all blocks and perform the action specified. 310 * (NLM_ACT_CHECK handled by nlmsvc_inspect_file). 311 */ 312 void 313 nlmsvc_traverse_blocks(struct nlm_host *host, struct nlm_file *file, int action) 314 { 315 if (action == NLM_ACT_MARK) 316 nlmsvc_act_mark(host, file); 317 else 318 nlmsvc_act_unlock(host, file); 319 } 320 321 /* 322 * Initialize arguments for GRANTED call. The nlm_rqst structure 323 * has been cleared already. 324 */ 325 static int nlmsvc_setgrantargs(struct nlm_rqst *call, struct nlm_lock *lock) 326 { 327 locks_copy_lock(&call->a_args.lock.fl, &lock->fl); 328 memcpy(&call->a_args.lock.fh, &lock->fh, sizeof(call->a_args.lock.fh)); 329 call->a_args.lock.caller = system_utsname.nodename; 330 call->a_args.lock.oh.len = lock->oh.len; 331 332 /* set default data area */ 333 call->a_args.lock.oh.data = call->a_owner; 334 call->a_args.lock.svid = lock->fl.fl_pid; 335 336 if (lock->oh.len > NLMCLNT_OHSIZE) { 337 void *data = kmalloc(lock->oh.len, GFP_KERNEL); 338 if (!data) 339 return 0; 340 call->a_args.lock.oh.data = (u8 *) data; 341 } 342 343 memcpy(call->a_args.lock.oh.data, lock->oh.data, lock->oh.len); 344 return 1; 345 } 346 347 static void nlmsvc_freegrantargs(struct nlm_rqst *call) 348 { 349 if (call->a_args.lock.oh.data != call->a_owner) 350 kfree(call->a_args.lock.oh.data); 351 } 352 353 /* 354 * Attempt to establish a lock, and if it can't be granted, block it 355 * if required. 356 */ 357 u32 358 nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file, 359 struct nlm_lock *lock, int wait, struct nlm_cookie *cookie) 360 { 361 struct nlm_block *block, *newblock = NULL; 362 int error; 363 u32 ret; 364 365 dprintk("lockd: nlmsvc_lock(%s/%ld, ty=%d, pi=%d, %Ld-%Ld, bl=%d)\n", 366 file->f_file->f_dentry->d_inode->i_sb->s_id, 367 file->f_file->f_dentry->d_inode->i_ino, 368 lock->fl.fl_type, lock->fl.fl_pid, 369 (long long)lock->fl.fl_start, 370 (long long)lock->fl.fl_end, 371 wait); 372 373 374 lock->fl.fl_flags &= ~FL_SLEEP; 375 again: 376 /* Lock file against concurrent access */ 377 down(&file->f_sema); 378 /* Get existing block (in case client is busy-waiting) */ 379 block = nlmsvc_lookup_block(file, lock); 380 if (block == NULL) { 381 if (newblock != NULL) 382 lock = &newblock->b_call->a_args.lock; 383 } else 384 lock = &block->b_call->a_args.lock; 385 386 error = posix_lock_file(file->f_file, &lock->fl); 387 lock->fl.fl_flags &= ~FL_SLEEP; 388 389 dprintk("lockd: posix_lock_file returned %d\n", error); 390 391 switch(error) { 392 case 0: 393 ret = nlm_granted; 394 goto out; 395 case -EAGAIN: 396 break; 397 case -EDEADLK: 398 ret = nlm_deadlock; 399 goto out; 400 default: /* includes ENOLCK */ 401 ret = nlm_lck_denied_nolocks; 402 goto out; 403 } 404 405 ret = nlm_lck_denied; 406 if (!wait) 407 goto out; 408 409 ret = nlm_lck_blocked; 410 if (block != NULL) 411 goto out; 412 413 /* If we don't have a block, create and initialize it. Then 414 * retry because we may have slept in kmalloc. */ 415 /* We have to release f_sema as nlmsvc_create_block may try to 416 * to claim it while doing host garbage collection */ 417 if (newblock == NULL) { 418 up(&file->f_sema); 419 dprintk("lockd: blocking on this lock (allocating).\n"); 420 if (!(newblock = nlmsvc_create_block(rqstp, file, lock, cookie))) 421 return nlm_lck_denied_nolocks; 422 goto again; 423 } 424 425 /* Append to list of blocked */ 426 nlmsvc_insert_block(newblock, NLM_NEVER); 427 out: 428 up(&file->f_sema); 429 nlmsvc_release_block(newblock); 430 nlmsvc_release_block(block); 431 dprintk("lockd: nlmsvc_lock returned %u\n", ret); 432 return ret; 433 } 434 435 /* 436 * Test for presence of a conflicting lock. 437 */ 438 u32 439 nlmsvc_testlock(struct nlm_file *file, struct nlm_lock *lock, 440 struct nlm_lock *conflock) 441 { 442 dprintk("lockd: nlmsvc_testlock(%s/%ld, ty=%d, %Ld-%Ld)\n", 443 file->f_file->f_dentry->d_inode->i_sb->s_id, 444 file->f_file->f_dentry->d_inode->i_ino, 445 lock->fl.fl_type, 446 (long long)lock->fl.fl_start, 447 (long long)lock->fl.fl_end); 448 449 if (posix_test_lock(file->f_file, &lock->fl, &conflock->fl)) { 450 dprintk("lockd: conflicting lock(ty=%d, %Ld-%Ld)\n", 451 conflock->fl.fl_type, 452 (long long)conflock->fl.fl_start, 453 (long long)conflock->fl.fl_end); 454 conflock->caller = "somehost"; /* FIXME */ 455 conflock->oh.len = 0; /* don't return OH info */ 456 conflock->svid = conflock->fl.fl_pid; 457 return nlm_lck_denied; 458 } 459 460 return nlm_granted; 461 } 462 463 /* 464 * Remove a lock. 465 * This implies a CANCEL call: We send a GRANT_MSG, the client replies 466 * with a GRANT_RES call which gets lost, and calls UNLOCK immediately 467 * afterwards. In this case the block will still be there, and hence 468 * must be removed. 469 */ 470 u32 471 nlmsvc_unlock(struct nlm_file *file, struct nlm_lock *lock) 472 { 473 int error; 474 475 dprintk("lockd: nlmsvc_unlock(%s/%ld, pi=%d, %Ld-%Ld)\n", 476 file->f_file->f_dentry->d_inode->i_sb->s_id, 477 file->f_file->f_dentry->d_inode->i_ino, 478 lock->fl.fl_pid, 479 (long long)lock->fl.fl_start, 480 (long long)lock->fl.fl_end); 481 482 /* First, cancel any lock that might be there */ 483 nlmsvc_cancel_blocked(file, lock); 484 485 lock->fl.fl_type = F_UNLCK; 486 error = posix_lock_file(file->f_file, &lock->fl); 487 488 return (error < 0)? nlm_lck_denied_nolocks : nlm_granted; 489 } 490 491 /* 492 * Cancel a previously blocked request. 493 * 494 * A cancel request always overrides any grant that may currently 495 * be in progress. 496 * The calling procedure must check whether the file can be closed. 497 */ 498 u32 499 nlmsvc_cancel_blocked(struct nlm_file *file, struct nlm_lock *lock) 500 { 501 struct nlm_block *block; 502 int status = 0; 503 504 dprintk("lockd: nlmsvc_cancel(%s/%ld, pi=%d, %Ld-%Ld)\n", 505 file->f_file->f_dentry->d_inode->i_sb->s_id, 506 file->f_file->f_dentry->d_inode->i_ino, 507 lock->fl.fl_pid, 508 (long long)lock->fl.fl_start, 509 (long long)lock->fl.fl_end); 510 511 down(&file->f_sema); 512 block = nlmsvc_lookup_block(file, lock); 513 up(&file->f_sema); 514 if (block != NULL) { 515 status = nlmsvc_unlink_block(block); 516 nlmsvc_release_block(block); 517 } 518 return status ? nlm_lck_denied : nlm_granted; 519 } 520 521 /* 522 * Unblock a blocked lock request. This is a callback invoked from the 523 * VFS layer when a lock on which we blocked is removed. 524 * 525 * This function doesn't grant the blocked lock instantly, but rather moves 526 * the block to the head of nlm_blocked where it can be picked up by lockd. 527 */ 528 static void 529 nlmsvc_notify_blocked(struct file_lock *fl) 530 { 531 struct nlm_block **bp, *block; 532 533 dprintk("lockd: VFS unblock notification for block %p\n", fl); 534 for (bp = &nlm_blocked; (block = *bp) != 0; bp = &block->b_next) { 535 if (nlm_compare_locks(&block->b_call->a_args.lock.fl, fl)) { 536 nlmsvc_insert_block(block, 0); 537 svc_wake_up(block->b_daemon); 538 return; 539 } 540 } 541 542 printk(KERN_WARNING "lockd: notification for unknown block!\n"); 543 } 544 545 static int nlmsvc_same_owner(struct file_lock *fl1, struct file_lock *fl2) 546 { 547 return fl1->fl_owner == fl2->fl_owner && fl1->fl_pid == fl2->fl_pid; 548 } 549 550 struct lock_manager_operations nlmsvc_lock_operations = { 551 .fl_compare_owner = nlmsvc_same_owner, 552 .fl_notify = nlmsvc_notify_blocked, 553 }; 554 555 /* 556 * Try to claim a lock that was previously blocked. 557 * 558 * Note that we use both the RPC_GRANTED_MSG call _and_ an async 559 * RPC thread when notifying the client. This seems like overkill... 560 * Here's why: 561 * - we don't want to use a synchronous RPC thread, otherwise 562 * we might find ourselves hanging on a dead portmapper. 563 * - Some lockd implementations (e.g. HP) don't react to 564 * RPC_GRANTED calls; they seem to insist on RPC_GRANTED_MSG calls. 565 */ 566 static void 567 nlmsvc_grant_blocked(struct nlm_block *block) 568 { 569 struct nlm_file *file = block->b_file; 570 struct nlm_lock *lock = &block->b_call->a_args.lock; 571 int error; 572 573 dprintk("lockd: grant blocked lock %p\n", block); 574 575 /* Unlink block request from list */ 576 nlmsvc_unlink_block(block); 577 578 /* If b_granted is true this means we've been here before. 579 * Just retry the grant callback, possibly refreshing the RPC 580 * binding */ 581 if (block->b_granted) { 582 nlm_rebind_host(block->b_host); 583 goto callback; 584 } 585 586 /* Try the lock operation again */ 587 lock->fl.fl_flags |= FL_SLEEP; 588 error = posix_lock_file(file->f_file, &lock->fl); 589 lock->fl.fl_flags &= ~FL_SLEEP; 590 591 switch (error) { 592 case 0: 593 break; 594 case -EAGAIN: 595 dprintk("lockd: lock still blocked\n"); 596 nlmsvc_insert_block(block, NLM_NEVER); 597 return; 598 default: 599 printk(KERN_WARNING "lockd: unexpected error %d in %s!\n", 600 -error, __FUNCTION__); 601 nlmsvc_insert_block(block, 10 * HZ); 602 return; 603 } 604 605 callback: 606 /* Lock was granted by VFS. */ 607 dprintk("lockd: GRANTing blocked lock.\n"); 608 block->b_granted = 1; 609 610 /* Schedule next grant callback in 30 seconds */ 611 nlmsvc_insert_block(block, 30 * HZ); 612 613 /* Call the client */ 614 kref_get(&block->b_count); 615 if (nlm_async_call(block->b_call, NLMPROC_GRANTED_MSG, 616 &nlmsvc_grant_ops) < 0) 617 nlmsvc_release_block(block); 618 } 619 620 /* 621 * This is the callback from the RPC layer when the NLM_GRANTED_MSG 622 * RPC call has succeeded or timed out. 623 * Like all RPC callbacks, it is invoked by the rpciod process, so it 624 * better not sleep. Therefore, we put the blocked lock on the nlm_blocked 625 * chain once more in order to have it removed by lockd itself (which can 626 * then sleep on the file semaphore without disrupting e.g. the nfs client). 627 */ 628 static void nlmsvc_grant_callback(struct rpc_task *task, void *data) 629 { 630 struct nlm_rqst *call = data; 631 struct nlm_block *block = call->a_block; 632 unsigned long timeout; 633 634 dprintk("lockd: GRANT_MSG RPC callback\n"); 635 636 /* Technically, we should down the file semaphore here. Since we 637 * move the block towards the head of the queue only, no harm 638 * can be done, though. */ 639 if (task->tk_status < 0) { 640 /* RPC error: Re-insert for retransmission */ 641 timeout = 10 * HZ; 642 } else if (block->b_done) { 643 /* Block already removed, kill it for real */ 644 timeout = 0; 645 } else { 646 /* Call was successful, now wait for client callback */ 647 timeout = 60 * HZ; 648 } 649 nlmsvc_insert_block(block, timeout); 650 svc_wake_up(block->b_daemon); 651 } 652 653 static void nlmsvc_grant_release(void *data) 654 { 655 struct nlm_rqst *call = data; 656 657 nlmsvc_release_block(call->a_block); 658 } 659 660 static const struct rpc_call_ops nlmsvc_grant_ops = { 661 .rpc_call_done = nlmsvc_grant_callback, 662 .rpc_release = nlmsvc_grant_release, 663 }; 664 665 /* 666 * We received a GRANT_RES callback. Try to find the corresponding 667 * block. 668 */ 669 void 670 nlmsvc_grant_reply(struct svc_rqst *rqstp, struct nlm_cookie *cookie, u32 status) 671 { 672 struct nlm_block *block; 673 struct nlm_file *file; 674 675 dprintk("grant_reply: looking for cookie %x, host (%08x), s=%d \n", 676 *(unsigned int *)(cookie->data), 677 ntohl(rqstp->rq_addr.sin_addr.s_addr), status); 678 if (!(block = nlmsvc_find_block(cookie, &rqstp->rq_addr))) 679 return; 680 file = block->b_file; 681 682 if (block) { 683 if (status == NLM_LCK_DENIED_GRACE_PERIOD) { 684 /* Try again in a couple of seconds */ 685 nlmsvc_insert_block(block, 10 * HZ); 686 } else { 687 /* Lock is now held by client, or has been rejected. 688 * In both cases, the block should be removed. */ 689 nlmsvc_unlink_block(block); 690 } 691 } 692 nlmsvc_release_block(block); 693 } 694 695 /* 696 * Retry all blocked locks that have been notified. This is where lockd 697 * picks up locks that can be granted, or grant notifications that must 698 * be retransmitted. 699 */ 700 unsigned long 701 nlmsvc_retry_blocked(void) 702 { 703 struct nlm_block *block; 704 705 dprintk("nlmsvc_retry_blocked(%p, when=%ld)\n", 706 nlm_blocked, 707 nlm_blocked? nlm_blocked->b_when : 0); 708 while ((block = nlm_blocked) != 0) { 709 if (block->b_when == NLM_NEVER) 710 break; 711 if (time_after(block->b_when,jiffies)) 712 break; 713 dprintk("nlmsvc_retry_blocked(%p, when=%ld, done=%d)\n", 714 block, block->b_when, block->b_done); 715 kref_get(&block->b_count); 716 if (block->b_done) 717 nlmsvc_unlink_block(block); 718 else 719 nlmsvc_grant_blocked(block); 720 nlmsvc_release_block(block); 721 } 722 723 if ((block = nlm_blocked) && block->b_when != NLM_NEVER) 724 return (block->b_when - jiffies); 725 726 return MAX_SCHEDULE_TIMEOUT; 727 } 728