summaryrefslogtreecommitdiffstats
path: root/fs/lockd/svclock.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-11-23 02:00:47 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-11-23 02:00:47 +0000
commit06615f62b17d7de6e12d2f5ec6b88cf30af08413 (patch)
tree8766f208847d4876a6db619aebbf54d53b76eb44 /fs/lockd/svclock.c
parentfa9bdb574f4febb751848a685d9a9017e04e1d53 (diff)
Merge with Linux 2.4.0-test10.
Diffstat (limited to 'fs/lockd/svclock.c')
-rw-r--r--fs/lockd/svclock.c47
1 files changed, 32 insertions, 15 deletions
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
index a175d39eb..5460e8c9f 100644
--- a/fs/lockd/svclock.c
+++ b/fs/lockd/svclock.c
@@ -24,6 +24,8 @@
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/smp_lock.h>
#include <linux/sunrpc/clnt.h>
#include <linux/sunrpc/svc.h>
#include <linux/lockd/nlm.h>
@@ -40,7 +42,7 @@ static void nlmsvc_notify_blocked(struct file_lock *);
/*
* The list of blocked locks to retry
*/
-static struct nlm_block * nlm_blocked = NULL;
+static struct nlm_block * nlm_blocked;
/*
* Insert a blocked lock into the global list
@@ -53,9 +55,15 @@ nlmsvc_insert_block(struct nlm_block *block, unsigned long when)
dprintk("lockd: nlmsvc_insert_block(%p, %ld)\n", block, when);
if (block->b_queued)
nlmsvc_remove_block(block);
- for (bp = &nlm_blocked; (b = *bp); bp = &b->b_next)
- if (when < b->b_when)
- break;
+ bp = &nlm_blocked;
+ if (when != NLM_NEVER) {
+ if ((when += jiffies) == NLM_NEVER)
+ when ++;
+ while ((b = *bp) && time_before_eq(b->b_when,when))
+ bp = &b->b_next;
+ } else
+ while ((b = *bp))
+ bp = &b->b_next;
block->b_queued = 1;
block->b_when = when;
@@ -106,8 +114,10 @@ nlmsvc_lookup_block(struct nlm_file *file, struct nlm_lock *lock, int remove)
(long long)fl->fl_end, fl->fl_type,
*(unsigned int*)(block->b_call.a_args.cookie.data));
if (block->b_file == file && nlm_compare_locks(fl, &lock->fl)) {
- if (remove)
+ if (remove) {
*head = block->b_next;
+ block->b_queued = 0;
+ }
return block;
}
}
@@ -173,10 +183,11 @@ nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_file *file,
locks_init_lock(&block->b_call.a_args.lock.fl);
locks_init_lock(&block->b_call.a_res.lock.fl);
- /* Set notifier function for VFS, and init args */
- lock->fl.fl_notify = nlmsvc_notify_blocked;
if (!nlmclnt_setgrantargs(&block->b_call, lock))
goto failed_free;
+
+ /* Set notifier function for VFS, and init args */
+ block->b_call.a_args.lock.fl.fl_notify = nlmsvc_notify_blocked;
block->b_call.a_args.cookie = *cookie; /* see above */
dprintk("lockd: created block %p...\n", block);
@@ -349,7 +360,7 @@ again:
/* Append to list of blocked */
nlmsvc_insert_block(block, NLM_NEVER);
- if (list_empty(&block->b_call.a_args.lock.fl.fl_list)) {
+ if (list_empty(&block->b_call.a_args.lock.fl.fl_block)) {
/* Now add block to block list of the conflicting lock
if we haven't done so. */
dprintk("lockd: blocking on this lock.\n");
@@ -457,13 +468,15 @@ nlmsvc_notify_blocked(struct file_lock *fl)
dprintk("lockd: VFS unblock notification for block %p\n", fl);
posix_unblock_lock(fl);
+ lock_kernel();
for (bp = &nlm_blocked; (block = *bp); bp = &block->b_next) {
if (nlm_compare_locks(&block->b_call.a_args.lock.fl, fl)) {
- svc_wake_up(block->b_daemon);
nlmsvc_insert_block(block, 0);
+ svc_wake_up(block->b_daemon);
return;
}
}
+ unlock_kernel();
printk(KERN_WARNING "lockd: notification for unknown block!\n");
}
@@ -520,7 +533,7 @@ nlmsvc_grant_blocked(struct nlm_block *block)
if ((error = posix_lock_file(&file->f_file, &lock->fl, 0)) < 0) {
printk(KERN_WARNING "lockd: unexpected error %d in %s!\n",
-error, __FUNCTION__);
- nlmsvc_insert_block(block, jiffies + 10 * HZ);
+ nlmsvc_insert_block(block, 10 * HZ);
up(&file->f_sema);
return;
}
@@ -532,7 +545,7 @@ callback:
block->b_incall = 1;
/* Schedule next grant callback in 30 seconds */
- nlmsvc_insert_block(block, jiffies + 30 * HZ);
+ nlmsvc_insert_block(block, 30 * HZ);
/* Call the client */
nlm_get_host(block->b_call.a_host);
@@ -570,13 +583,13 @@ nlmsvc_grant_callback(struct rpc_task *task)
* can be done, though. */
if (task->tk_status < 0) {
/* RPC error: Re-insert for retransmission */
- timeout = jiffies + 10 * HZ;
+ timeout = 10 * HZ;
} else if (block->b_done) {
/* Block already removed, kill it for real */
timeout = 0;
} else {
/* Call was successful, now wait for client callback */
- timeout = jiffies + 60 * HZ;
+ timeout = 60 * HZ;
}
nlmsvc_insert_block(block, timeout);
svc_wake_up(block->b_daemon);
@@ -604,7 +617,7 @@ nlmsvc_grant_reply(struct nlm_cookie *cookie, u32 status)
if ((block = nlmsvc_find_block(cookie)) != NULL) {
if (status == NLM_LCK_DENIED_GRACE_PERIOD) {
/* Try again in a couple of seconds */
- nlmsvc_insert_block(block, jiffies + 10 * HZ);
+ nlmsvc_insert_block(block, 10 * HZ);
block = NULL;
} else {
/* Lock is now held by client, or has been rejected.
@@ -635,7 +648,11 @@ nlmsvc_retry_blocked(void)
dprintk("nlmsvc_retry_blocked(%p, when=%ld)\n",
nlm_blocked,
nlm_blocked? nlm_blocked->b_when : 0);
- while ((block = nlm_blocked) && block->b_when <= jiffies) {
+ while ((block = nlm_blocked)) {
+ if (block->b_when == NLM_NEVER)
+ break;
+ if (time_after(block->b_when,jiffies))
+ break;
dprintk("nlmsvc_retry_blocked(%p, when=%ld, done=%d)\n",
block, block->b_when, block->b_done);
if (block->b_done)