aboutsummaryrefslogtreecommitdiffstats
path: root/fs/lockd/svclock.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/lockd/svclock.c')
-rw-r--r--fs/lockd/svclock.c34
1 files changed, 11 insertions, 23 deletions
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c
index b7a8174fd1dc..0d7398e3804f 100644
--- a/fs/lockd/svclock.c
+++ b/fs/lockd/svclock.c
@@ -365,7 +365,7 @@ __be32
365nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file, 365nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
366 struct nlm_lock *lock, int wait, struct nlm_cookie *cookie) 366 struct nlm_lock *lock, int wait, struct nlm_cookie *cookie)
367{ 367{
368 struct nlm_block *block, *newblock = NULL; 368 struct nlm_block *block = NULL;
369 int error; 369 int error;
370 __be32 ret; 370 __be32 ret;
371 371
@@ -378,17 +378,20 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file,
378 wait); 378 wait);
379 379
380 380
381 lock->fl.fl_flags &= ~FL_SLEEP;
382again:
383 /* Lock file against concurrent access */ 381 /* Lock file against concurrent access */
384 mutex_lock(&file->f_mutex); 382 mutex_lock(&file->f_mutex);
385 /* Get existing block (in case client is busy-waiting) */ 383 /* Get existing block (in case client is busy-waiting)
384 * or create new block
385 */
386 block = nlmsvc_lookup_block(file, lock); 386 block = nlmsvc_lookup_block(file, lock);
387 if (block == NULL) { 387 if (block == NULL) {
388 if (newblock != NULL) 388 block = nlmsvc_create_block(rqstp, file, lock, cookie);
389 lock = &newblock->b_call->a_args.lock; 389 ret = nlm_lck_denied_nolocks;
390 } else 390 if (block == NULL)
391 goto out;
391 lock = &block->b_call->a_args.lock; 392 lock = &block->b_call->a_args.lock;
393 } else
394 lock->fl.fl_flags &= ~FL_SLEEP;
392 395
393 error = posix_lock_file(file->f_file, &lock->fl, NULL); 396 error = posix_lock_file(file->f_file, &lock->fl, NULL);
394 lock->fl.fl_flags &= ~FL_SLEEP; 397 lock->fl.fl_flags &= ~FL_SLEEP;
@@ -414,26 +417,11 @@ again:
414 goto out; 417 goto out;
415 418
416 ret = nlm_lck_blocked; 419 ret = nlm_lck_blocked;
417 if (block != NULL)
418 goto out;
419
420 /* If we don't have a block, create and initialize it. Then
421 * retry because we may have slept in kmalloc. */
422 /* We have to release f_mutex as nlmsvc_create_block may try to
423 * to claim it while doing host garbage collection */
424 if (newblock == NULL) {
425 mutex_unlock(&file->f_mutex);
426 dprintk("lockd: blocking on this lock (allocating).\n");
427 if (!(newblock = nlmsvc_create_block(rqstp, file, lock, cookie)))
428 return nlm_lck_denied_nolocks;
429 goto again;
430 }
431 420
432 /* Append to list of blocked */ 421 /* Append to list of blocked */
433 nlmsvc_insert_block(newblock, NLM_NEVER); 422 nlmsvc_insert_block(block, NLM_NEVER);
434out: 423out:
435 mutex_unlock(&file->f_mutex); 424 mutex_unlock(&file->f_mutex);
436 nlmsvc_release_block(newblock);
437 nlmsvc_release_block(block); 425 nlmsvc_release_block(block);
438 dprintk("lockd: nlmsvc_lock returned %u\n", ret); 426 dprintk("lockd: nlmsvc_lock returned %u\n", ret);
439 return ret; 427 return ret;