f2fs: prevent atomic file from being dirtied before commit

[ Upstream commit fccaa81de8 ]

Keep atomic file clean while updating and make it dirtied during commit
in order to avoid unnecessary and excessive inode updates in the previous
fix.

Fixes: 4bf7832234 ("f2fs: mark inode dirty for FI_ATOMIC_COMMITTED flag")
Signed-off-by: Daeho Jeong <daehojeong@google.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
Daeho Jeong 2024-09-04 08:33:06 -07:00 committed by Greg Kroah-Hartman
parent b6f186bd6a
commit 364afd8aa8
3 changed files with 14 additions and 1 deletions

View File

@ -798,6 +798,7 @@ enum {
FI_ALIGNED_WRITE, /* enable aligned write */ FI_ALIGNED_WRITE, /* enable aligned write */
FI_COW_FILE, /* indicate COW file */ FI_COW_FILE, /* indicate COW file */
FI_ATOMIC_COMMITTED, /* indicate atomic commit completed except disk sync */ FI_ATOMIC_COMMITTED, /* indicate atomic commit completed except disk sync */
FI_ATOMIC_DIRTIED, /* indicate atomic file is dirtied */
FI_ATOMIC_REPLACE, /* indicate atomic replace */ FI_ATOMIC_REPLACE, /* indicate atomic replace */
FI_OPENED_FILE, /* indicate file has been opened */ FI_OPENED_FILE, /* indicate file has been opened */
FI_MAX, /* max flag, never be used */ FI_MAX, /* max flag, never be used */
@ -3039,7 +3040,6 @@ static inline void __mark_inode_dirty_flag(struct inode *inode,
case FI_INLINE_DOTS: case FI_INLINE_DOTS:
case FI_PIN_FILE: case FI_PIN_FILE:
case FI_COMPRESS_RELEASED: case FI_COMPRESS_RELEASED:
case FI_ATOMIC_COMMITTED:
f2fs_mark_inode_dirty_sync(inode, true); f2fs_mark_inode_dirty_sync(inode, true);
} }
} }

View File

@ -35,6 +35,11 @@ void f2fs_mark_inode_dirty_sync(struct inode *inode, bool sync)
if (f2fs_inode_dirtied(inode, sync)) if (f2fs_inode_dirtied(inode, sync))
return; return;
if (f2fs_is_atomic_file(inode)) {
set_inode_flag(inode, FI_ATOMIC_DIRTIED);
return;
}
mark_inode_dirty_sync(inode); mark_inode_dirty_sync(inode);
} }

View File

@ -199,6 +199,10 @@ void f2fs_abort_atomic_write(struct inode *inode, bool clean)
clear_inode_flag(inode, FI_ATOMIC_COMMITTED); clear_inode_flag(inode, FI_ATOMIC_COMMITTED);
clear_inode_flag(inode, FI_ATOMIC_REPLACE); clear_inode_flag(inode, FI_ATOMIC_REPLACE);
clear_inode_flag(inode, FI_ATOMIC_FILE); clear_inode_flag(inode, FI_ATOMIC_FILE);
if (is_inode_flag_set(inode, FI_ATOMIC_DIRTIED)) {
clear_inode_flag(inode, FI_ATOMIC_DIRTIED);
f2fs_mark_inode_dirty_sync(inode, true);
}
stat_dec_atomic_inode(inode); stat_dec_atomic_inode(inode);
F2FS_I(inode)->atomic_write_task = NULL; F2FS_I(inode)->atomic_write_task = NULL;
@ -368,6 +372,10 @@ out:
} else { } else {
sbi->committed_atomic_block += fi->atomic_write_cnt; sbi->committed_atomic_block += fi->atomic_write_cnt;
set_inode_flag(inode, FI_ATOMIC_COMMITTED); set_inode_flag(inode, FI_ATOMIC_COMMITTED);
if (is_inode_flag_set(inode, FI_ATOMIC_DIRTIED)) {
clear_inode_flag(inode, FI_ATOMIC_DIRTIED);
f2fs_mark_inode_dirty_sync(inode, true);
}
} }
__complete_revoke_list(inode, &revoke_list, ret ? true : false); __complete_revoke_list(inode, &revoke_list, ret ? true : false);