diff options
Diffstat (limited to 'fs/ext4/super.c')
| -rw-r--r-- | fs/ext4/super.c | 68 | 
1 files changed, 42 insertions, 26 deletions
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 58987b5c514b..a63c7b0a10cf 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -60,6 +60,7 @@ static struct ext4_lazy_init *ext4_li_info;  static struct mutex ext4_li_mtx;  static struct ext4_features *ext4_feat;  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 *,  			     unsigned long journal_devnum); @@ -84,7 +85,7 @@ static void ext4_unregister_li_request(struct super_block *sb);  static void ext4_clear_request_list(void);  static int ext4_reserve_clusters(struct ext4_sb_info *, ext4_fsblk_t); -#if !defined(CONFIG_EXT2_FS) && !defined(CONFIG_EXT2_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT23) +#if !defined(CONFIG_EXT2_FS) && !defined(CONFIG_EXT2_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT2)  static struct file_system_type ext2_fs_type = {  	.owner		= THIS_MODULE,  	.name		= "ext2", @@ -100,7 +101,6 @@ MODULE_ALIAS("ext2");  #endif -#if !defined(CONFIG_EXT3_FS) && !defined(CONFIG_EXT3_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT23)  static struct file_system_type ext3_fs_type = {  	.owner		= THIS_MODULE,  	.name		= "ext3", @@ -111,9 +111,6 @@ static struct file_system_type ext3_fs_type = {  MODULE_ALIAS_FS("ext3");  MODULE_ALIAS("ext3");  #define IS_EXT3_SB(sb) ((sb)->s_bdev->bd_holder == &ext3_fs_type) -#else -#define IS_EXT3_SB(sb) (0) -#endif  static int ext4_verify_csum_type(struct super_block *sb,  				 struct ext4_super_block *es) @@ -325,6 +322,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; @@ -1394,9 +1407,9 @@ static const struct mount_opts {  	{Opt_stripe, 0, MOPT_GTE0},  	{Opt_resuid, 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_ordered, EXT4_MOUNT_ORDERED_DATA, MOPT_NO_EXT2 | MOPT_DATAJ},  	{Opt_data_writeback, EXT4_MOUNT_WRITEBACK_DATA, @@ -1763,10 +1776,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  } @@ -3643,6 +3656,8 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)  		}  		if (test_opt(sb, DELALLOC))  			clear_opt(sb, DELALLOC); +	} else { +		sb->s_iflags |= SB_I_CGROUPWB;  	}  	sb->s_flags = (sb->s_flags & ~MS_POSIXACL) | @@ -4275,9 +4290,10 @@ no_journal:  				 "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)  		mod_timer(&sbi->s_err_report, jiffies + 300*HZ); /* 5 minutes */ @@ -4617,7 +4633,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)) {  		/* @@ -4665,7 +4681,8 @@ static int ext4_commit_super(struct super_block *sb, int sync)  	ext4_superblock_csum_set(sb);  	mark_buffer_dirty(sbh);  	if (sync) { -		error = sync_dirty_buffer(sbh); +		error = __sync_dirty_buffer(sbh, +			test_opt(sb, BARRIER) ? WRITE_FUA : WRITE_SYNC);  		if (error)  			return error; @@ -4833,10 +4850,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) @@ -4854,8 +4872,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;  } @@ -5500,7 +5521,7 @@ static struct dentry *ext4_mount(struct file_system_type *fs_type, int flags,  	return mount_bdev(fs_type, flags, dev_name, data, ext4_fill_super);  } -#if !defined(CONFIG_EXT2_FS) && !defined(CONFIG_EXT2_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT23) +#if !defined(CONFIG_EXT2_FS) && !defined(CONFIG_EXT2_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT2)  static inline void register_as_ext2(void)  {  	int err = register_filesystem(&ext2_fs_type); @@ -5530,7 +5551,6 @@ static inline void unregister_as_ext2(void) { }  static inline int ext2_feature_set_ok(struct super_block *sb) { return 0; }  #endif -#if !defined(CONFIG_EXT3_FS) && !defined(CONFIG_EXT3_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT23)  static inline void register_as_ext3(void)  {  	int err = register_filesystem(&ext3_fs_type); @@ -5556,11 +5576,6 @@ static inline int ext3_feature_set_ok(struct super_block *sb)  		return 0;  	return 1;  } -#else -static inline void register_as_ext3(void) { } -static inline void unregister_as_ext3(void) { } -static inline int ext3_feature_set_ok(struct super_block *sb) { return 0; } -#endif  static struct file_system_type ext4_fs_type = {  	.owner		= THIS_MODULE, @@ -5610,6 +5625,7 @@ static int __init ext4_init_fs(void)  {  	int i, err; +	ratelimit_state_init(&ext4_mount_msg_ratelimit, 30 * HZ, 64);  	ext4_li_info = NULL;  	mutex_init(&ext4_li_mtx);  |