mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson
synced 2025-09-07 14:02:58 +00:00
ext4: fix i_version handling on remount
i_version mount option is getting lost on remount. This is because the
'i_version' mount option differs from the util-linux mount option
'iversion', but it has exactly the same functionality. We have to
specifically notify the vfs that this is what we want by setting
appropriate flag in fc->sb_flags. Fix it and as a result we can remove
*flags argument from __ext4_remount(); do the same for
__ext4_fill_super().
In addition set out to deprecate ext4 specific 'i_version' mount option
in favor or 'iversion' by kernel version 5.20.
Signed-off-by: Lukas Czerner <lczerner@redhat.com>
Fixes: cebe85d570
("ext4: switch to the new mount api")
Link: https://lore.kernel.org/r/20211222104517.11187-2-lczerner@redhat.com
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
This commit is contained in:
parent
4437992be7
commit
960e0ab63b
@ -2246,6 +2246,8 @@ static int ext4_parse_param(struct fs_context *fc, struct fs_parameter *param)
|
|||||||
ctx_set_mount_flags(ctx, EXT4_MF_FS_ABORTED);
|
ctx_set_mount_flags(ctx, EXT4_MF_FS_ABORTED);
|
||||||
return 0;
|
return 0;
|
||||||
case Opt_i_version:
|
case Opt_i_version:
|
||||||
|
ext4_msg(NULL, KERN_WARNING, deprecated_msg, param->key, "5.20");
|
||||||
|
ext4_msg(NULL, KERN_WARNING, "Use iversion instead\n");
|
||||||
ctx_set_flags(ctx, SB_I_VERSION);
|
ctx_set_flags(ctx, SB_I_VERSION);
|
||||||
return 0;
|
return 0;
|
||||||
case Opt_inlinecrypt:
|
case Opt_inlinecrypt:
|
||||||
@ -2875,6 +2877,14 @@ static int ext4_apply_options(struct fs_context *fc, struct super_block *sb)
|
|||||||
sb->s_flags &= ~ctx->mask_s_flags;
|
sb->s_flags &= ~ctx->mask_s_flags;
|
||||||
sb->s_flags |= ctx->vals_s_flags;
|
sb->s_flags |= ctx->vals_s_flags;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* i_version differs from common mount option iversion so we have
|
||||||
|
* to let vfs know that it was set, otherwise it would get cleared
|
||||||
|
* on remount
|
||||||
|
*/
|
||||||
|
if (ctx->mask_s_flags & SB_I_VERSION)
|
||||||
|
fc->sb_flags |= SB_I_VERSION;
|
||||||
|
|
||||||
#define APPLY(X) ({ if (ctx->spec & EXT4_SPEC_##X) sbi->X = ctx->X; })
|
#define APPLY(X) ({ if (ctx->spec & EXT4_SPEC_##X) sbi->X = ctx->X; })
|
||||||
APPLY(s_commit_interval);
|
APPLY(s_commit_interval);
|
||||||
APPLY(s_stripe);
|
APPLY(s_stripe);
|
||||||
@ -4342,8 +4352,7 @@ static struct ext4_sb_info *ext4_alloc_sbi(struct super_block *sb)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb,
|
static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
|
||||||
int silent)
|
|
||||||
{
|
{
|
||||||
struct buffer_head *bh, **group_desc;
|
struct buffer_head *bh, **group_desc;
|
||||||
struct ext4_super_block *es = NULL;
|
struct ext4_super_block *es = NULL;
|
||||||
@ -4363,6 +4372,7 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb,
|
|||||||
int err = 0;
|
int err = 0;
|
||||||
ext4_group_t first_not_zeroed;
|
ext4_group_t first_not_zeroed;
|
||||||
struct ext4_fs_context *ctx = fc->fs_private;
|
struct ext4_fs_context *ctx = fc->fs_private;
|
||||||
|
int silent = fc->sb_flags & SB_SILENT;
|
||||||
|
|
||||||
/* Set defaults for the variables that will be set during parsing */
|
/* Set defaults for the variables that will be set during parsing */
|
||||||
ctx->journal_ioprio = DEFAULT_JOURNAL_IOPRIO;
|
ctx->journal_ioprio = DEFAULT_JOURNAL_IOPRIO;
|
||||||
@ -5540,7 +5550,7 @@ static int ext4_fill_super(struct super_block *sb, struct fs_context *fc)
|
|||||||
if (ctx->spec & EXT4_SPEC_s_sb_block)
|
if (ctx->spec & EXT4_SPEC_s_sb_block)
|
||||||
sbi->s_sb_block = ctx->s_sb_block;
|
sbi->s_sb_block = ctx->s_sb_block;
|
||||||
|
|
||||||
ret = __ext4_fill_super(fc, sb, fc->sb_flags & SB_SILENT);
|
ret = __ext4_fill_super(fc, sb);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto free_sbi;
|
goto free_sbi;
|
||||||
|
|
||||||
@ -6199,13 +6209,12 @@ struct ext4_mount_options {
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static int __ext4_remount(struct fs_context *fc, struct super_block *sb,
|
static int __ext4_remount(struct fs_context *fc, struct super_block *sb)
|
||||||
int *flags)
|
|
||||||
{
|
{
|
||||||
struct ext4_fs_context *ctx = fc->fs_private;
|
struct ext4_fs_context *ctx = fc->fs_private;
|
||||||
struct ext4_super_block *es;
|
struct ext4_super_block *es;
|
||||||
struct ext4_sb_info *sbi = EXT4_SB(sb);
|
struct ext4_sb_info *sbi = EXT4_SB(sb);
|
||||||
unsigned long old_sb_flags, vfs_flags;
|
unsigned long old_sb_flags;
|
||||||
struct ext4_mount_options old_opts;
|
struct ext4_mount_options old_opts;
|
||||||
ext4_group_t g;
|
ext4_group_t g;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
@ -6245,14 +6254,6 @@ static int __ext4_remount(struct fs_context *fc, struct super_block *sb,
|
|||||||
ctx->journal_ioprio =
|
ctx->journal_ioprio =
|
||||||
sbi->s_journal->j_task->io_context->ioprio;
|
sbi->s_journal->j_task->io_context->ioprio;
|
||||||
|
|
||||||
/*
|
|
||||||
* Some options can be enabled by ext4 and/or by VFS mount flag
|
|
||||||
* either way we need to make sure it matches in both *flags and
|
|
||||||
* s_flags. Copy those selected flags from *flags to s_flags
|
|
||||||
*/
|
|
||||||
vfs_flags = SB_I_VERSION;
|
|
||||||
sb->s_flags = (sb->s_flags & ~vfs_flags) | (*flags & vfs_flags);
|
|
||||||
|
|
||||||
ext4_apply_options(fc, sb);
|
ext4_apply_options(fc, sb);
|
||||||
|
|
||||||
if ((old_opts.s_mount_opt & EXT4_MOUNT_JOURNAL_CHECKSUM) ^
|
if ((old_opts.s_mount_opt & EXT4_MOUNT_JOURNAL_CHECKSUM) ^
|
||||||
@ -6306,13 +6307,13 @@ static int __ext4_remount(struct fs_context *fc, struct super_block *sb,
|
|||||||
/* Flush outstanding errors before changing fs state */
|
/* Flush outstanding errors before changing fs state */
|
||||||
flush_work(&sbi->s_error_work);
|
flush_work(&sbi->s_error_work);
|
||||||
|
|
||||||
if ((bool)(*flags & SB_RDONLY) != sb_rdonly(sb)) {
|
if ((bool)(fc->sb_flags & SB_RDONLY) != sb_rdonly(sb)) {
|
||||||
if (ext4_test_mount_flag(sb, EXT4_MF_FS_ABORTED)) {
|
if (ext4_test_mount_flag(sb, EXT4_MF_FS_ABORTED)) {
|
||||||
err = -EROFS;
|
err = -EROFS;
|
||||||
goto restore_opts;
|
goto restore_opts;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*flags & SB_RDONLY) {
|
if (fc->sb_flags & SB_RDONLY) {
|
||||||
err = sync_filesystem(sb);
|
err = sync_filesystem(sb);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto restore_opts;
|
goto restore_opts;
|
||||||
@ -6460,13 +6461,6 @@ static int __ext4_remount(struct fs_context *fc, struct super_block *sb,
|
|||||||
if (!ext4_has_feature_mmp(sb) || sb_rdonly(sb))
|
if (!ext4_has_feature_mmp(sb) || sb_rdonly(sb))
|
||||||
ext4_stop_mmpd(sbi);
|
ext4_stop_mmpd(sbi);
|
||||||
|
|
||||||
/*
|
|
||||||
* Some options can be enabled by ext4 and/or by VFS mount flag
|
|
||||||
* either way we need to make sure it matches in both *flags and
|
|
||||||
* s_flags. Copy those selected flags from s_flags to *flags
|
|
||||||
*/
|
|
||||||
*flags = (*flags & ~vfs_flags) | (sb->s_flags & vfs_flags);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
restore_opts:
|
restore_opts:
|
||||||
@ -6498,7 +6492,6 @@ static int __ext4_remount(struct fs_context *fc, struct super_block *sb,
|
|||||||
static int ext4_reconfigure(struct fs_context *fc)
|
static int ext4_reconfigure(struct fs_context *fc)
|
||||||
{
|
{
|
||||||
struct super_block *sb = fc->root->d_sb;
|
struct super_block *sb = fc->root->d_sb;
|
||||||
int flags = fc->sb_flags;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
fc->s_fs_info = EXT4_SB(sb);
|
fc->s_fs_info = EXT4_SB(sb);
|
||||||
@ -6507,7 +6500,7 @@ static int ext4_reconfigure(struct fs_context *fc)
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
ret = __ext4_remount(fc, sb, &flags);
|
ret = __ext4_remount(fc, sb);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user