Sleeping function called in invalid context
While doing some testing on today's checkout of Linus' master branch I got the following:
[ 9.302725] BUG: sleeping function called from invalid context at ./include/linux/buffer_head.h:358
[ 9.304403] in_atomic(): 1, irqs_disabled(): 0, pid: 1718, name: mount
[ 9.305633] 8 locks held by mount/1718:
[ 9.306382] #0: (sb_writers#6){.+.+.+}, at: [<ffffffff811f0473>] __sb_start_write+0xd3/0xf0
[ 9.308178] #1: (&type->i_mutex_dir_key#2/1){+.+.+.}, at: [<ffffffff811f9574>] lock_rename+0xe4/0x120
[ 9.310096] #2: (&sb->s_type->i_mutex_key#9){+.+.+.}, at: [<ffffffff8120c157>] lock_two_nondirectories+0x47/0x90
[ 9.312195] #3: (&sb->s_type->i_mutex_key#9/4){+.+.+.}, at: [<ffffffff8120c18f>] lock_two_nondirectories+0x7f/0x90
[ 9.314315] #4: (&sbi->s_journal_flag_rwsem){.+.+.+}, at: [<ffffffff812988c0>] ext4_writepages+0x50/0xff0
[ 9.316278] #5: (jbd2_handle){++++..}, at: [<ffffffff812e8d43>] start_this_handle+0x143/0x4c0
[ 9.318032] #6: (&ei->i_data_sem){++++..}, at: [<ffffffff81294803>] ext4_map_blocks+0x123/0x540
[ 9.319793] #7: (&(&bgl->locks[i].lock)->rlock){+.+...}, at: [<ffffffff812d0df3>] ext4_mb_init_cache+0x3e3/0xa70
[ 9.321887] CPU: 0 PID: 1718 Comm: mount Not tainted 4.7.0-clouder1 #5
[ 9.322873] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.8.1-0-g4adadbd-20150316_085822-nilsson.home.kraxel.org 04/01/2014
[ 9.322873] 0000000000000000 ffff88003a4d3058 ffffffff81375c97 ffffffff819c29f9
[ 9.322873] 0000000000000166 ffff880038a41500 ffffffff819c29f9 ffff88003a4d3088
[ 9.322873] ffffffff8108dc43 ffff88003a4d3088 0000000000000000 0000000000000166
[ 9.322873] Call Trace:
[ 9.322873] [<ffffffff81375c97>] dump_stack+0x6b/0xa4
[ 9.322873] [<ffffffff8108dc43>] ___might_sleep+0x183/0x240
[ 9.322873] [<ffffffff8108dd52>] __might_sleep+0x52/0x90
[ 9.322873] [<ffffffff812ae9c1>] ext4_commit_super+0x191/0x2a0
[ 9.322873] [<ffffffff812af790>] __ext4_grp_locked_error+0x170/0x240
[ 9.322873] [<ffffffff8108dd52>] ? __might_sleep+0x52/0x90
[ 9.322873] [<ffffffff812cf00c>] ext4_mb_generate_buddy+0x20c/0x360
[ 9.322873] [<ffffffff812d0e61>] ext4_mb_init_cache+0x451/0xa70
[ 9.322873] [<ffffffff812d167c>] ext4_mb_init_group+0x1fc/0x2b0
[ 9.322873] [<ffffffff812d73dd>] ? ext4_mb_new_blocks+0x24d/0x1160
[ 9.322873] [<ffffffff812d18af>] ext4_mb_good_group+0x17f/0x190
[ 9.322873] [<ffffffff812d6fa7>] ext4_mb_regular_allocator+0x2c7/0x4b0
[ 9.322873] [<ffffffff812d05ae>] ? ext4_mb_use_preallocated+0x3e/0x4a0
[ 9.322873] [<ffffffff811c9e0c>] ? kmem_cache_alloc+0x24c/0x2d0
[ 9.322873] [<ffffffff812d73dd>] ? ext4_mb_new_blocks+0x24d/0x1160
[ 9.322873] [<ffffffff812cdea4>] ? ext4_mb_initialize_context+0x84/0x1a0
[ 9.322873] [<ffffffff812d7a84>] ext4_mb_new_blocks+0x8f4/0x1160
[ 9.322873] [<ffffffff810b1bf6>] ? check_usage+0x86/0x4c0
[ 9.322873] [<ffffffff810b2f9b>] ? __lock_acquire+0x39b/0x1800
[ 9.322873] [<ffffffff810b379e>] ? __lock_acquire+0xb9e/0x1800
[ 9.322873] [<ffffffff812c28de>] ? ext4_find_extent+0x23e/0x2b0
[ 9.322873] [<ffffffff810c6fff>] ? rcu_read_lock_sched_held+0x4f/0x90
[ 9.322873] [<ffffffff811caf84>] ? __kmalloc+0x274/0x320
[ 9.322873] [<ffffffff812c28de>] ? ext4_find_extent+0x23e/0x2b0
[ 9.322873] [<ffffffff812c28de>] ? ext4_find_extent+0x23e/0x2b0
[ 9.322873] [<ffffffff812c7f5c>] ext4_ext_map_blocks+0xcfc/0x1140
[ 9.322873] [<ffffffff812de7d8>] ? ext4_es_lookup_extent+0x58/0x3a0
[ 9.322873] [<ffffffff81294803>] ? ext4_map_blocks+0x123/0x540
[ 9.322873] [<ffffffff81294803>] ? ext4_map_blocks+0x123/0x540
[ 9.322873] [<ffffffff81294827>] ext4_map_blocks+0x147/0x540
[ 9.322873] [<ffffffff81298ea8>] ? ext4_writepages+0x638/0xff0
[ 9.322873] [<ffffffff812991c4>] ext4_writepages+0x954/0xff0
[ 9.322873] [<ffffffff810b0908>] ? add_lock_to_list.clone.0+0x78/0xb0
[ 9.322873] [<ffffffff810b379e>] ? __lock_acquire+0xb9e/0x1800
[ 9.322873] [<ffffffff816fc1db>] ? _raw_spin_unlock+0x2b/0x40
[ 9.322873] [<ffffffff81223fb9>] ? wbc_attach_and_unlock_inode+0x179/0x290
[ 9.322873] [<ffffffff8116eb43>] do_writepages+0x23/0x40
[ 9.322873] [<ffffffff8115c6a5>] __filemap_fdatawrite_range+0xb5/0x100
[ 9.322873] [<ffffffff810b0908>] ? add_lock_to_list.clone.0+0x78/0xb0
[ 9.322873] [<ffffffff8115c8fc>] filemap_flush+0x1c/0x20
[ 9.322873] [<ffffffff81293bf6>] ext4_alloc_da_blocks+0x56/0x160
[ 9.322873] [<ffffffff812a7655>] ext4_rename+0x665/0x900
[ 9.322873] [<ffffffff8120c18f>] ? lock_two_nondirectories+0x7f/0x90
[ 9.322873] [<ffffffff8120c18f>] ? lock_two_nondirectories+0x7f/0x90
[ 9.322873] [<ffffffff812a7912>] ext4_rename2+0x22/0x40
[ 9.322873] [<ffffffff811fa5ec>] vfs_rename+0x27c/0x5e0
[ 9.322873] [<ffffffff811fea71>] SyS_renameat2+0x431/0x4c0
[ 9.322873] [<ffffffff811f88ce>] SyS_rename+0x1e/0x20
[ 9.322873] [<ffffffff816fc365>] entry_SYSCALL_64_fastpath+0x18/0xa8
[ 9.322873] [<ffffffff816fc31a>] ? entry_SYSCALL_64_after_swapgs+0x17/0x4aLine 358 is lock_buffer
Jan Kara
reviewerQuoted 7 lines · Nikolay Borisov
While doing some testing on today's checkout of Linus' master branch I got the following:
[ 9.302725] BUG: sleeping function called from invalid context at ./include/linux/buffer_head.h:358 [ 9.304403] in_atomic(): 1, irqs_disabled(): 0, pid: 1718, name: mount [ 9.305633] 8 locks held by mount/1718:
Yeah, this looks like a regression cause by commit 4743f83990614af "ext4:
Fix WARN_ON_ONCE in ext4_commit_super()". Arguably that cure is worse than the disease but OTOH calling ext4_commit_super() from an atomic context (like __ext4_grp_locked_error() does) sucks as well.
I'm not sure what the right fix is here. The cleanest would probably be to always drop group lock in __ext4_grp_locked_error() and make sure we always properly bail out of mballoc code on such error. But that's a non-trivial amount of work. Not sure if other ext4 people have opinion on this?
Honza
Signature · 2 lines
Jan Kara <[email protected]> SUSE Labs, CR
Theodore Ts'o
maintainerQuoted 14 lines · Jan Kara
Quoted 7 lines · Nikolay Borisov
While doing some testing on today's checkout of Linus' master branch I got the following:
[ 9.302725] BUG: sleeping function called from invalid context at ./include/linux/buffer_head.h:358 [ 9.304403] in_atomic(): 1, irqs_disabled(): 0, pid: 1718, name: mount [ 9.305633] 8 locks held by mount/1718:Yeah, this looks like a regression cause by commit
4743f83990614af"ext4:
FixWARN_ON_ONCEinext4_commit_super()". Arguably that cure is worse than the disease but OTOH callingext4_commit_super()from an atomic context (like__ext4_grp_locked_error()does) sucks as well.
Quoted 4 lines
I'm not sure what the right fix is here. The cleanest would probably be to always drop group lock in
__ext4_grp_locked_error()and make sure we always properly bail out of mballoc code on such error. But that's a non-trivial amount of work. Not sure if other ext4 people have opinion on this?
The easist way to fix this is defer the ext4_commit_super() to a workqueue. We only need this in the errors=continue case, and in that scenario we're not in a hurry when the superblock gets written out.
In fact, we probably want to be doing this for all of the errors=continue cases when we want to save the error state to the superblock, so we can do the update properly using the journal, instead of calling ext4_commit_super() which just force writes the block.
(Of course, if the journal is aborted we'll need to fall back to using ext4_commit_super, of course.)
- Ted
Quoted 15 lines · Theodore Ts'o
Quoted 14 lines · Jan Kara
Quoted 7 lines · Nikolay Borisov
While doing some testing on today's checkout of Linus' master branch I got the following:
[ 9.302725] BUG: sleeping function called from invalid context at ./include/linux/buffer_head.h:358 [ 9.304403] in_atomic(): 1, irqs_disabled(): 0, pid: 1718, name: mount [ 9.305633] 8 locks held by mount/1718:Yeah, this looks like a regression cause by commit
4743f83990614af"ext4:
FixWARN_ON_ONCEinext4_commit_super()". Arguably that cure is worse than the disease but OTOH callingext4_commit_super()from an atomic context (like__ext4_grp_locked_error()does) sucks as well.
Quoted 8 lines
Quoted 4 lines
I'm not sure what the right fix is here. The cleanest would probably be to always drop group lock in
__ext4_grp_locked_error()and make sure we always properly bail out of mballoc code on such error. But that's a non-trivial amount of work. Not sure if other ext4 people have opinion on this?The easist way to fix this is defer the
ext4_commit_super()to a workqueue. We only need this in the errors=continue case, and in that scenario we're not in a hurry when the superblock gets written out.
Is errors=continue the default option if nothing specifically is specified at mount time, since I don't have this set explicitly:
/dev/vda / ext4 rw,relatime,data=ordered 0 0
Quoted 16 lines
In fact, we probably want to be doing this for all of the errors=continue cases when we want to save the error state to the superblock, so we can do the update properly using the journal, instead of calling
ext4_commit_super()which just force writes the block.(Of course, if the journal is aborted we'll need to fall back to using
ext4_commit_super, of course.)- Ted
--
To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Theodore Ts'o
maintainerQuoted 8 lines · Nikolay Borisov
Quoted 3 lines
The easist way to fix this is defer the
ext4_commit_super()to a workqueue. We only need this in the errors=continue case, and in that scenario we're not in a hurry when the superblock gets written out.Is errors=continue the default option if nothing specifically is specified at mount time, since I don't have this set explicitly:
/dev/vda/ ext4 rw,relatime,data=ordered 0 0
Yes, it's the default. I keep wondering whether we should change the default to remount-ro or even panic, since people sometimes don't notice that the "file system has been corrupted" messages, and then they can end up losing a lot more detail if we forced them to address the issue right away.
- Ted
Quoted 8 lines · Theodore Ts'o
Quoted 7 lines · Nikolay Borisov
Quoted 3 lines
The easist way to fix this is defer the
ext4_commit_super()to a workqueue. We only need this in the errors=continue case, and in that scenario we're not in a hurry when the superblock gets written out.Is errors=continue the default option if nothing specifically is specified at mount time, since I don't have this set explicitly:
Quoted 7 lines
Quoted 1 line
/dev/vda/ ext4 rw,relatime,data=ordered 0 0Yes, it's the default. I keep wondering whether we should change the default to remount-ro or even panic, since people sometimes don't notice that the "file system has been corrupted" messages, and then they can end up losing a lot more detail if we forced them to address the issue right away.
Yes, please. :)
(At the moment I'm also trying to sort out some ext3 bug where jbd flushes some dirty pages to disk ahead of writing out a transaction but the dirty page writeback fails. Apparently the userspace program is long gone by the time this happens (I haven't been able to verify that they're actually calling fsync) and the FS doesn't shut down, but a later umount/mount/reread shows old file contents. Hence I now know about data_err=abort.)
--D
Quoted 6 lines
- Ted
--
To unsubscribe from this list: send the line "unsubscribe linux-ext4" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Quoted 11 lines · Theodore Ts'o
Quoted 7 lines · Nikolay Borisov
Quoted 3 lines
The easist way to fix this is defer the
ext4_commit_super()to a workqueue. We only need this in the errors=continue case, and in that scenario we're not in a hurry when the superblock gets written out.Is errors=continue the default option if nothing specifically is specified at mount time, since I don't have this set explicitly:
Quoted 7 lines
Quoted 1 line
/dev/vda/ ext4 rw,relatime,data=ordered 0 0Yes, it's the default. I keep wondering whether we should change the default to remount-ro or even panic, since people sometimes don't notice that the "file system has been corrupted" messages, and then they can end up losing a lot more detail if we forced them to address the issue right away.
I'd definitely be in favour of making the default "errors=remount-ro". We've been setting that explicitly for years, since otherwise people may not notice their ongoing problems until the filesystem completely explodes.
Related to that, there is a Lustre patch to handle inconsistencies between group descriptors and block/inode bitmaps by marking only the group as unusable for new allocations, instead of marking the whole filesystem in error. Is that something that is of interest to a wider audience?
Patch against RHEL7 is attached, but could be updated for newer kernels if there is interest.
Cheers, Andreas
Since we could skip corrupt block groups, this patch use ext4_warning() intead of ext4_error() to make FS not emount RO in default, also fix a leftover from upstream commit 163a203ddb36c36d4a1c942
---
fs/ext4/balloc.c +13 -28
@@ -185,25 +185,17 @@ static int ext4_init_block_bitmap(struct super_block *sb,struct ext4_sb_info *sbi =EXT4_SB (sb);ext4_fsblk_t start, tmp;int flex_bg =0 ; -struct ext4_group_info *grp;J_ASSERT_BH (bh,buffer_locked (bh));/* If checksum is bad mark all blocks used to prevent allocation * essentially implementing a per-group read-only flag. */ if (!ext4_group_desc_csum_verify (sb, block_group, gdp)) { - grp =ext4_get_group_info (sb, block_group); -if (!EXT4_MB_GRP_BBITMAP_CORRUPT (grp)) -percpu_counter_sub (&sbi->s_freeclusters_counter, - grp->bb_free); -set_bit (EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT , &grp->bb_state); -if (!EXT4_MB_GRP_IBITMAP_CORRUPT (grp)) { -int count; - count =ext4_free_inodes_count (sb, gdp); -percpu_counter_sub (&sbi->s_freeinodes_counter, - count); - } -set_bit (EXT4_GROUP_INFO_IBITMAP_CORRUPT_BIT , &grp->bb_state); +ext4_corrupted_block_group (sb, block_group, +EXT4_GROUP_INFO_BBITMAP_CORRUPT | +EXT4_GROUP_INFO_IBITMAP_CORRUPT , +"Checksum bad for group %u" , + block_group);return -EIO ; }memset (bh->b_data,0 , sb->s_blocksize);
@@ -367,8 +359,6 @@ static void ext4_validate_block_bitmap(struct super_block *sb, struct buffer_head *bh) {ext4_fsblk_t blk; -struct ext4_group_info *grp =ext4_get_group_info (sb, block_group); -struct ext4_sb_info *sbi =EXT4_SB (sb);if (buffer_verified (bh))return ;
@@ -377,22 +367,19 @@ static void ext4_validate_block_bitmap(struct super_block *sb, blk =ext4_valid_block_bitmap (sb, desc, block_group, bh);if (unlikely (blk !=0 )) {ext4_unlock_group (sb, block_group); -ext4_error (sb,"bg %u: block %llu: invalid block bitmap" , - block_group, blk); -if (!EXT4_MB_GRP_BBITMAP_CORRUPT (grp)) -percpu_counter_sub (&sbi->s_freeclusters_counter, - grp->bb_free); -set_bit (EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT , &grp->bb_state); +ext4_corrupted_block_group (sb, block_group, +EXT4_GROUP_INFO_BBITMAP_CORRUPT , +"bg %u: block %llu: invalid block bitmap" , + block_group, blk);return ; }if (unlikely (!ext4_block_bitmap_csum_verify (sb, block_group, desc, bh))) {ext4_unlock_group (sb, block_group); -ext4_error (sb,"bg %u: bad block bitmap checksum" , block_group); -if (!EXT4_MB_GRP_BBITMAP_CORRUPT (grp)) -percpu_counter_sub (&sbi->s_freeclusters_counter, - grp->bb_free); -set_bit (EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT , &grp->bb_state); +ext4_corrupted_block_group (sb, block_group, +EXT4_GROUP_INFO_BBITMAP_CORRUPT , +"bg %u: bad block bitmap checksum" , + block_group);return ; }set_buffer_verified (bh);
@@ -445,8 +432,6 @@ ext4_read_block_bitmap_nowait(struct super_block *sb, ext4_group_t block_group)set_buffer_uptodate (bh);ext4_unlock_group (sb, block_group);unlock_buffer (bh); -if (err) -ext4_error (sb,"Checksum bad for grp %u" , block_group);return bh; }ext4_unlock_group (sb, block_group);
fs/ext4/ext4.h +15 -0
@@ -91,6 +91,17 @@ typedef __u32 ext4_lblk_t;/* data type for block group number */ typedef unsigned int ext4_group_t ; +void __ext4_corrupted_block_group (struct super_block *sb, +ext4_group_t group,unsigned int flags, +const char *function,unsigned int line); + +#define ext4_corrupted_block_group (sb, group, flags, fmt, ...) \ + do { \ + __ext4_warning(sb, __func__, __LINE__, fmt, \ + ##__VA_ARGS__); \ + __ext4_corrupted_block_group(sb, group, flags, \ + __func__, __LINE__); \ + } while (0)/* * Flags used in mballoc's allocation_context flags field. *
@@ -2673,7 +2684,11 @@ struct ext4_group_info {#define EXT4_GROUP_INFO_NEED_INIT_BIT 0#define EXT4_GROUP_INFO_WAS_TRIMMED_BIT 1#define EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT 2 +#define EXT4_GROUP_INFO_BBITMAP_CORRUPT \ + (1 << EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT)#define EXT4_GROUP_INFO_IBITMAP_CORRUPT_BIT 3 +#define EXT4_GROUP_INFO_IBITMAP_CORRUPT \ + (1 << EXT4_GROUP_INFO_IBITMAP_CORRUPT_BIT)#define EXT4_MB_GRP_NEED_INIT (grp) \ (test_bit(EXT4_GROUP_INFO_NEED_INIT_BIT, &((grp)->bb_state)))
fs/ext4/ialloc.c +11 -35
75 lines not on this page · raw message
fs/ext4/mballoc.c +44 -51
198 lines not on this page · raw message
fs/ext4/super.c +31 -0
@@ -633,6 +633,37 @@ void __ext4_warning(struct super_block *sb, const char *function,va_end (args); } +void __ext4_corrupted_block_group (struct super_block *sb,ext4_group_t group, +unsigned int flags,const char *function, +unsigned int line) +{ +struct ext4_sb_info *sbi =EXT4_SB (sb); +struct ext4_group_info *grp =ext4_get_group_info (sb, group); +struct ext4_group_desc *gdp =ext4_get_group_desc (sb, group,NULL ); + +if (flags &EXT4_GROUP_INFO_BBITMAP_CORRUPT && + !EXT4_MB_GRP_BBITMAP_CORRUPT (grp)) { +percpu_counter_sub (&sbi->s_freeclusters_counter, + grp->bb_free); +set_bit (EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT , + &grp->bb_state); + } + +if (flags &EXT4_GROUP_INFO_IBITMAP_CORRUPT && + !EXT4_MB_GRP_IBITMAP_CORRUPT (grp)) { +if (gdp) { +int count; + + count =ext4_free_inodes_count (sb, gdp); +percpu_counter_sub (&sbi->s_freeinodes_counter, + count); + } +set_bit (EXT4_GROUP_INFO_IBITMAP_CORRUPT_BIT , + &grp->bb_state); + } +save_error_info (sb, function, line); +} + void __ext4_grp_locked_error(const char *function, unsigned int line, struct super_block *sb, ext4_group_t grp, unsigned long ino, ext4_fsblk_t block,