From 789d95e669710036adc1734938e57ceb3b3d46bb Mon Sep 17 00:00:00 2001 From: Neil Brown Date: Fri, 14 Mar 2003 02:11:42 -0800 Subject: [PATCH] [PATCH] kNFSd: Fix deadlock problem in lockd. nlmsvc_lock calls nlmsvc_create_block with file->f_sema held. nlmsvc_create_block calls nlmclnt_lookup_host which might call nlm_gc_hosts which might, eventually, try to claim file->f_sema for the same file -> deadlock. nlmsvc_create_block does not need any protection under any lock as lockd is single-threaded and _create_block only plays with internal data structures. So we release the f_sema before calling in, and make sure it gets claimed again afterwards. --- fs/lockd/svclock.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c index 8a827b109c937..dfb16a579c995 100644 --- a/fs/lockd/svclock.c +++ b/fs/lockd/svclock.c @@ -305,8 +305,6 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file, (long long)lock->fl.fl_end, wait); - /* Lock file against concurrent access */ - down(&file->f_sema); /* Get existing block (in case client is busy-waiting) */ block = nlmsvc_lookup_block(file, lock, 0); @@ -314,6 +312,9 @@ nlmsvc_lock(struct svc_rqst *rqstp, struct nlm_file *file, lock->fl.fl_flags |= FL_LOCKD; again: + /* Lock file against concurrent access */ + down(&file->f_sema); + if (!(conflock = posix_test_lock(&file->f_file, &lock->fl))) { error = posix_lock_file(&file->f_file, &lock->fl); @@ -346,7 +347,10 @@ again: /* If we don't have a block, create and initialize it. Then * retry because we may have slept in kmalloc. */ + /* We have to release f_sema as nlmsvc_create_block may try to + * to claim it while doing host garbage collection */ if (block == NULL) { + up(&file->f_sema); dprintk("lockd: blocking on this lock (allocating).\n"); if (!(block = nlmsvc_create_block(rqstp, file, lock, cookie))) return nlm_lck_denied_nolocks; -- 2.53.0