diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-03-20 13:44:45 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-03-20 13:44:45 -0500 |
commit | 92737230dd3f1478033819d4bc20339f8da852da (patch) | |
tree | 27bc7804a077a29b7614c698bb02632dc4ce228e /fs/lockd | |
parent | e4cd038a45a46ffbe06a1a72f3f15246e5b041ca (diff) |
NLM: Add nlmclnt_release_call
Add a helper function to simplify the freeing of NLM client requests.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/lockd')
-rw-r--r-- | fs/lockd/clntproc.c | 195 | ||||
-rw-r--r-- | fs/lockd/svc4proc.c | 34 | ||||
-rw-r--r-- | fs/lockd/svclock.c | 66 | ||||
-rw-r--r-- | fs/lockd/svcproc.c | 33 |
4 files changed, 129 insertions, 199 deletions
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) | |||
152 | int | 152 | int |
153 | nlmclnt_proc(struct inode *inode, int cmd, struct file_lock *fl) | 153 | nlmclnt_proc(struct inode *inode, int cmd, struct file_lock *fl) |
154 | { | 154 | { |
155 | struct nfs_server *nfssrv = NFS_SERVER(inode); | ||
156 | struct nlm_host *host; | 155 | struct nlm_host *host; |
157 | struct nlm_rqst reqst, *call = &reqst; | 156 | struct nlm_rqst *call; |
158 | sigset_t oldset; | 157 | sigset_t oldset; |
159 | unsigned long flags; | 158 | unsigned long flags; |
160 | int status, proto, vers; | 159 | int status, proto, vers; |
@@ -168,23 +167,17 @@ nlmclnt_proc(struct inode *inode, int cmd, struct file_lock *fl) | |||
168 | /* Retrieve transport protocol from NFS client */ | 167 | /* Retrieve transport protocol from NFS client */ |
169 | proto = NFS_CLIENT(inode)->cl_xprt->prot; | 168 | proto = NFS_CLIENT(inode)->cl_xprt->prot; |
170 | 169 | ||
171 | if (!(host = nlmclnt_lookup_host(NFS_ADDR(inode), proto, vers))) | 170 | host = nlmclnt_lookup_host(NFS_ADDR(inode), proto, vers); |
171 | if (host == NULL) | ||
172 | return -ENOLCK; | 172 | return -ENOLCK; |
173 | 173 | ||
174 | /* Create RPC client handle if not there, and copy soft | 174 | call = nlm_alloc_call(host); |
175 | * and intr flags from NFS client. */ | 175 | if (call == NULL) |
176 | if (host->h_rpcclnt == NULL) { | 176 | return -ENOMEM; |
177 | struct rpc_clnt *clnt; | ||
178 | 177 | ||
179 | /* Bind an rpc client to this host handle (does not | 178 | nlmclnt_locks_init_private(fl, host); |
180 | * perform a portmapper lookup) */ | 179 | /* Set up the argument struct */ |
181 | if (!(clnt = nlm_bind_host(host))) { | 180 | nlmclnt_setlockargs(call, fl); |
182 | status = -ENOLCK; | ||
183 | goto done; | ||
184 | } | ||
185 | clnt->cl_softrtry = nfssrv->client->cl_softrtry; | ||
186 | clnt->cl_intr = nfssrv->client->cl_intr; | ||
187 | } | ||
188 | 181 | ||
189 | /* Keep the old signal mask */ | 182 | /* Keep the old signal mask */ |
190 | spin_lock_irqsave(¤t->sighand->siglock, flags); | 183 | spin_lock_irqsave(¤t->sighand->siglock, flags); |
@@ -197,26 +190,10 @@ nlmclnt_proc(struct inode *inode, int cmd, struct file_lock *fl) | |||
197 | && (current->flags & PF_EXITING)) { | 190 | && (current->flags & PF_EXITING)) { |
198 | sigfillset(¤t->blocked); /* Mask all signals */ | 191 | sigfillset(¤t->blocked); /* Mask all signals */ |
199 | recalc_sigpending(); | 192 | recalc_sigpending(); |
200 | spin_unlock_irqrestore(¤t->sighand->siglock, flags); | ||
201 | 193 | ||
202 | call = nlmclnt_alloc_call(); | ||
203 | if (!call) { | ||
204 | status = -ENOMEM; | ||
205 | goto out_restore; | ||
206 | } | ||
207 | call->a_flags = RPC_TASK_ASYNC; | 194 | call->a_flags = RPC_TASK_ASYNC; |
208 | } else { | ||
209 | spin_unlock_irqrestore(¤t->sighand->siglock, flags); | ||
210 | memset(call, 0, sizeof(*call)); | ||
211 | locks_init_lock(&call->a_args.lock.fl); | ||
212 | locks_init_lock(&call->a_res.lock.fl); | ||
213 | } | 195 | } |
214 | call->a_host = host; | 196 | spin_unlock_irqrestore(¤t->sighand->siglock, flags); |
215 | |||
216 | nlmclnt_locks_init_private(fl, host); | ||
217 | |||
218 | /* Set up the argument struct */ | ||
219 | nlmclnt_setlockargs(call, fl); | ||
220 | 197 | ||
221 | if (IS_SETLK(cmd) || IS_SETLKW(cmd)) { | 198 | if (IS_SETLK(cmd) || IS_SETLKW(cmd)) { |
222 | if (fl->fl_type != F_UNLCK) { | 199 | if (fl->fl_type != F_UNLCK) { |
@@ -229,24 +206,26 @@ nlmclnt_proc(struct inode *inode, int cmd, struct file_lock *fl) | |||
229 | else | 206 | else |
230 | status = -EINVAL; | 207 | status = -EINVAL; |
231 | 208 | ||
232 | out_restore: | 209 | fl->fl_ops->fl_release_private(fl); |
210 | fl->fl_ops = NULL; | ||
211 | |||
233 | spin_lock_irqsave(¤t->sighand->siglock, flags); | 212 | spin_lock_irqsave(¤t->sighand->siglock, flags); |
234 | current->blocked = oldset; | 213 | current->blocked = oldset; |
235 | recalc_sigpending(); | 214 | recalc_sigpending(); |
236 | spin_unlock_irqrestore(¤t->sighand->siglock, flags); | 215 | spin_unlock_irqrestore(¤t->sighand->siglock, flags); |
237 | 216 | ||
238 | done: | ||
239 | dprintk("lockd: clnt proc returns %d\n", status); | 217 | dprintk("lockd: clnt proc returns %d\n", status); |
240 | nlm_release_host(host); | ||
241 | return status; | 218 | return status; |
242 | } | 219 | } |
243 | EXPORT_SYMBOL(nlmclnt_proc); | 220 | EXPORT_SYMBOL(nlmclnt_proc); |
244 | 221 | ||
245 | /* | 222 | /* |
246 | * Allocate an NLM RPC call struct | 223 | * Allocate an NLM RPC call struct |
224 | * | ||
225 | * Note: the caller must hold a reference to host. In case of failure, | ||
226 | * this reference will be released. | ||
247 | */ | 227 | */ |
248 | struct nlm_rqst * | 228 | struct nlm_rqst *nlm_alloc_call(struct nlm_host *host) |
249 | nlmclnt_alloc_call(void) | ||
250 | { | 229 | { |
251 | struct nlm_rqst *call; | 230 | struct nlm_rqst *call; |
252 | 231 | ||
@@ -255,16 +234,30 @@ nlmclnt_alloc_call(void) | |||
255 | if (call != NULL) { | 234 | if (call != NULL) { |
256 | locks_init_lock(&call->a_args.lock.fl); | 235 | locks_init_lock(&call->a_args.lock.fl); |
257 | locks_init_lock(&call->a_res.lock.fl); | 236 | locks_init_lock(&call->a_res.lock.fl); |
237 | call->a_host = host; | ||
258 | return call; | 238 | return call; |
259 | } | 239 | } |
260 | if (signalled()) | 240 | if (signalled()) |
261 | break; | 241 | break; |
262 | printk("nlmclnt_alloc_call: failed, waiting for memory\n"); | 242 | printk("nlm_alloc_call: failed, waiting for memory\n"); |
263 | schedule_timeout_interruptible(5*HZ); | 243 | schedule_timeout_interruptible(5*HZ); |
264 | } | 244 | } |
245 | nlm_release_host(host); | ||
265 | return NULL; | 246 | return NULL; |
266 | } | 247 | } |
267 | 248 | ||
249 | void nlm_release_call(struct nlm_rqst *call) | ||
250 | { | ||
251 | nlm_release_host(call->a_host); | ||
252 | nlmclnt_release_lockargs(call); | ||
253 | kfree(call); | ||
254 | } | ||
255 | |||
256 | static void nlmclnt_rpc_release(void *data) | ||
257 | { | ||
258 | return nlm_release_call(data); | ||
259 | } | ||
260 | |||
268 | static int nlm_wait_on_grace(wait_queue_head_t *queue) | 261 | static int nlm_wait_on_grace(wait_queue_head_t *queue) |
269 | { | 262 | { |
270 | DEFINE_WAIT(wait); | 263 | DEFINE_WAIT(wait); |
@@ -361,7 +354,7 @@ in_grace_period: | |||
361 | /* | 354 | /* |
362 | * Generic NLM call, async version. | 355 | * Generic NLM call, async version. |
363 | */ | 356 | */ |
364 | int nlmsvc_async_call(struct nlm_rqst *req, u32 proc, const struct rpc_call_ops *tk_ops) | 357 | int nlm_async_call(struct nlm_rqst *req, u32 proc, const struct rpc_call_ops *tk_ops) |
365 | { | 358 | { |
366 | struct nlm_host *host = req->a_host; | 359 | struct nlm_host *host = req->a_host; |
367 | struct rpc_clnt *clnt; | 360 | struct rpc_clnt *clnt; |
@@ -369,48 +362,23 @@ int nlmsvc_async_call(struct nlm_rqst *req, u32 proc, const struct rpc_call_ops | |||
369 | .rpc_argp = &req->a_args, | 362 | .rpc_argp = &req->a_args, |
370 | .rpc_resp = &req->a_res, | 363 | .rpc_resp = &req->a_res, |
371 | }; | 364 | }; |
372 | int status; | 365 | int status = -ENOLCK; |
373 | |||
374 | dprintk("lockd: call procedure %d on %s (async)\n", | ||
375 | (int)proc, host->h_name); | ||
376 | |||
377 | /* If we have no RPC client yet, create one. */ | ||
378 | if ((clnt = nlm_bind_host(host)) == NULL) | ||
379 | return -ENOLCK; | ||
380 | msg.rpc_proc = &clnt->cl_procinfo[proc]; | ||
381 | |||
382 | /* bootstrap and kick off the async RPC call */ | ||
383 | status = rpc_call_async(clnt, &msg, RPC_TASK_ASYNC, tk_ops, req); | ||
384 | |||
385 | return status; | ||
386 | } | ||
387 | |||
388 | static int nlmclnt_async_call(struct nlm_rqst *req, u32 proc, const struct rpc_call_ops *tk_ops) | ||
389 | { | ||
390 | struct nlm_host *host = req->a_host; | ||
391 | struct rpc_clnt *clnt; | ||
392 | struct nlm_args *argp = &req->a_args; | ||
393 | struct nlm_res *resp = &req->a_res; | ||
394 | struct rpc_message msg = { | ||
395 | .rpc_argp = argp, | ||
396 | .rpc_resp = resp, | ||
397 | }; | ||
398 | int status; | ||
399 | 366 | ||
400 | dprintk("lockd: call procedure %d on %s (async)\n", | 367 | dprintk("lockd: call procedure %d on %s (async)\n", |
401 | (int)proc, host->h_name); | 368 | (int)proc, host->h_name); |
402 | 369 | ||
403 | /* If we have no RPC client yet, create one. */ | 370 | /* If we have no RPC client yet, create one. */ |
404 | if ((clnt = nlm_bind_host(host)) == NULL) | 371 | clnt = nlm_bind_host(host); |
405 | return -ENOLCK; | 372 | if (clnt == NULL) |
373 | goto out_err; | ||
406 | msg.rpc_proc = &clnt->cl_procinfo[proc]; | 374 | msg.rpc_proc = &clnt->cl_procinfo[proc]; |
407 | 375 | ||
408 | /* Increment host refcount */ | ||
409 | nlm_get_host(host); | ||
410 | /* bootstrap and kick off the async RPC call */ | 376 | /* bootstrap and kick off the async RPC call */ |
411 | status = rpc_call_async(clnt, &msg, RPC_TASK_ASYNC, tk_ops, req); | 377 | status = rpc_call_async(clnt, &msg, RPC_TASK_ASYNC, tk_ops, req); |
412 | if (status < 0) | 378 | if (status == 0) |
413 | nlm_release_host(host); | 379 | return 0; |
380 | out_err: | ||
381 | nlm_release_call(req); | ||
414 | return status; | 382 | return status; |
415 | } | 383 | } |
416 | 384 | ||
@@ -423,26 +391,28 @@ nlmclnt_test(struct nlm_rqst *req, struct file_lock *fl) | |||
423 | int status; | 391 | int status; |
424 | 392 | ||
425 | status = nlmclnt_call(req, NLMPROC_TEST); | 393 | status = nlmclnt_call(req, NLMPROC_TEST); |
426 | nlmclnt_release_lockargs(req); | ||
427 | if (status < 0) | 394 | if (status < 0) |
428 | return status; | 395 | goto out; |
429 | 396 | ||
430 | status = req->a_res.status; | 397 | switch (req->a_res.status) { |
431 | if (status == NLM_LCK_GRANTED) { | 398 | case NLM_LCK_GRANTED: |
432 | fl->fl_type = F_UNLCK; | 399 | fl->fl_type = F_UNLCK; |
433 | } if (status == NLM_LCK_DENIED) { | 400 | break; |
434 | /* | 401 | case NLM_LCK_DENIED: |
435 | * Report the conflicting lock back to the application. | 402 | /* |
436 | */ | 403 | * Report the conflicting lock back to the application. |
437 | fl->fl_start = req->a_res.lock.fl.fl_start; | 404 | */ |
438 | fl->fl_end = req->a_res.lock.fl.fl_start; | 405 | fl->fl_start = req->a_res.lock.fl.fl_start; |
439 | fl->fl_type = req->a_res.lock.fl.fl_type; | 406 | fl->fl_end = req->a_res.lock.fl.fl_start; |
440 | fl->fl_pid = 0; | 407 | fl->fl_type = req->a_res.lock.fl.fl_type; |
441 | } else { | 408 | fl->fl_pid = 0; |
442 | return nlm_stat_to_errno(req->a_res.status); | 409 | break; |
410 | default: | ||
411 | status = nlm_stat_to_errno(req->a_res.status); | ||
443 | } | 412 | } |
444 | 413 | out: | |
445 | return 0; | 414 | nlm_release_call(req); |
415 | return status; | ||
446 | } | 416 | } |
447 | 417 | ||
448 | static void nlmclnt_locks_copy_lock(struct file_lock *new, struct file_lock *fl) | 418 | static void nlmclnt_locks_copy_lock(struct file_lock *new, struct file_lock *fl) |
@@ -560,7 +530,7 @@ out_unblock: | |||
560 | if (resp->status == NLM_LCK_BLOCKED) | 530 | if (resp->status == NLM_LCK_BLOCKED) |
561 | nlmclnt_cancel(host, req->a_args.block, fl); | 531 | nlmclnt_cancel(host, req->a_args.block, fl); |
562 | out: | 532 | out: |
563 | nlmclnt_release_lockargs(req); | 533 | nlm_release_call(req); |
564 | return status; | 534 | return status; |
565 | } | 535 | } |
566 | 536 | ||
@@ -623,32 +593,24 @@ nlmclnt_unlock(struct nlm_rqst *req, struct file_lock *fl) | |||
623 | */ | 593 | */ |
624 | do_vfs_lock(fl); | 594 | do_vfs_lock(fl); |
625 | 595 | ||
626 | if (req->a_flags & RPC_TASK_ASYNC) { | 596 | if (req->a_flags & RPC_TASK_ASYNC) |
627 | status = nlmclnt_async_call(req, NLMPROC_UNLOCK, | 597 | return nlm_async_call(req, NLMPROC_UNLOCK, &nlmclnt_unlock_ops); |
628 | &nlmclnt_unlock_ops); | ||
629 | /* Hrmf... Do the unlock early since locks_remove_posix() | ||
630 | * really expects us to free the lock synchronously */ | ||
631 | if (status < 0) { | ||
632 | nlmclnt_release_lockargs(req); | ||
633 | kfree(req); | ||
634 | } | ||
635 | return status; | ||
636 | } | ||
637 | 598 | ||
638 | status = nlmclnt_call(req, NLMPROC_UNLOCK); | 599 | status = nlmclnt_call(req, NLMPROC_UNLOCK); |
639 | nlmclnt_release_lockargs(req); | ||
640 | if (status < 0) | 600 | if (status < 0) |
641 | return status; | 601 | goto out; |
642 | 602 | ||
603 | status = 0; | ||
643 | if (resp->status == NLM_LCK_GRANTED) | 604 | if (resp->status == NLM_LCK_GRANTED) |
644 | return 0; | 605 | goto out; |
645 | 606 | ||
646 | if (resp->status != NLM_LCK_DENIED_NOLOCKS) | 607 | if (resp->status != NLM_LCK_DENIED_NOLOCKS) |
647 | printk("lockd: unexpected unlock status: %d\n", resp->status); | 608 | printk("lockd: unexpected unlock status: %d\n", resp->status); |
648 | |||
649 | /* What to do now? I'm out of my depth... */ | 609 | /* What to do now? I'm out of my depth... */ |
650 | 610 | status = -ENOLCK; | |
651 | return -ENOLCK; | 611 | out: |
612 | nlm_release_call(req); | ||
613 | return status; | ||
652 | } | 614 | } |
653 | 615 | ||
654 | static void nlmclnt_unlock_callback(struct rpc_task *task, void *data) | 616 | 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) | |||
670 | if (status != NLM_LCK_GRANTED) | 632 | if (status != NLM_LCK_GRANTED) |
671 | printk(KERN_WARNING "lockd: unexpected unlock status: %d\n", status); | 633 | printk(KERN_WARNING "lockd: unexpected unlock status: %d\n", status); |
672 | die: | 634 | die: |
673 | nlm_release_host(req->a_host); | ||
674 | nlmclnt_release_lockargs(req); | ||
675 | kfree(req); | ||
676 | return; | 635 | return; |
677 | retry_rebind: | 636 | retry_rebind: |
678 | nlm_rebind_host(req->a_host); | 637 | nlm_rebind_host(req->a_host); |
@@ -682,6 +641,7 @@ die: | |||
682 | 641 | ||
683 | static const struct rpc_call_ops nlmclnt_unlock_ops = { | 642 | static const struct rpc_call_ops nlmclnt_unlock_ops = { |
684 | .rpc_call_done = nlmclnt_unlock_callback, | 643 | .rpc_call_done = nlmclnt_unlock_callback, |
644 | .rpc_release = nlmclnt_rpc_release, | ||
685 | }; | 645 | }; |
686 | 646 | ||
687 | /* | 647 | /* |
@@ -703,20 +663,15 @@ static int nlmclnt_cancel(struct nlm_host *host, int block, struct file_lock *fl | |||
703 | recalc_sigpending(); | 663 | recalc_sigpending(); |
704 | spin_unlock_irqrestore(¤t->sighand->siglock, flags); | 664 | spin_unlock_irqrestore(¤t->sighand->siglock, flags); |
705 | 665 | ||
706 | req = nlmclnt_alloc_call(); | 666 | req = nlm_alloc_call(nlm_get_host(host)); |
707 | if (!req) | 667 | if (!req) |
708 | return -ENOMEM; | 668 | return -ENOMEM; |
709 | req->a_host = host; | ||
710 | req->a_flags = RPC_TASK_ASYNC; | 669 | req->a_flags = RPC_TASK_ASYNC; |
711 | 670 | ||
712 | nlmclnt_setlockargs(req, fl); | 671 | nlmclnt_setlockargs(req, fl); |
713 | req->a_args.block = block; | 672 | req->a_args.block = block; |
714 | 673 | ||
715 | status = nlmclnt_async_call(req, NLMPROC_CANCEL, &nlmclnt_cancel_ops); | 674 | status = nlm_async_call(req, NLMPROC_CANCEL, &nlmclnt_cancel_ops); |
716 | if (status < 0) { | ||
717 | nlmclnt_release_lockargs(req); | ||
718 | kfree(req); | ||
719 | } | ||
720 | 675 | ||
721 | spin_lock_irqsave(¤t->sighand->siglock, flags); | 676 | spin_lock_irqsave(¤t->sighand->siglock, flags); |
722 | current->blocked = oldset; | 677 | current->blocked = oldset; |
@@ -757,9 +712,6 @@ static void nlmclnt_cancel_callback(struct rpc_task *task, void *data) | |||
757 | } | 712 | } |
758 | 713 | ||
759 | die: | 714 | die: |
760 | nlm_release_host(req->a_host); | ||
761 | nlmclnt_release_lockargs(req); | ||
762 | kfree(req); | ||
763 | return; | 715 | return; |
764 | 716 | ||
765 | retry_cancel: | 717 | retry_cancel: |
@@ -773,6 +725,7 @@ retry_cancel: | |||
773 | 725 | ||
774 | static const struct rpc_call_ops nlmclnt_cancel_ops = { | 726 | static const struct rpc_call_ops nlmclnt_cancel_ops = { |
775 | .rpc_call_done = nlmclnt_cancel_callback, | 727 | .rpc_call_done = nlmclnt_cancel_callback, |
728 | .rpc_release = nlmclnt_rpc_release, | ||
776 | }; | 729 | }; |
777 | 730 | ||
778 | /* | 731 | /* |
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) | |||
480 | struct nlm_host *host; | 480 | struct nlm_host *host; |
481 | struct nlm_rqst *call; | 481 | struct nlm_rqst *call; |
482 | 482 | ||
483 | if (!(call = nlmclnt_alloc_call())) | 483 | host = nlmsvc_lookup_host(rqstp); |
484 | if (host == NULL) | ||
484 | return rpc_system_err; | 485 | return rpc_system_err; |
485 | 486 | ||
486 | host = nlmsvc_lookup_host(rqstp); | 487 | call = nlm_alloc_call(host); |
487 | if (!host) { | 488 | if (call == NULL) |
488 | kfree(call); | ||
489 | return rpc_system_err; | 489 | return rpc_system_err; |
490 | } | 490 | |
491 | 491 | ||
492 | call->a_flags = RPC_TASK_ASYNC; | 492 | call->a_flags = RPC_TASK_ASYNC; |
493 | call->a_host = host; | ||
494 | memcpy(&call->a_args, resp, sizeof(*resp)); | 493 | memcpy(&call->a_args, resp, sizeof(*resp)); |
495 | 494 | ||
496 | if (nlmsvc_async_call(call, proc, &nlm4svc_callback_ops) < 0) | 495 | if (nlm_async_call(call, proc, &nlm4svc_callback_ops) < 0) |
497 | goto error; | 496 | return rpc_system_err; |
498 | |||
499 | return rpc_success; | 497 | return rpc_success; |
500 | error: | ||
501 | kfree(call); | ||
502 | nlm_release_host(host); | ||
503 | return rpc_system_err; | ||
504 | } | 498 | } |
505 | 499 | ||
506 | static void nlm4svc_callback_exit(struct rpc_task *task, void *data) | 500 | static void nlm4svc_callback_exit(struct rpc_task *task, void *data) |
507 | { | 501 | { |
508 | struct nlm_rqst *call = data; | 502 | dprintk("lockd: %4d callback returned %d\n", task->tk_pid, |
503 | -task->tk_status); | ||
504 | } | ||
509 | 505 | ||
510 | if (task->tk_status < 0) { | 506 | static void nlm4svc_callback_release(void *data) |
511 | dprintk("lockd: %4d callback failed (errno = %d)\n", | 507 | { |
512 | task->tk_pid, -task->tk_status); | 508 | nlm_release_call(data); |
513 | } | ||
514 | nlm_release_host(call->a_host); | ||
515 | kfree(call); | ||
516 | } | 509 | } |
517 | 510 | ||
518 | static const struct rpc_call_ops nlm4svc_callback_ops = { | 511 | static const struct rpc_call_ops nlm4svc_callback_ops = { |
519 | .rpc_call_done = nlm4svc_callback_exit, | 512 | .rpc_call_done = nlm4svc_callback_exit, |
513 | .rpc_release = nlm4svc_callback_release, | ||
520 | }; | 514 | }; |
521 | 515 | ||
522 | /* | 516 | /* |
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) | |||
117 | (long long)lock->fl.fl_start, | 117 | (long long)lock->fl.fl_start, |
118 | (long long)lock->fl.fl_end, lock->fl.fl_type); | 118 | (long long)lock->fl.fl_end, lock->fl.fl_type); |
119 | for (head = &nlm_blocked; (block = *head) != 0; head = &block->b_next) { | 119 | for (head = &nlm_blocked; (block = *head) != 0; head = &block->b_next) { |
120 | fl = &block->b_call.a_args.lock.fl; | 120 | fl = &block->b_call->a_args.lock.fl; |
121 | dprintk("lockd: check f=%p pd=%d %Ld-%Ld ty=%d cookie=%s\n", | 121 | dprintk("lockd: check f=%p pd=%d %Ld-%Ld ty=%d cookie=%s\n", |
122 | block->b_file, fl->fl_pid, | 122 | block->b_file, fl->fl_pid, |
123 | (long long)fl->fl_start, | 123 | (long long)fl->fl_start, |
124 | (long long)fl->fl_end, fl->fl_type, | 124 | (long long)fl->fl_end, fl->fl_type, |
125 | nlmdbg_cookie2a(&block->b_call.a_args.cookie)); | 125 | nlmdbg_cookie2a(&block->b_call->a_args.cookie)); |
126 | if (block->b_file == file && nlm_compare_locks(fl, &lock->fl)) { | 126 | if (block->b_file == file && nlm_compare_locks(fl, &lock->fl)) { |
127 | if (remove) { | 127 | if (remove) { |
128 | *head = block->b_next; | 128 | *head = block->b_next; |
@@ -156,7 +156,7 @@ nlmsvc_find_block(struct nlm_cookie *cookie, struct sockaddr_in *sin) | |||
156 | for (block = nlm_blocked; block; block = block->b_next) { | 156 | for (block = nlm_blocked; block; block = block->b_next) { |
157 | dprintk("cookie: head of blocked queue %p, block %p\n", | 157 | dprintk("cookie: head of blocked queue %p, block %p\n", |
158 | nlm_blocked, block); | 158 | nlm_blocked, block); |
159 | if (nlm_cookie_match(&block->b_call.a_args.cookie,cookie) | 159 | if (nlm_cookie_match(&block->b_call->a_args.cookie,cookie) |
160 | && nlm_cmp_addr(sin, &block->b_host->h_addr)) | 160 | && nlm_cmp_addr(sin, &block->b_host->h_addr)) |
161 | break; | 161 | break; |
162 | } | 162 | } |
@@ -182,28 +182,30 @@ nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_file *file, | |||
182 | { | 182 | { |
183 | struct nlm_block *block; | 183 | struct nlm_block *block; |
184 | struct nlm_host *host; | 184 | struct nlm_host *host; |
185 | struct nlm_rqst *call; | 185 | struct nlm_rqst *call = NULL; |
186 | 186 | ||
187 | /* Create host handle for callback */ | 187 | /* Create host handle for callback */ |
188 | host = nlmsvc_lookup_host(rqstp); | 188 | host = nlmsvc_lookup_host(rqstp); |
189 | if (host == NULL) | 189 | if (host == NULL) |
190 | return NULL; | 190 | return NULL; |
191 | 191 | ||
192 | call = nlm_alloc_call(host); | ||
193 | if (call == NULL) | ||
194 | return NULL; | ||
195 | |||
192 | /* Allocate memory for block, and initialize arguments */ | 196 | /* Allocate memory for block, and initialize arguments */ |
193 | if (!(block = (struct nlm_block *) kmalloc(sizeof(*block), GFP_KERNEL))) | 197 | block = kzalloc(sizeof(*block), GFP_KERNEL); |
198 | if (block == NULL) | ||
194 | goto failed; | 199 | goto failed; |
195 | memset(block, 0, sizeof(*block)); | ||
196 | locks_init_lock(&block->b_call.a_args.lock.fl); | ||
197 | locks_init_lock(&block->b_call.a_res.lock.fl); | ||
198 | kref_init(&block->b_count); | 200 | kref_init(&block->b_count); |
199 | 201 | ||
200 | if (!nlmsvc_setgrantargs(&block->b_call, lock)) | 202 | if (!nlmsvc_setgrantargs(call, lock)) |
201 | goto failed_free; | 203 | goto failed_free; |
202 | 204 | ||
203 | /* Set notifier function for VFS, and init args */ | 205 | /* Set notifier function for VFS, and init args */ |
204 | block->b_call.a_args.lock.fl.fl_flags |= FL_SLEEP; | 206 | call->a_args.lock.fl.fl_flags |= FL_SLEEP; |
205 | block->b_call.a_args.lock.fl.fl_lmops = &nlmsvc_lock_operations; | 207 | call->a_args.lock.fl.fl_lmops = &nlmsvc_lock_operations; |
206 | block->b_call.a_args.cookie = *cookie; /* see above */ | 208 | call->a_args.cookie = *cookie; /* see above */ |
207 | 209 | ||
208 | dprintk("lockd: created block %p...\n", block); | 210 | dprintk("lockd: created block %p...\n", block); |
209 | 211 | ||
@@ -217,16 +219,16 @@ nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_file *file, | |||
217 | file->f_blocks = block; | 219 | file->f_blocks = block; |
218 | 220 | ||
219 | /* Set up RPC arguments for callback */ | 221 | /* Set up RPC arguments for callback */ |
220 | call = &block->b_call; | 222 | block->b_call = call; |
221 | call->a_host = host; | ||
222 | call->a_flags = RPC_TASK_ASYNC; | 223 | call->a_flags = RPC_TASK_ASYNC; |
224 | call->a_block = block; | ||
223 | 225 | ||
224 | return block; | 226 | return block; |
225 | 227 | ||
226 | failed_free: | 228 | failed_free: |
227 | kfree(block); | 229 | kfree(block); |
228 | failed: | 230 | failed: |
229 | nlm_release_host(host); | 231 | nlm_release_call(call); |
230 | return NULL; | 232 | return NULL; |
231 | } | 233 | } |
232 | 234 | ||
@@ -242,7 +244,7 @@ static int nlmsvc_unlink_block(struct nlm_block *block) | |||
242 | dprintk("lockd: unlinking block %p...\n", block); | 244 | dprintk("lockd: unlinking block %p...\n", block); |
243 | 245 | ||
244 | /* Remove block from list */ | 246 | /* Remove block from list */ |
245 | status = posix_unblock_lock(block->b_file->f_file, &block->b_call.a_args.lock.fl); | 247 | status = posix_unblock_lock(block->b_file->f_file, &block->b_call->a_args.lock.fl); |
246 | nlmsvc_remove_block(block); | 248 | nlmsvc_remove_block(block); |
247 | return status; | 249 | return status; |
248 | } | 250 | } |
@@ -263,9 +265,8 @@ static void nlmsvc_free_block(struct kref *kref) | |||
263 | } | 265 | } |
264 | } | 266 | } |
265 | 267 | ||
266 | if (block->b_host) | 268 | nlmsvc_freegrantargs(block->b_call); |
267 | nlm_release_host(block->b_host); | 269 | nlm_release_call(block->b_call); |
268 | nlmsvc_freegrantargs(&block->b_call); | ||
269 | kfree(block); | 270 | kfree(block); |
270 | } | 271 | } |
271 | 272 | ||
@@ -316,10 +317,8 @@ static int nlmsvc_setgrantargs(struct nlm_rqst *call, struct nlm_lock *lock) | |||
316 | 317 | ||
317 | if (lock->oh.len > NLMCLNT_OHSIZE) { | 318 | if (lock->oh.len > NLMCLNT_OHSIZE) { |
318 | void *data = kmalloc(lock->oh.len, GFP_KERNEL); | 319 | void *data = kmalloc(lock->oh.len, GFP_KERNEL); |
319 | if (!data) { | 320 | if (!data) |
320 | nlmsvc_freegrantargs(call); | ||
321 | return 0; | 321 | return 0; |
322 | } | ||
323 | call->a_args.lock.oh.data = (u8 *) data; | 322 | call->a_args.lock.oh.data = (u8 *) data; |
324 | } | 323 | } |
325 | 324 | ||
@@ -329,17 +328,8 @@ static int nlmsvc_setgrantargs(struct nlm_rqst *call, struct nlm_lock *lock) | |||
329 | 328 | ||
330 | static void nlmsvc_freegrantargs(struct nlm_rqst *call) | 329 | static void nlmsvc_freegrantargs(struct nlm_rqst *call) |
331 | { | 330 | { |
332 | struct file_lock *fl = &call->a_args.lock.fl; | 331 | if (call->a_args.lock.oh.data != call->a_owner) |
333 | /* | ||
334 | * Check whether we allocated memory for the owner. | ||
335 | */ | ||
336 | if (call->a_args.lock.oh.data != (u8 *) call->a_owner) { | ||
337 | kfree(call->a_args.lock.oh.data); | 332 | kfree(call->a_args.lock.oh.data); |
338 | } | ||
339 | if (fl->fl_ops && fl->fl_ops->fl_release_private) | ||
340 | fl->fl_ops->fl_release_private(fl); | ||
341 | if (fl->fl_lmops && fl->fl_lmops->fl_release_private) | ||
342 | fl->fl_lmops->fl_release_private(fl); | ||
343 | } | 333 | } |
344 | 334 | ||
345 | /* | 335 | /* |
@@ -371,9 +361,9 @@ again: | |||
371 | block = nlmsvc_lookup_block(file, lock, 0); | 361 | block = nlmsvc_lookup_block(file, lock, 0); |
372 | if (block == NULL) { | 362 | if (block == NULL) { |
373 | if (newblock != NULL) | 363 | if (newblock != NULL) |
374 | lock = &newblock->b_call.a_args.lock; | 364 | lock = &newblock->b_call->a_args.lock; |
375 | } else | 365 | } else |
376 | lock = &block->b_call.a_args.lock; | 366 | lock = &block->b_call->a_args.lock; |
377 | 367 | ||
378 | error = posix_lock_file(file->f_file, &lock->fl); | 368 | error = posix_lock_file(file->f_file, &lock->fl); |
379 | lock->fl.fl_flags &= ~FL_SLEEP; | 369 | lock->fl.fl_flags &= ~FL_SLEEP; |
@@ -523,7 +513,7 @@ nlmsvc_notify_blocked(struct file_lock *fl) | |||
523 | 513 | ||
524 | dprintk("lockd: VFS unblock notification for block %p\n", fl); | 514 | dprintk("lockd: VFS unblock notification for block %p\n", fl); |
525 | for (bp = &nlm_blocked; (block = *bp) != 0; bp = &block->b_next) { | 515 | for (bp = &nlm_blocked; (block = *bp) != 0; bp = &block->b_next) { |
526 | if (nlm_compare_locks(&block->b_call.a_args.lock.fl, fl)) { | 516 | if (nlm_compare_locks(&block->b_call->a_args.lock.fl, fl)) { |
527 | nlmsvc_insert_block(block, 0); | 517 | nlmsvc_insert_block(block, 0); |
528 | svc_wake_up(block->b_daemon); | 518 | svc_wake_up(block->b_daemon); |
529 | return; | 519 | return; |
@@ -558,7 +548,7 @@ static void | |||
558 | nlmsvc_grant_blocked(struct nlm_block *block) | 548 | nlmsvc_grant_blocked(struct nlm_block *block) |
559 | { | 549 | { |
560 | struct nlm_file *file = block->b_file; | 550 | struct nlm_file *file = block->b_file; |
561 | struct nlm_lock *lock = &block->b_call.a_args.lock; | 551 | struct nlm_lock *lock = &block->b_call->a_args.lock; |
562 | int error; | 552 | int error; |
563 | 553 | ||
564 | dprintk("lockd: grant blocked lock %p\n", block); | 554 | dprintk("lockd: grant blocked lock %p\n", block); |
@@ -606,7 +596,7 @@ callback: | |||
606 | 596 | ||
607 | /* Call the client */ | 597 | /* Call the client */ |
608 | kref_get(&block->b_count); | 598 | kref_get(&block->b_count); |
609 | if (nlmsvc_async_call(&block->b_call, NLMPROC_GRANTED_MSG, | 599 | if (nlm_async_call(block->b_call, NLMPROC_GRANTED_MSG, |
610 | &nlmsvc_grant_ops) < 0) | 600 | &nlmsvc_grant_ops) < 0) |
611 | nlmsvc_release_block(block); | 601 | nlmsvc_release_block(block); |
612 | out_unlock: | 602 | out_unlock: |
@@ -624,7 +614,7 @@ out_unlock: | |||
624 | static void nlmsvc_grant_callback(struct rpc_task *task, void *data) | 614 | static void nlmsvc_grant_callback(struct rpc_task *task, void *data) |
625 | { | 615 | { |
626 | struct nlm_rqst *call = data; | 616 | struct nlm_rqst *call = data; |
627 | struct nlm_block *block = container_of(call, struct nlm_block, b_call); | 617 | struct nlm_block *block = call->a_block; |
628 | unsigned long timeout; | 618 | unsigned long timeout; |
629 | 619 | ||
630 | dprintk("lockd: GRANT_MSG RPC callback\n"); | 620 | 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) | |||
505 | struct nlm_host *host; | 505 | struct nlm_host *host; |
506 | struct nlm_rqst *call; | 506 | struct nlm_rqst *call; |
507 | 507 | ||
508 | if (!(call = nlmclnt_alloc_call())) | 508 | host = nlmsvc_lookup_host(rqstp); |
509 | if (host == NULL) | ||
509 | return rpc_system_err; | 510 | return rpc_system_err; |
510 | 511 | ||
511 | host = nlmsvc_lookup_host(rqstp); | 512 | call = nlm_alloc_call(host); |
512 | if (!host) { | 513 | if (call == NULL) |
513 | kfree(call); | ||
514 | return rpc_system_err; | 514 | return rpc_system_err; |
515 | } | ||
516 | 515 | ||
517 | call->a_flags = RPC_TASK_ASYNC; | 516 | call->a_flags = RPC_TASK_ASYNC; |
518 | call->a_host = host; | ||
519 | memcpy(&call->a_args, resp, sizeof(*resp)); | 517 | memcpy(&call->a_args, resp, sizeof(*resp)); |
520 | 518 | ||
521 | if (nlmsvc_async_call(call, proc, &nlmsvc_callback_ops) < 0) | 519 | if (nlm_async_call(call, proc, &nlmsvc_callback_ops) < 0) |
522 | goto error; | 520 | return rpc_system_err; |
523 | |||
524 | return rpc_success; | 521 | return rpc_success; |
525 | error: | ||
526 | nlm_release_host(host); | ||
527 | kfree(call); | ||
528 | return rpc_system_err; | ||
529 | } | 522 | } |
530 | 523 | ||
531 | static void nlmsvc_callback_exit(struct rpc_task *task, void *data) | 524 | static void nlmsvc_callback_exit(struct rpc_task *task, void *data) |
532 | { | 525 | { |
533 | struct nlm_rqst *call = data; | 526 | dprintk("lockd: %4d callback returned %d\n", task->tk_pid, |
527 | -task->tk_status); | ||
528 | } | ||
534 | 529 | ||
535 | if (task->tk_status < 0) { | 530 | static void nlmsvc_callback_release(void *data) |
536 | dprintk("lockd: %4d callback failed (errno = %d)\n", | 531 | { |
537 | task->tk_pid, -task->tk_status); | 532 | nlm_release_call(data); |
538 | } | ||
539 | nlm_release_host(call->a_host); | ||
540 | kfree(call); | ||
541 | } | 533 | } |
542 | 534 | ||
543 | static const struct rpc_call_ops nlmsvc_callback_ops = { | 535 | static const struct rpc_call_ops nlmsvc_callback_ops = { |
544 | .rpc_call_done = nlmsvc_callback_exit, | 536 | .rpc_call_done = nlmsvc_callback_exit, |
537 | .rpc_release = nlmsvc_callback_release, | ||
545 | }; | 538 | }; |
546 | 539 | ||
547 | /* | 540 | /* |