aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2006-03-20 13:44:45 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2006-03-20 13:44:45 -0500
commit92737230dd3f1478033819d4bc20339f8da852da (patch)
tree27bc7804a077a29b7614c698bb02632dc4ce228e /fs
parente4cd038a45a46ffbe06a1a72f3f15246e5b041ca (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')
-rw-r--r--fs/lockd/clntproc.c195
-rw-r--r--fs/lockd/svc4proc.c34
-rw-r--r--fs/lockd/svclock.c66
-rw-r--r--fs/lockd/svcproc.c33
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)
152int 152int
153nlmclnt_proc(struct inode *inode, int cmd, struct file_lock *fl) 153nlmclnt_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(&current->sighand->siglock, flags); 183 spin_lock_irqsave(&current->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(&current->blocked); /* Mask all signals */ 191 sigfillset(&current->blocked); /* Mask all signals */
199 recalc_sigpending(); 192 recalc_sigpending();
200 spin_unlock_irqrestore(&current->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(&current->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(&current->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(&current->sighand->siglock, flags); 212 spin_lock_irqsave(&current->sighand->siglock, flags);
234 current->blocked = oldset; 213 current->blocked = oldset;
235 recalc_sigpending(); 214 recalc_sigpending();
236 spin_unlock_irqrestore(&current->sighand->siglock, flags); 215 spin_unlock_irqrestore(&current->sighand->siglock, flags);
237 216
238done:
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}
243EXPORT_SYMBOL(nlmclnt_proc); 220EXPORT_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 */
248struct nlm_rqst * 228struct nlm_rqst *nlm_alloc_call(struct nlm_host *host)
249nlmclnt_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
249void 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
256static void nlmclnt_rpc_release(void *data)
257{
258 return nlm_release_call(data);
259}
260
268static int nlm_wait_on_grace(wait_queue_head_t *queue) 261static 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 */
364int nlmsvc_async_call(struct nlm_rqst *req, u32 proc, const struct rpc_call_ops *tk_ops) 357int 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
388static 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;
380out_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 413out:
445 return 0; 414 nlm_release_call(req);
415 return status;
446} 416}
447 417
448static void nlmclnt_locks_copy_lock(struct file_lock *new, struct file_lock *fl) 418static 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);
562out: 532out:
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; 611out:
612 nlm_release_call(req);
613 return status;
652} 614}
653 615
654static void nlmclnt_unlock_callback(struct rpc_task *task, void *data) 616static 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);
672die: 634die:
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
683static const struct rpc_call_ops nlmclnt_unlock_ops = { 642static 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(&current->sighand->siglock, flags); 664 spin_unlock_irqrestore(&current->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(&current->sighand->siglock, flags); 676 spin_lock_irqsave(&current->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
759die: 714die:
760 nlm_release_host(req->a_host);
761 nlmclnt_release_lockargs(req);
762 kfree(req);
763 return; 715 return;
764 716
765retry_cancel: 717retry_cancel:
@@ -773,6 +725,7 @@ retry_cancel:
773 725
774static const struct rpc_call_ops nlmclnt_cancel_ops = { 726static 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
506static void nlm4svc_callback_exit(struct rpc_task *task, void *data) 500static 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) { 506static 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
518static const struct rpc_call_ops nlm4svc_callback_ops = { 511static 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
226failed_free: 228failed_free:
227 kfree(block); 229 kfree(block);
228failed: 230failed:
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
330static void nlmsvc_freegrantargs(struct nlm_rqst *call) 329static 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
558nlmsvc_grant_blocked(struct nlm_block *block) 548nlmsvc_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);
612out_unlock: 602out_unlock:
@@ -624,7 +614,7 @@ out_unlock:
624static void nlmsvc_grant_callback(struct rpc_task *task, void *data) 614static 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
531static void nlmsvc_callback_exit(struct rpc_task *task, void *data) 524static 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) { 530static 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
543static const struct rpc_call_ops nlmsvc_callback_ops = { 535static 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/*