[patch] fixed lock_super() deadlock (process in D state)

Andrea Arcangeli (andrea@e-mind.com)
Wed, 24 Feb 1999 21:42:33 +0100 (CET)


With the help of David Mansfield I am been able to remotely debug the
process in D state problem of 2.2.2 (and previous).

The problem is that the same process does lock_super() two times.

This patch I developed some hours ago against 2.2.2 fix the deadlock
perfectly:

Index: include/linux/locks.h
===================================================================
RCS file: /var/cvs/linux/include/linux/locks.h,v
retrieving revision 1.1.2.3
diff -u -r1.1.2.3 locks.h
--- locks.h 1999/02/09 20:27:39 1.1.2.3
+++ linux/include/linux/locks.h 1999/02/24 18:28:19
@@ -39,17 +39,20 @@
*/
extern void __wait_on_super(struct super_block *);

+#define is_super_locked(sb) ((sb)->s_lock && (sb)->s_owner != current)
+
extern inline void wait_on_super(struct super_block * sb)
{
- if (sb->s_lock)
+ if (is_super_locked(sb))
__wait_on_super(sb);
}

extern inline void lock_super(struct super_block * sb)
{
- if (sb->s_lock)
+ if (is_super_locked(sb))
__wait_on_super(sb);
sb->s_lock = 1;
+ sb->s_owner = current;
}

extern inline void unlock_super(struct super_block * sb)
Index: include/linux/fs.h
===================================================================
RCS file: /var/cvs/linux/include/linux/fs.h,v
retrieving revision 1.1.2.9
diff -u -r1.1.2.9 fs.h
--- fs.h 1999/02/16 17:30:00 1.1.2.9
+++ linux/include/linux/fs.h 1999/02/24 18:23:20
@@ -519,6 +519,7 @@
unsigned char s_lock;
unsigned char s_rd_only;
unsigned char s_dirt;
+ struct task_struct * s_owner;
struct file_system_type *s_type;
struct super_operations *s_op;
struct dquot_operations *dq_op;
Index: fs//super.c
===================================================================
RCS file: /var/cvs/linux/fs/super.c,v
retrieving revision 1.1.2.3
diff -u -r1.1.2.3 super.c
--- super.c 1999/01/31 22:44:49 1.1.2.3
+++ linux/fs/super.c 1999/02/24 18:28:39
@@ -517,7 +517,7 @@
s = sb_entry(s->s_list.next)) {
if (s->s_dev)
continue;
- if (!s->s_lock)
+ if (!is_super_locked(s))
return s;
printk("VFS: empty superblock %p locked!\n", s);
}

I don't know _why_ this patch is needed and if it's 100% safe. Right now I
am trying with David's help to understand where the kernel is recursively
calling lock_super().

I want also to point out that the new semaphores of 2.2.2 had nothing to
do with these deadlock (so be quiet and go ahead porting them to all archs ;).

Andrea Arcangeli

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/