linux-f2fs-devel Mailing List for linux-f2fs
Brought to you by:
kjgkr
You can subscribe to this list here.
2012 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
(10) |
Dec
(98) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2013 |
Jan
(100) |
Feb
(72) |
Mar
(79) |
Apr
(122) |
May
(93) |
Jun
(97) |
Jul
(72) |
Aug
(72) |
Sep
(73) |
Oct
(121) |
Nov
(161) |
Dec
(206) |
2014 |
Jan
(75) |
Feb
(54) |
Mar
(82) |
Apr
(98) |
May
(67) |
Jun
(89) |
Jul
(136) |
Aug
(122) |
Sep
(136) |
Oct
(58) |
Nov
(87) |
Dec
(114) |
2015 |
Jan
(140) |
Feb
(129) |
Mar
(141) |
Apr
(71) |
May
(192) |
Jun
(52) |
Jul
(120) |
Aug
(125) |
Sep
(157) |
Oct
(100) |
Nov
(54) |
Dec
(248) |
2016 |
Jan
(301) |
Feb
(180) |
Mar
(138) |
Apr
(137) |
May
(145) |
Jun
(123) |
Jul
(98) |
Aug
(143) |
Sep
(196) |
Oct
(166) |
Nov
(205) |
Dec
(141) |
2017 |
Jan
(167) |
Feb
(275) |
Mar
(273) |
Apr
(239) |
May
(193) |
Jun
(171) |
Jul
(226) |
Aug
(153) |
Sep
(212) |
Oct
(311) |
Nov
(257) |
Dec
(418) |
2018 |
Jan
(474) |
Feb
(188) |
Mar
(252) |
Apr
(500) |
May
(176) |
Jun
(291) |
Jul
(361) |
Aug
(331) |
Sep
(355) |
Oct
(154) |
Nov
(209) |
Dec
(185) |
2019 |
Jan
(172) |
Feb
(214) |
Mar
(247) |
Apr
(425) |
May
(273) |
Jun
(360) |
Jul
(400) |
Aug
(409) |
Sep
(149) |
Oct
(218) |
Nov
(319) |
Dec
(225) |
2020 |
Jan
(231) |
Feb
(487) |
Mar
(411) |
Apr
(258) |
May
(292) |
Jun
(369) |
Jul
(407) |
Aug
(173) |
Sep
(266) |
Oct
(317) |
Nov
(273) |
Dec
(391) |
2021 |
Jan
(285) |
Feb
(130) |
Mar
(232) |
Apr
(156) |
May
(311) |
Jun
(252) |
Jul
(336) |
Aug
(326) |
Sep
(151) |
Oct
(86) |
Nov
(114) |
Dec
(125) |
2022 |
Jan
(132) |
Feb
(167) |
Mar
(230) |
Apr
(460) |
May
(334) |
Jun
(324) |
Jul
(147) |
Aug
(188) |
Sep
(262) |
Oct
(346) |
Nov
(314) |
Dec
(245) |
2023 |
Jan
(306) |
Feb
(190) |
Mar
(199) |
Apr
(444) |
May
(378) |
Jun
(441) |
Jul
(403) |
Aug
(464) |
Sep
(144) |
Oct
(98) |
Nov
(152) |
Dec
(212) |
2024 |
Jan
(288) |
Feb
(365) |
Mar
(218) |
Apr
(275) |
May
(200) |
Jun
(228) |
Jul
(255) |
Aug
(228) |
Sep
(280) |
Oct
(319) |
Nov
(241) |
Dec
(174) |
2025 |
Jan
(166) |
Feb
(171) |
Mar
(469) |
Apr
(235) |
May
(257) |
Jun
(342) |
Jul
(391) |
Aug
(231) |
Sep
|
Oct
|
Nov
|
Dec
|
From: wangzijie <wan...@ho...> - 2025-08-19 02:36:57
|
>> >> Sometimes I suffered the nat_tree_lock contention between f2fs_write_checkpoint >> and f2fs_get_node_info. Commit a9419b6("f2fs: do not bother checkpoint by >> f2fs_get_node_info") also mentioned that situation. >> >> My idea is, when flush nat entries, we can use some structures to record nat >> pages we may read, and readahead them before hold nat_tree_lock. Before >> impletement code, I did some survey and found a submittion in community. >> >> Subject: f2fs: use bucket sort to avoid tree lookup and list sort when nat flushing >> Link: https://lore.kernel.org/linux-f2fs-devel/201...@hu.../ >> This patch aims to improve nat entry set sort by using bucket. >> I steal that structure and readahead nat pages contain nat entry set which cannot be moved >> to journal according to dirty nat entry set bucket. >> >> By doing this, I think there are two benefits to reducing nat_tree_lock hold time when >> when flush nat entries. >> 1. avoid nat set tree lookup and sort >> 2. readahead nat pages before holding nat_tree_lock >> >> Signed-off-by: wangzijie <wan...@ho...> >> --- >> fs/f2fs/f2fs.h | 1 + >> fs/f2fs/node.c | 70 ++++++++++++++++++++++++-------------------------- >> fs/f2fs/node.h | 2 +- >> 3 files changed, 35 insertions(+), 38 deletions(-) >> >> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h >> index 46be75605..b27cc059f 100644 >> --- a/fs/f2fs/f2fs.h >> +++ b/fs/f2fs/f2fs.h >> @@ -975,6 +975,7 @@ struct f2fs_nm_info { >> struct radix_tree_root nat_set_root;/* root of the nat set cache */ >> struct f2fs_rwsem nat_tree_lock; /* protect nat entry tree */ >> struct list_head nat_entries; /* cached nat entry list (clean) */ >> + struct list_head nat_dirty_set[NAT_ENTRY_PER_BLOCK + 1]; /* store dirty nat set */ >> spinlock_t nat_list_lock; /* protect clean nat entry list */ >> unsigned int nat_cnt[MAX_NAT_STATE]; /* the # of cached nat entries */ >> unsigned int nat_blocks; /* # of nat blocks */ >> diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c >> index 27743b93e..87c975ee8 100644 >> --- a/fs/f2fs/node.c >> +++ b/fs/f2fs/node.c >> @@ -244,6 +244,12 @@ static void __del_from_nat_cache(struct f2fs_nm_info *nm_i, struct nat_entry *e) >> __free_nat_entry(e); >> } >> >> +static void __relocate_nat_entry_set(struct f2fs_nm_info *nm_i, >> + struct nat_entry_set *set) >> +{ >> + list_move_tail(&set->set_list, &nm_i->nat_dirty_set[set->entry_cnt]); >> +} >Hi zijie, >Is there any lock protecting this list related operations in the >current process? Hi, Zhiguo I think the lock protection needed is as same as __set_nat_cache_dirty(). >> + >> static struct nat_entry_set *__grab_nat_entry_set(struct f2fs_nm_info *nm_i, >> struct nat_entry *ne) >> { >> @@ -260,6 +266,7 @@ static struct nat_entry_set *__grab_nat_entry_set(struct f2fs_nm_info *nm_i, >> head->set = set; >> head->entry_cnt = 0; >> f2fs_radix_tree_insert(&nm_i->nat_set_root, set, head); >> + __relocate_nat_entry_set(nm_i, head); >> } >> return head; >> } >> @@ -279,8 +286,10 @@ static void __set_nat_cache_dirty(struct f2fs_nm_info *nm_i, >> * 2. update old block address to new one; >> */ >> if (!new_ne && (get_nat_flag(ne, IS_PREALLOC) || >> - !get_nat_flag(ne, IS_DIRTY))) >> + !get_nat_flag(ne, IS_DIRTY))) { >> head->entry_cnt++; >> + __relocate_nat_entry_set(nm_i, head); >> + } >> >> set_nat_flag(ne, IS_PREALLOC, new_ne); >> >> @@ -309,6 +318,7 @@ static void __clear_nat_cache_dirty(struct f2fs_nm_info *nm_i, >> >> set_nat_flag(ne, IS_DIRTY, false); >> set->entry_cnt--; >> + __relocate_nat_entry_set(nm_i, set); >> nm_i->nat_cnt[DIRTY_NAT]--; >> nm_i->nat_cnt[RECLAIMABLE_NAT]++; >> } >> @@ -2976,24 +2986,6 @@ static void remove_nats_in_journal(struct f2fs_sb_info *sbi) >> up_write(&curseg->journal_rwsem); >> } >> >> -static void __adjust_nat_entry_set(struct nat_entry_set *nes, >> - struct list_head *head, int max) >> -{ >> - struct nat_entry_set *cur; >> - >> - if (nes->entry_cnt >= max) >> - goto add_out; >> - >> - list_for_each_entry(cur, head, set_list) { >> - if (cur->entry_cnt >= nes->entry_cnt) { >> - list_add(&nes->set_list, cur->set_list.prev); >> - return; >> - } >> - } >> -add_out: >> - list_add_tail(&nes->set_list, head); >> -} >> - >> static void __update_nat_bits(struct f2fs_sb_info *sbi, nid_t start_nid, >> const struct f2fs_nat_block *nat_blk) >> { >> @@ -3095,6 +3087,7 @@ static int __flush_nat_entry_set(struct f2fs_sb_info *sbi, >> >> /* Allow dirty nats by node block allocation in write_begin */ >> if (!set->entry_cnt) { >> + list_del(&set->set_list); >> radix_tree_delete(&NM_I(sbi)->nat_set_root, set->set); >> kmem_cache_free(nat_entry_set_slab, set); >> } >> @@ -3109,11 +3102,8 @@ int f2fs_flush_nat_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc) >> struct f2fs_nm_info *nm_i = NM_I(sbi); >> struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA); >> struct f2fs_journal *journal = curseg->journal; >> - struct nat_entry_set *setvec[NAT_VEC_SIZE]; >> struct nat_entry_set *set, *tmp; >> - unsigned int found; >> - nid_t set_idx = 0; >> - LIST_HEAD(sets); >> + int i; >> int err = 0; >> >> /* >> @@ -3129,6 +3119,16 @@ int f2fs_flush_nat_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc) >> if (!nm_i->nat_cnt[DIRTY_NAT]) >> return 0; >> >> + /* readahead sets which cannot be moved to journal */ >> + if (!__has_cursum_space(journal, nm_i->nat_cnt[DIRTY_NAT], NAT_JOURNAL)) { >> + for (i = MAX_NAT_JENTRIES(journal); i <= NAT_ENTRY_PER_BLOCK; i++) { >i am a little confused, why is there "i <= NAT_ENTRY_PER_BLOCK;"? >do we need to calculate according to the current nat block/entry number? >thanks! Yes, you are right, we can calculate according to DIRTY_NAT count to end this loop early. >> + list_for_each_entry_safe(set, tmp, &nm_i->nat_dirty_set[i], set_list) { >> + f2fs_ra_meta_pages(sbi, set->set, 1, >> + META_NAT, true); >> + } >> + } >> + } >> + >> f2fs_down_write(&nm_i->nat_tree_lock); >> >> /* >> @@ -3141,21 +3141,13 @@ int f2fs_flush_nat_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc) >> nm_i->nat_cnt[DIRTY_NAT], NAT_JOURNAL)) >> remove_nats_in_journal(sbi); >> >> - while ((found = __gang_lookup_nat_set(nm_i, >> - set_idx, NAT_VEC_SIZE, setvec))) { >> - unsigned idx; >> - >> - set_idx = setvec[found - 1]->set + 1; >> - for (idx = 0; idx < found; idx++) >> - __adjust_nat_entry_set(setvec[idx], &sets, >> - MAX_NAT_JENTRIES(journal)); >> - } >> - >> /* flush dirty nats in nat entry set */ >> - list_for_each_entry_safe(set, tmp, &sets, set_list) { >> - err = __flush_nat_entry_set(sbi, set, cpc); >> - if (err) >> - break; >> + for (i = 0; i <= NAT_ENTRY_PER_BLOCK; i++) { >> + list_for_each_entry_safe(set, tmp, &nm_i->nat_dirty_set[i], set_list) { >> + err = __flush_nat_entry_set(sbi, set, cpc); >> + if (err) >> + break; >> + } >> } >> >> f2fs_up_write(&nm_i->nat_tree_lock); >> @@ -3249,6 +3241,7 @@ static int init_node_manager(struct f2fs_sb_info *sbi) >> struct f2fs_nm_info *nm_i = NM_I(sbi); >> unsigned char *version_bitmap; >> unsigned int nat_segs; >> + int i; >> int err; >> >> nm_i->nat_blkaddr = le32_to_cpu(sb_raw->nat_blkaddr); >> @@ -3275,6 +3268,9 @@ static int init_node_manager(struct f2fs_sb_info *sbi) >> INIT_LIST_HEAD(&nm_i->nat_entries); >> spin_lock_init(&nm_i->nat_list_lock); >> >> + for (i = 0; i <= NAT_ENTRY_PER_BLOCK; i++) >> + INIT_LIST_HEAD(&nm_i->nat_dirty_set[i]); >> + >> mutex_init(&nm_i->build_lock); >> spin_lock_init(&nm_i->nid_list_lock); >> init_f2fs_rwsem(&nm_i->nat_tree_lock); >> diff --git a/fs/f2fs/node.h b/fs/f2fs/node.h >> index 030390543..d805d4ce7 100644 >> --- a/fs/f2fs/node.h >> +++ b/fs/f2fs/node.h >> @@ -158,7 +158,7 @@ enum mem_type { >> }; >> >> struct nat_entry_set { >> - struct list_head set_list; /* link with other nat sets */ >> + struct list_head set_list; /* link with nat sets which have same entry_cnt */ >> struct list_head entry_list; /* link with dirty nat entries */ >> nid_t set; /* set number*/ >> unsigned int entry_cnt; /* the # of nat entries in set */ >> -- >> 2.25.1 By the way, Chao and Zhiguo I noticed that in f2fs_flush_nat_entries(), the check for nat_cnt[DIRTY_NAT] is out of nat_tree_lock, and in f2fs_write_checkpoint(), there has below check without nat_tree_lock: if (cpc->reason & CP_DISCARD) { if (!f2fs_exist_trim_candidates(sbi, cpc)) { unblock_operations(sbi); goto out; } if (NM_I(sbi)->nat_cnt[DIRTY_NAT] == 0 && SIT_I(sbi)->dirty_sentries == 0 && prefree_segments(sbi) == 0) { f2fs_flush_sit_entries(sbi, cpc); f2fs_clear_prefree_segments(sbi, cpc); unblock_operations(sbi); goto out; } } Is there a missing or we don't need nat_tree_lock in these situations? And do you think the way in this patch is appropriate for reducing nat_tree_lock hold time? |
From: Hongbo Li <lih...@hu...> - 2025-08-19 01:16:43
|
On 2025/8/18 10:09, Chao Yu wrote: > The mount behavior changed after commit d18535132523 ("f2fs: separate the > options parsing and options checking"), let's fix it. > > [Scripts] > mkfs.f2fs -f /dev/vdb > mount -t f2fs -o usrquota /dev/vdb /mnt/f2fs > quotacheck -uc /mnt/f2fs > umount /mnt/f2fs > mount -t f2fs -o usrjquota=aquota.user,jqfmt=vfsold /dev/vdb /mnt/f2fs > mount|grep f2fs > mount -t f2fs -o remount,usrjquota=,jqfmt=vfsold /dev/vdb /mnt/f2fs > mount|grep f2fs > dmesg > > [Before commit] > mount#1: ...,quota,jqfmt=vfsold,usrjquota=aquota.user,... > mount#2: ...,quota,jqfmt=vfsold,... > kmsg: no output > > [After commit] > mount#1: ...,quota,jqfmt=vfsold,usrjquota=aquota.user,... > mount#2: ...,quota,jqfmt=vfsold,usrjquota=aquota.user,... > kmsg: "user quota file already specified" > > [After patch] > mount#1: ...,quota,jqfmt=vfsold,usrjquota=aquota.user,... > mount#2: ...,quota,jqfmt=vfsold,... > kmsg: "remove qf_name aquota.user" > > Fixes: d18535132523 ("f2fs: separate the options parsing and options checking") > Cc: Hongbo Li <lih...@hu...> > Signed-off-by: Chao Yu <ch...@ke...> > --- Reviewed-by: Hongbo Li <lih...@hu...> Thanks, Hongbo > fs/f2fs/super.c | 7 +++++-- > 1 file changed, 5 insertions(+), 2 deletions(-) > > diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c > index 465604fdc5dd..07f6c8cac07a 100644 > --- a/fs/f2fs/super.c > +++ b/fs/f2fs/super.c > @@ -1219,8 +1219,11 @@ static int f2fs_check_quota_consistency(struct fs_context *fc, > goto err_jquota_change; > > if (old_qname) { > - if (new_qname && > - strcmp(old_qname, new_qname) == 0) { > + if (!new_qname) { > + f2fs_info(sbi, "remove qf_name %s", > + old_qname); > + continue; > + } else if (strcmp(old_qname, new_qname) == 0) { > ctx->qname_mask &= ~(1 << i); > continue; > } |
From: Hongbo Li <lih...@hu...> - 2025-08-19 01:16:13
|
On 2025/8/18 10:09, Chao Yu wrote: > syzbot reported a f2fs bug as below: > > Oops: gen[ 107.736417][ T5848] Oops: general protection fault, probably for non-canonical address 0xdffffc0000000000: 0000 [#1] SMP KASAN PTI > KASAN: null-ptr-deref in range [0x0000000000000000-0x0000000000000007] > CPU: 1 UID: 0 PID: 5848 Comm: syz-executor263 Tainted: G W 6.17.0-rc1-syzkaller-00014-g0e39a731820a #0 PREEMPT_{RT,(full)} > RIP: 0010:strcmp+0x3c/0xc0 lib/string.c:284 > Call Trace: > <TASK> > f2fs_check_quota_consistency fs/f2fs/super.c:1188 [inline] > f2fs_check_opt_consistency+0x1378/0x2c10 fs/f2fs/super.c:1436 > __f2fs_remount fs/f2fs/super.c:2653 [inline] > f2fs_reconfigure+0x482/0x1770 fs/f2fs/super.c:5297 > reconfigure_super+0x224/0x890 fs/super.c:1077 > do_remount fs/namespace.c:3314 [inline] > path_mount+0xd18/0xfe0 fs/namespace.c:4112 > do_mount fs/namespace.c:4133 [inline] > __do_sys_mount fs/namespace.c:4344 [inline] > __se_sys_mount+0x317/0x410 fs/namespace.c:4321 > do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] > do_syscall_64+0xfa/0x3b0 arch/x86/entry/syscall_64.c:94 > entry_SYSCALL_64_after_hwframe+0x77/0x7f > > The direct reason is f2fs_check_quota_consistency() may suffer null-ptr-deref > issue in strcmp(). > > The bug can be reproduced w/ below scripts: > mkfs.f2fs -f /dev/vdb > mount -t f2fs -o usrquota /dev/vdb /mnt/f2fs > quotacheck -uc /mnt/f2fs/ > umount /mnt/f2fs > mount -t f2fs -o usrjquota=aquota.user,jqfmt=vfsold /dev/vdb /mnt/f2fs > mount -t f2fs -o remount,usrjquota=,jqfmt=vfsold /dev/vdb /mnt/f2fs > umount /mnt/f2fs > > So, before old_qname and new_qname comparison, we need to check whether > they are all valid pointers, fix it. > > Reported-by: syz...@sy... > Fixes: d18535132523 ("f2fs: separate the options parsing and options checking") > Closes: https://lore.kernel.org/linux-f2fs-devel/689...@go... > Cc: Hongbo Li <lih...@hu...> > Signed-off-by: Chao Yu <ch...@ke...> > --- Reviewed-by: Hongbo Li <lih...@hu...> Thanks, Hongbo > fs/f2fs/super.c | 3 ++- > 1 file changed, 2 insertions(+), 1 deletion(-) > > diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c > index 5aa9d650512d..465604fdc5dd 100644 > --- a/fs/f2fs/super.c > +++ b/fs/f2fs/super.c > @@ -1219,7 +1219,8 @@ static int f2fs_check_quota_consistency(struct fs_context *fc, > goto err_jquota_change; > > if (old_qname) { > - if (strcmp(old_qname, new_qname) == 0) { > + if (new_qname && > + strcmp(old_qname, new_qname) == 0) { > ctx->qname_mask &= ~(1 << i); > continue; > } |
From: Chao Yu <ch...@ke...> - 2025-08-18 09:06:07
|
On 8/18/25 11:51, 王晓珺 wrote: > Hi Chao, > > The combination of truncate and falloc complicates the recovery process. > > For example, in the following scenario: > > write fileA 2M | fsync | truncate 256K | falloc -k 256K 1M | fsync A | SPO > The falloc (256K, 1M) need to be recovered as pre-allocated space. > > But in the following scenarios, the situation is the opposite. > > write fileA 2M | fsync | falloc -k 2M 10M | fsync A | truncate 256K | > fsync A | SPO > In this scenario, the space allocated by falloc needs to be truncated. > In fact, the current f2fs cannot reclaim this part of the space. > > During the recovery process, it is difficult to distinguish > between the above two types of falloc. > > I think that when a file is truncated, a FI_TRUNC_FILE flag should be > setted. > When the file is fsync'd, if the FI_TRUNC_FILE flag is present, > a checkpoint needs to be performed. truncate to small size and fsync would be a common case, it's better to not trigger checkpoint during fsync. What do you think of triggering checkpoint for fsync after falloc -k ... instead? IMO, it shouldn't be a common case in Android. Thanks, > > Thanks, > > On 8/11/2025 10:54 AM, Wang Xiaojun wrote: >> Hi Chao, >> >> This patch will cause falloc to fail in the following scenarios. >> write fileA 2M | fsync | truncate 256K | falloc -k 256K 1M | fsync A >> | SPO >> So I will fix this issue in the next version of the patch. >> >> Thanks, >> >> On 8/8/2025 12:16 PM, Chao Yu wrote: >>> Xiaojun, >>> >>> I just notice generic/483 will fail w/ this change, can you please >>> take a >>> look? >>> >>> Thanks, >>> >>> On 8/7/2025 4:44 PM, Wang Xiaojun wrote: >>>> This patch fixes missing space reclamation during the recovery process. >>>> In the following scenarios, F2FS cannot reclaim truncated space. >>>> case 1: >>>> write file A, size is 1G | CP | truncate A to 1M | fsync A | SPO >>>> >>>> case 2: >>>> CP | write file A, size is 1G | fsync A | truncate A to 1M | fsync A >>>> |SPO >>>> >>>> During the recovery process, F2FS will recover file A, >>>> but the 1M-1G space cannot be reclaimed. >>>> >>>> Fixes: d624c96fb3249 ("f2fs: add recovery routines for roll-forward") >>>> >>>> Signed-off-by: Wang Xiaojun <wan...@vi...> >>>> --- >>>> v3: Add a Fixes line. >>>> v2: Apply Chao's suggestion from v1. No logical changes. >>>> v1: Fix missing space reclamation during the recovery process. >>>> --- >>>> fs/f2fs/f2fs.h | 1 + >>>> fs/f2fs/recovery.c | 18 +++++++++++++++++- >>>> 2 files changed, 18 insertions(+), 1 deletion(-) >>>> >>>> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h >>>> index 46be7560548c..28fce59198ce 100644 >>>> --- a/fs/f2fs/f2fs.h >>>> +++ b/fs/f2fs/f2fs.h >>>> @@ -459,6 +459,7 @@ struct fsync_inode_entry { >>>> struct inode *inode; /* vfs inode pointer */ >>>> block_t blkaddr; /* block address locating the last fsync */ >>>> block_t last_dentry; /* block address locating the last >>>> dentry */ >>>> + loff_t max_i_size; /* previous max file size for truncate */ >>>> }; >>>> #define nats_in_cursum(jnl) (le16_to_cpu((jnl)->n_nats)) >>>> diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c >>>> index 4cb3a91801b4..68b62c8a74d3 100644 >>>> --- a/fs/f2fs/recovery.c >>>> +++ b/fs/f2fs/recovery.c >>>> @@ -95,6 +95,7 @@ static struct fsync_inode_entry >>>> *add_fsync_inode(struct f2fs_sb_info *sbi, >>>> entry = f2fs_kmem_cache_alloc(fsync_entry_slab, >>>> GFP_F2FS_ZERO, true, NULL); >>>> entry->inode = inode; >>>> + entry->max_i_size = i_size_read(inode); >>>> list_add_tail(&entry->list, head); >>>> return entry; >>>> @@ -796,6 +797,7 @@ static int recover_data(struct f2fs_sb_info >>>> *sbi, struct list_head *inode_list, >>>> while (1) { >>>> struct fsync_inode_entry *entry; >>>> struct folio *folio; >>>> + loff_t i_size; >>>> if (!f2fs_is_valid_blkaddr(sbi, blkaddr, META_POR)) >>>> break; >>>> @@ -828,6 +830,9 @@ static int recover_data(struct f2fs_sb_info >>>> *sbi, struct list_head *inode_list, >>>> break; >>>> } >>>> recovered_inode++; >>>> + i_size = i_size_read(entry->inode); >>>> + if (entry->max_i_size < i_size) >>>> + entry->max_i_size = i_size; >>>> } >>>> if (entry->last_dentry == blkaddr) { >>>> err = recover_dentry(entry->inode, folio, dir_list); >>>> @@ -844,8 +849,19 @@ static int recover_data(struct f2fs_sb_info >>>> *sbi, struct list_head *inode_list, >>>> } >>>> recovered_dnode++; >>>> - if (entry->blkaddr == blkaddr) >>>> + if (entry->blkaddr == blkaddr) { >>>> + i_size = i_size_read(entry->inode); >>>> + if (entry->max_i_size > i_size) { >>>> + err = f2fs_truncate_blocks(entry->inode, >>>> + i_size, false); >>>> + if (err) { >>>> + f2fs_folio_put(folio, true); >>>> + break; >>>> + } >>>> + f2fs_mark_inode_dirty_sync(entry->inode, true); >>>> + } >>>> list_move_tail(&entry->list, tmp_inode_list); >>>> + } >>>> next: >>>> ra_blocks = adjust_por_ra_blocks(sbi, ra_blocks, blkaddr, >>>> next_blkaddr_of_node(folio)); >>> >> > |
From: Chao Yu <ch...@ke...> - 2025-08-18 08:28:37
|
On 8/18/25 16:06, Hongbo Li wrote: > Hi Chao, > > On 2025/8/18 10:09, Chao Yu wrote: >> The mount behavior changed after commit d18535132523 ("f2fs: separate the >> options parsing and options checking"), let's fix it. >> >> [Scripts] >> mkfs.f2fs -f /dev/vdb >> mount -t f2fs -o usrquota /dev/vdb /mnt/f2fs >> quotacheck -uc /mnt/f2fs >> umount /mnt/f2fs >> mount -t f2fs -o usrjquota=aquota.user,jqfmt=vfsold /dev/vdb /mnt/f2fs >> mount|grep f2fs >> mount -t f2fs -o remount,usrjquota=,jqfmt=vfsold /dev/vdb /mnt/f2fs >> mount|grep f2fs >> dmesg >> >> [Before commit] >> mount#1: ...,quota,jqfmt=vfsold,usrjquota=aquota.user,... >> mount#2: ...,quota,jqfmt=vfsold,... >> kmsg: no output >> >> [After commit] >> mount#1: ...,quota,jqfmt=vfsold,usrjquota=aquota.user,... >> mount#2: ...,quota,jqfmt=vfsold,usrjquota=aquota.user,... >> kmsg: "user quota file already specified" >> >> [After patch] >> mount#1: ...,quota,jqfmt=vfsold,usrjquota=aquota.user,... >> mount#2: ...,quota,jqfmt=vfsold,... >> kmsg: "remove qf_name aquota.user" >> >> Fixes: d18535132523 ("f2fs: separate the options parsing and options checking") >> Cc: Hongbo Li <lih...@hu...> >> Signed-off-by: Chao Yu <ch...@ke...> >> --- >> fs/f2fs/super.c | 7 +++++-- >> 1 file changed, 5 insertions(+), 2 deletions(-) >> >> diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c >> index 465604fdc5dd..07f6c8cac07a 100644 >> --- a/fs/f2fs/super.c >> +++ b/fs/f2fs/super.c >> @@ -1219,8 +1219,11 @@ static int f2fs_check_quota_consistency(struct fs_context *fc, >> goto err_jquota_change; >> if (old_qname) { >> - if (new_qname && >> - strcmp(old_qname, new_qname) == 0) { >> + if (!new_qname) { > > Thanks for catching this. Do we also need the patch 1/2 ? It seems this patch also solve the syzbot problems. I prefer to split it, since it'd better to use one patch to resolve one problem. :) Thanks, > > Thanks, > Hongbo > >> + f2fs_info(sbi, "remove qf_name %s", >> + old_qname); >> + continue; >> + } else if (strcmp(old_qname, new_qname) == 0) { >> ctx->qname_mask &= ~(1 << i); >> continue; >> } |
From: Hongbo Li <lih...@hu...> - 2025-08-18 08:25:16
|
Hi Chao, On 2025/8/18 10:09, Chao Yu wrote: > The mount behavior changed after commit d18535132523 ("f2fs: separate the > options parsing and options checking"), let's fix it. > > [Scripts] > mkfs.f2fs -f /dev/vdb > mount -t f2fs -o usrquota /dev/vdb /mnt/f2fs > quotacheck -uc /mnt/f2fs > umount /mnt/f2fs > mount -t f2fs -o usrjquota=aquota.user,jqfmt=vfsold /dev/vdb /mnt/f2fs > mount|grep f2fs > mount -t f2fs -o remount,usrjquota=,jqfmt=vfsold /dev/vdb /mnt/f2fs > mount|grep f2fs > dmesg > > [Before commit] > mount#1: ...,quota,jqfmt=vfsold,usrjquota=aquota.user,... > mount#2: ...,quota,jqfmt=vfsold,... > kmsg: no output > > [After commit] > mount#1: ...,quota,jqfmt=vfsold,usrjquota=aquota.user,... > mount#2: ...,quota,jqfmt=vfsold,usrjquota=aquota.user,... > kmsg: "user quota file already specified" > > [After patch] > mount#1: ...,quota,jqfmt=vfsold,usrjquota=aquota.user,... > mount#2: ...,quota,jqfmt=vfsold,... > kmsg: "remove qf_name aquota.user" > > Fixes: d18535132523 ("f2fs: separate the options parsing and options checking") > Cc: Hongbo Li <lih...@hu...> > Signed-off-by: Chao Yu <ch...@ke...> > --- > fs/f2fs/super.c | 7 +++++-- > 1 file changed, 5 insertions(+), 2 deletions(-) > > diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c > index 465604fdc5dd..07f6c8cac07a 100644 > --- a/fs/f2fs/super.c > +++ b/fs/f2fs/super.c > @@ -1219,8 +1219,11 @@ static int f2fs_check_quota_consistency(struct fs_context *fc, > goto err_jquota_change; > > if (old_qname) { > - if (new_qname && > - strcmp(old_qname, new_qname) == 0) { > + if (!new_qname) { Thanks for catching this. Do we also need the patch 1/2 ? It seems this patch also solve the syzbot problems. Thanks, Hongbo > + f2fs_info(sbi, "remove qf_name %s", > + old_qname); > + continue; > + } else if (strcmp(old_qname, new_qname) == 0) { > ctx->qname_mask &= ~(1 << i); > continue; > } |
From: 王晓珺 <wan...@vi...> - 2025-08-18 03:52:05
|
Hi Chao, The combination of truncate and falloc complicates the recovery process. For example, in the following scenario: write fileA 2M | fsync | truncate 256K | falloc -k 256K 1M | fsync A | SPO The falloc (256K, 1M) need to be recovered as pre-allocated space. But in the following scenarios, the situation is the opposite. write fileA 2M | fsync | falloc -k 2M 10M | fsync A | truncate 256K | fsync A | SPO In this scenario, the space allocated by falloc needs to be truncated. In fact, the current f2fs cannot reclaim this part of the space. During the recovery process, it is difficult to distinguish between the above two types of falloc. I think that when a file is truncated, a FI_TRUNC_FILE flag should be setted. When the file is fsync'd, if the FI_TRUNC_FILE flag is present, a checkpoint needs to be performed. Thanks, On 8/11/2025 10:54 AM, Wang Xiaojun wrote: > Hi Chao, > > This patch will cause falloc to fail in the following scenarios. > write fileA 2M | fsync | truncate 256K | falloc -k 256K 1M | fsync A > | SPO > So I will fix this issue in the next version of the patch. > > Thanks, > > On 8/8/2025 12:16 PM, Chao Yu wrote: >> Xiaojun, >> >> I just notice generic/483 will fail w/ this change, can you please >> take a >> look? >> >> Thanks, >> >> On 8/7/2025 4:44 PM, Wang Xiaojun wrote: >>> This patch fixes missing space reclamation during the recovery process. >>> In the following scenarios, F2FS cannot reclaim truncated space. >>> case 1: >>> write file A, size is 1G | CP | truncate A to 1M | fsync A | SPO >>> >>> case 2: >>> CP | write file A, size is 1G | fsync A | truncate A to 1M | fsync A >>> |SPO >>> >>> During the recovery process, F2FS will recover file A, >>> but the 1M-1G space cannot be reclaimed. >>> >>> Fixes: d624c96fb3249 ("f2fs: add recovery routines for roll-forward") >>> >>> Signed-off-by: Wang Xiaojun <wan...@vi...> >>> --- >>> v3: Add a Fixes line. >>> v2: Apply Chao's suggestion from v1. No logical changes. >>> v1: Fix missing space reclamation during the recovery process. >>> --- >>> fs/f2fs/f2fs.h | 1 + >>> fs/f2fs/recovery.c | 18 +++++++++++++++++- >>> 2 files changed, 18 insertions(+), 1 deletion(-) >>> >>> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h >>> index 46be7560548c..28fce59198ce 100644 >>> --- a/fs/f2fs/f2fs.h >>> +++ b/fs/f2fs/f2fs.h >>> @@ -459,6 +459,7 @@ struct fsync_inode_entry { >>> struct inode *inode; /* vfs inode pointer */ >>> block_t blkaddr; /* block address locating the last fsync */ >>> block_t last_dentry; /* block address locating the last >>> dentry */ >>> + loff_t max_i_size; /* previous max file size for truncate */ >>> }; >>> #define nats_in_cursum(jnl) (le16_to_cpu((jnl)->n_nats)) >>> diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c >>> index 4cb3a91801b4..68b62c8a74d3 100644 >>> --- a/fs/f2fs/recovery.c >>> +++ b/fs/f2fs/recovery.c >>> @@ -95,6 +95,7 @@ static struct fsync_inode_entry >>> *add_fsync_inode(struct f2fs_sb_info *sbi, >>> entry = f2fs_kmem_cache_alloc(fsync_entry_slab, >>> GFP_F2FS_ZERO, true, NULL); >>> entry->inode = inode; >>> + entry->max_i_size = i_size_read(inode); >>> list_add_tail(&entry->list, head); >>> return entry; >>> @@ -796,6 +797,7 @@ static int recover_data(struct f2fs_sb_info >>> *sbi, struct list_head *inode_list, >>> while (1) { >>> struct fsync_inode_entry *entry; >>> struct folio *folio; >>> + loff_t i_size; >>> if (!f2fs_is_valid_blkaddr(sbi, blkaddr, META_POR)) >>> break; >>> @@ -828,6 +830,9 @@ static int recover_data(struct f2fs_sb_info >>> *sbi, struct list_head *inode_list, >>> break; >>> } >>> recovered_inode++; >>> + i_size = i_size_read(entry->inode); >>> + if (entry->max_i_size < i_size) >>> + entry->max_i_size = i_size; >>> } >>> if (entry->last_dentry == blkaddr) { >>> err = recover_dentry(entry->inode, folio, dir_list); >>> @@ -844,8 +849,19 @@ static int recover_data(struct f2fs_sb_info >>> *sbi, struct list_head *inode_list, >>> } >>> recovered_dnode++; >>> - if (entry->blkaddr == blkaddr) >>> + if (entry->blkaddr == blkaddr) { >>> + i_size = i_size_read(entry->inode); >>> + if (entry->max_i_size > i_size) { >>> + err = f2fs_truncate_blocks(entry->inode, >>> + i_size, false); >>> + if (err) { >>> + f2fs_folio_put(folio, true); >>> + break; >>> + } >>> + f2fs_mark_inode_dirty_sync(entry->inode, true); >>> + } >>> list_move_tail(&entry->list, tmp_inode_list); >>> + } >>> next: >>> ra_blocks = adjust_por_ra_blocks(sbi, ra_blocks, blkaddr, >>> next_blkaddr_of_node(folio)); >> > |
From: Zhiguo N. <niu...@gm...> - 2025-08-18 02:22:10
|
wangzijie <wan...@ho...> 于2025年8月13日周三 12:06写道: > > Sometimes I suffered the nat_tree_lock contention between f2fs_write_checkpoint > and f2fs_get_node_info. Commit a9419b6("f2fs: do not bother checkpoint by > f2fs_get_node_info") also mentioned that situation. > > My idea is, when flush nat entries, we can use some structures to record nat > pages we may read, and readahead them before hold nat_tree_lock. Before > impletement code, I did some survey and found a submittion in community. > > Subject: f2fs: use bucket sort to avoid tree lookup and list sort when nat flushing > Link: https://lore.kernel.org/linux-f2fs-devel/201...@hu.../ > This patch aims to improve nat entry set sort by using bucket. > I steal that structure and readahead nat pages contain nat entry set which cannot be moved > to journal according to dirty nat entry set bucket. > > By doing this, I think there are two benefits to reducing nat_tree_lock hold time when > when flush nat entries. > 1. avoid nat set tree lookup and sort > 2. readahead nat pages before holding nat_tree_lock > > Signed-off-by: wangzijie <wan...@ho...> > --- > fs/f2fs/f2fs.h | 1 + > fs/f2fs/node.c | 70 ++++++++++++++++++++++++-------------------------- > fs/f2fs/node.h | 2 +- > 3 files changed, 35 insertions(+), 38 deletions(-) > > diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h > index 46be75605..b27cc059f 100644 > --- a/fs/f2fs/f2fs.h > +++ b/fs/f2fs/f2fs.h > @@ -975,6 +975,7 @@ struct f2fs_nm_info { > struct radix_tree_root nat_set_root;/* root of the nat set cache */ > struct f2fs_rwsem nat_tree_lock; /* protect nat entry tree */ > struct list_head nat_entries; /* cached nat entry list (clean) */ > + struct list_head nat_dirty_set[NAT_ENTRY_PER_BLOCK + 1]; /* store dirty nat set */ > spinlock_t nat_list_lock; /* protect clean nat entry list */ > unsigned int nat_cnt[MAX_NAT_STATE]; /* the # of cached nat entries */ > unsigned int nat_blocks; /* # of nat blocks */ > diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c > index 27743b93e..87c975ee8 100644 > --- a/fs/f2fs/node.c > +++ b/fs/f2fs/node.c > @@ -244,6 +244,12 @@ static void __del_from_nat_cache(struct f2fs_nm_info *nm_i, struct nat_entry *e) > __free_nat_entry(e); > } > > +static void __relocate_nat_entry_set(struct f2fs_nm_info *nm_i, > + struct nat_entry_set *set) > +{ > + list_move_tail(&set->set_list, &nm_i->nat_dirty_set[set->entry_cnt]); > +} Hi zijie, Is there any lock protecting this list related operations in the current process? > + > static struct nat_entry_set *__grab_nat_entry_set(struct f2fs_nm_info *nm_i, > struct nat_entry *ne) > { > @@ -260,6 +266,7 @@ static struct nat_entry_set *__grab_nat_entry_set(struct f2fs_nm_info *nm_i, > head->set = set; > head->entry_cnt = 0; > f2fs_radix_tree_insert(&nm_i->nat_set_root, set, head); > + __relocate_nat_entry_set(nm_i, head); > } > return head; > } > @@ -279,8 +286,10 @@ static void __set_nat_cache_dirty(struct f2fs_nm_info *nm_i, > * 2. update old block address to new one; > */ > if (!new_ne && (get_nat_flag(ne, IS_PREALLOC) || > - !get_nat_flag(ne, IS_DIRTY))) > + !get_nat_flag(ne, IS_DIRTY))) { > head->entry_cnt++; > + __relocate_nat_entry_set(nm_i, head); > + } > > set_nat_flag(ne, IS_PREALLOC, new_ne); > > @@ -309,6 +318,7 @@ static void __clear_nat_cache_dirty(struct f2fs_nm_info *nm_i, > > set_nat_flag(ne, IS_DIRTY, false); > set->entry_cnt--; > + __relocate_nat_entry_set(nm_i, set); > nm_i->nat_cnt[DIRTY_NAT]--; > nm_i->nat_cnt[RECLAIMABLE_NAT]++; > } > @@ -2976,24 +2986,6 @@ static void remove_nats_in_journal(struct f2fs_sb_info *sbi) > up_write(&curseg->journal_rwsem); > } > > -static void __adjust_nat_entry_set(struct nat_entry_set *nes, > - struct list_head *head, int max) > -{ > - struct nat_entry_set *cur; > - > - if (nes->entry_cnt >= max) > - goto add_out; > - > - list_for_each_entry(cur, head, set_list) { > - if (cur->entry_cnt >= nes->entry_cnt) { > - list_add(&nes->set_list, cur->set_list.prev); > - return; > - } > - } > -add_out: > - list_add_tail(&nes->set_list, head); > -} > - > static void __update_nat_bits(struct f2fs_sb_info *sbi, nid_t start_nid, > const struct f2fs_nat_block *nat_blk) > { > @@ -3095,6 +3087,7 @@ static int __flush_nat_entry_set(struct f2fs_sb_info *sbi, > > /* Allow dirty nats by node block allocation in write_begin */ > if (!set->entry_cnt) { > + list_del(&set->set_list); > radix_tree_delete(&NM_I(sbi)->nat_set_root, set->set); > kmem_cache_free(nat_entry_set_slab, set); > } > @@ -3109,11 +3102,8 @@ int f2fs_flush_nat_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc) > struct f2fs_nm_info *nm_i = NM_I(sbi); > struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA); > struct f2fs_journal *journal = curseg->journal; > - struct nat_entry_set *setvec[NAT_VEC_SIZE]; > struct nat_entry_set *set, *tmp; > - unsigned int found; > - nid_t set_idx = 0; > - LIST_HEAD(sets); > + int i; > int err = 0; > > /* > @@ -3129,6 +3119,16 @@ int f2fs_flush_nat_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc) > if (!nm_i->nat_cnt[DIRTY_NAT]) > return 0; > > + /* readahead sets which cannot be moved to journal */ > + if (!__has_cursum_space(journal, nm_i->nat_cnt[DIRTY_NAT], NAT_JOURNAL)) { > + for (i = MAX_NAT_JENTRIES(journal); i <= NAT_ENTRY_PER_BLOCK; i++) { i am a little confused, why is there "i <= NAT_ENTRY_PER_BLOCK;"? do we need to calculate according to the current nat block/entry number? thanks! > + list_for_each_entry_safe(set, tmp, &nm_i->nat_dirty_set[i], set_list) { > + f2fs_ra_meta_pages(sbi, set->set, 1, > + META_NAT, true); > + } > + } > + } > + > f2fs_down_write(&nm_i->nat_tree_lock); > > /* > @@ -3141,21 +3141,13 @@ int f2fs_flush_nat_entries(struct f2fs_sb_info *sbi, struct cp_control *cpc) > nm_i->nat_cnt[DIRTY_NAT], NAT_JOURNAL)) > remove_nats_in_journal(sbi); > > - while ((found = __gang_lookup_nat_set(nm_i, > - set_idx, NAT_VEC_SIZE, setvec))) { > - unsigned idx; > - > - set_idx = setvec[found - 1]->set + 1; > - for (idx = 0; idx < found; idx++) > - __adjust_nat_entry_set(setvec[idx], &sets, > - MAX_NAT_JENTRIES(journal)); > - } > - > /* flush dirty nats in nat entry set */ > - list_for_each_entry_safe(set, tmp, &sets, set_list) { > - err = __flush_nat_entry_set(sbi, set, cpc); > - if (err) > - break; > + for (i = 0; i <= NAT_ENTRY_PER_BLOCK; i++) { > + list_for_each_entry_safe(set, tmp, &nm_i->nat_dirty_set[i], set_list) { > + err = __flush_nat_entry_set(sbi, set, cpc); > + if (err) > + break; > + } > } > > f2fs_up_write(&nm_i->nat_tree_lock); > @@ -3249,6 +3241,7 @@ static int init_node_manager(struct f2fs_sb_info *sbi) > struct f2fs_nm_info *nm_i = NM_I(sbi); > unsigned char *version_bitmap; > unsigned int nat_segs; > + int i; > int err; > > nm_i->nat_blkaddr = le32_to_cpu(sb_raw->nat_blkaddr); > @@ -3275,6 +3268,9 @@ static int init_node_manager(struct f2fs_sb_info *sbi) > INIT_LIST_HEAD(&nm_i->nat_entries); > spin_lock_init(&nm_i->nat_list_lock); > > + for (i = 0; i <= NAT_ENTRY_PER_BLOCK; i++) > + INIT_LIST_HEAD(&nm_i->nat_dirty_set[i]); > + > mutex_init(&nm_i->build_lock); > spin_lock_init(&nm_i->nid_list_lock); > init_f2fs_rwsem(&nm_i->nat_tree_lock); > diff --git a/fs/f2fs/node.h b/fs/f2fs/node.h > index 030390543..d805d4ce7 100644 > --- a/fs/f2fs/node.h > +++ b/fs/f2fs/node.h > @@ -158,7 +158,7 @@ enum mem_type { > }; > > struct nat_entry_set { > - struct list_head set_list; /* link with other nat sets */ > + struct list_head set_list; /* link with nat sets which have same entry_cnt */ > struct list_head entry_list; /* link with dirty nat entries */ > nid_t set; /* set number*/ > unsigned int entry_cnt; /* the # of nat entries in set */ > -- > 2.25.1 > > > > _______________________________________________ > Linux-f2fs-devel mailing list > Lin...@li... > https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel |
From: Chao Yu <ch...@ke...> - 2025-08-18 02:09:57
|
The mount behavior changed after commit d18535132523 ("f2fs: separate the options parsing and options checking"), let's fix it. [Scripts] mkfs.f2fs -f /dev/vdb mount -t f2fs -o usrquota /dev/vdb /mnt/f2fs quotacheck -uc /mnt/f2fs umount /mnt/f2fs mount -t f2fs -o usrjquota=aquota.user,jqfmt=vfsold /dev/vdb /mnt/f2fs mount|grep f2fs mount -t f2fs -o remount,usrjquota=,jqfmt=vfsold /dev/vdb /mnt/f2fs mount|grep f2fs dmesg [Before commit] mount#1: ...,quota,jqfmt=vfsold,usrjquota=aquota.user,... mount#2: ...,quota,jqfmt=vfsold,... kmsg: no output [After commit] mount#1: ...,quota,jqfmt=vfsold,usrjquota=aquota.user,... mount#2: ...,quota,jqfmt=vfsold,usrjquota=aquota.user,... kmsg: "user quota file already specified" [After patch] mount#1: ...,quota,jqfmt=vfsold,usrjquota=aquota.user,... mount#2: ...,quota,jqfmt=vfsold,... kmsg: "remove qf_name aquota.user" Fixes: d18535132523 ("f2fs: separate the options parsing and options checking") Cc: Hongbo Li <lih...@hu...> Signed-off-by: Chao Yu <ch...@ke...> --- fs/f2fs/super.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 465604fdc5dd..07f6c8cac07a 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -1219,8 +1219,11 @@ static int f2fs_check_quota_consistency(struct fs_context *fc, goto err_jquota_change; if (old_qname) { - if (new_qname && - strcmp(old_qname, new_qname) == 0) { + if (!new_qname) { + f2fs_info(sbi, "remove qf_name %s", + old_qname); + continue; + } else if (strcmp(old_qname, new_qname) == 0) { ctx->qname_mask &= ~(1 << i); continue; } -- 2.49.0 |
From: Chao Yu <ch...@ke...> - 2025-08-18 02:09:55
|
syzbot reported a f2fs bug as below: Oops: gen[ 107.736417][ T5848] Oops: general protection fault, probably for non-canonical address 0xdffffc0000000000: 0000 [#1] SMP KASAN PTI KASAN: null-ptr-deref in range [0x0000000000000000-0x0000000000000007] CPU: 1 UID: 0 PID: 5848 Comm: syz-executor263 Tainted: G W 6.17.0-rc1-syzkaller-00014-g0e39a731820a #0 PREEMPT_{RT,(full)} RIP: 0010:strcmp+0x3c/0xc0 lib/string.c:284 Call Trace: <TASK> f2fs_check_quota_consistency fs/f2fs/super.c:1188 [inline] f2fs_check_opt_consistency+0x1378/0x2c10 fs/f2fs/super.c:1436 __f2fs_remount fs/f2fs/super.c:2653 [inline] f2fs_reconfigure+0x482/0x1770 fs/f2fs/super.c:5297 reconfigure_super+0x224/0x890 fs/super.c:1077 do_remount fs/namespace.c:3314 [inline] path_mount+0xd18/0xfe0 fs/namespace.c:4112 do_mount fs/namespace.c:4133 [inline] __do_sys_mount fs/namespace.c:4344 [inline] __se_sys_mount+0x317/0x410 fs/namespace.c:4321 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] do_syscall_64+0xfa/0x3b0 arch/x86/entry/syscall_64.c:94 entry_SYSCALL_64_after_hwframe+0x77/0x7f The direct reason is f2fs_check_quota_consistency() may suffer null-ptr-deref issue in strcmp(). The bug can be reproduced w/ below scripts: mkfs.f2fs -f /dev/vdb mount -t f2fs -o usrquota /dev/vdb /mnt/f2fs quotacheck -uc /mnt/f2fs/ umount /mnt/f2fs mount -t f2fs -o usrjquota=aquota.user,jqfmt=vfsold /dev/vdb /mnt/f2fs mount -t f2fs -o remount,usrjquota=,jqfmt=vfsold /dev/vdb /mnt/f2fs umount /mnt/f2fs So, before old_qname and new_qname comparison, we need to check whether they are all valid pointers, fix it. Reported-by: syz...@sy... Fixes: d18535132523 ("f2fs: separate the options parsing and options checking") Closes: https://lore.kernel.org/linux-f2fs-devel/689...@go... Cc: Hongbo Li <lih...@hu...> Signed-off-by: Chao Yu <ch...@ke...> --- fs/f2fs/super.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 5aa9d650512d..465604fdc5dd 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -1219,7 +1219,8 @@ static int f2fs_check_quota_consistency(struct fs_context *fc, goto err_jquota_change; if (old_qname) { - if (strcmp(old_qname, new_qname) == 0) { + if (new_qname && + strcmp(old_qname, new_qname) == 0) { ctx->qname_mask &= ~(1 << i); continue; } -- 2.49.0 |
From: ABN A. P. <ab...@nl...> - 2025-08-17 15:05:51
|
From: Zorro L. <zl...@re...> - 2025-08-17 08:43:31
|
On Sat, Aug 16, 2025 at 03:29:09PM +0800, Chao Yu wrote: > w/ below change [1], f2fs will enable lookup_mode=perf by default, it > will change f2fs dirent lookup method from linear based lookup to hash > based lookup. > > So that, f2fs will ignore sb.s_encoding_flags by default, which is not > compatible w/ f2fs/012 testcase, in where it will control lookup method > by configuring this flag w/ fsck.f2fs. > > To avoid failure of f2fs/012, let's check whether f2fs has supported > "lookup_mode=auto" mount option, mount w/ the option if it can, > otherwise, don't. > > [1] https://lore.kernel.org/linux-f2fs-devel/202...@go... > > Cc: Jaegeuk Kim <ja...@ke...> > Cc: Daniel Lee <ch...@go...> > Signed-off-by: Chao Yu <ch...@ke...> > --- > v2: > - ignore error from _try_scratch_mount "-o lookup_mode=auto" This version looks good to me, thanks for fixing it. Reviewed-by: Zorro Lang <zl...@re...> > tests/f2fs/012 | 13 +++++++++++-- > 1 file changed, 11 insertions(+), 2 deletions(-) > > diff --git a/tests/f2fs/012 b/tests/f2fs/012 > index b3df9a8f..7438d9ce 100755 > --- a/tests/f2fs/012 > +++ b/tests/f2fs/012 > @@ -22,6 +22,15 @@ _require_scratch_nocheck > _require_command "$F2FS_IO_PROG" f2fs_io > _require_command "$F2FS_INJECT_PROG" inject.f2fs > > +#check whether f2fs supports "lookup_mode=x" mount option > +mntopt="" > +_scratch_mkfs -O casefold -C utf8 >> $seqres.full > +_try_scratch_mount "-o lookup_mode=auto" >> $seqres.full 2>&1 > +if [ $? == 0 ]; then > + mntopt="-o lookup_mode=auto" > + _scratch_unmount > +fi > + > check_lookup() > { > local nolinear_lookup=$1 > @@ -30,7 +39,7 @@ check_lookup() > local redheart=$dir/$'\u2764\ufe0f' > > _scratch_mkfs -O casefold -C utf8 >> $seqres.full > - _scratch_mount > + _scratch_mount $mntopt > > mkdir $dir > $F2FS_IO_PROG setflags casefold $dir >> $seqres.full > @@ -52,7 +61,7 @@ check_lookup() > > $F2FS_INJECT_PROG --dent --mb d_hash --nid $ino --val 0x9a2ea068 $SCRATCH_DEV >> $seqres.full > > - _scratch_mount > + _scratch_mount $mntopt > if [ $nolinear_lookup == "1" ]; then > [ -f $redheart ] && _fail "red heart file should not exist" > else > -- > 2.49.0 > |
From: Nanzhe Z. <nz...@12...> - 2025-08-17 04:43:57
|
There's another important reason to utilize an f2fs_iomap_folio_state. Because f2fs doesn't possess a per block state tracking data structure like buffer heads or subpages, it can't track per block dirty state or read/write bytes pending itself. Growing such a structure for f2fs and applying it to all code paths could be a tremendous and destructive task. So I think it's convenient to possess an f2fs own per folio private data structure that can both be compatible with iomap and f2fs's needs, especially helpful for other f2fs's i/o paths that need to support large folios altogether with buffered io but can't go into iomap path (i.e., garbage collection). It can also be extended with fields to meet the needs of other types of f2fs files (e.g., compressed files) if they need to support large folios too. At 2025-08-14 08:39:31, "赵南哲 " <nz...@12...> wrote: >Hi Mr.Christoph, > >Thanks for the quick feedback! > >> That's pretty ugly. What additional flags do you need? > >F2FS can utilize the folio's private field in a non-pointer mode to store its extra flags, which indicate the folio's additional status. >Please take a look at the f2fs.h file from PAGE_PRIVATE_GET_FUNC to the end of clear_page_private_all(). > >These flags persist throughout the entire lifetime of a folio, which conflicts with the iomap_folio_state pointer. >Currently, the private fields of iomap's existing data structures,namely struct iomap's private, struct iomap_iter's private, >and struct iomap_ioend's io_private,are either allocated locally on the stack or have a lifecycle on the heap that only exists >for the duration of the I/O routine. This cannot meet F2FS's requirements. > >> We should try to figure out if there is a sensible way to support the needs >> with a single codebase and data structure. > >As far as I know, only F2FS has this requirement, while other file systems do not. >Therefore, my initial thought was to avoid directly modifying the generic logic in fs/iomap. Instead, I propose designing >a wrapper structure for iomap_folio_state specifically for F2FS to satisfy both iomap's and F2FS's own needs. > >Another issue is the handling of order-0 folios. Since the iomap framework does not allocate an iomap_folio_state for these folios, >F2FS will always stores its private flags in the folio->private field. Then iomap framework would mistakenly interpret these flags as a pointer. > >If we are to solve this issue in generic iomap layer, a minimal changes method to iomap framework I suppose is to let iomap logic can >both distinguish pointer and non pointer mode of folio->private. We should also add a private field to iomap_folio_state , or extend he state >flexible array to store the extra infomation. If iomap detects a order>0 folio's folio->private is used in non pointer mode, then it store the flags in a newly >allocted iomap_folio_state first , clear the private field and then store's its address in it. > >P.S. I just noticed you didn't reply via my resend patch. I misspelled f2fs's subsytem mail address in the original patch and I sincerely apologize for that. >I already re-sent the series as > "[f2fs-dev] [RESEND RFC PATCH 0/9] f2fs: Enable buffered read/write large folios support with extended iomap" >Could we continue the discussion on that thread so the right list gets the >full context? Thanks! > >Best regards, >Nanzhe Zhao > >At 2025-08-13 23:22:37, "Christoph Hellwig" <hc...@in...> wrote: >>On Wed, Aug 13, 2025 at 05:21:22PM +0800, Nanzhe Zhao wrote: >>> * **Why extends iomap** >>> * F2FS stores its flags in the folio's private field, >>> which conflicts with iomap_folio_state. >>> * To resolve this, we designed f2fs_iomap_folio_state, >>> compatible with iomap_folio_state's layout while extending >>> its flexible state array for F2FS private flags. >>> * We store a magic number in read_bytes_pending to distinguish >>> whether a folio uses the original or F2FS's iomap_folio_state. >>> It's chosen because it remains 0 after readahead completes. >> >>That's pretty ugly. What additionals flags do you need? We should >>try to figure out if there is a sensible way to support the needs >>with a single codebase and data structure if that the requirements >>are sensible. |
From: syzbot <syz...@sy...> - 2025-08-17 04:13:11
|
Hello, syzbot has tested the proposed patch and the reproducer did not trigger any issue: Reported-by: syz...@sy... Tested-by: syz...@sy... Tested on: commit: b3b0143b f2fs: fix to avoid NULL pointer dereference i.. git tree: https://git.kernel.org/pub/scm/linux/kernel/git/chao/linux.git bugfix/syzbot console output: https://syzkaller.appspot.com/x/log.txt?x=108473a2580000 kernel config: https://syzkaller.appspot.com/x/.config?x=13f39c6a0380a209 dashboard link: https://syzkaller.appspot.com/bug?extid=d371efea57d5aeab877b compiler: Debian clang version 20.1.7 (++20250616065708+6146a88f6049-1~exp1~20250616065826.132), Debian LLD 20.1.7 Note: no patches were applied. Note: testing is done by a robot and is best-effort only. |
From: Chao Yu <ch...@ke...> - 2025-08-17 03:35:17
|
#syz test: https://git.kernel.org/pub/scm/linux/kernel/git/chao/linux.git bugfix/syzbot On 2025/8/16 11:18, syzbot wrote: > Hello, > > syzbot found the following issue on: > > HEAD commit: 0e39a731820a Merge tag 'for-6.17-rc1-tag' of git://git.ker.. > git tree: upstream > console+strace: https://syzkaller.appspot.com/x/log.txt?x=13344da2580000 > kernel config: https://syzkaller.appspot.com/x/.config?x=13f39c6a0380a209 > dashboard link: https://syzkaller.appspot.com/bug?extid=d371efea57d5aeab877b > compiler: Debian clang version 20.1.7 (++20250616065708+6146a88f6049-1~exp1~20250616065826.132), Debian LLD 20.1.7 > syz repro: https://syzkaller.appspot.com/x/repro.syz?x=12c22c34580000 > C reproducer: https://syzkaller.appspot.com/x/repro.c?x=15a125a2580000 > > Downloadable assets: > disk image: https://storage.googleapis.com/syzbot-assets/e0297ec5b8e1/disk-0e39a731.raw.xz > vmlinux: https://storage.googleapis.com/syzbot-assets/0396bfd57e65/vmlinux-0e39a731.xz > kernel image: https://storage.googleapis.com/syzbot-assets/68482d381f43/bzImage-0e39a731.xz > mounted in repro: https://storage.googleapis.com/syzbot-assets/f909676ebee0/mount_0.gz > fsck result: failed (log: https://syzkaller.appspot.com/x/fsck.log?x=15344da2580000) > > The issue was bisected to: > > commit d185351325237da688de006a2c579e82ea97bdfe > Author: Hongbo Li <lih...@hu...> > Date: Thu Jul 10 12:14:13 2025 +0000 > > f2fs: separate the options parsing and options checking > > bisection log: https://syzkaller.appspot.com/x/bisect.txt?x=137ca5a2580000 > final oops: https://syzkaller.appspot.com/x/report.txt?x=10fca5a2580000 > console output: https://syzkaller.appspot.com/x/log.txt?x=177ca5a2580000 > > IMPORTANT: if you fix the issue, please add the following tag to the commit: > Reported-by: syz...@sy... > Fixes: d18535132523 ("f2fs: separate the options parsing and options checking") > > F2FS-fs (loop0): f2fs_recover_fsync_data: recovery fsync data, check_only: 0 > F2FS-fs (loop0): Mounted with checkpoint version = 48b305e4 > Oops: gen[ 107.736417][ T5848] Oops: general protection fault, probably for non-canonical address 0xdffffc0000000000: 0000 [#1] SMP KASAN PTI > KASAN: null-ptr-deref in range [0x0000000000000000-0x0000000000000007] > CPU: 1 UID: 0 PID: 5848 Comm: syz-executor263 Tainted: G W 6.17.0-rc1-syzkaller-00014-g0e39a731820a #0 PREEMPT_{RT,(full)} > Tainted: [W]=WARN > Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 07/12/2025 > RIP: 0010:strcmp+0x3c/0xc0 lib/string.c:284 > Code: 00 fc ff df 45 31 f6 4a 8d 04 37 48 89 c1 48 c1 e9 03 0f b6 0c 19 84 c9 75 2c 42 0f b6 2c 37 4a 8d 04 36 48 89 c1 48 c1 e9 03 <0f> b6 0c 19 84 c9 75 33 42 0f b6 0c 36 40 38 cd 75 48 49 ff c6 40 > RSP: 0018:ffffc90004adf8f8 EFLAGS: 00010246 > RAX: 0000000000000000 RBX: dffffc0000000000 RCX: 0000000000000000 > RDX: 0000000021ec2c00 RSI: 0000000000000000 RDI: ffff888021ec2c80 > RBP: 0000000000000066 R08: 0000000000000000 R09: 0000000000000000 > R10: ffff88803d2c9768 R11: ffffed1007a592fb R12: 1ffff1100611a891 > R13: 0000000000000000 R14: 0000000000000000 R15: ffff888021ec2c80 > FS: 0000555575c20480(0000) GS:ffff8881269c5000(0000) knlGS:0000000000000000 > CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 > CR2: 0000200000001000 CR3: 000000003d342000 CR4: 00000000003526f0 > Call Trace: > <TASK> > f2fs_check_quota_consistency fs/f2fs/super.c:1188 [inline] > f2fs_check_opt_consistency+0x1378/0x2c10 fs/f2fs/super.c:1436 > __f2fs_remount fs/f2fs/super.c:2653 [inline] > f2fs_reconfigure+0x482/0x1770 fs/f2fs/super.c:5297 > reconfigure_super+0x224/0x890 fs/super.c:1077 > do_remount fs/namespace.c:3314 [inline] > path_mount+0xd18/0xfe0 fs/namespace.c:4112 > do_mount fs/namespace.c:4133 [inline] > __do_sys_mount fs/namespace.c:4344 [inline] > __se_sys_mount+0x317/0x410 fs/namespace.c:4321 > do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] > do_syscall_64+0xfa/0x3b0 arch/x86/entry/syscall_64.c:94 > entry_SYSCALL_64_after_hwframe+0x77/0x7f > RIP: 0033:0x7f13267ca259 > Code: 28 00 00 00 75 05 48 83 c4 28 c3 e8 f1 17 00 00 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 b8 ff ff ff f7 d8 64 89 01 48 > RSP: 002b:00007fff3d15d4a8 EFLAGS: 00000246 ORIG_RAX: 00000000000000a5 > RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f13267ca259 > RDX: 0000000000000000 RSI: 0000200000000040 RDI: 0000000000000000 > RBP: 0000000000000000 R08: 0000200000000140 R09: 00007fff3d15d4e0 > R10: 0000000000000020 R11: 0000000000000246 R12: 00007fff3d15d4e0 > R13: 00007fff3d15d768 R14: 431bde82d7b634db R15: 00007f132681303b > </TASK> > Modules linked in: > ---[ end trace 0000000000000000 ]--- > RIP: 0010:strcmp+0x3c/0xc0 lib/string.c:284 > Code: 00 fc ff df 45 31 f6 4a 8d 04 37 48 89 c1 48 c1 e9 03 0f b6 0c 19 84 c9 75 2c 42 0f b6 2c 37 4a 8d 04 36 48 89 c1 48 c1 e9 03 <0f> b6 0c 19 84 c9 75 33 42 0f b6 0c 36 40 38 cd 75 48 49 ff c6 40 > RSP: 0018:ffffc90004adf8f8 EFLAGS: 00010246 > RAX: 0000000000000000 RBX: dffffc0000000000 RCX: 0000000000000000 > RDX: 0000000021ec2c00 RSI: 0000000000000000 RDI: ffff888021ec2c80 > RBP: 0000000000000066 R08: 0000000000000000 R09: 0000000000000000 > R10: ffff88803d2c9768 R11: ffffed1007a592fb R12: 1ffff1100611a891 > R13: 0000000000000000 R14: 0000000000000000 R15: ffff888021ec2c80 > FS: 0000555575c20480(0000) GS:ffff8881268c5000(0000) knlGS:0000000000000000 > CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 > CR2: 0000000000000000 CR3: 000000003d342000 CR4: 00000000003526f0 > ---------------- > Code disassembly (best guess), 4 bytes skipped: > 0: 45 31 f6 xor %r14d,%r14d > 3: 4a 8d 04 37 lea (%rdi,%r14,1),%rax > 7: 48 89 c1 mov %rax,%rcx > a: 48 c1 e9 03 shr $0x3,%rcx > e: 0f b6 0c 19 movzbl (%rcx,%rbx,1),%ecx > 12: 84 c9 test %cl,%cl > 14: 75 2c jne 0x42 > 16: 42 0f b6 2c 37 movzbl (%rdi,%r14,1),%ebp > 1b: 4a 8d 04 36 lea (%rsi,%r14,1),%rax > 1f: 48 89 c1 mov %rax,%rcx > 22: 48 c1 e9 03 shr $0x3,%rcx > * 26: 0f b6 0c 19 movzbl (%rcx,%rbx,1),%ecx <-- trapping instruction > 2a: 84 c9 test %cl,%cl > 2c: 75 33 jne 0x61 > 2e: 42 0f b6 0c 36 movzbl (%rsi,%r14,1),%ecx > 33: 40 38 cd cmp %cl,%bpl > 36: 75 48 jne 0x80 > 38: 49 ff c6 inc %r14 > 3b: 40 rex > > > --- > This report is generated by a bot. It may contain errors. > See https://goo.gl/tpsmEJ for more information about syzbot. > syzbot engineers can be reached at syz...@go.... > > syzbot will keep track of this issue. See: > https://goo.gl/tpsmEJ#status for how to communicate with syzbot. > For information about bisection process see: https://goo.gl/tpsmEJ#bisection > > If the report is already addressed, let syzbot know by replying with: > #syz fix: exact-commit-title > > If you want syzbot to run the reproducer, reply with: > #syz test: git://repo/address.git branch-or-commit-hash > If you attach or paste a git patch, syzbot will apply it before testing. > > If you want to overwrite report's subsystems, reply with: > #syz set subsystems: new-subsystem > (See the list of subsystem names on the web dashboard) > > If the report is a duplicate of another one, reply with: > #syz dup: exact-subject-of-another-report > > If you want to undo deduplication, reply with: > #syz undup |
From: Chao Yu <ch...@ke...> - 2025-08-16 07:29:44
|
w/ below change [1], f2fs will enable lookup_mode=perf by default, it will change f2fs dirent lookup method from linear based lookup to hash based lookup. So that, f2fs will ignore sb.s_encoding_flags by default, which is not compatible w/ f2fs/012 testcase, in where it will control lookup method by configuring this flag w/ fsck.f2fs. To avoid failure of f2fs/012, let's check whether f2fs has supported "lookup_mode=auto" mount option, mount w/ the option if it can, otherwise, don't. [1] https://lore.kernel.org/linux-f2fs-devel/202...@go... Cc: Jaegeuk Kim <ja...@ke...> Cc: Daniel Lee <ch...@go...> Signed-off-by: Chao Yu <ch...@ke...> --- v2: - ignore error from _try_scratch_mount "-o lookup_mode=auto" tests/f2fs/012 | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/tests/f2fs/012 b/tests/f2fs/012 index b3df9a8f..7438d9ce 100755 --- a/tests/f2fs/012 +++ b/tests/f2fs/012 @@ -22,6 +22,15 @@ _require_scratch_nocheck _require_command "$F2FS_IO_PROG" f2fs_io _require_command "$F2FS_INJECT_PROG" inject.f2fs +#check whether f2fs supports "lookup_mode=x" mount option +mntopt="" +_scratch_mkfs -O casefold -C utf8 >> $seqres.full +_try_scratch_mount "-o lookup_mode=auto" >> $seqres.full 2>&1 +if [ $? == 0 ]; then + mntopt="-o lookup_mode=auto" + _scratch_unmount +fi + check_lookup() { local nolinear_lookup=$1 @@ -30,7 +39,7 @@ check_lookup() local redheart=$dir/$'\u2764\ufe0f' _scratch_mkfs -O casefold -C utf8 >> $seqres.full - _scratch_mount + _scratch_mount $mntopt mkdir $dir $F2FS_IO_PROG setflags casefold $dir >> $seqres.full @@ -52,7 +61,7 @@ check_lookup() $F2FS_INJECT_PROG --dent --mb d_hash --nid $ino --val 0x9a2ea068 $SCRATCH_DEV >> $seqres.full - _scratch_mount + _scratch_mount $mntopt if [ $nolinear_lookup == "1" ]; then [ -f $redheart ] && _fail "red heart file should not exist" else -- 2.49.0 |
From: Chao Yu <ch...@ke...> - 2025-08-16 07:15:35
|
On 2025/8/15 23:54, Zorro Lang wrote: > On Fri, Aug 08, 2025 at 02:58:03PM +0800, Chao Yu wrote: >> w/ below change [1], f2fs will enable lookup_mode=perf by default, it >> will change f2fs dirent lookup method from linear based lookup to hash >> based lookup. >> >> So that, f2fs will ignore sb.s_encoding_flags by default, which is not >> compatible w/ f2fs/012 testcase, in where it will control lookup method >> by configuring this flag w/ fsck.f2fs. >> >> To avoid failure of f2fs/012, let's check whether f2fs has supported >> "lookup_mode=auto" mount option, mount w/ the option if it can, >> otherwise, don't. >> >> [1] https://lore.kernel.org/linux-f2fs-devel/202...@go... >> >> Cc: Daniel Lee <ch...@go...> >> Signed-off-by: Chao Yu <ch...@ke...> >> --- > > With this patch, I always get below error: > > f2fs/012 2s ... - output mismatch (see /root/git/xfstests/results//f2fs/012.out.bad) > --- tests/f2fs/012.out 2025-07-21 13:33:12.379585206 +0800 > +++ /root/git/xfstests/results//f2fs/012.out.bad 2025-08-15 23:51:54.156835560 +0800 > @@ -1,2 +1,4 @@ > QA output created by 012 > +mount: /mnt/scratch: wrong fs type, bad option, bad superblock on /dev/sda6, missing codepage or helper program, or other error. > + dmesg(1) may have more information after failed mount system call. > Silence is golden > ... > (Run 'diff -u /root/git/xfstests/tests/f2fs/012.out /root/git/xfstests/results//f2fs/012.out.bad' to see the entire diff) > > Then test passed without this patch: Sorry, I thought I've checked the case that kernel doesn't support lookup_mode=x mount option. > > f2fs/012 2s ... 3s > Ran: f2fs/012 > Passed all 1 tests > > >> tests/f2fs/012 | 13 +++++++++++-- >> 1 file changed, 11 insertions(+), 2 deletions(-) >> >> diff --git a/tests/f2fs/012 b/tests/f2fs/012 >> index b3df9a8f..15fc8f0c 100755 >> --- a/tests/f2fs/012 >> +++ b/tests/f2fs/012 >> @@ -22,6 +22,15 @@ _require_scratch_nocheck >> _require_command "$F2FS_IO_PROG" f2fs_io >> _require_command "$F2FS_INJECT_PROG" inject.f2fs >> >> +#check whether f2fs supports "lookup_mode=x" mount option >> +mntopt="" >> +_scratch_mkfs -O casefold -C utf8 >> $seqres.full >> +_try_scratch_mount "-o lookup_mode=auto" We need to ignore the error from _try_scratch_mount ... here, let me fix it. Thanks, >> +if [ $? == 0 ]; then >> + mntopt="-o lookup_mode=auto" >> + _scratch_unmount >> +fi >> + >> check_lookup() >> { >> local nolinear_lookup=$1 >> @@ -30,7 +39,7 @@ check_lookup() >> local redheart=$dir/$'\u2764\ufe0f' >> >> _scratch_mkfs -O casefold -C utf8 >> $seqres.full >> - _scratch_mount >> + _scratch_mount $mntopt >> >> mkdir $dir >> $F2FS_IO_PROG setflags casefold $dir >> $seqres.full >> @@ -52,7 +61,7 @@ check_lookup() >> >> $F2FS_INJECT_PROG --dent --mb d_hash --nid $ino --val 0x9a2ea068 $SCRATCH_DEV >> $seqres.full >> >> - _scratch_mount >> + _scratch_mount $mntopt >> if [ $nolinear_lookup == "1" ]; then >> [ -f $redheart ] && _fail "red heart file should not exist" >> else >> -- >> 2.40.1 >> > |
From: Chao Yu <ch...@ke...> - 2025-08-16 07:09:45
|
On 2025/8/15 23:31, Zorro Lang wrote: > On Fri, Aug 15, 2025 at 04:14:03PM +0800, Chao Yu wrote: >> This is a regression testcase, it is added to check below case >> and its variants: >> - write 16k data into compressed file (data will be compressed) >> - truncate file to 12k (truncate partial data in compressed cluster) >> - truncate file to 20k >> - verify data in range of [12k, 16k] to see whether data is all zero >> or not >> >> Cc: Jaegeuk Kim <ja...@ke...> >> Signed-off-by: Chao Yu <ch...@ke...> >> --- >> v3: >> - introduce build_fio_config() for cleanup >> - use run_check() to check return value of check_data_eof() >> - add _cleanup >> - use $XFS_IO_PROG instead of xfs_io >> tests/f2fs/018 | 89 ++++++++++++++++++++++++++++++++++++++++++++++ >> tests/f2fs/018.out | 2 ++ >> 2 files changed, 91 insertions(+) >> create mode 100755 tests/f2fs/018 >> create mode 100644 tests/f2fs/018.out >> >> diff --git a/tests/f2fs/018 b/tests/f2fs/018 >> new file mode 100755 >> index 00000000..8013042d >> --- /dev/null >> +++ b/tests/f2fs/018 >> @@ -0,0 +1,89 @@ >> +#! /bin/bash >> +# SPDX-License-Identifier: GPL-2.0 >> +# Copyright (c) 2025 Chao Yu. All Rights Reserved. >> +# >> +# FS QA Test No. f2fs/018 >> +# >> +# This is a regression test to check whether page eof will be >> +# zero or not after we truncate partial data in compressed >> +# cluster. >> +# >> +. ./common/preamble >> +_begin_fstest auto quick rw compress >> + >> +_fixed_by_kernel_commit ba8dac350faf \ >> + "f2fs: fix to zero post-eof page" >> +_fixed_by_kernel_commit xxxxxxxxxxxx \ >> + "f2fs: fix to zero data after EOF for compressed file correctly" >> + >> +_require_xfs_io_command "truncate" >> +_require_scratch >> + >> +testfile=$SCRATCH_MNT/testfile >> +fio_config=$tmp.fio >> + >> +build_fio_config() >> +{ >> + local offset=$1 >> + local size=$2 >> + >> + cat >$fio_config <<EOF >> +[verify-data] >> +filename=$testfile >> +rw=read >> +verify=pattern >> +verify_pattern=0x00 >> +do_verify=1 >> +verify_only >> +offset=$offset >> +size=$size >> +numjobs=1 >> +EOF >> + cat $fio_config >> $seqres.full >> +} >> + >> +build_fio_config 0 4k >> +_require_fio $fio_config >> + >> +_cleanup() >> +{ >> + rm -f $testfile >> +} > > This _cleanup isn't necessary, the $testfile is on SCRATCH_DEV, we don't > need to cleanup SCRATCH_DEV manually. > > Others look good to me, I can help to remove above _cleanup function when > I merge this patchset, if other 2 patches are good to merge too :) Fine to me. :) > > Reviewed-by: Zorro Lang <zl...@re...> Thanks a lot for all your review and suggestion. Thanks, > > Thanks, > Zorro > >> + >> +_scratch_mkfs "-O extra_attr,compression" >> $seqres.full || _fail "mkfs failed" >> +_scratch_mount "-o compress_extension=*" >> $seqres.full >> + >> +check_data_eof() >> +{ >> + local eof_start=$1 >> + local eof_size=$2 >> + local filesize=$3 >> + local offset1=$4 >> + local offset2=$5 >> + local offset3=$6 >> + >> + rm -f $testfile >> + >> + $XFS_IO_PROG -f -c "pwrite 0 $filesize" -c "fsync" $testfile >> $seqres.full >> + $XFS_IO_PROG -c "truncate $offset1" $testfile >> + $XFS_IO_PROG -c "truncate $offset2" $testfile >> + >> + if [ "$offset3" ]; then >> + $XFS_IO_PROG -c "truncate $offset3" $testfile >> + fi >> + >> + build_fio_config $eof_start $eof_size >> + $FIO_PROG $fio_config >> $seqres.full 2>&1 >> + >> + return $? >> +} >> + >> +run_check check_data_eof 12k 4k 16k 12k 20k >> +run_check check_data_eof 10k 6k 16k 10k 20k >> +run_check check_data_eof 12k 4k 16k 8k 12k 20k >> +run_check check_data_eof 10k 6k 16k 8k 10k 20k >> + >> +echo "Silence is golden" >> + >> +status=0 >> +exit >> diff --git a/tests/f2fs/018.out b/tests/f2fs/018.out >> new file mode 100644 >> index 00000000..8849e303 >> --- /dev/null >> +++ b/tests/f2fs/018.out >> @@ -0,0 +1,2 @@ >> +QA output created by 018 >> +Silence is golden >> -- >> 2.49.0 >> > |
From: Chao Yu <ch...@ke...> - 2025-08-16 07:08:14
|
On 2025/8/15 23:12, Zorro Lang wrote: > On Fri, Aug 15, 2025 at 04:02:12PM +0800, Chao Yu wrote: >> On 8/15/25 05:18, Zorro Lang wrote: >>> On Thu, Aug 14, 2025 at 05:07:12PM +0800, Chao Yu wrote: >>>> This is a regression test: >>>> 1. create directory >>>> 2. add a new xattr entry to create xattr node >>>> 3. use inject.f2fs to inject nid of xattr node w/ ino in a file >>>> 4. check whether f2fs kernel module will detect and report such >>>> corruption in the file >>>> >>>> Cc: Jaegeuk Kim <ja...@ke...> >>>> Signed-off-by: Chao Yu <ch...@ke...> >>>> --- >>>> v3: >>>> - use _require_scratch_nocheck instead of _require_scratch >>>> - add missing _require_attrs user >>>> - add comments for why exporting MKFS_OPTIONS="" >>>> tests/f2fs/020 | 51 ++++++++++++++++++++++++++++++++++++++++++++++ >>>> tests/f2fs/020.out | 2 ++ >>>> 2 files changed, 53 insertions(+) >>>> create mode 100755 tests/f2fs/020 >>>> create mode 100644 tests/f2fs/020.out >>>> >>>> diff --git a/tests/f2fs/020 b/tests/f2fs/020 >>>> new file mode 100755 >>>> index 00000000..7ce1f92f >>>> --- /dev/null >>>> +++ b/tests/f2fs/020 >>>> @@ -0,0 +1,51 @@ >>>> +#! /bin/bash >>>> +# SPDX-License-Identifier: GPL-2.0 >>>> +# Copyright (c) 2025 Chao Yu. All Rights Reserved. >>>> +# >>>> +# FS QA Test No. f2fs/020 >>>> +# >>>> +# This is a regression test: >>>> +# 1. create directory >>>> +# 2. add a new xattr entry to create xattr node >>>> +# 3. use inject.f2fs to inject nid of xattr node w/ ino in a file >>>> +# 4. check whether f2fs kernel module will detect and report such >>>> +# corruption in the file >>>> +# >>>> +. ./common/preamble >>>> +_begin_fstest auto quick rw >>>> + >>>> +. ./common/attr >>>> + >>>> +_fixed_by_kernel_commit 061cf3a84bde \ >>>> + "f2fs: fix to do sanity check on ino and xnid" >>>> + >>>> +_require_scratch_nocheck >>>> +_require_command "$F2FS_INJECT_PROG" inject.f2fs >>>> +_require_attrs user >>>> + >>>> +# remove all mkfs options to avoid layout change of on-disk inode >>>> +export MKFS_OPTIONS="" >>>> + >>>> +testdir=$SCRATCH_MNT/testdir >>>> + >>>> +_scratch_mkfs >> $seqres.full >>>> +_scratch_mount "-o user_xattr,noinline_xattr" >>>> + >>>> +mkdir $testdir >>>> +# add a new xattr entry to create xattr node >>>> +$SETFATTR_PROG -n user.abc -v 123 $testdir >>>> + >>>> +_scratch_unmount >>>> + >>>> +# inject i_xattr_nid w/ nid of inode node >>>> +$F2FS_INJECT_PROG --node --mb i_xattr_nid --nid 4 --val 4 $SCRATCH_DEV >> $seqres.full >> >> Zorro, I missed one thing, this testcase relies on a f2fs-tools patch, please apply >> this before running the testcase. >> >> https://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs-tools.git/commit/?h=dev-test&id=2174461cdd0a22edc5e7d172605bff4740582438 >> >> Do I need to create a _require_* function for f2fs to verify whether f2fs-tools >> support the required feature or not? > > Actually for further f2fs testing (depends on injection), we'd better to have related > functions, you can refer to: > > _require_xfs_db_command > > Or more xfs_db related functions in common/xfs if you need. Thanks for the information. > > If you don't want to add this _require_ function in this patch (this's not the only > one f2fs case uses inject.f2fs), I think you can send another patchset to do that > later (just let this case fails on old f2fs temporarily :). Okay, will introduce _require_ function in separated patch. :) Thanks, > > Thanks, > Zorro > >> >>>> + >>>> +_scratch_mount >> >> Oh, I may missed to add "-o acl,user_xattr" here. >> >>>> +# may potentially trigger a deadlock w/ double inode_lock on parent's inode >>>> +mkdir $testdir/dir >> $seqres.full 2>&1 >>>> +_scratch_unmount >>> >>> Can you provide a test result to prove this test case trigger a failure >>> on general kernel (not debug kernel). If it can, then this version is good >>> to me :) >> >> Well, expectation is it will hang kernel, so that the f2fs/020 will stop here >> once we encounter the issue. >> >> Thanks, >> >>> >>> Thanks, >>> Zorro >>> >>>> + >>>> +echo "Silence is golden" >>>> + >>>> +status=0 >>>> +exit >>>> diff --git a/tests/f2fs/020.out b/tests/f2fs/020.out >>>> new file mode 100644 >>>> index 00000000..20d7944e >>>> --- /dev/null >>>> +++ b/tests/f2fs/020.out >>>> @@ -0,0 +1,2 @@ >>>> +QA output created by 020 >>>> +Silence is golden >>>> -- >>>> 2.49.0 >>>> >>> >> > |
From: Chao Yu <ch...@ke...> - 2025-08-16 07:05:53
|
On 2025/8/16 00:20, Jaegeuk Kim via Linux-f2fs-devel wrote: > This patch introduces a proc entry to show the currently enrolled donation > files. > > - "File path" indicates a file. > - "Status" > a. "Donated" means the file is registed in the donation list by > fadvise(offset, length, POSIX_FADV_NOREUSE) > b. "Evicted" means the donated pages were reclaimed. > - "Offset (kb)" and "Length (kb) show the registered donation range. > - "Cached pages (kb)" shows the amount of cached pages in the inode page cache. > > For example, > > Donation List > # of files : 2 > File path Status Offset (kb) Length (kb) Cached pages (kb) > --- > /local/tmp/test2 Donated 0 1048576 2097152 > /local/tmp/test Evicted 0 1048576 1048576 > > Signed-off-by: Jaegeuk Kim <ja...@ke...> Reviewed-by: Chao Yu <ch...@ke...> Thanks, |
From: Chao Yu <ch...@ke...> - 2025-08-16 07:05:15
|
On 2025/8/15 19:27, Sheng Yong wrote: > On 8/15/25 18:38, Chao Yu wrote: >> Yong, >> >> Could you please split this patchset to two, 1~13 and 14~32? and update >> 1~13 first? I guess 1~13 are almost clear to be merged. > > Hi, Chao, > > Sorry for the delay. I will split the patchset and send a new version ASAP. Thanks a lot, Yong. :) Thanks, > > Thanks, > shengyong >> >> On 6/10/25 20:37, Sheng Yong wrote: >>> Hi, folks, >>> >>> This patchset tries to add an auto testsuit for f2fs-tools, including >>> fsck.f2fs, inject.f2fs for now. >>> >>> The patchset can splited into 3 parts: >>> PATCH 1~9: is a preparation for testcases. It fixes some errors in >>> fsck and inject, and do some cleanup and improvement for >>> f2fs-tools. >>> PATCH 10~13: add new injection members >>> PATCH 14~32: add testcases >>> >>> thanks, >>> shengyong >>> >>> -8<- >>> >>> The following is almost quoted from v1: >>> >>> The basic idea of these testcases are: >>> 1. create f2fs image >>> 2. corrupt the image by inject specific fields >>> 3. fsck fixes the image >>> 4. verify fsck output with expected message >>> >>> Some helper scripts are provided: >>> * test_config.in: is used to derive basic configurations of all >>> testcases. >>> * runtests.in: is used to derive `runtests' which is used to run >>> testcases. >>> * filter.sed: removes unnecessary messages and cleanup arbitrary >>> values. >>> * helpers: provides helper functions >>> >>> The usage of `runtests': >>> * run all testcases: >>> runtests >>> * run one testcase: >>> runtests <testcase directory path> >>> * cleanup previous results: >>> runtests clean >>> >>> To run the testcases on Android, only have to change settings in >>> test_config: >>> * set path of $META and $DATA >>> * set path of tools >>> * push tests directory to an Android phone >>> NOTE TAHT: the testcases will format $META!!! >>> >>> Some testcase requires root permission to mount the image and create >>> files. >>> >>> Each testcase should have a sub-directory, where three files are needed: >>> * README: describe information of the testcase >>> * script: testcase itself >>> * expect.in: is used to derive expected output message >>> >>> New files are generated in the testcase directory after test: >>> * log: output in detail >>> * expect: derived from expect.in >>> * out: output that will be compared with expect >>> * PASS: testcase is passed >>> * FAIL: testcase is failed, in which differ of out and expect is saved >>> >>> The name of testcase directory has some optional prefix: >>> * f_: fsck testcase >>> * i_: inject testcase >>> * m_: mkfs testcase >>> But there are only fsck and inject testcases for now. >>> >>> To run testcases, it's better to compile fsck.f2fs as statically linked >>> executable, or `make install' installs tools and libraries. Otherwise, >>> libtool compiles f2fs-tools in debug mode and create a wrapper script >>> to locate elf executable and libraries. However, dump.f2fs and >>> inject.f2fs cannot be used in the wrapper way. >>> >>> v2: * add some fix and cleanup >>> * remove img.tar.gz from testcases >>> * add testcases for injection >>> * cleanup helpers script and simplify filter.sed and expected.in >>> v1: https://lore.kernel.org/linux-f2fs-devel/202...@op.../ >>> >>> Sheng Yong (32): >>> fsck.f2fs: do not finish/reset zone if dry-run is true >>> f2fs-tools: add option N to answer no for all questions >>> f2fs-tools: cleanup {nid|segno}_in_journal >>> fsck.f2fs: fix invalidate checkpoint >>> dump.f2fs: print more info >>> f2fs-tools: add and export lookup_sit_in_journal >>> inject.f2fs: fix injecting sit/nat in journal >>> inject.f2fs: fix injection on zoned device >>> inject.f2fs: fix and cleanup parsing numeric options >>> inject.f2fs: add members in inject_cp >>> inject.f2fs: add member `feature' in inject_sb >>> inject.f2fs: add members in inject_node >>> inject.f2fs: add member `filename' in inject_dentry >>> tests: prepare helper scripts for testcases >>> tests: add fsck testcase of fixing bad super magic >>> tests: add fsck testcase of fixing errors recorded in sb >>> tests: add fsck testcase of fixing cp crc >>> tests: add fsck testcase of fixing nat entry with invalid ino >>> tests: add fsck testcase of fixing nat entry with invalid blkaddr >>> tests: add fsck testcase of fixing sit entry type >>> tests: add fsck testcase of fixing sit entry vblocks >>> tests: add fsck testcase of fixing sit entry valid_map >>> tests: add fsck testcase of fixing sum entry nid >>> tests: add fsck testcase of fixing sum footer type >>> tests: add fsck testcase of fixing sum entry ofs_in_node >>> tests: add fsck testcase of fixing inode invalid i_addr >>> tests: add fsck testcase of fixing dentry hash code >>> tests: add fsck testcase of fixing lost dots >>> tests: add fsck testcase of fixing duplicated dots >>> tests: add fsck testcase of fixing loop fsync dnodes >>> tests: add inject testcase of injecting META area >>> tests: add inject testcase of injecting node block >>> >>> .gitignore | 14 + >>> Makefile.am | 2 +- >>> configure.ac | 1 + >>> fsck/dump.c | 15 +- >>> fsck/f2fs.h | 12 +- >>> fsck/fsck.c | 2 +- >>> fsck/fsck.h | 4 +- >>> fsck/inject.c | 438 +++++++++++++++++++++----- >>> fsck/inject.h | 1 + >>> fsck/main.c | 14 +- >>> fsck/mount.c | 61 ++-- >>> include/f2fs_fs.h | 1 + >>> lib/libf2fs_zoned.c | 6 +- >>> man/inject.f2fs.8 | 43 ++- >>> tests/Makefile.am | 26 ++ >>> tests/f_cp_bad_crc/README | 5 + >>> tests/f_cp_bad_crc/expect.in | 4 + >>> tests/f_cp_bad_crc/script | 38 +++ >>> tests/f_dentry_bad_hash/README | 8 + >>> tests/f_dentry_bad_hash/expect.in | 8 + >>> tests/f_dentry_bad_hash/script | 56 ++++ >>> tests/f_dentry_dup_dots/README | 11 + >>> tests/f_dentry_dup_dots/expect.in | 26 ++ >>> tests/f_dentry_dup_dots/script | 49 +++ >>> tests/f_dentry_lost_dots/README | 7 + >>> tests/f_dentry_lost_dots/expect.in | 16 + >>> tests/f_dentry_lost_dots/script | 37 +++ >>> tests/f_inode_bad_iaddr/README | 6 + >>> tests/f_inode_bad_iaddr/expect.in | 13 + >>> tests/f_inode_bad_iaddr/script | 50 +++ >>> tests/f_loop_fsync_dnodes/README | 5 + >>> tests/f_loop_fsync_dnodes/expect.in | 6 + >>> tests/f_loop_fsync_dnodes/script | 46 +++ >>> tests/f_nat_bad_blkaddr/README | 4 + >>> tests/f_nat_bad_blkaddr/expect.in | 12 + >>> tests/f_nat_bad_blkaddr/script | 25 ++ >>> tests/f_nat_bad_ino/README | 4 + >>> tests/f_nat_bad_ino/expect.in | 12 + >>> tests/f_nat_bad_ino/script | 31 ++ >>> tests/f_sb_bad_magic/README | 3 + >>> tests/f_sb_bad_magic/expect.in | 5 + >>> tests/f_sb_bad_magic/script | 15 + >>> tests/f_sb_errors/README | 5 + >>> tests/f_sb_errors/expect.in | 7 + >>> tests/f_sb_errors/script | 22 ++ >>> tests/f_sit_bad_type/README | 5 + >>> tests/f_sit_bad_type/expect.in | 3 + >>> tests/f_sit_bad_type/script | 38 +++ >>> tests/f_sit_bad_valid_map/README | 5 + >>> tests/f_sit_bad_valid_map/expect.in | 4 + >>> tests/f_sit_bad_valid_map/script | 43 +++ >>> tests/f_sit_bad_vblocks/README | 5 + >>> tests/f_sit_bad_vblocks/expect.in | 3 + >>> tests/f_sit_bad_vblocks/script | 38 +++ >>> tests/f_ssa_bad_nid/README | 5 + >>> tests/f_ssa_bad_nid/expect.in | 3 + >>> tests/f_ssa_bad_nid/script | 36 +++ >>> tests/f_ssa_bad_ofs_in_node/README | 5 + >>> tests/f_ssa_bad_ofs_in_node/expect.in | 3 + >>> tests/f_ssa_bad_ofs_in_node/script | 36 +++ >>> tests/f_ssa_bad_type/README | 5 + >>> tests/f_ssa_bad_type/expect.in | 3 + >>> tests/f_ssa_bad_type/script | 31 ++ >>> tests/filter.sed | 69 ++++ >>> tests/helpers | 269 ++++++++++++++++ >>> tests/i_meta/README | 5 + >>> tests/i_meta/expect.in | 60 ++++ >>> tests/i_meta/script | 212 +++++++++++++ >>> tests/i_node/README | 5 + >>> tests/i_node/expect.in | 66 ++++ >>> tests/i_node/script | 166 ++++++++++ >>> tests/runtests.in | 48 +++ >>> tests/test_config.in | 53 ++++ >>> 73 files changed, 2284 insertions(+), 116 deletions(-) >>> create mode 100644 tests/Makefile.am >>> create mode 100644 tests/f_cp_bad_crc/README >>> create mode 100644 tests/f_cp_bad_crc/expect.in >>> create mode 100644 tests/f_cp_bad_crc/script >>> create mode 100644 tests/f_dentry_bad_hash/README >>> create mode 100644 tests/f_dentry_bad_hash/expect.in >>> create mode 100644 tests/f_dentry_bad_hash/script >>> create mode 100644 tests/f_dentry_dup_dots/README >>> create mode 100644 tests/f_dentry_dup_dots/expect.in >>> create mode 100644 tests/f_dentry_dup_dots/script >>> create mode 100644 tests/f_dentry_lost_dots/README >>> create mode 100644 tests/f_dentry_lost_dots/expect.in >>> create mode 100644 tests/f_dentry_lost_dots/script >>> create mode 100644 tests/f_inode_bad_iaddr/README >>> create mode 100644 tests/f_inode_bad_iaddr/expect.in >>> create mode 100644 tests/f_inode_bad_iaddr/script >>> create mode 100644 tests/f_loop_fsync_dnodes/README >>> create mode 100644 tests/f_loop_fsync_dnodes/expect.in >>> create mode 100644 tests/f_loop_fsync_dnodes/script >>> create mode 100644 tests/f_nat_bad_blkaddr/README >>> create mode 100644 tests/f_nat_bad_blkaddr/expect.in >>> create mode 100644 tests/f_nat_bad_blkaddr/script >>> create mode 100644 tests/f_nat_bad_ino/README >>> create mode 100644 tests/f_nat_bad_ino/expect.in >>> create mode 100644 tests/f_nat_bad_ino/script >>> create mode 100644 tests/f_sb_bad_magic/README >>> create mode 100644 tests/f_sb_bad_magic/expect.in >>> create mode 100644 tests/f_sb_bad_magic/script >>> create mode 100644 tests/f_sb_errors/README >>> create mode 100644 tests/f_sb_errors/expect.in >>> create mode 100644 tests/f_sb_errors/script >>> create mode 100644 tests/f_sit_bad_type/README >>> create mode 100644 tests/f_sit_bad_type/expect.in >>> create mode 100644 tests/f_sit_bad_type/script >>> create mode 100644 tests/f_sit_bad_valid_map/README >>> create mode 100644 tests/f_sit_bad_valid_map/expect.in >>> create mode 100644 tests/f_sit_bad_valid_map/script >>> create mode 100644 tests/f_sit_bad_vblocks/README >>> create mode 100644 tests/f_sit_bad_vblocks/expect.in >>> create mode 100644 tests/f_sit_bad_vblocks/script >>> create mode 100644 tests/f_ssa_bad_nid/README >>> create mode 100644 tests/f_ssa_bad_nid/expect.in >>> create mode 100644 tests/f_ssa_bad_nid/script >>> create mode 100644 tests/f_ssa_bad_ofs_in_node/README >>> create mode 100644 tests/f_ssa_bad_ofs_in_node/expect.in >>> create mode 100644 tests/f_ssa_bad_ofs_in_node/script >>> create mode 100644 tests/f_ssa_bad_type/README >>> create mode 100644 tests/f_ssa_bad_type/expect.in >>> create mode 100644 tests/f_ssa_bad_type/script >>> create mode 100644 tests/filter.sed >>> create mode 100644 tests/helpers >>> create mode 100644 tests/i_meta/README >>> create mode 100644 tests/i_meta/expect.in >>> create mode 100644 tests/i_meta/script >>> create mode 100644 tests/i_node/README >>> create mode 100644 tests/i_node/expect.in >>> create mode 100644 tests/i_node/script >>> create mode 100644 tests/runtests.in >>> create mode 100644 tests/test_config.in >>> >> > |
From: syzbot <syz...@sy...> - 2025-08-16 03:18:48
|
Hello, syzbot found the following issue on: HEAD commit: 0e39a731820a Merge tag 'for-6.17-rc1-tag' of git://git.ker.. git tree: upstream console+strace: https://syzkaller.appspot.com/x/log.txt?x=13344da2580000 kernel config: https://syzkaller.appspot.com/x/.config?x=13f39c6a0380a209 dashboard link: https://syzkaller.appspot.com/bug?extid=d371efea57d5aeab877b compiler: Debian clang version 20.1.7 (++20250616065708+6146a88f6049-1~exp1~20250616065826.132), Debian LLD 20.1.7 syz repro: https://syzkaller.appspot.com/x/repro.syz?x=12c22c34580000 C reproducer: https://syzkaller.appspot.com/x/repro.c?x=15a125a2580000 Downloadable assets: disk image: https://storage.googleapis.com/syzbot-assets/e0297ec5b8e1/disk-0e39a731.raw.xz vmlinux: https://storage.googleapis.com/syzbot-assets/0396bfd57e65/vmlinux-0e39a731.xz kernel image: https://storage.googleapis.com/syzbot-assets/68482d381f43/bzImage-0e39a731.xz mounted in repro: https://storage.googleapis.com/syzbot-assets/f909676ebee0/mount_0.gz fsck result: failed (log: https://syzkaller.appspot.com/x/fsck.log?x=15344da2580000) The issue was bisected to: commit d185351325237da688de006a2c579e82ea97bdfe Author: Hongbo Li <lih...@hu...> Date: Thu Jul 10 12:14:13 2025 +0000 f2fs: separate the options parsing and options checking bisection log: https://syzkaller.appspot.com/x/bisect.txt?x=137ca5a2580000 final oops: https://syzkaller.appspot.com/x/report.txt?x=10fca5a2580000 console output: https://syzkaller.appspot.com/x/log.txt?x=177ca5a2580000 IMPORTANT: if you fix the issue, please add the following tag to the commit: Reported-by: syz...@sy... Fixes: d18535132523 ("f2fs: separate the options parsing and options checking") F2FS-fs (loop0): f2fs_recover_fsync_data: recovery fsync data, check_only: 0 F2FS-fs (loop0): Mounted with checkpoint version = 48b305e4 Oops: gen[ 107.736417][ T5848] Oops: general protection fault, probably for non-canonical address 0xdffffc0000000000: 0000 [#1] SMP KASAN PTI KASAN: null-ptr-deref in range [0x0000000000000000-0x0000000000000007] CPU: 1 UID: 0 PID: 5848 Comm: syz-executor263 Tainted: G W 6.17.0-rc1-syzkaller-00014-g0e39a731820a #0 PREEMPT_{RT,(full)} Tainted: [W]=WARN Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 07/12/2025 RIP: 0010:strcmp+0x3c/0xc0 lib/string.c:284 Code: 00 fc ff df 45 31 f6 4a 8d 04 37 48 89 c1 48 c1 e9 03 0f b6 0c 19 84 c9 75 2c 42 0f b6 2c 37 4a 8d 04 36 48 89 c1 48 c1 e9 03 <0f> b6 0c 19 84 c9 75 33 42 0f b6 0c 36 40 38 cd 75 48 49 ff c6 40 RSP: 0018:ffffc90004adf8f8 EFLAGS: 00010246 RAX: 0000000000000000 RBX: dffffc0000000000 RCX: 0000000000000000 RDX: 0000000021ec2c00 RSI: 0000000000000000 RDI: ffff888021ec2c80 RBP: 0000000000000066 R08: 0000000000000000 R09: 0000000000000000 R10: ffff88803d2c9768 R11: ffffed1007a592fb R12: 1ffff1100611a891 R13: 0000000000000000 R14: 0000000000000000 R15: ffff888021ec2c80 FS: 0000555575c20480(0000) GS:ffff8881269c5000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000200000001000 CR3: 000000003d342000 CR4: 00000000003526f0 Call Trace: <TASK> f2fs_check_quota_consistency fs/f2fs/super.c:1188 [inline] f2fs_check_opt_consistency+0x1378/0x2c10 fs/f2fs/super.c:1436 __f2fs_remount fs/f2fs/super.c:2653 [inline] f2fs_reconfigure+0x482/0x1770 fs/f2fs/super.c:5297 reconfigure_super+0x224/0x890 fs/super.c:1077 do_remount fs/namespace.c:3314 [inline] path_mount+0xd18/0xfe0 fs/namespace.c:4112 do_mount fs/namespace.c:4133 [inline] __do_sys_mount fs/namespace.c:4344 [inline] __se_sys_mount+0x317/0x410 fs/namespace.c:4321 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] do_syscall_64+0xfa/0x3b0 arch/x86/entry/syscall_64.c:94 entry_SYSCALL_64_after_hwframe+0x77/0x7f RIP: 0033:0x7f13267ca259 Code: 28 00 00 00 75 05 48 83 c4 28 c3 e8 f1 17 00 00 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 b8 ff ff ff f7 d8 64 89 01 48 RSP: 002b:00007fff3d15d4a8 EFLAGS: 00000246 ORIG_RAX: 00000000000000a5 RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f13267ca259 RDX: 0000000000000000 RSI: 0000200000000040 RDI: 0000000000000000 RBP: 0000000000000000 R08: 0000200000000140 R09: 00007fff3d15d4e0 R10: 0000000000000020 R11: 0000000000000246 R12: 00007fff3d15d4e0 R13: 00007fff3d15d768 R14: 431bde82d7b634db R15: 00007f132681303b </TASK> Modules linked in: ---[ end trace 0000000000000000 ]--- RIP: 0010:strcmp+0x3c/0xc0 lib/string.c:284 Code: 00 fc ff df 45 31 f6 4a 8d 04 37 48 89 c1 48 c1 e9 03 0f b6 0c 19 84 c9 75 2c 42 0f b6 2c 37 4a 8d 04 36 48 89 c1 48 c1 e9 03 <0f> b6 0c 19 84 c9 75 33 42 0f b6 0c 36 40 38 cd 75 48 49 ff c6 40 RSP: 0018:ffffc90004adf8f8 EFLAGS: 00010246 RAX: 0000000000000000 RBX: dffffc0000000000 RCX: 0000000000000000 RDX: 0000000021ec2c00 RSI: 0000000000000000 RDI: ffff888021ec2c80 RBP: 0000000000000066 R08: 0000000000000000 R09: 0000000000000000 R10: ffff88803d2c9768 R11: ffffed1007a592fb R12: 1ffff1100611a891 R13: 0000000000000000 R14: 0000000000000000 R15: ffff888021ec2c80 FS: 0000555575c20480(0000) GS:ffff8881268c5000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000000000000 CR3: 000000003d342000 CR4: 00000000003526f0 ---------------- Code disassembly (best guess), 4 bytes skipped: 0: 45 31 f6 xor %r14d,%r14d 3: 4a 8d 04 37 lea (%rdi,%r14,1),%rax 7: 48 89 c1 mov %rax,%rcx a: 48 c1 e9 03 shr $0x3,%rcx e: 0f b6 0c 19 movzbl (%rcx,%rbx,1),%ecx 12: 84 c9 test %cl,%cl 14: 75 2c jne 0x42 16: 42 0f b6 2c 37 movzbl (%rdi,%r14,1),%ebp 1b: 4a 8d 04 36 lea (%rsi,%r14,1),%rax 1f: 48 89 c1 mov %rax,%rcx 22: 48 c1 e9 03 shr $0x3,%rcx * 26: 0f b6 0c 19 movzbl (%rcx,%rbx,1),%ecx <-- trapping instruction 2a: 84 c9 test %cl,%cl 2c: 75 33 jne 0x61 2e: 42 0f b6 0c 36 movzbl (%rsi,%r14,1),%ecx 33: 40 38 cd cmp %cl,%bpl 36: 75 48 jne 0x80 38: 49 ff c6 inc %r14 3b: 40 rex --- This report is generated by a bot. It may contain errors. See https://goo.gl/tpsmEJ for more information about syzbot. syzbot engineers can be reached at syz...@go.... syzbot will keep track of this issue. See: https://goo.gl/tpsmEJ#status for how to communicate with syzbot. For information about bisection process see: https://goo.gl/tpsmEJ#bisection If the report is already addressed, let syzbot know by replying with: #syz fix: exact-commit-title If you want syzbot to run the reproducer, reply with: #syz test: git://repo/address.git branch-or-commit-hash If you attach or paste a git patch, syzbot will apply it before testing. If you want to overwrite report's subsystems, reply with: #syz set subsystems: new-subsystem (See the list of subsystem names on the web dashboard) If the report is a duplicate of another one, reply with: #syz dup: exact-subject-of-another-report If you want to undo deduplication, reply with: #syz undup |
From: <pat...@ke...> - 2025-08-15 16:40:19
|
Hello: This patch was applied to jaegeuk/f2fs.git (dev) by Jaegeuk Kim <ja...@ke...>: On Thu, 7 Aug 2025 21:35:01 +0800 you wrote: > This patch allows privileged users to reserve nodes via the > 'reserve_node' mount option, which is similar to the existing > 'reserve_root' option. > > "-o reserve_node=<N>" means <N> nodes are reserved for privileged > users only. > > [...] Here is the summary with links: - [f2fs-dev,v6] f2fs: add reserved nodes for privileged users https://git.kernel.org/jaegeuk/f2fs/c/a3b0697610ba You are awesome, thank you! -- Deet-doot-dot, I am a bot. https://korg.docs.kernel.org/patchwork/pwbot.html |
From: <pat...@ke...> - 2025-08-15 16:40:17
|
Hello: This series was applied to jaegeuk/f2fs.git (dev) by Jaegeuk Kim <ja...@ke...>: On Thu, 31 Jul 2025 13:34:04 +0800 you wrote: > generic/299 w/ mode=lfs will cause long time latency of checkpoint, > let's dump more information once we hit case. > > CP merge: > - Queued : 0 > - Issued : 1 > - Total : 1 > - Cur time : 9765(ms) > - Peak time : 9765(ms) > > [...] Here is the summary with links: - [f2fs-dev,1/2] f2fs: dump more information when checkpoint was blocked for long time https://git.kernel.org/jaegeuk/f2fs/c/3fcf228b6494 - [f2fs-dev,2/2] f2fs: add time stats of checkpoint for debug https://git.kernel.org/jaegeuk/f2fs/c/57e74035ad5e You are awesome, thank you! -- Deet-doot-dot, I am a bot. https://korg.docs.kernel.org/patchwork/pwbot.html |
From: <pat...@ke...> - 2025-08-15 16:40:16
|
Hello: This patch was applied to jaegeuk/f2fs.git (dev) by Jaegeuk Kim <ja...@ke...>: On Wed, 6 Aug 2025 14:11:06 +0800 you wrote: > generic/091 may fail, then it bisects to the bad commit ba8dac350faf > ("f2fs: fix to zero post-eof page"). > > What will cause generic/091 to fail is something like below Testcase #1: > 1. write 16k as compressed blocks > 2. truncate to 12k > 3. truncate to 20k > 4. verify data in range of [12k, 16k], however data is not zero as > expected > > [...] Here is the summary with links: - [f2fs-dev,v4,2/3] f2fs: fix to zero data after EOF for compressed file correctly https://git.kernel.org/jaegeuk/f2fs/c/0b2cd5092139 You are awesome, thank you! -- Deet-doot-dot, I am a bot. https://korg.docs.kernel.org/patchwork/pwbot.html |