Skip to content

Commit d80afef

Browse files
chaseyuJaegeuk Kim
authored andcommitted
f2fs: fix to account FS_CP_DATA_IO correctly
f2fs_inode_info.cp_task was introduced for FS_CP_DATA_IO accounting since commit b0af6d4 ("f2fs: add app/fs io stat"). However, cp_task usage coverage has been increased due to below commits: commit 040d2bb ("f2fs: fix to avoid deadloop if data_flush is on") commit 186857c ("f2fs: fix potential recursive call when enabling data_flush") So that, if data_flush mountoption is on, when data flush was triggered from background, the IO from data flush will be accounted as checkpoint IO type incorrectly. In order to fix this issue, this patch splits cp_task into two: a) cp_task: used for IO accounting b) wb_task: used to avoid deadlock Fixes: 040d2bb ("f2fs: fix to avoid deadloop if data_flush is on") Fixes: 186857c ("f2fs: fix potential recursive call when enabling data_flush") Signed-off-by: Chao Yu <[email protected]> Signed-off-by: Jaegeuk Kim <[email protected]>
1 parent 544b53d commit d80afef

File tree

4 files changed

+15
-8
lines changed

4 files changed

+15
-8
lines changed

fs/f2fs/checkpoint.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1061,7 +1061,8 @@ void f2fs_remove_dirty_inode(struct inode *inode)
10611061
spin_unlock(&sbi->inode_lock[type]);
10621062
}
10631063

1064-
int f2fs_sync_dirty_inodes(struct f2fs_sb_info *sbi, enum inode_type type)
1064+
int f2fs_sync_dirty_inodes(struct f2fs_sb_info *sbi, enum inode_type type,
1065+
bool from_cp)
10651066
{
10661067
struct list_head *head;
10671068
struct inode *inode;
@@ -1096,11 +1097,15 @@ int f2fs_sync_dirty_inodes(struct f2fs_sb_info *sbi, enum inode_type type)
10961097
if (inode) {
10971098
unsigned long cur_ino = inode->i_ino;
10981099

1099-
F2FS_I(inode)->cp_task = current;
1100+
if (from_cp)
1101+
F2FS_I(inode)->cp_task = current;
1102+
F2FS_I(inode)->wb_task = current;
11001103

11011104
filemap_fdatawrite(inode->i_mapping);
11021105

1103-
F2FS_I(inode)->cp_task = NULL;
1106+
F2FS_I(inode)->wb_task = NULL;
1107+
if (from_cp)
1108+
F2FS_I(inode)->cp_task = NULL;
11041109

11051110
iput(inode);
11061111
/* We need to give cpu to another writers. */
@@ -1229,7 +1234,7 @@ static int block_operations(struct f2fs_sb_info *sbi)
12291234
/* write all the dirty dentry pages */
12301235
if (get_pages(sbi, F2FS_DIRTY_DENTS)) {
12311236
f2fs_unlock_all(sbi);
1232-
err = f2fs_sync_dirty_inodes(sbi, DIR_INODE);
1237+
err = f2fs_sync_dirty_inodes(sbi, DIR_INODE, true);
12331238
if (err)
12341239
return err;
12351240
cond_resched();

fs/f2fs/data.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2856,7 +2856,7 @@ int f2fs_write_single_data_page(struct page *page, int *submitted,
28562856
}
28572857
unlock_page(page);
28582858
if (!S_ISDIR(inode->i_mode) && !IS_NOQUOTA(inode) &&
2859-
!F2FS_I(inode)->cp_task && allow_balance)
2859+
!F2FS_I(inode)->wb_task && allow_balance)
28602860
f2fs_balance_fs(sbi, need_balance_fs);
28612861

28622862
if (unlikely(f2fs_cp_error(sbi))) {
@@ -3156,7 +3156,7 @@ static inline bool __should_serialize_io(struct inode *inode,
31563156
struct writeback_control *wbc)
31573157
{
31583158
/* to avoid deadlock in path of data flush */
3159-
if (F2FS_I(inode)->cp_task)
3159+
if (F2FS_I(inode)->wb_task)
31603160
return false;
31613161

31623162
if (!S_ISREG(inode->i_mode))

fs/f2fs/f2fs.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -786,6 +786,7 @@ struct f2fs_inode_info {
786786
unsigned int clevel; /* maximum level of given file name */
787787
struct task_struct *task; /* lookup and create consistency */
788788
struct task_struct *cp_task; /* separate cp/wb IO stats*/
789+
struct task_struct *wb_task; /* indicate inode is in context of writeback */
789790
nid_t i_xattr_nid; /* node id that contains xattrs */
790791
loff_t last_disk_size; /* lastly written file size */
791792
spinlock_t i_size_lock; /* protect last_disk_size */
@@ -3745,7 +3746,8 @@ int f2fs_recover_orphan_inodes(struct f2fs_sb_info *sbi);
37453746
int f2fs_get_valid_checkpoint(struct f2fs_sb_info *sbi);
37463747
void f2fs_update_dirty_folio(struct inode *inode, struct folio *folio);
37473748
void f2fs_remove_dirty_inode(struct inode *inode);
3748-
int f2fs_sync_dirty_inodes(struct f2fs_sb_info *sbi, enum inode_type type);
3749+
int f2fs_sync_dirty_inodes(struct f2fs_sb_info *sbi, enum inode_type type,
3750+
bool from_cp);
37493751
void f2fs_wait_on_all_pages(struct f2fs_sb_info *sbi, int type);
37503752
u64 f2fs_get_sectors_written(struct f2fs_sb_info *sbi);
37513753
int f2fs_write_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc);

fs/f2fs/segment.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -476,7 +476,7 @@ void f2fs_balance_fs_bg(struct f2fs_sb_info *sbi, bool from_bg)
476476
mutex_lock(&sbi->flush_lock);
477477

478478
blk_start_plug(&plug);
479-
f2fs_sync_dirty_inodes(sbi, FILE_INODE);
479+
f2fs_sync_dirty_inodes(sbi, FILE_INODE, false);
480480
blk_finish_plug(&plug);
481481

482482
mutex_unlock(&sbi->flush_lock);

0 commit comments

Comments
 (0)