Commit:     97855b49b6bac0bd25f16b017883634d13591d00
Parent:     fb7267acfef1de3e49d4e0c80be3cc603e974b3b
Author:     J. Bruce Fields <[EMAIL PROTECTED]>
AuthorDate: Tue Oct 30 11:20:02 2007 -0400
Committer:  Linus Torvalds <[EMAIL PROTECTED]>
CommitDate: Tue Oct 30 09:04:18 2007 -0700

    locks: fix possible infinite loop in posix deadlock detection
    It's currently possible to send posix_locks_deadlock() into an infinite
    loop (under the BKL).
    For now, fix this just by bailing out after a few iterations.  We may
    want to fix this in a way that better clarifies the semantics of
    deadlock detection.  But that will take more time, and this minimal fix
    is probably adequate for any realistic scenario, and is simple enough to
    be appropriate for applying to stable kernels now.
    Thanks to George Davis for reporting the problem.
    Cc: "George G. Davis" <[EMAIL PROTECTED]>
    Signed-off-by: J. Bruce Fields <[EMAIL PROTECTED]>
    Acked-by: Alan Cox <[EMAIL PROTECTED]>
    Signed-off-by: Linus Torvalds <[EMAIL PROTECTED]>
 fs/locks.c |   11 +++++++++++
 1 files changed, 11 insertions(+), 0 deletions(-)

diff --git a/fs/locks.c b/fs/locks.c
index 0127a28..8b8388e 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -696,17 +696,28 @@ 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.
 static int posix_locks_deadlock(struct file_lock *caller_fl,
                                struct file_lock *block_fl)
        struct file_lock *fl;
+       int i = 0;
        if (posix_same_owner(caller_fl, block_fl))
                return 1;
        list_for_each_entry(fl, &blocked_list, 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;
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at

Reply via email to