diff options
author | Marc Eshel <eshel@almaden.ibm.com> | 2006-11-28 16:27:06 -0500 |
---|---|---|
committer | J. Bruce Fields <bfields@citi.umich.edu> | 2007-05-06 20:38:50 -0400 |
commit | 1a8322b2b02071b0c7ac37a28357b93e6362f13e (patch) | |
tree | 04fbdd52d8b3c2886d70b3739b9dff683aa79f02 | |
parent | f812048020282fdfa9b72a6cf539c33b6df1fd07 (diff) |
lockd: add code to handle deferred lock requests
Rewrite nlmsvc_lock() to use the asynchronous interface.
As with testlock, we answer nlm requests in nlmsvc_lock by first looking up
the block and then using the results we find in the block if B_QUEUED is
set, and calling vfs_lock_file() otherwise.
If this a new lock request and we get -EINPROGRESS return on a non-blocking
request then we defer the request.
Also modify nlmsvc_unlock() to call the filesystem method if appropriate.
Signed-off-by: Marc Eshel <eshel@almaden.ibm.com>
Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
-rw-r--r-- | fs/lockd/svc4proc.c | 2 | ||||
-rw-r--r-- | fs/lockd/svclock.c | 41 | ||||
-rw-r--r-- | fs/lockd/svcproc.c | 2 | ||||
-rw-r--r-- | fs/lockd/svcsubs.c | 2 |
4 files changed, 40 insertions, 7 deletions
diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c index 205d8befbf1b..bf27b6c6cb6b 100644 --- a/fs/lockd/svc4proc.c +++ b/fs/lockd/svc4proc.c | |||
@@ -145,6 +145,8 @@ nlm4svc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp, | |||
145 | /* Now try to lock the file */ | 145 | /* Now try to lock the file */ |
146 | resp->status = nlmsvc_lock(rqstp, file, &argp->lock, | 146 | resp->status = nlmsvc_lock(rqstp, file, &argp->lock, |
147 | argp->block, &argp->cookie); | 147 | argp->block, &argp->cookie); |
148 | if (resp->status == nlm_drop_reply) | ||
149 | return rpc_drop_reply; | ||
148 | 150 | ||
149 | dprintk("lockd: LOCK status %d\n", ntohl(resp->status)); | 151 | dprintk("lockd: LOCK status %d\n", ntohl(resp->status)); |
150 | nlm_release_host(host); | 152 | nlm_release_host(host); |
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c index 0d7398e3804f..b3efa4536cc5 100644 --- a/fs/lockd/svclock.c +++ b/fs/lockd/svclock.c | |||
@@ -393,17 +393,43 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file, | |||
393 | } else | 393 | } else |
394 | lock->fl.fl_flags &= ~FL_SLEEP; | 394 | lock->fl.fl_flags &= ~FL_SLEEP; |
395 | 395 | ||
396 | error = posix_lock_file(file->f_file, &lock->fl, NULL); | 396 | if (block->b_flags & B_QUEUED) { |
397 | 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 | } | ||
398 | 412 | ||
399 | 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; | ||
400 | 417 | ||
418 | dprintk("lockd: vfs_lock_file returned %d\n", error); | ||
401 | switch(error) { | 419 | switch(error) { |
402 | case 0: | 420 | case 0: |
403 | ret = nlm_granted; | 421 | ret = nlm_granted; |
404 | goto out; | 422 | goto out; |
405 | case -EAGAIN: | 423 | case -EAGAIN: |
424 | ret = nlm_lck_denied; | ||
406 | 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; | ||
407 | case -EDEADLK: | 433 | case -EDEADLK: |
408 | ret = nlm_deadlock; | 434 | ret = nlm_deadlock; |
409 | goto out; | 435 | goto out; |
@@ -535,7 +561,7 @@ nlmsvc_unlock(struct nlm_file *file, struct nlm_lock *lock) | |||
535 | nlmsvc_cancel_blocked(file, lock); | 561 | nlmsvc_cancel_blocked(file, lock); |
536 | 562 | ||
537 | lock->fl.fl_type = F_UNLCK; | 563 | lock->fl.fl_type = F_UNLCK; |
538 | error = posix_lock_file(file->f_file, &lock->fl, NULL); | 564 | error = vfs_lock_file(file->f_file, F_SETLK, &lock->fl, NULL); |
539 | 565 | ||
540 | return (error < 0)? nlm_lck_denied_nolocks : nlm_granted; | 566 | return (error < 0)? nlm_lck_denied_nolocks : nlm_granted; |
541 | } | 567 | } |
@@ -564,6 +590,8 @@ nlmsvc_cancel_blocked(struct nlm_file *file, struct nlm_lock *lock) | |||
564 | block = nlmsvc_lookup_block(file, lock); | 590 | block = nlmsvc_lookup_block(file, lock); |
565 | mutex_unlock(&file->f_mutex); | 591 | mutex_unlock(&file->f_mutex); |
566 | if (block != NULL) { | 592 | if (block != NULL) { |
593 | vfs_cancel_lock(block->b_file->f_file, | ||
594 | &block->b_call->a_args.lock.fl); | ||
567 | status = nlmsvc_unlink_block(block); | 595 | status = nlmsvc_unlink_block(block); |
568 | nlmsvc_release_block(block); | 596 | nlmsvc_release_block(block); |
569 | } | 597 | } |
@@ -697,14 +725,15 @@ nlmsvc_grant_blocked(struct nlm_block *block) | |||
697 | 725 | ||
698 | /* Try the lock operation again */ | 726 | /* Try the lock operation again */ |
699 | lock->fl.fl_flags |= FL_SLEEP; | 727 | lock->fl.fl_flags |= FL_SLEEP; |
700 | error = posix_lock_file(file->f_file, &lock->fl, NULL); | 728 | error = vfs_lock_file(file->f_file, F_SETLK, &lock->fl, NULL); |
701 | lock->fl.fl_flags &= ~FL_SLEEP; | 729 | lock->fl.fl_flags &= ~FL_SLEEP; |
702 | 730 | ||
703 | switch (error) { | 731 | switch (error) { |
704 | case 0: | 732 | case 0: |
705 | break; | 733 | break; |
706 | case -EAGAIN: | 734 | case -EAGAIN: |
707 | dprintk("lockd: lock still blocked\n"); | 735 | case -EINPROGRESS: |
736 | dprintk("lockd: lock still blocked error %d\n", error); | ||
708 | nlmsvc_insert_block(block, NLM_NEVER); | 737 | nlmsvc_insert_block(block, NLM_NEVER); |
709 | nlmsvc_release_block(block); | 738 | nlmsvc_release_block(block); |
710 | return; | 739 | return; |
diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c index 40b5cf496b51..9cd5c8b37593 100644 --- a/fs/lockd/svcproc.c +++ b/fs/lockd/svcproc.c | |||
@@ -175,6 +175,8 @@ nlmsvc_proc_lock(struct svc_rqst *rqstp, struct nlm_args *argp, | |||
175 | /* Now try to lock the file */ | 175 | /* Now try to lock the file */ |
176 | resp->status = cast_status(nlmsvc_lock(rqstp, file, &argp->lock, | 176 | resp->status = cast_status(nlmsvc_lock(rqstp, file, &argp->lock, |
177 | argp->block, &argp->cookie)); | 177 | argp->block, &argp->cookie)); |
178 | if (resp->status == nlm_drop_reply) | ||
179 | return rpc_drop_reply; | ||
178 | 180 | ||
179 | dprintk("lockd: LOCK status %d\n", ntohl(resp->status)); | 181 | dprintk("lockd: LOCK status %d\n", ntohl(resp->status)); |
180 | nlm_release_host(host); | 182 | nlm_release_host(host); |
diff --git a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c index 50957089be1f..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, NULL) < 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; |