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