diff options
Diffstat (limited to 'fs/lockd')
-rw-r--r-- | fs/lockd/mon.c | 10 | ||||
-rw-r--r-- | fs/lockd/svc4proc.c | 6 | ||||
-rw-r--r-- | fs/lockd/svclock.c | 275 | ||||
-rw-r--r-- | fs/lockd/svcproc.c | 7 | ||||
-rw-r--r-- | fs/lockd/svcsubs.c | 2 | ||||
-rw-r--r-- | fs/lockd/xdr.c | 20 | ||||
-rw-r--r-- | fs/lockd/xdr4.c | 24 |
7 files changed, 268 insertions, 76 deletions
diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c index eb243edf8932..2102e2d0134d 100644 --- a/fs/lockd/mon.c +++ b/fs/lockd/mon.c | |||
@@ -225,16 +225,13 @@ xdr_decode_stat(struct rpc_rqst *rqstp, __be32 *p, struct nsm_res *resp) | |||
225 | #define SM_monres_sz 2 | 225 | #define SM_monres_sz 2 |
226 | #define SM_unmonres_sz 1 | 226 | #define SM_unmonres_sz 1 |
227 | 227 | ||
228 | #ifndef MAX | ||
229 | # define MAX(a, b) (((a) > (b))? (a) : (b)) | ||
230 | #endif | ||
231 | |||
232 | static struct rpc_procinfo nsm_procedures[] = { | 228 | static struct rpc_procinfo nsm_procedures[] = { |
233 | [SM_MON] = { | 229 | [SM_MON] = { |
234 | .p_proc = SM_MON, | 230 | .p_proc = SM_MON, |
235 | .p_encode = (kxdrproc_t) xdr_encode_mon, | 231 | .p_encode = (kxdrproc_t) xdr_encode_mon, |
236 | .p_decode = (kxdrproc_t) xdr_decode_stat_res, | 232 | .p_decode = (kxdrproc_t) xdr_decode_stat_res, |
237 | .p_bufsiz = MAX(SM_mon_sz, SM_monres_sz) << 2, | 233 | .p_arglen = SM_mon_sz, |
234 | .p_replen = SM_monres_sz, | ||
238 | .p_statidx = SM_MON, | 235 | .p_statidx = SM_MON, |
239 | .p_name = "MONITOR", | 236 | .p_name = "MONITOR", |
240 | }, | 237 | }, |
@@ -242,7 +239,8 @@ static struct rpc_procinfo nsm_procedures[] = { | |||
242 | .p_proc = SM_UNMON, | 239 | .p_proc = SM_UNMON, |
243 | .p_encode = (kxdrproc_t) xdr_encode_unmon, | 240 | .p_encode = (kxdrproc_t) xdr_encode_unmon, |
244 | .p_decode = (kxdrproc_t) xdr_decode_stat, | 241 | .p_decode = (kxdrproc_t) xdr_decode_stat, |
245 | .p_bufsiz = MAX(SM_mon_id_sz, SM_unmonres_sz) << 2, | 242 | .p_arglen = SM_mon_id_sz, |
243 | .p_replen = SM_unmonres_sz, | ||
246 | .p_statidx = SM_UNMON, | 244 | .p_statidx = SM_UNMON, |
247 | .p_name = "UNMONITOR", | 245 | .p_name = "UNMONITOR", |
248 | }, | 246 | }, |
diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c index 47a66aa5d55b..bf27b6c6cb6b 100644 --- a/fs/lockd/svc4proc.c +++ b/fs/lockd/svc4proc.c | |||
@@ -99,7 +99,9 @@ nlm4svc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp, | |||
99 | return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; | 99 | return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; |
100 | 100 | ||
101 | /* Now check for conflicting locks */ | 101 | /* Now check for conflicting locks */ |
102 | resp->status = nlmsvc_testlock(file, &argp->lock, &resp->lock); | 102 | resp->status = nlmsvc_testlock(rqstp, file, &argp->lock, &resp->lock, &resp->cookie); |
103 | if (resp->status == nlm_drop_reply) | ||
104 | return rpc_drop_reply; | ||
103 | 105 | ||
104 | dprintk("lockd: TEST4 status %d\n", ntohl(resp->status)); | 106 | dprintk("lockd: TEST4 status %d\n", ntohl(resp->status)); |
105 | nlm_release_host(host); | 107 | nlm_release_host(host); |
@@ -143,6 +145,8 @@ nlm4svc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp, | |||
143 | /* Now try to lock the file */ | 145 | /* Now try to lock the file */ |
144 | resp->status = nlmsvc_lock(rqstp, file, &argp->lock, | 146 | resp->status = nlmsvc_lock(rqstp, file, &argp->lock, |
145 | argp->block, &argp->cookie); | 147 | argp->block, &argp->cookie); |
148 | if (resp->status == nlm_drop_reply) | ||
149 | return rpc_drop_reply; | ||
146 | 150 | ||
147 | dprintk("lockd: LOCK status %d\n", ntohl(resp->status)); | 151 | dprintk("lockd: LOCK status %d\n", ntohl(resp->status)); |
148 | nlm_release_host(host); | 152 | nlm_release_host(host); |
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c index cf51f849e76c..b3efa4536cc5 100644 --- a/fs/lockd/svclock.c +++ b/fs/lockd/svclock.c | |||
@@ -173,7 +173,7 @@ found: | |||
173 | */ | 173 | */ |
174 | static inline struct nlm_block * | 174 | static inline struct nlm_block * |
175 | nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_file *file, | 175 | nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_file *file, |
176 | struct nlm_lock *lock, struct nlm_cookie *cookie) | 176 | struct nlm_lock *lock, struct nlm_cookie *cookie) |
177 | { | 177 | { |
178 | struct nlm_block *block; | 178 | struct nlm_block *block; |
179 | struct nlm_host *host; | 179 | struct nlm_host *host; |
@@ -210,6 +210,7 @@ nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_file *file, | |||
210 | block->b_daemon = rqstp->rq_server; | 210 | block->b_daemon = rqstp->rq_server; |
211 | block->b_host = host; | 211 | block->b_host = host; |
212 | block->b_file = file; | 212 | block->b_file = file; |
213 | block->b_fl = NULL; | ||
213 | file->f_count++; | 214 | file->f_count++; |
214 | 215 | ||
215 | /* Add to file's list of blocks */ | 216 | /* Add to file's list of blocks */ |
@@ -261,6 +262,7 @@ static void nlmsvc_free_block(struct kref *kref) | |||
261 | nlmsvc_freegrantargs(block->b_call); | 262 | nlmsvc_freegrantargs(block->b_call); |
262 | nlm_release_call(block->b_call); | 263 | nlm_release_call(block->b_call); |
263 | nlm_release_file(block->b_file); | 264 | nlm_release_file(block->b_file); |
265 | kfree(block->b_fl); | ||
264 | kfree(block); | 266 | kfree(block); |
265 | } | 267 | } |
266 | 268 | ||
@@ -331,6 +333,31 @@ static void nlmsvc_freegrantargs(struct nlm_rqst *call) | |||
331 | } | 333 | } |
332 | 334 | ||
333 | /* | 335 | /* |
336 | * Deferred lock request handling for non-blocking lock | ||
337 | */ | ||
338 | static u32 | ||
339 | nlmsvc_defer_lock_rqst(struct svc_rqst *rqstp, struct nlm_block *block) | ||
340 | { | ||
341 | u32 status = nlm_lck_denied_nolocks; | ||
342 | |||
343 | block->b_flags |= B_QUEUED; | ||
344 | |||
345 | nlmsvc_insert_block(block, NLM_TIMEOUT); | ||
346 | |||
347 | block->b_cache_req = &rqstp->rq_chandle; | ||
348 | if (rqstp->rq_chandle.defer) { | ||
349 | block->b_deferred_req = | ||
350 | rqstp->rq_chandle.defer(block->b_cache_req); | ||
351 | if (block->b_deferred_req != NULL) | ||
352 | status = nlm_drop_reply; | ||
353 | } | ||
354 | dprintk("lockd: nlmsvc_defer_lock_rqst block %p flags %d status %d\n", | ||
355 | block, block->b_flags, status); | ||
356 | |||
357 | return status; | ||
358 | } | ||
359 | |||
360 | /* | ||
334 | * Attempt to establish a lock, and if it can't be granted, block it | 361 | * Attempt to establish a lock, and if it can't be granted, block it |
335 | * if required. | 362 | * if required. |
336 | */ | 363 | */ |
@@ -338,7 +365,7 @@ __be32 | |||
338 | nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file, | 365 | nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file, |
339 | struct nlm_lock *lock, int wait, struct nlm_cookie *cookie) | 366 | struct nlm_lock *lock, int wait, struct nlm_cookie *cookie) |
340 | { | 367 | { |
341 | struct nlm_block *block, *newblock = NULL; | 368 | struct nlm_block *block = NULL; |
342 | int error; | 369 | int error; |
343 | __be32 ret; | 370 | __be32 ret; |
344 | 371 | ||
@@ -351,29 +378,58 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file, | |||
351 | wait); | 378 | wait); |
352 | 379 | ||
353 | 380 | ||
354 | lock->fl.fl_flags &= ~FL_SLEEP; | ||
355 | again: | ||
356 | /* Lock file against concurrent access */ | 381 | /* Lock file against concurrent access */ |
357 | mutex_lock(&file->f_mutex); | 382 | mutex_lock(&file->f_mutex); |
358 | /* Get existing block (in case client is busy-waiting) */ | 383 | /* Get existing block (in case client is busy-waiting) |
384 | * or create new block | ||
385 | */ | ||
359 | block = nlmsvc_lookup_block(file, lock); | 386 | block = nlmsvc_lookup_block(file, lock); |
360 | if (block == NULL) { | 387 | if (block == NULL) { |
361 | if (newblock != NULL) | 388 | block = nlmsvc_create_block(rqstp, file, lock, cookie); |
362 | lock = &newblock->b_call->a_args.lock; | 389 | ret = nlm_lck_denied_nolocks; |
363 | } else | 390 | if (block == NULL) |
391 | goto out; | ||
364 | lock = &block->b_call->a_args.lock; | 392 | lock = &block->b_call->a_args.lock; |
393 | } else | ||
394 | lock->fl.fl_flags &= ~FL_SLEEP; | ||
365 | 395 | ||
366 | error = posix_lock_file(file->f_file, &lock->fl); | 396 | if (block->b_flags & B_QUEUED) { |
367 | lock->fl.fl_flags &= ~FL_SLEEP; | 397 | dprintk("lockd: nlmsvc_lock deferred block %p flags %d\n", |
398 | block, block->b_flags); | ||
399 | if (block->b_granted) { | ||
400 | nlmsvc_unlink_block(block); | ||
401 | ret = nlm_granted; | ||
402 | goto out; | ||
403 | } | ||
404 | if (block->b_flags & B_TIMED_OUT) { | ||
405 | nlmsvc_unlink_block(block); | ||
406 | ret = nlm_lck_denied; | ||
407 | goto out; | ||
408 | } | ||
409 | ret = nlm_drop_reply; | ||
410 | goto out; | ||
411 | } | ||
368 | 412 | ||
369 | dprintk("lockd: posix_lock_file returned %d\n", error); | 413 | if (!wait) |
414 | lock->fl.fl_flags &= ~FL_SLEEP; | ||
415 | error = vfs_lock_file(file->f_file, F_SETLK, &lock->fl, NULL); | ||
416 | lock->fl.fl_flags &= ~FL_SLEEP; | ||
370 | 417 | ||
418 | dprintk("lockd: vfs_lock_file returned %d\n", error); | ||
371 | switch(error) { | 419 | switch(error) { |
372 | case 0: | 420 | case 0: |
373 | ret = nlm_granted; | 421 | ret = nlm_granted; |
374 | goto out; | 422 | goto out; |
375 | case -EAGAIN: | 423 | case -EAGAIN: |
424 | ret = nlm_lck_denied; | ||
376 | break; | 425 | break; |
426 | case -EINPROGRESS: | ||
427 | if (wait) | ||
428 | break; | ||
429 | /* Filesystem lock operation is in progress | ||
430 | Add it to the queue waiting for callback */ | ||
431 | ret = nlmsvc_defer_lock_rqst(rqstp, block); | ||
432 | goto out; | ||
377 | case -EDEADLK: | 433 | case -EDEADLK: |
378 | ret = nlm_deadlock; | 434 | ret = nlm_deadlock; |
379 | goto out; | 435 | goto out; |
@@ -387,26 +443,11 @@ again: | |||
387 | goto out; | 443 | goto out; |
388 | 444 | ||
389 | ret = nlm_lck_blocked; | 445 | ret = nlm_lck_blocked; |
390 | if (block != NULL) | ||
391 | goto out; | ||
392 | |||
393 | /* If we don't have a block, create and initialize it. Then | ||
394 | * retry because we may have slept in kmalloc. */ | ||
395 | /* We have to release f_mutex as nlmsvc_create_block may try to | ||
396 | * to claim it while doing host garbage collection */ | ||
397 | if (newblock == NULL) { | ||
398 | mutex_unlock(&file->f_mutex); | ||
399 | dprintk("lockd: blocking on this lock (allocating).\n"); | ||
400 | if (!(newblock = nlmsvc_create_block(rqstp, file, lock, cookie))) | ||
401 | return nlm_lck_denied_nolocks; | ||
402 | goto again; | ||
403 | } | ||
404 | 446 | ||
405 | /* Append to list of blocked */ | 447 | /* Append to list of blocked */ |
406 | nlmsvc_insert_block(newblock, NLM_NEVER); | 448 | nlmsvc_insert_block(block, NLM_NEVER); |
407 | out: | 449 | out: |
408 | mutex_unlock(&file->f_mutex); | 450 | mutex_unlock(&file->f_mutex); |
409 | nlmsvc_release_block(newblock); | ||
410 | nlmsvc_release_block(block); | 451 | nlmsvc_release_block(block); |
411 | dprintk("lockd: nlmsvc_lock returned %u\n", ret); | 452 | dprintk("lockd: nlmsvc_lock returned %u\n", ret); |
412 | return ret; | 453 | return ret; |
@@ -416,9 +457,14 @@ out: | |||
416 | * Test for presence of a conflicting lock. | 457 | * Test for presence of a conflicting lock. |
417 | */ | 458 | */ |
418 | __be32 | 459 | __be32 |
419 | nlmsvc_testlock(struct nlm_file *file, struct nlm_lock *lock, | 460 | nlmsvc_testlock(struct svc_rqst *rqstp, struct nlm_file *file, |
420 | struct nlm_lock *conflock) | 461 | struct nlm_lock *lock, struct nlm_lock *conflock, |
462 | struct nlm_cookie *cookie) | ||
421 | { | 463 | { |
464 | struct nlm_block *block = NULL; | ||
465 | int error; | ||
466 | __be32 ret; | ||
467 | |||
422 | dprintk("lockd: nlmsvc_testlock(%s/%ld, ty=%d, %Ld-%Ld)\n", | 468 | dprintk("lockd: nlmsvc_testlock(%s/%ld, ty=%d, %Ld-%Ld)\n", |
423 | file->f_file->f_path.dentry->d_inode->i_sb->s_id, | 469 | file->f_file->f_path.dentry->d_inode->i_sb->s_id, |
424 | file->f_file->f_path.dentry->d_inode->i_ino, | 470 | file->f_file->f_path.dentry->d_inode->i_ino, |
@@ -426,19 +472,70 @@ nlmsvc_testlock(struct nlm_file *file, struct nlm_lock *lock, | |||
426 | (long long)lock->fl.fl_start, | 472 | (long long)lock->fl.fl_start, |
427 | (long long)lock->fl.fl_end); | 473 | (long long)lock->fl.fl_end); |
428 | 474 | ||
429 | if (posix_test_lock(file->f_file, &lock->fl, &conflock->fl)) { | 475 | /* Get existing block (in case client is busy-waiting) */ |
430 | dprintk("lockd: conflicting lock(ty=%d, %Ld-%Ld)\n", | 476 | block = nlmsvc_lookup_block(file, lock); |
431 | conflock->fl.fl_type, | 477 | |
432 | (long long)conflock->fl.fl_start, | 478 | if (block == NULL) { |
433 | (long long)conflock->fl.fl_end); | 479 | struct file_lock *conf = kzalloc(sizeof(*conf), GFP_KERNEL); |
434 | conflock->caller = "somehost"; /* FIXME */ | 480 | |
435 | conflock->len = strlen(conflock->caller); | 481 | if (conf == NULL) |
436 | conflock->oh.len = 0; /* don't return OH info */ | 482 | return nlm_granted; |
437 | conflock->svid = conflock->fl.fl_pid; | 483 | block = nlmsvc_create_block(rqstp, file, lock, cookie); |
438 | return nlm_lck_denied; | 484 | if (block == NULL) { |
485 | kfree(conf); | ||
486 | return nlm_granted; | ||
487 | } | ||
488 | block->b_fl = conf; | ||
489 | } | ||
490 | if (block->b_flags & B_QUEUED) { | ||
491 | dprintk("lockd: nlmsvc_testlock deferred block %p flags %d fl %p\n", | ||
492 | block, block->b_flags, block->b_fl); | ||
493 | if (block->b_flags & B_TIMED_OUT) { | ||
494 | nlmsvc_unlink_block(block); | ||
495 | return nlm_lck_denied; | ||
496 | } | ||
497 | if (block->b_flags & B_GOT_CALLBACK) { | ||
498 | if (block->b_fl != NULL | ||
499 | && block->b_fl->fl_type != F_UNLCK) { | ||
500 | lock->fl = *block->b_fl; | ||
501 | goto conf_lock; | ||
502 | } | ||
503 | else { | ||
504 | nlmsvc_unlink_block(block); | ||
505 | return nlm_granted; | ||
506 | } | ||
507 | } | ||
508 | return nlm_drop_reply; | ||
439 | } | 509 | } |
440 | 510 | ||
441 | return nlm_granted; | 511 | error = vfs_test_lock(file->f_file, &lock->fl); |
512 | if (error == -EINPROGRESS) | ||
513 | return nlmsvc_defer_lock_rqst(rqstp, block); | ||
514 | if (error) { | ||
515 | ret = nlm_lck_denied_nolocks; | ||
516 | goto out; | ||
517 | } | ||
518 | if (lock->fl.fl_type == F_UNLCK) { | ||
519 | ret = nlm_granted; | ||
520 | goto out; | ||
521 | } | ||
522 | |||
523 | conf_lock: | ||
524 | dprintk("lockd: conflicting lock(ty=%d, %Ld-%Ld)\n", | ||
525 | lock->fl.fl_type, (long long)lock->fl.fl_start, | ||
526 | (long long)lock->fl.fl_end); | ||
527 | conflock->caller = "somehost"; /* FIXME */ | ||
528 | conflock->len = strlen(conflock->caller); | ||
529 | conflock->oh.len = 0; /* don't return OH info */ | ||
530 | conflock->svid = lock->fl.fl_pid; | ||
531 | conflock->fl.fl_type = lock->fl.fl_type; | ||
532 | conflock->fl.fl_start = lock->fl.fl_start; | ||
533 | conflock->fl.fl_end = lock->fl.fl_end; | ||
534 | ret = nlm_lck_denied; | ||
535 | out: | ||
536 | if (block) | ||
537 | nlmsvc_release_block(block); | ||
538 | return ret; | ||
442 | } | 539 | } |
443 | 540 | ||
444 | /* | 541 | /* |
@@ -464,7 +561,7 @@ nlmsvc_unlock(struct nlm_file *file, struct nlm_lock *lock) | |||
464 | nlmsvc_cancel_blocked(file, lock); | 561 | nlmsvc_cancel_blocked(file, lock); |
465 | 562 | ||
466 | lock->fl.fl_type = F_UNLCK; | 563 | lock->fl.fl_type = F_UNLCK; |
467 | error = posix_lock_file(file->f_file, &lock->fl); | 564 | error = vfs_lock_file(file->f_file, F_SETLK, &lock->fl, NULL); |
468 | 565 | ||
469 | return (error < 0)? nlm_lck_denied_nolocks : nlm_granted; | 566 | return (error < 0)? nlm_lck_denied_nolocks : nlm_granted; |
470 | } | 567 | } |
@@ -493,6 +590,8 @@ nlmsvc_cancel_blocked(struct nlm_file *file, struct nlm_lock *lock) | |||
493 | block = nlmsvc_lookup_block(file, lock); | 590 | block = nlmsvc_lookup_block(file, lock); |
494 | mutex_unlock(&file->f_mutex); | 591 | mutex_unlock(&file->f_mutex); |
495 | if (block != NULL) { | 592 | if (block != NULL) { |
593 | vfs_cancel_lock(block->b_file->f_file, | ||
594 | &block->b_call->a_args.lock.fl); | ||
496 | status = nlmsvc_unlink_block(block); | 595 | status = nlmsvc_unlink_block(block); |
497 | nlmsvc_release_block(block); | 596 | nlmsvc_release_block(block); |
498 | } | 597 | } |
@@ -500,6 +599,63 @@ nlmsvc_cancel_blocked(struct nlm_file *file, struct nlm_lock *lock) | |||
500 | } | 599 | } |
501 | 600 | ||
502 | /* | 601 | /* |
602 | * This is a callback from the filesystem for VFS file lock requests. | ||
603 | * It will be used if fl_grant is defined and the filesystem can not | ||
604 | * respond to the request immediately. | ||
605 | * For GETLK request it will copy the reply to the nlm_block. | ||
606 | * For SETLK or SETLKW request it will get the local posix lock. | ||
607 | * In all cases it will move the block to the head of nlm_blocked q where | ||
608 | * nlmsvc_retry_blocked() can send back a reply for SETLKW or revisit the | ||
609 | * deferred rpc for GETLK and SETLK. | ||
610 | */ | ||
611 | static void | ||
612 | nlmsvc_update_deferred_block(struct nlm_block *block, struct file_lock *conf, | ||
613 | int result) | ||
614 | { | ||
615 | block->b_flags |= B_GOT_CALLBACK; | ||
616 | if (result == 0) | ||
617 | block->b_granted = 1; | ||
618 | else | ||
619 | block->b_flags |= B_TIMED_OUT; | ||
620 | if (conf) { | ||
621 | if (block->b_fl) | ||
622 | locks_copy_lock(block->b_fl, conf); | ||
623 | } | ||
624 | } | ||
625 | |||
626 | static int nlmsvc_grant_deferred(struct file_lock *fl, struct file_lock *conf, | ||
627 | int result) | ||
628 | { | ||
629 | struct nlm_block *block; | ||
630 | int rc = -ENOENT; | ||
631 | |||
632 | lock_kernel(); | ||
633 | list_for_each_entry(block, &nlm_blocked, b_list) { | ||
634 | if (nlm_compare_locks(&block->b_call->a_args.lock.fl, fl)) { | ||
635 | dprintk("lockd: nlmsvc_notify_blocked block %p flags %d\n", | ||
636 | block, block->b_flags); | ||
637 | if (block->b_flags & B_QUEUED) { | ||
638 | if (block->b_flags & B_TIMED_OUT) { | ||
639 | rc = -ENOLCK; | ||
640 | break; | ||
641 | } | ||
642 | nlmsvc_update_deferred_block(block, conf, result); | ||
643 | } else if (result == 0) | ||
644 | block->b_granted = 1; | ||
645 | |||
646 | nlmsvc_insert_block(block, 0); | ||
647 | svc_wake_up(block->b_daemon); | ||
648 | rc = 0; | ||
649 | break; | ||
650 | } | ||
651 | } | ||
652 | unlock_kernel(); | ||
653 | if (rc == -ENOENT) | ||
654 | printk(KERN_WARNING "lockd: grant for unknown block\n"); | ||
655 | return rc; | ||
656 | } | ||
657 | |||
658 | /* | ||
503 | * Unblock a blocked lock request. This is a callback invoked from the | 659 | * Unblock a blocked lock request. This is a callback invoked from the |
504 | * VFS layer when a lock on which we blocked is removed. | 660 | * VFS layer when a lock on which we blocked is removed. |
505 | * | 661 | * |
@@ -531,6 +687,7 @@ static int nlmsvc_same_owner(struct file_lock *fl1, struct file_lock *fl2) | |||
531 | struct lock_manager_operations nlmsvc_lock_operations = { | 687 | struct lock_manager_operations nlmsvc_lock_operations = { |
532 | .fl_compare_owner = nlmsvc_same_owner, | 688 | .fl_compare_owner = nlmsvc_same_owner, |
533 | .fl_notify = nlmsvc_notify_blocked, | 689 | .fl_notify = nlmsvc_notify_blocked, |
690 | .fl_grant = nlmsvc_grant_deferred, | ||
534 | }; | 691 | }; |
535 | 692 | ||
536 | /* | 693 | /* |
@@ -553,6 +710,8 @@ nlmsvc_grant_blocked(struct nlm_block *block) | |||
553 | 710 | ||
554 | dprintk("lockd: grant blocked lock %p\n", block); | 711 | dprintk("lockd: grant blocked lock %p\n", block); |
555 | 712 | ||
713 | kref_get(&block->b_count); | ||
714 | |||
556 | /* Unlink block request from list */ | 715 | /* Unlink block request from list */ |
557 | nlmsvc_unlink_block(block); | 716 | nlmsvc_unlink_block(block); |
558 | 717 | ||
@@ -566,20 +725,23 @@ nlmsvc_grant_blocked(struct nlm_block *block) | |||
566 | 725 | ||
567 | /* Try the lock operation again */ | 726 | /* Try the lock operation again */ |
568 | lock->fl.fl_flags |= FL_SLEEP; | 727 | lock->fl.fl_flags |= FL_SLEEP; |
569 | error = posix_lock_file(file->f_file, &lock->fl); | 728 | error = vfs_lock_file(file->f_file, F_SETLK, &lock->fl, NULL); |
570 | lock->fl.fl_flags &= ~FL_SLEEP; | 729 | lock->fl.fl_flags &= ~FL_SLEEP; |
571 | 730 | ||
572 | switch (error) { | 731 | switch (error) { |
573 | case 0: | 732 | case 0: |
574 | break; | 733 | break; |
575 | case -EAGAIN: | 734 | case -EAGAIN: |
576 | dprintk("lockd: lock still blocked\n"); | 735 | case -EINPROGRESS: |
736 | dprintk("lockd: lock still blocked error %d\n", error); | ||
577 | nlmsvc_insert_block(block, NLM_NEVER); | 737 | nlmsvc_insert_block(block, NLM_NEVER); |
738 | nlmsvc_release_block(block); | ||
578 | return; | 739 | return; |
579 | default: | 740 | default: |
580 | printk(KERN_WARNING "lockd: unexpected error %d in %s!\n", | 741 | printk(KERN_WARNING "lockd: unexpected error %d in %s!\n", |
581 | -error, __FUNCTION__); | 742 | -error, __FUNCTION__); |
582 | nlmsvc_insert_block(block, 10 * HZ); | 743 | nlmsvc_insert_block(block, 10 * HZ); |
744 | nlmsvc_release_block(block); | ||
583 | return; | 745 | return; |
584 | } | 746 | } |
585 | 747 | ||
@@ -592,7 +754,6 @@ callback: | |||
592 | nlmsvc_insert_block(block, 30 * HZ); | 754 | nlmsvc_insert_block(block, 30 * HZ); |
593 | 755 | ||
594 | /* Call the client */ | 756 | /* Call the client */ |
595 | kref_get(&block->b_count); | ||
596 | nlm_async_call(block->b_call, NLMPROC_GRANTED_MSG, &nlmsvc_grant_ops); | 757 | nlm_async_call(block->b_call, NLMPROC_GRANTED_MSG, &nlmsvc_grant_ops); |
597 | } | 758 | } |
598 | 759 | ||
@@ -665,6 +826,23 @@ nlmsvc_grant_reply(struct nlm_cookie *cookie, __be32 status) | |||
665 | nlmsvc_release_block(block); | 826 | nlmsvc_release_block(block); |
666 | } | 827 | } |
667 | 828 | ||
829 | /* Helper function to handle retry of a deferred block. | ||
830 | * If it is a blocking lock, call grant_blocked. | ||
831 | * For a non-blocking lock or test lock, revisit the request. | ||
832 | */ | ||
833 | static void | ||
834 | retry_deferred_block(struct nlm_block *block) | ||
835 | { | ||
836 | if (!(block->b_flags & B_GOT_CALLBACK)) | ||
837 | block->b_flags |= B_TIMED_OUT; | ||
838 | nlmsvc_insert_block(block, NLM_TIMEOUT); | ||
839 | dprintk("revisit block %p flags %d\n", block, block->b_flags); | ||
840 | if (block->b_deferred_req) { | ||
841 | block->b_deferred_req->revisit(block->b_deferred_req, 0); | ||
842 | block->b_deferred_req = NULL; | ||
843 | } | ||
844 | } | ||
845 | |||
668 | /* | 846 | /* |
669 | * Retry all blocked locks that have been notified. This is where lockd | 847 | * Retry all blocked locks that have been notified. This is where lockd |
670 | * picks up locks that can be granted, or grant notifications that must | 848 | * picks up locks that can be granted, or grant notifications that must |
@@ -688,9 +866,12 @@ nlmsvc_retry_blocked(void) | |||
688 | 866 | ||
689 | dprintk("nlmsvc_retry_blocked(%p, when=%ld)\n", | 867 | dprintk("nlmsvc_retry_blocked(%p, when=%ld)\n", |
690 | block, block->b_when); | 868 | block, block->b_when); |
691 | kref_get(&block->b_count); | 869 | if (block->b_flags & B_QUEUED) { |
692 | nlmsvc_grant_blocked(block); | 870 | dprintk("nlmsvc_retry_blocked delete block (%p, granted=%d, flags=%d)\n", |
693 | nlmsvc_release_block(block); | 871 | block, block->b_granted, block->b_flags); |
872 | retry_deferred_block(block); | ||
873 | } else | ||
874 | nlmsvc_grant_blocked(block); | ||
694 | } | 875 | } |
695 | 876 | ||
696 | return timeout; | 877 | return timeout; |
diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c index 31cb48425733..9cd5c8b37593 100644 --- a/fs/lockd/svcproc.c +++ b/fs/lockd/svcproc.c | |||
@@ -33,6 +33,7 @@ cast_to_nlm(__be32 status, u32 vers) | |||
33 | case nlm_lck_denied_nolocks: | 33 | case nlm_lck_denied_nolocks: |
34 | case nlm_lck_blocked: | 34 | case nlm_lck_blocked: |
35 | case nlm_lck_denied_grace_period: | 35 | case nlm_lck_denied_grace_period: |
36 | case nlm_drop_reply: | ||
36 | break; | 37 | break; |
37 | case nlm4_deadlock: | 38 | case nlm4_deadlock: |
38 | status = nlm_lck_denied; | 39 | status = nlm_lck_denied; |
@@ -127,7 +128,9 @@ nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_args *argp, | |||
127 | return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; | 128 | return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; |
128 | 129 | ||
129 | /* Now check for conflicting locks */ | 130 | /* Now check for conflicting locks */ |
130 | resp->status = cast_status(nlmsvc_testlock(file, &argp->lock, &resp->lock)); | 131 | resp->status = cast_status(nlmsvc_testlock(rqstp, file, &argp->lock, &resp->lock, &resp->cookie)); |
132 | if (resp->status == nlm_drop_reply) | ||
133 | return rpc_drop_reply; | ||
131 | 134 | ||
132 | dprintk("lockd: TEST status %d vers %d\n", | 135 | dprintk("lockd: TEST status %d vers %d\n", |
133 | ntohl(resp->status), rqstp->rq_vers); | 136 | ntohl(resp->status), rqstp->rq_vers); |
@@ -172,6 +175,8 @@ nlmsvc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp, | |||
172 | /* Now try to lock the file */ | 175 | /* Now try to lock the file */ |
173 | resp->status = cast_status(nlmsvc_lock(rqstp, file, &argp->lock, | 176 | resp->status = cast_status(nlmsvc_lock(rqstp, file, &argp->lock, |
174 | argp->block, &argp->cookie)); | 177 | argp->block, &argp->cookie)); |
178 | if (resp->status == nlm_drop_reply) | ||
179 | return rpc_drop_reply; | ||
175 | 180 | ||
176 | dprintk("lockd: LOCK status %d\n", ntohl(resp->status)); | 181 | dprintk("lockd: LOCK status %d\n", ntohl(resp->status)); |
177 | nlm_release_host(host); | 182 | nlm_release_host(host); |
diff --git a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c index c0df00c74ce3..84ebba33b98d 100644 --- a/fs/lockd/svcsubs.c +++ b/fs/lockd/svcsubs.c | |||
@@ -182,7 +182,7 @@ again: | |||
182 | lock.fl_type = F_UNLCK; | 182 | lock.fl_type = F_UNLCK; |
183 | lock.fl_start = 0; | 183 | lock.fl_start = 0; |
184 | lock.fl_end = OFFSET_MAX; | 184 | lock.fl_end = OFFSET_MAX; |
185 | if (posix_lock_file(file->f_file, &lock) < 0) { | 185 | if (vfs_lock_file(file->f_file, F_SETLK, &lock, NULL) < 0) { |
186 | printk("lockd: unlock failure in %s:%d\n", | 186 | printk("lockd: unlock failure in %s:%d\n", |
187 | __FILE__, __LINE__); | 187 | __FILE__, __LINE__); |
188 | return 1; | 188 | return 1; |
diff --git a/fs/lockd/xdr.c b/fs/lockd/xdr.c index 34dae5d70738..9702956d206c 100644 --- a/fs/lockd/xdr.c +++ b/fs/lockd/xdr.c | |||
@@ -510,17 +510,20 @@ nlmclt_decode_res(struct rpc_rqst *req, __be32 *p, struct nlm_res *resp) | |||
510 | return 0; | 510 | return 0; |
511 | } | 511 | } |
512 | 512 | ||
513 | #if (NLMCLNT_OHSIZE > XDR_MAX_NETOBJ) | ||
514 | # error "NLM host name cannot be larger than XDR_MAX_NETOBJ!" | ||
515 | #endif | ||
516 | |||
513 | /* | 517 | /* |
514 | * Buffer requirements for NLM | 518 | * Buffer requirements for NLM |
515 | */ | 519 | */ |
516 | #define NLM_void_sz 0 | 520 | #define NLM_void_sz 0 |
517 | #define NLM_cookie_sz 1+XDR_QUADLEN(NLM_MAXCOOKIELEN) | 521 | #define NLM_cookie_sz 1+XDR_QUADLEN(NLM_MAXCOOKIELEN) |
518 | #define NLM_caller_sz 1+XDR_QUADLEN(sizeof(utsname()->nodename)) | 522 | #define NLM_caller_sz 1+XDR_QUADLEN(NLMCLNT_OHSIZE) |
519 | #define NLM_netobj_sz 1+XDR_QUADLEN(XDR_MAX_NETOBJ) | 523 | #define NLM_owner_sz 1+XDR_QUADLEN(NLMCLNT_OHSIZE) |
520 | /* #define NLM_owner_sz 1+XDR_QUADLEN(NLM_MAXOWNER) */ | ||
521 | #define NLM_fhandle_sz 1+XDR_QUADLEN(NFS2_FHSIZE) | 524 | #define NLM_fhandle_sz 1+XDR_QUADLEN(NFS2_FHSIZE) |
522 | #define NLM_lock_sz 3+NLM_caller_sz+NLM_netobj_sz+NLM_fhandle_sz | 525 | #define NLM_lock_sz 3+NLM_caller_sz+NLM_owner_sz+NLM_fhandle_sz |
523 | #define NLM_holder_sz 4+NLM_netobj_sz | 526 | #define NLM_holder_sz 4+NLM_owner_sz |
524 | 527 | ||
525 | #define NLM_testargs_sz NLM_cookie_sz+1+NLM_lock_sz | 528 | #define NLM_testargs_sz NLM_cookie_sz+1+NLM_lock_sz |
526 | #define NLM_lockargs_sz NLM_cookie_sz+4+NLM_lock_sz | 529 | #define NLM_lockargs_sz NLM_cookie_sz+4+NLM_lock_sz |
@@ -531,10 +534,6 @@ nlmclt_decode_res(struct rpc_rqst *req, __be32 *p, struct nlm_res *resp) | |||
531 | #define NLM_res_sz NLM_cookie_sz+1 | 534 | #define NLM_res_sz NLM_cookie_sz+1 |
532 | #define NLM_norep_sz 0 | 535 | #define NLM_norep_sz 0 |
533 | 536 | ||
534 | #ifndef MAX | ||
535 | # define MAX(a, b) (((a) > (b))? (a) : (b)) | ||
536 | #endif | ||
537 | |||
538 | /* | 537 | /* |
539 | * For NLM, a void procedure really returns nothing | 538 | * For NLM, a void procedure really returns nothing |
540 | */ | 539 | */ |
@@ -545,7 +544,8 @@ nlmclt_decode_res(struct rpc_rqst *req, __be32 *p, struct nlm_res *resp) | |||
545 | .p_proc = NLMPROC_##proc, \ | 544 | .p_proc = NLMPROC_##proc, \ |
546 | .p_encode = (kxdrproc_t) nlmclt_encode_##argtype, \ | 545 | .p_encode = (kxdrproc_t) nlmclt_encode_##argtype, \ |
547 | .p_decode = (kxdrproc_t) nlmclt_decode_##restype, \ | 546 | .p_decode = (kxdrproc_t) nlmclt_decode_##restype, \ |
548 | .p_bufsiz = MAX(NLM_##argtype##_sz, NLM_##restype##_sz) << 2, \ | 547 | .p_arglen = NLM_##argtype##_sz, \ |
548 | .p_replen = NLM_##restype##_sz, \ | ||
549 | .p_statidx = NLMPROC_##proc, \ | 549 | .p_statidx = NLMPROC_##proc, \ |
550 | .p_name = #proc, \ | 550 | .p_name = #proc, \ |
551 | } | 551 | } |
diff --git a/fs/lockd/xdr4.c b/fs/lockd/xdr4.c index a78240551219..ce1efdbe1b3a 100644 --- a/fs/lockd/xdr4.c +++ b/fs/lockd/xdr4.c | |||
@@ -516,17 +516,24 @@ nlm4clt_decode_res(struct rpc_rqst *req, __be32 *p, struct nlm_res *resp) | |||
516 | return 0; | 516 | return 0; |
517 | } | 517 | } |
518 | 518 | ||
519 | #if (NLMCLNT_OHSIZE > XDR_MAX_NETOBJ) | ||
520 | # error "NLM host name cannot be larger than XDR_MAX_NETOBJ!" | ||
521 | #endif | ||
522 | |||
523 | #if (NLMCLNT_OHSIZE > NLM_MAXSTRLEN) | ||
524 | # error "NLM host name cannot be larger than NLM's maximum string length!" | ||
525 | #endif | ||
526 | |||
519 | /* | 527 | /* |
520 | * Buffer requirements for NLM | 528 | * Buffer requirements for NLM |
521 | */ | 529 | */ |
522 | #define NLM4_void_sz 0 | 530 | #define NLM4_void_sz 0 |
523 | #define NLM4_cookie_sz 1+XDR_QUADLEN(NLM_MAXCOOKIELEN) | 531 | #define NLM4_cookie_sz 1+XDR_QUADLEN(NLM_MAXCOOKIELEN) |
524 | #define NLM4_caller_sz 1+XDR_QUADLEN(NLM_MAXSTRLEN) | 532 | #define NLM4_caller_sz 1+XDR_QUADLEN(NLMCLNT_OHSIZE) |
525 | #define NLM4_netobj_sz 1+XDR_QUADLEN(XDR_MAX_NETOBJ) | 533 | #define NLM4_owner_sz 1+XDR_QUADLEN(NLMCLNT_OHSIZE) |
526 | /* #define NLM4_owner_sz 1+XDR_QUADLEN(NLM4_MAXOWNER) */ | ||
527 | #define NLM4_fhandle_sz 1+XDR_QUADLEN(NFS3_FHSIZE) | 534 | #define NLM4_fhandle_sz 1+XDR_QUADLEN(NFS3_FHSIZE) |
528 | #define NLM4_lock_sz 5+NLM4_caller_sz+NLM4_netobj_sz+NLM4_fhandle_sz | 535 | #define NLM4_lock_sz 5+NLM4_caller_sz+NLM4_owner_sz+NLM4_fhandle_sz |
529 | #define NLM4_holder_sz 6+NLM4_netobj_sz | 536 | #define NLM4_holder_sz 6+NLM4_owner_sz |
530 | 537 | ||
531 | #define NLM4_testargs_sz NLM4_cookie_sz+1+NLM4_lock_sz | 538 | #define NLM4_testargs_sz NLM4_cookie_sz+1+NLM4_lock_sz |
532 | #define NLM4_lockargs_sz NLM4_cookie_sz+4+NLM4_lock_sz | 539 | #define NLM4_lockargs_sz NLM4_cookie_sz+4+NLM4_lock_sz |
@@ -537,10 +544,6 @@ nlm4clt_decode_res(struct rpc_rqst *req, __be32 *p, struct nlm_res *resp) | |||
537 | #define NLM4_res_sz NLM4_cookie_sz+1 | 544 | #define NLM4_res_sz NLM4_cookie_sz+1 |
538 | #define NLM4_norep_sz 0 | 545 | #define NLM4_norep_sz 0 |
539 | 546 | ||
540 | #ifndef MAX | ||
541 | # define MAX(a,b) (((a) > (b))? (a) : (b)) | ||
542 | #endif | ||
543 | |||
544 | /* | 547 | /* |
545 | * For NLM, a void procedure really returns nothing | 548 | * For NLM, a void procedure really returns nothing |
546 | */ | 549 | */ |
@@ -551,7 +554,8 @@ nlm4clt_decode_res(struct rpc_rqst *req, __be32 *p, struct nlm_res *resp) | |||
551 | .p_proc = NLMPROC_##proc, \ | 554 | .p_proc = NLMPROC_##proc, \ |
552 | .p_encode = (kxdrproc_t) nlm4clt_encode_##argtype, \ | 555 | .p_encode = (kxdrproc_t) nlm4clt_encode_##argtype, \ |
553 | .p_decode = (kxdrproc_t) nlm4clt_decode_##restype, \ | 556 | .p_decode = (kxdrproc_t) nlm4clt_decode_##restype, \ |
554 | .p_bufsiz = MAX(NLM4_##argtype##_sz, NLM4_##restype##_sz) << 2, \ | 557 | .p_arglen = NLM4_##argtype##_sz, \ |
558 | .p_replen = NLM4_##restype##_sz, \ | ||
555 | .p_statidx = NLMPROC_##proc, \ | 559 | .p_statidx = NLMPROC_##proc, \ |
556 | .p_name = #proc, \ | 560 | .p_name = #proc, \ |
557 | } | 561 | } |