From 36943fa4b2701b9ef2d60084c85ecbe634aec252 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Mon, 20 Mar 2006 13:44:05 -0500 Subject: NLM: nlm_alloc_call should not immediately fail on signal Currently, nlm_alloc_call tests for a signal before it even tries to allocate memory. Fix it so that it tries at least once. Signed-off-by: Trond Myklebust --- fs/lockd/clntproc.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'fs/lockd') diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c index 970b6a6aa337..615a988a92a7 100644 --- a/fs/lockd/clntproc.c +++ b/fs/lockd/clntproc.c @@ -291,14 +291,15 @@ nlmclnt_alloc_call(void) { struct nlm_rqst *call; - while (!signalled()) { - call = (struct nlm_rqst *) kmalloc(sizeof(struct nlm_rqst), GFP_KERNEL); - if (call) { - memset(call, 0, sizeof(*call)); + for(;;) { + call = kzalloc(sizeof(*call), GFP_KERNEL); + if (call != NULL) { locks_init_lock(&call->a_args.lock.fl); locks_init_lock(&call->a_res.lock.fl); return call; } + if (signalled()) + break; printk("nlmclnt_alloc_call: failed, waiting for memory\n"); schedule_timeout_interruptible(5*HZ); } -- cgit v1.2.2 From 7bab377fcb495ee2e5a1cd69d235f8d84c76e3af Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Mon, 20 Mar 2006 13:44:06 -0500 Subject: lockd: Don't expose the process pid to the NLM server Instead we use the nlm_lockowner->pid. Signed-off-by: Trond Myklebust --- fs/lockd/clntlock.c | 10 +++++++++- fs/lockd/clntproc.c | 7 +++++-- fs/lockd/svclock.c | 1 + fs/lockd/xdr.c | 13 ++++++++----- fs/lockd/xdr4.c | 17 ++++++++++------- 5 files changed, 33 insertions(+), 15 deletions(-) (limited to 'fs/lockd') diff --git a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c index da6354baa0b8..8ae79ae4b998 100644 --- a/fs/lockd/clntlock.c +++ b/fs/lockd/clntlock.c @@ -125,7 +125,15 @@ u32 nlmclnt_grant(const struct sockaddr_in *addr, const struct nlm_lock *lock) list_for_each_entry(block, &nlm_blocked, b_list) { struct file_lock *fl_blocked = block->b_lock; - if (!nlm_compare_locks(fl_blocked, fl)) + if (fl_blocked->fl_start != fl->fl_start) + continue; + if (fl_blocked->fl_end != fl->fl_end) + continue; + /* + * Careful! The NLM server will return the 32-bit "pid" that + * we put on the wire: in this case the lockowner "pid". + */ + if (fl_blocked->fl_u.nfs_fl.owner->pid != lock->svid) continue; if (!nlm_cmp_addr(&block->b_host->h_addr, addr)) continue; diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c index 615a988a92a7..acc3eb13a02b 100644 --- a/fs/lockd/clntproc.c +++ b/fs/lockd/clntproc.c @@ -132,8 +132,10 @@ static void nlmclnt_setlockargs(struct nlm_rqst *req, struct file_lock *fl) memcpy(&lock->fh, NFS_FH(fl->fl_file->f_dentry->d_inode), sizeof(struct nfs_fh)); lock->caller = system_utsname.nodename; lock->oh.data = req->a_owner; - lock->oh.len = sprintf(req->a_owner, "%d@%s", - current->pid, system_utsname.nodename); + lock->oh.len = snprintf(req->a_owner, sizeof(req->a_owner), "%u@%s", + (unsigned int)fl->fl_u.nfs_fl.owner->pid, + system_utsname.nodename); + lock->svid = fl->fl_u.nfs_fl.owner->pid; locks_copy_lock(&lock->fl, fl); } @@ -159,6 +161,7 @@ nlmclnt_setgrantargs(struct nlm_rqst *call, struct nlm_lock *lock) /* set default data area */ call->a_args.lock.oh.data = call->a_owner; + call->a_args.lock.svid = lock->fl.fl_pid; if (lock->oh.len > NLMCLNT_OHSIZE) { void *data = kmalloc(lock->oh.len, GFP_KERNEL); diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c index 9cfced65d4a2..a525a141dd3b 100644 --- a/fs/lockd/svclock.c +++ b/fs/lockd/svclock.c @@ -397,6 +397,7 @@ nlmsvc_testlock(struct nlm_file *file, struct nlm_lock *lock, (long long)fl->fl_end); conflock->caller = "somehost"; /* FIXME */ conflock->oh.len = 0; /* don't return OH info */ + conflock->svid = fl->fl_pid; conflock->fl = *fl; return nlm_lck_denied; } diff --git a/fs/lockd/xdr.c b/fs/lockd/xdr.c index 200fbda2c6d1..1e984ab14d3f 100644 --- a/fs/lockd/xdr.c +++ b/fs/lockd/xdr.c @@ -131,10 +131,11 @@ nlm_decode_lock(u32 *p, struct nlm_lock *lock) || !(p = nlm_decode_fh(p, &lock->fh)) || !(p = nlm_decode_oh(p, &lock->oh))) return NULL; + lock->svid = ntohl(*p++); locks_init_lock(fl); fl->fl_owner = current->files; - fl->fl_pid = ntohl(*p++); + fl->fl_pid = (pid_t)lock->svid; fl->fl_flags = FL_POSIX; fl->fl_type = F_RDLCK; /* as good as anything else */ start = ntohl(*p++); @@ -174,7 +175,7 @@ nlm_encode_lock(u32 *p, struct nlm_lock *lock) else len = loff_t_to_s32(fl->fl_end - fl->fl_start + 1); - *p++ = htonl(fl->fl_pid); + *p++ = htonl(lock->svid); *p++ = htonl(start); *p++ = htonl(len); @@ -197,7 +198,7 @@ nlm_encode_testres(u32 *p, struct nlm_res *resp) struct file_lock *fl = &resp->lock.fl; *p++ = (fl->fl_type == F_RDLCK)? xdr_zero : xdr_one; - *p++ = htonl(fl->fl_pid); + *p++ = htonl(resp->lock.svid); /* Encode owner handle. */ if (!(p = xdr_encode_netobj(p, &resp->lock.oh))) @@ -298,7 +299,8 @@ nlmsvc_decode_shareargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp) memset(lock, 0, sizeof(*lock)); locks_init_lock(&lock->fl); - lock->fl.fl_pid = ~(u32) 0; + lock->svid = ~(u32) 0; + lock->fl.fl_pid = (pid_t)lock->svid; if (!(p = nlm_decode_cookie(p, &argp->cookie)) || !(p = xdr_decode_string_inplace(p, &lock->caller, @@ -415,7 +417,8 @@ nlmclt_decode_testres(struct rpc_rqst *req, u32 *p, struct nlm_res *resp) memset(&resp->lock, 0, sizeof(resp->lock)); locks_init_lock(fl); excl = ntohl(*p++); - fl->fl_pid = ntohl(*p++); + resp->lock.svid = ntohl(*p++); + fl->fl_pid = (pid_t)resp->lock.svid; if (!(p = nlm_decode_oh(p, &resp->lock.oh))) return -EIO; diff --git a/fs/lockd/xdr4.c b/fs/lockd/xdr4.c index fdcf105a5303..906ddc203186 100644 --- a/fs/lockd/xdr4.c +++ b/fs/lockd/xdr4.c @@ -130,10 +130,11 @@ nlm4_decode_lock(u32 *p, struct nlm_lock *lock) || !(p = nlm4_decode_fh(p, &lock->fh)) || !(p = nlm4_decode_oh(p, &lock->oh))) return NULL; + lock->svid = ntohl(*p++); locks_init_lock(fl); fl->fl_owner = current->files; - fl->fl_pid = ntohl(*p++); + fl->fl_pid = (pid_t)lock->svid; fl->fl_flags = FL_POSIX; fl->fl_type = F_RDLCK; /* as good as anything else */ p = xdr_decode_hyper(p, &start); @@ -167,7 +168,7 @@ nlm4_encode_lock(u32 *p, struct nlm_lock *lock) || (fl->fl_end > NLM4_OFFSET_MAX && fl->fl_end != OFFSET_MAX)) return NULL; - *p++ = htonl(fl->fl_pid); + *p++ = htonl(lock->svid); start = loff_t_to_s64(fl->fl_start); if (fl->fl_end == OFFSET_MAX) @@ -198,7 +199,7 @@ nlm4_encode_testres(u32 *p, struct nlm_res *resp) struct file_lock *fl = &resp->lock.fl; *p++ = (fl->fl_type == F_RDLCK)? xdr_zero : xdr_one; - *p++ = htonl(fl->fl_pid); + *p++ = htonl(resp->lock.svid); /* Encode owner handle. */ if (!(p = xdr_encode_netobj(p, &resp->lock.oh))) @@ -212,8 +213,8 @@ nlm4_encode_testres(u32 *p, struct nlm_res *resp) p = xdr_encode_hyper(p, start); p = xdr_encode_hyper(p, len); - dprintk("xdr: encode_testres (status %d pid %d type %d start %Ld end %Ld)\n", - resp->status, fl->fl_pid, fl->fl_type, + dprintk("xdr: encode_testres (status %u pid %d type %d start %Ld end %Ld)\n", + resp->status, (int)resp->lock.svid, fl->fl_type, (long long)fl->fl_start, (long long)fl->fl_end); } @@ -303,7 +304,8 @@ nlm4svc_decode_shareargs(struct svc_rqst *rqstp, u32 *p, nlm_args *argp) memset(lock, 0, sizeof(*lock)); locks_init_lock(&lock->fl); - lock->fl.fl_pid = ~(u32) 0; + lock->svid = ~(u32) 0; + lock->fl.fl_pid = (pid_t)lock->svid; if (!(p = nlm4_decode_cookie(p, &argp->cookie)) || !(p = xdr_decode_string_inplace(p, &lock->caller, @@ -420,7 +422,8 @@ nlm4clt_decode_testres(struct rpc_rqst *req, u32 *p, struct nlm_res *resp) memset(&resp->lock, 0, sizeof(resp->lock)); locks_init_lock(fl); excl = ntohl(*p++); - fl->fl_pid = ntohl(*p++); + resp->lock.svid = ntohl(*p++); + fl->fl_pid = (pid_t)resp->lock.svid; if (!(p = nlm4_decode_oh(p, &resp->lock.oh))) return -EIO; -- cgit v1.2.2 From cc0175c1dc1de8f6af0eb0631dcc5b999a6fcc42 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Mon, 20 Mar 2006 13:44:22 -0500 Subject: SUNRPC: display human-readable procedure name in rpc_iostats output Add fields to the rpc_procinfo struct that allow the display of a human-readable name for each procedure in the rpc_iostats output. Also fix it so that the NFSv4 stats are broken up correctly by sub-procedure number. NFSv4 uses only two real RPC procedures: NULL, and COMPOUND. Test plan: Mount with NFSv2, NFSv3, and NFSv4, and do "cat /proc/self/mountstats". Signed-off-by: Chuck Lever Signed-off-by: Trond Myklebust --- fs/lockd/mon.c | 4 ++++ fs/lockd/xdr.c | 4 +++- fs/lockd/xdr4.c | 4 +++- 3 files changed, 10 insertions(+), 2 deletions(-) (limited to 'fs/lockd') diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c index 0edc03e67966..84ee39e6a3a2 100644 --- a/fs/lockd/mon.c +++ b/fs/lockd/mon.c @@ -214,12 +214,16 @@ static struct rpc_procinfo nsm_procedures[] = { .p_encode = (kxdrproc_t) xdr_encode_mon, .p_decode = (kxdrproc_t) xdr_decode_stat_res, .p_bufsiz = MAX(SM_mon_sz, SM_monres_sz) << 2, + .p_statidx = SM_MON, + .p_name = "MONITOR", }, [SM_UNMON] = { .p_proc = SM_UNMON, .p_encode = (kxdrproc_t) xdr_encode_unmon, .p_decode = (kxdrproc_t) xdr_decode_stat, .p_bufsiz = MAX(SM_mon_id_sz, SM_unmonres_sz) << 2, + .p_statidx = SM_UNMON, + .p_name = "UNMONITOR", }, }; diff --git a/fs/lockd/xdr.c b/fs/lockd/xdr.c index 1e984ab14d3f..766ce06146b5 100644 --- a/fs/lockd/xdr.c +++ b/fs/lockd/xdr.c @@ -546,7 +546,9 @@ nlmclt_decode_res(struct rpc_rqst *req, u32 *p, struct nlm_res *resp) .p_proc = NLMPROC_##proc, \ .p_encode = (kxdrproc_t) nlmclt_encode_##argtype, \ .p_decode = (kxdrproc_t) nlmclt_decode_##restype, \ - .p_bufsiz = MAX(NLM_##argtype##_sz, NLM_##restype##_sz) << 2 \ + .p_bufsiz = MAX(NLM_##argtype##_sz, NLM_##restype##_sz) << 2, \ + .p_statidx = NLMPROC_##proc, \ + .p_name = #proc, \ } static struct rpc_procinfo nlm_procedures[] = { diff --git a/fs/lockd/xdr4.c b/fs/lockd/xdr4.c index 906ddc203186..36eb175ec335 100644 --- a/fs/lockd/xdr4.c +++ b/fs/lockd/xdr4.c @@ -551,7 +551,9 @@ nlm4clt_decode_res(struct rpc_rqst *req, u32 *p, struct nlm_res *resp) .p_proc = NLMPROC_##proc, \ .p_encode = (kxdrproc_t) nlm4clt_encode_##argtype, \ .p_decode = (kxdrproc_t) nlm4clt_decode_##restype, \ - .p_bufsiz = MAX(NLM4_##argtype##_sz, NLM4_##restype##_sz) << 2 \ + .p_bufsiz = MAX(NLM4_##argtype##_sz, NLM4_##restype##_sz) << 2, \ + .p_statidx = NLMPROC_##proc, \ + .p_name = #proc, \ } static struct rpc_procinfo nlm4_procedures[] = { -- cgit v1.2.2 From dead28da8e3fb32601d38fb32b7021122e0a3d21 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Mon, 20 Mar 2006 13:44:23 -0500 Subject: SUNRPC: eliminate rpc_call() Clean-up: replace rpc_call() helper with direct call to rpc_call_sync. This makes NFSv2 and NFSv3 synchronous calls more computationally efficient, and reduces stack consumption in functions that used to invoke rpc_call more than once. Test plan: Compile kernel with CONFIG_NFS enabled. Connectathon on NFS version 2, version 3, and version 4 mount points. Signed-off-by: Chuck Lever Signed-off-by: Trond Myklebust --- fs/lockd/mon.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'fs/lockd') diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c index 84ee39e6a3a2..5dd52b70859a 100644 --- a/fs/lockd/mon.c +++ b/fs/lockd/mon.c @@ -35,6 +35,10 @@ nsm_mon_unmon(struct nlm_host *host, u32 proc, struct nsm_res *res) struct rpc_clnt *clnt; int status; struct nsm_args args; + struct rpc_message msg = { + .rpc_argp = &args, + .rpc_resp = res, + }; clnt = nsm_create(); if (IS_ERR(clnt)) { @@ -49,7 +53,8 @@ nsm_mon_unmon(struct nlm_host *host, u32 proc, struct nsm_res *res) args.proc = NLMPROC_NSM_NOTIFY; memset(res, 0, sizeof(*res)); - status = rpc_call(clnt, proc, &args, res, 0); + msg.rpc_proc = &clnt->cl_procinfo[proc]; + status = rpc_call_sync(clnt, &msg, 0); if (status < 0) printk(KERN_DEBUG "nsm_mon_unmon: rpc failed, status=%d\n", status); -- cgit v1.2.2 From 15dadef9460ad8d3b1d5ede1c1697dc79af44a72 Mon Sep 17 00:00:00 2001 From: Andy Adamson Date: Mon, 20 Mar 2006 13:44:24 -0500 Subject: lockd: clean up nlmsvc_lock Slightly more consistent dprintk error reporting, consolidate some up()'s. Signed-off-by: Andy Adamson Signed-off-by: J. Bruce Fields Signed-off-by: Trond Myklebust --- fs/lockd/svclock.c | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) (limited to 'fs/lockd') diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c index a525a141dd3b..42dd105456c5 100644 --- a/fs/lockd/svclock.c +++ b/fs/lockd/svclock.c @@ -300,6 +300,7 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file, struct file_lock *conflock; struct nlm_block *block; int error; + u32 ret; dprintk("lockd: nlmsvc_lock(%s/%ld, ty=%d, pi=%d, %Ld-%Ld, bl=%d)\n", file->f_file->f_dentry->d_inode->i_sb->s_id, @@ -329,24 +330,28 @@ again: dprintk("lockd: posix_lock_file returned %d\n", -error); switch(-error) { case 0: - return nlm_granted; + ret = nlm_granted; + goto out; case EDEADLK: - return nlm_deadlock; + ret = nlm_deadlock; + goto out; case EAGAIN: - return nlm_lck_denied; + ret = nlm_lck_denied; + goto out; default: /* includes ENOLCK */ - return nlm_lck_denied_nolocks; + ret = nlm_lck_denied_nolocks; + goto out; } } if (!wait) { - up(&file->f_sema); - return nlm_lck_denied; + ret = nlm_lck_denied; + goto out_unlock; } if (posix_locks_deadlock(&lock->fl, conflock)) { - up(&file->f_sema); - return nlm_deadlock; + ret = nlm_deadlock; + goto out_unlock; } /* If we don't have a block, create and initialize it. Then @@ -371,8 +376,12 @@ again: posix_block_lock(conflock, &block->b_call.a_args.lock.fl); } + ret = nlm_lck_blocked; +out_unlock: up(&file->f_sema); - return nlm_lck_blocked; +out: + dprintk("lockd: nlmsvc_lock returned %u\n", ret); + return ret; } /* @@ -535,8 +544,7 @@ nlmsvc_grant_blocked(struct nlm_block *block) dprintk("lockd: lock still blocked\n"); nlmsvc_insert_block(block, NLM_NEVER); posix_block_lock(conflock, &lock->fl); - up(&file->f_sema); - return; + goto out_unlock; } /* Alright, no conflicting lock. Now lock it for real. If the @@ -547,8 +555,7 @@ nlmsvc_grant_blocked(struct nlm_block *block) printk(KERN_WARNING "lockd: unexpected error %d in %s!\n", -error, __FUNCTION__); nlmsvc_insert_block(block, 10 * HZ); - up(&file->f_sema); - return; + goto out_unlock; } callback: @@ -565,6 +572,7 @@ callback: if (nlmsvc_async_call(&block->b_call, NLMPROC_GRANTED_MSG, &nlmsvc_grant_ops) < 0) nlm_release_host(block->b_call.a_host); +out_unlock: up(&file->f_sema); } -- cgit v1.2.2 From 5de0e5024a4e21251fd80dbfdb83316ce97086bc Mon Sep 17 00:00:00 2001 From: Andy Adamson Date: Mon, 20 Mar 2006 13:44:25 -0500 Subject: lockd: simplify nlmsvc_grant_blocked Reorganize nlmsvc_grant_blocked() to make full use of posix_lock_file(). Note that there's no need for separate calls to posix_test_lock(), posix_locks_deadlock(), or posix_block_lock(). Signed-off-by: Andy Adamson Signed-off-by: J. Bruce Fields Signed-off-by: Trond Myklebust --- fs/lockd/svclock.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) (limited to 'fs/lockd') diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c index 42dd105456c5..58bbfede94ec 100644 --- a/fs/lockd/svclock.c +++ b/fs/lockd/svclock.c @@ -519,7 +519,6 @@ nlmsvc_grant_blocked(struct nlm_block *block) { struct nlm_file *file = block->b_file; struct nlm_lock *lock = &block->b_call.a_args.lock; - struct file_lock *conflock; int error; dprintk("lockd: grant blocked lock %p\n", block); @@ -539,19 +538,15 @@ nlmsvc_grant_blocked(struct nlm_block *block) } /* Try the lock operation again */ - if ((conflock = posix_test_lock(file->f_file, &lock->fl)) != NULL) { - /* Bummer, we blocked again */ + error = posix_lock_file(file->f_file, &lock->fl); + switch (error) { + case 0: + break; + case -EAGAIN: dprintk("lockd: lock still blocked\n"); nlmsvc_insert_block(block, NLM_NEVER); - posix_block_lock(conflock, &lock->fl); goto out_unlock; - } - - /* Alright, no conflicting lock. Now lock it for real. If the - * following yields an error, this is most probably due to low - * memory. Retry the lock in a few seconds. - */ - if ((error = posix_lock_file(file->f_file, &lock->fl)) < 0) { + default: printk(KERN_WARNING "lockd: unexpected error %d in %s!\n", -error, __FUNCTION__); nlmsvc_insert_block(block, 10 * HZ); -- cgit v1.2.2 From a85f193e2fb7d53e48ae6a9d9ea990bfb4cea555 Mon Sep 17 00:00:00 2001 From: Andy Adamson Date: Mon, 20 Mar 2006 13:44:25 -0500 Subject: lockd: make nlmsvc_lock use only posix_lock_file Reorganize nlmsvc_lock() to make full use of posix_lock_file(), which does eveything nlmsvc_lock() needs - no need to call posix_test_lock(), posix_locks_deadlock(), or posix_block_lock() separately. Signed-off-by: Andy Adamson Signed-off-by: J. Bruce Fields Signed-off-by: Trond Myklebust --- fs/lockd/svclock.c | 23 ++++------------------- 1 file changed, 4 insertions(+), 19 deletions(-) (limited to 'fs/lockd') diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c index 58bbfede94ec..f5398097b84b 100644 --- a/fs/lockd/svclock.c +++ b/fs/lockd/svclock.c @@ -297,7 +297,6 @@ u32 nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file, struct nlm_lock *lock, int wait, struct nlm_cookie *cookie) { - struct file_lock *conflock; struct nlm_block *block; int error; u32 ret; @@ -320,14 +319,15 @@ again: /* Lock file against concurrent access */ down(&file->f_sema); - if (!(conflock = posix_test_lock(file->f_file, &lock->fl))) { - error = posix_lock_file(file->f_file, &lock->fl); + error = posix_lock_file(file->f_file, &lock->fl); + + dprintk("lockd: posix_lock_file returned %d\n", error); + if (error != -EAGAIN) { if (block) nlmsvc_delete_block(block, 0); up(&file->f_sema); - dprintk("lockd: posix_lock_file returned %d\n", -error); switch(-error) { case 0: ret = nlm_granted; @@ -335,9 +335,6 @@ again: case EDEADLK: ret = nlm_deadlock; goto out; - case EAGAIN: - ret = nlm_lck_denied; - goto out; default: /* includes ENOLCK */ ret = nlm_lck_denied_nolocks; goto out; @@ -349,11 +346,6 @@ again: goto out_unlock; } - if (posix_locks_deadlock(&lock->fl, conflock)) { - ret = nlm_deadlock; - goto out_unlock; - } - /* If we don't have a block, create and initialize it. Then * retry because we may have slept in kmalloc. */ /* We have to release f_sema as nlmsvc_create_block may try to @@ -369,13 +361,6 @@ again: /* Append to list of blocked */ nlmsvc_insert_block(block, NLM_NEVER); - 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"); - posix_block_lock(conflock, &block->b_call.a_args.lock.fl); - } - ret = nlm_lck_blocked; out_unlock: up(&file->f_sema); -- cgit v1.2.2 From 8dc7c3115b611c00006eac3ee5b108296432aab7 Mon Sep 17 00:00:00 2001 From: Andy Adamson Date: Mon, 20 Mar 2006 13:44:26 -0500 Subject: locks,lockd: fix race in nlmsvc_testlock posix_test_lock() returns a pointer to a struct file_lock which is unprotected and can be removed while in use by the caller. Move the conflicting lock from the return to a parameter, and copy the conflicting lock. In most cases the caller ends up putting the copy of the conflicting lock on the stack. On i386, sizeof(struct file_lock) appears to be about 100 bytes. We're assuming that's reasonable. Signed-off-by: Andy Adamson Signed-off-by: J. Bruce Fields Signed-off-by: Trond Myklebust --- fs/lockd/svclock.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'fs/lockd') diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c index f5398097b84b..d683dd022e08 100644 --- a/fs/lockd/svclock.c +++ b/fs/lockd/svclock.c @@ -376,8 +376,6 @@ u32 nlmsvc_testlock(struct nlm_file *file, struct nlm_lock *lock, struct nlm_lock *conflock) { - struct file_lock *fl; - dprintk("lockd: nlmsvc_testlock(%s/%ld, ty=%d, %Ld-%Ld)\n", file->f_file->f_dentry->d_inode->i_sb->s_id, file->f_file->f_dentry->d_inode->i_ino, @@ -385,14 +383,14 @@ nlmsvc_testlock(struct nlm_file *file, struct nlm_lock *lock, (long long)lock->fl.fl_start, (long long)lock->fl.fl_end); - if ((fl = posix_test_lock(file->f_file, &lock->fl)) != NULL) { + if (posix_test_lock(file->f_file, &lock->fl, &conflock->fl)) { dprintk("lockd: conflicting lock(ty=%d, %Ld-%Ld)\n", - fl->fl_type, (long long)fl->fl_start, - (long long)fl->fl_end); + conflock->fl.fl_type, + (long long)conflock->fl.fl_start, + (long long)conflock->fl.fl_end); conflock->caller = "somehost"; /* FIXME */ conflock->oh.len = 0; /* don't return OH info */ - conflock->svid = fl->fl_pid; - conflock->fl = *fl; + conflock->svid = conflock->fl.fl_pid; return nlm_lck_denied; } -- cgit v1.2.2 From 7117bf3dfb10b534a017260d9fc643bc1d0afd2a Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Mon, 20 Mar 2006 13:44:26 -0500 Subject: lockd: Remove FL_LOCKD flag Currently lockd identifies its own locks using the FL_LOCKD flag. This doesn't scale well to multiple lock managers--if we did this in nfsv4 too, for example, we'd be left with only one free flag bit. Instead, we just check whether the file manager ops (fl_lmops) set on this lock are our own. The only use for this is in nlm_traverse_locks, which uses it to find locks that need cleaning up when freeing a host or a file. In the long run it might be nice to do reference counting instead of traversing all the locks like this.... Signed-off-by: J. Bruce Fields Signed-off-by: Trond Myklebust --- fs/lockd/svclock.c | 2 -- fs/lockd/svcsubs.c | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) (limited to 'fs/lockd') diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c index d683dd022e08..d50946dcddd9 100644 --- a/fs/lockd/svclock.c +++ b/fs/lockd/svclock.c @@ -313,8 +313,6 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file, /* Get existing block (in case client is busy-waiting) */ block = nlmsvc_lookup_block(file, lock, 0); - lock->fl.fl_flags |= FL_LOCKD; - again: /* Lock file against concurrent access */ down(&file->f_sema); diff --git a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c index 62f4a385177f..601e5b3dfe20 100644 --- a/fs/lockd/svcsubs.c +++ b/fs/lockd/svcsubs.c @@ -182,7 +182,7 @@ nlm_traverse_locks(struct nlm_host *host, struct nlm_file *file, int action) again: file->f_locks = 0; for (fl = inode->i_flock; fl; fl = fl->fl_next) { - if (!(fl->fl_flags & FL_LOCKD)) + if (fl->fl_lmops != &nlmsvc_lock_operations) continue; /* update current lock count */ -- cgit v1.2.2 From 09c7938c5640a6f22bef074ca6b803dccfdb93e3 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Mon, 20 Mar 2006 13:44:38 -0500 Subject: lockd: Fix server-side lock blocking code Signed-off-by: Trond Myklebust --- fs/lockd/svclock.c | 73 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 40 insertions(+), 33 deletions(-) (limited to 'fs/lockd') diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c index d50946dcddd9..1d3a74df93f3 100644 --- a/fs/lockd/svclock.c +++ b/fs/lockd/svclock.c @@ -193,6 +193,7 @@ nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_file *file, goto failed_free; /* Set notifier function for VFS, and init args */ + block->b_call.a_args.lock.fl.fl_flags |= FL_SLEEP; block->b_call.a_args.lock.fl.fl_lmops = &nlmsvc_lock_operations; block->b_call.a_args.cookie = *cookie; /* see above */ @@ -228,19 +229,18 @@ failed: * can be closed hereafter. */ static int -nlmsvc_delete_block(struct nlm_block *block, int unlock) +nlmsvc_delete_block(struct nlm_block *block) { struct file_lock *fl = &block->b_call.a_args.lock.fl; struct nlm_file *file = block->b_file; struct nlm_block **bp; - int status = 0; + int status; dprintk("lockd: deleting block %p...\n", block); /* Remove block from list */ nlmsvc_remove_block(block); - if (unlock) - status = posix_unblock_lock(file->f_file, fl); + status = posix_unblock_lock(file->f_file, fl); /* If the block is in the middle of a GRANT callback, * don't kill it yet. */ @@ -282,7 +282,7 @@ nlmsvc_traverse_blocks(struct nlm_host *host, struct nlm_file *file, int action) block->b_host->h_inuse = 1; else if (action == NLM_ACT_UNLOCK) { if (host == NULL || host == block->b_host) - nlmsvc_delete_block(block, 1); + nlmsvc_delete_block(block); } } up(&file->f_sema); @@ -297,7 +297,7 @@ u32 nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file, struct nlm_lock *lock, int wait, struct nlm_cookie *cookie) { - struct nlm_block *block; + struct nlm_block *block, *newblock = NULL; int error; u32 ret; @@ -310,59 +310,65 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file, wait); - /* Get existing block (in case client is busy-waiting) */ - block = nlmsvc_lookup_block(file, lock, 0); - + lock->fl.fl_flags &= ~FL_SLEEP; again: /* Lock file against concurrent access */ down(&file->f_sema); + /* Get existing block (in case client is busy-waiting) */ + block = nlmsvc_lookup_block(file, lock, 0); + if (block == NULL) { + if (newblock != NULL) + lock = &newblock->b_call.a_args.lock.fl; + } else + lock = &block->b_call.a_args.lock.fl; error = posix_lock_file(file->f_file, &lock->fl); + lock->fl.fl_flags &= ~FL_SLEEP; dprintk("lockd: posix_lock_file returned %d\n", error); - if (error != -EAGAIN) { - if (block) - nlmsvc_delete_block(block, 0); - up(&file->f_sema); - - switch(-error) { + switch(error) { case 0: ret = nlm_granted; goto out; - case EDEADLK: + case -EAGAIN: + break; + case -EDEADLK: ret = nlm_deadlock; goto out; default: /* includes ENOLCK */ ret = nlm_lck_denied_nolocks; goto out; - } } - if (!wait) { - ret = nlm_lck_denied; - goto out_unlock; - } + ret = nlm_lck_denied; + if (!wait) + goto out; + + ret = nlm_lck_blocked; + if (block != NULL) + goto out; /* If we don't have a block, create and initialize it. Then * retry because we may have slept in kmalloc. */ /* We have to release f_sema as nlmsvc_create_block may try to * to claim it while doing host garbage collection */ - if (block == NULL) { + if (newblock == NULL) { up(&file->f_sema); dprintk("lockd: blocking on this lock (allocating).\n"); - if (!(block = nlmsvc_create_block(rqstp, file, lock, cookie))) + if (!(newblock = nlmsvc_create_block(rqstp, file, lock, cookie))) return nlm_lck_denied_nolocks; goto again; } /* Append to list of blocked */ - nlmsvc_insert_block(block, NLM_NEVER); + nlmsvc_insert_block(newblock, NLM_NEVER); + newblock = NULL; - ret = nlm_lck_blocked; -out_unlock: - up(&file->f_sema); out: + up(&file->f_sema); + if (newblock != NULL) + nlmsvc_delete_block(newblock); dprintk("lockd: nlmsvc_lock returned %u\n", ret); return ret; } @@ -445,7 +451,7 @@ nlmsvc_cancel_blocked(struct nlm_file *file, struct nlm_lock *lock) down(&file->f_sema); if ((block = nlmsvc_lookup_block(file, lock, 1)) != NULL) - status = nlmsvc_delete_block(block, 1); + status = nlmsvc_delete_block(block); up(&file->f_sema); return status ? nlm_lck_denied : nlm_granted; } @@ -519,7 +525,11 @@ nlmsvc_grant_blocked(struct nlm_block *block) } /* Try the lock operation again */ + posix_unblock_lock(file->f_file, &lock->fl); + lock->fl.fl_flags |= FL_SLEEP; error = posix_lock_file(file->f_file, &lock->fl); + lock->fl.fl_flags &= ~FL_SLEEP; + switch (error) { case 0: break; @@ -630,11 +640,8 @@ nlmsvc_grant_reply(struct svc_rqst *rqstp, struct nlm_cookie *cookie, u32 status } else { /* Lock is now held by client, or has been rejected. * In both cases, the block should be removed. */ + nlmsvc_delete_block(block); up(&file->f_sema); - if (status == NLM_LCK_GRANTED) - nlmsvc_delete_block(block, 0); - else - nlmsvc_delete_block(block, 1); } } nlm_release_file(file); @@ -661,7 +668,7 @@ nlmsvc_retry_blocked(void) dprintk("nlmsvc_retry_blocked(%p, when=%ld, done=%d)\n", block, block->b_when, block->b_done); if (block->b_done) - nlmsvc_delete_block(block, 0); + nlmsvc_delete_block(block); else nlmsvc_grant_blocked(block); } -- cgit v1.2.2 From 6849c0cab69f5d1a0fc7b05fa5bfb3dec53f86df Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Mon, 20 Mar 2006 13:44:39 -0500 Subject: lockd: Add refcounting to struct nlm_block Otherwise, the block may disappear from underneath us when in nlmsvc_retry_blocked. Signed-off-by: Trond Myklebust --- fs/lockd/svclock.c | 94 ++++++++++++++++++++++++++---------------------------- 1 file changed, 45 insertions(+), 49 deletions(-) (limited to 'fs/lockd') diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c index 1d3a74df93f3..20caeceffb14 100644 --- a/fs/lockd/svclock.c +++ b/fs/lockd/svclock.c @@ -39,6 +39,7 @@ #define nlm_deadlock nlm_lck_denied #endif +static void nlmsvc_release_block(struct nlm_block *block); static void nlmsvc_insert_block(struct nlm_block *block, unsigned long); static int nlmsvc_remove_block(struct nlm_block *block); @@ -58,6 +59,7 @@ nlmsvc_insert_block(struct nlm_block *block, unsigned long when) struct nlm_block **bp, *b; dprintk("lockd: nlmsvc_insert_block(%p, %ld)\n", block, when); + kref_get(&block->b_count); if (block->b_queued) nlmsvc_remove_block(block); bp = &nlm_blocked; @@ -90,6 +92,7 @@ nlmsvc_remove_block(struct nlm_block *block) if (b == block) { *bp = block->b_next; block->b_queued = 0; + nlmsvc_release_block(block); return 1; } } @@ -123,6 +126,7 @@ nlmsvc_lookup_block(struct nlm_file *file, struct nlm_lock *lock, int remove) *head = block->b_next; block->b_queued = 0; } + kref_get(&block->b_count); return block; } } @@ -155,6 +159,8 @@ nlmsvc_find_block(struct nlm_cookie *cookie, struct sockaddr_in *sin) break; } + if (block != NULL) + kref_get(&block->b_count); return block; } @@ -188,6 +194,7 @@ nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_file *file, memset(block, 0, sizeof(*block)); locks_init_lock(&block->b_call.a_args.lock.fl); locks_init_lock(&block->b_call.a_res.lock.fl); + kref_init(&block->b_count); if (!nlmclnt_setgrantargs(&block->b_call, lock)) goto failed_free; @@ -228,27 +235,24 @@ failed: * It is the caller's responsibility to check whether the file * can be closed hereafter. */ -static int -nlmsvc_delete_block(struct nlm_block *block) +static int nlmsvc_unlink_block(struct nlm_block *block) { - struct file_lock *fl = &block->b_call.a_args.lock.fl; - struct nlm_file *file = block->b_file; - struct nlm_block **bp; int status; - - dprintk("lockd: deleting block %p...\n", block); + dprintk("lockd: unlinking block %p...\n", block); /* Remove block from list */ + status = posix_unblock_lock(block->b_file->f_file, &block->b_call.a_args.lock.fl); nlmsvc_remove_block(block); - status = posix_unblock_lock(file->f_file, fl); + return status; +} - /* If the block is in the middle of a GRANT callback, - * don't kill it yet. */ - if (block->b_incall) { - nlmsvc_insert_block(block, NLM_NEVER); - block->b_done = 1; - return status; - } +static void nlmsvc_free_block(struct kref *kref) +{ + struct nlm_block *block = container_of(kref, struct nlm_block, b_count); + struct nlm_file *file = block->b_file; + struct nlm_block **bp; + + dprintk("lockd: freeing block %p...\n", block); /* Remove block from file's list of blocks */ for (bp = &file->f_blocks; *bp; bp = &(*bp)->b_fnext) { @@ -262,7 +266,12 @@ nlmsvc_delete_block(struct nlm_block *block) nlm_release_host(block->b_host); nlmclnt_freegrantargs(&block->b_call); kfree(block); - return status; +} + +static void nlmsvc_release_block(struct nlm_block *block) +{ + if (block != NULL) + kref_put(&block->b_count, nlmsvc_free_block); } /* @@ -282,7 +291,7 @@ nlmsvc_traverse_blocks(struct nlm_host *host, struct nlm_file *file, int action) block->b_host->h_inuse = 1; else if (action == NLM_ACT_UNLOCK) { if (host == NULL || host == block->b_host) - nlmsvc_delete_block(block); + nlmsvc_unlink_block(block); } } up(&file->f_sema); @@ -318,9 +327,9 @@ again: block = nlmsvc_lookup_block(file, lock, 0); if (block == NULL) { if (newblock != NULL) - lock = &newblock->b_call.a_args.lock.fl; + lock = &newblock->b_call.a_args.lock; } else - lock = &block->b_call.a_args.lock.fl; + lock = &block->b_call.a_args.lock; error = posix_lock_file(file->f_file, &lock->fl); lock->fl.fl_flags &= ~FL_SLEEP; @@ -363,12 +372,10 @@ again: /* Append to list of blocked */ nlmsvc_insert_block(newblock, NLM_NEVER); - newblock = NULL; - out: up(&file->f_sema); - if (newblock != NULL) - nlmsvc_delete_block(newblock); + nlmsvc_release_block(newblock); + nlmsvc_release_block(block); dprintk("lockd: nlmsvc_lock returned %u\n", ret); return ret; } @@ -450,8 +457,10 @@ nlmsvc_cancel_blocked(struct nlm_file *file, struct nlm_lock *lock) (long long)lock->fl.fl_end); down(&file->f_sema); - if ((block = nlmsvc_lookup_block(file, lock, 1)) != NULL) - status = nlmsvc_delete_block(block); + if ((block = nlmsvc_lookup_block(file, lock, 1)) != NULL) { + status = nlmsvc_unlink_block(block); + nlmsvc_release_block(block); + } up(&file->f_sema); return status ? nlm_lck_denied : nlm_granted; } @@ -514,7 +523,7 @@ nlmsvc_grant_blocked(struct nlm_block *block) down(&file->f_sema); /* Unlink block request from list */ - nlmsvc_remove_block(block); + nlmsvc_unlink_block(block); /* If b_granted is true this means we've been here before. * Just retry the grant callback, possibly refreshing the RPC @@ -525,7 +534,6 @@ nlmsvc_grant_blocked(struct nlm_block *block) } /* Try the lock operation again */ - posix_unblock_lock(file->f_file, &lock->fl); lock->fl.fl_flags |= FL_SLEEP; error = posix_lock_file(file->f_file, &lock->fl); lock->fl.fl_flags &= ~FL_SLEEP; @@ -548,16 +556,15 @@ callback: /* Lock was granted by VFS. */ dprintk("lockd: GRANTing blocked lock.\n"); block->b_granted = 1; - block->b_incall = 1; /* Schedule next grant callback in 30 seconds */ nlmsvc_insert_block(block, 30 * HZ); /* Call the client */ - nlm_get_host(block->b_call.a_host); + kref_get(&block->b_count); if (nlmsvc_async_call(&block->b_call, NLMPROC_GRANTED_MSG, &nlmsvc_grant_ops) < 0) - nlm_release_host(block->b_call.a_host); + nlmsvc_release_block(block); out_unlock: up(&file->f_sema); } @@ -573,20 +580,10 @@ out_unlock: static void nlmsvc_grant_callback(struct rpc_task *task, void *data) { struct nlm_rqst *call = data; - struct nlm_block *block; + struct nlm_block *block = container_of(call, struct nlm_block, b_call); unsigned long timeout; - struct sockaddr_in *peer_addr = RPC_PEERADDR(task->tk_client); dprintk("lockd: GRANT_MSG RPC callback\n"); - dprintk("callback: looking for cookie %s, host (%u.%u.%u.%u)\n", - nlmdbg_cookie2a(&call->a_args.cookie), - NIPQUAD(peer_addr->sin_addr.s_addr)); - if (!(block = nlmsvc_find_block(&call->a_args.cookie, peer_addr))) { - dprintk("lockd: no block for cookie %s, host (%u.%u.%u.%u)\n", - nlmdbg_cookie2a(&call->a_args.cookie), - NIPQUAD(peer_addr->sin_addr.s_addr)); - return; - } /* Technically, we should down the file semaphore here. Since we * move the block towards the head of the queue only, no harm @@ -603,9 +600,7 @@ static void nlmsvc_grant_callback(struct rpc_task *task, void *data) } nlmsvc_insert_block(block, timeout); svc_wake_up(block->b_daemon); - block->b_incall = 0; - - nlm_release_host(call->a_host); + nlmsvc_release_block(block); } static const struct rpc_call_ops nlmsvc_grant_ops = { @@ -631,20 +626,19 @@ nlmsvc_grant_reply(struct svc_rqst *rqstp, struct nlm_cookie *cookie, u32 status file->f_count++; down(&file->f_sema); - block = nlmsvc_find_block(cookie, &rqstp->rq_addr); if (block) { if (status == NLM_LCK_DENIED_GRACE_PERIOD) { /* Try again in a couple of seconds */ nlmsvc_insert_block(block, 10 * HZ); - up(&file->f_sema); } else { /* Lock is now held by client, or has been rejected. * In both cases, the block should be removed. */ - nlmsvc_delete_block(block); - up(&file->f_sema); + nlmsvc_unlink_block(block); } } + up(&file->f_sema); nlm_release_file(file); + nlmsvc_release_block(block); } /* @@ -667,10 +661,12 @@ nlmsvc_retry_blocked(void) break; dprintk("nlmsvc_retry_blocked(%p, when=%ld, done=%d)\n", block, block->b_when, block->b_done); + kref_get(&block->b_count); if (block->b_done) - nlmsvc_delete_block(block); + nlmsvc_unlink_block(block); else nlmsvc_grant_blocked(block); + nlmsvc_release_block(block); } if ((block = nlm_blocked) && block->b_when != NLM_NEVER) -- cgit v1.2.2 From 5e1abf8cb713a0b94f5a400c7b9b797990cd9dec Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Mon, 20 Mar 2006 13:44:39 -0500 Subject: lockd: Clean up of the server-side GRANTED code Signed-off-by: Trond Myklebust --- fs/lockd/clntproc.c | 43 ---------------------------------------- fs/lockd/svclock.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 53 insertions(+), 46 deletions(-) (limited to 'fs/lockd') diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c index acc3eb13a02b..80ae3127699f 100644 --- a/fs/lockd/clntproc.c +++ b/fs/lockd/clntproc.c @@ -147,49 +147,6 @@ static void nlmclnt_release_lockargs(struct nlm_rqst *req) fl->fl_ops->fl_release_private(fl); } -/* - * Initialize arguments for GRANTED call. The nlm_rqst structure - * has been cleared already. - */ -int -nlmclnt_setgrantargs(struct nlm_rqst *call, struct nlm_lock *lock) -{ - locks_copy_lock(&call->a_args.lock.fl, &lock->fl); - memcpy(&call->a_args.lock.fh, &lock->fh, sizeof(call->a_args.lock.fh)); - call->a_args.lock.caller = system_utsname.nodename; - call->a_args.lock.oh.len = lock->oh.len; - - /* set default data area */ - call->a_args.lock.oh.data = call->a_owner; - call->a_args.lock.svid = lock->fl.fl_pid; - - if (lock->oh.len > NLMCLNT_OHSIZE) { - void *data = kmalloc(lock->oh.len, GFP_KERNEL); - if (!data) { - nlmclnt_freegrantargs(call); - return 0; - } - call->a_args.lock.oh.data = (u8 *) data; - } - - memcpy(call->a_args.lock.oh.data, lock->oh.data, lock->oh.len); - return 1; -} - -void -nlmclnt_freegrantargs(struct nlm_rqst *call) -{ - struct file_lock *fl = &call->a_args.lock.fl; - /* - * Check whether we allocated memory for the owner. - */ - if (call->a_args.lock.oh.data != (u8 *) call->a_owner) { - kfree(call->a_args.lock.oh.data); - } - if (fl->fl_ops && fl->fl_ops->fl_release_private) - fl->fl_ops->fl_release_private(fl); -} - /* * This is the main entry point for the NLM client. */ diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c index 20caeceffb14..3c7dd956d9c1 100644 --- a/fs/lockd/svclock.c +++ b/fs/lockd/svclock.c @@ -43,6 +43,8 @@ static void nlmsvc_release_block(struct nlm_block *block); static void nlmsvc_insert_block(struct nlm_block *block, unsigned long); static int nlmsvc_remove_block(struct nlm_block *block); +static int nlmsvc_setgrantargs(struct nlm_rqst *call, struct nlm_lock *lock); +static void nlmsvc_freegrantargs(struct nlm_rqst *call); static const struct rpc_call_ops nlmsvc_grant_ops; /* @@ -196,7 +198,7 @@ nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_file *file, locks_init_lock(&block->b_call.a_res.lock.fl); kref_init(&block->b_count); - if (!nlmclnt_setgrantargs(&block->b_call, lock)) + if (!nlmsvc_setgrantargs(&block->b_call, lock)) goto failed_free; /* Set notifier function for VFS, and init args */ @@ -264,7 +266,7 @@ static void nlmsvc_free_block(struct kref *kref) if (block->b_host) nlm_release_host(block->b_host); - nlmclnt_freegrantargs(&block->b_call); + nlmsvc_freegrantargs(&block->b_call); kfree(block); } @@ -298,6 +300,49 @@ nlmsvc_traverse_blocks(struct nlm_host *host, struct nlm_file *file, int action) return 0; } +/* + * Initialize arguments for GRANTED call. The nlm_rqst structure + * has been cleared already. + */ +static int nlmsvc_setgrantargs(struct nlm_rqst *call, struct nlm_lock *lock) +{ + locks_copy_lock(&call->a_args.lock.fl, &lock->fl); + memcpy(&call->a_args.lock.fh, &lock->fh, sizeof(call->a_args.lock.fh)); + call->a_args.lock.caller = system_utsname.nodename; + call->a_args.lock.oh.len = lock->oh.len; + + /* set default data area */ + call->a_args.lock.oh.data = call->a_owner; + call->a_args.lock.svid = lock->fl.fl_pid; + + if (lock->oh.len > NLMCLNT_OHSIZE) { + void *data = kmalloc(lock->oh.len, GFP_KERNEL); + if (!data) { + nlmsvc_freegrantargs(call); + return 0; + } + call->a_args.lock.oh.data = (u8 *) data; + } + + memcpy(call->a_args.lock.oh.data, lock->oh.data, lock->oh.len); + return 1; +} + +static void nlmsvc_freegrantargs(struct nlm_rqst *call) +{ + struct file_lock *fl = &call->a_args.lock.fl; + /* + * Check whether we allocated memory for the owner. + */ + if (call->a_args.lock.oh.data != (u8 *) call->a_owner) { + kfree(call->a_args.lock.oh.data); + } + if (fl->fl_ops && fl->fl_ops->fl_release_private) + fl->fl_ops->fl_release_private(fl); + if (fl->fl_lmops && fl->fl_lmops->fl_release_private) + fl->fl_lmops->fl_release_private(fl); +} + /* * Attempt to establish a lock, and if it can't be granted, block it * if required. @@ -600,11 +645,16 @@ static void nlmsvc_grant_callback(struct rpc_task *task, void *data) } nlmsvc_insert_block(block, timeout); svc_wake_up(block->b_daemon); - nlmsvc_release_block(block); +} + +void nlmsvc_grant_release(void *data) +{ + nlmsvc_release_block(data); } static const struct rpc_call_ops nlmsvc_grant_ops = { .rpc_call_done = nlmsvc_grant_callback, + .rpc_release = nlmsvc_grant_release, }; /* -- cgit v1.2.2 From 686517f1ad1630c11964d668b556aab79b8c942e Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Mon, 20 Mar 2006 13:44:39 -0500 Subject: lockd: Make nlmsvc_create_block() use nlmsvc_lookup_host() Currently it uses nlmclnt_lookup_host(), which puts the resulting host structure on a different list. Signed-off-by: Trond Myklebust --- fs/lockd/svc4proc.c | 3 +-- fs/lockd/svclock.c | 3 +-- fs/lockd/svcproc.c | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) (limited to 'fs/lockd') diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c index b10f913aa06a..ac4a700af01a 100644 --- a/fs/lockd/svc4proc.c +++ b/fs/lockd/svc4proc.c @@ -483,8 +483,7 @@ nlm4svc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_res *resp) if (!(call = nlmclnt_alloc_call())) return rpc_system_err; - host = nlmclnt_lookup_host(&rqstp->rq_addr, - rqstp->rq_prot, rqstp->rq_vers); + host = nlmsvc_lookup_host(rqstp); if (!host) { kfree(call); return rpc_system_err; diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c index 3c7dd956d9c1..a95d260b7137 100644 --- a/fs/lockd/svclock.c +++ b/fs/lockd/svclock.c @@ -185,8 +185,7 @@ nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_file *file, struct nlm_rqst *call; /* Create host handle for callback */ - host = nlmclnt_lookup_host(&rqstp->rq_addr, - rqstp->rq_prot, rqstp->rq_vers); + host = nlmsvc_lookup_host(rqstp); if (host == NULL) return NULL; diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c index 35681d9cf1fc..4986fbe44540 100644 --- a/fs/lockd/svcproc.c +++ b/fs/lockd/svcproc.c @@ -508,8 +508,7 @@ nlmsvc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_res *resp) if (!(call = nlmclnt_alloc_call())) return rpc_system_err; - host = nlmclnt_lookup_host(&rqstp->rq_addr, - rqstp->rq_prot, rqstp->rq_vers); + host = nlmsvc_lookup_host(rqstp); if (!host) { kfree(call); return rpc_system_err; -- cgit v1.2.2 From 04266473ecf5cdca242201d9f1ed890afe070fb6 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Mon, 20 Mar 2006 13:44:40 -0500 Subject: lockd: Make lockd use rpc_new_client() instead of rpc_create_client When doing NLM_GRANTED requests, lockd may end up blocking if we use rpc_create_client() due to the synchronous call to rpc_ping(). Instead, use rpc_new_client(). Signed-off-by: Trond Myklebust --- fs/lockd/host.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'fs/lockd') diff --git a/fs/lockd/host.c b/fs/lockd/host.c index 82f7a0b1d8ae..100e78229700 100644 --- a/fs/lockd/host.c +++ b/fs/lockd/host.c @@ -191,11 +191,12 @@ nlm_bind_host(struct nlm_host *host) xprt->resvport = 1; /* NLM requires a reserved port */ /* Existing NLM servers accept AUTH_UNIX only */ - clnt = rpc_create_client(xprt, host->h_name, &nlm_program, + clnt = rpc_new_client(xprt, host->h_name, &nlm_program, host->h_version, RPC_AUTH_UNIX); if (IS_ERR(clnt)) goto forgetit; clnt->cl_autobind = 1; /* turn on pmap queries */ + clnt->cl_softrtry = 1; /* All queries are soft */ host->h_rpcclnt = clnt; } -- cgit v1.2.2 From 26bcbf965f857c710adafd16cf424f043006b5dd Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 20 Mar 2006 13:44:40 -0500 Subject: lockd: stop abusing file_lock_list Currently lockd directly access the file_lock_list from fs/locks.c. It does so to mark locks granted or reclaimable. This is very suboptimal, because a) lockd needs to poke into locks.c internals, and b) it needs to iterate over all locks in the system for marking locks granted or reclaimable. This patch adds lists for granted and reclaimable locks to the nlm_host structure instead, and adds locks to those. nlmclnt_lock: now adds the lock to h_granted instead of setting the NFS_LCK_GRANTED, still O(1) nlmclnt_mark_reclaim: goes away completely, replaced by a list_splice_init. Complexity reduced from O(locks in the system) to O(1) reclaimer: iterates over h_reclaim now, complexity reduced from O(locks in the system) to O(locks per nlm_host) Signed-off-by: Christoph Hellwig Signed-off-by: Trond Myklebust --- fs/lockd/clntlock.c | 54 +++++++++-------------------------------------------- fs/lockd/clntproc.c | 11 ++++++----- fs/lockd/host.c | 2 ++ 3 files changed, 17 insertions(+), 50 deletions(-) (limited to 'fs/lockd') diff --git a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c index 8ae79ae4b998..0fc0ee267b04 100644 --- a/fs/lockd/clntlock.c +++ b/fs/lockd/clntlock.c @@ -154,34 +154,6 @@ u32 nlmclnt_grant(const struct sockaddr_in *addr, const struct nlm_lock *lock) * server crash. */ -/* - * Mark the locks for reclaiming. - * FIXME: In 2.5 we don't want to iterate through any global file_lock_list. - * Maintain NLM lock reclaiming lists in the nlm_host instead. - */ -static -void nlmclnt_mark_reclaim(struct nlm_host *host) -{ - struct file_lock *fl; - struct inode *inode; - struct list_head *tmp; - - list_for_each(tmp, &file_lock_list) { - fl = list_entry(tmp, struct file_lock, fl_link); - - inode = fl->fl_file->f_dentry->d_inode; - if (inode->i_sb->s_magic != NFS_SUPER_MAGIC) - continue; - if (fl->fl_u.nfs_fl.owner == NULL) - continue; - if (fl->fl_u.nfs_fl.owner->host != host) - continue; - if (!(fl->fl_u.nfs_fl.flags & NFS_LCK_GRANTED)) - continue; - fl->fl_u.nfs_fl.flags |= NFS_LCK_RECLAIM; - } -} - /* * Someone has sent us an SM_NOTIFY. Ensure we bind to the new port number, * that we mark locks for reclaiming, and that we bump the pseudo NSM state. @@ -194,7 +166,12 @@ void nlmclnt_prepare_reclaim(struct nlm_host *host, u32 newstate) host->h_state++; host->h_nextrebind = 0; nlm_rebind_host(host); - nlmclnt_mark_reclaim(host); + + /* + * Mark the locks for reclaiming. + */ + list_splice_init(&host->h_granted, &host->h_reclaim); + dprintk("NLM: reclaiming locks for host %s", host->h_name); } @@ -223,9 +200,7 @@ reclaimer(void *ptr) { struct nlm_host *host = (struct nlm_host *) ptr; struct nlm_wait *block; - struct list_head *tmp; - struct file_lock *fl; - struct inode *inode; + struct file_lock *fl, *next; daemonize("%s-reclaim", host->h_name); allow_signal(SIGKILL); @@ -237,20 +212,9 @@ reclaimer(void *ptr) /* First, reclaim all locks that have been marked. */ restart: - list_for_each(tmp, &file_lock_list) { - fl = list_entry(tmp, struct file_lock, fl_link); - - inode = fl->fl_file->f_dentry->d_inode; - if (inode->i_sb->s_magic != NFS_SUPER_MAGIC) - continue; - if (fl->fl_u.nfs_fl.owner == NULL) - continue; - if (fl->fl_u.nfs_fl.owner->host != host) - continue; - if (!(fl->fl_u.nfs_fl.flags & NFS_LCK_RECLAIM)) - continue; + list_for_each_entry_safe(fl, next, &host->h_reclaim, fl_u.nfs_fl.list) { + list_del(&fl->fl_u.nfs_fl.list); - fl->fl_u.nfs_fl.flags &= ~NFS_LCK_RECLAIM; nlmclnt_reclaim(host, fl); if (signalled()) break; diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c index 80ae3127699f..cb469431bd1d 100644 --- a/fs/lockd/clntproc.c +++ b/fs/lockd/clntproc.c @@ -465,7 +465,6 @@ static void nlmclnt_locks_init_private(struct file_lock *fl, struct nlm_host *ho { BUG_ON(fl->fl_ops != NULL); fl->fl_u.nfs_fl.state = 0; - fl->fl_u.nfs_fl.flags = 0; fl->fl_u.nfs_fl.owner = nlm_find_lockowner(host, fl->fl_owner); fl->fl_ops = &nlmclnt_lock_ops; } @@ -552,8 +551,8 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl) if (resp->status == NLM_LCK_GRANTED) { fl->fl_u.nfs_fl.state = host->h_state; - fl->fl_u.nfs_fl.flags |= NFS_LCK_GRANTED; fl->fl_flags |= FL_SLEEP; + list_add_tail(&fl->fl_u.nfs_fl.list, &host->h_granted); do_vfs_lock(fl); } status = nlm_stat_to_errno(resp->status); @@ -619,9 +618,11 @@ nlmclnt_unlock(struct nlm_rqst *req, struct file_lock *fl) struct nlm_res *resp = &req->a_res; int status; - /* Clean the GRANTED flag now so the lock doesn't get - * reclaimed while we're stuck in the unlock call. */ - fl->fl_u.nfs_fl.flags &= ~NFS_LCK_GRANTED; + /* + * Remove from the granted list now so the lock doesn't get + * reclaimed while we're stuck in the unlock call. + */ + list_del(&fl->fl_u.nfs_fl.list); /* * Note: the server is supposed to either grant us the unlock diff --git a/fs/lockd/host.c b/fs/lockd/host.c index 100e78229700..f456f8ed9acd 100644 --- a/fs/lockd/host.c +++ b/fs/lockd/host.c @@ -123,6 +123,8 @@ nlm_lookup_host(int server, struct sockaddr_in *sin, nlm_hosts[hash] = host; INIT_LIST_HEAD(&host->h_lockowners); spin_lock_init(&host->h_lock); + INIT_LIST_HEAD(&host->h_granted); + INIT_LIST_HEAD(&host->h_reclaim); if (++nrhosts > NLM_HOST_MAX) next_gc = 0; -- cgit v1.2.2 From 4c060b531006e0711db32a132d6ac7661594b280 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Mon, 20 Mar 2006 13:44:41 -0500 Subject: lockd: Fix Oopses due to list manipulation errors. The patch "stop abusing file_lock_list introduces a couple of bugs since the locks may be copied and need to be removed from the lists when they are destroyed. Signed-off-by: Trond Myklebust --- fs/lockd/clntlock.c | 7 ++++--- fs/lockd/clntproc.c | 15 ++++++--------- fs/lockd/host.c | 7 +++++-- 3 files changed, 15 insertions(+), 14 deletions(-) (limited to 'fs/lockd') diff --git a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c index 0fc0ee267b04..7cf41c1e1a88 100644 --- a/fs/lockd/clntlock.c +++ b/fs/lockd/clntlock.c @@ -213,11 +213,12 @@ reclaimer(void *ptr) /* First, reclaim all locks that have been marked. */ restart: list_for_each_entry_safe(fl, next, &host->h_reclaim, fl_u.nfs_fl.list) { - list_del(&fl->fl_u.nfs_fl.list); + list_del_init(&fl->fl_u.nfs_fl.list); - nlmclnt_reclaim(host, fl); if (signalled()) - break; + continue; + if (nlmclnt_reclaim(host, fl) == 0) + list_add_tail(&fl->fl_u.nfs_fl.list, &host->h_granted); goto restart; } diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c index cb469431bd1d..3e90356b4882 100644 --- a/fs/lockd/clntproc.c +++ b/fs/lockd/clntproc.c @@ -446,12 +446,14 @@ nlmclnt_test(struct nlm_rqst *req, struct file_lock *fl) static void nlmclnt_locks_copy_lock(struct file_lock *new, struct file_lock *fl) { - memcpy(&new->fl_u.nfs_fl, &fl->fl_u.nfs_fl, sizeof(new->fl_u.nfs_fl)); - nlm_get_lockowner(new->fl_u.nfs_fl.owner); + new->fl_u.nfs_fl.state = fl->fl_u.nfs_fl.state; + new->fl_u.nfs_fl.owner = nlm_get_lockowner(fl->fl_u.nfs_fl.owner); + list_add_tail(&new->fl_u.nfs_fl.list, &fl->fl_u.nfs_fl.owner->host->h_granted); } static void nlmclnt_locks_release_private(struct file_lock *fl) { + list_del(&fl->fl_u.nfs_fl.list); nlm_put_lockowner(fl->fl_u.nfs_fl.owner); fl->fl_ops = NULL; } @@ -466,6 +468,7 @@ static void nlmclnt_locks_init_private(struct file_lock *fl, struct nlm_host *ho BUG_ON(fl->fl_ops != NULL); fl->fl_u.nfs_fl.state = 0; fl->fl_u.nfs_fl.owner = nlm_find_lockowner(host, fl->fl_owner); + INIT_LIST_HEAD(&fl->fl_u.nfs_fl.list); fl->fl_ops = &nlmclnt_lock_ops; } @@ -552,7 +555,7 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl) if (resp->status == NLM_LCK_GRANTED) { fl->fl_u.nfs_fl.state = host->h_state; fl->fl_flags |= FL_SLEEP; - list_add_tail(&fl->fl_u.nfs_fl.list, &host->h_granted); + /* Ensure the resulting lock will get added to granted list */ do_vfs_lock(fl); } status = nlm_stat_to_errno(resp->status); @@ -618,12 +621,6 @@ nlmclnt_unlock(struct nlm_rqst *req, struct file_lock *fl) struct nlm_res *resp = &req->a_res; int status; - /* - * Remove from the granted list now so the lock doesn't get - * reclaimed while we're stuck in the unlock call. - */ - list_del(&fl->fl_u.nfs_fl.list); - /* * Note: the server is supposed to either grant us the unlock * request, or to deny it with NLM_LCK_DENIED_GRACE_PERIOD. In either diff --git a/fs/lockd/host.c b/fs/lockd/host.c index f456f8ed9acd..112ebf8b8dfe 100644 --- a/fs/lockd/host.c +++ b/fs/lockd/host.c @@ -245,8 +245,12 @@ void nlm_release_host(struct nlm_host *host) { if (host != NULL) { dprintk("lockd: release host %s\n", host->h_name); - atomic_dec(&host->h_count); BUG_ON(atomic_read(&host->h_count) < 0); + if (atomic_dec_and_test(&host->h_count)) { + BUG_ON(!list_empty(&host->h_lockowners)); + BUG_ON(!list_empty(&host->h_granted)); + BUG_ON(!list_empty(&host->h_reclaim)); + } } } @@ -334,7 +338,6 @@ nlm_gc_hosts(void) rpc_destroy_client(host->h_rpcclnt); } } - BUG_ON(!list_empty(&host->h_lockowners)); kfree(host); nrhosts--; } -- cgit v1.2.2 From 35576cba57f1c042b87d6586b3229d13067264c6 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Mon, 20 Mar 2006 13:44:41 -0500 Subject: NLM: nlmclnt_cancel_callback should accept NLM_LCK_DENIED errors NLM_LCK_DENIED is a valid error return for an NLM_CANCEL call by the client. Signed-off-by: Trond Myklebust --- fs/lockd/clntproc.c | 1 + 1 file changed, 1 insertion(+) (limited to 'fs/lockd') diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c index 3e90356b4882..c25044f3b660 100644 --- a/fs/lockd/clntproc.c +++ b/fs/lockd/clntproc.c @@ -750,6 +750,7 @@ static void nlmclnt_cancel_callback(struct rpc_task *task, void *data) switch (req->a_res.status) { case NLM_LCK_GRANTED: case NLM_LCK_DENIED_GRACE_PERIOD: + case NLM_LCK_DENIED: /* Everything's good */ break; case NLM_LCK_DENIED_NOLOCKS: -- cgit v1.2.2 From 3a649b884637c4fdff50a6beebc3dc0e6082e048 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Mon, 20 Mar 2006 13:44:44 -0500 Subject: NLM: Simplify client locks Signed-off-by: Trond Myklebust --- fs/lockd/clntlock.c | 43 ++++++++++++++++--------------------------- fs/lockd/clntproc.c | 39 ++++++++++++++++----------------------- 2 files changed, 32 insertions(+), 50 deletions(-) (limited to 'fs/lockd') diff --git a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c index 7cf41c1e1a88..bce744468708 100644 --- a/fs/lockd/clntlock.c +++ b/fs/lockd/clntlock.c @@ -44,32 +44,25 @@ static LIST_HEAD(nlm_blocked); /* * Queue up a lock for blocking so that the GRANTED request can see it */ -int nlmclnt_prepare_block(struct nlm_rqst *req, struct nlm_host *host, struct file_lock *fl) +struct nlm_wait *nlmclnt_prepare_block(struct nlm_host *host, struct file_lock *fl) { struct nlm_wait *block; - BUG_ON(req->a_block != NULL); block = kmalloc(sizeof(*block), GFP_KERNEL); - if (block == NULL) - return -ENOMEM; - block->b_host = host; - block->b_lock = fl; - init_waitqueue_head(&block->b_wait); - block->b_status = NLM_LCK_BLOCKED; - - list_add(&block->b_list, &nlm_blocked); - req->a_block = block; - - return 0; + if (block != NULL) { + block->b_host = host; + block->b_lock = fl; + init_waitqueue_head(&block->b_wait); + block->b_status = NLM_LCK_BLOCKED; + list_add(&block->b_list, &nlm_blocked); + } + return block; } -void nlmclnt_finish_block(struct nlm_rqst *req) +void nlmclnt_finish_block(struct nlm_wait *block) { - struct nlm_wait *block = req->a_block; - if (block == NULL) return; - req->a_block = NULL; list_del(&block->b_list); kfree(block); } @@ -77,15 +70,14 @@ void nlmclnt_finish_block(struct nlm_rqst *req) /* * Block on a lock */ -long nlmclnt_block(struct nlm_rqst *req, long timeout) +int nlmclnt_block(struct nlm_wait *block, struct nlm_rqst *req, long timeout) { - struct nlm_wait *block = req->a_block; long ret; /* A borken server might ask us to block even if we didn't * request it. Just say no! */ - if (!req->a_args.block) + if (block == NULL) return -EAGAIN; /* Go to sleep waiting for GRANT callback. Some servers seem @@ -99,13 +91,10 @@ long nlmclnt_block(struct nlm_rqst *req, long timeout) ret = wait_event_interruptible_timeout(block->b_wait, block->b_status != NLM_LCK_BLOCKED, timeout); - - if (block->b_status != NLM_LCK_BLOCKED) { - req->a_res.status = block->b_status; - block->b_status = NLM_LCK_BLOCKED; - } - - return ret; + if (ret < 0) + return -ERESTARTSYS; + req->a_res.status = block->b_status; + return 0; } /* diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c index c25044f3b660..8af017105854 100644 --- a/fs/lockd/clntproc.c +++ b/fs/lockd/clntproc.c @@ -136,15 +136,14 @@ static void nlmclnt_setlockargs(struct nlm_rqst *req, struct file_lock *fl) (unsigned int)fl->fl_u.nfs_fl.owner->pid, system_utsname.nodename); lock->svid = fl->fl_u.nfs_fl.owner->pid; - locks_copy_lock(&lock->fl, fl); + lock->fl.fl_start = fl->fl_start; + lock->fl.fl_end = fl->fl_end; + lock->fl.fl_type = fl->fl_type; } static void nlmclnt_release_lockargs(struct nlm_rqst *req) { - struct file_lock *fl = &req->a_args.lock.fl; - - if (fl->fl_ops && fl->fl_ops->fl_release_private) - fl->fl_ops->fl_release_private(fl); + BUG_ON(req->a_args.lock.fl.fl_ops != NULL); } /* @@ -455,7 +454,6 @@ static void nlmclnt_locks_release_private(struct file_lock *fl) { list_del(&fl->fl_u.nfs_fl.list); nlm_put_lockowner(fl->fl_u.nfs_fl.owner); - fl->fl_ops = NULL; } static struct file_lock_operations nlmclnt_lock_ops = { @@ -515,41 +513,36 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl) { struct nlm_host *host = req->a_host; struct nlm_res *resp = &req->a_res; - long timeout; - int status; + struct nlm_wait *block = NULL; + int status = -ENOLCK; if (!host->h_monitored && nsm_monitor(host) < 0) { printk(KERN_NOTICE "lockd: failed to monitor %s\n", host->h_name); - status = -ENOLCK; goto out; } - if (req->a_args.block) { - status = nlmclnt_prepare_block(req, host, fl); - if (status < 0) - goto out; - } + block = nlmclnt_prepare_block(host, fl); for(;;) { status = nlmclnt_call(req, NLMPROC_LOCK); if (status < 0) goto out_unblock; - if (resp->status != NLM_LCK_BLOCKED) + if (!req->a_args.block) break; - /* Wait on an NLM blocking lock */ - timeout = nlmclnt_block(req, NLMCLNT_POLL_TIMEOUT); /* Did a reclaimer thread notify us of a server reboot? */ if (resp->status == NLM_LCK_DENIED_GRACE_PERIOD) continue; if (resp->status != NLM_LCK_BLOCKED) break; - if (timeout >= 0) - continue; - /* We were interrupted. Send a CANCEL request to the server + /* Wait on an NLM blocking lock */ + status = nlmclnt_block(block, req, NLMCLNT_POLL_TIMEOUT); + /* if we were interrupted. Send a CANCEL request to the server * and exit */ - status = (int)timeout; - goto out_unblock; + if (status < 0) + goto out_unblock; + if (resp->status != NLM_LCK_BLOCKED) + break; } if (resp->status == NLM_LCK_GRANTED) { @@ -560,7 +553,7 @@ nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl) } status = nlm_stat_to_errno(resp->status); out_unblock: - nlmclnt_finish_block(req); + nlmclnt_finish_block(block); /* Cancel the blocked request if it is still pending */ if (resp->status == NLM_LCK_BLOCKED) nlmclnt_cancel(host, req->a_args.block, fl); -- cgit v1.2.2 From e4cd038a45a46ffbe06a1a72f3f15246e5b041ca Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Mon, 20 Mar 2006 13:44:44 -0500 Subject: NLM: Fix nlmclnt_test to not copy private part of locks The struct file_lock does not carry a properly initialised lock, so don't copy it as if it were. Signed-off-by: Trond Myklebust --- fs/lockd/clntproc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'fs/lockd') diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c index 8af017105854..7a239864b8bf 100644 --- a/fs/lockd/clntproc.c +++ b/fs/lockd/clntproc.c @@ -434,7 +434,9 @@ nlmclnt_test(struct nlm_rqst *req, struct file_lock *fl) /* * Report the conflicting lock back to the application. */ - locks_copy_lock(fl, &req->a_res.lock.fl); + fl->fl_start = req->a_res.lock.fl.fl_start; + fl->fl_end = req->a_res.lock.fl.fl_start; + fl->fl_type = req->a_res.lock.fl.fl_type; fl->fl_pid = 0; } else { return nlm_stat_to_errno(req->a_res.status); -- cgit v1.2.2 From 92737230dd3f1478033819d4bc20339f8da852da Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Mon, 20 Mar 2006 13:44:45 -0500 Subject: NLM: Add nlmclnt_release_call Add a helper function to simplify the freeing of NLM client requests. Signed-off-by: Trond Myklebust --- fs/lockd/clntproc.c | 195 ++++++++++++++++++++-------------------------------- fs/lockd/svc4proc.c | 34 ++++----- fs/lockd/svclock.c | 66 ++++++++---------- fs/lockd/svcproc.c | 33 ++++----- 4 files changed, 129 insertions(+), 199 deletions(-) (limited to 'fs/lockd') diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c index 7a239864b8bf..3f8ad7c54efa 100644 --- a/fs/lockd/clntproc.c +++ b/fs/lockd/clntproc.c @@ -152,9 +152,8 @@ static void nlmclnt_release_lockargs(struct nlm_rqst *req) int nlmclnt_proc(struct inode *inode, int cmd, struct file_lock *fl) { - struct nfs_server *nfssrv = NFS_SERVER(inode); struct nlm_host *host; - struct nlm_rqst reqst, *call = &reqst; + struct nlm_rqst *call; sigset_t oldset; unsigned long flags; int status, proto, vers; @@ -168,23 +167,17 @@ nlmclnt_proc(struct inode *inode, int cmd, struct file_lock *fl) /* Retrieve transport protocol from NFS client */ proto = NFS_CLIENT(inode)->cl_xprt->prot; - if (!(host = nlmclnt_lookup_host(NFS_ADDR(inode), proto, vers))) + host = nlmclnt_lookup_host(NFS_ADDR(inode), proto, vers); + if (host == NULL) return -ENOLCK; - /* Create RPC client handle if not there, and copy soft - * and intr flags from NFS client. */ - if (host->h_rpcclnt == NULL) { - struct rpc_clnt *clnt; + call = nlm_alloc_call(host); + if (call == NULL) + return -ENOMEM; - /* Bind an rpc client to this host handle (does not - * perform a portmapper lookup) */ - if (!(clnt = nlm_bind_host(host))) { - status = -ENOLCK; - goto done; - } - clnt->cl_softrtry = nfssrv->client->cl_softrtry; - clnt->cl_intr = nfssrv->client->cl_intr; - } + nlmclnt_locks_init_private(fl, host); + /* Set up the argument struct */ + nlmclnt_setlockargs(call, fl); /* Keep the old signal mask */ spin_lock_irqsave(¤t->sighand->siglock, flags); @@ -197,26 +190,10 @@ nlmclnt_proc(struct inode *inode, int cmd, struct file_lock *fl) && (current->flags & PF_EXITING)) { sigfillset(¤t->blocked); /* Mask all signals */ recalc_sigpending(); - spin_unlock_irqrestore(¤t->sighand->siglock, flags); - call = nlmclnt_alloc_call(); - if (!call) { - status = -ENOMEM; - goto out_restore; - } call->a_flags = RPC_TASK_ASYNC; - } else { - spin_unlock_irqrestore(¤t->sighand->siglock, flags); - memset(call, 0, sizeof(*call)); - locks_init_lock(&call->a_args.lock.fl); - locks_init_lock(&call->a_res.lock.fl); } - call->a_host = host; - - nlmclnt_locks_init_private(fl, host); - - /* Set up the argument struct */ - nlmclnt_setlockargs(call, fl); + spin_unlock_irqrestore(¤t->sighand->siglock, flags); if (IS_SETLK(cmd) || IS_SETLKW(cmd)) { if (fl->fl_type != F_UNLCK) { @@ -229,24 +206,26 @@ nlmclnt_proc(struct inode *inode, int cmd, struct file_lock *fl) else status = -EINVAL; - out_restore: + fl->fl_ops->fl_release_private(fl); + fl->fl_ops = NULL; + spin_lock_irqsave(¤t->sighand->siglock, flags); current->blocked = oldset; recalc_sigpending(); spin_unlock_irqrestore(¤t->sighand->siglock, flags); -done: dprintk("lockd: clnt proc returns %d\n", status); - nlm_release_host(host); return status; } EXPORT_SYMBOL(nlmclnt_proc); /* * Allocate an NLM RPC call struct + * + * Note: the caller must hold a reference to host. In case of failure, + * this reference will be released. */ -struct nlm_rqst * -nlmclnt_alloc_call(void) +struct nlm_rqst *nlm_alloc_call(struct nlm_host *host) { struct nlm_rqst *call; @@ -255,16 +234,30 @@ nlmclnt_alloc_call(void) if (call != NULL) { locks_init_lock(&call->a_args.lock.fl); locks_init_lock(&call->a_res.lock.fl); + call->a_host = host; return call; } if (signalled()) break; - printk("nlmclnt_alloc_call: failed, waiting for memory\n"); + printk("nlm_alloc_call: failed, waiting for memory\n"); schedule_timeout_interruptible(5*HZ); } + nlm_release_host(host); return NULL; } +void nlm_release_call(struct nlm_rqst *call) +{ + nlm_release_host(call->a_host); + nlmclnt_release_lockargs(call); + kfree(call); +} + +static void nlmclnt_rpc_release(void *data) +{ + return nlm_release_call(data); +} + static int nlm_wait_on_grace(wait_queue_head_t *queue) { DEFINE_WAIT(wait); @@ -361,7 +354,7 @@ in_grace_period: /* * Generic NLM call, async version. */ -int nlmsvc_async_call(struct nlm_rqst *req, u32 proc, const struct rpc_call_ops *tk_ops) +int nlm_async_call(struct nlm_rqst *req, u32 proc, const struct rpc_call_ops *tk_ops) { struct nlm_host *host = req->a_host; struct rpc_clnt *clnt; @@ -369,48 +362,23 @@ int nlmsvc_async_call(struct nlm_rqst *req, u32 proc, const struct rpc_call_ops .rpc_argp = &req->a_args, .rpc_resp = &req->a_res, }; - int status; - - dprintk("lockd: call procedure %d on %s (async)\n", - (int)proc, host->h_name); - - /* If we have no RPC client yet, create one. */ - if ((clnt = nlm_bind_host(host)) == NULL) - return -ENOLCK; - msg.rpc_proc = &clnt->cl_procinfo[proc]; - - /* bootstrap and kick off the async RPC call */ - status = rpc_call_async(clnt, &msg, RPC_TASK_ASYNC, tk_ops, req); - - return status; -} - -static int nlmclnt_async_call(struct nlm_rqst *req, u32 proc, const struct rpc_call_ops *tk_ops) -{ - struct nlm_host *host = req->a_host; - struct rpc_clnt *clnt; - struct nlm_args *argp = &req->a_args; - struct nlm_res *resp = &req->a_res; - struct rpc_message msg = { - .rpc_argp = argp, - .rpc_resp = resp, - }; - int status; + int status = -ENOLCK; dprintk("lockd: call procedure %d on %s (async)\n", (int)proc, host->h_name); /* If we have no RPC client yet, create one. */ - if ((clnt = nlm_bind_host(host)) == NULL) - return -ENOLCK; + clnt = nlm_bind_host(host); + if (clnt == NULL) + goto out_err; msg.rpc_proc = &clnt->cl_procinfo[proc]; - /* Increment host refcount */ - nlm_get_host(host); /* bootstrap and kick off the async RPC call */ status = rpc_call_async(clnt, &msg, RPC_TASK_ASYNC, tk_ops, req); - if (status < 0) - nlm_release_host(host); + if (status == 0) + return 0; +out_err: + nlm_release_call(req); return status; } @@ -423,26 +391,28 @@ nlmclnt_test(struct nlm_rqst *req, struct file_lock *fl) int status; status = nlmclnt_call(req, NLMPROC_TEST); - nlmclnt_release_lockargs(req); if (status < 0) - return status; + goto out; - status = req->a_res.status; - if (status == NLM_LCK_GRANTED) { - fl->fl_type = F_UNLCK; - } if (status == NLM_LCK_DENIED) { - /* - * Report the conflicting lock back to the application. - */ - fl->fl_start = req->a_res.lock.fl.fl_start; - fl->fl_end = req->a_res.lock.fl.fl_start; - fl->fl_type = req->a_res.lock.fl.fl_type; - fl->fl_pid = 0; - } else { - return nlm_stat_to_errno(req->a_res.status); + switch (req->a_res.status) { + case NLM_LCK_GRANTED: + fl->fl_type = F_UNLCK; + break; + case NLM_LCK_DENIED: + /* + * Report the conflicting lock back to the application. + */ + fl->fl_start = req->a_res.lock.fl.fl_start; + fl->fl_end = req->a_res.lock.fl.fl_start; + fl->fl_type = req->a_res.lock.fl.fl_type; + fl->fl_pid = 0; + break; + default: + status = nlm_stat_to_errno(req->a_res.status); } - - return 0; +out: + nlm_release_call(req); + return status; } static void nlmclnt_locks_copy_lock(struct file_lock *new, struct file_lock *fl) @@ -560,7 +530,7 @@ out_unblock: if (resp->status == NLM_LCK_BLOCKED) nlmclnt_cancel(host, req->a_args.block, fl); out: - nlmclnt_release_lockargs(req); + nlm_release_call(req); return status; } @@ -623,32 +593,24 @@ nlmclnt_unlock(struct nlm_rqst *req, struct file_lock *fl) */ do_vfs_lock(fl); - if (req->a_flags & RPC_TASK_ASYNC) { - status = nlmclnt_async_call(req, NLMPROC_UNLOCK, - &nlmclnt_unlock_ops); - /* Hrmf... Do the unlock early since locks_remove_posix() - * really expects us to free the lock synchronously */ - if (status < 0) { - nlmclnt_release_lockargs(req); - kfree(req); - } - return status; - } + if (req->a_flags & RPC_TASK_ASYNC) + return nlm_async_call(req, NLMPROC_UNLOCK, &nlmclnt_unlock_ops); status = nlmclnt_call(req, NLMPROC_UNLOCK); - nlmclnt_release_lockargs(req); if (status < 0) - return status; + goto out; + status = 0; if (resp->status == NLM_LCK_GRANTED) - return 0; + goto out; if (resp->status != NLM_LCK_DENIED_NOLOCKS) printk("lockd: unexpected unlock status: %d\n", resp->status); - /* What to do now? I'm out of my depth... */ - - return -ENOLCK; + status = -ENOLCK; +out: + nlm_release_call(req); + return status; } static void nlmclnt_unlock_callback(struct rpc_task *task, void *data) @@ -670,9 +632,6 @@ static void nlmclnt_unlock_callback(struct rpc_task *task, void *data) if (status != NLM_LCK_GRANTED) printk(KERN_WARNING "lockd: unexpected unlock status: %d\n", status); die: - nlm_release_host(req->a_host); - nlmclnt_release_lockargs(req); - kfree(req); return; retry_rebind: nlm_rebind_host(req->a_host); @@ -682,6 +641,7 @@ die: static const struct rpc_call_ops nlmclnt_unlock_ops = { .rpc_call_done = nlmclnt_unlock_callback, + .rpc_release = nlmclnt_rpc_release, }; /* @@ -703,20 +663,15 @@ static int nlmclnt_cancel(struct nlm_host *host, int block, struct file_lock *fl recalc_sigpending(); spin_unlock_irqrestore(¤t->sighand->siglock, flags); - req = nlmclnt_alloc_call(); + req = nlm_alloc_call(nlm_get_host(host)); if (!req) return -ENOMEM; - req->a_host = host; req->a_flags = RPC_TASK_ASYNC; nlmclnt_setlockargs(req, fl); req->a_args.block = block; - status = nlmclnt_async_call(req, NLMPROC_CANCEL, &nlmclnt_cancel_ops); - if (status < 0) { - nlmclnt_release_lockargs(req); - kfree(req); - } + status = nlm_async_call(req, NLMPROC_CANCEL, &nlmclnt_cancel_ops); spin_lock_irqsave(¤t->sighand->siglock, flags); current->blocked = oldset; @@ -757,9 +712,6 @@ static void nlmclnt_cancel_callback(struct rpc_task *task, void *data) } die: - nlm_release_host(req->a_host); - nlmclnt_release_lockargs(req); - kfree(req); return; retry_cancel: @@ -773,6 +725,7 @@ retry_cancel: static const struct rpc_call_ops nlmclnt_cancel_ops = { .rpc_call_done = nlmclnt_cancel_callback, + .rpc_release = nlmclnt_rpc_release, }; /* diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c index ac4a700af01a..cb51c7025825 100644 --- a/fs/lockd/svc4proc.c +++ b/fs/lockd/svc4proc.c @@ -480,43 +480,37 @@ nlm4svc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_res *resp) struct nlm_host *host; struct nlm_rqst *call; - if (!(call = nlmclnt_alloc_call())) + host = nlmsvc_lookup_host(rqstp); + if (host == NULL) return rpc_system_err; - host = nlmsvc_lookup_host(rqstp); - if (!host) { - kfree(call); + call = nlm_alloc_call(host); + if (call == NULL) return rpc_system_err; - } + call->a_flags = RPC_TASK_ASYNC; - call->a_host = host; memcpy(&call->a_args, resp, sizeof(*resp)); - if (nlmsvc_async_call(call, proc, &nlm4svc_callback_ops) < 0) - goto error; - + if (nlm_async_call(call, proc, &nlm4svc_callback_ops) < 0) + return rpc_system_err; return rpc_success; - error: - kfree(call); - nlm_release_host(host); - return rpc_system_err; } static void nlm4svc_callback_exit(struct rpc_task *task, void *data) { - struct nlm_rqst *call = data; + dprintk("lockd: %4d callback returned %d\n", task->tk_pid, + -task->tk_status); +} - if (task->tk_status < 0) { - dprintk("lockd: %4d callback failed (errno = %d)\n", - task->tk_pid, -task->tk_status); - } - nlm_release_host(call->a_host); - kfree(call); +static void nlm4svc_callback_release(void *data) +{ + nlm_release_call(data); } static const struct rpc_call_ops nlm4svc_callback_ops = { .rpc_call_done = nlm4svc_callback_exit, + .rpc_release = nlm4svc_callback_release, }; /* diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c index a95d260b7137..185bf7ea1c0c 100644 --- a/fs/lockd/svclock.c +++ b/fs/lockd/svclock.c @@ -117,12 +117,12 @@ nlmsvc_lookup_block(struct nlm_file *file, struct nlm_lock *lock, int remove) (long long)lock->fl.fl_start, (long long)lock->fl.fl_end, lock->fl.fl_type); for (head = &nlm_blocked; (block = *head) != 0; head = &block->b_next) { - fl = &block->b_call.a_args.lock.fl; + fl = &block->b_call->a_args.lock.fl; dprintk("lockd: check f=%p pd=%d %Ld-%Ld ty=%d cookie=%s\n", block->b_file, fl->fl_pid, (long long)fl->fl_start, (long long)fl->fl_end, fl->fl_type, - nlmdbg_cookie2a(&block->b_call.a_args.cookie)); + nlmdbg_cookie2a(&block->b_call->a_args.cookie)); if (block->b_file == file && nlm_compare_locks(fl, &lock->fl)) { if (remove) { *head = block->b_next; @@ -156,7 +156,7 @@ nlmsvc_find_block(struct nlm_cookie *cookie, struct sockaddr_in *sin) for (block = nlm_blocked; block; block = block->b_next) { dprintk("cookie: head of blocked queue %p, block %p\n", nlm_blocked, block); - if (nlm_cookie_match(&block->b_call.a_args.cookie,cookie) + if (nlm_cookie_match(&block->b_call->a_args.cookie,cookie) && nlm_cmp_addr(sin, &block->b_host->h_addr)) break; } @@ -182,28 +182,30 @@ nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_file *file, { struct nlm_block *block; struct nlm_host *host; - struct nlm_rqst *call; + struct nlm_rqst *call = NULL; /* Create host handle for callback */ host = nlmsvc_lookup_host(rqstp); if (host == NULL) return NULL; + call = nlm_alloc_call(host); + if (call == NULL) + return NULL; + /* Allocate memory for block, and initialize arguments */ - if (!(block = (struct nlm_block *) kmalloc(sizeof(*block), GFP_KERNEL))) + block = kzalloc(sizeof(*block), GFP_KERNEL); + if (block == NULL) goto failed; - memset(block, 0, sizeof(*block)); - locks_init_lock(&block->b_call.a_args.lock.fl); - locks_init_lock(&block->b_call.a_res.lock.fl); kref_init(&block->b_count); - if (!nlmsvc_setgrantargs(&block->b_call, lock)) + if (!nlmsvc_setgrantargs(call, lock)) goto failed_free; /* Set notifier function for VFS, and init args */ - block->b_call.a_args.lock.fl.fl_flags |= FL_SLEEP; - block->b_call.a_args.lock.fl.fl_lmops = &nlmsvc_lock_operations; - block->b_call.a_args.cookie = *cookie; /* see above */ + call->a_args.lock.fl.fl_flags |= FL_SLEEP; + call->a_args.lock.fl.fl_lmops = &nlmsvc_lock_operations; + call->a_args.cookie = *cookie; /* see above */ dprintk("lockd: created block %p...\n", block); @@ -217,16 +219,16 @@ nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_file *file, file->f_blocks = block; /* Set up RPC arguments for callback */ - call = &block->b_call; - call->a_host = host; + block->b_call = call; call->a_flags = RPC_TASK_ASYNC; + call->a_block = block; return block; failed_free: kfree(block); failed: - nlm_release_host(host); + nlm_release_call(call); return NULL; } @@ -242,7 +244,7 @@ static int nlmsvc_unlink_block(struct nlm_block *block) dprintk("lockd: unlinking block %p...\n", block); /* Remove block from list */ - status = posix_unblock_lock(block->b_file->f_file, &block->b_call.a_args.lock.fl); + status = posix_unblock_lock(block->b_file->f_file, &block->b_call->a_args.lock.fl); nlmsvc_remove_block(block); return status; } @@ -263,9 +265,8 @@ static void nlmsvc_free_block(struct kref *kref) } } - if (block->b_host) - nlm_release_host(block->b_host); - nlmsvc_freegrantargs(&block->b_call); + nlmsvc_freegrantargs(block->b_call); + nlm_release_call(block->b_call); kfree(block); } @@ -316,10 +317,8 @@ static int nlmsvc_setgrantargs(struct nlm_rqst *call, struct nlm_lock *lock) if (lock->oh.len > NLMCLNT_OHSIZE) { void *data = kmalloc(lock->oh.len, GFP_KERNEL); - if (!data) { - nlmsvc_freegrantargs(call); + if (!data) return 0; - } call->a_args.lock.oh.data = (u8 *) data; } @@ -329,17 +328,8 @@ static int nlmsvc_setgrantargs(struct nlm_rqst *call, struct nlm_lock *lock) static void nlmsvc_freegrantargs(struct nlm_rqst *call) { - struct file_lock *fl = &call->a_args.lock.fl; - /* - * Check whether we allocated memory for the owner. - */ - if (call->a_args.lock.oh.data != (u8 *) call->a_owner) { + if (call->a_args.lock.oh.data != call->a_owner) kfree(call->a_args.lock.oh.data); - } - if (fl->fl_ops && fl->fl_ops->fl_release_private) - fl->fl_ops->fl_release_private(fl); - if (fl->fl_lmops && fl->fl_lmops->fl_release_private) - fl->fl_lmops->fl_release_private(fl); } /* @@ -371,9 +361,9 @@ again: block = nlmsvc_lookup_block(file, lock, 0); if (block == NULL) { if (newblock != NULL) - lock = &newblock->b_call.a_args.lock; + lock = &newblock->b_call->a_args.lock; } else - lock = &block->b_call.a_args.lock; + lock = &block->b_call->a_args.lock; error = posix_lock_file(file->f_file, &lock->fl); lock->fl.fl_flags &= ~FL_SLEEP; @@ -523,7 +513,7 @@ nlmsvc_notify_blocked(struct file_lock *fl) dprintk("lockd: VFS unblock notification for block %p\n", fl); for (bp = &nlm_blocked; (block = *bp) != 0; bp = &block->b_next) { - if (nlm_compare_locks(&block->b_call.a_args.lock.fl, fl)) { + if (nlm_compare_locks(&block->b_call->a_args.lock.fl, fl)) { nlmsvc_insert_block(block, 0); svc_wake_up(block->b_daemon); return; @@ -558,7 +548,7 @@ static void nlmsvc_grant_blocked(struct nlm_block *block) { struct nlm_file *file = block->b_file; - struct nlm_lock *lock = &block->b_call.a_args.lock; + struct nlm_lock *lock = &block->b_call->a_args.lock; int error; dprintk("lockd: grant blocked lock %p\n", block); @@ -606,7 +596,7 @@ callback: /* Call the client */ kref_get(&block->b_count); - if (nlmsvc_async_call(&block->b_call, NLMPROC_GRANTED_MSG, + if (nlm_async_call(block->b_call, NLMPROC_GRANTED_MSG, &nlmsvc_grant_ops) < 0) nlmsvc_release_block(block); out_unlock: @@ -624,7 +614,7 @@ out_unlock: static void nlmsvc_grant_callback(struct rpc_task *task, void *data) { struct nlm_rqst *call = data; - struct nlm_block *block = container_of(call, struct nlm_block, b_call); + struct nlm_block *block = call->a_block; unsigned long timeout; dprintk("lockd: GRANT_MSG RPC callback\n"); diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c index 4986fbe44540..956d1d71e2af 100644 --- a/fs/lockd/svcproc.c +++ b/fs/lockd/svcproc.c @@ -505,43 +505,36 @@ nlmsvc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_res *resp) struct nlm_host *host; struct nlm_rqst *call; - if (!(call = nlmclnt_alloc_call())) + host = nlmsvc_lookup_host(rqstp); + if (host == NULL) return rpc_system_err; - host = nlmsvc_lookup_host(rqstp); - if (!host) { - kfree(call); + call = nlm_alloc_call(host); + if (call == NULL) return rpc_system_err; - } call->a_flags = RPC_TASK_ASYNC; - call->a_host = host; memcpy(&call->a_args, resp, sizeof(*resp)); - if (nlmsvc_async_call(call, proc, &nlmsvc_callback_ops) < 0) - goto error; - + if (nlm_async_call(call, proc, &nlmsvc_callback_ops) < 0) + return rpc_system_err; return rpc_success; - error: - nlm_release_host(host); - kfree(call); - return rpc_system_err; } static void nlmsvc_callback_exit(struct rpc_task *task, void *data) { - struct nlm_rqst *call = data; + dprintk("lockd: %4d callback returned %d\n", task->tk_pid, + -task->tk_status); +} - if (task->tk_status < 0) { - dprintk("lockd: %4d callback failed (errno = %d)\n", - task->tk_pid, -task->tk_status); - } - nlm_release_host(call->a_host); - kfree(call); +static void nlmsvc_callback_release(void *data) +{ + nlm_release_call(data); } static const struct rpc_call_ops nlmsvc_callback_ops = { .rpc_call_done = nlmsvc_callback_exit, + .rpc_release = nlmsvc_callback_release, }; /* -- cgit v1.2.2 From d47166244860eb5dfdb12ee4703968beef8a0db2 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Mon, 20 Mar 2006 13:44:45 -0500 Subject: lockd: Add helper for *_RES callbacks Signed-off-by: Trond Myklebust --- fs/lockd/clntproc.c | 27 +++++++--- fs/lockd/svc4proc.c | 150 +++++++++++++++++++--------------------------------- fs/lockd/svcproc.c | 143 +++++++++++++++++++------------------------------ 3 files changed, 128 insertions(+), 192 deletions(-) (limited to 'fs/lockd') diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c index 3f8ad7c54efa..f96e38155b5c 100644 --- a/fs/lockd/clntproc.c +++ b/fs/lockd/clntproc.c @@ -354,14 +354,10 @@ in_grace_period: /* * Generic NLM call, async version. */ -int nlm_async_call(struct nlm_rqst *req, u32 proc, const struct rpc_call_ops *tk_ops) +static int __nlm_async_call(struct nlm_rqst *req, u32 proc, struct rpc_message *msg, const struct rpc_call_ops *tk_ops) { struct nlm_host *host = req->a_host; struct rpc_clnt *clnt; - struct rpc_message msg = { - .rpc_argp = &req->a_args, - .rpc_resp = &req->a_res, - }; int status = -ENOLCK; dprintk("lockd: call procedure %d on %s (async)\n", @@ -371,10 +367,10 @@ int nlm_async_call(struct nlm_rqst *req, u32 proc, const struct rpc_call_ops *tk clnt = nlm_bind_host(host); if (clnt == NULL) goto out_err; - msg.rpc_proc = &clnt->cl_procinfo[proc]; + msg->rpc_proc = &clnt->cl_procinfo[proc]; /* bootstrap and kick off the async RPC call */ - status = rpc_call_async(clnt, &msg, RPC_TASK_ASYNC, tk_ops, req); + status = rpc_call_async(clnt, msg, RPC_TASK_ASYNC, tk_ops, req); if (status == 0) return 0; out_err: @@ -382,6 +378,23 @@ out_err: return status; } +int nlm_async_call(struct nlm_rqst *req, u32 proc, const struct rpc_call_ops *tk_ops) +{ + struct rpc_message msg = { + .rpc_argp = &req->a_args, + .rpc_resp = &req->a_res, + }; + return __nlm_async_call(req, proc, &msg, tk_ops); +} + +int nlm_async_reply(struct nlm_rqst *req, u32 proc, const struct rpc_call_ops *tk_ops) +{ + struct rpc_message msg = { + .rpc_argp = &req->a_res, + }; + return __nlm_async_call(req, proc, &msg, tk_ops); +} + /* * TEST for the presence of a conflicting lock */ diff --git a/fs/lockd/svc4proc.c b/fs/lockd/svc4proc.c index cb51c7025825..a2dd9ccb9b32 100644 --- a/fs/lockd/svc4proc.c +++ b/fs/lockd/svc4proc.c @@ -21,10 +21,6 @@ #define NLMDBG_FACILITY NLMDBG_CLIENT -static u32 nlm4svc_callback(struct svc_rqst *, u32, struct nlm_res *); - -static const struct rpc_call_ops nlm4svc_callback_ops; - /* * Obtain client and file from arguments */ @@ -233,84 +229,90 @@ nlm4svc_proc_granted(struct svc_rqst *rqstp, struct nlm_args *argp, return rpc_success; } +/* + * This is the generic lockd callback for async RPC calls + */ +static void nlm4svc_callback_exit(struct rpc_task *task, void *data) +{ + dprintk("lockd: %4d callback returned %d\n", task->tk_pid, + -task->tk_status); +} + +static void nlm4svc_callback_release(void *data) +{ + nlm_release_call(data); +} + +static const struct rpc_call_ops nlm4svc_callback_ops = { + .rpc_call_done = nlm4svc_callback_exit, + .rpc_release = nlm4svc_callback_release, +}; + /* * `Async' versions of the above service routines. They aren't really, * because we send the callback before the reply proper. I hope this * doesn't break any clients. */ -static int -nlm4svc_proc_test_msg(struct svc_rqst *rqstp, struct nlm_args *argp, - void *resp) +static int nlm4svc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_args *argp, + int (*func)(struct svc_rqst *, struct nlm_args *, struct nlm_res *)) { - struct nlm_res res; - u32 stat; + struct nlm_host *host; + struct nlm_rqst *call; + int stat; - dprintk("lockd: TEST_MSG called\n"); - memset(&res, 0, sizeof(res)); + host = nlmsvc_lookup_host(rqstp); + if (host == NULL) + return rpc_system_err; + + call = nlm_alloc_call(host); + if (call == NULL) + return rpc_system_err; + + stat = func(rqstp, argp, &call->a_res); + if (stat != 0) { + nlm_release_call(call); + return stat; + } - if ((stat = nlm4svc_proc_test(rqstp, argp, &res)) == 0) - stat = nlm4svc_callback(rqstp, NLMPROC_TEST_RES, &res); - return stat; + call->a_flags = RPC_TASK_ASYNC; + if (nlm_async_reply(call, proc, &nlm4svc_callback_ops) < 0) + return rpc_system_err; + return rpc_success; } -static int -nlm4svc_proc_lock_msg(struct svc_rqst *rqstp, struct nlm_args *argp, +static int nlm4svc_proc_test_msg(struct svc_rqst *rqstp, struct nlm_args *argp, void *resp) { - struct nlm_res res; - u32 stat; + dprintk("lockd: TEST_MSG called\n"); + return nlm4svc_callback(rqstp, NLMPROC_TEST_RES, argp, nlm4svc_proc_test); +} +static int nlm4svc_proc_lock_msg(struct svc_rqst *rqstp, struct nlm_args *argp, + void *resp) +{ dprintk("lockd: LOCK_MSG called\n"); - memset(&res, 0, sizeof(res)); - - if ((stat = nlm4svc_proc_lock(rqstp, argp, &res)) == 0) - stat = nlm4svc_callback(rqstp, NLMPROC_LOCK_RES, &res); - return stat; + return nlm4svc_callback(rqstp, NLMPROC_LOCK_RES, argp, nlm4svc_proc_lock); } -static int -nlm4svc_proc_cancel_msg(struct svc_rqst *rqstp, struct nlm_args *argp, +static int nlm4svc_proc_cancel_msg(struct svc_rqst *rqstp, struct nlm_args *argp, void *resp) { - struct nlm_res res; - u32 stat; - dprintk("lockd: CANCEL_MSG called\n"); - memset(&res, 0, sizeof(res)); - - if ((stat = nlm4svc_proc_cancel(rqstp, argp, &res)) == 0) - stat = nlm4svc_callback(rqstp, NLMPROC_CANCEL_RES, &res); - return stat; + return nlm4svc_callback(rqstp, NLMPROC_CANCEL_RES, argp, nlm4svc_proc_cancel); } -static int -nlm4svc_proc_unlock_msg(struct svc_rqst *rqstp, struct nlm_args *argp, +static int nlm4svc_proc_unlock_msg(struct svc_rqst *rqstp, struct nlm_args *argp, void *resp) { - struct nlm_res res; - u32 stat; - dprintk("lockd: UNLOCK_MSG called\n"); - memset(&res, 0, sizeof(res)); - - if ((stat = nlm4svc_proc_unlock(rqstp, argp, &res)) == 0) - stat = nlm4svc_callback(rqstp, NLMPROC_UNLOCK_RES, &res); - return stat; + return nlm4svc_callback(rqstp, NLMPROC_UNLOCK_RES, argp, nlm4svc_proc_unlock); } -static int -nlm4svc_proc_granted_msg(struct svc_rqst *rqstp, struct nlm_args *argp, +static int nlm4svc_proc_granted_msg(struct svc_rqst *rqstp, struct nlm_args *argp, void *resp) { - struct nlm_res res; - u32 stat; - dprintk("lockd: GRANTED_MSG called\n"); - memset(&res, 0, sizeof(res)); - - if ((stat = nlm4svc_proc_granted(rqstp, argp, &res)) == 0) - stat = nlm4svc_callback(rqstp, NLMPROC_GRANTED_RES, &res); - return stat; + return nlm4svc_callback(rqstp, NLMPROC_GRANTED_RES, argp, nlm4svc_proc_granted); } /* @@ -471,48 +473,6 @@ nlm4svc_proc_granted_res(struct svc_rqst *rqstp, struct nlm_res *argp, } -/* - * This is the generic lockd callback for async RPC calls - */ -static u32 -nlm4svc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_res *resp) -{ - struct nlm_host *host; - struct nlm_rqst *call; - - host = nlmsvc_lookup_host(rqstp); - if (host == NULL) - return rpc_system_err; - - call = nlm_alloc_call(host); - if (call == NULL) - return rpc_system_err; - - - call->a_flags = RPC_TASK_ASYNC; - memcpy(&call->a_args, resp, sizeof(*resp)); - - if (nlm_async_call(call, proc, &nlm4svc_callback_ops) < 0) - return rpc_system_err; - return rpc_success; -} - -static void nlm4svc_callback_exit(struct rpc_task *task, void *data) -{ - dprintk("lockd: %4d callback returned %d\n", task->tk_pid, - -task->tk_status); -} - -static void nlm4svc_callback_release(void *data) -{ - nlm_release_call(data); -} - -static const struct rpc_call_ops nlm4svc_callback_ops = { - .rpc_call_done = nlm4svc_callback_exit, - .rpc_release = nlm4svc_callback_release, -}; - /* * NLM Server procedures. */ diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c index 956d1d71e2af..d210cf304e92 100644 --- a/fs/lockd/svcproc.c +++ b/fs/lockd/svcproc.c @@ -22,10 +22,6 @@ #define NLMDBG_FACILITY NLMDBG_CLIENT -static u32 nlmsvc_callback(struct svc_rqst *, u32, struct nlm_res *); - -static const struct rpc_call_ops nlmsvc_callback_ops; - #ifdef CONFIG_LOCKD_V4 static u32 cast_to_nlm(u32 status, u32 vers) @@ -261,84 +257,92 @@ nlmsvc_proc_granted(struct svc_rqst *rqstp, struct nlm_args *argp, return rpc_success; } +/* + * This is the generic lockd callback for async RPC calls + */ +static void nlmsvc_callback_exit(struct rpc_task *task, void *data) +{ + dprintk("lockd: %4d callback returned %d\n", task->tk_pid, + -task->tk_status); +} + +static void nlmsvc_callback_release(void *data) +{ + nlm_release_call(data); +} + +static const struct rpc_call_ops nlmsvc_callback_ops = { + .rpc_call_done = nlmsvc_callback_exit, + .rpc_release = nlmsvc_callback_release, +}; + /* * `Async' versions of the above service routines. They aren't really, * because we send the callback before the reply proper. I hope this * doesn't break any clients. */ -static int -nlmsvc_proc_test_msg(struct svc_rqst *rqstp, struct nlm_args *argp, - void *resp) +static int nlmsvc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_args *argp, + int (*func)(struct svc_rqst *, struct nlm_args *, struct nlm_res *)) { - struct nlm_res res; - u32 stat; + struct nlm_host *host; + struct nlm_rqst *call; + int stat; - dprintk("lockd: TEST_MSG called\n"); - memset(&res, 0, sizeof(res)); + host = nlmsvc_lookup_host(rqstp); + if (host == NULL) + return rpc_system_err; + + call = nlm_alloc_call(host); + if (call == NULL) + return rpc_system_err; + + stat = func(rqstp, argp, &call->a_res); + if (stat != 0) { + nlm_release_call(call); + return stat; + } - if ((stat = nlmsvc_proc_test(rqstp, argp, &res)) == 0) - stat = nlmsvc_callback(rqstp, NLMPROC_TEST_RES, &res); - return stat; + call->a_flags = RPC_TASK_ASYNC; + if (nlm_async_reply(call, proc, &nlmsvc_callback_ops) < 0) + return rpc_system_err; + return rpc_success; } -static int -nlmsvc_proc_lock_msg(struct svc_rqst *rqstp, struct nlm_args *argp, +static int nlmsvc_proc_test_msg(struct svc_rqst *rqstp, struct nlm_args *argp, void *resp) { - struct nlm_res res; - u32 stat; + dprintk("lockd: TEST_MSG called\n"); + return nlmsvc_callback(rqstp, NLMPROC_TEST_RES, argp, nlmsvc_proc_test); +} +static int nlmsvc_proc_lock_msg(struct svc_rqst *rqstp, struct nlm_args *argp, + void *resp) +{ dprintk("lockd: LOCK_MSG called\n"); - memset(&res, 0, sizeof(res)); - - if ((stat = nlmsvc_proc_lock(rqstp, argp, &res)) == 0) - stat = nlmsvc_callback(rqstp, NLMPROC_LOCK_RES, &res); - return stat; + return nlmsvc_callback(rqstp, NLMPROC_LOCK_RES, argp, nlmsvc_proc_lock); } -static int -nlmsvc_proc_cancel_msg(struct svc_rqst *rqstp, struct nlm_args *argp, +static int nlmsvc_proc_cancel_msg(struct svc_rqst *rqstp, struct nlm_args *argp, void *resp) { - struct nlm_res res; - u32 stat; - dprintk("lockd: CANCEL_MSG called\n"); - memset(&res, 0, sizeof(res)); - - if ((stat = nlmsvc_proc_cancel(rqstp, argp, &res)) == 0) - stat = nlmsvc_callback(rqstp, NLMPROC_CANCEL_RES, &res); - return stat; + return nlmsvc_callback(rqstp, NLMPROC_CANCEL_RES, argp, nlmsvc_proc_cancel); } static int nlmsvc_proc_unlock_msg(struct svc_rqst *rqstp, struct nlm_args *argp, void *resp) { - struct nlm_res res; - u32 stat; - dprintk("lockd: UNLOCK_MSG called\n"); - memset(&res, 0, sizeof(res)); - - if ((stat = nlmsvc_proc_unlock(rqstp, argp, &res)) == 0) - stat = nlmsvc_callback(rqstp, NLMPROC_UNLOCK_RES, &res); - return stat; + return nlmsvc_callback(rqstp, NLMPROC_UNLOCK_RES, argp, nlmsvc_proc_unlock); } static int nlmsvc_proc_granted_msg(struct svc_rqst *rqstp, struct nlm_args *argp, void *resp) { - struct nlm_res res; - u32 stat; - dprintk("lockd: GRANTED_MSG called\n"); - memset(&res, 0, sizeof(res)); - - if ((stat = nlmsvc_proc_granted(rqstp, argp, &res)) == 0) - stat = nlmsvc_callback(rqstp, NLMPROC_GRANTED_RES, &res); - return stat; + return nlmsvc_callback(rqstp, NLMPROC_GRANTED_RES, argp, nlmsvc_proc_granted); } /* @@ -496,47 +500,6 @@ nlmsvc_proc_granted_res(struct svc_rqst *rqstp, struct nlm_res *argp, return rpc_success; } -/* - * This is the generic lockd callback for async RPC calls - */ -static u32 -nlmsvc_callback(struct svc_rqst *rqstp, u32 proc, struct nlm_res *resp) -{ - struct nlm_host *host; - struct nlm_rqst *call; - - host = nlmsvc_lookup_host(rqstp); - if (host == NULL) - return rpc_system_err; - - call = nlm_alloc_call(host); - if (call == NULL) - return rpc_system_err; - - call->a_flags = RPC_TASK_ASYNC; - memcpy(&call->a_args, resp, sizeof(*resp)); - - if (nlm_async_call(call, proc, &nlmsvc_callback_ops) < 0) - return rpc_system_err; - return rpc_success; -} - -static void nlmsvc_callback_exit(struct rpc_task *task, void *data) -{ - dprintk("lockd: %4d callback returned %d\n", task->tk_pid, - -task->tk_status); -} - -static void nlmsvc_callback_release(void *data) -{ - nlm_release_call(data); -} - -static const struct rpc_call_ops nlmsvc_callback_ops = { - .rpc_call_done = nlmsvc_callback_exit, - .rpc_release = nlmsvc_callback_release, -}; - /* * NLM Server procedures. */ -- cgit v1.2.2 From 6041b79192bdf0e7ab18ea6859effa5d8311391b Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Mon, 20 Mar 2006 13:44:45 -0500 Subject: lockd: Fix a typo in nlmsvc_grant_release() Signed-off-by: Trond Myklebust --- fs/lockd/svclock.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'fs/lockd') diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c index 185bf7ea1c0c..c16c94f5a856 100644 --- a/fs/lockd/svclock.c +++ b/fs/lockd/svclock.c @@ -638,7 +638,9 @@ static void nlmsvc_grant_callback(struct rpc_task *task, void *data) void nlmsvc_grant_release(void *data) { - nlmsvc_release_block(data); + struct nlm_rqst *call = data; + + nlmsvc_release_block(call->a_block); } static const struct rpc_call_ops nlmsvc_grant_ops = { -- cgit v1.2.2 From d9f6eb75d4900782a095b98470decfe98971f920 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Mon, 20 Mar 2006 13:44:47 -0500 Subject: lockd: blocks should hold a reference to the nlm_file Signed-off-by: Trond Myklebust --- fs/lockd/svclock.c | 81 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 46 insertions(+), 35 deletions(-) (limited to 'fs/lockd') diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c index c16c94f5a856..ce754efe2841 100644 --- a/fs/lockd/svclock.c +++ b/fs/lockd/svclock.c @@ -103,11 +103,10 @@ nlmsvc_remove_block(struct nlm_block *block) } /* - * Find a block for a given lock and optionally remove it from - * the list. + * Find a block for a given lock */ static struct nlm_block * -nlmsvc_lookup_block(struct nlm_file *file, struct nlm_lock *lock, int remove) +nlmsvc_lookup_block(struct nlm_file *file, struct nlm_lock *lock) { struct nlm_block **head, *block; struct file_lock *fl; @@ -124,10 +123,6 @@ nlmsvc_lookup_block(struct nlm_file *file, struct nlm_lock *lock, int remove) (long long)fl->fl_end, fl->fl_type, nlmdbg_cookie2a(&block->b_call->a_args.cookie)); if (block->b_file == file && nlm_compare_locks(fl, &lock->fl)) { - if (remove) { - *head = block->b_next; - block->b_queued = 0; - } kref_get(&block->b_count); return block; } @@ -213,6 +208,7 @@ nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_file *file, block->b_daemon = rqstp->rq_server; block->b_host = host; block->b_file = file; + file->f_count++; /* Add to file's list of blocks */ block->b_fnext = file->f_blocks; @@ -257,6 +253,7 @@ static void nlmsvc_free_block(struct kref *kref) dprintk("lockd: freeing block %p...\n", block); + down(&file->f_sema); /* Remove block from file's list of blocks */ for (bp = &file->f_blocks; *bp; bp = &(*bp)->b_fnext) { if (*bp == block) { @@ -264,9 +261,11 @@ static void nlmsvc_free_block(struct kref *kref) break; } } + up(&file->f_sema); nlmsvc_freegrantargs(block->b_call); nlm_release_call(block->b_call); + nlm_release_file(block->b_file); kfree(block); } @@ -276,6 +275,36 @@ static void nlmsvc_release_block(struct nlm_block *block) kref_put(&block->b_count, nlmsvc_free_block); } +static void nlmsvc_act_mark(struct nlm_host *host, struct nlm_file *file) +{ + struct nlm_block *block; + + down(&file->f_sema); + for (block = file->f_blocks; block != NULL; block = block->b_fnext) + block->b_host->h_inuse = 1; + up(&file->f_sema); +} + +static void nlmsvc_act_unlock(struct nlm_host *host, struct nlm_file *file) +{ + struct nlm_block *block; + +restart: + down(&file->f_sema); + for (block = file->f_blocks; block != NULL; block = block->b_fnext) { + if (host != NULL && host != block->b_host) + continue; + if (!block->b_queued) + continue; + kref_get(&block->b_count); + up(&file->f_sema); + nlmsvc_unlink_block(block); + nlmsvc_release_block(block); + goto restart; + } + up(&file->f_sema); +} + /* * Loop over all blocks and perform the action specified. * (NLM_ACT_CHECK handled by nlmsvc_inspect_file). @@ -283,20 +312,10 @@ static void nlmsvc_release_block(struct nlm_block *block) int nlmsvc_traverse_blocks(struct nlm_host *host, struct nlm_file *file, int action) { - struct nlm_block *block, *next; - /* XXX: Will everything get cleaned up if we don't unlock here? */ - - down(&file->f_sema); - for (block = file->f_blocks; block; block = next) { - next = block->b_fnext; - if (action == NLM_ACT_MARK) - block->b_host->h_inuse = 1; - else if (action == NLM_ACT_UNLOCK) { - if (host == NULL || host == block->b_host) - nlmsvc_unlink_block(block); - } - } - up(&file->f_sema); + if (action == NLM_ACT_MARK) + nlmsvc_act_mark(host, file); + else + nlmsvc_act_unlock(host, file); return 0; } @@ -358,7 +377,7 @@ again: /* Lock file against concurrent access */ down(&file->f_sema); /* Get existing block (in case client is busy-waiting) */ - block = nlmsvc_lookup_block(file, lock, 0); + block = nlmsvc_lookup_block(file, lock); if (block == NULL) { if (newblock != NULL) lock = &newblock->b_call->a_args.lock; @@ -491,11 +510,12 @@ nlmsvc_cancel_blocked(struct nlm_file *file, struct nlm_lock *lock) (long long)lock->fl.fl_end); down(&file->f_sema); - if ((block = nlmsvc_lookup_block(file, lock, 1)) != NULL) { + block = nlmsvc_lookup_block(file, lock); + up(&file->f_sema); + if (block != NULL) { status = nlmsvc_unlink_block(block); nlmsvc_release_block(block); } - up(&file->f_sema); return status ? nlm_lck_denied : nlm_granted; } @@ -553,9 +573,6 @@ nlmsvc_grant_blocked(struct nlm_block *block) dprintk("lockd: grant blocked lock %p\n", block); - /* First thing is lock the file */ - down(&file->f_sema); - /* Unlink block request from list */ nlmsvc_unlink_block(block); @@ -578,12 +595,12 @@ nlmsvc_grant_blocked(struct nlm_block *block) case -EAGAIN: dprintk("lockd: lock still blocked\n"); nlmsvc_insert_block(block, NLM_NEVER); - goto out_unlock; + return; default: printk(KERN_WARNING "lockd: unexpected error %d in %s!\n", -error, __FUNCTION__); nlmsvc_insert_block(block, 10 * HZ); - goto out_unlock; + return; } callback: @@ -599,8 +616,6 @@ callback: if (nlm_async_call(block->b_call, NLMPROC_GRANTED_MSG, &nlmsvc_grant_ops) < 0) nlmsvc_release_block(block); -out_unlock: - up(&file->f_sema); } /* @@ -665,8 +680,6 @@ nlmsvc_grant_reply(struct svc_rqst *rqstp, struct nlm_cookie *cookie, u32 status return; file = block->b_file; - file->f_count++; - down(&file->f_sema); if (block) { if (status == NLM_LCK_DENIED_GRACE_PERIOD) { /* Try again in a couple of seconds */ @@ -677,8 +690,6 @@ nlmsvc_grant_reply(struct svc_rqst *rqstp, struct nlm_cookie *cookie, u32 status nlmsvc_unlink_block(block); } } - up(&file->f_sema); - nlm_release_file(file); nlmsvc_release_block(block); } -- cgit v1.2.2 From f3ee439f43381e45b191cf721b4a51d41f33301f Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Mon, 20 Mar 2006 23:24:13 -0500 Subject: LOCKD: nlmsvc_traverse_blocks return is unused Note that we never return non-zero. Signed-off-by: J. Bruce Fields Signed-off-by: Trond Myklebust --- fs/lockd/svclock.c | 3 +-- fs/lockd/svcsubs.c | 5 +++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'fs/lockd') diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c index ce754efe2841..d2b66bad7d50 100644 --- a/fs/lockd/svclock.c +++ b/fs/lockd/svclock.c @@ -309,14 +309,13 @@ restart: * Loop over all blocks and perform the action specified. * (NLM_ACT_CHECK handled by nlmsvc_inspect_file). */ -int +void nlmsvc_traverse_blocks(struct nlm_host *host, struct nlm_file *file, int action) { if (action == NLM_ACT_MARK) nlmsvc_act_mark(host, file); else nlmsvc_act_unlock(host, file); - return 0; } /* diff --git a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c index 601e5b3dfe20..2043011a1a2d 100644 --- a/fs/lockd/svcsubs.c +++ b/fs/lockd/svcsubs.c @@ -224,8 +224,9 @@ nlm_inspect_file(struct nlm_host *host, struct nlm_file *file, int action) if (file->f_count || file->f_blocks || file->f_shares) return 1; } else { - if (nlmsvc_traverse_blocks(host, file, action) - || nlmsvc_traverse_shares(host, file, action)) + nlmsvc_traverse_blocks(host, file, action); + + if (nlmsvc_traverse_shares(host, file, action)) return 1; } return nlm_traverse_locks(host, file, action); -- cgit v1.2.2 From 5f12191bc000ea31970339a5f54c11087506711c Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Mon, 20 Mar 2006 23:24:25 -0500 Subject: LOCKD: Make nlmsvc_traverse_shares return void The nlmsvc_traverse_shares return value is always zero, hence useless. Signed-off-by: J. Bruce Fields Signed-off-by: Trond Myklebust --- fs/lockd/svcshare.c | 4 +--- fs/lockd/svcsubs.c | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) (limited to 'fs/lockd') diff --git a/fs/lockd/svcshare.c b/fs/lockd/svcshare.c index 4943fb7836ce..27288c83da96 100644 --- a/fs/lockd/svcshare.c +++ b/fs/lockd/svcshare.c @@ -88,7 +88,7 @@ nlmsvc_unshare_file(struct nlm_host *host, struct nlm_file *file, * Traverse all shares for a given file (and host). * NLM_ACT_CHECK is handled by nlmsvc_inspect_file. */ -int +void nlmsvc_traverse_shares(struct nlm_host *host, struct nlm_file *file, int action) { struct nlm_share *share, **shpp; @@ -106,6 +106,4 @@ nlmsvc_traverse_shares(struct nlm_host *host, struct nlm_file *file, int action) } shpp = &share->s_next; } - - return 0; } diff --git a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c index 2043011a1a2d..c7a6e3ae44d6 100644 --- a/fs/lockd/svcsubs.c +++ b/fs/lockd/svcsubs.c @@ -225,9 +225,7 @@ nlm_inspect_file(struct nlm_host *host, struct nlm_file *file, int action) return 1; } else { nlmsvc_traverse_blocks(host, file, action); - - if (nlmsvc_traverse_shares(host, file, action)) - return 1; + nlmsvc_traverse_shares(host, file, action); } return nlm_traverse_locks(host, file, action); } -- cgit v1.2.2