6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chao Yu chao@kernel.org
[ Upstream commit db03c20c0850dc8d2bcabfa54b9438f7d666c863 ]
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 Signed-off-by: Sasha Levin sashal@kernel.org --- fs/f2fs/inode.c | 4 +++- fs/f2fs/segment.c | 6 ++++++ fs/f2fs/super.c | 4 +++- 3 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c index 50e64b7b016dc..06688b9957c81 100644 --- a/fs/f2fs/inode.c +++ b/fs/f2fs/inode.c @@ -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); diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index 769a90b609e2c..449c0acbfabc0 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -370,7 +370,13 @@ static int __f2fs_commit_atomic_write(struct inode *inode) } 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); } diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index b1ab7ee2adf9c..330f89ddb5c8f 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -1516,7 +1516,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;