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 0127a2846819..8b8388eca05e 100644 --- a/fs/locks.c +++ b/fs/locks.c | |||
@@ -696,17 +696,28 @@ EXPORT_SYMBOL(posix_test_lock); | |||
696 | * Note: the above assumption may not be true when handling lock requests | 696 | * Note: the above assumption may not be true when handling lock requests |
697 | * from a broken NFS client. But broken NFS clients have a lot more to | 697 | * from a broken NFS client. But broken NFS clients have a lot more to |
698 | * worry about than proper deadlock detection anyway... --okir | 698 | * worry about than proper deadlock detection anyway... --okir |
699 | * | ||
700 | * However, the failure of this assumption (also possible in the case of | ||
701 | * multiple tasks sharing the same open file table) also means there's no | ||
702 | * guarantee that the loop below will terminate. As a hack, we give up | ||
703 | * after a few iterations. | ||
699 | */ | 704 | */ |
705 | |||
706 | #define MAX_DEADLK_ITERATIONS 10 | ||
707 | |||
700 | static int posix_locks_deadlock(struct file_lock *caller_fl, | 708 | static int posix_locks_deadlock(struct file_lock *caller_fl, |
701 | struct file_lock *block_fl) | 709 | struct file_lock *block_fl) |
702 | { | 710 | { |
703 | struct file_lock *fl; | 711 | struct file_lock *fl; |
712 | int i = 0; | ||
704 | 713 | ||
705 | next_task: | 714 | next_task: |
706 | if (posix_same_owner(caller_fl, block_fl)) | 715 | if (posix_same_owner(caller_fl, block_fl)) |
707 | return 1; | 716 | return 1; |
708 | list_for_each_entry(fl, &blocked_list, fl_link) { | 717 | list_for_each_entry(fl, &blocked_list, fl_link) { |
709 | if (posix_same_owner(fl, block_fl)) { | 718 | if (posix_same_owner(fl, block_fl)) { |
719 | if (i++ > MAX_DEADLK_ITERATIONS) | ||
720 | return 0; | ||
710 | fl = fl->fl_next; | 721 | fl = fl->fl_next; |
711 | block_fl = fl; | 722 | block_fl = fl; |
712 | goto next_task; | 723 | goto next_task; |