diff options
Diffstat (limited to 'fs/locks.c')
-rw-r--r-- | fs/locks.c | 11 |
1 files changed, 11 insertions, 0 deletions
diff --git a/fs/locks.c b/fs/locks.c index c795eaaf6c4c..494f2504a487 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -694,11 +694,20 @@ EXPORT_SYMBOL(posix_test_lock); * Note: the above assumption may not be true when handling lock requests * from a broken NFS client. But broken NFS clients have a lot more to * worry about than proper deadlock detection anyway... --okir + * + * However, the failure of this assumption (also possible in the case of + * multiple tasks sharing the same open file table) also means there's no + * guarantee that the loop below will terminate. As a hack, we give up + * after a few iterations. */ + +#define MAX_DEADLK_ITERATIONS 10 + static int posix_locks_deadlock(struct file_lock *caller_fl, struct file_lock *block_fl) { struct list_head *tmp; + int i = 0; next_task: if (posix_same_owner(caller_fl, block_fl)) @@ -706,6 +715,8 @@ next_task: list_for_each(tmp, &blocked_list) { struct file_lock *fl = list_entry(tmp, struct file_lock, fl_link); if (posix_same_owner(fl, block_fl)) { + if (i++ > MAX_DEADLK_ITERATIONS) + return 0; fl = fl->fl_next; block_fl = fl; goto next_task; |