blob: 21d497a7e74a18906d2135096af026671499a305 [file] [log] [blame]
From stable-bounces@linux.kernel.org Thu Sep 7 17:10:17 2006
From: Trond Myklebust <Trond.Myklebust@netapp.com>
Date: Thu, 07 Sep 2006 20:09:41 -0400
To: stable@kernel.org
Message-Id: <20060908000941.10655.26648.stgit@lade.trondhjem.org>
Subject: LOCKD: Fix a deadlock in nlm_traverse_files()
From: Trond Myklebust <Trond.Myklebust@netapp.com>
nlm_traverse_files() is not allowed to hold the nlm_file_mutex while calling
nlm_inspect file, since it may end up calling nlm_release_file() when
releaseing the blocks.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
fs/lockd/svcsubs.c | 15 +++++++++------
1 file changed, 9 insertions(+), 6 deletions(-)
--- linux-2.6.17.13.orig/fs/lockd/svcsubs.c
+++ linux-2.6.17.13/fs/lockd/svcsubs.c
@@ -238,19 +238,22 @@ static int
nlm_traverse_files(struct nlm_host *host, int action)
{
struct nlm_file *file, **fp;
- int i;
+ int i, ret = 0;
mutex_lock(&nlm_file_mutex);
for (i = 0; i < FILE_NRHASH; i++) {
fp = nlm_files + i;
while ((file = *fp) != NULL) {
+ file->f_count++;
+ mutex_unlock(&nlm_file_mutex);
+
/* Traverse locks, blocks and shares of this file
* and update file->f_locks count */
- if (nlm_inspect_file(host, file, action)) {
- mutex_unlock(&nlm_file_mutex);
- return 1;
- }
+ if (nlm_inspect_file(host, file, action))
+ ret = 1;
+ mutex_lock(&nlm_file_mutex);
+ file->f_count--;
/* No more references to this file. Let go of it. */
if (!file->f_blocks && !file->f_locks
&& !file->f_shares && !file->f_count) {
@@ -263,7 +266,7 @@ nlm_traverse_files(struct nlm_host *host
}
}
mutex_unlock(&nlm_file_mutex);
- return 0;
+ return ret;
}
/*