diff options
Diffstat (limited to 'fs/ext4/super.c')
| -rw-r--r-- | fs/ext4/super.c | 269 | 
1 files changed, 175 insertions, 94 deletions
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 2c2e6cbc6be..6df7bc611db 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -59,6 +59,7 @@ static struct kset *ext4_kset;  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 int ext4_load_journal(struct super_block *, struct ext4_super_block *,  			     unsigned long journal_devnum); @@ -137,8 +138,8 @@ static __le32 ext4_superblock_csum(struct super_block *sb,  	return cpu_to_le32(csum);  } -int ext4_superblock_csum_verify(struct super_block *sb, -				struct ext4_super_block *es) +static int ext4_superblock_csum_verify(struct super_block *sb, +				       struct ext4_super_block *es)  {  	if (!EXT4_HAS_RO_COMPAT_FEATURE(sb,  				       EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) @@ -411,20 +412,26 @@ static void ext4_handle_error(struct super_block *sb)  			sb->s_id);  } +#define ext4_error_ratelimit(sb)					\ +		___ratelimit(&(EXT4_SB(sb)->s_err_ratelimit_state),	\ +			     "EXT4-fs error") +  void __ext4_error(struct super_block *sb, const char *function,  		  unsigned int line, const char *fmt, ...)  {  	struct va_format vaf;  	va_list args; -	va_start(args, fmt); -	vaf.fmt = fmt; -	vaf.va = &args; -	printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: comm %s: %pV\n", -	       sb->s_id, function, line, current->comm, &vaf); -	va_end(args); +	if (ext4_error_ratelimit(sb)) { +		va_start(args, fmt); +		vaf.fmt = fmt; +		vaf.va = &args; +		printk(KERN_CRIT +		       "EXT4-fs error (device %s): %s:%d: comm %s: %pV\n", +		       sb->s_id, function, line, current->comm, &vaf); +		va_end(args); +	}  	save_error_info(sb, function, line); -  	ext4_handle_error(sb);  } @@ -438,22 +445,23 @@ void __ext4_error_inode(struct inode *inode, const char *function,  	es->s_last_error_ino = cpu_to_le32(inode->i_ino);  	es->s_last_error_block = cpu_to_le64(block); +	if (ext4_error_ratelimit(inode->i_sb)) { +		va_start(args, fmt); +		vaf.fmt = fmt; +		vaf.va = &args; +		if (block) +			printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: " +			       "inode #%lu: block %llu: comm %s: %pV\n", +			       inode->i_sb->s_id, function, line, inode->i_ino, +			       block, current->comm, &vaf); +		else +			printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: " +			       "inode #%lu: comm %s: %pV\n", +			       inode->i_sb->s_id, function, line, inode->i_ino, +			       current->comm, &vaf); +		va_end(args); +	}  	save_error_info(inode->i_sb, function, line); -	va_start(args, fmt); -	vaf.fmt = fmt; -	vaf.va = &args; -	if (block) -		printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: " -		       "inode #%lu: block %llu: comm %s: %pV\n", -		       inode->i_sb->s_id, function, line, inode->i_ino, -		       block, current->comm, &vaf); -	else -		printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: " -		       "inode #%lu: comm %s: %pV\n", -		       inode->i_sb->s_id, function, line, inode->i_ino, -		       current->comm, &vaf); -	va_end(args); -  	ext4_handle_error(inode->i_sb);  } @@ -469,27 +477,28 @@ void __ext4_error_file(struct file *file, const char *function,  	es = EXT4_SB(inode->i_sb)->s_es;  	es->s_last_error_ino = cpu_to_le32(inode->i_ino); +	if (ext4_error_ratelimit(inode->i_sb)) { +		path = d_path(&(file->f_path), pathname, sizeof(pathname)); +		if (IS_ERR(path)) +			path = "(unknown)"; +		va_start(args, fmt); +		vaf.fmt = fmt; +		vaf.va = &args; +		if (block) +			printk(KERN_CRIT +			       "EXT4-fs error (device %s): %s:%d: inode #%lu: " +			       "block %llu: comm %s: path %s: %pV\n", +			       inode->i_sb->s_id, function, line, inode->i_ino, +			       block, current->comm, path, &vaf); +		else +			printk(KERN_CRIT +			       "EXT4-fs error (device %s): %s:%d: inode #%lu: " +			       "comm %s: path %s: %pV\n", +			       inode->i_sb->s_id, function, line, inode->i_ino, +			       current->comm, path, &vaf); +		va_end(args); +	}  	save_error_info(inode->i_sb, function, line); -	path = d_path(&(file->f_path), pathname, sizeof(pathname)); -	if (IS_ERR(path)) -		path = "(unknown)"; -	va_start(args, fmt); -	vaf.fmt = fmt; -	vaf.va = &args; -	if (block) -		printk(KERN_CRIT -		       "EXT4-fs error (device %s): %s:%d: inode #%lu: " -		       "block %llu: comm %s: path %s: %pV\n", -		       inode->i_sb->s_id, function, line, inode->i_ino, -		       block, current->comm, path, &vaf); -	else -		printk(KERN_CRIT -		       "EXT4-fs error (device %s): %s:%d: inode #%lu: " -		       "comm %s: path %s: %pV\n", -		       inode->i_sb->s_id, function, line, inode->i_ino, -		       current->comm, path, &vaf); -	va_end(args); -  	ext4_handle_error(inode->i_sb);  } @@ -543,11 +552,13 @@ void __ext4_std_error(struct super_block *sb, const char *function,  	    (sb->s_flags & MS_RDONLY))  		return; -	errstr = ext4_decode_error(sb, errno, nbuf); -	printk(KERN_CRIT "EXT4-fs error (device %s) in %s:%d: %s\n", -	       sb->s_id, function, line, errstr); -	save_error_info(sb, function, line); +	if (ext4_error_ratelimit(sb)) { +		errstr = ext4_decode_error(sb, errno, nbuf); +		printk(KERN_CRIT "EXT4-fs error (device %s) in %s:%d: %s\n", +		       sb->s_id, function, line, errstr); +	} +	save_error_info(sb, function, line);  	ext4_handle_error(sb);  } @@ -597,6 +608,9 @@ void __ext4_msg(struct super_block *sb,  	struct va_format vaf;  	va_list args; +	if (!___ratelimit(&(EXT4_SB(sb)->s_msg_ratelimit_state), "EXT4-fs")) +		return; +  	va_start(args, fmt);  	vaf.fmt = fmt;  	vaf.va = &args; @@ -610,6 +624,10 @@ void __ext4_warning(struct super_block *sb, const char *function,  	struct va_format vaf;  	va_list args; +	if (!___ratelimit(&(EXT4_SB(sb)->s_warning_ratelimit_state), +			  "EXT4-fs warning")) +		return; +  	va_start(args, fmt);  	vaf.fmt = fmt;  	vaf.va = &args; @@ -633,18 +651,20 @@ __acquires(bitlock)  	es->s_last_error_block = cpu_to_le64(block);  	__save_error_info(sb, function, line); -	va_start(args, fmt); - -	vaf.fmt = fmt; -	vaf.va = &args; -	printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: group %u, ", -	       sb->s_id, function, line, grp); -	if (ino) -		printk(KERN_CONT "inode %lu: ", ino); -	if (block) -		printk(KERN_CONT "block %llu:", (unsigned long long) block); -	printk(KERN_CONT "%pV\n", &vaf); -	va_end(args); +	if (ext4_error_ratelimit(sb)) { +		va_start(args, fmt); +		vaf.fmt = fmt; +		vaf.va = &args; +		printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: group %u, ", +		       sb->s_id, function, line, grp); +		if (ino) +			printk(KERN_CONT "inode %lu: ", ino); +		if (block) +			printk(KERN_CONT "block %llu:", +			       (unsigned long long) block); +		printk(KERN_CONT "%pV\n", &vaf); +		va_end(args); +	}  	if (test_opt(sb, ERRORS_CONT)) {  		ext4_commit_super(sb, 0); @@ -773,7 +793,7 @@ static void ext4_put_super(struct super_block *sb)  	}  	ext4_es_unregister_shrinker(sbi); -	del_timer(&sbi->s_err_report); +	del_timer_sync(&sbi->s_err_report);  	ext4_release_system_zone(sb);  	ext4_mb_release(sb);  	ext4_ext_release(sb); @@ -826,6 +846,10 @@ static void ext4_put_super(struct super_block *sb)  		invalidate_bdev(sbi->journal_bdev);  		ext4_blkdev_remove(sbi);  	} +	if (sbi->s_mb_cache) { +		ext4_xattr_destroy_cache(sbi->s_mb_cache); +		sbi->s_mb_cache = NULL; +	}  	if (sbi->s_mmp_tsk)  		kthread_stop(sbi->s_mmp_tsk);  	sb->s_fs_info = NULL; @@ -855,6 +879,7 @@ static struct inode *ext4_alloc_inode(struct super_block *sb)  		return NULL;  	ei->vfs_inode.i_version = 1; +	spin_lock_init(&ei->i_raw_lock);  	INIT_LIST_HEAD(&ei->i_prealloc_list);  	spin_lock_init(&ei->i_prealloc_lock);  	ext4_es_init_tree(&ei->i_es_tree); @@ -921,7 +946,7 @@ static void init_once(void *foo)  	inode_init_once(&ei->vfs_inode);  } -static int init_inodecache(void) +static int __init init_inodecache(void)  {  	ext4_inode_cachep = kmem_cache_create("ext4_inode_cache",  					     sizeof(struct ext4_inode_info), @@ -1500,8 +1525,6 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token,  			arg = JBD2_DEFAULT_MAX_COMMIT_AGE;  		sbi->s_commit_interval = HZ * arg;  	} else if (token == Opt_max_batch_time) { -		if (arg == 0) -			arg = EXT4_DEF_MAX_BATCH_TIME;  		sbi->s_max_batch_time = arg;  	} else if (token == Opt_min_batch_time) {  		sbi->s_min_batch_time = arg; @@ -1879,7 +1902,7 @@ static int ext4_setup_super(struct super_block *sb, struct ext4_super_block *es,  	if (!(sbi->s_mount_state & EXT4_VALID_FS))  		ext4_msg(sb, KERN_WARNING, "warning: mounting unchecked fs, "  			 "running e2fsck is recommended"); -	else if ((sbi->s_mount_state & EXT4_ERROR_FS)) +	else if (sbi->s_mount_state & EXT4_ERROR_FS)  		ext4_msg(sb, KERN_WARNING,  			 "warning: mounting fs with errors, "  			 "running e2fsck is recommended"); @@ -2380,6 +2403,16 @@ static ext4_fsblk_t descriptor_loc(struct super_block *sb,  	if (ext4_bg_has_super(sb, bg))  		has_super = 1; +	/* +	 * If we have a meta_bg fs with 1k blocks, group 0's GDT is at +	 * block 2, not 1.  If s_first_data_block == 0 (bigalloc is enabled +	 * on modern mke2fs or blksize > 1k on older mke2fs) then we must +	 * compensate. +	 */ +	if (sb->s_blocksize == 1024 && nr == 0 && +	    le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block) == 0) +		has_super++; +  	return (has_super + ext4_group_first_block_no(sb, bg));  } @@ -2606,6 +2639,12 @@ EXT4_RW_ATTR_SBI_UI(mb_group_prealloc, s_mb_group_prealloc);  EXT4_DEPRECATED_ATTR(max_writeback_mb_bump, 128);  EXT4_RW_ATTR_SBI_UI(extent_max_zeroout_kb, s_extent_max_zeroout_kb);  EXT4_ATTR(trigger_fs_error, 0200, NULL, trigger_test_error); +EXT4_RW_ATTR_SBI_UI(err_ratelimit_interval_ms, s_err_ratelimit_state.interval); +EXT4_RW_ATTR_SBI_UI(err_ratelimit_burst, s_err_ratelimit_state.burst); +EXT4_RW_ATTR_SBI_UI(warning_ratelimit_interval_ms, s_warning_ratelimit_state.interval); +EXT4_RW_ATTR_SBI_UI(warning_ratelimit_burst, s_warning_ratelimit_state.burst); +EXT4_RW_ATTR_SBI_UI(msg_ratelimit_interval_ms, s_msg_ratelimit_state.interval); +EXT4_RW_ATTR_SBI_UI(msg_ratelimit_burst, s_msg_ratelimit_state.burst);  static struct attribute *ext4_attrs[] = {  	ATTR_LIST(delayed_allocation_blocks), @@ -2623,6 +2662,12 @@ static struct attribute *ext4_attrs[] = {  	ATTR_LIST(max_writeback_mb_bump),  	ATTR_LIST(extent_max_zeroout_kb),  	ATTR_LIST(trigger_fs_error), +	ATTR_LIST(err_ratelimit_interval_ms), +	ATTR_LIST(err_ratelimit_burst), +	ATTR_LIST(warning_ratelimit_interval_ms), +	ATTR_LIST(warning_ratelimit_burst), +	ATTR_LIST(msg_ratelimit_interval_ms), +	ATTR_LIST(msg_ratelimit_burst),  	NULL,  }; @@ -2762,10 +2807,11 @@ static void print_daily_error_info(unsigned long arg)  	es = sbi->s_es;  	if (es->s_error_count) -		ext4_msg(sb, KERN_NOTICE, "error count: %u", +		/* fsck newer than v1.41.13 is needed to clean this condition. */ +		ext4_msg(sb, KERN_NOTICE, "error count since last fsck: %u",  			 le32_to_cpu(es->s_error_count));  	if (es->s_first_error_time) { -		printk(KERN_NOTICE "EXT4-fs (%s): initial error at %u: %.*s:%d", +		printk(KERN_NOTICE "EXT4-fs (%s): initial error at time %u: %.*s:%d",  		       sb->s_id, le32_to_cpu(es->s_first_error_time),  		       (int) sizeof(es->s_first_error_func),  		       es->s_first_error_func, @@ -2779,7 +2825,7 @@ static void print_daily_error_info(unsigned long arg)  		printk("\n");  	}  	if (es->s_last_error_time) { -		printk(KERN_NOTICE "EXT4-fs (%s): last error at %u: %.*s:%d", +		printk(KERN_NOTICE "EXT4-fs (%s): last error at time %u: %.*s:%d",  		       sb->s_id, le32_to_cpu(es->s_last_error_time),  		       (int) sizeof(es->s_last_error_func),  		       es->s_last_error_func, @@ -3037,7 +3083,6 @@ static struct ext4_li_request *ext4_li_request_new(struct super_block *sb,  {  	struct ext4_sb_info *sbi = EXT4_SB(sb);  	struct ext4_li_request *elr; -	unsigned long rnd;  	elr = kzalloc(sizeof(*elr), GFP_KERNEL);  	if (!elr) @@ -3052,10 +3097,8 @@ static struct ext4_li_request *ext4_li_request_new(struct super_block *sb,  	 * spread the inode table initialization requests  	 * better.  	 */ -	get_random_bytes(&rnd, sizeof(rnd)); -	elr->lr_next_sched = jiffies + (unsigned long)rnd % -			     (EXT4_DEF_LI_MAX_START_DELAY * HZ); - +	elr->lr_next_sched = jiffies + (prandom_u32() % +				(EXT4_DEF_LI_MAX_START_DELAY * HZ));  	return elr;  } @@ -3288,19 +3331,28 @@ int ext4_calculate_overhead(struct super_block *sb)  } -static ext4_fsblk_t ext4_calculate_resv_clusters(struct ext4_sb_info *sbi) +static ext4_fsblk_t ext4_calculate_resv_clusters(struct super_block *sb)  {  	ext4_fsblk_t resv_clusters;  	/* +	 * There's no need to reserve anything when we aren't using extents. +	 * The space estimates are exact, there are no unwritten extents, +	 * hole punching doesn't need new metadata... This is needed especially +	 * to keep ext2/3 backward compatibility. +	 */ +	if (!EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_EXTENTS)) +		return 0; +	/*  	 * By default we reserve 2% or 4096 clusters, whichever is smaller.  	 * This should cover the situations where we can not afford to run  	 * out of space like for example punch hole, or converting -	 * uninitialized extents in delalloc path. In most cases such +	 * unwritten extents in delalloc path. In most cases such  	 * allocation would require 1, or 2 blocks, higher numbers are  	 * very rare.  	 */ -	resv_clusters = ext4_blocks_count(sbi->s_es) >> sbi->s_cluster_bits; +	resv_clusters = ext4_blocks_count(EXT4_SB(sb)->s_es) >> +			EXT4_SB(sb)->s_cluster_bits;  	do_div(resv_clusters, 50);  	resv_clusters = min_t(ext4_fsblk_t, resv_clusters, 4096); @@ -3538,6 +3590,16 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)  		       "feature flags set on rev 0 fs, "  		       "running e2fsck is recommended"); +	if (es->s_creator_os == cpu_to_le32(EXT4_OS_HURD)) { +		set_opt2(sb, HURD_COMPAT); +		if (EXT4_HAS_INCOMPAT_FEATURE(sb, +					      EXT4_FEATURE_INCOMPAT_64BIT)) { +			ext4_msg(sb, KERN_ERR, +				 "The Hurd can't support 64-bit file systems"); +			goto failed_mount; +		} +	} +  	if (IS_EXT2_SB(sb)) {  		if (ext2_feature_set_ok(sb))  			ext4_msg(sb, KERN_INFO, "mounting ext2 file system " @@ -3658,16 +3720,22 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)  	for (i = 0; i < 4; i++)  		sbi->s_hash_seed[i] = le32_to_cpu(es->s_hash_seed[i]);  	sbi->s_def_hash_version = es->s_def_hash_version; -	i = le32_to_cpu(es->s_flags); -	if (i & EXT2_FLAGS_UNSIGNED_HASH) -		sbi->s_hash_unsigned = 3; -	else if ((i & EXT2_FLAGS_SIGNED_HASH) == 0) { +	if (EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_DIR_INDEX)) { +		i = le32_to_cpu(es->s_flags); +		if (i & EXT2_FLAGS_UNSIGNED_HASH) +			sbi->s_hash_unsigned = 3; +		else if ((i & EXT2_FLAGS_SIGNED_HASH) == 0) {  #ifdef __CHAR_UNSIGNED__ -		es->s_flags |= cpu_to_le32(EXT2_FLAGS_UNSIGNED_HASH); -		sbi->s_hash_unsigned = 3; +			if (!(sb->s_flags & MS_RDONLY)) +				es->s_flags |= +					cpu_to_le32(EXT2_FLAGS_UNSIGNED_HASH); +			sbi->s_hash_unsigned = 3;  #else -		es->s_flags |= cpu_to_le32(EXT2_FLAGS_SIGNED_HASH); +			if (!(sb->s_flags & MS_RDONLY)) +				es->s_flags |= +					cpu_to_le32(EXT2_FLAGS_SIGNED_HASH);  #endif +		}  	}  	/* Handle clustersize */ @@ -3967,6 +4035,14 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)  	percpu_counter_set(&sbi->s_dirtyclusters_counter, 0);  no_journal: +	if (ext4_mballoc_ready) { +		sbi->s_mb_cache = ext4_xattr_create_cache(sb->s_id); +		if (!sbi->s_mb_cache) { +			ext4_msg(sb, KERN_ERR, "Failed to create an mb_cache"); +			goto failed_mount_wq; +		} +	} +  	/*  	 * Get the # of file system overhead blocks from the  	 * superblock if present. @@ -4043,10 +4119,10 @@ no_journal:  			 "available");  	} -	err = ext4_reserve_clusters(sbi, ext4_calculate_resv_clusters(sbi)); +	err = ext4_reserve_clusters(sbi, ext4_calculate_resv_clusters(sb));  	if (err) {  		ext4_msg(sb, KERN_ERR, "failed to reserve %llu clusters for " -			 "reserved pool", ext4_calculate_resv_clusters(sbi)); +			 "reserved pool", ext4_calculate_resv_clusters(sb));  		goto failed_mount4a;  	} @@ -4118,6 +4194,11 @@ no_journal:  	if (es->s_error_count)  		mod_timer(&sbi->s_err_report, jiffies + 300*HZ); /* 5 minutes */ +	/* Enable message ratelimiting. Default is 10 messages per 5 secs. */ +	ratelimit_state_init(&sbi->s_err_ratelimit_state, 5 * HZ, 10); +	ratelimit_state_init(&sbi->s_warning_ratelimit_state, 5 * HZ, 10); +	ratelimit_state_init(&sbi->s_msg_ratelimit_state, 5 * HZ, 10); +  	kfree(orig_data);  	return 0; @@ -4151,7 +4232,7 @@ failed_mount_wq:  	}  failed_mount3:  	ext4_es_unregister_shrinker(sbi); -	del_timer(&sbi->s_err_report); +	del_timer_sync(&sbi->s_err_report);  	if (sbi->s_flex_groups)  		ext4_kvfree(sbi->s_flex_groups);  	percpu_counter_destroy(&sbi->s_freeclusters_counter); @@ -4787,6 +4868,9 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)  		}  		if (*flags & MS_RDONLY) { +			err = sync_filesystem(sb); +			if (err < 0) +				goto restore_opts;  			err = dquot_suspend(sb, -1);  			if (err < 0)  				goto restore_opts; @@ -5293,6 +5377,7 @@ static ssize_t ext4_quota_write(struct super_block *sb, int type,  	bh = ext4_bread(handle, inode, blk, 1, &err);  	if (!bh)  		goto out; +	BUFFER_TRACE(bh, "get write access");  	err = ext4_journal_get_write_access(handle, bh);  	if (err) {  		brelse(bh); @@ -5468,11 +5553,9 @@ static int __init ext4_init_fs(void)  	err = ext4_init_mballoc();  	if (err) -		goto out3; - -	err = ext4_init_xattr(); -	if (err)  		goto out2; +	else +		ext4_mballoc_ready = 1;  	err = init_inodecache();  	if (err)  		goto out1; @@ -5488,10 +5571,9 @@ out:  	unregister_as_ext3();  	destroy_inodecache();  out1: -	ext4_exit_xattr(); -out2: +	ext4_mballoc_ready = 0;  	ext4_exit_mballoc(); -out3: +out2:  	ext4_exit_feat_adverts();  out4:  	if (ext4_proc_root) @@ -5514,7 +5596,6 @@ static void __exit ext4_exit_fs(void)  	unregister_as_ext3();  	unregister_filesystem(&ext4_fs_type);  	destroy_inodecache(); -	ext4_exit_xattr();  	ext4_exit_mballoc();  	ext4_exit_feat_adverts();  	remove_proc_entry("fs/ext4", NULL);  | 
