diff options
Diffstat (limited to 'fs/lockd/clntproc.c')
-rw-r--r-- | fs/lockd/clntproc.c | 46 |
1 files changed, 39 insertions, 7 deletions
diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c index d50df7eac..8df091923 100644 --- a/fs/lockd/clntproc.c +++ b/fs/lockd/clntproc.c @@ -30,6 +30,14 @@ static int nlm_stat_to_errno(u32 stat); */ static u32 nlm_cookie = 0x1234; +static inline void nlmclnt_next_cookie(struct nlm_cookie *c) +{ + memcpy(c->data, &nlm_cookie, 4); + memset(c->data+4, 0, 4); + c->len=4; + nlm_cookie++; +} + /* * Initialize arguments for TEST/LOCK/UNLOCK/CANCEL calls */ @@ -40,7 +48,7 @@ nlmclnt_setlockargs(struct nlm_rqst *req, struct file_lock *fl) struct nlm_lock *lock = &argp->lock; memset(argp, 0, sizeof(*argp)); - argp->cookie = nlm_cookie++; + nlmclnt_next_cookie(&argp->cookie); argp->state = nsm_local_state; lock->fh = *NFS_FH(fl->fl_file->f_dentry); lock->caller = system_utsname.nodename; @@ -57,7 +65,7 @@ nlmclnt_setlockargs(struct nlm_rqst *req, struct file_lock *fl) int nlmclnt_setgrantargs(struct nlm_rqst *call, struct nlm_lock *lock) { - call->a_args.cookie = nlm_cookie++; + nlmclnt_next_cookie(&call->a_args.cookie); call->a_args.lock = *lock; call->a_args.lock.caller = system_utsname.nodename; @@ -230,9 +238,24 @@ nlmclnt_call(struct nlm_rqst *req, u32 proc) /* Perform the RPC call. If an error occurs, try again */ if ((status = rpc_call(clnt, proc, argp, resp, 0)) < 0) { dprintk("lockd: rpc_call returned error %d\n", -status); - if (status == -ERESTARTSYS) - return status; - nlm_rebind_host(host); + switch (status) { + case -EPROTONOSUPPORT: + status = -EINVAL; + break; + case -ECONNREFUSED: + case -ETIMEDOUT: + case -ENOTCONN: + status = -EAGAIN; + break; + case -ERESTARTSYS: + return signalled () ? -EINTR : status; + default: + break; + } + if (req->a_args.block) + nlm_rebind_host(host); + else + break; } else if (resp->status == NLM_LCK_DENIED_GRACE_PERIOD) { dprintk("lockd: server in grace period\n"); @@ -248,9 +271,18 @@ nlmclnt_call(struct nlm_rqst *req, u32 proc) /* Back off a little and try again */ interruptible_sleep_on_timeout(&host->h_gracewait, 15*HZ); - } while (!signalled()); - return -ERESTARTSYS; + /* When the lock requested by F_SETLKW isn't available, + we will wait until the request can be satisfied. If + a signal is received during wait, we should return + -EINTR. */ + if (signalled ()) { + status = -EINTR; + break; + } + } while (1); + + return status; } /* |