Some ext4 regression and bug fixes for -rc1
-----BEGIN PGP SIGNATURE----- iQEzBAABCAAdFiEEK2m5VNv+CHkogTfJ8vlZVpUNgaMFAmROracACgkQ8vlZVpUN gaPqLQf/ZvzvspL4o3SNsHE/M2tKNBVY/z/vsfmAZwMgrGoK5qCkDsNA7c7+oUwE xjiHiVHOaYjJVWwkdODAwe7xNbWB6FoKptBaBi89fAyibMY/N7BZ8rad69NQTvyc JbKjorvEBc+qgsUEt2+ZpMogN9KHlVh3NJwlovesmucQtg2gWLKs8wrxW2bC7uAh 2uR9GWUnhDrs6jHbjHkG3/lgB0aS0StLRxfsbchjZvCsniTDZymLmmgkA1ln17ce 6iRg2ESjYUryPX09YFtUuQVvObtUTM+z8DzwyQuAJ4VfmdoPA4L6mpdqzPGFuKQc gJrLSB8VZJDvPoGjaHZ+Qdl1tHlFRw== =2SEf -----END PGP SIGNATURE----- Merge tag 'ext4_for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4 Pull ext4 fixes from Ted Ts'o: "Some ext4 regression and bug fixes" * tag 'ext4_for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4: ext4: clean up error handling in __ext4_fill_super() ext4: reflect error codes from ext4_multi_mount_protect() to its callers ext4: fix lost error code reporting in __ext4_fill_super() ext4: fix unused iterator variable warnings ext4: fix use-after-free read in ext4_find_extent for bigalloc + inline ext4: fix i_disksize exceeding i_size problem in paritally written case
This commit is contained in:
commit
06936aaf49
@ -5795,7 +5795,8 @@ int ext4_clu_mapped(struct inode *inode, ext4_lblk_t lclu)
|
||||
* mapped - no physical clusters have been allocated, and the
|
||||
* file has no extents
|
||||
*/
|
||||
if (ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA))
|
||||
if (ext4_test_inode_state(inode, EXT4_STATE_MAY_INLINE_DATA) ||
|
||||
ext4_has_inline_data(inode))
|
||||
return 0;
|
||||
|
||||
/* search for the extent closest to the first block in the cluster */
|
||||
|
@ -2982,6 +2982,9 @@ static int ext4_da_write_end(struct file *file,
|
||||
ext4_has_inline_data(inode))
|
||||
return ext4_write_inline_data_end(inode, pos, len, copied, page);
|
||||
|
||||
if (unlikely(copied < len) && !PageUptodate(page))
|
||||
copied = 0;
|
||||
|
||||
start = pos & (PAGE_SIZE - 1);
|
||||
end = start + copied - 1;
|
||||
|
||||
|
@ -282,6 +282,7 @@ int ext4_multi_mount_protect(struct super_block *sb,
|
||||
if (mmp_block < le32_to_cpu(es->s_first_data_block) ||
|
||||
mmp_block >= ext4_blocks_count(es)) {
|
||||
ext4_warning(sb, "Invalid MMP block in superblock");
|
||||
retval = -EINVAL;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
@ -307,6 +308,7 @@ int ext4_multi_mount_protect(struct super_block *sb,
|
||||
|
||||
if (seq == EXT4_MMP_SEQ_FSCK) {
|
||||
dump_mmp_msg(sb, mmp, "fsck is running on the filesystem");
|
||||
retval = -EBUSY;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
@ -320,6 +322,7 @@ int ext4_multi_mount_protect(struct super_block *sb,
|
||||
|
||||
if (schedule_timeout_interruptible(HZ * wait_time) != 0) {
|
||||
ext4_warning(sb, "MMP startup interrupted, failing mount\n");
|
||||
retval = -ETIMEDOUT;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
@ -330,6 +333,7 @@ int ext4_multi_mount_protect(struct super_block *sb,
|
||||
if (seq != le32_to_cpu(mmp->mmp_seq)) {
|
||||
dump_mmp_msg(sb, mmp,
|
||||
"Device is already active on another node.");
|
||||
retval = -EBUSY;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
@ -349,6 +353,7 @@ skip:
|
||||
*/
|
||||
if (schedule_timeout_interruptible(HZ * wait_time) != 0) {
|
||||
ext4_warning(sb, "MMP startup interrupted, failing mount");
|
||||
retval = -ETIMEDOUT;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
@ -359,6 +364,7 @@ skip:
|
||||
if (seq != le32_to_cpu(mmp->mmp_seq)) {
|
||||
dump_mmp_msg(sb, mmp,
|
||||
"Device is already active on another node.");
|
||||
retval = -EBUSY;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
@ -378,6 +384,7 @@ skip:
|
||||
EXT4_SB(sb)->s_mmp_tsk = NULL;
|
||||
ext4_warning(sb, "Unable to create kmmpd thread for %s.",
|
||||
sb->s_id);
|
||||
retval = -ENOMEM;
|
||||
goto failed;
|
||||
}
|
||||
|
||||
@ -385,5 +392,5 @@ skip:
|
||||
|
||||
failed:
|
||||
brelse(bh);
|
||||
return 1;
|
||||
return retval;
|
||||
}
|
||||
|
@ -1259,7 +1259,7 @@ static void ext4_put_super(struct super_block *sb)
|
||||
struct ext4_sb_info *sbi = EXT4_SB(sb);
|
||||
struct ext4_super_block *es = sbi->s_es;
|
||||
int aborted = 0;
|
||||
int i, err;
|
||||
int err;
|
||||
|
||||
/*
|
||||
* Unregister sysfs before destroying jbd2 journal.
|
||||
@ -1311,7 +1311,7 @@ static void ext4_put_super(struct super_block *sb)
|
||||
ext4_flex_groups_free(sbi);
|
||||
ext4_percpu_param_destroy(sbi);
|
||||
#ifdef CONFIG_QUOTA
|
||||
for (i = 0; i < EXT4_MAXQUOTAS; i++)
|
||||
for (int i = 0; i < EXT4_MAXQUOTAS; i++)
|
||||
kfree(get_qf_name(sb, sbi, i));
|
||||
#endif
|
||||
|
||||
@ -5196,10 +5196,8 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
|
||||
struct ext4_sb_info *sbi = EXT4_SB(sb);
|
||||
ext4_fsblk_t logical_sb_block;
|
||||
struct inode *root;
|
||||
int ret = -ENOMEM;
|
||||
unsigned int i;
|
||||
int needs_recovery;
|
||||
int err = 0;
|
||||
int err;
|
||||
ext4_group_t first_not_zeroed;
|
||||
struct ext4_fs_context *ctx = fc->fs_private;
|
||||
int silent = fc->sb_flags & SB_SILENT;
|
||||
@ -5212,8 +5210,6 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
|
||||
sbi->s_sectors_written_start =
|
||||
part_stat_read(sb->s_bdev, sectors[STAT_WRITE]);
|
||||
|
||||
/* -EINVAL is default */
|
||||
ret = -EINVAL;
|
||||
err = ext4_load_super(sb, &logical_sb_block, silent);
|
||||
if (err)
|
||||
goto out_fail;
|
||||
@ -5239,7 +5235,8 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
|
||||
*/
|
||||
sbi->s_li_wait_mult = EXT4_DEF_LI_WAIT_MULT;
|
||||
|
||||
if (ext4_inode_info_init(sb, es))
|
||||
err = ext4_inode_info_init(sb, es);
|
||||
if (err)
|
||||
goto failed_mount;
|
||||
|
||||
err = parse_apply_sb_mount_options(sb, ctx);
|
||||
@ -5255,10 +5252,12 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
|
||||
|
||||
ext4_apply_options(fc, sb);
|
||||
|
||||
if (ext4_encoding_init(sb, es))
|
||||
err = ext4_encoding_init(sb, es);
|
||||
if (err)
|
||||
goto failed_mount;
|
||||
|
||||
if (ext4_check_journal_data_mode(sb))
|
||||
err = ext4_check_journal_data_mode(sb);
|
||||
if (err)
|
||||
goto failed_mount;
|
||||
|
||||
sb->s_flags = (sb->s_flags & ~SB_POSIXACL) |
|
||||
@ -5267,18 +5266,22 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
|
||||
/* i_version is always enabled now */
|
||||
sb->s_flags |= SB_I_VERSION;
|
||||
|
||||
if (ext4_check_feature_compatibility(sb, es, silent))
|
||||
err = ext4_check_feature_compatibility(sb, es, silent);
|
||||
if (err)
|
||||
goto failed_mount;
|
||||
|
||||
if (ext4_block_group_meta_init(sb, silent))
|
||||
err = ext4_block_group_meta_init(sb, silent);
|
||||
if (err)
|
||||
goto failed_mount;
|
||||
|
||||
ext4_hash_info_init(sb);
|
||||
|
||||
if (ext4_handle_clustersize(sb))
|
||||
err = ext4_handle_clustersize(sb);
|
||||
if (err)
|
||||
goto failed_mount;
|
||||
|
||||
if (ext4_check_geometry(sb, es))
|
||||
err = ext4_check_geometry(sb, es);
|
||||
if (err)
|
||||
goto failed_mount;
|
||||
|
||||
timer_setup(&sbi->s_err_report, print_daily_error_info, 0);
|
||||
@ -5289,8 +5292,8 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
|
||||
if (err)
|
||||
goto failed_mount3;
|
||||
|
||||
/* Register extent status tree shrinker */
|
||||
if (ext4_es_register_shrinker(sbi))
|
||||
err = ext4_es_register_shrinker(sbi);
|
||||
if (err)
|
||||
goto failed_mount3;
|
||||
|
||||
sbi->s_stripe = ext4_get_stripe_size(sbi);
|
||||
@ -5329,10 +5332,13 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
|
||||
ext4_has_feature_orphan_present(sb) ||
|
||||
ext4_has_feature_journal_needs_recovery(sb));
|
||||
|
||||
if (ext4_has_feature_mmp(sb) && !sb_rdonly(sb))
|
||||
if (ext4_multi_mount_protect(sb, le64_to_cpu(es->s_mmp_block)))
|
||||
if (ext4_has_feature_mmp(sb) && !sb_rdonly(sb)) {
|
||||
err = ext4_multi_mount_protect(sb, le64_to_cpu(es->s_mmp_block));
|
||||
if (err)
|
||||
goto failed_mount3a;
|
||||
}
|
||||
|
||||
err = -EINVAL;
|
||||
/*
|
||||
* The first inode we look at is the journal inode. Don't try
|
||||
* root first: it may be modified in the journal!
|
||||
@ -5384,6 +5390,7 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
|
||||
if (!sbi->s_ea_block_cache) {
|
||||
ext4_msg(sb, KERN_ERR,
|
||||
"Failed to create ea_block_cache");
|
||||
err = -EINVAL;
|
||||
goto failed_mount_wq;
|
||||
}
|
||||
|
||||
@ -5392,6 +5399,7 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
|
||||
if (!sbi->s_ea_inode_cache) {
|
||||
ext4_msg(sb, KERN_ERR,
|
||||
"Failed to create ea_inode_cache");
|
||||
err = -EINVAL;
|
||||
goto failed_mount_wq;
|
||||
}
|
||||
}
|
||||
@ -5426,7 +5434,7 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
|
||||
alloc_workqueue("ext4-rsv-conversion", WQ_MEM_RECLAIM | WQ_UNBOUND, 1);
|
||||
if (!EXT4_SB(sb)->rsv_conversion_wq) {
|
||||
printk(KERN_ERR "EXT4-fs: failed to create workqueue\n");
|
||||
ret = -ENOMEM;
|
||||
err = -ENOMEM;
|
||||
goto failed_mount4;
|
||||
}
|
||||
|
||||
@ -5438,28 +5446,28 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
|
||||
root = ext4_iget(sb, EXT4_ROOT_INO, EXT4_IGET_SPECIAL);
|
||||
if (IS_ERR(root)) {
|
||||
ext4_msg(sb, KERN_ERR, "get root inode failed");
|
||||
ret = PTR_ERR(root);
|
||||
err = PTR_ERR(root);
|
||||
root = NULL;
|
||||
goto failed_mount4;
|
||||
}
|
||||
if (!S_ISDIR(root->i_mode) || !root->i_blocks || !root->i_size) {
|
||||
ext4_msg(sb, KERN_ERR, "corrupt root inode, run e2fsck");
|
||||
iput(root);
|
||||
err = -EFSCORRUPTED;
|
||||
goto failed_mount4;
|
||||
}
|
||||
|
||||
sb->s_root = d_make_root(root);
|
||||
if (!sb->s_root) {
|
||||
ext4_msg(sb, KERN_ERR, "get root dentry failed");
|
||||
ret = -ENOMEM;
|
||||
err = -ENOMEM;
|
||||
goto failed_mount4;
|
||||
}
|
||||
|
||||
ret = ext4_setup_super(sb, es, sb_rdonly(sb));
|
||||
if (ret == -EROFS) {
|
||||
err = ext4_setup_super(sb, es, sb_rdonly(sb));
|
||||
if (err == -EROFS) {
|
||||
sb->s_flags |= SB_RDONLY;
|
||||
ret = 0;
|
||||
} else if (ret)
|
||||
} else if (err)
|
||||
goto failed_mount4a;
|
||||
|
||||
ext4_set_resv_clusters(sb);
|
||||
@ -5503,7 +5511,8 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
|
||||
sbi->s_journal->j_commit_callback =
|
||||
ext4_journal_commit_callback;
|
||||
|
||||
if (ext4_percpu_param_init(sbi))
|
||||
err = ext4_percpu_param_init(sbi);
|
||||
if (err)
|
||||
goto failed_mount6;
|
||||
|
||||
if (ext4_has_feature_flex_bg(sb))
|
||||
@ -5511,7 +5520,7 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
|
||||
ext4_msg(sb, KERN_ERR,
|
||||
"unable to initialize "
|
||||
"flex_bg meta info!");
|
||||
ret = -ENOMEM;
|
||||
err = -ENOMEM;
|
||||
goto failed_mount6;
|
||||
}
|
||||
|
||||
@ -5628,7 +5637,7 @@ failed_mount:
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_QUOTA
|
||||
for (i = 0; i < EXT4_MAXQUOTAS; i++)
|
||||
for (unsigned int i = 0; i < EXT4_MAXQUOTAS; i++)
|
||||
kfree(get_qf_name(sb, sbi, i));
|
||||
#endif
|
||||
fscrypt_free_dummy_policy(&sbi->s_dummy_enc_policy);
|
||||
@ -5637,7 +5646,7 @@ failed_mount:
|
||||
ext4_blkdev_remove(sbi);
|
||||
out_fail:
|
||||
sb->s_fs_info = NULL;
|
||||
return err ? err : ret;
|
||||
return err;
|
||||
}
|
||||
|
||||
static int ext4_fill_super(struct super_block *sb, struct fs_context *fc)
|
||||
@ -6565,12 +6574,12 @@ static int __ext4_remount(struct fs_context *fc, struct super_block *sb)
|
||||
goto restore_opts;
|
||||
|
||||
sb->s_flags &= ~SB_RDONLY;
|
||||
if (ext4_has_feature_mmp(sb))
|
||||
if (ext4_multi_mount_protect(sb,
|
||||
le64_to_cpu(es->s_mmp_block))) {
|
||||
err = -EROFS;
|
||||
if (ext4_has_feature_mmp(sb)) {
|
||||
err = ext4_multi_mount_protect(sb,
|
||||
le64_to_cpu(es->s_mmp_block));
|
||||
if (err)
|
||||
goto restore_opts;
|
||||
}
|
||||
}
|
||||
#ifdef CONFIG_QUOTA
|
||||
enable_quota = 1;
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user