diff options
Diffstat (limited to 'fs/lockd/svclock.c')
-rw-r--r-- | fs/lockd/svclock.c | 56 |
1 files changed, 53 insertions, 3 deletions
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c index 20caeceffb14..3c7dd956d9c1 100644 --- a/fs/lockd/svclock.c +++ b/fs/lockd/svclock.c | |||
@@ -43,6 +43,8 @@ static void nlmsvc_release_block(struct nlm_block *block); | |||
43 | static void nlmsvc_insert_block(struct nlm_block *block, unsigned long); | 43 | static void nlmsvc_insert_block(struct nlm_block *block, unsigned long); |
44 | static int nlmsvc_remove_block(struct nlm_block *block); | 44 | static int nlmsvc_remove_block(struct nlm_block *block); |
45 | 45 | ||
46 | static int nlmsvc_setgrantargs(struct nlm_rqst *call, struct nlm_lock *lock); | ||
47 | static void nlmsvc_freegrantargs(struct nlm_rqst *call); | ||
46 | static const struct rpc_call_ops nlmsvc_grant_ops; | 48 | static const struct rpc_call_ops nlmsvc_grant_ops; |
47 | 49 | ||
48 | /* | 50 | /* |
@@ -196,7 +198,7 @@ nlmsvc_create_block(struct svc_rqst *rqstp, struct nlm_file *file, | |||
196 | locks_init_lock(&block->b_call.a_res.lock.fl); | 198 | locks_init_lock(&block->b_call.a_res.lock.fl); |
197 | kref_init(&block->b_count); | 199 | kref_init(&block->b_count); |
198 | 200 | ||
199 | if (!nlmclnt_setgrantargs(&block->b_call, lock)) | 201 | if (!nlmsvc_setgrantargs(&block->b_call, lock)) |
200 | goto failed_free; | 202 | goto failed_free; |
201 | 203 | ||
202 | /* Set notifier function for VFS, and init args */ | 204 | /* Set notifier function for VFS, and init args */ |
@@ -264,7 +266,7 @@ static void nlmsvc_free_block(struct kref *kref) | |||
264 | 266 | ||
265 | if (block->b_host) | 267 | if (block->b_host) |
266 | nlm_release_host(block->b_host); | 268 | nlm_release_host(block->b_host); |
267 | nlmclnt_freegrantargs(&block->b_call); | 269 | nlmsvc_freegrantargs(&block->b_call); |
268 | kfree(block); | 270 | kfree(block); |
269 | } | 271 | } |
270 | 272 | ||
@@ -299,6 +301,49 @@ nlmsvc_traverse_blocks(struct nlm_host *host, struct nlm_file *file, int action) | |||
299 | } | 301 | } |
300 | 302 | ||
301 | /* | 303 | /* |
304 | * Initialize arguments for GRANTED call. The nlm_rqst structure | ||
305 | * has been cleared already. | ||
306 | */ | ||
307 | static int nlmsvc_setgrantargs(struct nlm_rqst *call, struct nlm_lock *lock) | ||
308 | { | ||
309 | locks_copy_lock(&call->a_args.lock.fl, &lock->fl); | ||
310 | memcpy(&call->a_args.lock.fh, &lock->fh, sizeof(call->a_args.lock.fh)); | ||
311 | call->a_args.lock.caller = system_utsname.nodename; | ||
312 | call->a_args.lock.oh.len = lock->oh.len; | ||
313 | |||
314 | /* set default data area */ | ||
315 | call->a_args.lock.oh.data = call->a_owner; | ||
316 | call->a_args.lock.svid = lock->fl.fl_pid; | ||
317 | |||
318 | if (lock->oh.len > NLMCLNT_OHSIZE) { | ||
319 | void *data = kmalloc(lock->oh.len, GFP_KERNEL); | ||
320 | if (!data) { | ||
321 | nlmsvc_freegrantargs(call); | ||
322 | return 0; | ||
323 | } | ||
324 | call->a_args.lock.oh.data = (u8 *) data; | ||
325 | } | ||
326 | |||
327 | memcpy(call->a_args.lock.oh.data, lock->oh.data, lock->oh.len); | ||
328 | return 1; | ||
329 | } | ||
330 | |||
331 | static void nlmsvc_freegrantargs(struct nlm_rqst *call) | ||
332 | { | ||
333 | struct file_lock *fl = &call->a_args.lock.fl; | ||
334 | /* | ||
335 | * Check whether we allocated memory for the owner. | ||
336 | */ | ||
337 | if (call->a_args.lock.oh.data != (u8 *) call->a_owner) { | ||
338 | kfree(call->a_args.lock.oh.data); | ||
339 | } | ||
340 | if (fl->fl_ops && fl->fl_ops->fl_release_private) | ||
341 | fl->fl_ops->fl_release_private(fl); | ||
342 | if (fl->fl_lmops && fl->fl_lmops->fl_release_private) | ||
343 | fl->fl_lmops->fl_release_private(fl); | ||
344 | } | ||
345 | |||
346 | /* | ||
302 | * Attempt to establish a lock, and if it can't be granted, block it | 347 | * Attempt to establish a lock, and if it can't be granted, block it |
303 | * if required. | 348 | * if required. |
304 | */ | 349 | */ |
@@ -600,11 +645,16 @@ static void nlmsvc_grant_callback(struct rpc_task *task, void *data) | |||
600 | } | 645 | } |
601 | nlmsvc_insert_block(block, timeout); | 646 | nlmsvc_insert_block(block, timeout); |
602 | svc_wake_up(block->b_daemon); | 647 | svc_wake_up(block->b_daemon); |
603 | nlmsvc_release_block(block); | 648 | } |
649 | |||
650 | void nlmsvc_grant_release(void *data) | ||
651 | { | ||
652 | nlmsvc_release_block(data); | ||
604 | } | 653 | } |
605 | 654 | ||
606 | static const struct rpc_call_ops nlmsvc_grant_ops = { | 655 | static const struct rpc_call_ops nlmsvc_grant_ops = { |
607 | .rpc_call_done = nlmsvc_grant_callback, | 656 | .rpc_call_done = nlmsvc_grant_callback, |
657 | .rpc_release = nlmsvc_grant_release, | ||
608 | }; | 658 | }; |
609 | 659 | ||
610 | /* | 660 | /* |