Commit 01df9c5e authored by Trond Myklebust's avatar Trond Myklebust

LOCKD: Fix a deadlock in nlm_traverse_files()

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: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
(cherry picked from e558d3cde986e04f68afe8c790ad68ef4b94587a commit)
parent 8f8e7a50
...@@ -237,19 +237,22 @@ static int ...@@ -237,19 +237,22 @@ static int
nlm_traverse_files(struct nlm_host *host, int action) nlm_traverse_files(struct nlm_host *host, int action)
{ {
struct nlm_file *file, **fp; struct nlm_file *file, **fp;
int i; int i, ret = 0;
mutex_lock(&nlm_file_mutex); mutex_lock(&nlm_file_mutex);
for (i = 0; i < FILE_NRHASH; i++) { for (i = 0; i < FILE_NRHASH; i++) {
fp = nlm_files + i; fp = nlm_files + i;
while ((file = *fp) != NULL) { while ((file = *fp) != NULL) {
file->f_count++;
mutex_unlock(&nlm_file_mutex);
/* Traverse locks, blocks and shares of this file /* Traverse locks, blocks and shares of this file
* and update file->f_locks count */ * and update file->f_locks count */
if (nlm_inspect_file(host, file, action)) { if (nlm_inspect_file(host, file, action))
mutex_unlock(&nlm_file_mutex); ret = 1;
return 1;
}
mutex_lock(&nlm_file_mutex);
file->f_count--;
/* No more references to this file. Let go of it. */ /* No more references to this file. Let go of it. */
if (!file->f_blocks && !file->f_locks if (!file->f_blocks && !file->f_locks
&& !file->f_shares && !file->f_count) { && !file->f_shares && !file->f_count) {
...@@ -262,7 +265,7 @@ nlm_traverse_files(struct nlm_host *host, int action) ...@@ -262,7 +265,7 @@ nlm_traverse_files(struct nlm_host *host, int action)
} }
} }
mutex_unlock(&nlm_file_mutex); mutex_unlock(&nlm_file_mutex);
return 0; return ret;
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment