[patch 04/19] LOCKD: Fix a deadlock in nlm_traverse_files()

From: Greg KH
Date: Tue Oct 10 2006 - 13:17:04 EST


-stable review patch. If anyone has any objections, please let us know.

------------------
From: Trond Myklebust <Trond.Myklebust@xxxxxxxxxx>

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@xxxxxxxxxx>
Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxx>

---
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;
}

/*

--
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/