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.h...@vivo.com>
Signed-off-by: Yangtao Li <frank...@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(+)

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) {
-- 
2.39.0



_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

Reply via email to