[v2] f2fs: add support for an i_version counter

Message ID 20231130090413.1291703-1-frank.li@vivo.com
State New
Headers
Series [v2] f2fs: add support for an i_version counter |

Commit Message

李扬韬 Nov. 30, 2023, 9:04 a.m. UTC
  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

Matthew Wilcox Nov. 30, 2023, 6:35 p.m. UTC | #1
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 ?
  

Patch

diff --git a/Documentation/filesystems/f2fs.rst b/Documentation/filesystems/f2fs.rst
index d32c6209685d..eac23bc0bb92 100644
--- a/Documentation/filesystems/f2fs.rst
+++ b/Documentation/filesystems/f2fs.rst
@@ -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
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 9043cedfa12b..68fd2ef35104 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -28,6 +28,7 @@ 
 
 #include <linux/fscrypt.h>
 #include <linux/fsverity.h>
+#include <linux/iversion.h>
 
 struct pagevec;
 
diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
index 560bfcad1af2..b741eea7e724 100644
--- a/fs/f2fs/inode.c
+++ b/fs/f2fs/inode.c
@@ -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);
 }
 
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index 033af907c3b1..adae708e869c 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -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) {