These changes are a raw update to a vanilla kernel 4.1.10, with the
[kvmfornfv.git] / kernel / fs / ext4 / super.c
index ca12aff..ff89971 100644 (file)
@@ -324,6 +324,22 @@ static void save_error_info(struct super_block *sb, const char *func,
        ext4_commit_super(sb, 1);
 }
 
+/*
+ * 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 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 ext4_journal_commit_callback(journal_t *journal, transaction_t *txn)
 {
        struct super_block              *sb = journal->j_private;
@@ -1738,10 +1754,10 @@ static inline void ext4_show_quota_options(struct seq_file *seq,
        }
 
        if (sbi->s_qf_names[USRQUOTA])
-               seq_printf(seq, ",usrjquota=%s", sbi->s_qf_names[USRQUOTA]);
+               seq_show_option(seq, "usrjquota", sbi->s_qf_names[USRQUOTA]);
 
        if (sbi->s_qf_names[GRPQUOTA])
-               seq_printf(seq, ",grpjquota=%s", sbi->s_qf_names[GRPQUOTA]);
+               seq_show_option(seq, "grpjquota", sbi->s_qf_names[GRPQUOTA]);
 #endif
 }
 
@@ -4591,7 +4607,7 @@ static int ext4_commit_super(struct super_block *sb, int sync)
        struct buffer_head *sbh = EXT4_SB(sb)->s_sbh;
        int error = 0;
 
-       if (!sbh)
+       if (!sbh || block_device_ejected(sb))
                return error;
        if (buffer_write_io_error(sbh)) {
                /*
@@ -4807,10 +4823,11 @@ static int ext4_freeze(struct super_block *sb)
                error = jbd2_journal_flush(journal);
                if (error < 0)
                        goto out;
+
+               /* Journal blocked and flushed, clear needs_recovery flag. */
+               EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
        }
 
-       /* Journal blocked and flushed, clear needs_recovery flag. */
-       EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
        error = ext4_commit_super(sb, 1);
 out:
        if (journal)
@@ -4828,8 +4845,11 @@ static int ext4_unfreeze(struct super_block *sb)
        if (sb->s_flags & MS_RDONLY)
                return 0;
 
-       /* Reset the needs_recovery flag before the fs is unlocked. */
-       EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
+       if (EXT4_SB(sb)->s_journal) {
+               /* Reset the needs_recovery flag before the fs is unlocked. */
+               EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
+       }
+
        ext4_commit_super(sb, 1);
        return 0;
 }