diff options
Diffstat (limited to 'fs/ext4/super.c')
| -rw-r--r-- | fs/ext4/super.c | 67 | 
1 files changed, 52 insertions, 15 deletions
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index ca9d4a2fed41..58987b5c514b 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -24,6 +24,7 @@  #include <linux/slab.h>  #include <linux/init.h>  #include <linux/blkdev.h> +#include <linux/backing-dev.h>  #include <linux/parser.h>  #include <linux/buffer_head.h>  #include <linux/exportfs.h> @@ -451,7 +452,7 @@ 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)); +		path = file_path(file, pathname, sizeof(pathname));  		if (IS_ERR(path))  			path = "(unknown)";  		va_start(args, fmt); @@ -591,14 +592,17 @@ void __ext4_msg(struct super_block *sb,  	va_end(args);  } +#define ext4_warning_ratelimit(sb)					\ +		___ratelimit(&(EXT4_SB(sb)->s_warning_ratelimit_state),	\ +			     "EXT4-fs warning") +  void __ext4_warning(struct super_block *sb, const char *function,  		    unsigned int line, const char *fmt, ...)  {  	struct va_format vaf;  	va_list args; -	if (!___ratelimit(&(EXT4_SB(sb)->s_warning_ratelimit_state), -			  "EXT4-fs warning")) +	if (!ext4_warning_ratelimit(sb))  		return;  	va_start(args, fmt); @@ -609,6 +613,24 @@ void __ext4_warning(struct super_block *sb, const char *function,  	va_end(args);  } +void __ext4_warning_inode(const struct inode *inode, const char *function, +			  unsigned int line, const char *fmt, ...) +{ +	struct va_format vaf; +	va_list args; + +	if (!ext4_warning_ratelimit(inode->i_sb)) +		return; + +	va_start(args, fmt); +	vaf.fmt = fmt; +	vaf.va = &args; +	printk(KERN_WARNING "EXT4-fs warning (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); +} +  void __ext4_grp_locked_error(const char *function, unsigned int line,  			     struct super_block *sb, ext4_group_t grp,  			     unsigned long ino, ext4_fsblk_t block, @@ -807,6 +829,7 @@ static void ext4_put_super(struct super_block *sb)  		dump_orphan_list(sb, sbi);  	J_ASSERT(list_empty(&sbi->s_orphan)); +	sync_blockdev(sb->s_bdev);  	invalidate_bdev(sb->s_bdev);  	if (sbi->journal_bdev && sbi->journal_bdev != sb->s_bdev) {  		/* @@ -879,9 +902,8 @@ static struct inode *ext4_alloc_inode(struct super_block *sb)  	atomic_set(&ei->i_unwritten, 0);  	INIT_WORK(&ei->i_rsv_conversion_work, ext4_end_io_rsv_work);  #ifdef CONFIG_EXT4_FS_ENCRYPTION -	ei->i_encryption_key.mode = EXT4_ENCRYPTION_MODE_INVALID; +	ei->i_crypt_info = NULL;  #endif -  	return &ei->vfs_inode;  } @@ -958,6 +980,10 @@ void ext4_clear_inode(struct inode *inode)  		jbd2_free_inode(EXT4_I(inode)->jinode);  		EXT4_I(inode)->jinode = NULL;  	} +#ifdef CONFIG_EXT4_FS_ENCRYPTION +	if (EXT4_I(inode)->i_crypt_info) +		ext4_free_encryption_info(inode, EXT4_I(inode)->i_crypt_info); +#endif  }  static struct inode *ext4_nfs_get_inode(struct super_block *sb, @@ -3420,7 +3446,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)  	unsigned long journal_devnum = 0;  	unsigned long def_mount_opts;  	struct inode *root; -	char *cp;  	const char *descr;  	int ret = -ENOMEM;  	int blocksize, clustersize; @@ -3449,15 +3474,9 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)  	if (sb->s_bdev->bd_part)  		sbi->s_sectors_written_start =  			part_stat_read(sb->s_bdev->bd_part, sectors[1]); -#ifdef CONFIG_EXT4_FS_ENCRYPTION -	/* Modes of operations for file and directory encryption. */ -	sbi->s_file_encryption_mode = EXT4_ENCRYPTION_MODE_AES_256_XTS; -	sbi->s_dir_encryption_mode = EXT4_ENCRYPTION_MODE_INVALID; -#endif  	/* Cleanup superblock name */ -	for (cp = sb->s_id; (cp = strchr(cp, '/'));) -		*cp = '!'; +	strreplace(sb->s_id, '/', '!');  	/* -EINVAL is default */  	ret = -EINVAL; @@ -4067,7 +4086,15 @@ no_journal:  		}  	} -	if (unlikely(sbi->s_mount_flags & EXT4_MF_TEST_DUMMY_ENCRYPTION) && +	if ((DUMMY_ENCRYPTION_ENABLED(sbi) || +	     EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_ENCRYPT)) && +	    (blocksize != PAGE_CACHE_SIZE)) { +		ext4_msg(sb, KERN_ERR, +			 "Unsupported blocksize for fs encryption"); +		goto failed_mount_wq; +	} + +	if (DUMMY_ENCRYPTION_ENABLED(sbi) &&  	    !(sb->s_flags & MS_RDONLY) &&  	    !EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_ENCRYPT)) {  		EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_ENCRYPT); @@ -4943,6 +4970,9 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)  		set_task_ioprio(sbi->s_journal->j_task, journal_ioprio);  	} +	if (*flags & MS_LAZYTIME) +		sb->s_flags |= MS_LAZYTIME; +  	if ((*flags & MS_RDONLY) != (sb->s_flags & MS_RDONLY)) {  		if (sbi->s_mount_flags & EXT4_MF_FS_ABORTED) {  			err = -EROFS; @@ -5410,6 +5440,7 @@ static ssize_t ext4_quota_write(struct super_block *sb, int type,  	struct inode *inode = sb_dqopt(sb)->files[type];  	ext4_lblk_t blk = off >> EXT4_BLOCK_SIZE_BITS(sb);  	int err, offset = off & (sb->s_blocksize - 1); +	int retries = 0;  	struct buffer_head *bh;  	handle_t *handle = journal_current_handle(); @@ -5430,7 +5461,12 @@ static ssize_t ext4_quota_write(struct super_block *sb, int type,  		return -EIO;  	} -	bh = ext4_bread(handle, inode, blk, 1); +	do { +		bh = ext4_bread(handle, inode, blk, +				EXT4_GET_BLOCKS_CREATE | +				EXT4_GET_BLOCKS_METADATA_NOFAIL); +	} while (IS_ERR(bh) && (PTR_ERR(bh) == -ENOSPC) && +		 ext4_should_retry_alloc(inode->i_sb, &retries));  	if (IS_ERR(bh))  		return PTR_ERR(bh);  	if (!bh) @@ -5647,6 +5683,7 @@ out7:  static void __exit ext4_exit_fs(void)  { +	ext4_exit_crypto();  	ext4_destroy_lazyinit_thread();  	unregister_as_ext2();  	unregister_as_ext3();  |