402 Star 1.4K Fork 1.3K

GVPopenEuler / kernel

 / 详情

dm thin: Fix ABBA deadlock between shrink_slab and dm_pool_abort_metadata

已完成
缺陷
创建于  
2022-12-09 15:53

【标题描述】ext4 evict inode流程和dm thin pool提交失败处理流程并发可能导致ABBA死锁
【环境信息】
硬件信息:
NA
软件信息:
OLK-510
【问题复现步骤】
-smp 2
-m 4096
config 3 disks

  1. Apply diff and compile kernel
  2. gcc -o bb b.c
  3. ./test.s
    出现概率(是否必现,概率性错误)必现
    【预期结果】
    hung task
    【实际结果】
[   56.803898] release inode writer
[   56.809470] evict
[   56.809967] test.sh(2496) read bh
[   56.810695] test.sh(2496): try get pmd->root_lock, wait other submit
[   56.914566] sync(2643): try get pmd->root_lock, wait other submit
[   57.316585] commit kworker/u4:1 52 make fail
[   57.317499] device-mapper: thin: 252:0: metadata operation 'dm_pool_commit_metadata' failed: error = -22
[   57.319118] device-mapper: thin: 252:0: aborting current metadata transaction
[   58.083735] jbd2/dm-1-8(2629): try get pmd->root_lock, wait other submit
[   83.171810] kworker/u4:3(105) read bh
[   83.175520] kworker/u4:3(105) read bh done
[  241.995417] INFO: task kworker/u4:1:52 blocked for more than 119 seconds.
[  241.996787]       Not tainted 5.10.0-czh-1009-defconfig-pipe_revert+ #129
[  241.997921] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
[  241.999231] task:kworker/u4:1    state:D stack:    0 pid:   52 ppid:     2 flags:0x00004000
[  241.999257] Workqueue: dm-thin do_worker
[  241.999259] Call Trace:
[  241.999274]  __schedule+0x3ba/0x750
[  241.999291]  schedule+0x46/0xb0
[  241.999296]  rwsem_down_write_slowpath+0x341/0x4b0
[  241.999308]  unregister_shrinker+0x20/0xa0
[  241.999312]  dm_bufio_client_destroy+0xa5/0x200
[  241.999316]  dm_block_manager_destroy+0x11/0x20
[  241.999319]  dm_pool_abort_metadata+0x60/0xa0
[  241.999321]  metadata_operation_failed+0x5a/0xb0
[  241.999323]  commit+0x5a/0x170
[  241.999325]  process_deferred_bios+0x7c6/0x7f0
[  241.999329]  ? internal_add_timer+0x44/0x70
[  241.999332]  do_worker+0xb0/0xd0
[  241.999336]  process_one_work+0x1ab/0x340
[  241.999338]  worker_thread+0x4d/0x390
[  241.999341]  ? process_one_work+0x340/0x340
[  241.999343]  kthread+0xfe/0x140
[  241.999345]  ? __kthread_cancel_work+0x50/0x50
[  241.999348]  ret_from_fork+0x22/0x30
[  241.999362] INFO: task test.sh:2496 blocked for more than 119 seconds.
[  242.000501]       Not tainted 5.10.0-czh-1009-defconfig-pipe_revert+ #129
[  242.001897] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
[  242.003217] task:test.sh         state:D stack:    0 pid: 2496 ppid:  2404 flags:0x00004004
[  242.003222] Call Trace:
[  242.003233]  __schedule+0x3ba/0x750
[  242.003237]  schedule+0x46/0xb0
[  242.003239]  rwsem_down_read_slowpath+0x198/0x4d0
[  242.003245]  ? del_timer_sync+0x25/0x40
[  242.003251]  dm_thin_find_block+0x3c/0xa0
[  242.003254]  thin_map+0x172/0x270
[  242.003261]  __map_bio+0x4c/0x210
[  242.003264]  __split_and_process_non_flush+0x19c/0x1f0
[  242.003266]  dm_submit_bio+0x170/0x3e0
[  242.003273]  submit_bio_noacct+0x100/0x400
[  242.003279]  ? bio_associate_blkg_from_css+0xfc/0x2c0
[  242.003281]  submit_bio+0x42/0x130
[  242.003284]  ? guard_bio_eod+0x25/0x70
[  242.003289]  submit_bh_wbc+0x16a/0x1a0
[  242.003296]  ext4_read_block_bitmap_nowait+0x24e/0x6d0
[  242.003300]  ext4_mb_init_cache+0x151/0x670
[  242.003311]  ext4_mb_load_buddy_gfp+0x3a4/0x420
[  242.003314]  ext4_discard_preallocations+0x1ac/0x480
[  242.003318]  ext4_clear_inode+0x28/0x90
[  242.003324]  ext4_evict_inode+0x95/0x640
[  242.003330]  evict+0xcb/0x190
[  242.003333]  dispose_list+0x48/0x70
[  242.003335]  prune_icache_sb+0x54/0x80
[  242.003339]  super_cache_scan+0x124/0x1b0
[  242.003346]  do_shrink_slab+0x13e/0x2c0
[  242.003349]  shrink_slab+0xac/0x2b0
[  242.003353]  drop_slab_node+0x45/0x90
[  242.003355]  drop_slab+0x36/0x70
[  242.003361]  drop_caches_sysctl_handler+0x74/0x90
[  242.003366]  proc_sys_call_handler+0x143/0x260
[  242.003370]  new_sync_write+0x116/0x1c0
[  242.003373]  vfs_write+0x1b7/0x250
[  242.003376]  ksys_write+0x5f/0xe0
[  242.003379]  do_syscall_64+0x40/0x80
[  242.003383]  entry_SYSCALL_64_after_hwframe+0x61/0xc6
[  242.003387] RIP: 0033:0x7f8c76901130
[  242.003388] RSP: 002b:00007fff0143dae8 EFLAGS: 00000246 ORIG_RAX: 0000000000000001
[  242.003391] RAX: ffffffffffffffda RBX: 0000000000000002 RCX: 00007f8c76901130
[  242.003392] RDX: 0000000000000002 RSI: 0000556ce417c8b0 RDI: 0000000000000001
[  242.003394] RBP: 0000556ce417c8b0 R08: 000000000000000a R09: 00007f8c77212700
[  242.003395] R10: 0000556ce417bb80 R11: 0000000000000246 R12: 0000000000000002
[  242.003396] R13: 0000000000000001 R14: 00007f8c76bd15e0 R15: 00007f8c76bcc8c0
[  242.003402] INFO: task jbd2/dm-1-8:2629 blocked for more than 119 seconds.
[  242.004590]       Not tainted 5.10.0-czh-1009-defconfig-pipe_revert+ #129
[  242.005732] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
[  242.007032] task:jbd2/dm-1-8     state:D stack:    0 pid: 2629 ppid:     2 flags:0x00004000
[  242.007036] Call Trace:
[  242.007045]  __schedule+0x3ba/0x750
[  242.007048]  schedule+0x46/0xb0
[  242.007051]  rwsem_down_read_slowpath+0x198/0x4d0
[  242.007056]  ? del_timer_sync+0x25/0x40
[  242.007062]  dm_thin_find_block+0x3c/0xa0
[  242.007065]  thin_map+0x172/0x270
[  242.007071]  __map_bio+0x4c/0x210
[  242.007074]  __split_and_process_non_flush+0x19c/0x1f0
[  242.007076]  dm_submit_bio+0x170/0x3e0
[  242.007081]  submit_bio_noacct+0x100/0x400
[  242.007087]  ? bio_associate_blkg_from_css+0x13c/0x2c0
[  242.007089]  submit_bio+0x42/0x130
[  242.007094]  ? guard_bio_eod+0x25/0x70
[  242.007099]  submit_bh_wbc+0x16a/0x1a0
[  242.007104]  jbd2_write_superblock+0xb4/0x190
[  242.007107]  jbd2_journal_update_sb_log_tail+0x66/0xd0
[  242.007112]  jbd2_journal_commit_transaction+0x37c/0x1a60
[  242.007118]  ? pick_next_task_fair+0x1f5/0xba0
[  242.007123]  ? __switch_to_asm+0x42/0x80
[  242.007125]  ? __switch_to_asm+0x5a/0x80
[  242.007127]  ? lock_timer_base+0x61/0x80
[  242.007129]  ? try_to_del_timer_sync+0x4f/0x80
[  242.007131]  kjournald2+0xb7/0x280
[  242.007136]  ? wait_woken+0x80/0x80
[  242.007137]  ? commit_timeout+0x10/0x10
[  242.007141]  kthread+0xfe/0x140
[  242.007144]  ? __kthread_cancel_work+0x50/0x50
[  242.007146]  ret_from_fork+0x22/0x30

【附件信息】
diff

diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c
index 5961caf17c71..13b27e2cefa8 100644
--- a/drivers/md/dm-thin-metadata.c
+++ b/drivers/md/dm-thin-metadata.c
@@ -1508,13 +1508,25 @@ static int __find_block(struct dm_thin_device *td, dm_block_t block,
 	return r;
 }
 
+#include <linux/delay.h>
+extern struct page *g_page;
 int dm_thin_find_block(struct dm_thin_device *td, dm_block_t block,
 		       int can_issue_io, struct dm_thin_lookup_result *result)
 {
 	int r;
 	struct dm_pool_metadata *pmd = td->pmd;
 
+	smp_rmb();
+	if (g_page) {
+		pr_err("%s(%d): try get pmd->root_lock, wait other submit\n", current->comm, current->pid);
+		msleep(4000);
+	}
+
 	down_read(&pmd->root_lock);
+
+	if (g_page)
+		pr_err("%s(%d): locked pmd->root_lock\n", current->comm, current->pid);
+
 	if (pmd->fail_io) {
 		up_read(&pmd->root_lock);
 		return -EINVAL;
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c
index e837839e4def..ba2836ed1211 100644
--- a/drivers/md/dm-thin.c
+++ b/drivers/md/dm-thin.c
@@ -1489,14 +1489,21 @@ static void check_for_data_space(struct pool *pool)
  * A non-zero return indicates read_only or fail_io mode.
  * Many callers don't care about the return value.
  */
+extern struct page *g_page;
 static int commit(struct pool *pool)
 {
 	int r;
+	static int inject = 0;
 
 	if (get_pool_mode(pool) >= PM_OUT_OF_METADATA_SPACE)
 		return -EINVAL;
 
 	r = dm_pool_commit_metadata(pool->pmd);
+	if (!inject && g_page && !strncmp(current->comm, "kworker", 7)) {
+		inject = 1;
+		pr_err("%s %s %d make fail\n", __func__, current->comm, current->pid);
+		r = -EINVAL;
+	}
 	if (r)
 		metadata_operation_failed(pool, "dm_pool_commit_metadata", r);
 	else {
diff --git a/fs/buffer.c b/fs/buffer.c
index 93324b06ecb4..83012ad5318c 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -1252,6 +1252,8 @@ static inline void check_irqs_on(void)
 #endif
 }
 
+struct buffer_head *g_bh;
+
 /*
  * Install a buffer_head into this cpu's LRU.  If not already in the LRU, it is
  * inserted at the front, and the buffer_head at the back if any is evicted.
@@ -3347,6 +3349,11 @@ EXPORT_SYMBOL(alloc_buffer_head);
 
 void free_buffer_head(struct buffer_head *bh)
 {
+	if (bh == g_bh) {
+		pr_err("%s: %px\n", __func__, bh);
+		g_bh = (void *)-1;
+		smp_wmb();
+	}
 	BUG_ON(!list_empty(&bh->b_assoc_buffers));
 	kmem_cache_free(bh_cachep, bh);
 	preempt_disable();
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index 1afd60fcd772..3ba9cc5b6776 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -417,6 +417,8 @@ static int ext4_validate_block_bitmap(struct super_block *sb,
  *
  * Return buffer_head on success or an ERR_PTR in case of failure.
  */
+#include <linux/delay.h>
+extern struct page *g_page;
 struct buffer_head *
 ext4_read_block_bitmap_nowait(struct super_block *sb, ext4_group_t block_group,
 			      bool ignore_locked)
@@ -426,6 +428,7 @@ ext4_read_block_bitmap_nowait(struct super_block *sb, ext4_group_t block_group,
 	struct buffer_head *bh;
 	ext4_fsblk_t bitmap_blk;
 	int err;
+	static int waited = 0;
 
 	desc = ext4_get_group_desc(sb, block_group, NULL);
 	if (!desc)
@@ -439,6 +442,13 @@ ext4_read_block_bitmap_nowait(struct super_block *sb, ext4_group_t block_group,
 					EXT4_GROUP_INFO_BBITMAP_CORRUPT);
 		return ERR_PTR(-EFSCORRUPTED);
 	}
+	if (g_page && !waited) {
+		waited = 1;
+		while (g_bh != (void *)-1) {
+			smp_rmb();
+			msleep(10);
+		}
+	}
 	bh = sb_getblk(sb, bitmap_blk);
 	if (unlikely(!bh)) {
 		ext4_warning(sb, "Cannot get buffer for block bitmap - "
@@ -498,11 +508,15 @@ ext4_read_block_bitmap_nowait(struct super_block *sb, ext4_group_t block_group,
 	/*
 	 * submit the buffer_head for reading
 	 */
+	if (g_page)
+		pr_err("%s(%d) read bh\n", current->comm, current->pid);
 	set_buffer_new(bh);
 	trace_ext4_read_block_bitmap_load(sb, block_group, ignore_locked);
 	ext4_read_bh_nowait(bh, REQ_META | REQ_PRIO |
 			    (ignore_locked ? REQ_RAHEAD : 0),
 			    ext4_end_bitmap_read);
+	if (g_page)
+		pr_err("%s(%d) read bh done\n", current->comm, current->pid);
 	return bh;
 verify:
 	err = ext4_validate_block_bitmap(sb, desc, block_group, bh);
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 3fcfc156d0d7..58cf40dbd437 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -340,6 +340,8 @@ void ext4_evict_inode(struct inode *inode)
 no_delete:
 	if (!list_empty(&EXT4_I(inode)->i_fc_list))
 		ext4_fc_mark_ineligible(inode->i_sb, EXT4_FC_REASON_NOMEM);
+	if (inode->i_ino == 12)
+		pr_err("evict\n");
 	ext4_clear_inode(inode);	/* We must guarantee clearing of inode... */
 }
 
@@ -373,6 +375,8 @@ void ext4_da_update_reserve_space(struct inode *inode,
 
 	/* Update per-inode reservations */
 	ei->i_reserved_data_blocks -= used;
+	if (inode->i_ino == 12 && ei->i_reserved_data_blocks == 0)
+		pr_err("release\n");
 	percpu_counter_sub(&sbi->s_dirtyclusters_counter, used);
 
 	spin_unlock(&EXT4_I(inode)->i_block_reservation_lock);
@@ -1487,6 +1491,8 @@ static int ext4_da_reserve_space(struct inode *inode)
 		return -ENOSPC;
 	}
 	ei->i_reserved_data_blocks++;
+	if (inode->i_ino == 12)
+		pr_err("reserve %d\n", ei->i_reserved_data_blocks);
 	trace_ext4_da_reserve_space(inode);
 	spin_unlock(&ei->i_block_reservation_lock);
 
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index fd8464aadf00..14e37cff9f7e 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -1153,9 +1153,10 @@ int ext4_mb_init_group(struct super_block *sb, ext4_group_t group, gfp_t gfp)
  * block group lock of all groups for this page; do not hold the BG lock when
  * calling this routine!
  */
+struct page *g_page;
 static noinline_for_stack int
 ext4_mb_load_buddy_gfp(struct super_block *sb, ext4_group_t group,
-		       struct ext4_buddy *e4b, gfp_t gfp)
+		       struct ext4_buddy *e4b, gfp_t gfp, int evt)
 {
 	int blocks_per_page;
 	int block;
@@ -1217,7 +1218,16 @@ ext4_mb_load_buddy_gfp(struct super_block *sb, ext4_group_t group,
 		if (page) {
 			BUG_ON(page->mapping != inode->i_mapping);
 			if (!PageUptodate(page)) {
+				if (evt) {
+					g_page = page;
+					smp_wmb();
+				}
 				ret = ext4_mb_init_cache(page, NULL, gfp);
+				if (evt) {
+					g_page = NULL;
+					smp_wmb();
+					//panic("END");
+				}
 				if (ret) {
 					unlock_page(page);
 					goto err;
@@ -1293,7 +1303,7 @@ ext4_mb_load_buddy_gfp(struct super_block *sb, ext4_group_t group,
 static int ext4_mb_load_buddy(struct super_block *sb, ext4_group_t group,
 			      struct ext4_buddy *e4b)
 {
-	return ext4_mb_load_buddy_gfp(sb, group, e4b, GFP_NOFS);
+	return ext4_mb_load_buddy_gfp(sb, group, e4b, GFP_NOFS, 0);
 }
 
 static void ext4_mb_unload_buddy(struct ext4_buddy *e4b)
@@ -3738,6 +3748,8 @@ static void ext4_mb_use_inode_pa(struct ext4_allocation_context *ac,
 	BUG_ON(end > pa->pa_pstart + EXT4_C2B(sbi, pa->pa_len));
 	BUG_ON(pa->pa_free < len);
 	pa->pa_free -= len;
+	if (ac->ac_inode->i_ino == 12)
+		pr_err("use len %d\n", len);
 
 	mb_debug(ac->ac_sb, "use %llu/%d from inode pa %p\n", start, len, pa);
 }
@@ -4036,6 +4048,7 @@ static void ext4_mb_put_pa(struct ext4_allocation_context *ac,
 	spin_lock(pa->pa_obj_lock);
 	list_del_rcu(&pa->pa_inode_list);
 	spin_unlock(pa->pa_obj_lock);
+	pr_err("free pa\n");
 
 	call_rcu(&(pa)->u.pa_rcu, ext4_mb_pa_callback);
 }
@@ -4123,6 +4136,9 @@ ext4_mb_new_inode_pa(struct ext4_allocation_context *ac)
 
 	list_add(&pa->pa_group_list, &grp->bb_prealloc_list);
 
+	if (ei->vfs_inode.i_ino == 12)
+		pr_err("add prealloc %d %lld\n", pa->pa_free, i_size_read(&ei->vfs_inode));
+
 	spin_lock(pa->pa_obj_lock);
 	list_add_rcu(&pa->pa_inode_list, &ei->i_prealloc_list);
 	spin_unlock(pa->pa_obj_lock);
@@ -4464,7 +4480,7 @@ void ext4_discard_preallocations(struct inode *inode, unsigned int needed)
 		group = ext4_get_group_number(sb, pa->pa_pstart);
 
 		err = ext4_mb_load_buddy_gfp(sb, group, &e4b,
-					     GFP_NOFS|__GFP_NOFAIL);
+					     GFP_NOFS|__GFP_NOFAIL, atomic_read(&inode->i_count) == 0 && (inode->i_state & I_FREEING) != 0 && inode->i_ino == 12 ? 1 : 0);
 		if (err) {
 			ext4_error_err(sb, -err, "Error %d loading buddy information for %u",
 				       err, group);
@@ -4759,7 +4775,7 @@ ext4_mb_discard_lg_preallocations(struct super_block *sb,
 
 		group = ext4_get_group_number(sb, pa->pa_pstart);
 		err = ext4_mb_load_buddy_gfp(sb, group, &e4b,
-					     GFP_NOFS|__GFP_NOFAIL);
+					     GFP_NOFS|__GFP_NOFAIL, 0);
 		if (err) {
 			ext4_error_err(sb, -err, "Error %d loading buddy information for %u",
 				       err, group);
@@ -5487,7 +5503,7 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
 
 	/* __GFP_NOFAIL: retry infinitely, ignore TIF_MEMDIE and memcg limit. */
 	err = ext4_mb_load_buddy_gfp(sb, block_group, &e4b,
-				     GFP_NOFS|__GFP_NOFAIL);
+				     GFP_NOFS|__GFP_NOFAIL, 0);
 	if (err)
 		goto error_return;
 
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index ace7e51aeebb..11f2e553e697 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -152,7 +152,6 @@ MODULE_ALIAS_FS("ext3");
 MODULE_ALIAS("ext3");
 #define IS_EXT3_SB(sb) ((sb)->s_bdev->bd_holder == &ext3_fs_type)
 
-
 static inline void __ext4_read_bh(struct buffer_head *bh, int op_flags,
 				  bh_end_io_t *end_io)
 {
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
index fa24b407a9dc..5bf7cfbfee17 100644
--- a/fs/jbd2/commit.c
+++ b/fs/jbd2/commit.c
@@ -378,6 +378,7 @@ static void jbd2_block_tag_csum_set(journal_t *j, journal_block_tag_t *tag,
  * The primary function for committing a transaction to the log.  This
  * function is called by the journal thread to begin a complete commit.
  */
+extern struct buffer_head *g_bh;
 void jbd2_journal_commit_transaction(journal_t *journal)
 {
 	struct transaction_stats_s stats;
@@ -700,7 +701,12 @@ void jbd2_journal_commit_transaction(journal_t *journal)
 		/* Bump b_count to prevent truncate from stumbling over
                    the shadowed buffer!  @@@ This can go if we ever get
                    rid of the shadow pairing of buffers. */
+		smp_rmb();
 		atomic_inc(&jh2bh(jh)->b_count);
+		if (jh2bh(jh) == g_bh) {
+			pr_err("inc bh %d\n", atomic_read(&jh2bh(jh)->b_count));
+			dump_stack();
+		}
 
 		/*
 		 * Make a temporary IO buffer with which to write it out
diff --git a/fs/open.c b/fs/open.c
index 7ce64c08bb40..3efebe38ac17 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -66,6 +66,7 @@ int do_truncate(struct dentry *dentry, loff_t length, unsigned int time_attrs,
 	return ret;
 }
 
+#include <linux/delay.h>
 long vfs_truncate(const struct path *path, loff_t length)
 {
 	struct inode *inode;
@@ -109,6 +110,12 @@ long vfs_truncate(const struct path *path, loff_t length)
 	if (!error)
 		error = do_truncate(path->dentry, length, 0, NULL);
 
+	if (inode->i_ino == 12) {
+		pr_err("wait add prealloc\n");
+		msleep(5000);
+		pr_err("release inode writer\n");
+	}
+
 put_write_and_out:
 	put_write_access(inode);
 mnt_drop_write_and_out:
diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h
index 8577ab2ef446..71e4b838f3b5 100644
--- a/include/linux/buffer_head.h
+++ b/include/linux/buffer_head.h
@@ -275,15 +275,26 @@ void buffer_init(void);
  * inline definitions
  */
 
+extern struct buffer_head *g_bh;
 static inline void get_bh(struct buffer_head *bh)
 {
         atomic_inc(&bh->b_count);
+	smp_rmb();
+	if (bh == g_bh) {
+		pr_err("%s: %d", __func__, atomic_read(&bh->b_count));
+		dump_stack();
+	}
 }
 
 static inline void put_bh(struct buffer_head *bh)
 {
         smp_mb__before_atomic();
         atomic_dec(&bh->b_count);
+	smp_rmb();
+	if (bh == g_bh) {
+		pr_err("%s: %d", __func__, atomic_read(&bh->b_count));
+		dump_stack();
+	}
 }
 
 static inline void brelse(struct buffer_head *bh)
@@ -325,7 +336,17 @@ sb_breadahead_unmovable(struct super_block *sb, sector_t block)
 static inline struct buffer_head *
 sb_getblk(struct super_block *sb, sector_t block)
 {
-	return __getblk_gfp(sb->s_bdev, block, sb->s_blocksize, __GFP_MOVABLE);
+	struct buffer_head *bh;
+
+	bh = __getblk_gfp(sb->s_bdev, block, sb->s_blocksize, __GFP_MOVABLE);
+	if (!g_bh && !strcmp(sb->s_id, "dm-1") && block == 130) {
+		pr_err("%s gen bh %px ref %d\n", __func__, bh, atomic_read(&bh->b_count));
+		g_bh = bh;
+		smp_wmb();
+		dump_stack();
+	}
+
+	return bh;
 }
 
 

b.c

#define _GNU_SOURCE             /* See feature_test_macros(7) */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mount.h>
#include <getopt.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/xattr.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/syscall.h>
#include <errno.h>
#include <string.h>
#include <linux/reboot.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <grp.h>
#include <sys/prctl.h>
#include <linux/fs.h>
#include <signal.h>
#include <sched.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <linux/perf_event.h>
#include <linux/bpf.h>
#include <sys/sysinfo.h>
#include <sys/epoll.h>
#include <asm/unistd.h>
#include <sys/time.h>
#include <sys/sendfile.h>
#include <stdarg.h>
#include <assert.h>
#include <linux/aio_abi.h>

#define DEV "dm-1"

int main(void)
{
	int i, ret, fd;
	__u64 sz = 1048576;
	char buf[4096];

	system("dd if=/dev/zero of=/dev/sda bs=1G count=2");
	system("dmsetup create pool --table \"0 2097152 thin-pool /dev/sda /dev/sdb 128 0\"");
	system("dmsetup message /dev/mapper/pool 0 \"create_thin 0\"");
	system("dmsetup create thin --table \"0 2097152 thin /dev/mapper/pool 0\"");
	system("umount /root/temp");
	system("mkfs.ext4 -F /dev/" DEV " 1G");
	system("mount /dev/" DEV " /root/temp");
	system("touch /root/temp/file");

	ret = fork();
	if (ret < 0) {
		perror("fork fail");
		return 0;
	} else if (ret == 0) {
		truncate("/root/temp/file", 0);
	} else {
		system("dd if=/dev/zero of=/root/temp/file bs=1 count=69999");
	}

	system("sync /root/temp/file");
	system("sync /root/temp/file");

	fd = open("/root/temp", O_RDONLY);
	if (fd < 0) {
		perror("open fail\n");
		return 0;
	}
	if (ioctl(fd, _IOW('f', 16, __u64), &sz) < 0)
		perror("ioctl fail");

	return 0;
}

test.sh

#!/bin/bash

./bb
sync
mkfs.ext4 -F /dev/sdc
while true
do
	echo 3 > /proc/sys/vm/drop_caches
done
#dd if=/dev/zero of=/root/temp/new_f bs=1K count=1K oflag=direct

评论 (1)

chengzhihao 创建了缺陷

Hi czh549642238, welcome to the openEuler Community.
I'm the Bot here serving you. You can find the instructions on how to interact with me at Here.
If you have any questions, please contact the SIG: Kernel, and any of the maintainers: @YangYingliang , @成坚 (CHENG Jian) , @jiaoff , @zhengzengkai , @刘勇强 , @wangxiongfeng , @朱科潜 , @WangShaoBo , @lujialin , @wuxu_buque , @Xu Kuohai , @冷嘲啊 , @Lingmingqiang , @yuzenghui , @juntian , @OSSIM , @陈结松 , @whoisxxx , @koulihong , @刘恺 , @hanjun-guo , @woqidaideshi , @Chiqijun , @Kefeng , @ThunderTown , @AlexGuo , @kylin-mayukun , @Zheng Zucheng , @柳歆 , @Jackie Liu , @zhujianwei001 , @郑振鹏 , @SuperSix173 , @colyli , @Zhang Yi , @htforge , @Qiuuuuu , @Yuehaibing , @xiehaocheng , @guzitao , @CTC-Xibo.Wang , @zhanghongchen , @chen wei , @Jason Zeng , @苟浩 , @DuanqiangWen , @georgeguo , @毛泓博 , @AllenShi , @Xie XiuQi

登录 后才可以发表评论

状态
负责人
项目
里程碑
Pull Requests
关联的 Pull Requests 被合并后可能会关闭此 issue
分支
开始日期   -   截止日期
-
置顶选项
优先级
预计工期 (小时)
参与者(2)
5329419 openeuler ci bot 1632792936
C
1
https://gitee.com/openeuler/kernel.git
git@gitee.com:openeuler/kernel.git
openeuler
kernel
kernel

搜索帮助