f2fs: fix to set atomic write status more clear
authorChao Yu <chao@kernel.org>
Thu, 27 Mar 2025 05:56:06 +0000 (13:56 +0800)
committerJaegeuk Kim <jaegeuk@kernel.org>
Thu, 10 Apr 2025 03:59:58 +0000 (03:59 +0000)
1. After we start atomic write in a database file, before committing
all data, we'd better not set inode w/ vfs dirty status to avoid
redundant updates, instead, we only set inode w/ atomic dirty status.

2. After we commit all data, before committing metadata, we need to
clear atomic dirty status, and set vfs dirty status to allow vfs flush
dirty inode.

Cc: Daeho Jeong <daehojeong@google.com>
Reported-by: Zhiguo Niu <zhiguo.niu@unisoc.com>
Signed-off-by: Chao Yu <chao@kernel.org>
Reviewed-by: Daeho Jeong <daehojeong@google.com>
Reviewed-by: Zhiguo Niu <zhiguo.niu@unisoc.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
fs/f2fs/inode.c
fs/f2fs/segment.c
fs/f2fs/super.c

index 83f862578fc80c903e24e512f3137ab02526f33c..fa5097da7c88034e7e7180b72853dd7c34dfdcc2 100644 (file)
@@ -34,7 +34,9 @@ void f2fs_mark_inode_dirty_sync(struct inode *inode, bool sync)
        if (f2fs_inode_dirtied(inode, sync))
                return;
 
-       if (f2fs_is_atomic_file(inode))
+       /* only atomic file w/ FI_ATOMIC_COMMITTED can be set vfs dirty */
+       if (f2fs_is_atomic_file(inode) &&
+                       !is_inode_flag_set(inode, FI_ATOMIC_COMMITTED))
                return;
 
        mark_inode_dirty_sync(inode);
index 396ef71f41e359f3d7c7ba4bf21d283086c3e8d9..3536fbdc0d91a8f4c5b77dfcb5dd6fab92d8cce7 100644 (file)
@@ -376,7 +376,13 @@ out:
        } else {
                sbi->committed_atomic_block += fi->atomic_write_cnt;
                set_inode_flag(inode, FI_ATOMIC_COMMITTED);
+
+               /*
+                * inode may has no FI_ATOMIC_DIRTIED flag due to no write
+                * before commit.
+                */
                if (is_inode_flag_set(inode, FI_ATOMIC_DIRTIED)) {
+                       /* clear atomic dirty status and set vfs dirty status */
                        clear_inode_flag(inode, FI_ATOMIC_DIRTIED);
                        f2fs_mark_inode_dirty_sync(inode, true);
                }
index 011925ee54f809b5701398e6472096b8265f17d1..22f26871b7aa75d0d25b0a1aad50fb64a9fbd379 100644 (file)
@@ -1532,7 +1532,9 @@ int f2fs_inode_dirtied(struct inode *inode, bool sync)
        }
        spin_unlock(&sbi->inode_lock[DIRTY_META]);
 
-       if (!ret && f2fs_is_atomic_file(inode))
+       /* if atomic write is not committed, set inode w/ atomic dirty */
+       if (!ret && f2fs_is_atomic_file(inode) &&
+                       !is_inode_flag_set(inode, FI_ATOMIC_COMMITTED))
                set_inode_flag(inode, FI_ATOMIC_DIRTIED);
 
        return ret;