Skip to content

Commit ab59919

Browse files
chaseyuJaegeuk Kim
authored andcommitted
f2fs: check skipped write in f2fs_enable_checkpoint()
This patch introduces sbi->nr_pages[F2FS_SKIPPED_WRITE] to record any skipped write during data flush in f2fs_enable_checkpoint(). So in the loop of data flush, if there is any skipped write in previous flush, let's retry sync_inode_sb(), otherwise, all dirty data written before f2fs_enable_checkpoint() should have been persisted, then break the retry loop. Signed-off-by: Chao Yu <chao@kernel.org> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
1 parent 9936638 commit ab59919

4 files changed

Lines changed: 55 additions & 4 deletions

File tree

fs/f2fs/data.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3495,6 +3495,16 @@ static inline void account_writeback(struct inode *inode, bool inc)
34953495
f2fs_up_read(&F2FS_I(inode)->i_sem);
34963496
}
34973497

3498+
static inline void update_skipped_write(struct f2fs_sb_info *sbi,
3499+
struct writeback_control *wbc)
3500+
{
3501+
long skipped = wbc->pages_skipped;
3502+
3503+
if (is_sbi_flag_set(sbi, SBI_ENABLE_CHECKPOINT) && skipped &&
3504+
wbc->sync_mode == WB_SYNC_ALL)
3505+
atomic_add(skipped, &sbi->nr_pages[F2FS_SKIPPED_WRITE]);
3506+
}
3507+
34983508
static int __f2fs_write_data_pages(struct address_space *mapping,
34993509
struct writeback_control *wbc,
35003510
enum iostat_type io_type)
@@ -3559,10 +3569,19 @@ static int __f2fs_write_data_pages(struct address_space *mapping,
35593569
*/
35603570

35613571
f2fs_remove_dirty_inode(inode);
3572+
3573+
/*
3574+
* f2fs_write_cache_pages() has retry logic for EAGAIN case which is
3575+
* common when racing w/ checkpoint, so only update skipped write
3576+
* when ret is non-zero.
3577+
*/
3578+
if (ret)
3579+
update_skipped_write(sbi, wbc);
35623580
return ret;
35633581

35643582
skip_write:
35653583
wbc->pages_skipped += get_dirty_pages(inode);
3584+
update_skipped_write(sbi, wbc);
35663585
trace_f2fs_writepages(mapping->host, wbc, DATA);
35673586
return 0;
35683587
}

fs/f2fs/debug.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,7 @@ static const char *s_flag[MAX_SBI_FLAG] = {
423423
[SBI_IS_RESIZEFS] = "resizefs",
424424
[SBI_IS_FREEZING] = "freezefs",
425425
[SBI_IS_WRITABLE] = "writable",
426+
[SBI_ENABLE_CHECKPOINT] = "enable_checkpoint",
426427
};
427428

428429
static const char *ipu_mode_names[F2FS_IPU_MAX] = {

fs/f2fs/f2fs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1238,6 +1238,7 @@ enum count_type {
12381238
F2FS_RD_META,
12391239
F2FS_DIO_WRITE,
12401240
F2FS_DIO_READ,
1241+
F2FS_SKIPPED_WRITE, /* skip or fail during f2fs_enable_checkpoint() */
12411242
NR_COUNT_TYPE,
12421243
};
12431244

@@ -1476,6 +1477,7 @@ enum {
14761477
SBI_IS_RESIZEFS, /* resizefs is in process */
14771478
SBI_IS_FREEZING, /* freezefs is in process */
14781479
SBI_IS_WRITABLE, /* remove ro mountoption transiently */
1480+
SBI_ENABLE_CHECKPOINT, /* indicate it's during f2fs_enable_checkpoint() */
14791481
MAX_SBI_FLAG,
14801482
};
14811483

fs/f2fs/super.c

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2690,6 +2690,7 @@ static int f2fs_enable_checkpoint(struct f2fs_sb_info *sbi)
26902690
long long start, writeback, end;
26912691
int ret;
26922692
struct f2fs_lock_context lc;
2693+
long long skipped_write, dirty_data;
26932694

26942695
f2fs_info(sbi, "f2fs_enable_checkpoint() starts, meta: %lld, node: %lld, data: %lld",
26952696
get_pages(sbi, F2FS_DIRTY_META),
@@ -2698,17 +2699,45 @@ static int f2fs_enable_checkpoint(struct f2fs_sb_info *sbi)
26982699

26992700
start = ktime_get();
27002701

2702+
set_sbi_flag(sbi, SBI_ENABLE_CHECKPOINT);
2703+
27012704
/* we should flush all the data to keep data consistency */
27022705
do {
2706+
skipped_write = get_pages(sbi, F2FS_SKIPPED_WRITE);
2707+
dirty_data = get_pages(sbi, F2FS_DIRTY_DATA);
2708+
27032709
sync_inodes_sb(sbi->sb);
27042710
f2fs_io_schedule_timeout(DEFAULT_SCHEDULE_TIMEOUT);
2705-
} while (get_pages(sbi, F2FS_DIRTY_DATA) && retry--);
2711+
2712+
f2fs_info(sbi, "sync_inode_sb done, dirty_data: %lld, %lld, "
2713+
"skipped write: %lld, %lld, retry: %d",
2714+
get_pages(sbi, F2FS_DIRTY_DATA),
2715+
dirty_data,
2716+
get_pages(sbi, F2FS_SKIPPED_WRITE),
2717+
skipped_write, retry);
2718+
2719+
/*
2720+
* sync_inodes_sb() has retry logic, so let's check dirty_data
2721+
* in prior to skipped_write in case there is no dirty data.
2722+
*/
2723+
if (!get_pages(sbi, F2FS_DIRTY_DATA))
2724+
break;
2725+
if (get_pages(sbi, F2FS_SKIPPED_WRITE) == skipped_write)
2726+
break;
2727+
} while (retry--);
2728+
2729+
clear_sbi_flag(sbi, SBI_ENABLE_CHECKPOINT);
27062730

27072731
writeback = ktime_get();
27082732

2709-
if (unlikely(get_pages(sbi, F2FS_DIRTY_DATA)))
2710-
f2fs_warn(sbi, "checkpoint=enable has some unwritten data: %lld",
2711-
get_pages(sbi, F2FS_DIRTY_DATA));
2733+
if (unlikely(get_pages(sbi, F2FS_DIRTY_DATA) ||
2734+
get_pages(sbi, F2FS_SKIPPED_WRITE)))
2735+
f2fs_warn(sbi, "checkpoint=enable unwritten data: %lld, skipped data: %lld, retry: %d",
2736+
get_pages(sbi, F2FS_DIRTY_DATA),
2737+
get_pages(sbi, F2FS_SKIPPED_WRITE), retry);
2738+
2739+
if (get_pages(sbi, F2FS_SKIPPED_WRITE))
2740+
atomic_set(&sbi->nr_pages[F2FS_SKIPPED_WRITE], 0);
27122741

27132742
f2fs_down_write_trace(&sbi->gc_lock, &lc);
27142743
f2fs_dirty_to_prefree(sbi);

0 commit comments

Comments
 (0)