add patch fix-scheduling-in-atomic-on-group-checksum-failure
[ext4-patch-queue.git] / fix-scheduling-in-atomic-on-group-checksum-failure
blobc1aaff920c56d9828198a8fb03e06eda25b94d04
1 ext4: fix scheduling in atomic on group checksum failure
3 From: Jan Kara <jack@suse.cz>
5 When block group checksum is wrong, we call ext4_error() while holding
6 group spinlock from ext4_init_block_bitmap() or
7 ext4_init_inode_bitmap() which results in scheduling while in atomic.
8 Fix the issue by calling ext4_error() later after dropping the spinlock.
10 CC: stable@vger.kernel.org
11 Reported-by: Dmitry Vyukov <dvyukov@google.com>
12 Signed-off-by: Jan Kara <jack@suse.cz>
13 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
14 Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
15 ---
16  fs/ext4/balloc.c | 7 ++++---
17  fs/ext4/ialloc.c | 6 ++++--
18  2 files changed, 8 insertions(+), 5 deletions(-)
20 diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
21 index ec0668a60678..fe1f50fe764f 100644
22 --- a/fs/ext4/balloc.c
23 +++ b/fs/ext4/balloc.c
24 @@ -191,7 +191,6 @@ static int ext4_init_block_bitmap(struct super_block *sb,
25         /* If checksum is bad mark all blocks used to prevent allocation
26          * essentially implementing a per-group read-only flag. */
27         if (!ext4_group_desc_csum_verify(sb, block_group, gdp)) {
28 -               ext4_error(sb, "Checksum bad for group %u", block_group);
29                 grp = ext4_get_group_info(sb, block_group);
30                 if (!EXT4_MB_GRP_BBITMAP_CORRUPT(grp))
31                         percpu_counter_sub(&sbi->s_freeclusters_counter,
32 @@ -442,14 +441,16 @@ ext4_read_block_bitmap_nowait(struct super_block *sb, ext4_group_t block_group)
33         }
34         ext4_lock_group(sb, block_group);
35         if (desc->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) {
37                 err = ext4_init_block_bitmap(sb, bh, block_group, desc);
38                 set_bitmap_uptodate(bh);
39                 set_buffer_uptodate(bh);
40                 ext4_unlock_group(sb, block_group);
41                 unlock_buffer(bh);
42 -               if (err)
43 +               if (err) {
44 +                       ext4_error(sb, "Failed to init block bitmap for group "
45 +                                  "%u: %d", block_group, err);
46                         goto out;
47 +               }
48                 goto verify;
49         }
50         ext4_unlock_group(sb, block_group);
51 diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
52 index 3fcfd50a2e8a..acc0ad56bf2f 100644
53 --- a/fs/ext4/ialloc.c
54 +++ b/fs/ext4/ialloc.c
55 @@ -76,7 +76,6 @@ static int ext4_init_inode_bitmap(struct super_block *sb,
56         /* If checksum is bad mark all blocks and inodes use to prevent
57          * allocation, essentially implementing a per-group read-only flag. */
58         if (!ext4_group_desc_csum_verify(sb, block_group, gdp)) {
59 -               ext4_error(sb, "Checksum bad for group %u", block_group);
60                 grp = ext4_get_group_info(sb, block_group);
61                 if (!EXT4_MB_GRP_BBITMAP_CORRUPT(grp))
62                         percpu_counter_sub(&sbi->s_freeclusters_counter,
63 @@ -191,8 +190,11 @@ ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group)
64                 set_buffer_verified(bh);
65                 ext4_unlock_group(sb, block_group);
66                 unlock_buffer(bh);
67 -               if (err)
68 +               if (err) {
69 +                       ext4_error(sb, "Failed to init inode bitmap for group "
70 +                                  "%u: %d", block_group, err);
71                         goto out;
72 +               }
73                 return bh;
74         }
75         ext4_unlock_group(sb, block_group);
76 -- 
77 2.6.2
80 To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
81 the body of a message to majordomo@vger.kernel.org
82 More majordomo info at  http://vger.kernel.org/majordomo-info.html