diff options
author | Li Jun <jun.li@nxp.com> | 2015-12-30 14:36:31 +0800 |
---|---|---|
committer | Nitin Garg <nitin.garg@nxp.com> | 2016-01-14 11:03:04 -0600 |
commit | 4eeb44518c53cb7fb98911ee6c8e8b980a931eed (patch) | |
tree | d3fc69f310774e5fd71927415506f6a483c4bebf /fs/ext3 | |
parent | 7e4c99aa45b6b4b9f9fbf1ad6bc478dddd53f31a (diff) |
MLK-12091 fs: ext3: add kludge to avoid an oops after the disk disappears
The idea of this patch is borrowed from the commit of ext4:
7c2e70879fc0949b4220ee61b7c4553f6976a94d, which is kept in upstream
as a kludge for ext4 driver, since ext3 driver has the same problem
but obsolete in upstream 4.3, we port it for ext3 for internal 4.1
tree.
Signed-off-by: Li Jun <jun.li@nxp.com>
Diffstat (limited to 'fs/ext3')
-rw-r--r-- | fs/ext3/super.c | 24 |
1 files changed, 21 insertions, 3 deletions
diff --git a/fs/ext3/super.c b/fs/ext3/super.c index a9312f0a54e5..daefedd8f58f 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c @@ -412,6 +412,22 @@ static void dump_orphan_list(struct super_block *sb, struct ext3_sb_info *sbi) } } +/* + * The del_gendisk() function uninitializes the disk-specific data + * structures, including the bdi structure, without telling anyone + * else. Once this happens, any attempt to call mark_buffer_dirty() + * (for example, by ext4_commit_super), will cause a kernel OOPS. + * This is a kludge to prevent these oops until we can put in a proper + * hook in del_gendisk() to inform the VFS and file system layers. + */ +static int ext3_block_device_ejected(struct super_block *sb) +{ + struct inode *bd_inode = sb->s_bdev->bd_inode; + struct backing_dev_info *bdi = inode_to_bdi(bd_inode); + + return bdi->dev == NULL; +} + static void ext3_put_super (struct super_block * sb) { struct ext3_sb_info *sbi = EXT3_SB(sb); @@ -428,9 +444,11 @@ static void ext3_put_super (struct super_block * sb) if (!(sb->s_flags & MS_RDONLY)) { EXT3_CLEAR_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER); es->s_state = cpu_to_le16(sbi->s_mount_state); - BUFFER_TRACE(sbi->s_sbh, "marking dirty"); - mark_buffer_dirty(sbi->s_sbh); - ext3_commit_super(sb, es, 1); + if (!ext3_block_device_ejected(sb)) { + BUFFER_TRACE(sbi->s_sbh, "marking dirty"); + mark_buffer_dirty(sbi->s_sbh); + ext3_commit_super(sb, es, 1); + } } for (i = 0; i < sbi->s_gdb_count; i++) |