[v2] f2fs: add support for an i_version counter
Commit Message
NFSv4 mandates a change attribute to avoid problems with timestamp
granularity, which Linux implements using the i_version counter. This is
particularly important when the underlying filesystem is fast.
BTW introduce a new mount option to enable the iversion functionality,
and disabling it by default.
Signed-off-by: Wenbo Hong <wenbo.hong@vivo.com>
Signed-off-by: Yangtao Li <frank.li@vivo.com>
---
Documentation/filesystems/f2fs.rst | 2 ++
fs/f2fs/f2fs.h | 1 +
fs/f2fs/inode.c | 2 ++
fs/f2fs/super.c | 17 +++++++++++++++++
4 files changed, 22 insertions(+)
Comments
On Thu, Nov 30, 2023 at 02:04:09AM -0700, Yangtao Li wrote:
> NFSv4 mandates a change attribute to avoid problems with timestamp
> granularity, which Linux implements using the i_version counter. This is
> particularly important when the underlying filesystem is fast.
>
> BTW introduce a new mount option to enable the iversion functionality,
> and disabling it by default.
Why do you want to replicate the mistake made in ext4 and undone by
commit 1ff20307393e ?
@@ -367,6 +367,8 @@ errors=%s Specify f2fs behavior on critical errors. This supports modes:
pending node write drop keep N/A
pending meta write keep keep N/A
====================== =============== =============== ========
+iversion Enable the feature of updating the inode I_version field.
+noiversion Disable the feature of updating the inode I_version field.
======================== ============================================================
Debugfs Entries
@@ -28,6 +28,7 @@
#include <linux/fscrypt.h>
#include <linux/fsverity.h>
+#include <linux/iversion.h>
struct pagevec;
@@ -32,6 +32,8 @@ void f2fs_mark_inode_dirty_sync(struct inode *inode, bool sync)
if (f2fs_inode_dirtied(inode, sync))
return;
+ if (IS_I_VERSION(inode))
+ inode_inc_iversion(inode);
mark_inode_dirty_sync(inode);
}
@@ -180,6 +180,8 @@ enum {
Opt_memory_mode,
Opt_age_extent_cache,
Opt_errors,
+ Opt_iversion,
+ Opt_noiversion,
Opt_err,
};
@@ -260,6 +262,8 @@ static match_table_t f2fs_tokens = {
{Opt_memory_mode, "memory=%s"},
{Opt_age_extent_cache, "age_extent_cache"},
{Opt_errors, "errors=%s"},
+ {Opt_iversion, "iversion"},
+ {Opt_noiversion, "noiversion"},
{Opt_err, NULL},
};
@@ -1334,6 +1338,12 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount)
}
kfree(name);
break;
+ case Opt_iversion:
+ sb->s_flags |= SB_I_VERSION;
+ break;
+ case Opt_noiversion:
+ sb->s_flags &= ~SB_I_VERSION;
+ break;
default:
f2fs_err(sbi, "Unrecognized mount option \"%s\" or missing value",
p);
@@ -2152,6 +2162,11 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
else if (F2FS_OPTION(sbi).errors == MOUNT_ERRORS_PANIC)
seq_printf(seq, ",errors=%s", "panic");
+ if (sbi->sb->s_flags & SB_I_VERSION)
+ seq_puts(seq, ",iversion");
+ else
+ seq_puts(seq, ",noiversion");
+
return 0;
}
@@ -2196,6 +2211,7 @@ static void default_options(struct f2fs_sb_info *sbi, bool remount)
F2FS_OPTION(sbi).errors = MOUNT_ERRORS_CONTINUE;
sbi->sb->s_flags &= ~SB_INLINECRYPT;
+ sbi->sb->s_flags &= ~SB_I_VERSION;
set_opt(sbi, INLINE_XATTR);
set_opt(sbi, INLINE_DATA);
@@ -2574,6 +2590,7 @@ static int f2fs_remount(struct super_block *sb, int *flags, char *data)
limit_reserve_root(sbi);
adjust_unusable_cap_perc(sbi);
*flags = (*flags & ~SB_LAZYTIME) | (sb->s_flags & SB_LAZYTIME);
+ *flags = (*flags & ~SB_I_VERSION) | (sb->s_flags & SB_I_VERSION);
return 0;
restore_checkpoint:
if (need_enable_checkpoint) {