|
@@ -60,6 +60,7 @@ static struct ext4_lazy_init *ext4_li_info;
|
|
static struct mutex ext4_li_mtx;
|
|
static struct mutex ext4_li_mtx;
|
|
static struct ext4_features *ext4_feat;
|
|
static struct ext4_features *ext4_feat;
|
|
static int ext4_mballoc_ready;
|
|
static int ext4_mballoc_ready;
|
|
|
|
+static struct ratelimit_state ext4_mount_msg_ratelimit;
|
|
|
|
|
|
static int ext4_load_journal(struct super_block *, struct ext4_super_block *,
|
|
static int ext4_load_journal(struct super_block *, struct ext4_super_block *,
|
|
unsigned long journal_devnum);
|
|
unsigned long journal_devnum);
|
|
@@ -321,6 +322,22 @@ static void save_error_info(struct super_block *sb, const char *func,
|
|
ext4_commit_super(sb, 1);
|
|
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)
|
|
static void ext4_journal_commit_callback(journal_t *journal, transaction_t *txn)
|
|
{
|
|
{
|
|
struct super_block *sb = journal->j_private;
|
|
struct super_block *sb = journal->j_private;
|
|
@@ -1390,9 +1407,9 @@ static const struct mount_opts {
|
|
{Opt_stripe, 0, MOPT_GTE0},
|
|
{Opt_stripe, 0, MOPT_GTE0},
|
|
{Opt_resuid, 0, MOPT_GTE0},
|
|
{Opt_resuid, 0, MOPT_GTE0},
|
|
{Opt_resgid, 0, MOPT_GTE0},
|
|
{Opt_resgid, 0, MOPT_GTE0},
|
|
- {Opt_journal_dev, 0, MOPT_GTE0},
|
|
|
|
- {Opt_journal_path, 0, MOPT_STRING},
|
|
|
|
- {Opt_journal_ioprio, 0, MOPT_GTE0},
|
|
|
|
|
|
+ {Opt_journal_dev, 0, MOPT_NO_EXT2 | MOPT_GTE0},
|
|
|
|
+ {Opt_journal_path, 0, MOPT_NO_EXT2 | MOPT_STRING},
|
|
|
|
+ {Opt_journal_ioprio, 0, MOPT_NO_EXT2 | MOPT_GTE0},
|
|
{Opt_data_journal, EXT4_MOUNT_JOURNAL_DATA, MOPT_NO_EXT2 | MOPT_DATAJ},
|
|
{Opt_data_journal, EXT4_MOUNT_JOURNAL_DATA, MOPT_NO_EXT2 | MOPT_DATAJ},
|
|
{Opt_data_ordered, EXT4_MOUNT_ORDERED_DATA, MOPT_NO_EXT2 | MOPT_DATAJ},
|
|
{Opt_data_ordered, EXT4_MOUNT_ORDERED_DATA, MOPT_NO_EXT2 | MOPT_DATAJ},
|
|
{Opt_data_writeback, EXT4_MOUNT_WRITEBACK_DATA,
|
|
{Opt_data_writeback, EXT4_MOUNT_WRITEBACK_DATA,
|
|
@@ -3639,6 +3656,8 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
|
|
}
|
|
}
|
|
if (test_opt(sb, DELALLOC))
|
|
if (test_opt(sb, DELALLOC))
|
|
clear_opt(sb, DELALLOC);
|
|
clear_opt(sb, DELALLOC);
|
|
|
|
+ } else {
|
|
|
|
+ sb->s_iflags |= SB_I_CGROUPWB;
|
|
}
|
|
}
|
|
|
|
|
|
sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
|
|
sb->s_flags = (sb->s_flags & ~MS_POSIXACL) |
|
|
@@ -4271,9 +4290,10 @@ no_journal:
|
|
"the device does not support discard");
|
|
"the device does not support discard");
|
|
}
|
|
}
|
|
|
|
|
|
- ext4_msg(sb, KERN_INFO, "mounted filesystem with%s. "
|
|
|
|
- "Opts: %s%s%s", descr, sbi->s_es->s_mount_opts,
|
|
|
|
- *sbi->s_es->s_mount_opts ? "; " : "", orig_data);
|
|
|
|
|
|
+ if (___ratelimit(&ext4_mount_msg_ratelimit, "EXT4-fs mount"))
|
|
|
|
+ ext4_msg(sb, KERN_INFO, "mounted filesystem with%s. "
|
|
|
|
+ "Opts: %s%s%s", descr, sbi->s_es->s_mount_opts,
|
|
|
|
+ *sbi->s_es->s_mount_opts ? "; " : "", orig_data);
|
|
|
|
|
|
if (es->s_error_count)
|
|
if (es->s_error_count)
|
|
mod_timer(&sbi->s_err_report, jiffies + 300*HZ); /* 5 minutes */
|
|
mod_timer(&sbi->s_err_report, jiffies + 300*HZ); /* 5 minutes */
|
|
@@ -4613,7 +4633,7 @@ static int ext4_commit_super(struct super_block *sb, int sync)
|
|
struct buffer_head *sbh = EXT4_SB(sb)->s_sbh;
|
|
struct buffer_head *sbh = EXT4_SB(sb)->s_sbh;
|
|
int error = 0;
|
|
int error = 0;
|
|
|
|
|
|
- if (!sbh)
|
|
|
|
|
|
+ if (!sbh || block_device_ejected(sb))
|
|
return error;
|
|
return error;
|
|
if (buffer_write_io_error(sbh)) {
|
|
if (buffer_write_io_error(sbh)) {
|
|
/*
|
|
/*
|
|
@@ -4661,7 +4681,8 @@ static int ext4_commit_super(struct super_block *sb, int sync)
|
|
ext4_superblock_csum_set(sb);
|
|
ext4_superblock_csum_set(sb);
|
|
mark_buffer_dirty(sbh);
|
|
mark_buffer_dirty(sbh);
|
|
if (sync) {
|
|
if (sync) {
|
|
- error = sync_dirty_buffer(sbh);
|
|
|
|
|
|
+ error = __sync_dirty_buffer(sbh,
|
|
|
|
+ test_opt(sb, BARRIER) ? WRITE_FUA : WRITE_SYNC);
|
|
if (error)
|
|
if (error)
|
|
return error;
|
|
return error;
|
|
|
|
|
|
@@ -4829,10 +4850,11 @@ static int ext4_freeze(struct super_block *sb)
|
|
error = jbd2_journal_flush(journal);
|
|
error = jbd2_journal_flush(journal);
|
|
if (error < 0)
|
|
if (error < 0)
|
|
goto out;
|
|
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);
|
|
error = ext4_commit_super(sb, 1);
|
|
out:
|
|
out:
|
|
if (journal)
|
|
if (journal)
|
|
@@ -4850,8 +4872,11 @@ static int ext4_unfreeze(struct super_block *sb)
|
|
if (sb->s_flags & MS_RDONLY)
|
|
if (sb->s_flags & MS_RDONLY)
|
|
return 0;
|
|
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);
|
|
ext4_commit_super(sb, 1);
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
@@ -5600,6 +5625,7 @@ static int __init ext4_init_fs(void)
|
|
{
|
|
{
|
|
int i, err;
|
|
int i, err;
|
|
|
|
|
|
|
|
+ ratelimit_state_init(&ext4_mount_msg_ratelimit, 30 * HZ, 64);
|
|
ext4_li_info = NULL;
|
|
ext4_li_info = NULL;
|
|
mutex_init(&ext4_li_mtx);
|
|
mutex_init(&ext4_li_mtx);
|
|
|
|
|