diff options
Diffstat (limited to 'fs/ext4/super.c')
| -rw-r--r-- | fs/ext4/super.c | 121 | 
1 files changed, 74 insertions, 47 deletions
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index b9693680463a..7dc94f3e18e6 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -667,9 +667,6 @@ static void ext4_handle_error(struct super_block *sb, bool force_ro, int error,  			ext4_commit_super(sb);  	} -	if (sb_rdonly(sb) || continue_fs) -		return; -  	/*  	 * We force ERRORS_RO behavior when system is rebooting. Otherwise we  	 * could panic during 'reboot -f' as the underlying device got already @@ -679,6 +676,10 @@ static void ext4_handle_error(struct super_block *sb, bool force_ro, int error,  		panic("EXT4-fs (device %s): panic forced after error\n",  			sb->s_id);  	} + +	if (sb_rdonly(sb) || continue_fs) +		return; +  	ext4_msg(sb, KERN_CRIT, "Remounting filesystem read-only");  	/*  	 * Make sure updated value of ->s_mount_flags will be visible before @@ -1688,7 +1689,7 @@ enum {  	Opt_dioread_nolock, Opt_dioread_lock,  	Opt_discard, Opt_nodiscard, Opt_init_itable, Opt_noinit_itable,  	Opt_max_dir_size_kb, Opt_nojournal_checksum, Opt_nombcache, -	Opt_prefetch_block_bitmaps, +	Opt_no_prefetch_block_bitmaps, Opt_mb_optimize_scan,  #ifdef CONFIG_EXT4_DEBUG  	Opt_fc_debug_max_replay, Opt_fc_debug_force  #endif @@ -1788,7 +1789,9 @@ static const match_table_t tokens = {  	{Opt_inlinecrypt, "inlinecrypt"},  	{Opt_nombcache, "nombcache"},  	{Opt_nombcache, "no_mbcache"},	/* for backward compatibility */ -	{Opt_prefetch_block_bitmaps, "prefetch_block_bitmaps"}, +	{Opt_removed, "prefetch_block_bitmaps"}, +	{Opt_no_prefetch_block_bitmaps, "no_prefetch_block_bitmaps"}, +	{Opt_mb_optimize_scan, "mb_optimize_scan=%d"},  	{Opt_removed, "check=none"},	/* mount option from ext2/3 */  	{Opt_removed, "nocheck"},	/* mount option from ext2/3 */  	{Opt_removed, "reservation"},	/* mount option from ext2/3 */ @@ -1821,6 +1824,8 @@ static ext4_fsblk_t get_sb_block(void **data)  }  #define DEFAULT_JOURNAL_IOPRIO (IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 3)) +#define DEFAULT_MB_OPTIMIZE_SCAN	(-1) +  static const char deprecated_msg[] =  	"Mount option \"%s\" will be removed by %s\n"  	"Contact [email protected] if you think we should keep it.\n"; @@ -2007,8 +2012,9 @@ static const struct mount_opts {  	{Opt_max_dir_size_kb, 0, MOPT_GTE0},  	{Opt_test_dummy_encryption, 0, MOPT_STRING},  	{Opt_nombcache, EXT4_MOUNT_NO_MBCACHE, MOPT_SET}, -	{Opt_prefetch_block_bitmaps, EXT4_MOUNT_PREFETCH_BLOCK_BITMAPS, +	{Opt_no_prefetch_block_bitmaps, EXT4_MOUNT_NO_PREFETCH_BLOCK_BITMAPS,  	 MOPT_SET}, +	{Opt_mb_optimize_scan, EXT4_MOUNT2_MB_OPTIMIZE_SCAN, MOPT_GTE0},  #ifdef CONFIG_EXT4_DEBUG  	{Opt_fc_debug_force, EXT4_MOUNT2_JOURNAL_FAST_COMMIT,  	 MOPT_SET | MOPT_2 | MOPT_EXT4_ONLY}, @@ -2090,9 +2096,15 @@ static int ext4_set_test_dummy_encryption(struct super_block *sb,  	return 1;  } +struct ext4_parsed_options { +	unsigned long journal_devnum; +	unsigned int journal_ioprio; +	int mb_optimize_scan; +}; +  static int handle_mount_opt(struct super_block *sb, char *opt, int token, -			    substring_t *args, unsigned long *journal_devnum, -			    unsigned int *journal_ioprio, int is_remount) +			    substring_t *args, struct ext4_parsed_options *parsed_opts, +			    int is_remount)  {  	struct ext4_sb_info *sbi = EXT4_SB(sb);  	const struct mount_opts *m; @@ -2249,7 +2261,7 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token,  				 "Cannot specify journal on remount");  			return -1;  		} -		*journal_devnum = arg; +		parsed_opts->journal_devnum = arg;  	} else if (token == Opt_journal_path) {  		char *journal_path;  		struct inode *journal_inode; @@ -2285,7 +2297,7 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token,  			return -1;  		} -		*journal_devnum = new_encode_dev(journal_inode->i_rdev); +		parsed_opts->journal_devnum = new_encode_dev(journal_inode->i_rdev);  		path_put(&path);  		kfree(journal_path);  	} else if (token == Opt_journal_ioprio) { @@ -2294,7 +2306,7 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token,  				 " (must be 0-7)");  			return -1;  		} -		*journal_ioprio = +		parsed_opts->journal_ioprio =  			IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, arg);  	} else if (token == Opt_test_dummy_encryption) {  		return ext4_set_test_dummy_encryption(sb, opt, &args[0], @@ -2384,6 +2396,13 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token,  		sbi->s_mount_opt |= m->mount_opt;  	} else if (token == Opt_data_err_ignore) {  		sbi->s_mount_opt &= ~m->mount_opt; +	} else if (token == Opt_mb_optimize_scan) { +		if (arg != 0 && arg != 1) { +			ext4_msg(sb, KERN_WARNING, +				 "mb_optimize_scan should be set to 0 or 1."); +			return -1; +		} +		parsed_opts->mb_optimize_scan = arg;  	} else {  		if (!args->from)  			arg = 1; @@ -2411,8 +2430,7 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token,  }  static int parse_options(char *options, struct super_block *sb, -			 unsigned long *journal_devnum, -			 unsigned int *journal_ioprio, +			 struct ext4_parsed_options *ret_opts,  			 int is_remount)  {  	struct ext4_sb_info __maybe_unused *sbi = EXT4_SB(sb); @@ -2432,8 +2450,8 @@ static int parse_options(char *options, struct super_block *sb,  		 */  		args[0].to = args[0].from = NULL;  		token = match_token(p, tokens, args); -		if (handle_mount_opt(sb, p, token, args, journal_devnum, -				     journal_ioprio, is_remount) < 0) +		if (handle_mount_opt(sb, p, token, args, ret_opts, +				     is_remount) < 0)  			return 0;  	}  #ifdef CONFIG_QUOTA @@ -3023,9 +3041,6 @@ static void ext4_orphan_cleanup(struct super_block *sb,  		sb->s_flags &= ~SB_RDONLY;  	}  #ifdef CONFIG_QUOTA -	/* Needed for iput() to work correctly and not trash data */ -	sb->s_flags |= SB_ACTIVE; -  	/*  	 * Turn on quotas which were not enabled for read-only mounts if  	 * filesystem has quota feature, so that they are updated correctly. @@ -3691,11 +3706,11 @@ static struct ext4_li_request *ext4_li_request_new(struct super_block *sb,  	elr->lr_super = sb;  	elr->lr_first_not_zeroed = start; -	if (test_opt(sb, PREFETCH_BLOCK_BITMAPS)) -		elr->lr_mode = EXT4_LI_MODE_PREFETCH_BBITMAP; -	else { +	if (test_opt(sb, NO_PREFETCH_BLOCK_BITMAPS)) {  		elr->lr_mode = EXT4_LI_MODE_ITABLE;  		elr->lr_next_group = start; +	} else { +		elr->lr_mode = EXT4_LI_MODE_PREFETCH_BBITMAP;  	}  	/* @@ -3726,7 +3741,7 @@ int ext4_register_li_request(struct super_block *sb,  		goto out;  	} -	if (!test_opt(sb, PREFETCH_BLOCK_BITMAPS) && +	if (test_opt(sb, NO_PREFETCH_BLOCK_BITMAPS) &&  	    (first_not_zeroed == ngroups || sb_rdonly(sb) ||  	     !test_opt(sb, INIT_INODE_TABLE)))  		goto out; @@ -4015,7 +4030,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)  	ext4_fsblk_t sb_block = get_sb_block(&data);  	ext4_fsblk_t logical_sb_block;  	unsigned long offset = 0; -	unsigned long journal_devnum = 0;  	unsigned long def_mount_opts;  	struct inode *root;  	const char *descr; @@ -4026,8 +4040,13 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)  	int needs_recovery, has_huge_files;  	__u64 blocks_count;  	int err = 0; -	unsigned int journal_ioprio = DEFAULT_JOURNAL_IOPRIO;  	ext4_group_t first_not_zeroed; +	struct ext4_parsed_options parsed_opts; + +	/* Set defaults for the variables that will be set during parsing */ +	parsed_opts.journal_ioprio = DEFAULT_JOURNAL_IOPRIO; +	parsed_opts.journal_devnum = 0; +	parsed_opts.mb_optimize_scan = DEFAULT_MB_OPTIMIZE_SCAN;  	if ((data && !orig_data) || !sbi)  		goto out_free_base; @@ -4273,8 +4292,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)  					      GFP_KERNEL);  		if (!s_mount_opts)  			goto failed_mount; -		if (!parse_options(s_mount_opts, sb, &journal_devnum, -				   &journal_ioprio, 0)) { +		if (!parse_options(s_mount_opts, sb, &parsed_opts, 0)) {  			ext4_msg(sb, KERN_WARNING,  				 "failed to parse options in superblock: %s",  				 s_mount_opts); @@ -4282,8 +4300,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)  		kfree(s_mount_opts);  	}  	sbi->s_def_mount_opt = sbi->s_mount_opt; -	if (!parse_options((char *) data, sb, &journal_devnum, -			   &journal_ioprio, 0)) +	if (!parse_options((char *) data, sb, &parsed_opts, 0))  		goto failed_mount;  #ifdef CONFIG_UNICODE @@ -4292,12 +4309,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)  		struct unicode_map *encoding;  		__u16 encoding_flags; -		if (ext4_has_feature_encrypt(sb)) { -			ext4_msg(sb, KERN_ERR, -				 "Can't mount with encoding and encryption"); -			goto failed_mount; -		} -  		if (ext4_sb_read_encoding(es, &encoding_info,  					  &encoding_flags)) {  			ext4_msg(sb, KERN_ERR, @@ -4774,7 +4785,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)  	 * root first: it may be modified in the journal!  	 */  	if (!test_opt(sb, NOLOAD) && ext4_has_feature_journal(sb)) { -		err = ext4_load_journal(sb, es, journal_devnum); +		err = ext4_load_journal(sb, es, parsed_opts.journal_devnum);  		if (err)  			goto failed_mount3a;  	} else if (test_opt(sb, NOLOAD) && !sb_rdonly(sb) && @@ -4874,7 +4885,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)  		goto failed_mount_wq;  	} -	set_task_ioprio(sbi->s_journal->j_task, journal_ioprio); +	set_task_ioprio(sbi->s_journal->j_task, parsed_opts.journal_ioprio);  	sbi->s_journal->j_submit_inode_data_buffers =  		ext4_journal_submit_inode_data_buffers; @@ -4980,6 +4991,19 @@ no_journal:  	ext4_fc_replay_cleanup(sb);  	ext4_ext_init(sb); + +	/* +	 * Enable optimize_scan if number of groups is > threshold. This can be +	 * turned off by passing "mb_optimize_scan=0". This can also be +	 * turned on forcefully by passing "mb_optimize_scan=1". +	 */ +	if (parsed_opts.mb_optimize_scan == 1) +		set_opt2(sb, MB_OPTIMIZE_SCAN); +	else if (parsed_opts.mb_optimize_scan == 0) +		clear_opt2(sb, MB_OPTIMIZE_SCAN); +	else if (sbi->s_groups_count >= MB_DEFAULT_LINEAR_SCAN_THRESHOLD) +		set_opt2(sb, MB_OPTIMIZE_SCAN); +  	err = ext4_mb_init(sb);  	if (err) {  		ext4_msg(sb, KERN_ERR, "failed to initialize mballoc (%d)", @@ -4996,7 +5020,7 @@ no_journal:  			ext4_journal_commit_callback;  	block = ext4_count_free_clusters(sb); -	ext4_free_blocks_count_set(sbi->s_es,  +	ext4_free_blocks_count_set(sbi->s_es,  				   EXT4_C2B(sbi, block));  	err = percpu_counter_init(&sbi->s_freeclusters_counter, block,  				  GFP_KERNEL); @@ -5561,8 +5585,10 @@ static int ext4_commit_super(struct super_block *sb)  	struct buffer_head *sbh = EXT4_SB(sb)->s_sbh;  	int error = 0; -	if (!sbh || block_device_ejected(sb)) -		return error; +	if (!sbh) +		return -EINVAL; +	if (block_device_ejected(sb)) +		return -ENODEV;  	ext4_update_super(sb); @@ -5813,13 +5839,16 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)  	struct ext4_mount_options old_opts;  	int enable_quota = 0;  	ext4_group_t g; -	unsigned int journal_ioprio = DEFAULT_JOURNAL_IOPRIO;  	int err = 0;  #ifdef CONFIG_QUOTA  	int i, j;  	char *to_free[EXT4_MAXQUOTAS];  #endif  	char *orig_data = kstrdup(data, GFP_KERNEL); +	struct ext4_parsed_options parsed_opts; + +	parsed_opts.journal_ioprio = DEFAULT_JOURNAL_IOPRIO; +	parsed_opts.journal_devnum = 0;  	if (data && !orig_data)  		return -ENOMEM; @@ -5850,7 +5879,8 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)  			old_opts.s_qf_names[i] = NULL;  #endif  	if (sbi->s_journal && sbi->s_journal->j_task->io_context) -		journal_ioprio = sbi->s_journal->j_task->io_context->ioprio; +		parsed_opts.journal_ioprio = +			sbi->s_journal->j_task->io_context->ioprio;  	/*  	 * Some options can be enabled by ext4 and/or by VFS mount flag @@ -5860,7 +5890,7 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)  	vfs_flags = SB_LAZYTIME | SB_I_VERSION;  	sb->s_flags = (sb->s_flags & ~vfs_flags) | (*flags & vfs_flags); -	if (!parse_options(data, sb, NULL, &journal_ioprio, 1)) { +	if (!parse_options(data, sb, &parsed_opts, 1)) {  		err = -EINVAL;  		goto restore_opts;  	} @@ -5910,7 +5940,7 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)  	if (sbi->s_journal) {  		ext4_init_journal_params(sb, sbi->s_journal); -		set_task_ioprio(sbi->s_journal->j_task, journal_ioprio); +		set_task_ioprio(sbi->s_journal->j_task, parsed_opts.journal_ioprio);  	}  	/* Flush outstanding errors before changing fs state */ @@ -6153,7 +6183,6 @@ static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf)  	struct ext4_sb_info *sbi = EXT4_SB(sb);  	struct ext4_super_block *es = sbi->s_es;  	ext4_fsblk_t overhead = 0, resv_blocks; -	u64 fsid;  	s64 bfree;  	resv_blocks = EXT4_C2B(sbi, atomic64_read(&sbi->s_resv_clusters)); @@ -6174,9 +6203,7 @@ static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf)  	buf->f_files = le32_to_cpu(es->s_inodes_count);  	buf->f_ffree = percpu_counter_sum_positive(&sbi->s_freeinodes_counter);  	buf->f_namelen = EXT4_NAME_LEN; -	fsid = le64_to_cpup((void *)es->s_uuid) ^ -	       le64_to_cpup((void *)es->s_uuid + sizeof(u64)); -	buf->f_fsid = u64_to_fsid(fsid); +	buf->f_fsid = uuid_to_fsid(es->s_uuid);  #ifdef CONFIG_QUOTA  	if (ext4_test_inode_flag(dentry->d_inode, EXT4_INODE_PROJINHERIT) &&  |