X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=fs%2Flocks.c;h=8b8388eca05e88bde827d97bc71193247c190e86;hb=3a10c30acc4821ca000b52ed0edafd0d3bf26a52;hp=7f9a3ea47418cf598b3084be4efd96b9884a10bf;hpb=65a6ec0d72a07f16719e9b7a96e1c4bae044b591;p=powerpc.git diff --git a/fs/locks.c b/fs/locks.c index 7f9a3ea474..8b8388eca0 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -199,7 +199,7 @@ EXPORT_SYMBOL(locks_init_lock); * Initialises the fields of the file lock which are invariant for * free file_locks. */ -static void init_once(void *foo, struct kmem_cache *cache, unsigned long flags) +static void init_once(struct kmem_cache *cache, void *foo) { struct file_lock *lock = (struct file_lock *) foo; @@ -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. */ + +#define MAX_DEADLK_ITERATIONS 10 + static int posix_locks_deadlock(struct file_lock *caller_fl, struct file_lock *block_fl) { struct file_lock *fl; + int i = 0; next_task: 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;