]> git.neil.brown.name Git - LaFS.git/commitdiff
Add tracing to help find iolock deadlocks
authorNeilBrown <neilb@suse.de>
Sun, 2 Aug 2009 09:47:40 +0000 (19:47 +1000)
committerNeilBrown <neilb@suse.de>
Sun, 2 Aug 2009 09:47:40 +0000 (19:47 +1000)
i.e. record the place where the iolock was last claimed
on each block.

Makefile
checkpoint.c
io.c
lafs.h
state.h

index 5e60ba24ebd86d2b27fef491ccc1535288f4a614..85e307c940e5510dfef3c93a92408020089d2f13 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -7,7 +7,7 @@ ARCH=i386
 ifneq ($(KERNELRELEASE),)
 # kbuild part
 
-EXTRA_CFLAGS += -Werror -DDUMP -DDEBUG_REF=1
+EXTRA_CFLAGS += -Werror -DDUMP -DDEBUG_REF=1 -DDEBUG_IOLOCK=1
 obj-m += lafs.o
 
 lafs-y := super.o io.o roll.o dir.o inode.o index.o block.o file.o link.o dir-avl.o \
index 0e8b9ca4461b4c2c64a07ed998b0d16aed09c021..87b622bf72348d2880e046a7f1521ed4ee953652 100644 (file)
@@ -307,7 +307,7 @@ struct block *lafs_get_flushable(struct fs *fs, int phase)
                /* the list counted a reference.  Now we hold it */
                list_del_init(&b->lru);
 
-               if (!test_bit(B_Index, &b->flags))
+               if (!test_bit(B_Index, &b->flags)) {
                        if (test_and_set_bit(B_IOLock, &b->flags)) {
                                /* someone else is invalidating this block,
                                 * so I can just skip it.  Better drop the ref.
@@ -315,7 +315,9 @@ struct block *lafs_get_flushable(struct fs *fs, int phase)
                                spin_unlock(&fs->lock);
                                putref(b, MKREF(leaf));
                                goto retry;
-                       }
+                       } else
+                               set_iolock_info(b);
+               }
        }
        spin_unlock(&fs->lock);
        if (b && test_bit(B_Index, &b->flags))
diff --git a/io.c b/io.c
index 859351c2122b61cf6853e7766dba62baf6509bd7..b37eafb96c18134747d837b7f9303f38b98e5c29 100644 (file)
--- a/io.c
+++ b/io.c
@@ -188,10 +188,15 @@ lafs_super_wait(struct fs *fs)
 static DECLARE_WAIT_QUEUE_HEAD(block_wait); /* need more of these later FIXME */
 
 void
-lafs_iolock_block(struct block *b)
+_lafs_iolock_block(struct block *b)
 {
        if (test_and_set_bit(B_IOLock, &b->flags)) {
                DEFINE_WAIT(wq);
+#ifdef DEBUG_IOLOCK
+               printk("iolock wait for %s:%d: %s\n",
+                      b->iolock_file, b->iolock_line,
+                      strblk(b));
+#endif
                for (;;) {
                        prepare_to_wait(&block_wait, &wq, TASK_UNINTERRUPTIBLE);
                        if (test_and_set_bit(B_IOLock, &b->flags))
diff --git a/lafs.h b/lafs.h
index c5190eecf8267840a11d009a6ed802761d9d1445..8e3baa6ba17734e34ef19de4bf275bc7560b2c5f 100644 (file)
--- a/lafs.h
+++ b/lafs.h
@@ -101,7 +101,14 @@ int __must_check lafs_find_next(struct inode *b, loff_t *bnum);
 struct indexblock *lafs_leaf_find(struct inode *inode, u32 addr,
                                  int adopt, u32 *next, int async, REFARG);
 u32 lafs_leaf_next(struct indexblock *ib, u32 start);
-void lafs_iolock_block(struct block *b);
+#ifdef DEBUG_IOLOCK
+#define set_iolock_info(b) do { (b)->iolock_file = __FILE__; (b)->iolock_line = __LINE__; } while (0)
+#else
+#define set_iolock_info(b) do {} while(0)
+#endif
+#define lafs_iolock_block(b) do { _lafs_iolock_block(b); set_iolock_info(b); } while(0)
+
+void _lafs_iolock_block(struct block *b);
 void lafs_iounlock_block(struct block *b, int bit);
 
 void lafs_super_write(struct fs *fs, int dev, u64 addr, char *buf, int size);
diff --git a/state.h b/state.h
index ba1bfcbcd833af2982243f6d529689dcb0f4342d..58ac84705f2b0a8881d64243d90c822d078efbd7 100644 (file)
--- a/state.h
+++ b/state.h
@@ -324,6 +324,11 @@ struct block {
 #if DEBUG_REF
        struct ref {int cnt; char *name; } holders[16];
 #endif
+#if DEBUG_IOLOCK
+       /* More debugging */
+       char *iolock_file;
+       int iolock_line;
+#endif
 };
 struct datablock {
        struct block b;