]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
fs/buffer.c: add debug print for __getblk_gfp() stall problem
authorTetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Mon, 23 Aug 2021 23:59:49 +0000 (09:59 +1000)
committerStephen Rothwell <sfr@canb.auug.org.au>
Wed, 25 Aug 2021 23:34:36 +0000 (09:34 +1000)
Among syzbot's unresolved hung task reports, 18 out of 65 reports contain
__getblk_gfp() line in the backtrace.  Since there is a comment block that
says that __getblk_gfp() will lock up the machine if try_to_free_buffers()
attempt from grow_dev_page() is failing, let's start from checking whether
syzbot is hitting that case.  This change will be removed after the bug is
fixed.

Link: http://lkml.kernel.org/r/9b9fcdda-c347-53ee-fdbb-8a7d11cf430e@I-love.SAKURA.ne.jp
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Cc: Dmitry Vyukov <dvyukov@google.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Mel Gorman <mgorman@techsingularity.net>
Cc: Michal Hocko <mhocko@kernel.org>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Jan Kara <jack@suse.cz>
Cc: Jeff Layton <jlayton@redhat.com>
Cc: <syzkaller-bugs@googlegroups.com>
Cc: Tim Chen <tim.c.chen@linux.intel.com>
Cc: Matthew Wilcox <willy@infradead.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
fs/buffer.c
include/linux/sched.h
lib/Kconfig.debug

index 6290c3afdba488ae4049274ca92bcdf0193f1e8c..a09e2c864cc53946730841be8778332eb0d7d15b 100644 (file)
@@ -956,10 +956,20 @@ grow_dev_page(struct block_device *bdev, sector_t block,
                        end_block = init_page_buffers(page, bdev,
                                                (sector_t)index << sizebits,
                                                size);
+#ifdef CONFIG_DEBUG_AID_FOR_SYZBOT
+                       current->getblk_executed |= 0x01;
+#endif
                        goto done;
                }
-               if (!try_to_free_buffers(page))
+               if (!try_to_free_buffers(page)) {
+#ifdef CONFIG_DEBUG_AID_FOR_SYZBOT
+                       current->getblk_executed |= 0x02;
+#endif
                        goto failed;
+               }
+#ifdef CONFIG_DEBUG_AID_FOR_SYZBOT
+               current->getblk_executed |= 0x04;
+#endif
        }
 
        /*
@@ -979,6 +989,9 @@ grow_dev_page(struct block_device *bdev, sector_t block,
        spin_unlock(&inode->i_mapping->private_lock);
 done:
        ret = (block < end_block) ? 1 : -ENXIO;
+#ifdef CONFIG_DEBUG_AID_FOR_SYZBOT
+       current->getblk_executed |= 0x08;
+#endif
 failed:
        unlock_page(page);
        put_page(page);
@@ -1030,6 +1043,12 @@ __getblk_slow(struct block_device *bdev, sector_t block,
                return NULL;
        }
 
+#ifdef CONFIG_DEBUG_AID_FOR_SYZBOT
+       current->getblk_stamp = jiffies;
+       current->getblk_executed = 0;
+       current->getblk_bh_count = 0;
+       current->getblk_bh_state = 0;
+#endif
        for (;;) {
                struct buffer_head *bh;
                int ret;
@@ -1041,6 +1060,18 @@ __getblk_slow(struct block_device *bdev, sector_t block,
                ret = grow_buffers(bdev, block, size, gfp);
                if (ret < 0)
                        return NULL;
+
+#ifdef CONFIG_DEBUG_AID_FOR_SYZBOT
+               if (!time_after(jiffies, current->getblk_stamp + 3 * HZ))
+                       continue;
+               printk(KERN_ERR "%s(%u): getblk(): executed=%x bh_count=%d bh_state=%lx\n",
+                      current->comm, current->pid, current->getblk_executed,
+                      current->getblk_bh_count, current->getblk_bh_state);
+               current->getblk_executed = 0;
+               current->getblk_bh_count = 0;
+               current->getblk_bh_state = 0;
+               current->getblk_stamp = jiffies;
+#endif
        }
 }
 
@@ -3187,6 +3218,11 @@ EXPORT_SYMBOL(sync_dirty_buffer);
  */
 static inline int buffer_busy(struct buffer_head *bh)
 {
+#ifdef CONFIG_DEBUG_AID_FOR_SYZBOT
+       current->getblk_executed |= 0x80;
+       current->getblk_bh_count = atomic_read(&bh->b_count);
+       current->getblk_bh_state = bh->b_state;
+#endif
        return atomic_read(&bh->b_count) |
                (bh->b_state & ((1 << BH_Dirty) | (1 << BH_Lock)));
 }
@@ -3225,11 +3261,18 @@ int try_to_free_buffers(struct page *page)
        int ret = 0;
 
        BUG_ON(!PageLocked(page));
-       if (PageWriteback(page))
+       if (PageWriteback(page)) {
+#ifdef CONFIG_DEBUG_AID_FOR_SYZBOT
+               current->getblk_executed |= 0x10;
+#endif
                return 0;
+       }
 
        if (mapping == NULL) {          /* can this still happen? */
                ret = drop_buffers(page, &buffers_to_free);
+#ifdef CONFIG_DEBUG_AID_FOR_SYZBOT
+               current->getblk_executed |= 0x20;
+#endif
                goto out;
        }
 
@@ -3253,6 +3296,9 @@ int try_to_free_buffers(struct page *page)
        if (ret)
                cancel_dirty_page(page);
        spin_unlock(&mapping->private_lock);
+#ifdef CONFIG_DEBUG_AID_FOR_SYZBOT
+       current->getblk_executed |= 0x40;
+#endif
 out:
        if (buffers_to_free) {
                struct buffer_head *bh = buffers_to_free;
index ec8d07d88641cd9d0d974377b6b74d920a12c53b..b36fe121da1d2b83f15b0dc70ac7f568ab294220 100644 (file)
@@ -1400,6 +1400,13 @@ struct task_struct {
        struct llist_head               kretprobe_instances;
 #endif
 
+#ifdef CONFIG_DEBUG_AID_FOR_SYZBOT
+       unsigned long                   getblk_stamp;
+       unsigned int                    getblk_executed;
+       unsigned int                    getblk_bh_count;
+       unsigned long                   getblk_bh_state;
+#endif
+
        /*
         * New fields for task_struct should be added above here, so that
         * they are included in the randomized portion of task_struct.
index 5ddd575159fb82f2f9d0bc95b7b162f2b47d8f5f..b91d8239c5ad2ed67f4b55b55f9b153308f5ec3f 100644 (file)
@@ -1807,6 +1807,12 @@ config IO_STRICT_DEVMEM
 
 menu "$(SRCARCH) Debugging"
 
+config DEBUG_AID_FOR_SYZBOT
+       bool "Additional debug code for syzbot"
+       default n
+       help
+         This option is intended for testing by syzbot.
+
 source "arch/$(SRCARCH)/Kconfig.debug"
 
 endmenu