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 | |
| 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>
| -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 | ||||
| -rw-r--r-- | include/linux/lockd/lockd.h | 10 |
5 files changed, 135 insertions, 203 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 | /* |
diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h index cb9933d04091..e7ba8110d579 100644 --- a/include/linux/lockd/lockd.h +++ b/include/linux/lockd/lockd.h | |||
| @@ -86,8 +86,9 @@ struct nlm_rqst { | |||
| 86 | struct nlm_host * a_host; /* host handle */ | 86 | struct nlm_host * a_host; /* host handle */ |
| 87 | struct nlm_args a_args; /* arguments */ | 87 | struct nlm_args a_args; /* arguments */ |
| 88 | struct nlm_res a_res; /* result */ | 88 | struct nlm_res a_res; /* result */ |
| 89 | struct nlm_block * a_block; | ||
| 89 | unsigned int a_retries; /* Retry count */ | 90 | unsigned int a_retries; /* Retry count */ |
| 90 | char a_owner[NLMCLNT_OHSIZE]; | 91 | u8 a_owner[NLMCLNT_OHSIZE]; |
| 91 | }; | 92 | }; |
| 92 | 93 | ||
| 93 | /* | 94 | /* |
| @@ -115,7 +116,7 @@ struct nlm_block { | |||
| 115 | struct kref b_count; /* Reference count */ | 116 | struct kref b_count; /* Reference count */ |
| 116 | struct nlm_block * b_next; /* linked list (all blocks) */ | 117 | struct nlm_block * b_next; /* linked list (all blocks) */ |
| 117 | struct nlm_block * b_fnext; /* linked list (per file) */ | 118 | struct nlm_block * b_fnext; /* linked list (per file) */ |
| 118 | struct nlm_rqst b_call; /* RPC args & callback info */ | 119 | struct nlm_rqst * b_call; /* RPC args & callback info */ |
| 119 | struct svc_serv * b_daemon; /* NLM service */ | 120 | struct svc_serv * b_daemon; /* NLM service */ |
| 120 | struct nlm_host * b_host; /* host handle for RPC clnt */ | 121 | struct nlm_host * b_host; /* host handle for RPC clnt */ |
| 121 | unsigned long b_when; /* next re-xmit */ | 122 | unsigned long b_when; /* next re-xmit */ |
| @@ -147,7 +148,9 @@ extern unsigned long nlmsvc_timeout; | |||
| 147 | /* | 148 | /* |
| 148 | * Lockd client functions | 149 | * Lockd client functions |
| 149 | */ | 150 | */ |
| 150 | struct nlm_rqst * nlmclnt_alloc_call(void); | 151 | struct nlm_rqst * nlm_alloc_call(struct nlm_host *host); |
| 152 | void nlm_release_call(struct nlm_rqst *); | ||
| 153 | int nlm_async_call(struct nlm_rqst *, u32, const struct rpc_call_ops *); | ||
| 151 | struct nlm_wait * nlmclnt_prepare_block(struct nlm_host *host, struct file_lock *fl); | 154 | struct nlm_wait * nlmclnt_prepare_block(struct nlm_host *host, struct file_lock *fl); |
| 152 | void nlmclnt_finish_block(struct nlm_wait *block); | 155 | void nlmclnt_finish_block(struct nlm_wait *block); |
| 153 | int nlmclnt_block(struct nlm_wait *block, struct nlm_rqst *req, long timeout); | 156 | int nlmclnt_block(struct nlm_wait *block, struct nlm_rqst *req, long timeout); |
| @@ -172,7 +175,6 @@ extern struct nlm_host *nlm_find_client(void); | |||
| 172 | /* | 175 | /* |
| 173 | * Server-side lock handling | 176 | * Server-side lock handling |
| 174 | */ | 177 | */ |
| 175 | int nlmsvc_async_call(struct nlm_rqst *, u32, const struct rpc_call_ops *); | ||
| 176 | u32 nlmsvc_lock(struct svc_rqst *, struct nlm_file *, | 178 | u32 nlmsvc_lock(struct svc_rqst *, struct nlm_file *, |
| 177 | struct nlm_lock *, int, struct nlm_cookie *); | 179 | struct nlm_lock *, int, struct nlm_cookie *); |
| 178 | u32 nlmsvc_unlock(struct nlm_file *, struct nlm_lock *); | 180 | u32 nlmsvc_unlock(struct nlm_file *, struct nlm_lock *); |
