[f2fs-dev] [PATCH] f2fs: device alias: add sanity check for device alias inode
Do sanity check for extent info of device alias inode, in order to avoid unexpected error caused by fuzz test. Cc: Daeho Jeong Signed-off-by: Chao Yu --- To Daeho and Jaegeuk, Merge this into initial patch or merge it separately is both fine to me. fs/f2fs/extent_cache.c | 32 +++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/fs/f2fs/extent_cache.c b/fs/f2fs/extent_cache.c index 0c8a705faa8b..5bf9e4c2b49c 100644 --- a/fs/f2fs/extent_cache.c +++ b/fs/f2fs/extent_cache.c @@ -24,6 +24,7 @@ bool sanity_check_extent_cache(struct inode *inode, struct page *ipage) struct f2fs_sb_info *sbi = F2FS_I_SB(inode); struct f2fs_extent *i_ext = &F2FS_INODE(ipage)->i_ext; struct extent_info ei; + int devi; get_read_extent_info(&ei, i_ext); @@ -38,7 +39,36 @@ bool sanity_check_extent_cache(struct inode *inode, struct page *ipage) ei.blk, ei.fofs, ei.len); return false; } - return true; + + if (!IS_DEVICE_ALIASING(inode)) + return true; + + for (devi = 0; devi < sbi->s_ndevs; devi++) { + if (FDEV(devi).start_blk != ei.blk || + FDEV(devi).end_blk != ei.blk + ei.len) + continue; + + if (devi == 0) { + f2fs_warn(sbi, + "%s: inode (ino=%lx) is an alias of meta device", + __func__, inode->i_ino); + return false; + } + + if (bdev_is_zoned(FDEV(devi).bdev)) { + f2fs_warn(sbi, + "%s: device alias inode (ino=%lx)'s extent info " + "[%u, %u, %u] maps to zoned block device", + __func__, inode->i_ino, ei.blk, ei.fofs, ei.len); + return false; + } + return true; + } + + f2fs_warn(sbi, "%s: device alias inode (ino=%lx)'s extent info " + "[%u, %u, %u] is inconsistent w/ any devices", + __func__, inode->i_ino, ei.blk, ei.fofs, ei.len); + return false; } static void __set_extent_info(struct extent_info *ei, -- 2.40.1 ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
Re: [f2fs-dev] [PATCH v2] f2fs: introduce device aliasing file
On 2024/9/23 23:53, Daeho Jeong wrote: From: Daeho Jeong F2FS should understand how the device aliasing file works and support deleting the file after use. A device aliasing file can be created by mkfs.f2fs tool and it can map the whole device with an extrent, not using node blocks. The file space should be pinned and normally used for read-only usages. Signed-off-by: Daeho Jeong --- v2: changed the position of f2fs_destroy_extent_tree() only for device aliasing files --- fs/f2fs/data.c | 5 + fs/f2fs/extent_cache.c | 10 ++ fs/f2fs/f2fs.h | 5 + fs/f2fs/file.c | 36 fs/f2fs/inode.c| 12 +++- fs/f2fs/sysfs.c| 2 ++ 6 files changed, 65 insertions(+), 5 deletions(-) diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index b94cf6eea2f9..385b46e62ede 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -3441,6 +3441,11 @@ static int prepare_write_begin(struct f2fs_sb_info *sbi, if (!f2fs_lookup_read_extent_cache_block(inode, index, &dn.data_blkaddr)) { + if (IS_DEVICE_ALIASING(inode)) { + err = -ENODATA; + goto out; + } + if (locked) { err = f2fs_reserve_block(&dn, index); goto out; diff --git a/fs/f2fs/extent_cache.c b/fs/f2fs/extent_cache.c index 62ac440d9416..0c8a705faa8b 100644 --- a/fs/f2fs/extent_cache.c +++ b/fs/f2fs/extent_cache.c @@ -401,6 +401,11 @@ void f2fs_init_read_extent_tree(struct inode *inode, struct page *ipage) if (atomic_read(&et->node_cnt) || !ei.len) goto skip; + if (IS_DEVICE_ALIASING(inode)) { + et->largest = ei; + goto skip; + } device alias feature replies on extent cache mount option, right? do we need to check noextent_cache option during parse_options()? Thanks, + en = __attach_extent_node(sbi, et, &ei, NULL, &et->root.rb_root.rb_node, true); if (en) { @@ -463,6 +468,11 @@ static bool __lookup_extent_tree(struct inode *inode, pgoff_t pgofs, goto out; } + if (IS_DEVICE_ALIASING(inode)) { + ret = false; + goto out; + } + en = __lookup_extent_node(&et->root, et->cached_en, pgofs); if (!en) goto out; diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 33f5449dc22d..b6ba22a1da47 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -213,6 +213,7 @@ struct f2fs_mount_info { #define F2FS_FEATURE_CASEFOLD 0x1000 #define F2FS_FEATURE_COMPRESSION 0x2000 #define F2FS_FEATURE_RO 0x4000 +#define F2FS_FEATURE_DEVICE_ALIAS 0x8000 #define __F2FS_HAS_FEATURE(raw_super, mask)\ ((raw_super->feature & cpu_to_le32(mask)) != 0) @@ -3046,6 +3047,7 @@ static inline void f2fs_change_bit(unsigned int nr, char *addr) #define F2FS_DIRSYNC_FL 0x0001 /* dirsync behaviour (directories only) */ #define F2FS_PROJINHERIT_FL 0x2000 /* Create with parents projid */ #define F2FS_CASEFOLD_FL 0x4000 /* Casefolded file */ +#define F2FS_DEVICE_ALIAS_FL 0x8000 /* File for aliasing a device */ #define F2FS_QUOTA_DEFAULT_FL (F2FS_NOATIME_FL | F2FS_IMMUTABLE_FL) @@ -3061,6 +3063,8 @@ static inline void f2fs_change_bit(unsigned int nr, char *addr) /* Flags that are appropriate for non-directories/regular files. */ #define F2FS_OTHER_FLMASK (F2FS_NODUMP_FL | F2FS_NOATIME_FL) +#define IS_DEVICE_ALIASING(inode) (F2FS_I(inode)->i_flags & F2FS_DEVICE_ALIAS_FL) + static inline __u32 f2fs_mask_flags(umode_t mode, __u32 flags) { if (S_ISDIR(mode)) @@ -4510,6 +4514,7 @@ F2FS_FEATURE_FUNCS(sb_chksum, SB_CHKSUM); F2FS_FEATURE_FUNCS(casefold, CASEFOLD); F2FS_FEATURE_FUNCS(compression, COMPRESSION); F2FS_FEATURE_FUNCS(readonly, RO); +F2FS_FEATURE_FUNCS(device_alias, DEVICE_ALIAS); #ifdef CONFIG_BLK_DEV_ZONED static inline bool f2fs_blkz_is_seq(struct f2fs_sb_info *sbi, int devi, diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 99903eafa7fe..f2d2d84d025b 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -725,6 +725,11 @@ int f2fs_do_truncate_blocks(struct inode *inode, u64 from, bool lock) trace_f2fs_truncate_blocks_enter(inode, from); + if (IS_DEVICE_ALIASING(inode) && from) { + err = -EINVAL; + goto out_err; + } + free_from = (pgoff_t)F2FS_BLK_ALIGN(from); if (free_from >= max_file_blocks(inode)) @@ -739,6 +744,21 @@ int f2fs_do_truncate_blocks(struct inode *inode, u64 from, bool lock) goto out; } + if (IS_DEVICE_ALIASING(inode)) { + struct extent_tree *et = F2FS_I(inode)->extent_tree[EX_R
Re: [f2fs-dev] [PATCH] f2fs: introduce device aliasing file
On 2024/9/23 23:14, Jaegeuk Kim wrote: On 09/23, Chao Yu wrote: On 2024/9/20 23:38, Daeho Jeong wrote: On Thu, Sep 19, 2024 at 6:14 AM Chao Yu wrote: On 2024/9/14 5:28, Daeho Jeong wrote: From: Daeho Jeong F2FS should understand how the device aliasing file works and support deleting the file after use. A device aliasing file can be created by mkfs.f2fs tool and it can map the whole device with an extrent, not using node blocks. The file space should be pinned and normally used for read-only usages. Signed-off-by: Daeho Jeong --- fs/f2fs/data.c | 5 + fs/f2fs/extent_cache.c | 10 ++ fs/f2fs/f2fs.h | 5 + fs/f2fs/file.c | 36 fs/f2fs/inode.c| 10 -- fs/f2fs/sysfs.c| 2 ++ 6 files changed, 62 insertions(+), 6 deletions(-) diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 6457e5bca9c9..9ce92093ba1e 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -3423,6 +3423,11 @@ static int prepare_write_begin(struct f2fs_sb_info *sbi, if (!f2fs_lookup_read_extent_cache_block(inode, index, &dn.data_blkaddr)) { + if (IS_DEVICE_ALIASING(inode)) { + err = -ENODATA; + goto out; + } + if (locked) { err = f2fs_reserve_block(&dn, index); goto out; diff --git a/fs/f2fs/extent_cache.c b/fs/f2fs/extent_cache.c index fd1fc06359ee..03883963b991 100644 --- a/fs/f2fs/extent_cache.c +++ b/fs/f2fs/extent_cache.c @@ -401,6 +401,11 @@ void f2fs_init_read_extent_tree(struct inode *inode, struct page *ipage) if (atomic_read(&et->node_cnt) || !ei.len) goto skip; + if (IS_DEVICE_ALIASING(inode)) { + et->largest = ei; + goto skip; + } + en = __attach_extent_node(sbi, et, &ei, NULL, &et->root.rb_root.rb_node, true); if (en) { @@ -463,6 +468,11 @@ static bool __lookup_extent_tree(struct inode *inode, pgoff_t pgofs, goto out; } + if (IS_DEVICE_ALIASING(inode)) { + ret = false; + goto out; + } + en = __lookup_extent_node(&et->root, et->cached_en, pgofs); if (!en) goto out; diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index ac19c61f0c3e..59179b9b3a83 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -208,6 +208,7 @@ struct f2fs_mount_info { #define F2FS_FEATURE_CASEFOLD 0x1000 #define F2FS_FEATURE_COMPRESSION0x2000 #define F2FS_FEATURE_RO 0x4000 +#define F2FS_FEATURE_DEVICE_ALIAS0x8000 #define __F2FS_HAS_FEATURE(raw_super, mask) \ ((raw_super->feature & cpu_to_le32(mask)) != 0) @@ -3001,6 +3002,7 @@ static inline void f2fs_change_bit(unsigned int nr, char *addr) #define F2FS_DIRSYNC_FL 0x0001 /* dirsync behaviour (directories only) */ #define F2FS_PROJINHERIT_FL 0x2000 /* Create with parents projid */ #define F2FS_CASEFOLD_FL0x4000 /* Casefolded file */ +#define F2FS_DEVICE_ALIAS_FL 0x8000 /* File for aliasing a device */ #define F2FS_QUOTA_DEFAULT_FL (F2FS_NOATIME_FL | F2FS_IMMUTABLE_FL) @@ -3016,6 +3018,8 @@ static inline void f2fs_change_bit(unsigned int nr, char *addr) /* Flags that are appropriate for non-directories/regular files. */ #define F2FS_OTHER_FLMASK (F2FS_NODUMP_FL | F2FS_NOATIME_FL) +#define IS_DEVICE_ALIASING(inode)(F2FS_I(inode)->i_flags & F2FS_DEVICE_ALIAS_FL) + static inline __u32 f2fs_mask_flags(umode_t mode, __u32 flags) { if (S_ISDIR(mode)) @@ -4478,6 +4482,7 @@ F2FS_FEATURE_FUNCS(sb_chksum, SB_CHKSUM); F2FS_FEATURE_FUNCS(casefold, CASEFOLD); F2FS_FEATURE_FUNCS(compression, COMPRESSION); F2FS_FEATURE_FUNCS(readonly, RO); +F2FS_FEATURE_FUNCS(device_alias, DEVICE_ALIAS); #ifdef CONFIG_BLK_DEV_ZONED static inline bool f2fs_blkz_is_seq(struct f2fs_sb_info *sbi, int devi, diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 168f08507004..0f4af6b303ff 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -727,6 +727,11 @@ int f2fs_do_truncate_blocks(struct inode *inode, u64 from, bool lock) trace_f2fs_truncate_blocks_enter(inode, from); + if (IS_DEVICE_ALIASING(inode) && from) { + err = -EINVAL; + goto out_err; + } + free_from = (pgoff_t)F2FS_BLK_ALIGN(from); if (free_from >= max_file_blocks(inode)) @@ -741,6 +746,21 @@ int f2fs_do_truncate_blocks(struct inode *inode, u64 from, bool lock) goto out; } + if (IS_DEVICE_ALIASING(inode)) { + struct extent_tree *et = F2FS_
Re: [f2fs-dev] [PATCH] f2fs: introduce device aliasing file
On 2024/9/20 23:38, Daeho Jeong wrote: On Thu, Sep 19, 2024 at 6:14 AM Chao Yu wrote: On 2024/9/14 5:28, Daeho Jeong wrote: From: Daeho Jeong F2FS should understand how the device aliasing file works and support deleting the file after use. A device aliasing file can be created by mkfs.f2fs tool and it can map the whole device with an extrent, not using node blocks. The file space should be pinned and normally used for read-only usages. Signed-off-by: Daeho Jeong --- fs/f2fs/data.c | 5 + fs/f2fs/extent_cache.c | 10 ++ fs/f2fs/f2fs.h | 5 + fs/f2fs/file.c | 36 fs/f2fs/inode.c| 10 -- fs/f2fs/sysfs.c| 2 ++ 6 files changed, 62 insertions(+), 6 deletions(-) diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 6457e5bca9c9..9ce92093ba1e 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -3423,6 +3423,11 @@ static int prepare_write_begin(struct f2fs_sb_info *sbi, if (!f2fs_lookup_read_extent_cache_block(inode, index, &dn.data_blkaddr)) { + if (IS_DEVICE_ALIASING(inode)) { + err = -ENODATA; + goto out; + } + if (locked) { err = f2fs_reserve_block(&dn, index); goto out; diff --git a/fs/f2fs/extent_cache.c b/fs/f2fs/extent_cache.c index fd1fc06359ee..03883963b991 100644 --- a/fs/f2fs/extent_cache.c +++ b/fs/f2fs/extent_cache.c @@ -401,6 +401,11 @@ void f2fs_init_read_extent_tree(struct inode *inode, struct page *ipage) if (atomic_read(&et->node_cnt) || !ei.len) goto skip; + if (IS_DEVICE_ALIASING(inode)) { + et->largest = ei; + goto skip; + } + en = __attach_extent_node(sbi, et, &ei, NULL, &et->root.rb_root.rb_node, true); if (en) { @@ -463,6 +468,11 @@ static bool __lookup_extent_tree(struct inode *inode, pgoff_t pgofs, goto out; } + if (IS_DEVICE_ALIASING(inode)) { + ret = false; + goto out; + } + en = __lookup_extent_node(&et->root, et->cached_en, pgofs); if (!en) goto out; diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index ac19c61f0c3e..59179b9b3a83 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -208,6 +208,7 @@ struct f2fs_mount_info { #define F2FS_FEATURE_CASEFOLD 0x1000 #define F2FS_FEATURE_COMPRESSION0x2000 #define F2FS_FEATURE_RO 0x4000 +#define F2FS_FEATURE_DEVICE_ALIAS0x8000 #define __F2FS_HAS_FEATURE(raw_super, mask) \ ((raw_super->feature & cpu_to_le32(mask)) != 0) @@ -3001,6 +3002,7 @@ static inline void f2fs_change_bit(unsigned int nr, char *addr) #define F2FS_DIRSYNC_FL 0x0001 /* dirsync behaviour (directories only) */ #define F2FS_PROJINHERIT_FL 0x2000 /* Create with parents projid */ #define F2FS_CASEFOLD_FL0x4000 /* Casefolded file */ +#define F2FS_DEVICE_ALIAS_FL 0x8000 /* File for aliasing a device */ #define F2FS_QUOTA_DEFAULT_FL (F2FS_NOATIME_FL | F2FS_IMMUTABLE_FL) @@ -3016,6 +3018,8 @@ static inline void f2fs_change_bit(unsigned int nr, char *addr) /* Flags that are appropriate for non-directories/regular files. */ #define F2FS_OTHER_FLMASK (F2FS_NODUMP_FL | F2FS_NOATIME_FL) +#define IS_DEVICE_ALIASING(inode)(F2FS_I(inode)->i_flags & F2FS_DEVICE_ALIAS_FL) + static inline __u32 f2fs_mask_flags(umode_t mode, __u32 flags) { if (S_ISDIR(mode)) @@ -4478,6 +4482,7 @@ F2FS_FEATURE_FUNCS(sb_chksum, SB_CHKSUM); F2FS_FEATURE_FUNCS(casefold, CASEFOLD); F2FS_FEATURE_FUNCS(compression, COMPRESSION); F2FS_FEATURE_FUNCS(readonly, RO); +F2FS_FEATURE_FUNCS(device_alias, DEVICE_ALIAS); #ifdef CONFIG_BLK_DEV_ZONED static inline bool f2fs_blkz_is_seq(struct f2fs_sb_info *sbi, int devi, diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 168f08507004..0f4af6b303ff 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -727,6 +727,11 @@ int f2fs_do_truncate_blocks(struct inode *inode, u64 from, bool lock) trace_f2fs_truncate_blocks_enter(inode, from); + if (IS_DEVICE_ALIASING(inode) && from) { + err = -EINVAL; + goto out_err; + } + free_from = (pgoff_t)F2FS_BLK_ALIGN(from); if (free_from >= max_file_blocks(inode)) @@ -741,6 +746,21 @@ int f2fs_do_truncate_blocks(struct inode *inode, u64 from, bool lock) goto out; } + if (IS_DEVICE_ALIASING(inode)) { + struct extent_tree *et = F2FS_I(inode)->extent_tree[EX_READ]; + struct extent_info ei = et->largest; +
Re: [f2fs-dev] [PATCH] f2fs: introduce device aliasing file
On 2024/9/14 5:28, Daeho Jeong wrote: From: Daeho Jeong F2FS should understand how the device aliasing file works and support deleting the file after use. A device aliasing file can be created by mkfs.f2fs tool and it can map the whole device with an extrent, not using node blocks. The file space should be pinned and normally used for read-only usages. Signed-off-by: Daeho Jeong --- fs/f2fs/data.c | 5 + fs/f2fs/extent_cache.c | 10 ++ fs/f2fs/f2fs.h | 5 + fs/f2fs/file.c | 36 fs/f2fs/inode.c| 10 -- fs/f2fs/sysfs.c| 2 ++ 6 files changed, 62 insertions(+), 6 deletions(-) diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 6457e5bca9c9..9ce92093ba1e 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -3423,6 +3423,11 @@ static int prepare_write_begin(struct f2fs_sb_info *sbi, if (!f2fs_lookup_read_extent_cache_block(inode, index, &dn.data_blkaddr)) { + if (IS_DEVICE_ALIASING(inode)) { + err = -ENODATA; + goto out; + } + if (locked) { err = f2fs_reserve_block(&dn, index); goto out; diff --git a/fs/f2fs/extent_cache.c b/fs/f2fs/extent_cache.c index fd1fc06359ee..03883963b991 100644 --- a/fs/f2fs/extent_cache.c +++ b/fs/f2fs/extent_cache.c @@ -401,6 +401,11 @@ void f2fs_init_read_extent_tree(struct inode *inode, struct page *ipage) if (atomic_read(&et->node_cnt) || !ei.len) goto skip; + if (IS_DEVICE_ALIASING(inode)) { + et->largest = ei; + goto skip; + } + en = __attach_extent_node(sbi, et, &ei, NULL, &et->root.rb_root.rb_node, true); if (en) { @@ -463,6 +468,11 @@ static bool __lookup_extent_tree(struct inode *inode, pgoff_t pgofs, goto out; } + if (IS_DEVICE_ALIASING(inode)) { + ret = false; + goto out; + } + en = __lookup_extent_node(&et->root, et->cached_en, pgofs); if (!en) goto out; diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index ac19c61f0c3e..59179b9b3a83 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -208,6 +208,7 @@ struct f2fs_mount_info { #define F2FS_FEATURE_CASEFOLD 0x1000 #define F2FS_FEATURE_COMPRESSION 0x2000 #define F2FS_FEATURE_RO 0x4000 +#define F2FS_FEATURE_DEVICE_ALIAS 0x8000 #define __F2FS_HAS_FEATURE(raw_super, mask)\ ((raw_super->feature & cpu_to_le32(mask)) != 0) @@ -3001,6 +3002,7 @@ static inline void f2fs_change_bit(unsigned int nr, char *addr) #define F2FS_DIRSYNC_FL 0x0001 /* dirsync behaviour (directories only) */ #define F2FS_PROJINHERIT_FL 0x2000 /* Create with parents projid */ #define F2FS_CASEFOLD_FL 0x4000 /* Casefolded file */ +#define F2FS_DEVICE_ALIAS_FL 0x8000 /* File for aliasing a device */ #define F2FS_QUOTA_DEFAULT_FL (F2FS_NOATIME_FL | F2FS_IMMUTABLE_FL) @@ -3016,6 +3018,8 @@ static inline void f2fs_change_bit(unsigned int nr, char *addr) /* Flags that are appropriate for non-directories/regular files. */ #define F2FS_OTHER_FLMASK (F2FS_NODUMP_FL | F2FS_NOATIME_FL) +#define IS_DEVICE_ALIASING(inode) (F2FS_I(inode)->i_flags & F2FS_DEVICE_ALIAS_FL) + static inline __u32 f2fs_mask_flags(umode_t mode, __u32 flags) { if (S_ISDIR(mode)) @@ -4478,6 +4482,7 @@ F2FS_FEATURE_FUNCS(sb_chksum, SB_CHKSUM); F2FS_FEATURE_FUNCS(casefold, CASEFOLD); F2FS_FEATURE_FUNCS(compression, COMPRESSION); F2FS_FEATURE_FUNCS(readonly, RO); +F2FS_FEATURE_FUNCS(device_alias, DEVICE_ALIAS); #ifdef CONFIG_BLK_DEV_ZONED static inline bool f2fs_blkz_is_seq(struct f2fs_sb_info *sbi, int devi, diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 168f08507004..0f4af6b303ff 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -727,6 +727,11 @@ int f2fs_do_truncate_blocks(struct inode *inode, u64 from, bool lock) trace_f2fs_truncate_blocks_enter(inode, from); + if (IS_DEVICE_ALIASING(inode) && from) { + err = -EINVAL; + goto out_err; + } + free_from = (pgoff_t)F2FS_BLK_ALIGN(from); if (free_from >= max_file_blocks(inode)) @@ -741,6 +746,21 @@ int f2fs_do_truncate_blocks(struct inode *inode, u64 from, bool lock) goto out; } + if (IS_DEVICE_ALIASING(inode)) { + struct extent_tree *et = F2FS_I(inode)->extent_tree[EX_READ]; + struct extent_info ei = et->largest; + unsigned int i; + + for (i = 0; i < ei.len; i++) + f2fs_invalidate_blocks(sbi, ei.blk + i); + + dec_valid_block_count(
Re: [f2fs-dev] [PATCH v2 2/2] mkfs.f2fs: add device aliasing feature
On 2024/9/17 3:20, Daeho Jeong wrote: From: Daeho Jeong We can add a device aliasing file which can map the whole device with an extent, not using node blocks. This mapped area should be pinned and normally used for read-only usages. After finished using it, we can deallocate the whole area and return it back to use it for other files. Signed-off-by: Daeho Jeong --- v2: removed unnecessary define and renamed IS_ALIASING() --- fsck/dump.c | 13 ++ fsck/fsck.c | 49 -- fsck/fsck.h | 4 +- fsck/main.c | 5 + include/f2fs_fs.h | 7 + mkfs/f2fs_format.c | 335 mkfs/f2fs_format_main.c | 30 +++- 7 files changed, 359 insertions(+), 84 deletions(-) diff --git a/fsck/dump.c b/fsck/dump.c index 448c0ef..bd4c7bd 100644 --- a/fsck/dump.c +++ b/fsck/dump.c @@ -527,6 +527,19 @@ static int dump_inode_blk(struct f2fs_sb_info *sbi, u32 nid, } c.show_file_map_max_offset = f2fs_max_file_offset(&node_blk->i); + + if (IS_DEVICE_ALIASING(&node_blk->i)) { + u32 blkaddr = le32_to_cpu(node_blk->i.i_ext.blk_addr); + u32 len = le32_to_cpu(node_blk->i.i_ext.len); + u32 idx; + + for (idx = 0; idx < len; idx++) + dump_data_blk(sbi, idx * F2FS_BLKSIZE, blkaddr++, false); Use type instead of false? + print_extent(true); + + goto dump_xattr; + } + addr_per_block = ADDRS_PER_BLOCK(&node_blk->i); /* check data blocks in inode */ diff --git a/fsck/fsck.c b/fsck/fsck.c index a18bee9..c9b0f36 100644 --- a/fsck/fsck.c +++ b/fsck/fsck.c @@ -902,6 +902,7 @@ void fsck_chk_inode_blk(struct f2fs_sb_info *sbi, u32 nid, int need_fix = 0; int ret; u32 cluster_size = 1 << node_blk->i.i_log_cluster_size; + bool is_aliasing = IS_DEVICE_ALIASING(&node_blk->i); if (!compressed) goto check_next; @@ -1132,6 +1133,33 @@ check_next: addrs_per_blk * NIDS_PER_BLOCK * NIDS_PER_BLOCK) * F2FS_BLKSIZE; } + + if (is_aliasing) { + struct extent_info ei; + + get_extent_info(&ei, &node_blk->i.i_ext); + for (idx = 0; idx < ei.len; idx++, child.pgofs++) { + block_t blkaddr = ei.blk + idx; + + /* check extent info */ + check_extent_info(&child, blkaddr, 0); + ret = fsck_chk_data_blk(sbi, &node_blk->i, blkaddr, + &child, (i_blocks == *blk_cnt), ftype, nid, + idx, ni->version, node_blk); + if (!ret) { + *blk_cnt = *blk_cnt + 1; + if (cur_qtype != -1) + qf_last_blkofs[cur_qtype] = child.pgofs; + } else if (c.fix_on) { + node_blk->i.i_ext.len = cpu_to_le32(idx); + need_fix = 1; + break; + } + } + + goto check; + } + for (idx = 0; idx < addrs; idx++, child.pgofs++) { block_t blkaddr = le32_to_cpu(node_blk->i.i_addr[ofs + idx]); @@ -1164,11 +1192,11 @@ check_next: child.pgofs - cbc->cheader_pgofs < cluster_size) cbc->cnt++; ret = fsck_chk_data_blk(sbi, - IS_CASEFOLDED(&node_blk->i), + &node_blk->i, blkaddr, &child, (i_blocks == *blk_cnt), ftype, nid, idx, ni->version, - file_is_encrypt(&node_blk->i), node_blk); + node_blk); if (blkaddr != le32_to_cpu(node_blk->i.i_addr[ofs + idx])) need_fix = 1; if (!ret) { @@ -1362,7 +1390,7 @@ skip_blkcnt_fix: } /* drop extent information to avoid potential wrong access */ - if (need_fix && f2fs_dev_is_writable()) + if (need_fix && f2fs_dev_is_writable() && !is_aliasing) node_blk->i.i_ext.len = 0; if ((c.feature & F2FS_FEATURE_INODE_CHKSUM) && @@ -1436,11 +1464,9 @@ int fsck_chk_dnode_blk(struct f2fs_sb_info *sbi, struct f2fs_inode *inode, if (!compr_rel && blkaddr == NEW_ADDR && child->pgofs - cbc->cheader_pgofs < cluster_size) cbc->cnt++; - ret = fsck_chk_data_blk(sbi, IS_CASEFOLDED(inode), - blkaddr, child, + ret = fsck_chk_data_blk(sbi, inode, blkaddr, child, le64_to_cpu(inode->i_blocks) == *blk_cnt, fty
Re: [f2fs-dev] [PATCH v2 2/2] f2fs: introduce get_section_mtime
On 2024/9/19 10:23, Zhiguo Niu wrote: Chao Yu via Linux-f2fs-devel 于2024年9月18日周三 14:45写道: On 2024/9/12 14:40, liuder...@oppo.com wrote: From: liuderong When segs_per_sec is larger than 1, section may contain free segments, mtime should be the mean value of each valid segments, so introduce get_section_mtime to exclude free segments in a section. Signed-off-by: liuderong --- fs/f2fs/f2fs.h| 2 ++ fs/f2fs/gc.c | 15 ++- fs/f2fs/segment.c | 41 - 3 files changed, 40 insertions(+), 18 deletions(-) diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 4dcdcdd..d6adf0f 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -3762,6 +3762,8 @@ enum rw_hint f2fs_io_type_to_rw_hint(struct f2fs_sb_info *sbi, unsigned int f2fs_usable_segs_in_sec(struct f2fs_sb_info *sbi); unsigned int f2fs_usable_blks_in_seg(struct f2fs_sb_info *sbi, unsigned int segno); +unsigned long long get_section_mtime(struct f2fs_sb_info *sbi, + unsigned int segno); Hi Derong, It needs to add "f2fs_" prefix for get_section_mtime() to avoid global namespace pollution. #define DEF_FRAGMENT_SIZE 4 #define MIN_FRAGMENT_SIZE 1 diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index 6299639..03c6117 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c @@ -332,20 +332,14 @@ static unsigned int check_bg_victims(struct f2fs_sb_info *sbi) static unsigned int get_cb_cost(struct f2fs_sb_info *sbi, unsigned int segno) { struct sit_info *sit_i = SIT_I(sbi); - unsigned int secno = GET_SEC_FROM_SEG(sbi, segno); - unsigned int start = GET_SEG_FROM_SEC(sbi, secno); unsigned long long mtime = 0; unsigned int vblocks; unsigned char age = 0; unsigned char u; - unsigned int i; unsigned int usable_segs_per_sec = f2fs_usable_segs_in_sec(sbi); - for (i = 0; i < usable_segs_per_sec; i++) - mtime += get_seg_entry(sbi, start + i)->mtime; + mtime = get_section_mtime(sbi, segno); vblocks = get_valid_blocks(sbi, segno, true); - - mtime = div_u64(mtime, usable_segs_per_sec); vblocks = div_u64(vblocks, usable_segs_per_sec); u = BLKS_TO_SEGS(sbi, vblocks * 100); @@ -485,10 +479,7 @@ static void add_victim_entry(struct f2fs_sb_info *sbi, struct victim_sel_policy *p, unsigned int segno) { struct sit_info *sit_i = SIT_I(sbi); - unsigned int secno = GET_SEC_FROM_SEG(sbi, segno); - unsigned int start = GET_SEG_FROM_SEC(sbi, secno); unsigned long long mtime = 0; - unsigned int i; if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) { if (p->gc_mode == GC_AT && @@ -496,9 +487,7 @@ static void add_victim_entry(struct f2fs_sb_info *sbi, return; } - for (i = 0; i < SEGS_PER_SEC(sbi); i++) - mtime += get_seg_entry(sbi, start + i)->mtime; - mtime = div_u64(mtime, SEGS_PER_SEC(sbi)); + mtime = get_section_mtime(sbi, segno); /* Handle if the system time has changed by the user */ if (mtime < sit_i->min_mtime) diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index 6627394..e62e722 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -5389,6 +5389,41 @@ unsigned int f2fs_usable_segs_in_sec(struct f2fs_sb_info *sbi) return SEGS_PER_SEC(sbi); } +unsigned long long get_section_mtime(struct f2fs_sb_info *sbi, + unsigned int segno) +{ + unsigned int usable_segs_per_sec = f2fs_usable_segs_in_sec(sbi); + unsigned int secno = 0, start = 0; + struct free_segmap_info *free_i = FREE_I(sbi); + unsigned int valid_seg_count = 0; + unsigned long long mtime = 0; + unsigned int i = 0; + + if (segno == NULL_SEGNO) + return 0; No needed. + + secno = GET_SEC_FROM_SEG(sbi, segno); + start = GET_SEG_FROM_SEC(sbi, secno); + + if (!__is_large_section(sbi)) + return get_seg_entry(sbi, start + i)->mtime; + + for (i = 0; i < usable_segs_per_sec; i++) { + /* for large section, only check the mtime of valid segments */ + spin_lock(&free_i->segmap_lock); + if (test_bit(start + i, free_i->free_segmap)) { + mtime += get_seg_entry(sbi, start + i)->mtime; + valid_seg_count++; + } + spin_unlock(&free_i->segmap_lock); + } After commit 6f3a01ae9b72 ("f2fs: record average update time of segment"), mtime of segment starts to indicate average update time of segment. So it needs to change like this? for (i = 0; i < usable_segs_per_sec; i++) { struct seg_entry *se = get_seg_entry(sbi, start + i); mtime += se->mtime * se->valid_blocks; total_valid_blocks += se->valid_blocks; } hi Chao, after I read this patch from Derong and base on your thi
Re: [f2fs-dev] [PATCH v3 2/2] f2fs: introduce f2fs_get_section_mtime
On 2024/9/18 18:06, liuder...@oppo.com wrote: From: liuderong When segs_per_sec is larger than 1, section may contain invalid segments, mtime should be the average value of each valid blocks, so introduce f2fs_get_section_mtime to record the average mtime of all valid blocks in a section. Signed-off-by: liuderong Reviewed-by: Chao Yu Thanks, ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
Re: [f2fs-dev] [PATCH v2 1/2] mkfs.f2fs: change -c option description
On 2024/9/17 3:20, Daeho Jeong wrote: From: Daeho Jeong Current description confuses users like they can add addtional devices with one -c option using commas(,) at the same time. Signed-off-by: Daeho Jeong Reviewed-by: Chao Yu Thanks, ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
Re: [f2fs-dev] [PATCH] f2fs: allow F2FS_IPU_NOCACHE for pinned file
On 2024/9/15 11:22, Jaegeuk Kim via Linux-f2fs-devel wrote: This patch allows f2fs to submit bios of in-place writes on pinned file. Signed-off-by: Jaegeuk Kim Reviewed-by: Chao Yu Thanks, ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
Re: [f2fs-dev] [PATCH v2 2/2] f2fs: introduce get_section_mtime
On 2024/9/12 14:40, liuder...@oppo.com wrote: From: liuderong When segs_per_sec is larger than 1, section may contain free segments, mtime should be the mean value of each valid segments, so introduce get_section_mtime to exclude free segments in a section. Signed-off-by: liuderong --- fs/f2fs/f2fs.h| 2 ++ fs/f2fs/gc.c | 15 ++- fs/f2fs/segment.c | 41 - 3 files changed, 40 insertions(+), 18 deletions(-) diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 4dcdcdd..d6adf0f 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -3762,6 +3762,8 @@ enum rw_hint f2fs_io_type_to_rw_hint(struct f2fs_sb_info *sbi, unsigned int f2fs_usable_segs_in_sec(struct f2fs_sb_info *sbi); unsigned int f2fs_usable_blks_in_seg(struct f2fs_sb_info *sbi, unsigned int segno); +unsigned long long get_section_mtime(struct f2fs_sb_info *sbi, + unsigned int segno); Hi Derong, It needs to add "f2fs_" prefix for get_section_mtime() to avoid global namespace pollution. #define DEF_FRAGMENT_SIZE 4 #define MIN_FRAGMENT_SIZE 1 diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index 6299639..03c6117 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c @@ -332,20 +332,14 @@ static unsigned int check_bg_victims(struct f2fs_sb_info *sbi) static unsigned int get_cb_cost(struct f2fs_sb_info *sbi, unsigned int segno) { struct sit_info *sit_i = SIT_I(sbi); - unsigned int secno = GET_SEC_FROM_SEG(sbi, segno); - unsigned int start = GET_SEG_FROM_SEC(sbi, secno); unsigned long long mtime = 0; unsigned int vblocks; unsigned char age = 0; unsigned char u; - unsigned int i; unsigned int usable_segs_per_sec = f2fs_usable_segs_in_sec(sbi); - for (i = 0; i < usable_segs_per_sec; i++) - mtime += get_seg_entry(sbi, start + i)->mtime; + mtime = get_section_mtime(sbi, segno); vblocks = get_valid_blocks(sbi, segno, true); - - mtime = div_u64(mtime, usable_segs_per_sec); vblocks = div_u64(vblocks, usable_segs_per_sec); u = BLKS_TO_SEGS(sbi, vblocks * 100); @@ -485,10 +479,7 @@ static void add_victim_entry(struct f2fs_sb_info *sbi, struct victim_sel_policy *p, unsigned int segno) { struct sit_info *sit_i = SIT_I(sbi); - unsigned int secno = GET_SEC_FROM_SEG(sbi, segno); - unsigned int start = GET_SEG_FROM_SEC(sbi, secno); unsigned long long mtime = 0; - unsigned int i; if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) { if (p->gc_mode == GC_AT && @@ -496,9 +487,7 @@ static void add_victim_entry(struct f2fs_sb_info *sbi, return; } - for (i = 0; i < SEGS_PER_SEC(sbi); i++) - mtime += get_seg_entry(sbi, start + i)->mtime; - mtime = div_u64(mtime, SEGS_PER_SEC(sbi)); + mtime = get_section_mtime(sbi, segno); /* Handle if the system time has changed by the user */ if (mtime < sit_i->min_mtime) diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index 6627394..e62e722 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -5389,6 +5389,41 @@ unsigned int f2fs_usable_segs_in_sec(struct f2fs_sb_info *sbi) return SEGS_PER_SEC(sbi); } +unsigned long long get_section_mtime(struct f2fs_sb_info *sbi, + unsigned int segno) +{ + unsigned int usable_segs_per_sec = f2fs_usable_segs_in_sec(sbi); + unsigned int secno = 0, start = 0; + struct free_segmap_info *free_i = FREE_I(sbi); + unsigned int valid_seg_count = 0; + unsigned long long mtime = 0; + unsigned int i = 0; + + if (segno == NULL_SEGNO) + return 0; No needed. + + secno = GET_SEC_FROM_SEG(sbi, segno); + start = GET_SEG_FROM_SEC(sbi, secno); + + if (!__is_large_section(sbi)) + return get_seg_entry(sbi, start + i)->mtime; + + for (i = 0; i < usable_segs_per_sec; i++) { + /* for large section, only check the mtime of valid segments */ + spin_lock(&free_i->segmap_lock); + if (test_bit(start + i, free_i->free_segmap)) { + mtime += get_seg_entry(sbi, start + i)->mtime; + valid_seg_count++; + } + spin_unlock(&free_i->segmap_lock); + } After commit 6f3a01ae9b72 ("f2fs: record average update time of segment"), mtime of segment starts to indicate average update time of segment. So it needs to change like this? for (i = 0; i < usable_segs_per_sec; i++) { struct seg_entry *se = get_seg_entry(sbi, start + i); mtime += se->mtime * se->valid_blocks; total_valid_blocks += se->valid_blocks; } if (total_valid_blocks == 0) return 0; return div_u64(mtime, total_valid_blocks); Thanks, + + if (valid_seg_count == 0) + return 0; + + ret
Re: [f2fs-dev] [PATCH v5] f2fs: zone: don't block IO if there is remained open zone
Ping. On 2024/4/22 14:29, Chao Yu wrote: max open zone may be larger than log header number of f2fs, for such case, it doesn't need to wait last IO in previous zone, let's introduce available_open_zone semaphore, and reduce it once we submit first write IO in a zone, and increase it after completion of last IO in the zone. Cc: Daeho Jeong Signed-off-by: Chao Yu Reviewed-by: Daeho Jeong --- v5: - fix `openned` typo pointed out by Juhyung Park fs/f2fs/data.c| 105 ++ fs/f2fs/f2fs.h| 31 +++--- fs/f2fs/iostat.c | 7 fs/f2fs/iostat.h | 2 + fs/f2fs/segment.c | 37 +++- fs/f2fs/segment.h | 3 +- fs/f2fs/super.c | 2 + 7 files changed, 143 insertions(+), 44 deletions(-) diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index d01345af5f3e..657579358498 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -373,11 +373,10 @@ static void f2fs_write_end_io(struct bio *bio) #ifdef CONFIG_BLK_DEV_ZONED static void f2fs_zone_write_end_io(struct bio *bio) { - struct f2fs_bio_info *io = (struct f2fs_bio_info *)bio->bi_private; + struct f2fs_sb_info *sbi = iostat_get_bio_private(bio); - bio->bi_private = io->bi_private; - complete(&io->zone_wait); f2fs_write_end_io(bio); + up(&sbi->available_open_zones); } #endif @@ -533,6 +532,24 @@ static void __submit_merged_bio(struct f2fs_bio_info *io) if (!io->bio) return; +#ifdef CONFIG_BLK_DEV_ZONED + if (io->open_zone) { + /* +* if there is no open zone, it will wait for last IO in +* previous zone before submitting new IO. +*/ + down(&fio->sbi->available_open_zones); + io->open_zone = false; + io->zone_opened = true; + } + + if (io->close_zone) { + io->bio->bi_end_io = f2fs_zone_write_end_io; + io->zone_opened = false; + io->close_zone = false; + } +#endif + if (is_read_io(fio->op)) { trace_f2fs_prepare_read_bio(io->sbi->sb, fio->type, io->bio); f2fs_submit_read_bio(io->sbi, io->bio, fio->type); @@ -603,9 +620,9 @@ int f2fs_init_write_merge_io(struct f2fs_sb_info *sbi) INIT_LIST_HEAD(&sbi->write_io[i][j].bio_list); init_f2fs_rwsem(&sbi->write_io[i][j].bio_list_lock); #ifdef CONFIG_BLK_DEV_ZONED - init_completion(&sbi->write_io[i][j].zone_wait); - sbi->write_io[i][j].zone_pending_bio = NULL; - sbi->write_io[i][j].bi_private = NULL; + sbi->write_io[i][j].open_zone = false; + sbi->write_io[i][j].zone_opened = false; + sbi->write_io[i][j].close_zone = false; #endif } } @@ -636,6 +653,31 @@ static void __f2fs_submit_merged_write(struct f2fs_sb_info *sbi, f2fs_up_write(&io->io_rwsem); } +void f2fs_blkzoned_submit_merged_write(struct f2fs_sb_info *sbi, int type) +{ +#ifdef CONFIG_BLK_DEV_ZONED + struct f2fs_bio_info *io; + + if (!f2fs_sb_has_blkzoned(sbi)) + return; + + io = sbi->write_io[PAGE_TYPE(type)] + type_to_temp(type); + + f2fs_down_write(&io->io_rwsem); + if (io->zone_opened) { + if (io->bio) { + io->close_zone = true; + __submit_merged_bio(io); + } else { + up(&sbi->available_open_zones); + io->zone_opened = false; + } + } + f2fs_up_write(&io->io_rwsem); +#endif + +} + static void __submit_merged_write_cond(struct f2fs_sb_info *sbi, struct inode *inode, struct page *page, nid_t ino, enum page_type type, bool force) @@ -920,22 +962,16 @@ int f2fs_merge_page_bio(struct f2fs_io_info *fio) } #ifdef CONFIG_BLK_DEV_ZONED -static bool is_end_zone_blkaddr(struct f2fs_sb_info *sbi, block_t blkaddr) +static bool is_blkaddr_zone_boundary(struct f2fs_sb_info *sbi, + block_t blkaddr, bool start) { - int devi = 0; + if (!f2fs_blkaddr_in_seqzone(sbi, blkaddr)) + return false; + + if (start) + return (blkaddr % sbi->blocks_per_blkz) == 0; + return (blkaddr % sbi->blocks_per_blkz == sbi->blocks_per_blkz - 1); - if (f2fs_is_multi_device(sbi)) { - devi = f2fs_target_device_index(sbi, blkaddr); - if (blkaddr < FDEV(devi).start_blk || - blkaddr > FDEV(devi).end_blk) { - f2fs_err(sbi, &
Re: [f2fs-dev] [PATCH v2 1/2] f2fs: use per-log target_bitmap to improve lookup performace of ssr allocation
On 2024/5/31 9:10, Chao Yu wrote: On 2024/5/31 7:39, Jaegeuk Kim wrote: On 05/29, Chao Yu wrote: Ping, Jaegeuk, Chao, sorry, I might need some time to take a look at the change cautiously. No problem, I've done some tests on this patch, though, I will keeping this in my queue, and do test base on the queue whenever it comes new patches. Jaegeuk, Any progress on this patchset? Thanks, Thanks, On 2024/4/23 10:07, Chao Yu wrote: Jaegeuk, any comments for this serials? On 2024/4/11 16:23, Chao Yu wrote: After commit 899fee36fac0 ("f2fs: fix to avoid data corruption by forbidding SSR overwrite"), valid block bitmap of current openned segment is fixed, let's introduce a per-log bitmap instead of temp bitmap to avoid unnecessary calculation overhead whenever allocating free slot w/ SSR allocator. Signed-off-by: Chao Yu --- v2: - rebase to last dev-test branch. fs/f2fs/segment.c | 30 ++ fs/f2fs/segment.h | 1 + 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index 6474b7338e81..af716925db19 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -2840,31 +2840,39 @@ static int new_curseg(struct f2fs_sb_info *sbi, int type, bool new_sec) return 0; } -static int __next_free_blkoff(struct f2fs_sb_info *sbi, - int segno, block_t start) +static void __get_segment_bitmap(struct f2fs_sb_info *sbi, + unsigned long *target_map, + int segno) { struct seg_entry *se = get_seg_entry(sbi, segno); int entries = SIT_VBLOCK_MAP_SIZE / sizeof(unsigned long); - unsigned long *target_map = SIT_I(sbi)->tmp_map; unsigned long *ckpt_map = (unsigned long *)se->ckpt_valid_map; unsigned long *cur_map = (unsigned long *)se->cur_valid_map; int i; for (i = 0; i < entries; i++) target_map[i] = ckpt_map[i] | cur_map[i]; +} + +static int __next_free_blkoff(struct f2fs_sb_info *sbi, unsigned long *bitmap, + int segno, block_t start) +{ + __get_segment_bitmap(sbi, bitmap, segno); - return __find_rev_next_zero_bit(target_map, BLKS_PER_SEG(sbi), start); + return __find_rev_next_zero_bit(bitmap, BLKS_PER_SEG(sbi), start); } static int f2fs_find_next_ssr_block(struct f2fs_sb_info *sbi, - struct curseg_info *seg) + struct curseg_info *seg) { - return __next_free_blkoff(sbi, seg->segno, seg->next_blkoff + 1); + return __find_rev_next_zero_bit(seg->target_map, + BLKS_PER_SEG(sbi), seg->next_blkoff + 1); } bool f2fs_segment_has_free_slot(struct f2fs_sb_info *sbi, int segno) { - return __next_free_blkoff(sbi, segno, 0) < BLKS_PER_SEG(sbi); + return __next_free_blkoff(sbi, SIT_I(sbi)->tmp_map, segno, 0) < + BLKS_PER_SEG(sbi); } /* @@ -2890,7 +2898,8 @@ static int change_curseg(struct f2fs_sb_info *sbi, int type) reset_curseg(sbi, type, 1); curseg->alloc_type = SSR; - curseg->next_blkoff = __next_free_blkoff(sbi, curseg->segno, 0); + curseg->next_blkoff = __next_free_blkoff(sbi, curseg->target_map, + curseg->segno, 0); sum_page = f2fs_get_sum_page(sbi, new_segno); if (IS_ERR(sum_page)) { @@ -4635,6 +4644,10 @@ static int build_curseg(struct f2fs_sb_info *sbi) sizeof(struct f2fs_journal), GFP_KERNEL); if (!array[i].journal) return -ENOMEM; + array[i].target_map = f2fs_kzalloc(sbi, SIT_VBLOCK_MAP_SIZE, + GFP_KERNEL); + if (!array[i].target_map) + return -ENOMEM; if (i < NR_PERSISTENT_LOG) array[i].seg_type = CURSEG_HOT_DATA + i; else if (i == CURSEG_COLD_DATA_PINNED) @@ -5453,6 +5466,7 @@ static void destroy_curseg(struct f2fs_sb_info *sbi) for (i = 0; i < NR_CURSEG_TYPE; i++) { kfree(array[i].sum_blk); kfree(array[i].journal); + kfree(array[i].target_map); } kfree(array); } diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h index e1c0f418aa11..10f3e44f036f 100644 --- a/fs/f2fs/segment.h +++ b/fs/f2fs/segment.h @@ -292,6 +292,7 @@ struct curseg_info { struct f2fs_summary_block *sum_blk; /* cached summary block */ struct rw_semaphore journal_rwsem; /* protect journal area */ struct f2fs_journal *journal; /* cached journal info */ + unsigned long *target_map; /* bitmap for SSR allocator */ unsigned char alloc_type; /* current allocation type */ unsigned short seg_type; /* segment type like CURSEG_XXX_TYPE */ unsigned int segno; /* current segment number */ ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.
Re: [f2fs-dev] [linus:master] [f2fs] 5c8764f867: xfstests.generic.091.fail
On 2024/9/12 21:50, kernel test robot wrote: Hello, kernel test robot noticed "xfstests.generic.091.fail" on: commit: 5c8764f8679e659c5cb295af7d32279002d13735 ("f2fs: fix to force buffered IO on inline_data inode") https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git master Can you please try below fix for xfstests? https://lore.kernel.org/fstests/20240911035333.364961-1-c...@kernel.org/ Thanks, in testcase: xfstests version: xfstests-x86_64-b1465280-1_20240909 with following parameters: disk: 4HDD fs: f2fs test: generic-091 compiler: gcc-12 test machine: 8 threads Intel(R) Core(TM) i7-6700 CPU @ 3.40GHz (Skylake) with 28G memory (please refer to attached dmesg/kmsg for entire log/backtrace) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot | Closes: https://lore.kernel.org/oe-lkp/202409122131.d6e2f8c1-oliver.s...@intel.com 2024-09-11 03:13:26 export TEST_DIR=/fs/sda1 2024-09-11 03:13:26 export TEST_DEV=/dev/sda1 2024-09-11 03:13:26 export FSTYP=f2fs 2024-09-11 03:13:26 export SCRATCH_MNT=/fs/scratch 2024-09-11 03:13:26 mkdir /fs/scratch -p 2024-09-11 03:13:26 export SCRATCH_DEV=/dev/sda4 2024-09-11 03:13:26 export MKFS_OPTIONS="-f" 2024-09-11 03:13:27 echo generic/091 2024-09-11 03:13:27 ./check generic/091 FSTYP -- f2fs PLATFORM -- Linux/x86_64 lkp-skl-d01 6.10.0-rc3-00027-g5c8764f8679e #1 SMP PREEMPT_DYNAMIC Wed Sep 11 10:37:47 CST 2024 MKFS_OPTIONS -- -f /dev/sda4 MOUNT_OPTIONS -- -o acl,user_xattr /dev/sda4 /fs/scratch generic/091 [failed, exit status 1]- output mismatch (see /lkp/benchmarks/xfstests/results//generic/091.out.bad) --- tests/generic/091.out 2024-09-09 16:31:23.0 + +++ /lkp/benchmarks/xfstests/results//generic/091.out.bad 2024-09-11 03:14:07.468026185 + @@ -1,7 +1,55 @@ QA output created by 091 fsx -N 1 -l 50 -r PSIZE -t BSIZE -w BSIZE -Z -R -W -fsx -N 1 -o 8192 -l 50 -r PSIZE -t BSIZE -w BSIZE -Z -R -W -fsx -N 1 -o 32768 -l 50 -r PSIZE -t BSIZE -w BSIZE -Z -R -W -fsx -N 1 -o 8192 -l 50 -r PSIZE -t BSIZE -w BSIZE -Z -R -W -fsx -N 1 -o 32768 -l 50 -r PSIZE -t BSIZE -w BSIZE -Z -R -W -fsx -N 1 -o 128000 -l 50 -r PSIZE -t BSIZE -w BSIZE -Z -W ... (Run 'diff -u /lkp/benchmarks/xfstests/tests/generic/091.out /lkp/benchmarks/xfstests/results//generic/091.out.bad' to see the entire diff) Ran: generic/091 Failures: generic/091 Failed 1 of 1 tests The kernel config and materials to reproduce are available at: https://download.01.org/0day-ci/archive/20240912/202409122131.d6e2f8c1-oliver.s...@intel.com ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
Re: [f2fs-dev] [PATCH v2] f2fs: forcibly migrate to secure space for zoned device file pinning
On 2024/9/13 0:59, Daeho Jeong wrote: From: Daeho Jeong We need to migrate data blocks even though it is full to secure space for zoned device file pinning. Signed-off-by: Daeho Jeong Fixes: 9703d69d9d15 ("f2fs: support file pinning for zoned devices") Reviewed-by: Chao Yu Thanks, ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
Re: [f2fs-dev] [PATCH v2 00/13] f2fs: introduce inline tail
On 2024/9/11 11:57, Wu Bo wrote: The inode in F2FS occupies an entire 4k block. For many small files, this means they consume much more space than their actual size. Therefore, there is significant potential to better utilize the inode block space. Currently, F2FS has two features to make use of the inode block space: inline data and inline xattr. Inline data stores file which size is smaller then 3.5k in inode block. However, for slightly larger small files, there still have much waste. For example, a 5k file requires 3 blocks, totaling 12k of space, which is more than twice the size of the file itself! Additionally, the end of a file often does not occupy an entire block. If we can store the end of the file data within the inode block, we can save an entire block for the file. This is particularly important for small files. In fact, the current inline data is a special case of inline tail, and inline tail is an extension of inline data. To make it simple, inline tail only on small files(<64k). And for larger files, inline tails don't provide any significant benefits. The layout of an inline tail inode block is following: | inode block | 4096 | inline tail enable| | --- | | --| | inode info | 360 | | | --- | | --| | | | extra info | 0~36 | | | | **compact_addr[16] | 64 | | addr table[923] | 3692 | reserved | 4| | | | **tail data| | | | | inline_xattr | 200 | | --- | | --| | nid table[5]| 20 | | node footer | 24 | F2fs-tools to support inline tail: https://lore.kernel.org/linux-f2fs-devel/20240903075931.3339584-1-bo...@vivo.com I tested inline tail by copying the source code of Linux 6.9.7. The storage space was reduced by approximately 8%. Additionally, due to the reduced IO, the copy time also reduced by around 10%. This patch series has been tested with xfstests by running 'kvm-xfstests -c f2fs -g quick' both with and without the patch; no regressions were observed. The test result is: f2fs/default: 583 tests, 6 failures, 213 skipped, 650 seconds Failures: generic/050 generic/064 generic/250 generic/252 generic/563 generic/735 Totals: 607 tests, 213 skipped, 30 failures, 0 errors, 579s MKFS_OPTIONS -- -O extra_attr,encrypt,inode_checksum,flexible_inline_xattr,inode_crtime,verity,compression -f /dev/vdc MOUNT_OPTIONS -- -o acl,user_xattr -o discard,inline_tail /dev/vdc /mnt/scratch_f2fs Before: Failures: generic/042 generic/050 generic/250 generic/252 generic/270 generic/389 generic/563 generic/700 generic/735 Failed 9 of 746 tests After: Failures: generic/042 generic/050 generic/125 generic/250 generic/252 generic/270 generic/389 generic/418 generic/551 generic/563 generic/700 generic/735 Failed 12 of 746 tests Failures: f2fs/004 Can you please check failed testcases? Thanks, --- v2: - fix ARCH=arc build warning --- Wu Bo (13): f2fs: add inline tail mount option f2fs: add inline tail disk layout definition f2fs: implement inline tail write & truncate f2fs: implement inline tail read & fiemap f2fs: set inline tail flag when create inode f2fs: fix address info has been truncated f2fs: support seek for inline tail f2fs: convert inline tail when inode expand f2fs: fix data loss during inline tail writing f2fs: avoid inlining quota files f2fs: fix inline tail data lost f2fs: convert inline tails to avoid potential issues f2fs: implement inline tail forward recovery fs/f2fs/data.c | 93 +- fs/f2fs/f2fs.h | 46 - fs/f2fs/file.c | 85 +++- fs/f2fs/inline.c | 159 +++-- fs/f2fs/inode.c| 6 ++ fs/f2fs/namei.c| 3 + fs/f2fs/node.c | 6 +- fs/f2fs/recovery.c | 9 ++- fs/f2fs/super.c| 25 +++ fs/f2fs/verity.c | 4 ++ 10 files changed, 409 insertions(+), 27 deletions(-) base-commit: 67784a74e258a467225f0e68335df77acd67b7ab ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
Re: [f2fs-dev] [PATCH 0/9] f2fs: new mount API conversion
On 2024/9/11 10:04, Hongbo Li wrote: Is the subject of the email required to be [f2fs-dev][PATCH]? Hongbo, "[f2fs-dev]" prefix is added by f2fs mailing list when it forwards your patch to someone who subscribes the list, if you receive a patch w/o f2fs-dev prefix, it is because you Sent/Cced patch to yourself, and the list selected to not send you another email which has prefix based on your mailing list option, IIUC. So, it doesn't matter. :) Thanks, ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
Re: [f2fs-dev] [PATCH v1 2/2] f2fs: introduce get_section_mtime
On 2024/9/11 10:40, liuder...@oppo.com wrote: From: liuderong When segs_per_sec is larger than 1, section may contain free segments, mtime should be the mean value of each valid segments, so introduce get_section_mtime to exclude free segments in a section. Signed-off-by: liuderong --- fs/f2fs/f2fs.h| 2 ++ fs/f2fs/gc.c | 15 ++- fs/f2fs/segment.c | 49 - 3 files changed, 48 insertions(+), 18 deletions(-) diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 4dcdcdd..d6adf0f 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -3762,6 +3762,8 @@ enum rw_hint f2fs_io_type_to_rw_hint(struct f2fs_sb_info *sbi, unsigned int f2fs_usable_segs_in_sec(struct f2fs_sb_info *sbi); unsigned int f2fs_usable_blks_in_seg(struct f2fs_sb_info *sbi, unsigned int segno); +unsigned long long get_section_mtime(struct f2fs_sb_info *sbi, + unsigned int segno); #define DEF_FRAGMENT_SIZE 4 #define MIN_FRAGMENT_SIZE 1 diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index 6299639..03c6117 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c @@ -332,20 +332,14 @@ static unsigned int check_bg_victims(struct f2fs_sb_info *sbi) static unsigned int get_cb_cost(struct f2fs_sb_info *sbi, unsigned int segno) { struct sit_info *sit_i = SIT_I(sbi); - unsigned int secno = GET_SEC_FROM_SEG(sbi, segno); - unsigned int start = GET_SEG_FROM_SEC(sbi, secno); unsigned long long mtime = 0; unsigned int vblocks; unsigned char age = 0; unsigned char u; - unsigned int i; unsigned int usable_segs_per_sec = f2fs_usable_segs_in_sec(sbi); - for (i = 0; i < usable_segs_per_sec; i++) - mtime += get_seg_entry(sbi, start + i)->mtime; + mtime = get_section_mtime(sbi, segno); vblocks = get_valid_blocks(sbi, segno, true); - - mtime = div_u64(mtime, usable_segs_per_sec); vblocks = div_u64(vblocks, usable_segs_per_sec); u = BLKS_TO_SEGS(sbi, vblocks * 100); @@ -485,10 +479,7 @@ static void add_victim_entry(struct f2fs_sb_info *sbi, struct victim_sel_policy *p, unsigned int segno) { struct sit_info *sit_i = SIT_I(sbi); - unsigned int secno = GET_SEC_FROM_SEG(sbi, segno); - unsigned int start = GET_SEG_FROM_SEC(sbi, secno); unsigned long long mtime = 0; - unsigned int i; if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) { if (p->gc_mode == GC_AT && @@ -496,9 +487,7 @@ static void add_victim_entry(struct f2fs_sb_info *sbi, return; } - for (i = 0; i < SEGS_PER_SEC(sbi); i++) - mtime += get_seg_entry(sbi, start + i)->mtime; - mtime = div_u64(mtime, SEGS_PER_SEC(sbi)); + mtime = get_section_mtime(sbi, segno); /* Handle if the system time has changed by the user */ if (mtime < sit_i->min_mtime) diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index 6627394..b63f35fa 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -5389,6 +5389,49 @@ unsigned int f2fs_usable_segs_in_sec(struct f2fs_sb_info *sbi) return SEGS_PER_SEC(sbi); } +unsigned long long get_section_mtime(struct f2fs_sb_info *sbi, + unsigned int segno) +{ + unsigned int usable_segs_per_sec = f2fs_usable_segs_in_sec(sbi); + unsigned int secno = 0, start = 0; + struct free_segmap_info *free_i = FREE_I(sbi); + unsigned int valid_seg_count = 0; + unsigned long long mtime = 0; + unsigned int i; + + if (segno == NULL_SEGNO) + return 0; + + secno = GET_SEC_FROM_SEG(sbi, segno); + start = GET_SEG_FROM_SEC(sbi, secno); + + for (i = 0; i < usable_segs_per_sec; i++) { + /* for large section, only check the mtime of valid segments */ + if (__is_large_section(sbi)) { + spin_lock(&free_i->segmap_lock); + if (test_bit(start + i, free_i->free_segmap)) { + mtime += get_seg_entry(sbi, start + i)->mtime; + valid_seg_count++; + } + spin_unlock(&free_i->segmap_lock); + } else { + mtime += get_seg_entry(sbi, start + i)->mtime; + } + } + + if (__is_large_section(sbi)) { + if (!valid_seg_count) + goto out; + mtime = div_u64(mtime, valid_seg_count); + } else { + mtime = div_u64(mtime, usable_segs_per_sec); + } What about: if (!__is_large_section(sbi)) return get_seg_entry(sbi, start + i)->mtime; for (i = 0; i < usable_segs_per_sec; i++) { /* for large section, only check the mtime of valid segments */ ... } return div_u64(mtime, usable_segs_per_sec); Thank
Re: [f2fs-dev] [PATCH v1 1/2] f2fs: remove unused parameters
On 2024/9/11 10:40, liuder...@oppo.com wrote: From: liuderong Remove unused parameter segno from f2fs_usable_segs_in_sec. Signed-off-by: liuderong Reviewed-by: Chao Yu Thanks, ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
Re: [f2fs-dev] [RFC PATCH] f2fs: don't set SBI_QUOTA_NEED_REPAIR flag if receive SIGKILL
On 2024/9/4 11:49, Chao Yu via Linux-f2fs-devel wrote: On 2024/9/3 14:06, wangzijie wrote: From: Chao Yu via Linux-f2fs-devel On 2024/8/27 14:22, wangzijie wrote: Thread A -dquot_initialize -dqget -f2fs_dquot_acquire -v2_read_dquot -qtree_read_dquot -find_tree_dqentry -f2fs_quota_read -read_cache_page_gfp -do_read_cache_folio -fiemap_read_folio -folio_wait_locked_killable -receive SIGKILL : return -EINTR -set SBI_QUOTA_NEED_REPAIR -set SBI_QUOTA_NEED_REPAIR When calling read_cache_page_gfp in quota read, thread may receive SIGKILL and set SBI_QUOTA_NEED_REPAIR, should we set SBI_QUOTA_NEED_REPAIR in this error path? f2fs_quota_read() can be called in a lot of contexts, can we just ignore -EINTR for f2fs_dquot_initialize() case? Thanks, Yes, in many contexts f2fs_quota_read() can be called and may return -EINTR, we need to ignore this errno for more cases. If we need to do so, I will check it and resend patch. Or do you have other suggestions to avoid unnecessary SBI_QUOTA_NEED_REPAIR flag set? How about this? --- fs/f2fs/f2fs.h | 1 + fs/f2fs/inode.c | 3 +-- fs/f2fs/super.c | 17 + 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index dfed1974eda5..a1704a19dfe9 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -810,6 +810,7 @@ enum { FI_ATOMIC_DIRTIED, /* indicate atomic file is dirtied */ FI_ATOMIC_REPLACE, /* indicate atomic replace */ FI_OPENED_FILE, /* indicate file has been opened */ + FI_INIT_DQUOT, /* indicate it's initializing dquot */ FI_MAX, /* max flag, never be used */ }; diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c index 008f01348afa..b1dbaeda306f 100644 --- a/fs/f2fs/inode.c +++ b/fs/f2fs/inode.c @@ -827,8 +827,7 @@ void f2fs_evict_inode(struct inode *inode) err = f2fs_dquot_initialize(inode); if (err) { - if (err != -EINTR) - set_sbi_flag(sbi, SBI_QUOTA_NEED_REPAIR); + set_sbi_flag(sbi, SBI_QUOTA_NEED_REPAIR); err = 0; } diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 8e29aba4b7a4..e774bdf875b2 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -2644,8 +2644,11 @@ static ssize_t f2fs_quota_read(struct super_block *sb, int type, char *data, if (PTR_ERR(page) == -ENOMEM) { memalloc_retry_wait(GFP_NOFS); goto repeat; - } else if (PTR_ERR(page) != -EINTR) - set_sbi_flag(F2FS_SB(sb), SBI_QUOTA_NEED_REPAIR); + } else if (PTR_ERR(page) == -EINTR && + is_inode_flag_set(inode, FI_INIT_DQUOT)) { Current inode is quota inode, it's not the same inode we tagged w/ FI_INIT_DQUOT, so please ignore this diff... Thanks, + return PTR_ERR(page); + } + set_sbi_flag(F2FS_SB(sb), SBI_QUOTA_NEED_REPAIR); return PTR_ERR(page); } @@ -2721,10 +2724,16 @@ static ssize_t f2fs_quota_write(struct super_block *sb, int type, int f2fs_dquot_initialize(struct inode *inode) { + int ret; + if (time_to_inject(F2FS_I_SB(inode), FAULT_DQUOT_INIT)) return -ESRCH; - return dquot_initialize(inode); + set_inode_flag(inode, FI_INIT_DQUOT); + ret = dquot_initialize(inode); + clear_inode_flag(inode, FI_INIT_DQUOT); + + return ret; } static struct dquot __rcu **f2fs_get_dquots(struct inode *inode) @@ -3064,7 +3073,7 @@ static int f2fs_dquot_acquire(struct dquot *dquot) f2fs_down_read(&sbi->quota_sem); ret = dquot_acquire(dquot); - if (ret < 0 && ret != -EINTR) + if (ret < 0) set_sbi_flag(sbi, SBI_QUOTA_NEED_REPAIR); f2fs_up_read(&sbi->quota_sem); return ret; ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
Re: [f2fs-dev] [PATCH] f2fs: fix to tag STATX_DIOALIGN only if inode support dio
On 2024/9/11 1:06, Eric Biggers wrote: On Tue, Sep 10, 2024 at 08:57:53PM +0800, Chao Yu via Linux-f2fs-devel wrote: After commit 5c8764f8679e ("f2fs: fix to force buffered IO on inline_data inode"), f2fs starts to force using buffered IO on inline_data inode. And also, it will cause f2fs_getattr() returning invalid zeroed value on .dio_mem_align and .dio_offset_align fields, however, STATX_DIOALIGN flag was been tagged. User may use zeroed .stx_dio_offset_align value since STATX_DIOALIGN was been tagged, then it causes a deadloop during generic/465 test due to below logic: align=stx_dio_offset_align(it equals to zero) page_size=4096 while [ $align -le $page_size ]; do echo "$AIO_TEST -a $align -d $testfile.$align" >> $seqres.full $AIO_TEST -a $align -d $testfile.$align 2>&1 | tee -a $seqres.full align=$((align * 2)) done Quoted from description of statx manual: " If a filesystem does not support a field or if it has an unrepresentable value (for instance, a file with an exotic type), then the mask bit corresponding to that field will be cleared in stx_mask even if the user asked for it and a dummy value will be filled in for compatibility purposes if one is available (e.g., a dummy UID and GID may be specified to mount under some circumstances)." We should not set STATX_DIOALIGN flag in kstat.stx_mask if inode does not support DIO, so that it can indicate related fields contain dummy value, and avoid following incorrect use of them. Fixes: c8c02272a9f7 ("f2fs: support STATX_DIOALIGN") When claiming to be Fixing a commit, please make sure to Cc the author of that commit. No problem, will make sure they were Cced. Signed-off-by: Chao Yu --- fs/f2fs/file.c | 11 --- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 99903eafa7fe..f0b8b77e93ba 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -906,14 +906,11 @@ int f2fs_getattr(struct mnt_idmap *idmap, const struct path *path, * f2fs sometimes supports DIO reads but not DIO writes. STATX_DIOALIGN * cannot represent that, so in that case we report no DIO support. */ - if ((request_mask & STATX_DIOALIGN) && S_ISREG(inode->i_mode)) { - unsigned int bsize = i_blocksize(inode); - + if ((request_mask & STATX_DIOALIGN) && S_ISREG(inode->i_mode) && + !f2fs_force_buffered_io(inode, WRITE)) { + stat->dio_mem_align = F2FS_BLKSIZE; + stat->dio_offset_align = F2FS_BLKSIZE; stat->result_mask |= STATX_DIOALIGN; - if (!f2fs_force_buffered_io(inode, WRITE)) { - stat->dio_mem_align = bsize; - stat->dio_offset_align = bsize; - } } flags = fi->i_flags; No, this patch is wrong and the existing code is correct. The cases are: Yes, you're right, thanks for pointing out this! STATX_DIOALIGN set and stx_dio_*_align nonzero: File supports DIO. STATX_DIOALIGN set and stx_dio_*_align zero: File doesn't support DIO. STATX_DIOALIGN unset: Filesystem doesn't support STATX_DIOALIGN, so it's unknown whether the file supports DIO or not. Above description is clear to me. Please see the statx(2) manual page which explains this too. However, below manual seems not very clear about explaining what does it mean about STATX_DIOALIGN is set or not? At least not so clear like above description. stx_dio_mem_align The alignment (in bytes) required for user memory buffers for direct I/O (O_DIRECT) on this file, or 0 if direct I/O is not supported on this file. STATX_DIOALIGN (stx_dio_mem_align and stx_dio_offset_align) is supported on block devices since Linux 6.1. The support on regular files varies by filesystem; it is supported by ext4, f2fs, and xfs since Linux 6.1. stx_dio_offset_align The alignment (in bytes) required for file offsets and I/O segment lengths for direct I/O (O_DIRECT) on this file, or 0 if direct I/O is not supported on this file. This will only be nonzero if stx_dio_mem_align is nonzero, and vice versa. Thanks, - Eric ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
Re: [f2fs-dev] [PATCH v2 7/7] f2fs: add valid block ratio not to do excessive GC for one time GC
On 2024/9/10 6:19, Daeho Jeong wrote: From: Daeho Jeong We need to introduce a valid block ratio threshold not to trigger excessive GC for zoned deivces. The initial value of it is 95%. So, F2FS will stop the thread from intiating GC for sections having valid blocks exceeding the ratio. Signed-off-by: Daeho Jeong Reviewed-by: Chao Yu Thanks, ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
Re: [f2fs-dev] [PATCH v2 6/7] f2fs: create gc_no_zoned_gc_percent and gc_boost_zoned_gc_percent
On 2024/9/10 6:19, Daeho Jeong wrote: From: Daeho Jeong Added control knobs for gc_no_zoned_gc_percent and gc_boost_zoned_gc_percent. Signed-off-by: Daeho Jeong Reviewed-by: Chao Yu Thanks, ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
Re: [f2fs-dev] [PATCH v2 5/7] f2fs: do FG_GC when GC boosting is required for zoned devices
On 2024/9/10 6:19, Daeho Jeong wrote: From: Daeho Jeong Under low free section count, we need to use FG_GC instead of BG_GC to recover free sections. Signed-off-by: Daeho Jeong Reviewed-by: Chao Yu Thanks, ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
Re: [f2fs-dev] [PATCH v2 4/7] f2fs: increase BG GC migration window granularity when boosted for zoned devices
On 2024/9/10 6:19, Daeho Jeong wrote: From: Daeho Jeong Need bigger BG GC migration window granularity when free section is running low. Signed-off-by: Daeho Jeong Reviewed-by: Chao Yu Thanks, ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
Re: [f2fs-dev] [PATCH v2 3/7] f2fs: add reserved_segments sysfs node
On 2024/9/10 6:19, Daeho Jeong wrote: From: Daeho Jeong For the fine tuning of GC behavior, add reserved_segments sysfs node. Signed-off-by: Daeho Jeong Reviewed-by: Chao Yu Thanks, ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
Re: [f2fs-dev] [PATCH v2 2/7] f2fs: introduce migration_window_granularity
On 2024/9/10 6:19, Daeho Jeong wrote: From: Daeho Jeong We can control the scanning window granularity for GC migration. For more frequent scanning and GC on zoned devices, we need a fine grained control knob for it. Signed-off-by: Daeho Jeong Reviewed-by: Chao Yu Thanks, ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
Re: [f2fs-dev] [PATCH v2 1/7] f2fs: make BG GC more aggressive for zoned devices
On 2024/9/10 6:19, Daeho Jeong wrote: From: Daeho Jeong Since we don't have any GC on device side for zoned devices, need more aggressive BG GC. So, tune the parameters for that. Signed-off-by: Daeho Jeong Daeho, What about collecting all last reviewed-by tags for each patch of this patchset? if there is no change when version updates. Reviewed-by: Chao Yu Thanks, ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
Re: [f2fs-dev] [PATCH] fsck.f2fs: remove redundant i_ext.len set to zero
On 2024/9/10 0:45, Daeho Jeong wrote: From: Daeho Jeong Removed a redundant code to set i_ext.len to zero. Signed-off-by: Daeho Jeong Reviewed-by: Chao Yu Thanks, ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
Re: [f2fs-dev] [syzbot] [f2fs?] WARNING in rcu_sync_dtor
#syz test: https://git.kernel.org/pub/scm/linux/kernel/git/chao/linux.git wip On 2024/7/26 15:54, syzbot wrote: Hello, syzbot found the following issue on: HEAD commit:1722389b0d86 Merge tag 'net-6.11-rc1' of git://git.kernel... git tree: upstream console+strace: https://syzkaller.appspot.com/x/log.txt?x=1495542398 kernel config: https://syzkaller.appspot.com/x/.config?x=b698a1b2fcd7ef5f dashboard link: https://syzkaller.appspot.com/bug?extid=20d7e439f76bbbd863a7 compiler: Debian clang version 15.0.6, GNU ld (GNU Binutils for Debian) 2.40 syz repro: https://syzkaller.appspot.com/x/repro.syz?x=1237a1f198 C reproducer: https://syzkaller.appspot.com/x/repro.c?x=115edac998 Downloadable assets: disk image: https://storage.googleapis.com/syzbot-assets/e3f4ec8ccf7c/disk-1722389b.raw.xz vmlinux: https://storage.googleapis.com/syzbot-assets/f19bcd908282/vmlinux-1722389b.xz kernel image: https://storage.googleapis.com/syzbot-assets/d93604974a98/bzImage-1722389b.xz mounted in repro: https://storage.googleapis.com/syzbot-assets/e0d10e1258f5/mount_0.gz IMPORTANT: if you fix the issue, please add the following tag to the commit: Reported-by: syzbot+20d7e439f76bbbd86...@syzkaller.appspotmail.com [ cut here ] WARNING: CPU: 1 PID: 58 at kernel/rcu/sync.c:177 rcu_sync_dtor+0xcd/0x180 kernel/rcu/sync.c:177 Modules linked in: CPU: 1 UID: 0 PID: 58 Comm: kworker/1:2 Not tainted 6.10.0-syzkaller-12562-g1722389b0d86 #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 06/27/2024 Workqueue: events destroy_super_work RIP: 0010:rcu_sync_dtor+0xcd/0x180 kernel/rcu/sync.c:177 Code: 74 19 e8 86 d5 00 00 43 0f b6 44 25 00 84 c0 0f 85 82 00 00 00 41 83 3f 00 75 1d 5b 41 5c 41 5d 41 5e 41 5f c3 cc cc cc cc 90 <0f> 0b 90 e9 66 ff ff ff 90 0f 0b 90 eb 89 90 0f 0b 90 eb dd 44 89 RSP: 0018:c9000133fb30 EFLAGS: 00010246 RAX: 0002 RBX: 111005324477 RCX: 8880163f5a00 RDX: RSI: 8c3f9540 RDI: 888029922350 RBP: 0167 R08: 82092061 R09: 11cbbbd4 R10: dc00 R11: fbfff1cbbbd5 R12: dc00 R13: 11100532446a R14: 888029922350 R15: 888029922350 FS: () GS:8880b930() knlGS: CS: 0010 DS: ES: CR0: 80050033 CR2: 7c167738 CR3: 7ada8000 CR4: 003506f0 DR0: DR1: DR2: DR3: DR6: fffe0ff0 DR7: 0400 Call Trace: percpu_free_rwsem+0x41/0x80 kernel/locking/percpu-rwsem.c:42 destroy_super_work+0xec/0x130 fs/super.c:282 process_one_work kernel/workqueue.c:3231 [inline] process_scheduled_works+0xa2c/0x1830 kernel/workqueue.c:3312 worker_thread+0x86d/0xd40 kernel/workqueue.c:3390 kthread+0x2f0/0x390 kernel/kthread.c:389 ret_from_fork+0x4b/0x80 arch/x86/kernel/process.c:147 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244 --- 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 syzkal...@googlegroups.com. syzbot will keep track of this issue. See: https://goo.gl/tpsmEJ#status for how to communicate with syzbot. 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 ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
[f2fs-dev] [PATCH] f2fs: fix to tag STATX_DIOALIGN only if inode support dio
After commit 5c8764f8679e ("f2fs: fix to force buffered IO on inline_data inode"), f2fs starts to force using buffered IO on inline_data inode. And also, it will cause f2fs_getattr() returning invalid zeroed value on .dio_mem_align and .dio_offset_align fields, however, STATX_DIOALIGN flag was been tagged. User may use zeroed .stx_dio_offset_align value since STATX_DIOALIGN was been tagged, then it causes a deadloop during generic/465 test due to below logic: align=stx_dio_offset_align(it equals to zero) page_size=4096 while [ $align -le $page_size ]; do echo "$AIO_TEST -a $align -d $testfile.$align" >> $seqres.full $AIO_TEST -a $align -d $testfile.$align 2>&1 | tee -a $seqres.full align=$((align * 2)) done Quoted from description of statx manual: " If a filesystem does not support a field or if it has an unrepresentable value (for instance, a file with an exotic type), then the mask bit corresponding to that field will be cleared in stx_mask even if the user asked for it and a dummy value will be filled in for compatibility purposes if one is available (e.g., a dummy UID and GID may be specified to mount under some circumstances)." We should not set STATX_DIOALIGN flag in kstat.stx_mask if inode does not support DIO, so that it can indicate related fields contain dummy value, and avoid following incorrect use of them. Fixes: c8c02272a9f7 ("f2fs: support STATX_DIOALIGN") Signed-off-by: Chao Yu --- fs/f2fs/file.c | 11 --- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 99903eafa7fe..f0b8b77e93ba 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -906,14 +906,11 @@ int f2fs_getattr(struct mnt_idmap *idmap, const struct path *path, * f2fs sometimes supports DIO reads but not DIO writes. STATX_DIOALIGN * cannot represent that, so in that case we report no DIO support. */ - if ((request_mask & STATX_DIOALIGN) && S_ISREG(inode->i_mode)) { - unsigned int bsize = i_blocksize(inode); - + if ((request_mask & STATX_DIOALIGN) && S_ISREG(inode->i_mode) && + !f2fs_force_buffered_io(inode, WRITE)) { + stat->dio_mem_align = F2FS_BLKSIZE; + stat->dio_offset_align = F2FS_BLKSIZE; stat->result_mask |= STATX_DIOALIGN; - if (!f2fs_force_buffered_io(inode, WRITE)) { - stat->dio_mem_align = bsize; - stat->dio_offset_align = bsize; - } } flags = fi->i_flags; -- 2.40.1 ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
[f2fs-dev] [PATCH] f2fs: fix to don't set SB_RDONLY in f2fs_handle_critical_error()
syzbot reports a f2fs bug as below: [ cut here ] WARNING: CPU: 1 PID: 58 at kernel/rcu/sync.c:177 rcu_sync_dtor+0xcd/0x180 kernel/rcu/sync.c:177 CPU: 1 UID: 0 PID: 58 Comm: kworker/1:2 Not tainted 6.10.0-syzkaller-12562-g1722389b0d86 #0 Workqueue: events destroy_super_work RIP: 0010:rcu_sync_dtor+0xcd/0x180 kernel/rcu/sync.c:177 Call Trace: percpu_free_rwsem+0x41/0x80 kernel/locking/percpu-rwsem.c:42 destroy_super_work+0xec/0x130 fs/super.c:282 process_one_work kernel/workqueue.c:3231 [inline] process_scheduled_works+0xa2c/0x1830 kernel/workqueue.c:3312 worker_thread+0x86d/0xd40 kernel/workqueue.c:3390 kthread+0x2f0/0x390 kernel/kthread.c:389 ret_from_fork+0x4b/0x80 arch/x86/kernel/process.c:147 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244 As Christian Brauner pointed out [1]: the root cause is f2fs sets SB_RDONLY flag in internal function, rather than setting the flag covered w/ sb->s_umount semaphore via remount procedure, then below race condition causes this bug: - freeze_super() - sb_wait_write(sb, SB_FREEZE_WRITE) - sb_wait_write(sb, SB_FREEZE_PAGEFAULT) - sb_wait_write(sb, SB_FREEZE_FS) - f2fs_handle_critical_error - sb->s_flags |= SB_RDONLY - thaw_super - thaw_super_locked - sb_rdonly() is true, so it skips sb_freeze_unlock(sb, SB_FREEZE_FS) - deactivate_locked_super Since f2fs has almost the same logic as ext4 [2] when handling critical error in filesystem if it mounts w/ errors=remount-ro option: - set CP_ERROR_FLAG flag which indicates filesystem is stopped - record errors to superblock - set SB_RDONLY falg Once we set CP_ERROR_FLAG flag, all writable interfaces can detect the flag and stop any further updates on filesystem. So, it is safe to not set SB_RDONLY flag, let's remove the logic and keep in line w/ ext4 [3]. [1] https://lore.kernel.org/all/20240729-himbeeren-funknetz-96e62f9c7aee@brauner [2] https://lore.kernel.org/all/20240729132721.hxih6ehigadqf7wx@quack3 [3] https://lore.kernel.org/linux-ext4/20240805201241.27286-1-j...@suse.cz Fixes: b62e71be2110 ("f2fs: support errors=remount-ro|continue|panic mountoption") Reported-by: syzbot+20d7e439f76bbbd86...@syzkaller.appspotmail.com Closes: https://lore.kernel.org/all/b90a8e061e21d...@google.com/ Cc: Jan Kara Cc: Christian Brauner Signed-off-by: Chao Yu --- fs/f2fs/super.c | 10 ++ 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index e774bdf875b2..acfd000c6bb0 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -4207,12 +4207,14 @@ void f2fs_handle_critical_error(struct f2fs_sb_info *sbi, unsigned char reason, } f2fs_warn(sbi, "Remounting filesystem read-only"); + /* -* Make sure updated value of ->s_mount_flags will be visible before -* ->s_flags update +* We have already set CP_ERROR_FLAG flag to stop all updates +* to filesystem, so it doesn't need to set SB_RDONLY flag here +* because the flag should be set covered w/ sb->s_umount semaphore +* via remount procedure, otherwise, it will confuse code like +* freeze_super() which will lead to deadlocks and other problems. */ - smp_wmb(); - sb->s_flags |= SB_RDONLY; } static void f2fs_record_error_work(struct work_struct *work) -- 2.40.1 ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
[f2fs-dev] [PATCH] f2fs: fix to don't panic system for no free segment fault injection
f2fs: fix to don't panic system for no free segment fault injection syzbot reports a f2fs bug as below: F2FS-fs (loop0): inject no free segment in get_new_segment of __allocate_new_segment+0x1ce/0x940 fs/f2fs/segment.c:3167 F2FS-fs (loop0): Stopped filesystem due to reason: 7 [ cut here ] kernel BUG at fs/f2fs/segment.c:2748! CPU: 0 UID: 0 PID: 5109 Comm: syz-executor304 Not tainted 6.11.0-rc6-syzkaller-00363-g89f5e14d05b4 #0 RIP: 0010:get_new_segment fs/f2fs/segment.c:2748 [inline] RIP: 0010:new_curseg+0x1f61/0x1f70 fs/f2fs/segment.c:2836 Call Trace: __allocate_new_segment+0x1ce/0x940 fs/f2fs/segment.c:3167 f2fs_allocate_new_section fs/f2fs/segment.c:3181 [inline] f2fs_allocate_pinning_section+0xfa/0x4e0 fs/f2fs/segment.c:3195 f2fs_expand_inode_data+0x5d6/0xbb0 fs/f2fs/file.c:1799 f2fs_fallocate+0x448/0x960 fs/f2fs/file.c:1903 vfs_fallocate+0x553/0x6c0 fs/open.c:334 do_vfs_ioctl+0x2592/0x2e50 fs/ioctl.c:886 __do_sys_ioctl fs/ioctl.c:905 [inline] __se_sys_ioctl+0x81/0x170 fs/ioctl.c:893 do_syscall_x64 arch/x86/entry/common.c:52 [inline] do_syscall_64+0xf3/0x230 arch/x86/entry/common.c:83 entry_SYSCALL_64_after_hwframe+0x77/0x7f RIP: 0010:get_new_segment fs/f2fs/segment.c:2748 [inline] RIP: 0010:new_curseg+0x1f61/0x1f70 fs/f2fs/segment.c:2836 The root cause is when we inject no free segment fault into f2fs, we should not panic system, fix it. Fixes: 8b10d3653735 ("f2fs: introduce FAULT_NO_SEGMENT") Reported-by: syzbot+341e5f32ebafbb46b...@syzkaller.appspotmail.com Closes: https://lore.kernel.org/linux-f2fs-devel/f0ee5b0621ab6...@google.com Signed-off-by: Chao Yu --- fs/f2fs/segment.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index 112d58d566d4..b7c1ca51ea32 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -2730,6 +2730,7 @@ static int get_new_segment(struct f2fs_sb_info *sbi, MAIN_SECS(sbi)); if (secno >= MAIN_SECS(sbi)) { ret = -ENOSPC; + f2fs_bug_on(sbi, 1); goto out_unlock; } } @@ -2740,6 +2741,7 @@ static int get_new_segment(struct f2fs_sb_info *sbi, MAIN_SECS(sbi)); if (secno >= MAIN_SECS(sbi)) { ret = -ENOSPC; + f2fs_bug_on(sbi, 1); goto out_unlock; } } @@ -2781,10 +2783,8 @@ static int get_new_segment(struct f2fs_sb_info *sbi, out_unlock: spin_unlock(&free_i->segmap_lock); - if (ret == -ENOSPC) { + if (ret == -ENOSPC) f2fs_stop_checkpoint(sbi, false, STOP_CP_REASON_NO_SEGMENT); - f2fs_bug_on(sbi, 1); - } return ret; } -- 2.40.1 ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
Re: [f2fs-dev] [syzbot] [f2fs?] kernel BUG in new_curseg
#syz test git://git.kernel.org/pub/scm/linux/kernel/git/chao/linux.git wip On 2024/9/9 16:19, syzbot wrote: Hello, syzbot found the following issue on: HEAD commit:89f5e14d05b4 Merge tag 'timers_urgent_for_v6.11_rc7' of gi.. git tree: upstream console output: https://syzkaller.appspot.com/x/log.txt?x=14085f2998 kernel config: https://syzkaller.appspot.com/x/.config?x=58a85aa6925a8b78 dashboard link: https://syzkaller.appspot.com/bug?extid=341e5f32ebafbb46b81c compiler: Debian clang version 15.0.6, GNU ld (GNU Binutils for Debian) 2.40 syz repro: https://syzkaller.appspot.com/x/repro.syz?x=1614c80798 C reproducer: https://syzkaller.appspot.com/x/repro.c?x=13854e0058 Downloadable assets: disk image (non-bootable): https://storage.googleapis.com/syzbot-assets/7bc7510fe41f/non_bootable_disk-89f5e14d.raw.xz vmlinux: https://storage.googleapis.com/syzbot-assets/dfc310daee41/vmlinux-89f5e14d.xz kernel image: https://storage.googleapis.com/syzbot-assets/a92f22c06568/bzImage-89f5e14d.xz mounted in repro: https://storage.googleapis.com/syzbot-assets/c7aaf1741c93/mount_1.gz IMPORTANT: if you fix the issue, please add the following tag to the commit: Reported-by: syzbot+341e5f32ebafbb46b...@syzkaller.appspotmail.com F2FS-fs (loop0): inject no free segment in get_new_segment of __allocate_new_segment+0x1ce/0x940 fs/f2fs/segment.c:3167 F2FS-fs (loop0): Stopped filesystem due to reason: 7 [ cut here ] kernel BUG at fs/f2fs/segment.c:2748! Oops: invalid opcode: [#1] PREEMPT SMP KASAN NOPTI CPU: 0 UID: 0 PID: 5109 Comm: syz-executor304 Not tainted 6.11.0-rc6-syzkaller-00363-g89f5e14d05b4 #0 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014 RIP: 0010:get_new_segment fs/f2fs/segment.c:2748 [inline] RIP: 0010:new_curseg+0x1f61/0x1f70 fs/f2fs/segment.c:2836 Code: 24 58 e8 12 b9 f2 ff eb 05 e8 4b 71 96 fd 48 8b 7c 24 70 e8 91 ac c6 07 48 8b 7c 24 10 31 f6 ba 07 00 00 00 e8 50 1e f6 ff 90 <0f> 0b 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 00 90 90 90 90 90 90 90 RSP: 0018:c9000179f548 EFLAGS: 00010246 RAX: 8fb07c62f860e300 RBX: 02b2 RCX: 8fb07c62f860e300 RDX: RSI: 8000 RDI: RBP: 8880125250c8 R08: 817401bc R09: 1920002f3e20 R10: dc00 R11: f520002f3e21 R12: 8880008c2700 R13: 8880125250cc R14: 1110024a4a19 R15: 02b2 FS: 93e0e380() GS:88801fe0() knlGS: CS: 0010 DS: ES: CR0: 80050033 CR2: 7f6cf8cb40f8 CR3: 1255a000 CR4: 00350ef0 DR0: DR1: DR2: DR3: DR6: fffe0ff0 DR7: 0400 Call Trace: __allocate_new_segment+0x1ce/0x940 fs/f2fs/segment.c:3167 f2fs_allocate_new_section fs/f2fs/segment.c:3181 [inline] f2fs_allocate_pinning_section+0xfa/0x4e0 fs/f2fs/segment.c:3195 f2fs_expand_inode_data+0x5d6/0xbb0 fs/f2fs/file.c:1799 f2fs_fallocate+0x448/0x960 fs/f2fs/file.c:1903 vfs_fallocate+0x553/0x6c0 fs/open.c:334 do_vfs_ioctl+0x2592/0x2e50 fs/ioctl.c:886 __do_sys_ioctl fs/ioctl.c:905 [inline] __se_sys_ioctl+0x81/0x170 fs/ioctl.c:893 do_syscall_x64 arch/x86/entry/common.c:52 [inline] do_syscall_64+0xf3/0x230 arch/x86/entry/common.c:83 entry_SYSCALL_64_after_hwframe+0x77/0x7f RIP: 0033:0x7f6cf8c37229 Code: 28 00 00 00 75 05 48 83 c4 28 c3 e8 21 18 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:7ffeb5036b58 EFLAGS: 0246 ORIG_RAX: 0010 RAX: ffda RBX: 0030656c69662f2e RCX: 7f6cf8c37229 RDX: 20c0 RSI: 40305828 RDI: 0004 RBP: R08: 7ffeb5036b90 R09: 7ffeb5036b90 R10: 7ffeb5036b90 R11: 0246 R12: 7ffeb5036b7c R13: 0002 R14: 431bde82d7b634db R15: 7ffeb5036bb0 Modules linked in: ---[ end trace ]--- RIP: 0010:get_new_segment fs/f2fs/segment.c:2748 [inline] RIP: 0010:new_curseg+0x1f61/0x1f70 fs/f2fs/segment.c:2836 Code: 24 58 e8 12 b9 f2 ff eb 05 e8 4b 71 96 fd 48 8b 7c 24 70 e8 91 ac c6 07 48 8b 7c 24 10 31 f6 ba 07 00 00 00 e8 50 1e f6 ff 90 <0f> 0b 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 00 90 90 90 90 90 90 90 RSP: 0018:c9000179f548 EFLAGS: 00010246 RAX: 8fb07c62f860e300 RBX: 02b2 RCX: 8fb07c62f860e300 RDX: RSI: 8000 RDI: RBP: 8880125250c8 R08: 817401bc R09: 1920002f3e20 R10: dc00 R11: f520002f3e21 R12: 8880008c2700 R13: 8880125250cc R14: 1110024a4a19 R15: 02b2 FS: 93e0e380() GS:88801fe0() knlGS: CS: 0010 DS: ES: CR0: 80050033 CR2: 7f6cf8cb40f8 CR3: 1255a000 CR4: 00350ef0 DR
Re: [f2fs-dev] [PATCH 7/7] f2fs: add valid block ratio not to do excessive GC for one time GC
On 2024/8/30 5:52, Daeho Jeong wrote: From: Daeho Jeong We need to introduce a valid block ratio threshold not to trigger excessive GC for zoned deivces. The initial value of it is 95%. So, F2FS will stop the thread from intiating GC for sections having valid blocks exceeding the ratio. Signed-off-by: Daeho Jeong --- Documentation/ABI/testing/sysfs-fs-f2fs | 8 fs/f2fs/f2fs.h | 2 +- fs/f2fs/gc.c| 15 +++ fs/f2fs/gc.h| 2 ++ fs/f2fs/segment.c | 6 -- fs/f2fs/segment.h | 1 + fs/f2fs/sysfs.c | 2 ++ 7 files changed, 29 insertions(+), 7 deletions(-) diff --git a/Documentation/ABI/testing/sysfs-fs-f2fs b/Documentation/ABI/testing/sysfs-fs-f2fs index 265baec879fd..2d3e42af0e63 100644 --- a/Documentation/ABI/testing/sysfs-fs-f2fs +++ b/Documentation/ABI/testing/sysfs-fs-f2fs @@ -783,3 +783,11 @@ Contact: "Daeho Jeong" Description: If the percentage of free sections over total sections is under this number, F2FS boosts garbage collection for zoned devices through the background GC thread. the default number is "25". + +What: /sys/fs/f2fs//gc_valid_thresh_ratio +Date: August 2024 +Contact: "Daeho Jeong" +Description: It controls the valid block ratio threshold not to trigger excessive GC + for zoned deivces. The initial value of it is 95(%). F2FS will stop the + background GC thread from intiating GC for sections having valid blocks + exceeding the ratio. diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index ee1fafc65e95..8220b3189780 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -3918,7 +3918,7 @@ void f2fs_destroy_garbage_collection_cache(void); /* victim selection function for cleaning and SSR */ int f2fs_get_victim(struct f2fs_sb_info *sbi, unsigned int *result, int gc_type, int type, char alloc_mode, - unsigned long long age); + unsigned long long age, bool one_time); /* * recovery.c diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index 6b79c43a57e3..feb80345aca3 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c @@ -196,6 +196,7 @@ int f2fs_start_gc_thread(struct f2fs_sb_info *sbi) return -ENOMEM; gc_th->urgent_sleep_time = DEF_GC_THREAD_URGENT_SLEEP_TIME; + gc_th->valid_thresh_ratio = DEF_GC_THREAD_VALID_THRESH_RATIO; if (f2fs_sb_has_blkzoned(sbi)) { gc_th->min_sleep_time = DEF_GC_THREAD_MIN_SLEEP_TIME_ZONED; @@ -396,6 +397,10 @@ static inline unsigned int get_gc_cost(struct f2fs_sb_info *sbi, if (p->alloc_mode == SSR) return get_seg_entry(sbi, segno)->ckpt_valid_blocks; + if (p->one_time_gc && (get_valid_blocks(sbi, segno, true) >= + BLKS_PER_SEC(sbi) * sbi->gc_thread->valid_thresh_ratio / 100)) Use CAP_BLKS_PER_SEC() instead of BLKS_PER_SEC() ? Thanks, + return UINT_MAX; + /* alloc_mode == LFS */ if (p->gc_mode == GC_GREEDY) return get_valid_blocks(sbi, segno, true); @@ -770,7 +775,7 @@ static int f2fs_gc_pinned_control(struct inode *inode, int gc_type, */ int f2fs_get_victim(struct f2fs_sb_info *sbi, unsigned int *result, int gc_type, int type, char alloc_mode, - unsigned long long age) + unsigned long long age, bool one_time) { struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); struct sit_info *sm = SIT_I(sbi); @@ -787,6 +792,7 @@ int f2fs_get_victim(struct f2fs_sb_info *sbi, unsigned int *result, p.alloc_mode = alloc_mode; p.age = age; p.age_threshold = sbi->am.age_threshold; + p.one_time_gc = one_time; retry: select_policy(sbi, gc_type, type, &p); @@ -1698,13 +1704,14 @@ static int gc_data_segment(struct f2fs_sb_info *sbi, struct f2fs_summary *sum, } static int __get_victim(struct f2fs_sb_info *sbi, unsigned int *victim, - int gc_type) + int gc_type, bool one_time) { struct sit_info *sit_i = SIT_I(sbi); int ret; down_write(&sit_i->sentry_lock); - ret = f2fs_get_victim(sbi, victim, gc_type, NO_CHECK_TYPE, LFS, 0); + ret = f2fs_get_victim(sbi, victim, gc_type, NO_CHECK_TYPE, + LFS, 0, one_time); up_write(&sit_i->sentry_lock); return ret; } @@ -1908,7 +1915,7 @@ int f2fs_gc(struct f2fs_sb_info *sbi, struct f2fs_gc_control *gc_control) goto stop; } retry: - ret = __get_victim(sbi, &segno, gc_type); + ret = __get_victim(sbi, &segno, gc_type, gc_control->one_time); if (ret) { /* allow to search victim from sections has pinned data */ if (ret == -ENODA
Re: [f2fs-dev] [RFC PATCH] f2fs: don't set SBI_QUOTA_NEED_REPAIR flag if receive SIGKILL
On 2024/9/9 12:06, wangzijie wrote: On 2024/9/8 12:12, wangzijie wrote: From: Chao Yu via Linux-f2fs-devel On 2024/8/27 14:22, wangzijie wrote: Thread A -dquot_initialize -dqget -f2fs_dquot_acquire -v2_read_dquot -qtree_read_dquot -find_tree_dqentry -f2fs_quota_read -read_cache_page_gfp -do_read_cache_folio -fiemap_read_folio -folio_wait_locked_killable -receive SIGKILL : return -EINTR -set SBI_QUOTA_NEED_REPAIR -set SBI_QUOTA_NEED_REPAIR When calling read_cache_page_gfp in quota read, thread may receive SIGKILL and set SBI_QUOTA_NEED_REPAIR, should we set SBI_QUOTA_NEED_REPAIR in this error path? f2fs_quota_read() can be called in a lot of contexts, can we just ignore -EINTR for f2fs_dquot_initialize() case? Thanks, Yes, in many contexts f2fs_quota_read() can be called and may return -EINTR, we need to ignore this errno for more cases. If we need to do so, I will check it and resend patch. Or do you have other suggestions to avoid unnecessary SBI_QUOTA_NEED_REPAIR flag set? How about this? --- fs/f2fs/f2fs.h | 1 + fs/f2fs/inode.c | 3 +-- fs/f2fs/super.c | 17 + 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index dfed1974eda5..a1704a19dfe9 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -810,6 +810,7 @@ enum { FI_ATOMIC_DIRTIED, /* indicate atomic file is dirtied */ FI_ATOMIC_REPLACE, /* indicate atomic replace */ FI_OPENED_FILE, /* indicate file has been opened */ + FI_INIT_DQUOT, /* indicate it's initializing dquot */ FI_MAX, /* max flag, never be used */ }; diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c index 008f01348afa..b1dbaeda306f 100644 --- a/fs/f2fs/inode.c +++ b/fs/f2fs/inode.c @@ -827,8 +827,7 @@ void f2fs_evict_inode(struct inode *inode) err = f2fs_dquot_initialize(inode); if (err) { - if (err != -EINTR) - set_sbi_flag(sbi, SBI_QUOTA_NEED_REPAIR); + set_sbi_flag(sbi, SBI_QUOTA_NEED_REPAIR); err = 0; } diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 8e29aba4b7a4..e774bdf875b2 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -2644,8 +2644,11 @@ static ssize_t f2fs_quota_read(struct super_block *sb, int type, char *data, if (PTR_ERR(page) == -ENOMEM) { memalloc_retry_wait(GFP_NOFS); goto repeat; - } else if (PTR_ERR(page) != -EINTR) - set_sbi_flag(F2FS_SB(sb), SBI_QUOTA_NEED_REPAIR); + } else if (PTR_ERR(page) == -EINTR && + is_inode_flag_set(inode, FI_INIT_DQUOT)) { + return PTR_ERR(page); + } + set_sbi_flag(F2FS_SB(sb), SBI_QUOTA_NEED_REPAIR); return PTR_ERR(page); } @@ -2721,10 +2724,16 @@ static ssize_t f2fs_quota_write(struct super_block *sb, int type, int f2fs_dquot_initialize(struct inode *inode) { + int ret; + if (time_to_inject(F2FS_I_SB(inode), FAULT_DQUOT_INIT)) return -ESRCH; - return dquot_initialize(inode); + set_inode_flag(inode, FI_INIT_DQUOT); + ret = dquot_initialize(inode); + clear_inode_flag(inode, FI_INIT_DQUOT); + + return ret; } static struct dquot __rcu **f2fs_get_dquots(struct inode *inode) @@ -3064,7 +3073,7 @@ static int f2fs_dquot_acquire(struct dquot *dquot) f2fs_down_read(&sbi->quota_sem); ret = dquot_acquire(dquot); - if (ret < 0 && ret != -EINTR) + if (ret < 0) set_sbi_flag(sbi, SBI_QUOTA_NEED_REPAIR); f2fs_up_read(&sbi->quota_sem); return ret; -- 2.40.1 Hi, Chao If we dont't ignore -EINTR in f2fs_dquot_acquire(), we will still set SBI_QUOTA_NEED_REPAIR flag in f2fs_dquot_acquire() if f2fs_quota_read return -EINTR. I think we need more cases in addition to dquot initializing and I will check it again. Maybe we can cover this case w/ below diff? --- 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 e774bdf875b2..7fc970121a3f 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -3073,7 +3073,8 @@ static int f2fs_dquot_acquire(struct dquot *dquot) f2fs_down_read(&sbi->quota_sem); ret = dquot_acquire(dquot); - if (ret < 0) + if (ret < 0 && + (ret != -EINTR || !is_inode_flag_set(inode, FI_INIT_DQUOT))) set_sbi_flag(sbi, SBI_QUOTA_NEED_REPAIR); f2fs_up_read(&sbi->quota_sem); return ret; -- 2.40.1 T
Re: [f2fs-dev] [PATCH 2/7] f2fs: read summary blocks with the correct amount for migration_granularity
On 2024/9/7 4:23, Daeho Jeong wrote: On Thu, Sep 5, 2024 at 7:56 PM Chao Yu wrote: On 2024/8/30 5:52, Daeho Jeong wrote: From: Daeho Jeong Now we do readahead for a full section by not considering migration_granularity and it triggers unnecessary read. So, make it read with the correct amount. Signed-off-by: Daeho Jeong --- fs/f2fs/gc.c | 33 - 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index 46e3bc26b78a..b5d3fd40b17a 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c @@ -1708,24 +1708,33 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi, struct blk_plug plug; unsigned int segno = start_segno; unsigned int end_segno = start_segno + SEGS_PER_SEC(sbi); + unsigned int sec_end_segno; int seg_freed = 0, migrated = 0; unsigned char type = IS_DATASEG(get_seg_entry(sbi, segno)->type) ? SUM_TYPE_DATA : SUM_TYPE_NODE; unsigned char data_type = (type == SUM_TYPE_DATA) ? DATA : NODE; int submitted = 0; - if (__is_large_section(sbi)) - end_segno = rounddown(end_segno, SEGS_PER_SEC(sbi)); + if (__is_large_section(sbi)) { + sec_end_segno = rounddown(end_segno, SEGS_PER_SEC(sbi)); - /* - * zone-capacity can be less than zone-size in zoned devices, - * resulting in less than expected usable segments in the zone, - * calculate the end segno in the zone which can be garbage collected - */ - if (f2fs_sb_has_blkzoned(sbi)) - end_segno -= SEGS_PER_SEC(sbi) - + /* + * zone-capacity can be less than zone-size in zoned devices, + * resulting in less than expected usable segments in the zone, + * calculate the end segno in the zone which can be garbage + * collected + */ + if (f2fs_sb_has_blkzoned(sbi)) + sec_end_segno -= SEGS_PER_SEC(sbi) - f2fs_usable_segs_in_sec(sbi, segno); + if (gc_type == BG_GC) + end_segno = start_segno + sbi->migration_granularity; + + if (end_segno > sec_end_segno) + end_segno = sec_end_segno; + } + sanity_check_seg_type(sbi, get_seg_entry(sbi, segno)->type); /* readahead multi ssa blocks those have contiguous address */ @@ -1762,9 +1771,6 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi, if (get_valid_blocks(sbi, segno, false) == 0) goto freed; - if (gc_type == BG_GC && __is_large_section(sbi) && - migrated >= sbi->migration_granularity) It seems we change the logic from migrating "migration_granularity" segments which has valid blocks to scanning "migration_granularity" segments and try migrating valid blocks in those segments. IIUC, when background GC recycle sparse zone, it will take gc thread more round, it seems low efficient. How do you think of keeping previous implementation? I got your point. However, with zoned devices having 1GB sections, per every round, we should touch almost 2MB size of ssa block pages, even though we didn't need to do it. Maybe, we can introduce Yes, or can we: a) just read SSA block for segment which has valid blocks; b) limit readahead size to a threshold as you proposed. Thanks, another sysfs node like migration_window_limit, which can be set as double as migration_granuality by default, limiting the size of scanning. Thanks, - goto skip; if (!PageUptodate(sum_page) || unlikely(f2fs_cp_error(sbi))) goto skip; @@ -1803,7 +1809,8 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi, if (__is_large_section(sbi)) sbi->next_victim_seg[gc_type] = - (segno + 1 < end_segno) ? segno + 1 : NULL_SEGNO; + (segno + 1 < sec_end_segno) ? + segno + 1 : NULL_SEGNO; skip: f2fs_put_page(sum_page, 0); } ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
Re: [f2fs-dev] [RFC PATCH] f2fs: don't set SBI_QUOTA_NEED_REPAIR flag if receive SIGKILL
On 2024/9/8 12:12, wangzijie wrote: From: Chao Yu via Linux-f2fs-devel On 2024/8/27 14:22, wangzijie wrote: Thread A -dquot_initialize -dqget -f2fs_dquot_acquire -v2_read_dquot -qtree_read_dquot -find_tree_dqentry -f2fs_quota_read -read_cache_page_gfp -do_read_cache_folio -fiemap_read_folio -folio_wait_locked_killable -receive SIGKILL : return -EINTR -set SBI_QUOTA_NEED_REPAIR -set SBI_QUOTA_NEED_REPAIR When calling read_cache_page_gfp in quota read, thread may receive SIGKILL and set SBI_QUOTA_NEED_REPAIR, should we set SBI_QUOTA_NEED_REPAIR in this error path? f2fs_quota_read() can be called in a lot of contexts, can we just ignore -EINTR for f2fs_dquot_initialize() case? Thanks, Yes, in many contexts f2fs_quota_read() can be called and may return -EINTR, we need to ignore this errno for more cases. If we need to do so, I will check it and resend patch. Or do you have other suggestions to avoid unnecessary SBI_QUOTA_NEED_REPAIR flag set? How about this? --- fs/f2fs/f2fs.h | 1 + fs/f2fs/inode.c | 3 +-- fs/f2fs/super.c | 17 + 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index dfed1974eda5..a1704a19dfe9 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -810,6 +810,7 @@ enum { FI_ATOMIC_DIRTIED, /* indicate atomic file is dirtied */ FI_ATOMIC_REPLACE, /* indicate atomic replace */ FI_OPENED_FILE, /* indicate file has been opened */ + FI_INIT_DQUOT, /* indicate it's initializing dquot */ FI_MAX, /* max flag, never be used */ }; diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c index 008f01348afa..b1dbaeda306f 100644 --- a/fs/f2fs/inode.c +++ b/fs/f2fs/inode.c @@ -827,8 +827,7 @@ void f2fs_evict_inode(struct inode *inode) err = f2fs_dquot_initialize(inode); if (err) { - if (err != -EINTR) - set_sbi_flag(sbi, SBI_QUOTA_NEED_REPAIR); + set_sbi_flag(sbi, SBI_QUOTA_NEED_REPAIR); err = 0; } diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 8e29aba4b7a4..e774bdf875b2 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -2644,8 +2644,11 @@ static ssize_t f2fs_quota_read(struct super_block *sb, int type, char *data, if (PTR_ERR(page) == -ENOMEM) { memalloc_retry_wait(GFP_NOFS); goto repeat; - } else if (PTR_ERR(page) != -EINTR) - set_sbi_flag(F2FS_SB(sb), SBI_QUOTA_NEED_REPAIR); + } else if (PTR_ERR(page) == -EINTR && + is_inode_flag_set(inode, FI_INIT_DQUOT)) { + return PTR_ERR(page); + } + set_sbi_flag(F2FS_SB(sb), SBI_QUOTA_NEED_REPAIR); return PTR_ERR(page); } @@ -2721,10 +2724,16 @@ static ssize_t f2fs_quota_write(struct super_block *sb, int type, int f2fs_dquot_initialize(struct inode *inode) { + int ret; + if (time_to_inject(F2FS_I_SB(inode), FAULT_DQUOT_INIT)) return -ESRCH; - return dquot_initialize(inode); + set_inode_flag(inode, FI_INIT_DQUOT); + ret = dquot_initialize(inode); + clear_inode_flag(inode, FI_INIT_DQUOT); + + return ret; } static struct dquot __rcu **f2fs_get_dquots(struct inode *inode) @@ -3064,7 +3073,7 @@ static int f2fs_dquot_acquire(struct dquot *dquot) f2fs_down_read(&sbi->quota_sem); ret = dquot_acquire(dquot); - if (ret < 0 && ret != -EINTR) + if (ret < 0) set_sbi_flag(sbi, SBI_QUOTA_NEED_REPAIR); f2fs_up_read(&sbi->quota_sem); return ret; -- 2.40.1 Hi, Chao If we dont't ignore -EINTR in f2fs_dquot_acquire(), we will still set SBI_QUOTA_NEED_REPAIR flag in f2fs_dquot_acquire() if f2fs_quota_read return -EINTR. I think we need more cases in addition to dquot initializing and I will check it again. Maybe we can cover this case w/ below diff? --- 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 e774bdf875b2..7fc970121a3f 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -3073,7 +3073,8 @@ static int f2fs_dquot_acquire(struct dquot *dquot) f2fs_down_read(&sbi->quota_sem); ret = dquot_acquire(dquot); - if (ret < 0) + if (ret < 0 && + (ret != -EINTR || !is_inode_flag_set(inode, FI_INIT_DQUOT))) set_sbi_flag(sbi, SBI_QUOTA_NEED_REPAIR); f2fs_up_read(&sbi->quota_sem); return ret; -- 2.40.1 Thanks, Thank you for your suggestion! Thank you for revi
Re: [f2fs-dev] [PATCH] Revert "f2fs: stop allocating pinned sections if EAGAIN happens"
On 2024/9/6 16:31, Wu Bo wrote: On Tue, Feb 20, 2024 at 02:50:11PM +0800, Chao Yu wrote: On 2024/2/8 16:11, Wu Bo wrote: On 2024/2/5 11:54, Chao Yu wrote: How about calling f2fs_balance_fs() to double check and make sure there is enough free space for following allocation. if (has_not_enough_free_secs(sbi, 0, GET_SEC_FROM_SEG(sbi, overprovision_segments(sbi { f2fs_down_write(&sbi->gc_lock); stat_inc_gc_call_count(sbi, FOREGROUND); err = f2fs_gc(sbi, &gc_control); if (err == -EAGAIN) f2fs_balance_fs(sbi, true); if (err && err != -ENODATA) goto out_err; } Thanks, f2fs_balance_fs() here will not change procedure branch and may just trigger another GC. I'm afraid this is a bit redundant. Okay. I guess maybe Jaegeuk has concern which is the reason to commit 2e42b7f817ac ("f2fs: stop allocating pinned sections if EAGAIN happens"). Hi Jaegeuk, We occasionally receive user complaints about OTA failures caused by this issue. Please consider merging this patch. I'm fine w/ this patch, but one another quick fix will be triggering background GC via f2fs ioctl after fallocate() failure, once has_not_enough_free_secs(, ovp_segs) returns false, fallocate() will succeed. Reviewed-by: Chao Yu Thanks, Thanks Thanks, ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
Re: [f2fs-dev] [PATCH 6/7] f2fs: create gc_no_zoned_gc_percent and gc_boost_zoned_gc_percent
On 2024/8/30 5:52, Daeho Jeong wrote: From: Daeho Jeong Added control knobs for gc_no_zoned_gc_percent and gc_boost_zoned_gc_percent. Signed-off-by: Daeho Jeong Reviewed-by: Chao Yu Thanks, ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
Re: [f2fs-dev] [PATCH 5/7] f2fs: do FG_GC when GC boosting is required for zoned devices
On 2024/8/30 5:52, Daeho Jeong wrote: From: Daeho Jeong Under low free section count, we need to use FG_GC instead of BG_GC to recover free sections. Signed-off-by: Daeho Jeong --- fs/f2fs/f2fs.h | 1 + fs/f2fs/gc.c | 24 +--- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 5e4db3ba534a..ee1fafc65e95 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -1294,6 +1294,7 @@ struct f2fs_gc_control { bool should_migrate_blocks; /* should migrate blocks */ bool err_gc_skipped;/* return EAGAIN if GC skipped */ bool one_time; /* require one time GC in one migration unit */ In order to avoid unnecessary padding for alignment. Thanks, unsigned int nr_free_secs; /* # of free sections to do GC */ + bool one_time; /* require one time GC in one migration unit */ }; /* diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index d6d71aab94f3..37b47a8d95f1 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c @@ -81,6 +81,8 @@ static int gc_thread_func(void *data) continue; } + gc_control.one_time = false; + /* * [GC triggering condition] * 0. GC is not conducted currently. @@ -126,15 +128,19 @@ static int gc_thread_func(void *data) wait_ms = gc_th->max_sleep_time; } - if (need_to_boost_gc(sbi)) + if (need_to_boost_gc(sbi)) { decrease_sleep_time(gc_th, &wait_ms); - else + if (f2fs_sb_has_blkzoned(sbi)) + gc_control.one_time = true; + } else { increase_sleep_time(gc_th, &wait_ms); + } do_gc: stat_inc_gc_call_count(sbi, foreground ? FOREGROUND : BACKGROUND); - sync_mode = F2FS_OPTION(sbi).bggc_mode == BGGC_MODE_SYNC; + sync_mode = (F2FS_OPTION(sbi).bggc_mode == BGGC_MODE_SYNC) || + gc_control.one_time; /* foreground GC was been triggered via f2fs_balance_fs() */ if (foreground) @@ -1701,7 +1707,7 @@ static int __get_victim(struct f2fs_sb_info *sbi, unsigned int *victim, static int do_garbage_collect(struct f2fs_sb_info *sbi, unsigned int start_segno, struct gc_inode_list *gc_list, int gc_type, - bool force_migrate) + bool force_migrate, bool one_time) { struct page *sum_page; struct f2fs_summary_block *sum; @@ -1728,7 +1734,7 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi, sec_end_segno -= SEGS_PER_SEC(sbi) - f2fs_usable_segs_in_sec(sbi, segno); - if (gc_type == BG_GC) { + if (gc_type == BG_GC || one_time) { unsigned int migration_granularity = sbi->migration_granularity; @@ -1908,7 +1914,8 @@ int f2fs_gc(struct f2fs_sb_info *sbi, struct f2fs_gc_control *gc_control) } seg_freed = do_garbage_collect(sbi, segno, &gc_list, gc_type, - gc_control->should_migrate_blocks); + gc_control->should_migrate_blocks, + gc_control->one_time); if (seg_freed < 0) goto stop; @@ -1919,6 +1926,9 @@ int f2fs_gc(struct f2fs_sb_info *sbi, struct f2fs_gc_control *gc_control) total_sec_freed++; } + if (gc_control->one_time) + goto stop; + if (gc_type == FG_GC) { sbi->cur_victim_sec = NULL_SEGNO; @@ -2044,7 +2054,7 @@ int f2fs_gc_range(struct f2fs_sb_info *sbi, }; do_garbage_collect(sbi, segno, &gc_list, FG_GC, - dry_run_sections == 0); + dry_run_sections == 0, false); put_gc_inode(&gc_list); if (!dry_run && get_valid_blocks(sbi, segno, true)) ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
[f2fs-dev] [PATCH] f2fs: get rid of online repaire on corrupted directory
syzbot reports a f2fs bug as below: kernel BUG at fs/f2fs/inode.c:896! RIP: 0010:f2fs_evict_inode+0x1598/0x15c0 fs/f2fs/inode.c:896 Call Trace: evict+0x532/0x950 fs/inode.c:704 dispose_list fs/inode.c:747 [inline] evict_inodes+0x5f9/0x690 fs/inode.c:797 generic_shutdown_super+0x9d/0x2d0 fs/super.c:627 kill_block_super+0x44/0x90 fs/super.c:1696 kill_f2fs_super+0x344/0x690 fs/f2fs/super.c:4898 deactivate_locked_super+0xc4/0x130 fs/super.c:473 cleanup_mnt+0x41f/0x4b0 fs/namespace.c:1373 task_work_run+0x24f/0x310 kernel/task_work.c:228 ptrace_notify+0x2d2/0x380 kernel/signal.c:2402 ptrace_report_syscall include/linux/ptrace.h:415 [inline] ptrace_report_syscall_exit include/linux/ptrace.h:477 [inline] syscall_exit_work+0xc6/0x190 kernel/entry/common.c:173 syscall_exit_to_user_mode_prepare kernel/entry/common.c:200 [inline] __syscall_exit_to_user_mode_work kernel/entry/common.c:205 [inline] syscall_exit_to_user_mode+0x279/0x370 kernel/entry/common.c:218 do_syscall_64+0x100/0x230 arch/x86/entry/common.c:89 entry_SYSCALL_64_after_hwframe+0x77/0x7f RIP: 0010:f2fs_evict_inode+0x1598/0x15c0 fs/f2fs/inode.c:896 Online repaire on corrupted directory in f2fs_lookup() can generate dirty data/meta while racing w/ readonly remount, it may leave dirty inode after filesystem becomes readonly, however, checkpoint() will skips flushing dirty inode in a state of readonly mode, result in above panic. Let's get rid of online repaire in f2fs_lookup(), and leave the work to fsck.f2fs. Fixes: 510022a85839 ("f2fs: add F2FS_INLINE_DOTS to recover missing dot dentries") Reported-by: syzbot+ebea2790904673d7c...@syzkaller.appspotmail.com Closes: https://lore.kernel.org/all/a7b20f061ff2d...@google.com Signed-off-by: Chao Yu --- fs/f2fs/f2fs.h | 11 --- fs/f2fs/namei.c | 68 - include/linux/f2fs_fs.h | 2 +- 3 files changed, 1 insertion(+), 80 deletions(-) diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index f280b757c590..729b264b3bab 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -790,7 +790,6 @@ enum { FI_NEED_IPU,/* used for ipu per file */ FI_ATOMIC_FILE, /* indicate atomic file */ FI_DATA_EXIST, /* indicate data exists */ - FI_INLINE_DOTS, /* indicate inline dot dentries */ FI_SKIP_WRITES, /* should skip data page writeback */ FI_OPU_WRITE, /* used for opu per file */ FI_DIRTY_FILE, /* indicate regular/symlink has dirty pages */ @@ -3082,7 +3081,6 @@ static inline void __mark_inode_dirty_flag(struct inode *inode, return; fallthrough; case FI_DATA_EXIST: - case FI_INLINE_DOTS: case FI_PIN_FILE: case FI_COMPRESS_RELEASED: f2fs_mark_inode_dirty_sync(inode, true); @@ -3206,8 +3204,6 @@ static inline void get_inline_info(struct inode *inode, struct f2fs_inode *ri) set_bit(FI_INLINE_DENTRY, fi->flags); if (ri->i_inline & F2FS_DATA_EXIST) set_bit(FI_DATA_EXIST, fi->flags); - if (ri->i_inline & F2FS_INLINE_DOTS) - set_bit(FI_INLINE_DOTS, fi->flags); if (ri->i_inline & F2FS_EXTRA_ATTR) set_bit(FI_EXTRA_ATTR, fi->flags); if (ri->i_inline & F2FS_PIN_FILE) @@ -3228,8 +3224,6 @@ static inline void set_raw_inline(struct inode *inode, struct f2fs_inode *ri) ri->i_inline |= F2FS_INLINE_DENTRY; if (is_inode_flag_set(inode, FI_DATA_EXIST)) ri->i_inline |= F2FS_DATA_EXIST; - if (is_inode_flag_set(inode, FI_INLINE_DOTS)) - ri->i_inline |= F2FS_INLINE_DOTS; if (is_inode_flag_set(inode, FI_EXTRA_ATTR)) ri->i_inline |= F2FS_EXTRA_ATTR; if (is_inode_flag_set(inode, FI_PIN_FILE)) @@ -3310,11 +3304,6 @@ static inline int f2fs_exist_data(struct inode *inode) return is_inode_flag_set(inode, FI_DATA_EXIST); } -static inline int f2fs_has_inline_dots(struct inode *inode) -{ - return is_inode_flag_set(inode, FI_INLINE_DOTS); -} - static inline int f2fs_is_mmap_file(struct inode *inode) { return is_inode_flag_set(inode, FI_MMAP_FILE); diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c index 38b4750475db..57d46e1439de 100644 --- a/fs/f2fs/namei.c +++ b/fs/f2fs/namei.c @@ -457,62 +457,6 @@ struct dentry *f2fs_get_parent(struct dentry *child) return d_obtain_alias(f2fs_iget(child->d_sb, ino)); } -static int __recover_dot_dentries(struct inode *dir, nid_t pino) -{ - struct f2fs_sb_info *sbi = F2FS_I_SB(dir); - struct qstr dot = QSTR_INIT(".", 1); - struct f2fs_dir_entry *de; - struct page *page; - int err = 0; - - if (f2fs_readonly(sbi->sb)) { - f2fs_info(sbi, "skip recovering inline_dots inode
Re: [f2fs-dev] [PATCH 4/7] f2fs: increase BG GC migration granularity when boosted for zoned devices
On 2024/8/30 5:52, Daeho Jeong wrote: From: Daeho Jeong Need bigger BG GC migration granularity when free section is running low. Signed-off-by: Daeho Jeong Reviewed-by: Chao Yu Thanks, ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
Re: [f2fs-dev] [PATCH 3/7] f2fs: add reserved_segments sysfs node
On 2024/8/30 5:52, Daeho Jeong wrote: From: Daeho Jeong For the fine tuning of GC behavior, add reserved_segments sysfs node. Signed-off-by: Daeho Jeong Reviewed-by: Chao Yu Thanks, ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
Re: [f2fs-dev] [PATCH 2/7] f2fs: read summary blocks with the correct amount for migration_granularity
On 2024/8/30 5:52, Daeho Jeong wrote: From: Daeho Jeong Now we do readahead for a full section by not considering migration_granularity and it triggers unnecessary read. So, make it read with the correct amount. Signed-off-by: Daeho Jeong --- fs/f2fs/gc.c | 33 - 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index 46e3bc26b78a..b5d3fd40b17a 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c @@ -1708,24 +1708,33 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi, struct blk_plug plug; unsigned int segno = start_segno; unsigned int end_segno = start_segno + SEGS_PER_SEC(sbi); + unsigned int sec_end_segno; int seg_freed = 0, migrated = 0; unsigned char type = IS_DATASEG(get_seg_entry(sbi, segno)->type) ? SUM_TYPE_DATA : SUM_TYPE_NODE; unsigned char data_type = (type == SUM_TYPE_DATA) ? DATA : NODE; int submitted = 0; - if (__is_large_section(sbi)) - end_segno = rounddown(end_segno, SEGS_PER_SEC(sbi)); + if (__is_large_section(sbi)) { + sec_end_segno = rounddown(end_segno, SEGS_PER_SEC(sbi)); - /* -* zone-capacity can be less than zone-size in zoned devices, -* resulting in less than expected usable segments in the zone, -* calculate the end segno in the zone which can be garbage collected -*/ - if (f2fs_sb_has_blkzoned(sbi)) - end_segno -= SEGS_PER_SEC(sbi) - + /* +* zone-capacity can be less than zone-size in zoned devices, +* resulting in less than expected usable segments in the zone, +* calculate the end segno in the zone which can be garbage +* collected +*/ + if (f2fs_sb_has_blkzoned(sbi)) + sec_end_segno -= SEGS_PER_SEC(sbi) - f2fs_usable_segs_in_sec(sbi, segno); + if (gc_type == BG_GC) + end_segno = start_segno + sbi->migration_granularity; + + if (end_segno > sec_end_segno) + end_segno = sec_end_segno; + } + sanity_check_seg_type(sbi, get_seg_entry(sbi, segno)->type); /* readahead multi ssa blocks those have contiguous address */ @@ -1762,9 +1771,6 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi, if (get_valid_blocks(sbi, segno, false) == 0) goto freed; - if (gc_type == BG_GC && __is_large_section(sbi) && - migrated >= sbi->migration_granularity) It seems we change the logic from migrating "migration_granularity" segments which has valid blocks to scanning "migration_granularity" segments and try migrating valid blocks in those segments. IIUC, when background GC recycle sparse zone, it will take gc thread more round, it seems low efficient. How do you think of keeping previous implementation? Thanks, - goto skip; if (!PageUptodate(sum_page) || unlikely(f2fs_cp_error(sbi))) goto skip; @@ -1803,7 +1809,8 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi, if (__is_large_section(sbi)) sbi->next_victim_seg[gc_type] = - (segno + 1 < end_segno) ? segno + 1 : NULL_SEGNO; + (segno + 1 < sec_end_segno) ? + segno + 1 : NULL_SEGNO; skip: f2fs_put_page(sum_page, 0); } ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
Re: [f2fs-dev] [PATCH 1/7] f2fs: make BG GC more aggressive for zoned devices
On 2024/8/30 5:52, Daeho Jeong wrote: From: Daeho Jeong Since we don't have any GC on device side for zoned devices, need more aggressive BG GC. So, tune the parameters for that. Signed-off-by: Daeho Jeong Reviewed-by: Chao Yu Thanks, ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
Re: [f2fs-dev] [PATCH] f2fs-tools: fix wrong endian conversion related to i_flags
On 2024/9/6 5:20, Daeho Jeong wrote: From: Daeho Jeong Fixed wrong endian conversions related to i_flags. Signed-off-by: Daeho Jeong Reviewed-by: Chao Yu Thanks, ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
Re: [f2fs-dev] [PATCH v2] f2fs: avoid unused block when dio write in LFS mode
On 2024/9/5 13:24, Daejun Park wrote: This patch addresses the problem that when using LFS mode, unused blocks may occur in f2fs_map_blocks() during block allocation for dio writes. If a new section is allocated during block allocation, it will not be included in the map struct by map_is_mergeable() if the LBA of the allocated block is not contiguous. However, the block already allocated in this process will remain unused due to the LFS mode. This patch avoids the possibility of unused blocks by escaping f2fs_map_blocks() when allocating the last block in a section. Signed-off-by: Daejun Park Reviewed-by: Chao Yu Thanks, ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
Re: [f2fs-dev] [PATCH v2] f2fs-tools: add write hint support
On 2024/9/4 9:12, Daejun Park wrote: This patch enables support for write hints by segment type. Signed-off-by: Daejun Park Reviewed-by: Chao Yu Thanks, ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
Re: [f2fs-dev] [syzbot] [f2fs?] possible deadlock in f2fs_release_file (2)
#syz invalid Becuase commit "f2fs: atomic: fix to not allow GC to pollute atomic_file" has been dropped from linux-next git repo. On 2024/8/16 17:16, syzbot wrote: Hello, syzbot found the following issue on: HEAD commit:9e6869691724 Add linux-next specific files for 20240812 git tree: linux-next console output: https://syzkaller.appspot.com/x/log.txt?x=1203caf398 kernel config: https://syzkaller.appspot.com/x/.config?x=61ba6f3b22ee5467 dashboard link: https://syzkaller.appspot.com/bug?extid=9aff3b6811f0a00daffa compiler: Debian clang version 15.0.6, GNU ld (GNU Binutils for Debian) 2.40 Unfortunately, I don't have any reproducer for this issue yet. Downloadable assets: disk image: https://storage.googleapis.com/syzbot-assets/f1b086192f50/disk-9e686969.raw.xz vmlinux: https://storage.googleapis.com/syzbot-assets/b457920fb52e/vmlinux-9e686969.xz kernel image: https://storage.googleapis.com/syzbot-assets/e63ba9cce98a/bzImage-9e686969.xz IMPORTANT: if you fix the issue, please add the following tag to the commit: Reported-by: syzbot+9aff3b6811f0a00da...@syzkaller.appspotmail.com F2FS-fs (loop0): Try to recover 1th superblock, ret: 0 F2FS-fs (loop0): Mounted with checkpoint version = 48b305e5 syz.0.98: attempt to access beyond end of device loop0: rw=2049, sector=45096, nr_sectors = 8 limit=40427 == WARNING: possible circular locking dependency detected 6.11.0-rc3-next-20240812-syzkaller #0 Not tainted -- syz.0.98/5917 is trying to acquire lock: 88807896ad30 (&sb->s_type->i_mutex_key#26){}-{3:3}, at: inode_lock include/linux/fs.h:799 [inline] 88807896ad30 (&sb->s_type->i_mutex_key#26){}-{3:3}, at: f2fs_release_file+0x9b/0x100 fs/f2fs/file.c:1940 but task is already holding lock: 88807896b308 (&fi->i_gc_rwsem[WRITE]){}-{3:3}, at: f2fs_down_write fs/f2fs/f2fs.h:2196 [inline] 88807896b308 (&fi->i_gc_rwsem[WRITE]){}-{3:3}, at: f2fs_commit_atomic_write+0x105/0x1510 fs/f2fs/segment.c:388 which lock already depends on the new lock. the existing dependency chain (in reverse order) is: -> #1 (&fi->i_gc_rwsem[WRITE]){}-{3:3}: lock_acquire+0x1ed/0x550 kernel/locking/lockdep.c:5762 down_write+0x99/0x220 kernel/locking/rwsem.c:1579 f2fs_down_write fs/f2fs/f2fs.h:2196 [inline] f2fs_setattr+0xb80/0x12d0 fs/f2fs/file.c:1060 notify_change+0xb9d/0xe70 fs/attr.c:535 do_truncate+0x220/0x310 fs/open.c:65 handle_truncate fs/namei.c:3395 [inline] do_open fs/namei.c:3745 [inline] path_openat+0x2ced/0x3470 fs/namei.c:3900 do_filp_open+0x235/0x490 fs/namei.c:3927 do_sys_openat2+0x13e/0x1d0 fs/open.c:1416 do_sys_open fs/open.c:1431 [inline] __do_sys_creat fs/open.c:1507 [inline] __se_sys_creat fs/open.c:1501 [inline] __x64_sys_creat+0x123/0x170 fs/open.c:1501 do_syscall_x64 arch/x86/entry/common.c:52 [inline] do_syscall_64+0xf3/0x230 arch/x86/entry/common.c:83 entry_SYSCALL_64_after_hwframe+0x77/0x7f -> #0 (&sb->s_type->i_mutex_key#26){}-{3:3}: check_prev_add kernel/locking/lockdep.c:3136 [inline] check_prevs_add kernel/locking/lockdep.c:3255 [inline] validate_chain+0x18e0/0x5900 kernel/locking/lockdep.c:3871 __lock_acquire+0x137a/0x2040 kernel/locking/lockdep.c:5145 lock_acquire+0x1ed/0x550 kernel/locking/lockdep.c:5762 down_write+0x99/0x220 kernel/locking/rwsem.c:1579 inode_lock include/linux/fs.h:799 [inline] f2fs_release_file+0x9b/0x100 fs/f2fs/file.c:1940 __fput+0x24a/0x8a0 fs/file_table.c:425 task_work_run+0x24f/0x310 kernel/task_work.c:228 get_signal+0x16ad/0x1810 kernel/signal.c:2690 arch_do_signal_or_restart+0x96/0x830 arch/x86/kernel/signal.c:337 exit_to_user_mode_loop kernel/entry/common.c:111 [inline] exit_to_user_mode_prepare include/linux/entry-common.h:328 [inline] __syscall_exit_to_user_mode_work kernel/entry/common.c:207 [inline] syscall_exit_to_user_mode+0xc9/0x370 kernel/entry/common.c:218 do_syscall_64+0x100/0x230 arch/x86/entry/common.c:89 entry_SYSCALL_64_after_hwframe+0x77/0x7f other info that might help us debug this: Possible unsafe locking scenario: CPU0CPU1 lock(&fi->i_gc_rwsem[WRITE]); lock(&sb->s_type->i_mutex_key#26); lock(&fi->i_gc_rwsem[WRITE]); lock(&sb->s_type->i_mutex_key#26); *** DEADLOCK *** 1 lock held by syz.0.98/5917: #0: 88807896b308 (&fi->i_gc_rwsem[WRITE]){}-{3:3}, at: f2fs_down_write fs/f2fs/f2fs.h:2196 [inline] #0: 88807896b308 (&fi->i_gc_rwsem[WRITE]){}-{3:3}, at: f2fs_commit_atomic_write+0x105/0x1510 fs/f2fs/segment.c:388 stack backtrace: CPU: 0 UID: 0 PID: 59
Re: [f2fs-dev] [syzbot] [f2fs?] WARNING: lock held when returning to user space in f2fs_commit_atomic_write
#syz invalid Becuase commit "f2fs: atomic: fix to not allow GC to pollute atomic_file" has been dropped from linux-next git repo. On 2024/8/14 4:49, syzbot wrote: Hello, syzbot found the following issue on: HEAD commit:9e6869691724 Add linux-next specific files for 20240812 git tree: linux-next console+strace: https://syzkaller.appspot.com/x/log.txt?x=177ea68d98 kernel config: https://syzkaller.appspot.com/x/.config?x=61ba6f3b22ee5467 dashboard link: https://syzkaller.appspot.com/bug?extid=78ff2855f26377625419 compiler: Debian clang version 15.0.6, GNU ld (GNU Binutils for Debian) 2.40 syz repro: https://syzkaller.appspot.com/x/repro.syz?x=13deecd598 C reproducer: https://syzkaller.appspot.com/x/repro.c?x=12c1fdd998 Downloadable assets: disk image: https://storage.googleapis.com/syzbot-assets/f1b086192f50/disk-9e686969.raw.xz vmlinux: https://storage.googleapis.com/syzbot-assets/b457920fb52e/vmlinux-9e686969.xz kernel image: https://storage.googleapis.com/syzbot-assets/e63ba9cce98a/bzImage-9e686969.xz mounted in repro: https://storage.googleapis.com/syzbot-assets/a0c7f05fa485/mount_0.gz The issue was bisected to: commit 7566a155c666dd23b413a002a50cd9ae7b95f053 Author: Chao Yu Date: Tue Jun 25 03:13:49 2024 + f2fs: atomic: fix to not allow GC to pollute atomic_file bisection log: https://syzkaller.appspot.com/x/bisect.txt?x=1255068d98 final oops: https://syzkaller.appspot.com/x/report.txt?x=1155068d98 console output: https://syzkaller.appspot.com/x/log.txt?x=1655068d98 IMPORTANT: if you fix the issue, please add the following tag to the commit: Reported-by: syzbot+78ff2855f26377625...@syzkaller.appspotmail.com Fixes: 7566a155c666 ("f2fs: atomic: fix to not allow GC to pollute atomic_file") F2FS-fs (loop0): Found nat_bits in checkpoint F2FS-fs (loop0): Try to recover 1th superblock, ret: 0 F2FS-fs (loop0): Mounted with checkpoint version = 48b305e4 syz-executor306: attempt to access beyond end of device loop0: rw=2049, sector=45096, nr_sectors = 64 limit=40427 WARNING: lock held when returning to user space! 6.11.0-rc3-next-20240812-syzkaller #0 Not tainted syz-executor306/5229 is leaving the kernel with locks still held! 1 lock held by syz-executor306/5229: #0: 8880473a18b0 (&fi->i_gc_rwsem[WRITE]){+.+.}-{3:3}, at: f2fs_down_write fs/f2fs/f2fs.h:2196 [inline] #0: 8880473a18b0 (&fi->i_gc_rwsem[WRITE]){+.+.}-{3:3}, at: f2fs_commit_atomic_write+0x105/0x1510 fs/f2fs/segment.c:388 --- 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 syzkal...@googlegroups.com. 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 ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
Re: [f2fs-dev] [syzbot] [f2fs?] WARNING: lock held when returning to user space in f2fs_ioc_start_atomic_write
#syz fix: f2fs: atomic: fix to forbid dio in atomic_file On 2024/8/14 19:51, syzbot wrote: Hello, syzbot found the following issue on: HEAD commit:9e6869691724 Add linux-next specific files for 20240812 git tree: linux-next console+strace: https://syzkaller.appspot.com/x/log.txt?x=1431e40598 kernel config: https://syzkaller.appspot.com/x/.config?x=61ba6f3b22ee5467 dashboard link: https://syzkaller.appspot.com/bug?extid=733300ca0a9baca7e245 compiler: Debian clang version 15.0.6, GNU ld (GNU Binutils for Debian) 2.40 syz repro: https://syzkaller.appspot.com/x/repro.syz?x=120ed77d98 C reproducer: https://syzkaller.appspot.com/x/repro.c?x=130e0ef398 Downloadable assets: disk image: https://storage.googleapis.com/syzbot-assets/f1b086192f50/disk-9e686969.raw.xz vmlinux: https://storage.googleapis.com/syzbot-assets/b457920fb52e/vmlinux-9e686969.xz kernel image: https://storage.googleapis.com/syzbot-assets/e63ba9cce98a/bzImage-9e686969.xz mounted in repro: https://storage.googleapis.com/syzbot-assets/08b48c782593/mount_0.gz The issue was bisected to: commit 374a8881ce4ccf787f5381a39f825cb17a3f6b14 Author: Chao Yu Date: Tue Jun 25 03:13:51 2024 + f2fs: atomic: fix to forbid dio in atomic_file bisection log: https://syzkaller.appspot.com/x/bisect.txt?x=1074142998 final oops: https://syzkaller.appspot.com/x/report.txt?x=1274142998 console output: https://syzkaller.appspot.com/x/log.txt?x=1474142998 IMPORTANT: if you fix the issue, please add the following tag to the commit: Reported-by: syzbot+733300ca0a9baca7e...@syzkaller.appspotmail.com Fixes: 374a8881ce4c ("f2fs: atomic: fix to forbid dio in atomic_file") F2FS-fs (loop0): Found nat_bits in checkpoint F2FS-fs (loop0): Mounted with checkpoint version = 48b305e5 syz-executor312: attempt to access beyond end of device loop0: rw=10241, sector=45096, nr_sectors = 8 limit=40427 WARNING: lock held when returning to user space! 6.11.0-rc3-next-20240812-syzkaller #0 Not tainted syz-executor312/5227 is leaving the kernel with locks still held! 1 lock held by syz-executor312/5227: #0: 8880695aa0e0 (&fi->i_gc_rwsem[READ]){+.+.}-{3:3}, at: f2fs_down_write fs/f2fs/f2fs.h:2196 [inline] #0: 8880695aa0e0 (&fi->i_gc_rwsem[READ]){+.+.}-{3:3}, at: f2fs_ioc_start_atomic_write+0x2ed/0xac0 fs/f2fs/file.c:2163 --- 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 syzkal...@googlegroups.com. 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 ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
Re: [f2fs-dev] [syzbot] [f2fs?] WARNING: lock held when returning
#syz invalid Becuase commit "f2fs: atomic: fix to not allow GC to pollute atomic_file" has been dropped. On 2024/8/17 8:27, syzbot wrote: Hello, syzbot found the following issue on: HEAD commit:9e6869691724 Add linux-next specific files for 20240812 git tree: linux-next console output: https://syzkaller.appspot.com/x/log.txt?x=177f4b7d98 kernel config: https://syzkaller.appspot.com/x/.config?x=61ba6f3b22ee5467 dashboard link: https://syzkaller.appspot.com/bug?extid=16c06d2c27b585e352f8 compiler: Debian clang version 15.0.6, GNU ld (GNU Binutils for Debian) 2.40 syz repro: https://syzkaller.appspot.com/x/repro.syz?x=14e46af598 C reproducer: https://syzkaller.appspot.com/x/repro.c?x=158ea2ed98 Downloadable assets: disk image: https://storage.googleapis.com/syzbot-assets/f1b086192f50/disk-9e686969.raw.xz vmlinux: https://storage.googleapis.com/syzbot-assets/b457920fb52e/vmlinux-9e686969.xz kernel image: https://storage.googleapis.com/syzbot-assets/e63ba9cce98a/bzImage-9e686969.xz mounted in repro: https://storage.googleapis.com/syzbot-assets/b1fc2a52ac10/mount_0.gz The issue was bisected to: commit 7566a155c666dd23b413a002a50cd9ae7b95f053 Author: Chao Yu Date: Tue Jun 25 03:13:49 2024 + f2fs: atomic: fix to not allow GC to pollute atomic_file bisection log: https://syzkaller.appspot.com/x/bisect.txt?x=1416b18398 final oops: https://syzkaller.appspot.com/x/report.txt?x=1616b18398 console output: https://syzkaller.appspot.com/x/log.txt?x=1216b18398 IMPORTANT: if you fix the issue, please add the following tag to the commit: Reported-by: syzbot+16c06d2c27b585e35...@syzkaller.appspotmail.com Fixes: 7566a155c666 ("f2fs: atomic: fix to not allow GC to pollute atomic_file") F2FS-fs (loop0): Mounted with checkpoint version = 48b305e5 syz-executor161: attempt to access beyond end of device loop0: rw=2049, sector=45096, nr_sectors = 8 limit=40427 WARNING: lock held when returning --- 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 syzkal...@googlegroups.com. 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 ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
Re: [f2fs-dev] [PATCH] mkfs.f2fs: use correct endian conversion for writing lpf inode
On 2024/9/4 1:31, Daeho Jeong wrote: From: Daeho Jeong The conversion between cpu and little endian is incorrect. Signed-off-by: Daeho Jeong Reviewed-by: Chao Yu Thanks, ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
Re: [f2fs-dev] [PATCH] f2fs: prevent atomic file from being dirtied before commit
On 2024/9/4 22:56, Daeho Jeong wrote: On Tue, Sep 3, 2024 at 8:35 PM Chao Yu wrote: On 2024/9/4 10:52, Daeho Jeong wrote: On Tue, Sep 3, 2024 at 7:26 PM Chao Yu wrote: On 2024/9/4 1:07, Daeho Jeong wrote: On Mon, Sep 2, 2024 at 3:08 AM Chao Yu wrote: On 2024/8/27 4:23, Daeho Jeong wrote: From: Daeho Jeong Keep atomic file clean while updating and make it dirtied during commit in order to avoid unnecessary and excessive inode updates in the previous fix. Fixes: 4bf78322346f ("f2fs: mark inode dirty for FI_ATOMIC_COMMITTED flag") Signed-off-by: Daeho Jeong --- fs/f2fs/f2fs.h| 3 +-- fs/f2fs/inode.c | 10 ++ fs/f2fs/segment.c | 10 -- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 465b2fd50c70..5a7f6fa8b585 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -801,7 +801,7 @@ enum { FI_COMPRESS_RELEASED, /* compressed blocks were released */ FI_ALIGNED_WRITE, /* enable aligned write */ FI_COW_FILE,/* indicate COW file */ - FI_ATOMIC_COMMITTED,/* indicate atomic commit completed except disk sync */ + FI_ATOMIC_DIRTIED, /* indicate atomic file is dirtied */ FI_ATOMIC_REPLACE, /* indicate atomic replace */ FI_OPENED_FILE, /* indicate file has been opened */ FI_MAX, /* max flag, never be used */ @@ -3042,7 +3042,6 @@ static inline void __mark_inode_dirty_flag(struct inode *inode, case FI_INLINE_DOTS: case FI_PIN_FILE: case FI_COMPRESS_RELEASED: - case FI_ATOMIC_COMMITTED: f2fs_mark_inode_dirty_sync(inode, true); } } diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c index 1eb250c6b392..5dd3e55d2be2 100644 --- a/fs/f2fs/inode.c +++ b/fs/f2fs/inode.c @@ -35,6 +35,11 @@ void f2fs_mark_inode_dirty_sync(struct inode *inode, bool sync) if (f2fs_inode_dirtied(inode, sync)) It will return directly here if inode was dirtied, so it may missed to set FI_ATOMIC_DIRTIED flag? Is it possible for it to be already dirty, since we already made it clean with f2fs_write_inode() when we started the atomic write? Some ioctl interfaces may race w/ atomic write? e.g. set_pin_file won't check atomic_file status, and may dirty inode after we started atomic write, so we'd better detect such race condition and break ioctl to avoid ruin atomic write? and maybe we can add f2fs_bug_on() in f2fs_mark_inode_dirty_sync() to detect any other missing cases? How about exchanging the positions of f2fs_write_inode() and set_inode_flag() in f2fs_ioc_start_atomic_write()? ... f2fs_write_inode(inode, NULL); stat_inc_atomic_inode(inode); set_inode_flag(inode, FI_ATOMIC_FILE); ... Oh, I'm not sure I've got your point, after exchanging we still may suffer below race condition, right? - f2fs_ioc_start_atomic_write - set_inode_flag(inode, FI_ATOMIC_FILE) - f2fs_write_inode(inode, NULL) - f2fs_ioc_set_pin_file - set_inode_flag(inode, FI_PIN_FILE) - __mark_inode_dirty_flag() => This attempt will be blocked by the below condition. + if (f2fs_is_atomic_file(inode)) { + set_inode_flag(inode, FI_ATOMIC_DIRTIED); + return; + } Oh, yes, FI_ATOMIC_DIRTIED will be tagged once inode becomes dirty. Thanks, Plz, refer to the above comment. - f2fs_ioc_commit_atomic_write So that I proposed a fix for this: https://lore.kernel.org/linux-f2fs-devel/20240904032047.1264706-1-c...@kernel.org Thanks, Thanks, Thanks, return; + if (f2fs_is_atomic_file(inode)) { + set_inode_flag(inode, FI_ATOMIC_DIRTIED); + return; + } + mark_inode_dirty_sync(inode); } @@ -653,10 +658,7 @@ void f2fs_update_inode(struct inode *inode, struct page *node_page) ri->i_gid = cpu_to_le32(i_gid_read(inode)); ri->i_links = cpu_to_le32(inode->i_nlink); ri->i_blocks = cpu_to_le64(SECTOR_TO_BLOCK(inode->i_blocks) + 1); - - if (!f2fs_is_atomic_file(inode) || - is_inode_flag_set(inode, FI_ATOMIC_COMMITTED)) - ri->i_size = cpu_to_le64(i_size_read(inode)); + ri->i_size = cpu_to_le64(i_size_read(inode)); if (et) { read_lock(&et->lock); diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index 78c3198a6308..2b5391b229a8 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -196,9 +196,12 @@ void f2fs_abort_atomic_write(struct inode *inode, bool clean) truncate_inode_pages_final(inode->i_mapping); release_atomic_write_cnt(inode); - clear_inode_flag(inode, FI_ATOMI
Re: [f2fs-dev] [PATCH v2] f2fs: Do not check the FI_DIRTY_INODE flag when umounting a ro fs.
On 2024/9/4 5:20, Jaegeuk Kim wrote: On 09/03, Chao Yu wrote: On 2024/9/2 21:01, Julian Sun wrote: On Mon, 2024-09-02 at 16:13 +0800, Chao Yu wrote: On 2024/8/29 0:54, Julian Sun wrote: Hi, all. Recently syzbot reported a bug as following: kernel BUG at fs/f2fs/inode.c:896! CPU: 1 UID: 0 PID: 5217 Comm: syz-executor605 Not tainted 6.11.0-rc4-syzkaller-00033-g872cf28b8df9 #0 RIP: 0010:f2fs_evict_inode+0x1598/0x15c0 fs/f2fs/inode.c:896 Call Trace: evict+0x532/0x950 fs/inode.c:704 dispose_list fs/inode.c:747 [inline] evict_inodes+0x5f9/0x690 fs/inode.c:797 generic_shutdown_super+0x9d/0x2d0 fs/super.c:627 kill_block_super+0x44/0x90 fs/super.c:1696 kill_f2fs_super+0x344/0x690 fs/f2fs/super.c:4898 deactivate_locked_super+0xc4/0x130 fs/super.c:473 cleanup_mnt+0x41f/0x4b0 fs/namespace.c:1373 task_work_run+0x24f/0x310 kernel/task_work.c:228 ptrace_notify+0x2d2/0x380 kernel/signal.c:2402 ptrace_report_syscall include/linux/ptrace.h:415 [inline] ptrace_report_syscall_exit include/linux/ptrace.h:477 [inline] syscall_exit_work+0xc6/0x190 kernel/entry/common.c:173 syscall_exit_to_user_mode_prepare kernel/entry/common.c:200 [inline] __syscall_exit_to_user_mode_work kernel/entry/common.c:205 [inline] syscall_exit_to_user_mode+0x279/0x370 kernel/entry/common.c:218 do_syscall_64+0x100/0x230 arch/x86/entry/common.c:89 entry_SYSCALL_64_after_hwframe+0x77/0x7f The syzbot constructed the following scenario: concurrently creating directories and setting the file system to read-only. In this case, while f2fs was making dir, the filesystem switched to readonly, and when it tried to clear the dirty flag, it triggered Go back to the root cause, I have no idea why it can leave dirty inode while mkdir races w/ readonly remount, due to the two operations should be exclusive, IIUC. Wait, we can think of writable disk mounted as fs-readonly. In that case, IIRC, we allow to recover files/data by roll-forward and so on, which can We will remove SB_RDONLY flag from sb->s_flags intentionally before recovery, so that following write_checkpoint() or sync_filesystem() won't skip flushing due to sb is readonly. static bool f2fs_recover_quota_begin(struct f2fs_sb_info *sbi) { ... if (readonly) { sbi->sb->s_flags &= ~SB_RDONLY; set_sbi_flag(sbi, SBI_IS_WRITABLE); } ... } make some dirty inodes. Can we check if there's any missing path which does not flush dirty inode? I guess the root cause of this issue is like this: - f2fs_lookup - __recover_dot_dentries() - clear_inode_flag(dir, FI_INLINE_DOTS) - __mark_inode_dirty_flag() - remount rdonly - sb->s_flags |= SB_RDONLY - umount - kill_f2fs_super - kill_block_super - generic_shutdown_super - sync_filesystem skips due to sb_rdonly is true - evict_inodes - dispose_list - f2fs_evict_inode panic So how about this? https://git.kernel.org/pub/scm/linux/kernel/git/chao/linux.git/commit/?h=wip&id=e080fc8bec4d674cb8eb26ef0a0432f88bd65dd0 Thanks, - mkdir - do_mkdirat - filename_create - mnt_want_write - mnt_get_write_access - mount - do_remount - reconfigure_super - sb_prepare_remount_readonly - mnt_hold_writers - vfs_mkdir - f2fs_mkdir But when I try to reproduce this bug w/ reproducer provided by syzbot, I have found a clue in the log: "skip recovering inline_dots inode..." So I doubt the root cause is __recover_dot_dentries() in f2fs_lookup() generates dirty data/meta, in this path, we will not grab related lock to exclude readonly remount. Let me try to verify below patch: https://git.kernel.org/pub/scm/linux/kernel/git/chao/linux.git/commit/?h=wip&id=69dc8f39f85f9f436ca562c98afbcc2a48d2 Thanks, this code path: f2fs_mkdir()-> f2fs_sync_fs()- f2fs_write_checkpoint() ->f2fs_readonly(). This resulted FI_DIRTY_INODE flag not being cleared, which eventually led to a bug being triggered during the FI_DIRTY_INODE check in f2fs_evict_inode(). In this case, we cannot do anything further, so if filesystem is readonly, do not trigger the BUG. Instead, clean up resources to the best of our ability to prevent triggering subsequent resource leak checks. If there is anything important I'm missing, please let me know, thanks. Reported-by: syzbot+ebea2790904673d7c...@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=ebea2790904673d7c618 Fixes: ca7d802a7d8e ("f2fs: detect dirty inode in evict_inode") CC: sta...@vger.kernel.org Signed-off-by: Julian Sun --- fs/f2fs/inode.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/f2fs/inode.c b
Re: [f2fs-dev] [RFC PATCH] f2fs: don't set SBI_QUOTA_NEED_REPAIR flag if receive SIGKILL
On 2024/9/3 14:06, wangzijie wrote: From: Chao Yu via Linux-f2fs-devel On 2024/8/27 14:22, wangzijie wrote: Thread A -dquot_initialize -dqget -f2fs_dquot_acquire -v2_read_dquot -qtree_read_dquot -find_tree_dqentry -f2fs_quota_read -read_cache_page_gfp -do_read_cache_folio -fiemap_read_folio -folio_wait_locked_killable -receive SIGKILL : return -EINTR -set SBI_QUOTA_NEED_REPAIR -set SBI_QUOTA_NEED_REPAIR When calling read_cache_page_gfp in quota read, thread may receive SIGKILL and set SBI_QUOTA_NEED_REPAIR, should we set SBI_QUOTA_NEED_REPAIR in this error path? f2fs_quota_read() can be called in a lot of contexts, can we just ignore -EINTR for f2fs_dquot_initialize() case? Thanks, Yes, in many contexts f2fs_quota_read() can be called and may return -EINTR, we need to ignore this errno for more cases. If we need to do so, I will check it and resend patch. Or do you have other suggestions to avoid unnecessary SBI_QUOTA_NEED_REPAIR flag set? How about this? --- fs/f2fs/f2fs.h | 1 + fs/f2fs/inode.c | 3 +-- fs/f2fs/super.c | 17 + 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index dfed1974eda5..a1704a19dfe9 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -810,6 +810,7 @@ enum { FI_ATOMIC_DIRTIED, /* indicate atomic file is dirtied */ FI_ATOMIC_REPLACE, /* indicate atomic replace */ FI_OPENED_FILE, /* indicate file has been opened */ + FI_INIT_DQUOT, /* indicate it's initializing dquot */ FI_MAX, /* max flag, never be used */ }; diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c index 008f01348afa..b1dbaeda306f 100644 --- a/fs/f2fs/inode.c +++ b/fs/f2fs/inode.c @@ -827,8 +827,7 @@ void f2fs_evict_inode(struct inode *inode) err = f2fs_dquot_initialize(inode); if (err) { - if (err != -EINTR) - set_sbi_flag(sbi, SBI_QUOTA_NEED_REPAIR); + set_sbi_flag(sbi, SBI_QUOTA_NEED_REPAIR); err = 0; } diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 8e29aba4b7a4..e774bdf875b2 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -2644,8 +2644,11 @@ static ssize_t f2fs_quota_read(struct super_block *sb, int type, char *data, if (PTR_ERR(page) == -ENOMEM) { memalloc_retry_wait(GFP_NOFS); goto repeat; - } else if (PTR_ERR(page) != -EINTR) - set_sbi_flag(F2FS_SB(sb), SBI_QUOTA_NEED_REPAIR); + } else if (PTR_ERR(page) == -EINTR && + is_inode_flag_set(inode, FI_INIT_DQUOT)) { + return PTR_ERR(page); + } + set_sbi_flag(F2FS_SB(sb), SBI_QUOTA_NEED_REPAIR); return PTR_ERR(page); } @@ -2721,10 +2724,16 @@ static ssize_t f2fs_quota_write(struct super_block *sb, int type, int f2fs_dquot_initialize(struct inode *inode) { + int ret; + if (time_to_inject(F2FS_I_SB(inode), FAULT_DQUOT_INIT)) return -ESRCH; - return dquot_initialize(inode); + set_inode_flag(inode, FI_INIT_DQUOT); + ret = dquot_initialize(inode); + clear_inode_flag(inode, FI_INIT_DQUOT); + + return ret; } static struct dquot __rcu **f2fs_get_dquots(struct inode *inode) @@ -3064,7 +3073,7 @@ static int f2fs_dquot_acquire(struct dquot *dquot) f2fs_down_read(&sbi->quota_sem); ret = dquot_acquire(dquot); - if (ret < 0 && ret != -EINTR) + if (ret < 0) set_sbi_flag(sbi, SBI_QUOTA_NEED_REPAIR); f2fs_up_read(&sbi->quota_sem); return ret; -- 2.40.1 Thank you for review. Signed-off-by: wangzijie --- fs/f2fs/inode.c | 3 ++- fs/f2fs/super.c | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c index ed629dabb..2af98e2b7 100644 --- a/fs/f2fs/inode.c +++ b/fs/f2fs/inode.c @@ -837,8 +837,9 @@ void f2fs_evict_inode(struct inode *inode) err = f2fs_dquot_initialize(inode); if (err) { + if (err != -EINTR) + set_sbi_flag(sbi, SBI_QUOTA_NEED_REPAIR); err = 0; - set_sbi_flag(sbi, SBI_QUOTA_NEED_REPAIR); } f2fs_remove_ino_entry(sbi, inode->i_ino, APPEND_INO); diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 1f1b3647a..f99a36ff3 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -2650,8 +2650,8 @@ static ssize_t f2fs_quota_read(struct super_block *sb, int type, char *data, if (PTR_ERR(page) == -ENOMEM) { memalloc_retry_wait(GFP_NOFS); goto repeat; - } - set
Re: [f2fs-dev] [PATCH] f2fs: prevent atomic file from being dirtied before commit
On 2024/9/4 10:52, Daeho Jeong wrote: On Tue, Sep 3, 2024 at 7:26 PM Chao Yu wrote: On 2024/9/4 1:07, Daeho Jeong wrote: On Mon, Sep 2, 2024 at 3:08 AM Chao Yu wrote: On 2024/8/27 4:23, Daeho Jeong wrote: From: Daeho Jeong Keep atomic file clean while updating and make it dirtied during commit in order to avoid unnecessary and excessive inode updates in the previous fix. Fixes: 4bf78322346f ("f2fs: mark inode dirty for FI_ATOMIC_COMMITTED flag") Signed-off-by: Daeho Jeong --- fs/f2fs/f2fs.h| 3 +-- fs/f2fs/inode.c | 10 ++ fs/f2fs/segment.c | 10 -- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 465b2fd50c70..5a7f6fa8b585 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -801,7 +801,7 @@ enum { FI_COMPRESS_RELEASED, /* compressed blocks were released */ FI_ALIGNED_WRITE, /* enable aligned write */ FI_COW_FILE,/* indicate COW file */ - FI_ATOMIC_COMMITTED,/* indicate atomic commit completed except disk sync */ + FI_ATOMIC_DIRTIED, /* indicate atomic file is dirtied */ FI_ATOMIC_REPLACE, /* indicate atomic replace */ FI_OPENED_FILE, /* indicate file has been opened */ FI_MAX, /* max flag, never be used */ @@ -3042,7 +3042,6 @@ static inline void __mark_inode_dirty_flag(struct inode *inode, case FI_INLINE_DOTS: case FI_PIN_FILE: case FI_COMPRESS_RELEASED: - case FI_ATOMIC_COMMITTED: f2fs_mark_inode_dirty_sync(inode, true); } } diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c index 1eb250c6b392..5dd3e55d2be2 100644 --- a/fs/f2fs/inode.c +++ b/fs/f2fs/inode.c @@ -35,6 +35,11 @@ void f2fs_mark_inode_dirty_sync(struct inode *inode, bool sync) if (f2fs_inode_dirtied(inode, sync)) It will return directly here if inode was dirtied, so it may missed to set FI_ATOMIC_DIRTIED flag? Is it possible for it to be already dirty, since we already made it clean with f2fs_write_inode() when we started the atomic write? Some ioctl interfaces may race w/ atomic write? e.g. set_pin_file won't check atomic_file status, and may dirty inode after we started atomic write, so we'd better detect such race condition and break ioctl to avoid ruin atomic write? and maybe we can add f2fs_bug_on() in f2fs_mark_inode_dirty_sync() to detect any other missing cases? How about exchanging the positions of f2fs_write_inode() and set_inode_flag() in f2fs_ioc_start_atomic_write()? ... f2fs_write_inode(inode, NULL); stat_inc_atomic_inode(inode); set_inode_flag(inode, FI_ATOMIC_FILE); ... Oh, I'm not sure I've got your point, after exchanging we still may suffer below race condition, right? - f2fs_ioc_start_atomic_write - set_inode_flag(inode, FI_ATOMIC_FILE) - f2fs_write_inode(inode, NULL) - f2fs_ioc_set_pin_file - set_inode_flag(inode, FI_PIN_FILE) - __mark_inode_dirty_flag() - f2fs_ioc_commit_atomic_write So that I proposed a fix for this: https://lore.kernel.org/linux-f2fs-devel/20240904032047.1264706-1-c...@kernel.org Thanks, Thanks, Thanks, return; + if (f2fs_is_atomic_file(inode)) { + set_inode_flag(inode, FI_ATOMIC_DIRTIED); + return; + } + mark_inode_dirty_sync(inode); } @@ -653,10 +658,7 @@ void f2fs_update_inode(struct inode *inode, struct page *node_page) ri->i_gid = cpu_to_le32(i_gid_read(inode)); ri->i_links = cpu_to_le32(inode->i_nlink); ri->i_blocks = cpu_to_le64(SECTOR_TO_BLOCK(inode->i_blocks) + 1); - - if (!f2fs_is_atomic_file(inode) || - is_inode_flag_set(inode, FI_ATOMIC_COMMITTED)) - ri->i_size = cpu_to_le64(i_size_read(inode)); + ri->i_size = cpu_to_le64(i_size_read(inode)); if (et) { read_lock(&et->lock); diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index 78c3198a6308..2b5391b229a8 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -196,9 +196,12 @@ void f2fs_abort_atomic_write(struct inode *inode, bool clean) truncate_inode_pages_final(inode->i_mapping); release_atomic_write_cnt(inode); - clear_inode_flag(inode, FI_ATOMIC_COMMITTED); clear_inode_flag(inode, FI_ATOMIC_REPLACE); clear_inode_flag(inode, FI_ATOMIC_FILE); + if (is_inode_flag_set(inode, FI_ATOMIC_DIRTIED)) { + clear_inode_flag(inode, FI_ATOMIC_DIRTIED); + f2fs_mark_inode_dirty_sync(inode, true); + } stat_dec_atomic_inode(inode); F2FS_I(inode)->atomic_write_task = NULL; @@ -365,7 +368,10 @@ static int __f2fs_commit_atomic_write(struct inode *inode) sbi->revoked_atomic_
[f2fs-dev] [PATCH] f2fs: fix to check atomic_file in f2fs ioctl interfaces
Some f2fs ioctl interfaces like f2fs_ioc_set_pin_file(), f2fs_move_file_range(), and f2fs_defragment_range() missed to check atomic_write status, which may cause potential race issue, fix it. Cc: sta...@vger.kernel.org Signed-off-by: Chao Yu --- fs/f2fs/file.c | 13 - 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index a8d153eb0a95..99903eafa7fe 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -2710,7 +2710,8 @@ static int f2fs_defragment_range(struct f2fs_sb_info *sbi, (range->start + range->len) >> PAGE_SHIFT, DIV_ROUND_UP(i_size_read(inode), PAGE_SIZE)); - if (is_inode_flag_set(inode, FI_COMPRESS_RELEASED)) { + if (is_inode_flag_set(inode, FI_COMPRESS_RELEASED) || + f2fs_is_atomic_file(inode)) { err = -EINVAL; goto unlock_out; } @@ -2943,6 +2944,11 @@ static int f2fs_move_file_range(struct file *file_in, loff_t pos_in, goto out_unlock; } + if (f2fs_is_atomic_file(src) || f2fs_is_atomic_file(dst)) { + ret = -EINVAL; + goto out_unlock; + } + ret = -EINVAL; if (pos_in + len > src->i_size || pos_in + len < pos_in) goto out_unlock; @@ -3326,6 +3332,11 @@ static int f2fs_ioc_set_pin_file(struct file *filp, unsigned long arg) inode_lock(inode); + if (f2fs_is_atomic_file(inode)) { + ret = -EINVAL; + goto out; + } + if (!pin) { clear_inode_flag(inode, FI_PIN_FILE); f2fs_i_gc_failures_write(inode, 0); -- 2.40.1 ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
[f2fs-dev] [PATCH 2/2] fsck.f2fs: support to add missing '.' or '..' dirent
Previously, once fsck.f2fs detects that directory missed '.' or '..' dirent, it tags inode w/ F2FS_INLINE_DOTS flag, and expects f2fs kernel module can repaire it online during it runs to lookup() on target directory. This patch abandons previous implementation, and do repaires directly. Reviewed-by: Sheng Yong Signed-off-by: Chao Yu --- fsck/fsck.c | 45 - fsck/main.c | 4 +++- 2 files changed, 43 insertions(+), 6 deletions(-) diff --git a/fsck/fsck.c b/fsck/fsck.c index 54ddc11..f8ea7f0 100644 --- a/fsck/fsck.c +++ b/fsck/fsck.c @@ -1307,17 +1307,52 @@ skip_blkcnt_fix: nid, i_links, child.links); } } - if ((child.dot == 0 || child.dotdot == 0) && - !(node_blk->i.i_inline & F2FS_INLINE_DOTS)) { - ASSERT_MSG("ino: 0x%x dot: %u, dotdot: %u", + if (child.dot == 0 || child.dotdot == 0) { + ASSERT_MSG("ino: 0x%x has no '.' and/or '..' dirents, dot: %u, dotdot: %u", nid, child.dot, child.dotdot); if (c.fix_on) { - node_blk->i.i_inline |= F2FS_INLINE_DOTS; + umode_t mode = le16_to_cpu(node_blk->i.i_mode); + block_t blkaddr; + + ret = convert_inline_dentry(sbi, node_blk, + &ni->blk_addr); + FIX_MSG("convert inline dentry ino: %u, pino: %u, ret: %d", + nid, child_d->p_ino, ret); + if (ret) + goto skip_dot_fix; + + if (child.dot == 0) { + char *name = "."; + + ret = f2fs_add_link(sbi, node_blk, + (const unsigned char *)name, + 1, nid, map_de_type(mode), + &blkaddr, 0); + FIX_MSG("add missing '%s' dirent in ino: %u, pino: %u, ret:%d", + name, nid, child_d->p_ino, ret); + if (ret) + goto skip_dot_fix; + } + + if (child.dotdot == 0) { + char *name = ".."; + + ret = f2fs_add_link(sbi, node_blk, + (const unsigned char *)name, + 2, child_d->p_ino, + map_de_type(mode), + &blkaddr, 0); + FIX_MSG("add missing '%s' dirent in ino: %u, pino: %u, ret:%d", + name, nid, child_d->p_ino, ret); + if (ret) + goto skip_dot_fix; + } + need_fix = 1; - FIX_MSG("Dir: 0x%x set inline_dots", nid); } } } +skip_dot_fix: i_gc_failures = le16_to_cpu(node_blk->i.i_gc_failures); diff --git a/fsck/main.c b/fsck/main.c index 8881936..4e0254d 100644 --- a/fsck/main.c +++ b/fsck/main.c @@ -892,6 +892,7 @@ static int do_fsck(struct f2fs_sb_info *sbi) u32 flag = le32_to_cpu(ckpt->ckpt_flags); u32 blk_cnt; struct f2fs_compr_blk_cnt cbc; + struct child_info child = { 0 }; errcode_t ret; fsck_init(sbi); @@ -957,8 +958,9 @@ static int do_fsck(struct f2fs_sb_info *sbi) if (fsck_sanity_check_nat(sbi, sbi->root_ino_num)) fsck_chk_root_inode(sbi); + child.p_ino = sbi->root_ino_num; fsck_chk_node_blk(sbi, NULL, sbi->root_ino_num, - F2FS_FT_DIR, TYPE_INODE, &blk_cnt, &cbc, NULL); + F2FS_FT_DIR, TYPE_INODE, &blk_cnt, &cbc, &child); fsck_chk_quota_files(sbi); ret = fsck_verify(sbi); -- 2.40.1 ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
[f2fs-dev] [PATCH 1/2] fsck.f2fs: fix to detect double '.' or '..'
If there are double '.' or '..' dirents in directory, fsck.f2fs won't detect and repaire the issue correctly, fix it. Reviewed-by: Sheng Yong Signed-off-by: Chao Yu --- fsck/fsck.c | 55 +++ fsck/fsck.h | 3 ++- include/f2fs_fs.h | 6 ++ 3 files changed, 45 insertions(+), 19 deletions(-) diff --git a/fsck/fsck.c b/fsck/fsck.c index a18bee9..54ddc11 100644 --- a/fsck/fsck.c +++ b/fsck/fsck.c @@ -1307,10 +1307,10 @@ skip_blkcnt_fix: nid, i_links, child.links); } } - if (child.dots < 2 && + if ((child.dot == 0 || child.dotdot == 0) && !(node_blk->i.i_inline & F2FS_INLINE_DOTS)) { - ASSERT_MSG("ino: 0x%x dots: %u", - nid, child.dots); + ASSERT_MSG("ino: 0x%x dot: %u, dotdot: %u", + nid, child.dot, child.dotdot); if (c.fix_on) { node_blk->i.i_inline |= F2FS_INLINE_DOTS; need_fix = 1; @@ -1862,26 +1862,45 @@ static int __chk_dentries(struct f2fs_sb_info *sbi, int casefolded, /* Becareful. 'dentry.file_type' is not imode. */ if (ftype == F2FS_FT_DIR) { - if ((name[0] == '.' && name_len == 1) || - (name[0] == '.' && name[1] == '.' && - name_len == 2)) { - ret = __chk_dots_dentries(sbi, casefolded, &dentry[i], - child, name, name_len, &filenames[i], - enc_name); - switch (ret) { - case 1: + enum dot_type dot_type = NON_DOT; + + if (name[0] == '.' && name_len == 1) + dot_type = TYPE_DOT; + else if (name[0] == '.' && name[1] == '.' && + name_len == 2) + dot_type = TYPE_DOTDOT; + + if (dot_type != NON_DOT) { + bool need_del = false; + + DBG(3, "i:%u, dot_type:%u, ino:%u, p:%u, pp:%u\n", + i, dot_type, dentry[i].ino, + child->p_ino, child->pp_ino); + + ret = __chk_dots_dentries(sbi, casefolded, + &dentry[i], child, name, name_len, + &filenames[i], enc_name); + if (ret) fixed = 1; - fallthrough; - case 0: - child->dots++; - break; + + if (dot_type == TYPE_DOT) { + if (child->dot == 0) + child->dot++; + else + need_del = true; + } else if (dot_type == TYPE_DOTDOT) { + if (child->dotdot == 0) + child->dotdot++; + else + need_del = true; } - if (child->dots > 2) { - ASSERT_MSG("More than one '.' or '..', should delete the extra one\n"); + if (need_del) { + ASSERT_MSG("More than one '%s', should delete the extra one, i: %u, ino:%u", + dot_type == TYPE_DOT ? "." : "..", + i, dentry[i].ino); nullify_dentry(&dentry[i], i, &filenames[i], &bitmap); - child->dots--; fixed = 1; } diff --git a/fsck/fsck.h b/fsck/fsck.h index a8f187e..efccfbc 100644 --- a/fsck/fsck.h +++ b/fsck/fsck.h @@ -70,7 +
Re: [f2fs-dev] [PATCH] f2fs: prevent atomic file from being dirtied before commit
On 2024/9/4 1:07, Daeho Jeong wrote: On Mon, Sep 2, 2024 at 3:08 AM Chao Yu wrote: On 2024/8/27 4:23, Daeho Jeong wrote: From: Daeho Jeong Keep atomic file clean while updating and make it dirtied during commit in order to avoid unnecessary and excessive inode updates in the previous fix. Fixes: 4bf78322346f ("f2fs: mark inode dirty for FI_ATOMIC_COMMITTED flag") Signed-off-by: Daeho Jeong --- fs/f2fs/f2fs.h| 3 +-- fs/f2fs/inode.c | 10 ++ fs/f2fs/segment.c | 10 -- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 465b2fd50c70..5a7f6fa8b585 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -801,7 +801,7 @@ enum { FI_COMPRESS_RELEASED, /* compressed blocks were released */ FI_ALIGNED_WRITE, /* enable aligned write */ FI_COW_FILE,/* indicate COW file */ - FI_ATOMIC_COMMITTED,/* indicate atomic commit completed except disk sync */ + FI_ATOMIC_DIRTIED, /* indicate atomic file is dirtied */ FI_ATOMIC_REPLACE, /* indicate atomic replace */ FI_OPENED_FILE, /* indicate file has been opened */ FI_MAX, /* max flag, never be used */ @@ -3042,7 +3042,6 @@ static inline void __mark_inode_dirty_flag(struct inode *inode, case FI_INLINE_DOTS: case FI_PIN_FILE: case FI_COMPRESS_RELEASED: - case FI_ATOMIC_COMMITTED: f2fs_mark_inode_dirty_sync(inode, true); } } diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c index 1eb250c6b392..5dd3e55d2be2 100644 --- a/fs/f2fs/inode.c +++ b/fs/f2fs/inode.c @@ -35,6 +35,11 @@ void f2fs_mark_inode_dirty_sync(struct inode *inode, bool sync) if (f2fs_inode_dirtied(inode, sync)) It will return directly here if inode was dirtied, so it may missed to set FI_ATOMIC_DIRTIED flag? Is it possible for it to be already dirty, since we already made it clean with f2fs_write_inode() when we started the atomic write? Some ioctl interfaces may race w/ atomic write? e.g. set_pin_file won't check atomic_file status, and may dirty inode after we started atomic write, so we'd better detect such race condition and break ioctl to avoid ruin atomic write? and maybe we can add f2fs_bug_on() in f2fs_mark_inode_dirty_sync() to detect any other missing cases? Thanks, Thanks, return; + if (f2fs_is_atomic_file(inode)) { + set_inode_flag(inode, FI_ATOMIC_DIRTIED); + return; + } + mark_inode_dirty_sync(inode); } @@ -653,10 +658,7 @@ void f2fs_update_inode(struct inode *inode, struct page *node_page) ri->i_gid = cpu_to_le32(i_gid_read(inode)); ri->i_links = cpu_to_le32(inode->i_nlink); ri->i_blocks = cpu_to_le64(SECTOR_TO_BLOCK(inode->i_blocks) + 1); - - if (!f2fs_is_atomic_file(inode) || - is_inode_flag_set(inode, FI_ATOMIC_COMMITTED)) - ri->i_size = cpu_to_le64(i_size_read(inode)); + ri->i_size = cpu_to_le64(i_size_read(inode)); if (et) { read_lock(&et->lock); diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index 78c3198a6308..2b5391b229a8 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -196,9 +196,12 @@ void f2fs_abort_atomic_write(struct inode *inode, bool clean) truncate_inode_pages_final(inode->i_mapping); release_atomic_write_cnt(inode); - clear_inode_flag(inode, FI_ATOMIC_COMMITTED); clear_inode_flag(inode, FI_ATOMIC_REPLACE); clear_inode_flag(inode, FI_ATOMIC_FILE); + if (is_inode_flag_set(inode, FI_ATOMIC_DIRTIED)) { + clear_inode_flag(inode, FI_ATOMIC_DIRTIED); + f2fs_mark_inode_dirty_sync(inode, true); + } stat_dec_atomic_inode(inode); F2FS_I(inode)->atomic_write_task = NULL; @@ -365,7 +368,10 @@ static int __f2fs_commit_atomic_write(struct inode *inode) sbi->revoked_atomic_block += fi->atomic_write_cnt; } else { sbi->committed_atomic_block += fi->atomic_write_cnt; - set_inode_flag(inode, FI_ATOMIC_COMMITTED); + if (is_inode_flag_set(inode, FI_ATOMIC_DIRTIED)) { + clear_inode_flag(inode, FI_ATOMIC_DIRTIED); + f2fs_mark_inode_dirty_sync(inode, true); + } } __complete_revoke_list(inode, &revoke_list, ret ? true : false); ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
Re: [f2fs-dev] [syzbot] [f2fs?] kernel BUG in f2fs_evict_inode (3)
#syz test git://git.kernel.org/pub/scm/linux/kernel/git/chao/linux.git wip On 2024/8/22 23:38, syzbot wrote: syzbot has found a reproducer for the following issue on: HEAD commit:872cf28b8df9 Merge tag 'platform-drivers-x86-v6.11-4' of g.. git tree: upstream console+strace: https://syzkaller.appspot.com/x/log.txt?x=13ece38d98 kernel config: https://syzkaller.appspot.com/x/.config?x=4fc2afd52fd008bb dashboard link: https://syzkaller.appspot.com/bug?extid=ebea2790904673d7c618 compiler: Debian clang version 15.0.6, GNU ld (GNU Binutils for Debian) 2.40 syz repro: https://syzkaller.appspot.com/x/repro.syz?x=1344680b98 C reproducer: https://syzkaller.appspot.com/x/repro.c?x=1034880b98 Downloadable assets: disk image: https://storage.googleapis.com/syzbot-assets/c63409516c62/disk-872cf28b.raw.xz vmlinux: https://storage.googleapis.com/syzbot-assets/79b2b8c52d3a/vmlinux-872cf28b.xz kernel image: https://storage.googleapis.com/syzbot-assets/27cb9df9c339/bzImage-872cf28b.xz mounted in repro #1: https://storage.googleapis.com/syzbot-assets/1f04d7ef7499/mount_0.gz mounted in repro #2: https://storage.googleapis.com/syzbot-assets/831601ee93df/mount_5.gz IMPORTANT: if you fix the issue, please add the following tag to the commit: Reported-by: syzbot+ebea2790904673d7c...@syzkaller.appspotmail.com [ cut here ] kernel BUG at fs/f2fs/inode.c:896! Oops: invalid opcode: [#1] PREEMPT SMP KASAN PTI CPU: 1 UID: 0 PID: 5217 Comm: syz-executor605 Not tainted 6.11.0-rc4-syzkaller-00033-g872cf28b8df9 #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 08/06/2024 RIP: 0010:f2fs_evict_inode+0x1598/0x15c0 fs/f2fs/inode.c:896 Code: 6e 9b ab fd 31 ff 89 de e8 65 9b ab fd 40 84 ed 75 28 e8 5b 98 ab fd e9 3c ec ff ff e8 51 98 ab fd 90 0f 0b e8 49 98 ab fd 90 <0f> 0b e8 41 98 ab fd 90 0f 0b 90 e9 fc fe ff ff e8 33 98 ab fd e8 RSP: 0018:c90003497808 EFLAGS: 00010293 RAX: 83e7f267 RBX: 0002 RCX: 88801a3e8000 RDX: RSI: 0002 RDI: RBP: R08: 83e7ec50 R09: 11100efe9611 R10: dc00 R11: ed100efe9612 R12: 88807a834000 R13: 888077f4b088 R14: 888077f4abe8 R15: dc00 FS: 6d6353c0() GS:8880b930() knlGS: CS: 0010 DS: ES: CR0: 80050033 CR2: 7f376cbf9000 CR3: 786a CR4: 003506f0 DR0: DR1: DR2: DR3: DR6: fffe0ff0 DR7: 0400 Call Trace: evict+0x532/0x950 fs/inode.c:704 dispose_list fs/inode.c:747 [inline] evict_inodes+0x5f9/0x690 fs/inode.c:797 generic_shutdown_super+0x9d/0x2d0 fs/super.c:627 kill_block_super+0x44/0x90 fs/super.c:1696 kill_f2fs_super+0x344/0x690 fs/f2fs/super.c:4898 deactivate_locked_super+0xc4/0x130 fs/super.c:473 cleanup_mnt+0x41f/0x4b0 fs/namespace.c:1373 task_work_run+0x24f/0x310 kernel/task_work.c:228 ptrace_notify+0x2d2/0x380 kernel/signal.c:2402 ptrace_report_syscall include/linux/ptrace.h:415 [inline] ptrace_report_syscall_exit include/linux/ptrace.h:477 [inline] syscall_exit_work+0xc6/0x190 kernel/entry/common.c:173 syscall_exit_to_user_mode_prepare kernel/entry/common.c:200 [inline] __syscall_exit_to_user_mode_work kernel/entry/common.c:205 [inline] syscall_exit_to_user_mode+0x279/0x370 kernel/entry/common.c:218 do_syscall_64+0x100/0x230 arch/x86/entry/common.c:89 entry_SYSCALL_64_after_hwframe+0x77/0x7f RIP: 0033:0x7f37740a00a7 Code: 08 00 48 83 c4 08 5b 5d c3 66 2e 0f 1f 84 00 00 00 00 00 c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 b8 a6 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 01 c3 48 c7 c2 b0 ff ff ff f7 d8 64 89 02 b8 RSP: 002b:7ffc120a25e8 EFLAGS: 0206 ORIG_RAX: 00a6 RAX: RBX: 00015fbb RCX: 7f37740a00a7 RDX: RSI: 0009 RDI: 7ffc120a26a0 RBP: 7ffc120a26a0 R08: R09: R10: R11: 0206 R12: 7ffc120a3750 R13: 6d636700 R14: 431bde82d7b634db R15: 7ffc120a36f4 Modules linked in: ---[ end trace ]--- RIP: 0010:f2fs_evict_inode+0x1598/0x15c0 fs/f2fs/inode.c:896 Code: 6e 9b ab fd 31 ff 89 de e8 65 9b ab fd 40 84 ed 75 28 e8 5b 98 ab fd e9 3c ec ff ff e8 51 98 ab fd 90 0f 0b e8 49 98 ab fd 90 <0f> 0b e8 41 98 ab fd 90 0f 0b 90 e9 fc fe ff ff e8 33 98 ab fd e8 RSP: 0018:c90003497808 EFLAGS: 00010293 RAX: 83e7f267 RBX: 0002 RCX: 88801a3e8000 RDX: RSI: 0002 RDI: RBP: R08: 83e7ec50 R09: 11100efe9611 R10: dc00 R11: ed100efe9612 R12: 88807a834000 R13: 888077f4b088 R14: 888077f4abe8 R15: dc00 FS: 6d6353c0() GS:8880b930() knlGS:
Re: [f2fs-dev] [PATCH v2] f2fs: Do not check the FI_DIRTY_INODE flag when umounting a ro fs.
On 2024/9/2 21:01, Julian Sun wrote: On Mon, 2024-09-02 at 16:13 +0800, Chao Yu wrote: On 2024/8/29 0:54, Julian Sun wrote: Hi, all. Recently syzbot reported a bug as following: kernel BUG at fs/f2fs/inode.c:896! CPU: 1 UID: 0 PID: 5217 Comm: syz-executor605 Not tainted 6.11.0-rc4-syzkaller-00033-g872cf28b8df9 #0 RIP: 0010:f2fs_evict_inode+0x1598/0x15c0 fs/f2fs/inode.c:896 Call Trace: evict+0x532/0x950 fs/inode.c:704 dispose_list fs/inode.c:747 [inline] evict_inodes+0x5f9/0x690 fs/inode.c:797 generic_shutdown_super+0x9d/0x2d0 fs/super.c:627 kill_block_super+0x44/0x90 fs/super.c:1696 kill_f2fs_super+0x344/0x690 fs/f2fs/super.c:4898 deactivate_locked_super+0xc4/0x130 fs/super.c:473 cleanup_mnt+0x41f/0x4b0 fs/namespace.c:1373 task_work_run+0x24f/0x310 kernel/task_work.c:228 ptrace_notify+0x2d2/0x380 kernel/signal.c:2402 ptrace_report_syscall include/linux/ptrace.h:415 [inline] ptrace_report_syscall_exit include/linux/ptrace.h:477 [inline] syscall_exit_work+0xc6/0x190 kernel/entry/common.c:173 syscall_exit_to_user_mode_prepare kernel/entry/common.c:200 [inline] __syscall_exit_to_user_mode_work kernel/entry/common.c:205 [inline] syscall_exit_to_user_mode+0x279/0x370 kernel/entry/common.c:218 do_syscall_64+0x100/0x230 arch/x86/entry/common.c:89 entry_SYSCALL_64_after_hwframe+0x77/0x7f The syzbot constructed the following scenario: concurrently creating directories and setting the file system to read-only. In this case, while f2fs was making dir, the filesystem switched to readonly, and when it tried to clear the dirty flag, it triggered Go back to the root cause, I have no idea why it can leave dirty inode while mkdir races w/ readonly remount, due to the two operations should be exclusive, IIUC. - mkdir - do_mkdirat - filename_create - mnt_want_write - mnt_get_write_access - mount - do_remount - reconfigure_super - sb_prepare_remount_readonly - mnt_hold_writers - vfs_mkdir - f2fs_mkdir But when I try to reproduce this bug w/ reproducer provided by syzbot, I have found a clue in the log: "skip recovering inline_dots inode..." So I doubt the root cause is __recover_dot_dentries() in f2fs_lookup() generates dirty data/meta, in this path, we will not grab related lock to exclude readonly remount. Let me try to verify below patch: https://git.kernel.org/pub/scm/linux/kernel/git/chao/linux.git/commit/?h=wip&id=69dc8f39f85f9f436ca562c98afbcc2a48d2 Thanks, this code path: f2fs_mkdir()-> f2fs_sync_fs()- f2fs_write_checkpoint() ->f2fs_readonly(). This resulted FI_DIRTY_INODE flag not being cleared, which eventually led to a bug being triggered during the FI_DIRTY_INODE check in f2fs_evict_inode(). In this case, we cannot do anything further, so if filesystem is readonly, do not trigger the BUG. Instead, clean up resources to the best of our ability to prevent triggering subsequent resource leak checks. If there is anything important I'm missing, please let me know, thanks. Reported-by: syzbot+ebea2790904673d7c...@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=ebea2790904673d7c618 Fixes: ca7d802a7d8e ("f2fs: detect dirty inode in evict_inode") CC: sta...@vger.kernel.org Signed-off-by: Julian Sun --- fs/f2fs/inode.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c index aef57172014f..ebf825dba0a5 100644 --- a/fs/f2fs/inode.c +++ b/fs/f2fs/inode.c @@ -892,7 +892,8 @@ void f2fs_evict_inode(struct inode *inode) atomic_read(&fi->i_compr_blocks)); if (likely(!f2fs_cp_error(sbi) && - !is_sbi_flag_set(sbi, SBI_CP_DISABLED))) + !is_sbi_flag_set(sbi, SBI_CP_DISABLED)) && + !f2fs_readonly(sbi->sb)) Is it fine to drop this dirty inode? Since once it remounts f2fs as rw one, previous updates on such inode may be lost? Or am I missing something? The purpose of calling this here is mainly to avoid triggering the f2fs_bug_on(sbi, 1); statement in the subsequent f2fs_put_super() due to a reference count check failure. I would say it's possible, but there doesn't seem to be much more we can do in this scenario: the inode is about to be freed, and the file system is read-only. Or do we need a mechanism to save the inode that is about to be freed and then write it back to disk at the appropriate time after the file system becomes rw again? But such a mechanism sounds somewhat complex and a little bit of weird... Do you have any suggestions? Thanks, f2fs_bug_on(sbi, is_inode_flag_set(inode, FI_DIRTY_INODE)); else f2fs_inode_synced(inode);
[f2fs-dev] [PATCH] f2fs/003: add missing _fixed_by_kernel_commit line
The bug related to this regression testcase has been fixed by commit b40a2b003709 ("f2fs: use meta inode for GC of atomic file"), let's add missing _fixed_by_kernel_commit line for this testcase. Cc: Jaegeuk Kim Cc: Daeho Jeong Signed-off-by: Chao Yu --- tests/f2fs/003 | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/f2fs/003 b/tests/f2fs/003 index 62821ed7..fbb08a3e 100755 --- a/tests/f2fs/003 +++ b/tests/f2fs/003 @@ -25,6 +25,9 @@ _cleanup() rm -r -f $tmp.* } +_fixed_by_kernel_commit b40a2b003709 \ + "f2fs: use meta inode for GC of atomic file" + _require_scratch _require_xfs_io_command "fpunch" -- 2.40.1 ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
Re: [f2fs-dev] [PATCH] f2fs: prevent atomic file from being dirtied before commit
On 2024/8/27 4:23, Daeho Jeong wrote: From: Daeho Jeong Keep atomic file clean while updating and make it dirtied during commit in order to avoid unnecessary and excessive inode updates in the previous fix. Fixes: 4bf78322346f ("f2fs: mark inode dirty for FI_ATOMIC_COMMITTED flag") Signed-off-by: Daeho Jeong --- fs/f2fs/f2fs.h| 3 +-- fs/f2fs/inode.c | 10 ++ fs/f2fs/segment.c | 10 -- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 465b2fd50c70..5a7f6fa8b585 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -801,7 +801,7 @@ enum { FI_COMPRESS_RELEASED, /* compressed blocks were released */ FI_ALIGNED_WRITE, /* enable aligned write */ FI_COW_FILE,/* indicate COW file */ - FI_ATOMIC_COMMITTED,/* indicate atomic commit completed except disk sync */ + FI_ATOMIC_DIRTIED, /* indicate atomic file is dirtied */ FI_ATOMIC_REPLACE, /* indicate atomic replace */ FI_OPENED_FILE, /* indicate file has been opened */ FI_MAX, /* max flag, never be used */ @@ -3042,7 +3042,6 @@ static inline void __mark_inode_dirty_flag(struct inode *inode, case FI_INLINE_DOTS: case FI_PIN_FILE: case FI_COMPRESS_RELEASED: - case FI_ATOMIC_COMMITTED: f2fs_mark_inode_dirty_sync(inode, true); } } diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c index 1eb250c6b392..5dd3e55d2be2 100644 --- a/fs/f2fs/inode.c +++ b/fs/f2fs/inode.c @@ -35,6 +35,11 @@ void f2fs_mark_inode_dirty_sync(struct inode *inode, bool sync) if (f2fs_inode_dirtied(inode, sync)) It will return directly here if inode was dirtied, so it may missed to set FI_ATOMIC_DIRTIED flag? Thanks, return; + if (f2fs_is_atomic_file(inode)) { + set_inode_flag(inode, FI_ATOMIC_DIRTIED); + return; + } + mark_inode_dirty_sync(inode); } @@ -653,10 +658,7 @@ void f2fs_update_inode(struct inode *inode, struct page *node_page) ri->i_gid = cpu_to_le32(i_gid_read(inode)); ri->i_links = cpu_to_le32(inode->i_nlink); ri->i_blocks = cpu_to_le64(SECTOR_TO_BLOCK(inode->i_blocks) + 1); - - if (!f2fs_is_atomic_file(inode) || - is_inode_flag_set(inode, FI_ATOMIC_COMMITTED)) - ri->i_size = cpu_to_le64(i_size_read(inode)); + ri->i_size = cpu_to_le64(i_size_read(inode)); if (et) { read_lock(&et->lock); diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index 78c3198a6308..2b5391b229a8 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -196,9 +196,12 @@ void f2fs_abort_atomic_write(struct inode *inode, bool clean) truncate_inode_pages_final(inode->i_mapping); release_atomic_write_cnt(inode); - clear_inode_flag(inode, FI_ATOMIC_COMMITTED); clear_inode_flag(inode, FI_ATOMIC_REPLACE); clear_inode_flag(inode, FI_ATOMIC_FILE); + if (is_inode_flag_set(inode, FI_ATOMIC_DIRTIED)) { + clear_inode_flag(inode, FI_ATOMIC_DIRTIED); + f2fs_mark_inode_dirty_sync(inode, true); + } stat_dec_atomic_inode(inode); F2FS_I(inode)->atomic_write_task = NULL; @@ -365,7 +368,10 @@ static int __f2fs_commit_atomic_write(struct inode *inode) sbi->revoked_atomic_block += fi->atomic_write_cnt; } else { sbi->committed_atomic_block += fi->atomic_write_cnt; - set_inode_flag(inode, FI_ATOMIC_COMMITTED); + if (is_inode_flag_set(inode, FI_ATOMIC_DIRTIED)) { + clear_inode_flag(inode, FI_ATOMIC_DIRTIED); + f2fs_mark_inode_dirty_sync(inode, true); + } } __complete_revoke_list(inode, &revoke_list, ret ? true : false); ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
Re: [f2fs-dev] [PATCH v2] f2fs: Do not check the FI_DIRTY_INODE flag when umounting a ro fs.
On 2024/8/29 0:54, Julian Sun wrote: Hi, all. Recently syzbot reported a bug as following: kernel BUG at fs/f2fs/inode.c:896! CPU: 1 UID: 0 PID: 5217 Comm: syz-executor605 Not tainted 6.11.0-rc4-syzkaller-00033-g872cf28b8df9 #0 RIP: 0010:f2fs_evict_inode+0x1598/0x15c0 fs/f2fs/inode.c:896 Call Trace: evict+0x532/0x950 fs/inode.c:704 dispose_list fs/inode.c:747 [inline] evict_inodes+0x5f9/0x690 fs/inode.c:797 generic_shutdown_super+0x9d/0x2d0 fs/super.c:627 kill_block_super+0x44/0x90 fs/super.c:1696 kill_f2fs_super+0x344/0x690 fs/f2fs/super.c:4898 deactivate_locked_super+0xc4/0x130 fs/super.c:473 cleanup_mnt+0x41f/0x4b0 fs/namespace.c:1373 task_work_run+0x24f/0x310 kernel/task_work.c:228 ptrace_notify+0x2d2/0x380 kernel/signal.c:2402 ptrace_report_syscall include/linux/ptrace.h:415 [inline] ptrace_report_syscall_exit include/linux/ptrace.h:477 [inline] syscall_exit_work+0xc6/0x190 kernel/entry/common.c:173 syscall_exit_to_user_mode_prepare kernel/entry/common.c:200 [inline] __syscall_exit_to_user_mode_work kernel/entry/common.c:205 [inline] syscall_exit_to_user_mode+0x279/0x370 kernel/entry/common.c:218 do_syscall_64+0x100/0x230 arch/x86/entry/common.c:89 entry_SYSCALL_64_after_hwframe+0x77/0x7f The syzbot constructed the following scenario: concurrently creating directories and setting the file system to read-only. In this case, while f2fs was making dir, the filesystem switched to readonly, and when it tried to clear the dirty flag, it triggered this code path: f2fs_mkdir()-> f2fs_sync_fs()->f2fs_write_checkpoint() ->f2fs_readonly(). This resulted FI_DIRTY_INODE flag not being cleared, which eventually led to a bug being triggered during the FI_DIRTY_INODE check in f2fs_evict_inode(). In this case, we cannot do anything further, so if filesystem is readonly, do not trigger the BUG. Instead, clean up resources to the best of our ability to prevent triggering subsequent resource leak checks. If there is anything important I'm missing, please let me know, thanks. Reported-by: syzbot+ebea2790904673d7c...@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=ebea2790904673d7c618 Fixes: ca7d802a7d8e ("f2fs: detect dirty inode in evict_inode") CC: sta...@vger.kernel.org Signed-off-by: Julian Sun --- fs/f2fs/inode.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c index aef57172014f..ebf825dba0a5 100644 --- a/fs/f2fs/inode.c +++ b/fs/f2fs/inode.c @@ -892,7 +892,8 @@ void f2fs_evict_inode(struct inode *inode) atomic_read(&fi->i_compr_blocks)); if (likely(!f2fs_cp_error(sbi) && - !is_sbi_flag_set(sbi, SBI_CP_DISABLED))) + !is_sbi_flag_set(sbi, SBI_CP_DISABLED)) && + !f2fs_readonly(sbi->sb)) Is it fine to drop this dirty inode? Since once it remounts f2fs as rw one, previous updates on such inode may be lost? Or am I missing something? Thanks, f2fs_bug_on(sbi, is_inode_flag_set(inode, FI_DIRTY_INODE)); else f2fs_inode_synced(inode); ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
Re: [f2fs-dev] [RFC PATCH] f2fs: don't set SBI_QUOTA_NEED_REPAIR flag if receive SIGKILL
On 2024/8/27 14:22, wangzijie wrote: Thread A -dquot_initialize -dqget -f2fs_dquot_acquire -v2_read_dquot -qtree_read_dquot -find_tree_dqentry -f2fs_quota_read -read_cache_page_gfp -do_read_cache_folio -fiemap_read_folio -folio_wait_locked_killable -receive SIGKILL : return -EINTR -set SBI_QUOTA_NEED_REPAIR -set SBI_QUOTA_NEED_REPAIR When calling read_cache_page_gfp in quota read, thread may receive SIGKILL and set SBI_QUOTA_NEED_REPAIR, should we set SBI_QUOTA_NEED_REPAIR in this error path? f2fs_quota_read() can be called in a lot of contexts, can we just ignore -EINTR for f2fs_dquot_initialize() case? Thanks, Signed-off-by: wangzijie --- fs/f2fs/inode.c | 3 ++- fs/f2fs/super.c | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c index ed629dabb..2af98e2b7 100644 --- a/fs/f2fs/inode.c +++ b/fs/f2fs/inode.c @@ -837,8 +837,9 @@ void f2fs_evict_inode(struct inode *inode) err = f2fs_dquot_initialize(inode); if (err) { + if (err != -EINTR) + set_sbi_flag(sbi, SBI_QUOTA_NEED_REPAIR); err = 0; - set_sbi_flag(sbi, SBI_QUOTA_NEED_REPAIR); } f2fs_remove_ino_entry(sbi, inode->i_ino, APPEND_INO); diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index 1f1b3647a..f99a36ff3 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -2650,8 +2650,8 @@ static ssize_t f2fs_quota_read(struct super_block *sb, int type, char *data, if (PTR_ERR(page) == -ENOMEM) { memalloc_retry_wait(GFP_NOFS); goto repeat; - } - set_sbi_flag(F2FS_SB(sb), SBI_QUOTA_NEED_REPAIR); + } else if (PTR_ERR(page) != -EINTR) + set_sbi_flag(F2FS_SB(sb), SBI_QUOTA_NEED_REPAIR); return PTR_ERR(page); } @@ -3070,7 +3070,7 @@ static int f2fs_dquot_acquire(struct dquot *dquot) f2fs_down_read(&sbi->quota_sem); ret = dquot_acquire(dquot); - if (ret < 0) + if (ret < 0 && ret != -EINTR) set_sbi_flag(sbi, SBI_QUOTA_NEED_REPAIR); f2fs_up_read(&sbi->quota_sem); return ret; ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
Re: [f2fs-dev] [PATCH v2 2/4] f2fs: atomic: fix to not allow GC to pollute atomic_file
On 2024/8/28 23:27, Jaegeuk Kim wrote: On 08/14, Chao Yu wrote: SQLite App GC Thread Shrinker - f2fs_ioc_start_atomic_write - f2fs_ioc_commit_atomic_write - f2fs_commit_atomic_write - filemap_write_and_wait_range : write atomic_file's data to cow_inode echo 3 > drop_caches - f2fs_gc - gc_data_segment - move_data_page - set_page_dirty : it may load data of previous transaction into pagecache. - f2fs_down_write(&fi->i_gc_rwsem[WRITE]) - __f2fs_commit_atomic_write - f2fs_up_write(&fi->i_gc_rwsem[WRITE]) During committing atomic_file, GC may be triggered to migrate atomic_file's block, so it may contain data of previous transaction in page cache, we should drop atomic_file's cache once it was migrated by GC. And also, we should writeback atomic_file and cow_file's data w/ i_gc_rwsem lock held, in order to avoid block address change during __f2fs_commit_atomic_write(). Meahwhile, this patch adds f2fs_wait_on_block_writeback_range() to wait completion of block migration. Fixes: 3db1de0e582c ("f2fs: change the current atomic write way") Signed-off-by: Chao Yu --- v2: - fix error path handling. fs/f2fs/segment.c | 27 +++ 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index 3aee71c9f3c6..a43054ab0cf1 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -236,6 +236,9 @@ static int __replace_atomic_write_block(struct inode *inode, pgoff_t index, return err; } + if (__is_valid_data_blkaddr(dn.data_blkaddr)) + f2fs_wait_on_block_writeback_range(inode, dn.data_blkaddr, 1); + if (recover) { /* dn.data_blkaddr is always valid */ if (!__is_valid_data_blkaddr(new_addr)) { @@ -339,6 +342,9 @@ static int __f2fs_commit_atomic_write(struct inode *inode) goto out; } + f2fs_wait_on_block_writeback_range(cow_inode, + blkaddr, 1); + new = f2fs_kmem_cache_alloc(revoke_entry_slab, GFP_NOFS, true, NULL); @@ -379,16 +385,29 @@ int f2fs_commit_atomic_write(struct inode *inode) struct f2fs_inode_info *fi = F2FS_I(inode); int err; + f2fs_down_write(&fi->i_gc_rwsem[WRITE]); + err = filemap_write_and_wait_range(inode->i_mapping, 0, LLONG_MAX); if (err) - return err; + goto out; - f2fs_down_write(&fi->i_gc_rwsem[WRITE]); - f2fs_lock_op(sbi); + /* writeback GCing page of cow_inode */ + err = filemap_write_and_wait_range(fi->cow_inode->i_mapping, + 0, LLONG_MAX); + if (err) + goto out; - err = __f2fs_commit_atomic_write(inode); + filemap_invalidate_lock(inode->i_mapping); + + /* don't allow clean page loaded by GC to pollute atomic_file */ + truncate_pagecache(inode, 0); Performance impact? Please drop this patch due to commit b40a2b003709 (f2fs: use meta inode for GC of atomic file) has fixed this issue. Thanks. Thanks, + f2fs_lock_op(sbi); + err = __f2fs_commit_atomic_write(inode); f2fs_unlock_op(sbi); + + filemap_invalidate_unlock(inode->i_mapping); +out: f2fs_up_write(&fi->i_gc_rwsem[WRITE]); return err; -- 2.40.1 ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
Re: [f2fs-dev] [PATCH v2 2/4] f2fs: atomic: fix to not allow GC to pollute atomic_file
On 2024/8/20 10:44, Sunmin Jeong wrote: Hello Chao Yu, SQLite App GC Thread Shrinker - f2fs_ioc_start_atomic_write - f2fs_ioc_commit_atomic_write - f2fs_commit_atomic_write - filemap_write_and_wait_range : write atomic_file's data to cow_inode echo 3 > drop_caches - f2fs_gc - gc_data_segment - move_data_page We modified the code to make GC of the atomic file go to move_data_block in commit b40a2b003709 (f2fs: use meta inode for GC of atomic file). Could you please check if this patch is still necessary? Sunmin, Yes, you're right. Also, I've checked f2fs/003 of xfstests w/ commit b40a2b003709, it can fix the regression issue as well, so let's drop it. Thanks for pointing it out. :) Thanks, Thanks, - set_page_dirty : it may load data of previous transaction into pagecache. - f2fs_down_write(&fi->i_gc_rwsem[WRITE]) - __f2fs_commit_atomic_write - f2fs_up_write(&fi->i_gc_rwsem[WRITE]) During committing atomic_file, GC may be triggered to migrate atomic_file's block, so it may contain data of previous transaction in page cache, we should drop atomic_file's cache once it was migrated by GC. And also, we should writeback atomic_file and cow_file's data w/ i_gc_rwsem lock held, in order to avoid block address change during __f2fs_commit_atomic_write(). Meahwhile, this patch adds f2fs_wait_on_block_writeback_range() to wait completion of block migration. Fixes: 3db1de0e582c ("f2fs: change the current atomic write way") Signed-off-by: Chao Yu --- v2: - fix error path handling. fs/f2fs/segment.c | 27 +++ 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index 3aee71c9f3c6..a43054ab0cf1 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -236,6 +236,9 @@ static int __replace_atomic_write_block(struct inode *inode, pgoff_t index, return err; } + if (__is_valid_data_blkaddr(dn.data_blkaddr)) + f2fs_wait_on_block_writeback_range(inode, dn.data_blkaddr, 1); + if (recover) { /* dn.data_blkaddr is always valid */ if (!__is_valid_data_blkaddr(new_addr)) { @@ -339,6 +342,9 @@ static int __f2fs_commit_atomic_write(struct inode *inode) goto out; } + f2fs_wait_on_block_writeback_range(cow_inode, + blkaddr, 1); + new = f2fs_kmem_cache_alloc(revoke_entry_slab, GFP_NOFS, true, NULL); @@ -379,16 +385,29 @@ int f2fs_commit_atomic_write(struct inode *inode) struct f2fs_inode_info *fi = F2FS_I(inode); int err; + f2fs_down_write(&fi->i_gc_rwsem[WRITE]); + err = filemap_write_and_wait_range(inode->i_mapping, 0, LLONG_MAX); if (err) - return err; + goto out; - f2fs_down_write(&fi->i_gc_rwsem[WRITE]); - f2fs_lock_op(sbi); + /* writeback GCing page of cow_inode */ + err = filemap_write_and_wait_range(fi->cow_inode->i_mapping, + 0, LLONG_MAX); + if (err) + goto out; - err = __f2fs_commit_atomic_write(inode); + filemap_invalidate_lock(inode->i_mapping); + + /* don't allow clean page loaded by GC to pollute atomic_file */ + truncate_pagecache(inode, 0); + f2fs_lock_op(sbi); + err = __f2fs_commit_atomic_write(inode); f2fs_unlock_op(sbi); + + filemap_invalidate_unlock(inode->i_mapping); +out: f2fs_up_write(&fi->i_gc_rwsem[WRITE]); return err; -- 2.40.1 ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
Re: [f2fs-dev] [PATCH v2 1/8] f2fs: convert f2fs_write_begin() to use folio
On 2024/8/20 14:58, Chao Yu wrote: On 2024/8/20 12:38, Li Zetao wrote: I want to apply your patch set for testing, but there is a conflict on the master branch of linux-next. Maybe it depends on a certain pre-patch. Please let me know, thank you. Applying: f2fs: convert f2fs_write_begin() to use folio error: patch failed: fs/f2fs/data.c:3566 error: fs/f2fs/data.c: patch does not apply Patch failed at 0001 f2fs: convert f2fs_write_begin() to use folio We should apply this patchset on top of dev-test branch? https://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs.git/log/?h=dev-test Oh, I missed one patch... Can you please check https://git.kernel.org/pub/scm/linux/kernel/git/chao/linux.git/log/?h=folio Thanks, Thanks, Thanks, Li Zetao. ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
[f2fs-dev] [PATCH v3 3/9] f2fs: convert f2fs_write_end() to use folio
Convert to use folio, so that we can get rid of 'page->index' to prepare for removal of 'index' field in structure page [1]. [1] https://lore.kernel.org/all/zp8fgusibgq1t...@casper.infradead.org/ Cc: Matthew Wilcox Signed-off-by: Chao Yu --- fs/f2fs/data.c | 13 +++-- 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 85ac05c3655a..e114d738b6b4 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -3698,7 +3698,8 @@ static int f2fs_write_end(struct file *file, loff_t pos, unsigned len, unsigned copied, struct page *page, void *fsdata) { - struct inode *inode = page->mapping->host; + struct folio *folio = page_folio(page); + struct inode *inode = folio->mapping->host; trace_f2fs_write_end(inode, pos, len, copied); @@ -3707,17 +3708,17 @@ static int f2fs_write_end(struct file *file, * should be PAGE_SIZE. Otherwise, we treat it with zero copied and * let generic_perform_write() try to copy data again through copied=0. */ - if (!PageUptodate(page)) { + if (!folio_test_uptodate(folio)) { if (unlikely(copied != len)) copied = 0; else - SetPageUptodate(page); + folio_mark_uptodate(folio); } #ifdef CONFIG_F2FS_FS_COMPRESSION /* overwrite compressed file */ if (f2fs_compressed_file(inode) && fsdata) { - f2fs_compress_write_end(inode, fsdata, page->index, copied); + f2fs_compress_write_end(inode, fsdata, folio->index, copied); f2fs_update_time(F2FS_I_SB(inode), REQ_TIME); if (pos + copied > i_size_read(inode) && @@ -3730,10 +3731,10 @@ static int f2fs_write_end(struct file *file, if (!copied) goto unlock_out; - set_page_dirty(page); + folio_mark_dirty(folio); if (f2fs_is_atomic_file(inode)) - set_page_private_atomic(page); + set_page_private_atomic(folio_page(folio, 0)); if (pos + copied > i_size_read(inode) && !f2fs_verity_in_progress(inode)) { -- 2.40.1 ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
[f2fs-dev] [PATCH v3 9/9] f2fs: get rid of page->index
Convert to use folio, so that we can get rid of 'page->index' to prepare for removal of 'index' field in structure page [1]. [1] https://lore.kernel.org/all/zp8fgusibgq1t...@casper.infradead.org/ Cc: Matthew Wilcox Signed-off-by: Chao Yu --- fs/f2fs/compress.c | 2 +- fs/f2fs/data.c | 12 ++-- fs/f2fs/dir.c | 3 ++- fs/f2fs/inode.c| 3 ++- fs/f2fs/node.c | 4 ++-- fs/f2fs/segment.c | 3 ++- 6 files changed, 15 insertions(+), 12 deletions(-) diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c index 67bb1e2e07a4..163ad0d7d495 100644 --- a/fs/f2fs/compress.c +++ b/fs/f2fs/compress.c @@ -881,7 +881,7 @@ static bool cluster_has_invalid_data(struct compress_ctx *cc) f2fs_bug_on(F2FS_I_SB(cc->inode), !page); /* beyond EOF */ - if (page->index >= nr_pages) + if (page_folio(page)->index >= nr_pages) return true; } return false; diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index e69097267b99..c6d688208f8b 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -354,7 +354,7 @@ static void f2fs_write_end_io(struct bio *bio) } f2fs_bug_on(sbi, page->mapping == NODE_MAPPING(sbi) && - page->index != nid_of_node(page)); + page_folio(page)->index != nid_of_node(page)); dec_page_count(sbi, type); if (f2fs_in_warm_node_list(sbi, page)) @@ -703,7 +703,7 @@ int f2fs_submit_page_bio(struct f2fs_io_info *fio) bio = __bio_alloc(fio, 1); f2fs_set_bio_crypt_ctx(bio, fio->page->mapping->host, - fio->page->index, fio, GFP_NOIO); + page_folio(fio->page)->index, fio, GFP_NOIO); if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) { bio_put(bio); @@ -802,7 +802,7 @@ static int add_ipu_page(struct f2fs_io_info *fio, struct bio **bio, fio->new_blkaddr)); if (f2fs_crypt_mergeable_bio(*bio, fio->page->mapping->host, - fio->page->index, fio) && + page_folio(fio->page)->index, fio) && bio_add_page(*bio, page, PAGE_SIZE, 0) == PAGE_SIZE) { ret = 0; @@ -902,7 +902,7 @@ int f2fs_merge_page_bio(struct f2fs_io_info *fio) if (!bio) { bio = __bio_alloc(fio, BIO_MAX_VECS); f2fs_set_bio_crypt_ctx(bio, fio->page->mapping->host, - fio->page->index, fio, GFP_NOIO); + page_folio(fio->page)->index, fio, GFP_NOIO); add_bio_entry(fio->sbi, bio, page, fio->temp); } else { @@ -995,13 +995,13 @@ void f2fs_submit_page_write(struct f2fs_io_info *fio) (!io_is_mergeable(sbi, io->bio, io, fio, io->last_block_in_bio, fio->new_blkaddr) || !f2fs_crypt_mergeable_bio(io->bio, fio->page->mapping->host, - bio_page->index, fio))) + page_folio(bio_page)->index, fio))) __submit_merged_bio(io); alloc_new: if (io->bio == NULL) { io->bio = __bio_alloc(fio, BIO_MAX_VECS); f2fs_set_bio_crypt_ctx(io->bio, fio->page->mapping->host, - bio_page->index, fio, GFP_NOIO); + page_folio(bio_page)->index, fio, GFP_NOIO); io->fio = *fio; } diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c index 5fcc952107e9..1136539a57a8 100644 --- a/fs/f2fs/dir.c +++ b/fs/f2fs/dir.c @@ -842,6 +842,7 @@ void f2fs_delete_entry(struct f2fs_dir_entry *dentry, struct page *page, struct f2fs_dentry_block *dentry_blk; unsigned int bit_pos; int slots = GET_DENTRY_SLOTS(le16_to_cpu(dentry->name_len)); + pgoff_t index = page_folio(page)->index; int i; f2fs_update_time(F2FS_I_SB(dir), REQ_TIME); @@ -867,7 +868,7 @@ void f2fs_delete_entry(struct f2fs_dir_entry *dentry, struct page *page, set_page_dirty(page); if (bit_pos == NR_DENTRY_IN_BLOCK && - !f2fs_truncate_hole(dir, page->index, page->index + 1)) { + !f2fs_truncate_hole(dir, index, index + 1)) { f2fs_clear_page_cache_dirty_tag(page_folio(page)); clear_page_dirty_for_io(page); ClearPageUptodate(page); diff --git a/fs/f2fs/inode.c b/fs/f2fs/inod
[f2fs-dev] [PATCH v3 1/9] f2fs: convert f2fs_submit_page_read() to use folio
Convert to use folio, so that we can get rid of 'page->index' to prepare for removal of 'index' field in structure page [1]. [1] https://lore.kernel.org/all/zp8fgusibgq1t...@casper.infradead.org/ Cc: Matthew Wilcox Signed-off-by: Chao Yu --- fs/f2fs/data.c | 12 ++-- 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 4f4e76c33611..0655fddfc4ba 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -1086,7 +1086,7 @@ static struct bio *f2fs_grab_read_bio(struct inode *inode, block_t blkaddr, } /* This can handle encryption stuffs */ -static int f2fs_submit_page_read(struct inode *inode, struct page *page, +static int f2fs_submit_page_read(struct inode *inode, struct folio *folio, block_t blkaddr, blk_opf_t op_flags, bool for_write) { @@ -1094,14 +1094,14 @@ static int f2fs_submit_page_read(struct inode *inode, struct page *page, struct bio *bio; bio = f2fs_grab_read_bio(inode, blkaddr, 1, op_flags, - page->index, for_write); + folio->index, for_write); if (IS_ERR(bio)) return PTR_ERR(bio); /* wait for GCed page writeback via META_MAPPING */ f2fs_wait_on_block_writeback(inode, blkaddr); - if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) { + if (!bio_add_folio(bio, folio, PAGE_SIZE, 0)) { iostat_update_and_unbind_ctx(bio); if (bio->bi_private) mempool_free(bio->bi_private, bio_post_read_ctx_pool); @@ -1269,7 +1269,7 @@ struct page *f2fs_get_read_data_page(struct inode *inode, pgoff_t index, return page; } - err = f2fs_submit_page_read(inode, page, dn.data_blkaddr, + err = f2fs_submit_page_read(inode, page_folio(page), dn.data_blkaddr, op_flags, for_write); if (err) goto put_err; @@ -3668,8 +3668,8 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping, goto fail; } err = f2fs_submit_page_read(use_cow ? - F2FS_I(inode)->cow_inode : inode, page, - blkaddr, 0, true); + F2FS_I(inode)->cow_inode : inode, + page_folio(page), blkaddr, 0, true); if (err) goto fail; -- 2.40.1 ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
[f2fs-dev] [PATCH v3 8/9] f2fs: convert read_node_page() to use folio
Convert to use folio, so that we can get rid of 'page->index' to prepare for removal of 'index' field in structure page [1]. [1] https://lore.kernel.org/all/zp8fgusibgq1t...@casper.infradead.org/ Cc: Matthew Wilcox Signed-off-by: Chao Yu --- fs/f2fs/node.c | 9 + 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index aeda3eecc9e2..f5e5abce695b 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c @@ -1369,6 +1369,7 @@ struct page *f2fs_new_node_page(struct dnode_of_data *dn, unsigned int ofs) */ static int read_node_page(struct page *page, blk_opf_t op_flags) { + struct folio *folio = page_folio(page); struct f2fs_sb_info *sbi = F2FS_P_SB(page); struct node_info ni; struct f2fs_io_info fio = { @@ -1381,21 +1382,21 @@ static int read_node_page(struct page *page, blk_opf_t op_flags) }; int err; - if (PageUptodate(page)) { + if (folio_test_uptodate(folio)) { if (!f2fs_inode_chksum_verify(sbi, page)) { - ClearPageUptodate(page); + folio_clear_uptodate(folio); return -EFSBADCRC; } return LOCKED_PAGE; } - err = f2fs_get_node_info(sbi, page->index, &ni, false); + err = f2fs_get_node_info(sbi, folio->index, &ni, false); if (err) return err; /* NEW_ADDR can be seen, after cp_error drops some dirty node pages */ if (unlikely(ni.blk_addr == NULL_ADDR || ni.blk_addr == NEW_ADDR)) { - ClearPageUptodate(page); + folio_clear_uptodate(folio); return -ENOENT; } -- 2.40.1 ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
[f2fs-dev] [PATCH v3 7/9] f2fs: convert __write_node_page() to use folio
Convert to use folio, so that we can get rid of 'page->index' to prepare for removal of 'index' field in structure page [1]. [1] https://lore.kernel.org/all/zp8fgusibgq1t...@casper.infradead.org/ Cc: Matthew Wilcox Signed-off-by: Chao Yu --- fs/f2fs/node.c | 19 ++- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index 7beaa3690e03..aeda3eecc9e2 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c @@ -1608,6 +1608,7 @@ static int __write_node_page(struct page *page, bool atomic, bool *submitted, enum iostat_type io_type, unsigned int *seq_id) { struct f2fs_sb_info *sbi = F2FS_P_SB(page); + struct folio *folio = page_folio(page); nid_t nid; struct node_info ni; struct f2fs_io_info fio = { @@ -1624,15 +1625,15 @@ static int __write_node_page(struct page *page, bool atomic, bool *submitted, }; unsigned int seq; - trace_f2fs_writepage(page_folio(page), NODE); + trace_f2fs_writepage(folio, NODE); if (unlikely(f2fs_cp_error(sbi))) { /* keep node pages in remount-ro mode */ if (F2FS_OPTION(sbi).errors == MOUNT_ERRORS_READONLY) goto redirty_out; - ClearPageUptodate(page); + folio_clear_uptodate(folio); dec_page_count(sbi, F2FS_DIRTY_NODES); - unlock_page(page); + folio_unlock(folio); return 0; } @@ -1646,7 +1647,7 @@ static int __write_node_page(struct page *page, bool atomic, bool *submitted, /* get old block addr of this node page */ nid = nid_of_node(page); - f2fs_bug_on(sbi, page->index != nid); + f2fs_bug_on(sbi, folio->index != nid); if (f2fs_get_node_info(sbi, nid, &ni, !do_balance)) goto redirty_out; @@ -1660,10 +1661,10 @@ static int __write_node_page(struct page *page, bool atomic, bool *submitted, /* This page is already truncated */ if (unlikely(ni.blk_addr == NULL_ADDR)) { - ClearPageUptodate(page); + folio_clear_uptodate(folio); dec_page_count(sbi, F2FS_DIRTY_NODES); f2fs_up_read(&sbi->node_write); - unlock_page(page); + folio_unlock(folio); return 0; } @@ -1684,7 +1685,7 @@ static int __write_node_page(struct page *page, bool atomic, bool *submitted, *seq_id = seq; } - set_page_writeback(page); + folio_start_writeback(folio); fio.old_blkaddr = ni.blk_addr; f2fs_do_write_node_page(nid, &fio); @@ -1697,7 +1698,7 @@ static int __write_node_page(struct page *page, bool atomic, bool *submitted, submitted = NULL; } - unlock_page(page); + folio_unlock(folio); if (unlikely(f2fs_cp_error(sbi))) { f2fs_submit_merged_write(sbi, NODE); @@ -1711,7 +1712,7 @@ static int __write_node_page(struct page *page, bool atomic, bool *submitted, return 0; redirty_out: - redirty_page_for_writepage(wbc, page); + folio_redirty_for_writepage(wbc, folio); return AOP_WRITEPAGE_ACTIVATE; } -- 2.40.1 ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
[f2fs-dev] [PATCH v3 5/9] f2fs: convert f2fs_do_write_data_page() to use folio
Convert to use folio, so that we can get rid of 'page->index' to prepare for removal of 'index' field in structure page [1]. [1] https://lore.kernel.org/all/zp8fgusibgq1t...@casper.infradead.org/ Cc: Matthew Wilcox Signed-off-by: Chao Yu --- fs/f2fs/data.c | 26 +- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index e114d738b6b4..c57ddee2c7c5 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -2648,8 +2648,8 @@ static inline bool need_inplace_update(struct f2fs_io_info *fio) int f2fs_do_write_data_page(struct f2fs_io_info *fio) { - struct page *page = fio->page; - struct inode *inode = page->mapping->host; + struct folio *folio = page_folio(fio->page); + struct inode *inode = folio->mapping->host; struct dnode_of_data dn; struct node_info ni; bool ipu_force = false; @@ -2658,14 +2658,14 @@ int f2fs_do_write_data_page(struct f2fs_io_info *fio) /* Use COW inode to make dnode_of_data for atomic write */ atomic_commit = f2fs_is_atomic_file(inode) && - page_private_atomic(fio->page); + page_private_atomic(folio_page(folio, 0)); if (atomic_commit) set_new_dnode(&dn, F2FS_I(inode)->cow_inode, NULL, NULL, 0); else set_new_dnode(&dn, inode, NULL, NULL, 0); if (need_inplace_update(fio) && - f2fs_lookup_read_extent_cache_block(inode, page->index, + f2fs_lookup_read_extent_cache_block(inode, folio->index, &fio->old_blkaddr)) { if (!f2fs_is_valid_blkaddr(fio->sbi, fio->old_blkaddr, DATA_GENERIC_ENHANCE)) @@ -2680,7 +2680,7 @@ int f2fs_do_write_data_page(struct f2fs_io_info *fio) if (fio->need_lock == LOCK_REQ && !f2fs_trylock_op(fio->sbi)) return -EAGAIN; - err = f2fs_get_dnode_of_data(&dn, page->index, LOOKUP_NODE); + err = f2fs_get_dnode_of_data(&dn, folio->index, LOOKUP_NODE); if (err) goto out; @@ -2688,8 +2688,8 @@ int f2fs_do_write_data_page(struct f2fs_io_info *fio) /* This page is already truncated */ if (fio->old_blkaddr == NULL_ADDR) { - ClearPageUptodate(page); - clear_page_private_gcing(page); + folio_clear_uptodate(folio); + clear_page_private_gcing(folio_page(folio, 0)); goto out_writepage; } got_it: @@ -2715,7 +2715,7 @@ int f2fs_do_write_data_page(struct f2fs_io_info *fio) if (err) goto out_writepage; - set_page_writeback(page); + folio_start_writeback(folio); f2fs_put_dnode(&dn); if (fio->need_lock == LOCK_REQ) f2fs_unlock_op(fio->sbi); @@ -2723,11 +2723,11 @@ int f2fs_do_write_data_page(struct f2fs_io_info *fio) if (err) { if (fscrypt_inode_uses_fs_layer_crypto(inode)) fscrypt_finalize_bounce_page(&fio->encrypted_page); - end_page_writeback(page); + folio_end_writeback(folio); } else { set_inode_flag(inode, FI_UPDATE_WRITE); } - trace_f2fs_do_write_data_page(page_folio(page), IPU); + trace_f2fs_do_write_data_page(folio, IPU); return err; } @@ -2749,17 +2749,17 @@ int f2fs_do_write_data_page(struct f2fs_io_info *fio) if (err) goto out_writepage; - set_page_writeback(page); + folio_start_writeback(folio); if (fio->compr_blocks && fio->old_blkaddr == COMPRESS_ADDR) f2fs_i_compr_blocks_update(inode, fio->compr_blocks - 1, false); /* LFS mode write path */ f2fs_outplace_write_data(&dn, fio); - trace_f2fs_do_write_data_page(page_folio(page), OPU); + trace_f2fs_do_write_data_page(folio, OPU); set_inode_flag(inode, FI_APPEND_WRITE); if (atomic_commit) - clear_page_private_atomic(page); + clear_page_private_atomic(folio_page(folio, 0)); out_writepage: f2fs_put_dnode(&dn); out: -- 2.40.1 ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
[f2fs-dev] [PATCH v3 2/9] f2fs: convert f2fs_write_begin() to use folio
Convert to use folio, so that we can get rid of 'page->index' to prepare for removal of 'index' field in structure page [1]. [1] https://lore.kernel.org/all/zp8fgusibgq1t...@casper.infradead.org/ Cc: Matthew Wilcox Signed-off-by: Chao Yu --- fs/f2fs/data.c | 44 +++- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 0655fddfc4ba..85ac05c3655a 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -3378,11 +3378,11 @@ void f2fs_write_failed(struct inode *inode, loff_t to) } static int prepare_write_begin(struct f2fs_sb_info *sbi, - struct page *page, loff_t pos, unsigned len, + struct folio *folio, loff_t pos, unsigned int len, block_t *blk_addr, bool *node_changed) { - struct inode *inode = page->mapping->host; - pgoff_t index = page->index; + struct inode *inode = folio->mapping->host; + pgoff_t index = folio->index; struct dnode_of_data dn; struct page *ipage; bool locked = false; @@ -3419,13 +3419,13 @@ static int prepare_write_begin(struct f2fs_sb_info *sbi, if (f2fs_has_inline_data(inode)) { if (pos + len <= MAX_INLINE_DATA(inode)) { - f2fs_do_read_inline_data(page_folio(page), ipage); + f2fs_do_read_inline_data(folio, ipage); set_inode_flag(inode, FI_DATA_EXIST); if (inode->i_nlink) set_page_private_inline(ipage); goto out; } - err = f2fs_convert_inline_page(&dn, page); + err = f2fs_convert_inline_page(&dn, folio_page(folio, 0)); if (err || dn.data_blkaddr != NULL_ADDR) goto out; } @@ -3518,12 +3518,12 @@ static int __reserve_data_block(struct inode *inode, pgoff_t index, } static int prepare_atomic_write_begin(struct f2fs_sb_info *sbi, - struct page *page, loff_t pos, unsigned int len, + struct folio *folio, loff_t pos, unsigned int len, block_t *blk_addr, bool *node_changed, bool *use_cow) { - struct inode *inode = page->mapping->host; + struct inode *inode = folio->mapping->host; struct inode *cow_inode = F2FS_I(inode)->cow_inode; - pgoff_t index = page->index; + pgoff_t index = folio->index; int err = 0; block_t ori_blk_addr = NULL_ADDR; @@ -3566,6 +3566,7 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping, struct inode *inode = mapping->host; struct f2fs_sb_info *sbi = F2FS_I_SB(inode); struct page *page = NULL; + struct folio *folio; pgoff_t index = ((unsigned long long) pos) >> PAGE_SHIFT; bool need_balance = false; bool use_cow = false; @@ -3625,22 +3626,23 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping, /* TODO: cluster can be compressed due to race with .writepage */ *pagep = page; + folio = page_folio(page); if (f2fs_is_atomic_file(inode)) - err = prepare_atomic_write_begin(sbi, page, pos, len, + err = prepare_atomic_write_begin(sbi, folio, pos, len, &blkaddr, &need_balance, &use_cow); else - err = prepare_write_begin(sbi, page, pos, len, + err = prepare_write_begin(sbi, folio, pos, len, &blkaddr, &need_balance); if (err) goto fail; if (need_balance && !IS_NOQUOTA(inode) && has_not_enough_free_secs(sbi, 0, 0)) { - unlock_page(page); + folio_unlock(folio); f2fs_balance_fs(sbi, true); - lock_page(page); - if (page->mapping != mapping) { + folio_lock(folio); + if (folio->mapping != mapping) { /* The page got truncated from under us */ f2fs_put_page(page, 1); goto repeat; @@ -3649,18 +3651,18 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping, f2fs_wait_on_page_writeback(page, DATA, false, true); - if (len == PAGE_SIZE || PageUptodate(page)) + if (len == PAGE_SIZE || folio_test_uptodate(folio)) return 0; if (!(pos & (PAGE_SIZE - 1)) && (pos + len) >= i_size_read(inode) && !f2fs_verity_in_progress(inode)) { - zero_user_segment(page, len, PAGE_SIZE); + folio_zero_segment(folio, len, folio_size(folio));
[f2fs-dev] [PATCH v3 4/9] f2fs: convert f2fs_set_compressed_page() to use folio
Convert to use folio, so that we can get rid of 'page->index' to prepare for removal of 'index' field in structure page [1]. [1] https://lore.kernel.org/all/zp8fgusibgq1t...@casper.infradead.org/ Cc: Matthew Wilcox Signed-off-by: Chao Yu --- fs/f2fs/compress.c | 8 +--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c index 82c31641e696..67bb1e2e07a4 100644 --- a/fs/f2fs/compress.c +++ b/fs/f2fs/compress.c @@ -90,11 +90,13 @@ bool f2fs_is_compressed_page(struct page *page) static void f2fs_set_compressed_page(struct page *page, struct inode *inode, pgoff_t index, void *data) { - attach_page_private(page, (void *)data); + struct folio *folio = page_folio(page); + + folio_attach_private(folio, (void *)data); /* i_crypto_info and iv index */ - page->index = index; - page->mapping = inode->i_mapping; + folio->index = index; + folio->mapping = inode->i_mapping; } static void f2fs_drop_rpages(struct compress_ctx *cc, int len, bool unlock) -- 2.40.1 ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
[f2fs-dev] [PATCH v3 6/9] f2fs: convert f2fs_write_data_page() to use folio
Convert to use folio, so that we can get rid of 'page->index' to prepare for removal of 'index' field in structure page [1]. [1] https://lore.kernel.org/all/zp8fgusibgq1t...@casper.infradead.org/ Cc: Matthew Wilcox Signed-off-by: Chao Yu --- fs/f2fs/data.c | 9 + 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index c57ddee2c7c5..e69097267b99 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -2945,22 +2945,23 @@ int f2fs_write_single_data_page(struct folio *folio, int *submitted, static int f2fs_write_data_page(struct page *page, struct writeback_control *wbc) { + struct folio *folio = page_folio(page); #ifdef CONFIG_F2FS_FS_COMPRESSION - struct inode *inode = page->mapping->host; + struct inode *inode = folio->mapping->host; if (unlikely(f2fs_cp_error(F2FS_I_SB(inode goto out; if (f2fs_compressed_file(inode)) { - if (f2fs_is_compressed_cluster(inode, page->index)) { - redirty_page_for_writepage(wbc, page); + if (f2fs_is_compressed_cluster(inode, folio->index)) { + folio_redirty_for_writepage(wbc, folio); return AOP_WRITEPAGE_ACTIVATE; } } out: #endif - return f2fs_write_single_data_page(page_folio(page), NULL, NULL, NULL, + return f2fs_write_single_data_page(folio, NULL, NULL, NULL, wbc, FS_DATA_IO, 0, true); } -- 2.40.1 ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
Re: [f2fs-dev] [PATCH v2 1/8] f2fs: convert f2fs_write_begin() to use folio
On 2024/8/20 12:38, Li Zetao wrote: I want to apply your patch set for testing, but there is a conflict on the master branch of linux-next. Maybe it depends on a certain pre-patch. Please let me know, thank you. Applying: f2fs: convert f2fs_write_begin() to use folio error: patch failed: fs/f2fs/data.c:3566 error: fs/f2fs/data.c: patch does not apply Patch failed at 0001 f2fs: convert f2fs_write_begin() to use folio We should apply this patchset on top of dev-test branch? https://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs.git/log/?h=dev-test Thanks, Thanks, Li Zetao. ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
[f2fs-dev] [PATCH v2 6/8] f2fs: convert __write_node_page() to use folio
Convert to use folio, so that we can get rid of 'page->index' to prepare for removal of 'index' field in structure page [1]. [1] https://lore.kernel.org/all/zp8fgusibgq1t...@casper.infradead.org/ Cc: Matthew Wilcox Signed-off-by: Chao Yu --- fs/f2fs/node.c | 19 ++- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index 7beaa3690e03..aeda3eecc9e2 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c @@ -1608,6 +1608,7 @@ static int __write_node_page(struct page *page, bool atomic, bool *submitted, enum iostat_type io_type, unsigned int *seq_id) { struct f2fs_sb_info *sbi = F2FS_P_SB(page); + struct folio *folio = page_folio(page); nid_t nid; struct node_info ni; struct f2fs_io_info fio = { @@ -1624,15 +1625,15 @@ static int __write_node_page(struct page *page, bool atomic, bool *submitted, }; unsigned int seq; - trace_f2fs_writepage(page_folio(page), NODE); + trace_f2fs_writepage(folio, NODE); if (unlikely(f2fs_cp_error(sbi))) { /* keep node pages in remount-ro mode */ if (F2FS_OPTION(sbi).errors == MOUNT_ERRORS_READONLY) goto redirty_out; - ClearPageUptodate(page); + folio_clear_uptodate(folio); dec_page_count(sbi, F2FS_DIRTY_NODES); - unlock_page(page); + folio_unlock(folio); return 0; } @@ -1646,7 +1647,7 @@ static int __write_node_page(struct page *page, bool atomic, bool *submitted, /* get old block addr of this node page */ nid = nid_of_node(page); - f2fs_bug_on(sbi, page->index != nid); + f2fs_bug_on(sbi, folio->index != nid); if (f2fs_get_node_info(sbi, nid, &ni, !do_balance)) goto redirty_out; @@ -1660,10 +1661,10 @@ static int __write_node_page(struct page *page, bool atomic, bool *submitted, /* This page is already truncated */ if (unlikely(ni.blk_addr == NULL_ADDR)) { - ClearPageUptodate(page); + folio_clear_uptodate(folio); dec_page_count(sbi, F2FS_DIRTY_NODES); f2fs_up_read(&sbi->node_write); - unlock_page(page); + folio_unlock(folio); return 0; } @@ -1684,7 +1685,7 @@ static int __write_node_page(struct page *page, bool atomic, bool *submitted, *seq_id = seq; } - set_page_writeback(page); + folio_start_writeback(folio); fio.old_blkaddr = ni.blk_addr; f2fs_do_write_node_page(nid, &fio); @@ -1697,7 +1698,7 @@ static int __write_node_page(struct page *page, bool atomic, bool *submitted, submitted = NULL; } - unlock_page(page); + folio_unlock(folio); if (unlikely(f2fs_cp_error(sbi))) { f2fs_submit_merged_write(sbi, NODE); @@ -1711,7 +1712,7 @@ static int __write_node_page(struct page *page, bool atomic, bool *submitted, return 0; redirty_out: - redirty_page_for_writepage(wbc, page); + folio_redirty_for_writepage(wbc, folio); return AOP_WRITEPAGE_ACTIVATE; } -- 2.40.1 ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
[f2fs-dev] [PATCH v2 8/8] f2fs: get rid of page->index
Convert to use folio, so that we can get rid of 'page->index' to prepare for removal of 'index' field in structure page [1]. [1] https://lore.kernel.org/all/zp8fgusibgq1t...@casper.infradead.org/ Cc: Matthew Wilcox Signed-off-by: Chao Yu --- fs/f2fs/compress.c | 2 +- fs/f2fs/data.c | 12 ++-- fs/f2fs/dir.c | 3 ++- fs/f2fs/inode.c| 3 ++- fs/f2fs/node.c | 4 ++-- fs/f2fs/segment.c | 3 ++- 6 files changed, 15 insertions(+), 12 deletions(-) diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c index 67bb1e2e07a4..163ad0d7d495 100644 --- a/fs/f2fs/compress.c +++ b/fs/f2fs/compress.c @@ -881,7 +881,7 @@ static bool cluster_has_invalid_data(struct compress_ctx *cc) f2fs_bug_on(F2FS_I_SB(cc->inode), !page); /* beyond EOF */ - if (page->index >= nr_pages) + if (page_folio(page)->index >= nr_pages) return true; } return false; diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index e69097267b99..c6d688208f8b 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -354,7 +354,7 @@ static void f2fs_write_end_io(struct bio *bio) } f2fs_bug_on(sbi, page->mapping == NODE_MAPPING(sbi) && - page->index != nid_of_node(page)); + page_folio(page)->index != nid_of_node(page)); dec_page_count(sbi, type); if (f2fs_in_warm_node_list(sbi, page)) @@ -703,7 +703,7 @@ int f2fs_submit_page_bio(struct f2fs_io_info *fio) bio = __bio_alloc(fio, 1); f2fs_set_bio_crypt_ctx(bio, fio->page->mapping->host, - fio->page->index, fio, GFP_NOIO); + page_folio(fio->page)->index, fio, GFP_NOIO); if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) { bio_put(bio); @@ -802,7 +802,7 @@ static int add_ipu_page(struct f2fs_io_info *fio, struct bio **bio, fio->new_blkaddr)); if (f2fs_crypt_mergeable_bio(*bio, fio->page->mapping->host, - fio->page->index, fio) && + page_folio(fio->page)->index, fio) && bio_add_page(*bio, page, PAGE_SIZE, 0) == PAGE_SIZE) { ret = 0; @@ -902,7 +902,7 @@ int f2fs_merge_page_bio(struct f2fs_io_info *fio) if (!bio) { bio = __bio_alloc(fio, BIO_MAX_VECS); f2fs_set_bio_crypt_ctx(bio, fio->page->mapping->host, - fio->page->index, fio, GFP_NOIO); + page_folio(fio->page)->index, fio, GFP_NOIO); add_bio_entry(fio->sbi, bio, page, fio->temp); } else { @@ -995,13 +995,13 @@ void f2fs_submit_page_write(struct f2fs_io_info *fio) (!io_is_mergeable(sbi, io->bio, io, fio, io->last_block_in_bio, fio->new_blkaddr) || !f2fs_crypt_mergeable_bio(io->bio, fio->page->mapping->host, - bio_page->index, fio))) + page_folio(bio_page)->index, fio))) __submit_merged_bio(io); alloc_new: if (io->bio == NULL) { io->bio = __bio_alloc(fio, BIO_MAX_VECS); f2fs_set_bio_crypt_ctx(io->bio, fio->page->mapping->host, - bio_page->index, fio, GFP_NOIO); + page_folio(bio_page)->index, fio, GFP_NOIO); io->fio = *fio; } diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c index 5fcc952107e9..1136539a57a8 100644 --- a/fs/f2fs/dir.c +++ b/fs/f2fs/dir.c @@ -842,6 +842,7 @@ void f2fs_delete_entry(struct f2fs_dir_entry *dentry, struct page *page, struct f2fs_dentry_block *dentry_blk; unsigned int bit_pos; int slots = GET_DENTRY_SLOTS(le16_to_cpu(dentry->name_len)); + pgoff_t index = page_folio(page)->index; int i; f2fs_update_time(F2FS_I_SB(dir), REQ_TIME); @@ -867,7 +868,7 @@ void f2fs_delete_entry(struct f2fs_dir_entry *dentry, struct page *page, set_page_dirty(page); if (bit_pos == NR_DENTRY_IN_BLOCK && - !f2fs_truncate_hole(dir, page->index, page->index + 1)) { + !f2fs_truncate_hole(dir, index, index + 1)) { f2fs_clear_page_cache_dirty_tag(page_folio(page)); clear_page_dirty_for_io(page); ClearPageUptodate(page); diff --git a/fs/f2fs/inode.c b/fs/f2fs/inod
[f2fs-dev] [PATCH v2 5/8] f2fs: convert f2fs_write_data_page() to use folio
Convert to use folio, so that we can get rid of 'page->index' to prepare for removal of 'index' field in structure page [1]. [1] https://lore.kernel.org/all/zp8fgusibgq1t...@casper.infradead.org/ Cc: Matthew Wilcox Signed-off-by: Chao Yu --- fs/f2fs/data.c | 9 + 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index c57ddee2c7c5..e69097267b99 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -2945,22 +2945,23 @@ int f2fs_write_single_data_page(struct folio *folio, int *submitted, static int f2fs_write_data_page(struct page *page, struct writeback_control *wbc) { + struct folio *folio = page_folio(page); #ifdef CONFIG_F2FS_FS_COMPRESSION - struct inode *inode = page->mapping->host; + struct inode *inode = folio->mapping->host; if (unlikely(f2fs_cp_error(F2FS_I_SB(inode goto out; if (f2fs_compressed_file(inode)) { - if (f2fs_is_compressed_cluster(inode, page->index)) { - redirty_page_for_writepage(wbc, page); + if (f2fs_is_compressed_cluster(inode, folio->index)) { + folio_redirty_for_writepage(wbc, folio); return AOP_WRITEPAGE_ACTIVATE; } } out: #endif - return f2fs_write_single_data_page(page_folio(page), NULL, NULL, NULL, + return f2fs_write_single_data_page(folio, NULL, NULL, NULL, wbc, FS_DATA_IO, 0, true); } -- 2.40.1 ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
[f2fs-dev] [PATCH v2 7/8] f2fs: convert read_node_page() to use folio
Convert to use folio, so that we can get rid of 'page->index' to prepare for removal of 'index' field in structure page [1]. [1] https://lore.kernel.org/all/zp8fgusibgq1t...@casper.infradead.org/ Cc: Matthew Wilcox Signed-off-by: Chao Yu --- fs/f2fs/node.c | 9 + 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index aeda3eecc9e2..f5e5abce695b 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c @@ -1369,6 +1369,7 @@ struct page *f2fs_new_node_page(struct dnode_of_data *dn, unsigned int ofs) */ static int read_node_page(struct page *page, blk_opf_t op_flags) { + struct folio *folio = page_folio(page); struct f2fs_sb_info *sbi = F2FS_P_SB(page); struct node_info ni; struct f2fs_io_info fio = { @@ -1381,21 +1382,21 @@ static int read_node_page(struct page *page, blk_opf_t op_flags) }; int err; - if (PageUptodate(page)) { + if (folio_test_uptodate(folio)) { if (!f2fs_inode_chksum_verify(sbi, page)) { - ClearPageUptodate(page); + folio_clear_uptodate(folio); return -EFSBADCRC; } return LOCKED_PAGE; } - err = f2fs_get_node_info(sbi, page->index, &ni, false); + err = f2fs_get_node_info(sbi, folio->index, &ni, false); if (err) return err; /* NEW_ADDR can be seen, after cp_error drops some dirty node pages */ if (unlikely(ni.blk_addr == NULL_ADDR || ni.blk_addr == NEW_ADDR)) { - ClearPageUptodate(page); + folio_clear_uptodate(folio); return -ENOENT; } -- 2.40.1 ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
[f2fs-dev] [PATCH v2 1/8] f2fs: convert f2fs_write_begin() to use folio
Convert to use folio, so that we can get rid of 'page->index' to prepare for removal of 'index' field in structure page [1]. [1] https://lore.kernel.org/all/zp8fgusibgq1t...@casper.infradead.org/ Cc: Matthew Wilcox Signed-off-by: Chao Yu --- v2: - fix compile error. fs/f2fs/data.c | 44 +++- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 0655fddfc4ba..85ac05c3655a 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -3378,11 +3378,11 @@ void f2fs_write_failed(struct inode *inode, loff_t to) } static int prepare_write_begin(struct f2fs_sb_info *sbi, - struct page *page, loff_t pos, unsigned len, + struct folio *folio, loff_t pos, unsigned int len, block_t *blk_addr, bool *node_changed) { - struct inode *inode = page->mapping->host; - pgoff_t index = page->index; + struct inode *inode = folio->mapping->host; + pgoff_t index = folio->index; struct dnode_of_data dn; struct page *ipage; bool locked = false; @@ -3419,13 +3419,13 @@ static int prepare_write_begin(struct f2fs_sb_info *sbi, if (f2fs_has_inline_data(inode)) { if (pos + len <= MAX_INLINE_DATA(inode)) { - f2fs_do_read_inline_data(page_folio(page), ipage); + f2fs_do_read_inline_data(folio, ipage); set_inode_flag(inode, FI_DATA_EXIST); if (inode->i_nlink) set_page_private_inline(ipage); goto out; } - err = f2fs_convert_inline_page(&dn, page); + err = f2fs_convert_inline_page(&dn, folio_page(folio, 0)); if (err || dn.data_blkaddr != NULL_ADDR) goto out; } @@ -3518,12 +3518,12 @@ static int __reserve_data_block(struct inode *inode, pgoff_t index, } static int prepare_atomic_write_begin(struct f2fs_sb_info *sbi, - struct page *page, loff_t pos, unsigned int len, + struct folio *folio, loff_t pos, unsigned int len, block_t *blk_addr, bool *node_changed, bool *use_cow) { - struct inode *inode = page->mapping->host; + struct inode *inode = folio->mapping->host; struct inode *cow_inode = F2FS_I(inode)->cow_inode; - pgoff_t index = page->index; + pgoff_t index = folio->index; int err = 0; block_t ori_blk_addr = NULL_ADDR; @@ -3566,6 +3566,7 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping, struct inode *inode = mapping->host; struct f2fs_sb_info *sbi = F2FS_I_SB(inode); struct page *page = NULL; + struct folio *folio; pgoff_t index = ((unsigned long long) pos) >> PAGE_SHIFT; bool need_balance = false; bool use_cow = false; @@ -3625,22 +3626,23 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping, /* TODO: cluster can be compressed due to race with .writepage */ *pagep = page; + folio = page_folio(page); if (f2fs_is_atomic_file(inode)) - err = prepare_atomic_write_begin(sbi, page, pos, len, + err = prepare_atomic_write_begin(sbi, folio, pos, len, &blkaddr, &need_balance, &use_cow); else - err = prepare_write_begin(sbi, page, pos, len, + err = prepare_write_begin(sbi, folio, pos, len, &blkaddr, &need_balance); if (err) goto fail; if (need_balance && !IS_NOQUOTA(inode) && has_not_enough_free_secs(sbi, 0, 0)) { - unlock_page(page); + folio_unlock(folio); f2fs_balance_fs(sbi, true); - lock_page(page); - if (page->mapping != mapping) { + folio_lock(folio); + if (folio->mapping != mapping) { /* The page got truncated from under us */ f2fs_put_page(page, 1); goto repeat; @@ -3649,18 +3651,18 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping, f2fs_wait_on_page_writeback(page, DATA, false, true); - if (len == PAGE_SIZE || PageUptodate(page)) + if (len == PAGE_SIZE || folio_test_uptodate(folio)) return 0; if (!(pos & (PAGE_SIZE - 1)) && (pos + len) >= i_size_read(inode) && !f2fs_verity_in_progress(inode)) { - zero_user_segment(page, len, PAGE_SIZE); + folio_zero_segment(folio,
[f2fs-dev] [PATCH v2 4/8] f2fs: convert f2fs_do_write_data_page() to use folio
Convert to use folio, so that we can get rid of 'page->index' to prepare for removal of 'index' field in structure page [1]. [1] https://lore.kernel.org/all/zp8fgusibgq1t...@casper.infradead.org/ Cc: Matthew Wilcox Signed-off-by: Chao Yu --- fs/f2fs/data.c | 26 +- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index e114d738b6b4..c57ddee2c7c5 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -2648,8 +2648,8 @@ static inline bool need_inplace_update(struct f2fs_io_info *fio) int f2fs_do_write_data_page(struct f2fs_io_info *fio) { - struct page *page = fio->page; - struct inode *inode = page->mapping->host; + struct folio *folio = page_folio(fio->page); + struct inode *inode = folio->mapping->host; struct dnode_of_data dn; struct node_info ni; bool ipu_force = false; @@ -2658,14 +2658,14 @@ int f2fs_do_write_data_page(struct f2fs_io_info *fio) /* Use COW inode to make dnode_of_data for atomic write */ atomic_commit = f2fs_is_atomic_file(inode) && - page_private_atomic(fio->page); + page_private_atomic(folio_page(folio, 0)); if (atomic_commit) set_new_dnode(&dn, F2FS_I(inode)->cow_inode, NULL, NULL, 0); else set_new_dnode(&dn, inode, NULL, NULL, 0); if (need_inplace_update(fio) && - f2fs_lookup_read_extent_cache_block(inode, page->index, + f2fs_lookup_read_extent_cache_block(inode, folio->index, &fio->old_blkaddr)) { if (!f2fs_is_valid_blkaddr(fio->sbi, fio->old_blkaddr, DATA_GENERIC_ENHANCE)) @@ -2680,7 +2680,7 @@ int f2fs_do_write_data_page(struct f2fs_io_info *fio) if (fio->need_lock == LOCK_REQ && !f2fs_trylock_op(fio->sbi)) return -EAGAIN; - err = f2fs_get_dnode_of_data(&dn, page->index, LOOKUP_NODE); + err = f2fs_get_dnode_of_data(&dn, folio->index, LOOKUP_NODE); if (err) goto out; @@ -2688,8 +2688,8 @@ int f2fs_do_write_data_page(struct f2fs_io_info *fio) /* This page is already truncated */ if (fio->old_blkaddr == NULL_ADDR) { - ClearPageUptodate(page); - clear_page_private_gcing(page); + folio_clear_uptodate(folio); + clear_page_private_gcing(folio_page(folio, 0)); goto out_writepage; } got_it: @@ -2715,7 +2715,7 @@ int f2fs_do_write_data_page(struct f2fs_io_info *fio) if (err) goto out_writepage; - set_page_writeback(page); + folio_start_writeback(folio); f2fs_put_dnode(&dn); if (fio->need_lock == LOCK_REQ) f2fs_unlock_op(fio->sbi); @@ -2723,11 +2723,11 @@ int f2fs_do_write_data_page(struct f2fs_io_info *fio) if (err) { if (fscrypt_inode_uses_fs_layer_crypto(inode)) fscrypt_finalize_bounce_page(&fio->encrypted_page); - end_page_writeback(page); + folio_end_writeback(folio); } else { set_inode_flag(inode, FI_UPDATE_WRITE); } - trace_f2fs_do_write_data_page(page_folio(page), IPU); + trace_f2fs_do_write_data_page(folio, IPU); return err; } @@ -2749,17 +2749,17 @@ int f2fs_do_write_data_page(struct f2fs_io_info *fio) if (err) goto out_writepage; - set_page_writeback(page); + folio_start_writeback(folio); if (fio->compr_blocks && fio->old_blkaddr == COMPRESS_ADDR) f2fs_i_compr_blocks_update(inode, fio->compr_blocks - 1, false); /* LFS mode write path */ f2fs_outplace_write_data(&dn, fio); - trace_f2fs_do_write_data_page(page_folio(page), OPU); + trace_f2fs_do_write_data_page(folio, OPU); set_inode_flag(inode, FI_APPEND_WRITE); if (atomic_commit) - clear_page_private_atomic(page); + clear_page_private_atomic(folio_page(folio, 0)); out_writepage: f2fs_put_dnode(&dn); out: -- 2.40.1 ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
[f2fs-dev] [PATCH v2 2/8] f2fs: convert f2fs_write_end() to use folio
Convert to use folio, so that we can get rid of 'page->index' to prepare for removal of 'index' field in structure page [1]. [1] https://lore.kernel.org/all/zp8fgusibgq1t...@casper.infradead.org/ Cc: Matthew Wilcox Signed-off-by: Chao Yu --- v2: - fix compile error. fs/f2fs/data.c | 13 +++-- 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 85ac05c3655a..e114d738b6b4 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -3698,7 +3698,8 @@ static int f2fs_write_end(struct file *file, loff_t pos, unsigned len, unsigned copied, struct page *page, void *fsdata) { - struct inode *inode = page->mapping->host; + struct folio *folio = page_folio(page); + struct inode *inode = folio->mapping->host; trace_f2fs_write_end(inode, pos, len, copied); @@ -3707,17 +3708,17 @@ static int f2fs_write_end(struct file *file, * should be PAGE_SIZE. Otherwise, we treat it with zero copied and * let generic_perform_write() try to copy data again through copied=0. */ - if (!PageUptodate(page)) { + if (!folio_test_uptodate(folio)) { if (unlikely(copied != len)) copied = 0; else - SetPageUptodate(page); + folio_mark_uptodate(folio); } #ifdef CONFIG_F2FS_FS_COMPRESSION /* overwrite compressed file */ if (f2fs_compressed_file(inode) && fsdata) { - f2fs_compress_write_end(inode, fsdata, page->index, copied); + f2fs_compress_write_end(inode, fsdata, folio->index, copied); f2fs_update_time(F2FS_I_SB(inode), REQ_TIME); if (pos + copied > i_size_read(inode) && @@ -3730,10 +3731,10 @@ static int f2fs_write_end(struct file *file, if (!copied) goto unlock_out; - set_page_dirty(page); + folio_mark_dirty(folio); if (f2fs_is_atomic_file(inode)) - set_page_private_atomic(page); + set_page_private_atomic(folio_page(folio, 0)); if (pos + copied > i_size_read(inode) && !f2fs_verity_in_progress(inode)) { -- 2.40.1 ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
[f2fs-dev] [PATCH v2 3/8] f2fs: convert f2fs_set_compressed_page() to use folio
Convert to use folio, so that we can get rid of 'page->index' to prepare for removal of 'index' field in structure page [1]. [1] https://lore.kernel.org/all/zp8fgusibgq1t...@casper.infradead.org/ Cc: Matthew Wilcox Signed-off-by: Chao Yu --- fs/f2fs/compress.c | 8 +--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c index 82c31641e696..67bb1e2e07a4 100644 --- a/fs/f2fs/compress.c +++ b/fs/f2fs/compress.c @@ -90,11 +90,13 @@ bool f2fs_is_compressed_page(struct page *page) static void f2fs_set_compressed_page(struct page *page, struct inode *inode, pgoff_t index, void *data) { - attach_page_private(page, (void *)data); + struct folio *folio = page_folio(page); + + folio_attach_private(folio, (void *)data); /* i_crypto_info and iv index */ - page->index = index; - page->mapping = inode->i_mapping; + folio->index = index; + folio->mapping = inode->i_mapping; } static void f2fs_drop_rpages(struct compress_ctx *cc, int len, bool unlock) -- 2.40.1 ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
Re: [f2fs-dev] [PATCH 2/8] f2fs: convert f2fs_write_end() to use folio
On 2024/8/20 11:04, Li Zetao wrote: Hi, 在 2024/8/19 9:20, Chao Yu 写道: Convert to use folio, so that we can get rid of 'page->index' to prepare for removal of 'index' field in structure page [1]. [1] https://lore.kernel.org/all/zp8fgusibgq1t...@casper.infradead.org/ Cc: Matthew Wilcox Signed-off-by: Chao Yu --- fs/f2fs/data.c | 19 ++- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 9e1ade13060c..e114d738b6b4 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -3378,7 +3378,7 @@ void f2fs_write_failed(struct inode *inode, loff_t to) } static int prepare_write_begin(struct f2fs_sb_info *sbi, - struct page *page, loff_t pos, unsigned len, + struct folio *folio, loff_t pos, unsigned int len, block_t *blk_addr, bool *node_changed) { struct inode *inode = folio->mapping->host; @@ -3425,7 +3425,7 @@ static int prepare_write_begin(struct f2fs_sb_info *sbi, set_page_private_inline(ipage); goto out; } - err = f2fs_convert_inline_page(&dn, page); + err = f2fs_convert_inline_page(&dn, folio_page(folio, 0)); if (err || dn.data_blkaddr != NULL_ADDR) goto out; } @@ -3629,7 +3629,7 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping, folio = page_folio(page); if (f2fs_is_atomic_file(inode)) - err = prepare_atomic_write_begin(sbi, folio, pos, len + err = prepare_atomic_write_begin(sbi, folio, pos, len, Thanks for your reminder, I removed comma after @len in patch 1/8 by mistake, let me fix it. Thanks, This has been changed in the first patch, it is redundant here. &blkaddr, &need_balance, &use_cow); else err = prepare_write_begin(sbi, folio, pos, len, @@ -3698,7 +3698,8 @@ static int f2fs_write_end(struct file *file, loff_t pos, unsigned len, unsigned copied, struct page *page, void *fsdata) { - struct inode *inode = page->mapping->host; + struct folio *folio = page_folio(page); + struct inode *inode = folio->mapping->host; trace_f2fs_write_end(inode, pos, len, copied); @@ -3707,17 +3708,17 @@ static int f2fs_write_end(struct file *file, * should be PAGE_SIZE. Otherwise, we treat it with zero copied and * let generic_perform_write() try to copy data again through copied=0. */ - if (!PageUptodate(page)) { + if (!folio_test_uptodate(folio)) { if (unlikely(copied != len)) copied = 0; else - SetPageUptodate(page); + folio_mark_uptodate(folio); } #ifdef CONFIG_F2FS_FS_COMPRESSION /* overwrite compressed file */ if (f2fs_compressed_file(inode) && fsdata) { - f2fs_compress_write_end(inode, fsdata, page->index, copied); + f2fs_compress_write_end(inode, fsdata, folio->index, copied); f2fs_update_time(F2FS_I_SB(inode), REQ_TIME); if (pos + copied > i_size_read(inode) && @@ -3730,10 +3731,10 @@ static int f2fs_write_end(struct file *file, if (!copied) goto unlock_out; - set_page_dirty(page); + folio_mark_dirty(folio); if (f2fs_is_atomic_file(inode)) - set_page_private_atomic(page); + set_page_private_atomic(folio_page(folio, 0)); if (pos + copied > i_size_read(inode) && !f2fs_verity_in_progress(inode)) { ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
Re: [f2fs-dev] [PATCH v2] f2fs: check discard support for conventional zones
On 2024/8/16 12:07, Shin'ichiro Kawasaki wrote: As the helper function f2fs_bdev_support_discard() shows, f2fs checks if the target block devices support discard by calling bdev_max_discard_sectors() and bdev_is_zoned(). This check works well for most cases, but it does not work for conventional zones on zoned block devices. F2fs assumes that zoned block devices support discard, and calls __submit_discard_cmd(). When __submit_discard_cmd() is called for sequential write required zones, it works fine since __submit_discard_cmd() issues zone reset commands instead of discard commands. However, when __submit_discard_cmd() is called for conventional zones, __blkdev_issue_discard() is called even when the devices do not support discard. The inappropriate __blkdev_issue_discard() call was not a problem before the commit 30f1e7241422 ("block: move discard checks into the ioctl handler") because __blkdev_issue_discard() checked if the target devices support discard or not. If not, it returned EOPNOTSUPP. After the commit, __blkdev_issue_discard() no longer checks it. It always returns zero and sets NULL to the given bio pointer. This NULL pointer triggers f2fs_bug_on() in __submit_discard_cmd(). The BUG is recreated with the commands below at the umount step, where /dev/nullb0 is a zoned null_blk with 5GB total size, 128MB zone size and 10 conventional zones. $ mkfs.f2fs -f -m /dev/nullb0 $ mount /dev/nullb0 /mnt $ for ((i=0;i<5;i++)); do dd if=/dev/zero of=/mnt/test bs=65536 count=1600 conv=fsync; done $ umount /mnt To fix the BUG, avoid the inappropriate __blkdev_issue_discard() call. When discard is requested for conventional zones, check if the device supports discard or not. If not, return EOPNOTSUPP. Fixes: 30f1e7241422 ("block: move discard checks into the ioctl handler") Cc: sta...@vger.kernel.org Signed-off-by: Shin'ichiro Kawasaki Reviewed-by: Damien Le Moal Reviewed-by: Chao Yu Thanks, ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
Re: [f2fs-dev] [syzbot] [f2fs?] kernel BUG in f2fs_vm_page_mkwrite
#syz fix: f2fs: fix return value of f2fs_convert_inline_inode() On 2024/8/5 23:22, syzbot wrote: syzbot suspects this issue was fixed by commit: commit a8eb3de28e7a365690c61161e7a07a4fc7c60bbf Author: Chao Yu Date: Mon Jun 3 01:07:45 2024 + f2fs: fix return value of f2fs_convert_inline_inode() bisection log: https://syzkaller.appspot.com/x/bisect.txt?x=1055414b98 start commit: 83814698cf48 Merge tag 'powerpc-6.10-2' of git://git.kerne.. git tree: upstream kernel config: https://syzkaller.appspot.com/x/.config?x=238430243a58f702 dashboard link: https://syzkaller.appspot.com/bug?extid=f195123a45ad487ca66c syz repro: https://syzkaller.appspot.com/x/repro.syz?x=1129d36298 C reproducer: https://syzkaller.appspot.com/x/repro.c?x=10d4ce0698 If the result looks correct, please mark the issue as fixed by replying with: #syz fix: f2fs: fix return value of f2fs_convert_inline_inode() For information about bisection process see: https://goo.gl/tpsmEJ#bisection ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
Re: [f2fs-dev] [PATCH v2] f2fs: compress: don't redirty sparse cluster during {, de}compress
On 2024/8/19 16:34, Yeongjin Gil wrote: In f2fs_do_write_data_page, when the data block is NULL_ADDR, it skips writepage considering that it has been already truncated. This results in an infinite loop as the PAGECACHE_TAG_TOWRITE tag is not cleared during the writeback process for a compressed file including NULL_ADDR in compress_mode=user. This is the reproduction process: 1. dd if=/dev/zero bs=4096 count=1024 seek=1024 of=testfile 2. f2fs_io compress testfile 3. dd if=/dev/zero bs=4096 count=1 conv=notrunc of=testfile 4. f2fs_io decompress testfile To prevent the problem, let's check whether the cluster is fully allocated before redirty its pages. Fixes: 5fdb322ff2c2 ("f2fs: add F2FS_IOC_DECOMPRESS_FILE and F2FS_IOC_COMPRESS_FILE") Reviewed-by: Sungjong Seo Reviewed-by: Sunmin Jeong Tested-by: Jaewook Kim Signed-off-by: Yeongjin Gil Reviewed-by: Chao Yu Thanks, ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
[f2fs-dev] [PATCH 7/8] f2fs: convert read_node_page() to use folio
Convert to use folio, so that we can get rid of 'page->index' to prepare for removal of 'index' field in structure page [1]. [1] https://lore.kernel.org/all/zp8fgusibgq1t...@casper.infradead.org/ Cc: Matthew Wilcox Signed-off-by: Chao Yu --- fs/f2fs/node.c | 9 + 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index aeda3eecc9e2..f5e5abce695b 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c @@ -1369,6 +1369,7 @@ struct page *f2fs_new_node_page(struct dnode_of_data *dn, unsigned int ofs) */ static int read_node_page(struct page *page, blk_opf_t op_flags) { + struct folio *folio = page_folio(page); struct f2fs_sb_info *sbi = F2FS_P_SB(page); struct node_info ni; struct f2fs_io_info fio = { @@ -1381,21 +1382,21 @@ static int read_node_page(struct page *page, blk_opf_t op_flags) }; int err; - if (PageUptodate(page)) { + if (folio_test_uptodate(folio)) { if (!f2fs_inode_chksum_verify(sbi, page)) { - ClearPageUptodate(page); + folio_clear_uptodate(folio); return -EFSBADCRC; } return LOCKED_PAGE; } - err = f2fs_get_node_info(sbi, page->index, &ni, false); + err = f2fs_get_node_info(sbi, folio->index, &ni, false); if (err) return err; /* NEW_ADDR can be seen, after cp_error drops some dirty node pages */ if (unlikely(ni.blk_addr == NULL_ADDR || ni.blk_addr == NEW_ADDR)) { - ClearPageUptodate(page); + folio_clear_uptodate(folio); return -ENOENT; } -- 2.40.1 ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
[f2fs-dev] [PATCH 8/8] f2fs: get rid of page->index
Convert to use folio, so that we can get rid of 'page->index' to prepare for removal of 'index' field in structure page [1]. [1] https://lore.kernel.org/all/zp8fgusibgq1t...@casper.infradead.org/ Cc: Matthew Wilcox Signed-off-by: Chao Yu --- fs/f2fs/compress.c | 2 +- fs/f2fs/data.c | 12 ++-- fs/f2fs/dir.c | 3 ++- fs/f2fs/inode.c| 3 ++- fs/f2fs/node.c | 4 ++-- fs/f2fs/segment.c | 3 ++- 6 files changed, 15 insertions(+), 12 deletions(-) diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c index 67bb1e2e07a4..163ad0d7d495 100644 --- a/fs/f2fs/compress.c +++ b/fs/f2fs/compress.c @@ -881,7 +881,7 @@ static bool cluster_has_invalid_data(struct compress_ctx *cc) f2fs_bug_on(F2FS_I_SB(cc->inode), !page); /* beyond EOF */ - if (page->index >= nr_pages) + if (page_folio(page)->index >= nr_pages) return true; } return false; diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index e69097267b99..c6d688208f8b 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -354,7 +354,7 @@ static void f2fs_write_end_io(struct bio *bio) } f2fs_bug_on(sbi, page->mapping == NODE_MAPPING(sbi) && - page->index != nid_of_node(page)); + page_folio(page)->index != nid_of_node(page)); dec_page_count(sbi, type); if (f2fs_in_warm_node_list(sbi, page)) @@ -703,7 +703,7 @@ int f2fs_submit_page_bio(struct f2fs_io_info *fio) bio = __bio_alloc(fio, 1); f2fs_set_bio_crypt_ctx(bio, fio->page->mapping->host, - fio->page->index, fio, GFP_NOIO); + page_folio(fio->page)->index, fio, GFP_NOIO); if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) { bio_put(bio); @@ -802,7 +802,7 @@ static int add_ipu_page(struct f2fs_io_info *fio, struct bio **bio, fio->new_blkaddr)); if (f2fs_crypt_mergeable_bio(*bio, fio->page->mapping->host, - fio->page->index, fio) && + page_folio(fio->page)->index, fio) && bio_add_page(*bio, page, PAGE_SIZE, 0) == PAGE_SIZE) { ret = 0; @@ -902,7 +902,7 @@ int f2fs_merge_page_bio(struct f2fs_io_info *fio) if (!bio) { bio = __bio_alloc(fio, BIO_MAX_VECS); f2fs_set_bio_crypt_ctx(bio, fio->page->mapping->host, - fio->page->index, fio, GFP_NOIO); + page_folio(fio->page)->index, fio, GFP_NOIO); add_bio_entry(fio->sbi, bio, page, fio->temp); } else { @@ -995,13 +995,13 @@ void f2fs_submit_page_write(struct f2fs_io_info *fio) (!io_is_mergeable(sbi, io->bio, io, fio, io->last_block_in_bio, fio->new_blkaddr) || !f2fs_crypt_mergeable_bio(io->bio, fio->page->mapping->host, - bio_page->index, fio))) + page_folio(bio_page)->index, fio))) __submit_merged_bio(io); alloc_new: if (io->bio == NULL) { io->bio = __bio_alloc(fio, BIO_MAX_VECS); f2fs_set_bio_crypt_ctx(io->bio, fio->page->mapping->host, - bio_page->index, fio, GFP_NOIO); + page_folio(bio_page)->index, fio, GFP_NOIO); io->fio = *fio; } diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c index 5fcc952107e9..1136539a57a8 100644 --- a/fs/f2fs/dir.c +++ b/fs/f2fs/dir.c @@ -842,6 +842,7 @@ void f2fs_delete_entry(struct f2fs_dir_entry *dentry, struct page *page, struct f2fs_dentry_block *dentry_blk; unsigned int bit_pos; int slots = GET_DENTRY_SLOTS(le16_to_cpu(dentry->name_len)); + pgoff_t index = page_folio(page)->index; int i; f2fs_update_time(F2FS_I_SB(dir), REQ_TIME); @@ -867,7 +868,7 @@ void f2fs_delete_entry(struct f2fs_dir_entry *dentry, struct page *page, set_page_dirty(page); if (bit_pos == NR_DENTRY_IN_BLOCK && - !f2fs_truncate_hole(dir, page->index, page->index + 1)) { + !f2fs_truncate_hole(dir, index, index + 1)) { f2fs_clear_page_cache_dirty_tag(page_folio(page)); clear_page_dirty_for_io(page); ClearPageUptodate(page); diff --git a/fs/f2fs/inode.c b/fs/f2fs/inod
[f2fs-dev] [PATCH 5/8] f2fs: convert f2fs_write_data_page() to use folio
Convert to use folio, so that we can get rid of 'page->index' to prepare for removal of 'index' field in structure page [1]. [1] https://lore.kernel.org/all/zp8fgusibgq1t...@casper.infradead.org/ Cc: Matthew Wilcox Signed-off-by: Chao Yu --- fs/f2fs/data.c | 9 + 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index c57ddee2c7c5..e69097267b99 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -2945,22 +2945,23 @@ int f2fs_write_single_data_page(struct folio *folio, int *submitted, static int f2fs_write_data_page(struct page *page, struct writeback_control *wbc) { + struct folio *folio = page_folio(page); #ifdef CONFIG_F2FS_FS_COMPRESSION - struct inode *inode = page->mapping->host; + struct inode *inode = folio->mapping->host; if (unlikely(f2fs_cp_error(F2FS_I_SB(inode goto out; if (f2fs_compressed_file(inode)) { - if (f2fs_is_compressed_cluster(inode, page->index)) { - redirty_page_for_writepage(wbc, page); + if (f2fs_is_compressed_cluster(inode, folio->index)) { + folio_redirty_for_writepage(wbc, folio); return AOP_WRITEPAGE_ACTIVATE; } } out: #endif - return f2fs_write_single_data_page(page_folio(page), NULL, NULL, NULL, + return f2fs_write_single_data_page(folio, NULL, NULL, NULL, wbc, FS_DATA_IO, 0, true); } -- 2.40.1 ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
[f2fs-dev] [PATCH 1/8] f2fs: convert f2fs_write_begin() to use folio
Convert to use folio, so that we can get rid of 'page->index' to prepare for removal of 'index' field in structure page [1]. [1] https://lore.kernel.org/all/zp8fgusibgq1t...@casper.infradead.org/ Cc: Matthew Wilcox Signed-off-by: Chao Yu --- fs/f2fs/data.c | 40 +--- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 0655fddfc4ba..9e1ade13060c 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -3381,8 +3381,8 @@ static int prepare_write_begin(struct f2fs_sb_info *sbi, struct page *page, loff_t pos, unsigned len, block_t *blk_addr, bool *node_changed) { - struct inode *inode = page->mapping->host; - pgoff_t index = page->index; + struct inode *inode = folio->mapping->host; + pgoff_t index = folio->index; struct dnode_of_data dn; struct page *ipage; bool locked = false; @@ -3419,7 +3419,7 @@ static int prepare_write_begin(struct f2fs_sb_info *sbi, if (f2fs_has_inline_data(inode)) { if (pos + len <= MAX_INLINE_DATA(inode)) { - f2fs_do_read_inline_data(page_folio(page), ipage); + f2fs_do_read_inline_data(folio, ipage); set_inode_flag(inode, FI_DATA_EXIST); if (inode->i_nlink) set_page_private_inline(ipage); @@ -3518,12 +3518,12 @@ static int __reserve_data_block(struct inode *inode, pgoff_t index, } static int prepare_atomic_write_begin(struct f2fs_sb_info *sbi, - struct page *page, loff_t pos, unsigned int len, + struct folio *folio, loff_t pos, unsigned int len, block_t *blk_addr, bool *node_changed, bool *use_cow) { - struct inode *inode = page->mapping->host; + struct inode *inode = folio->mapping->host; struct inode *cow_inode = F2FS_I(inode)->cow_inode; - pgoff_t index = page->index; + pgoff_t index = folio->index; int err = 0; block_t ori_blk_addr = NULL_ADDR; @@ -3566,6 +3566,7 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping, struct inode *inode = mapping->host; struct f2fs_sb_info *sbi = F2FS_I_SB(inode); struct page *page = NULL; + struct folio *folio; pgoff_t index = ((unsigned long long) pos) >> PAGE_SHIFT; bool need_balance = false; bool use_cow = false; @@ -3625,22 +3626,23 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping, /* TODO: cluster can be compressed due to race with .writepage */ *pagep = page; + folio = page_folio(page); if (f2fs_is_atomic_file(inode)) - err = prepare_atomic_write_begin(sbi, page, pos, len, + err = prepare_atomic_write_begin(sbi, folio, pos, len &blkaddr, &need_balance, &use_cow); else - err = prepare_write_begin(sbi, page, pos, len, + err = prepare_write_begin(sbi, folio, pos, len, &blkaddr, &need_balance); if (err) goto fail; if (need_balance && !IS_NOQUOTA(inode) && has_not_enough_free_secs(sbi, 0, 0)) { - unlock_page(page); + folio_unlock(folio); f2fs_balance_fs(sbi, true); - lock_page(page); - if (page->mapping != mapping) { + folio_lock(folio); + if (folio->mapping != mapping) { /* The page got truncated from under us */ f2fs_put_page(page, 1); goto repeat; @@ -3649,18 +3651,18 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping, f2fs_wait_on_page_writeback(page, DATA, false, true); - if (len == PAGE_SIZE || PageUptodate(page)) + if (len == PAGE_SIZE || folio_test_uptodate(folio)) return 0; if (!(pos & (PAGE_SIZE - 1)) && (pos + len) >= i_size_read(inode) && !f2fs_verity_in_progress(inode)) { - zero_user_segment(page, len, PAGE_SIZE); + folio_zero_segment(folio, len, folio_size(folio)); return 0; } if (blkaddr == NEW_ADDR) { - zero_user_segment(page, 0, PAGE_SIZE); - SetPageUptodate(page); + folio_zero_segment(folio, 0, folio_size(folio)); + folio_mark_uptodate(folio); } else { if (!f2fs_is_valid_blkaddr(sbi, blkaddr, DATA_GENERIC_ENHANCE_READ)) { @@ -3669,16 +3671,16 @@ static
[f2fs-dev] [PATCH 4/8] f2fs: convert f2fs_do_write_data_page() to use folio
Convert to use folio, so that we can get rid of 'page->index' to prepare for removal of 'index' field in structure page [1]. [1] https://lore.kernel.org/all/zp8fgusibgq1t...@casper.infradead.org/ Cc: Matthew Wilcox Signed-off-by: Chao Yu --- fs/f2fs/data.c | 26 +- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index e114d738b6b4..c57ddee2c7c5 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -2648,8 +2648,8 @@ static inline bool need_inplace_update(struct f2fs_io_info *fio) int f2fs_do_write_data_page(struct f2fs_io_info *fio) { - struct page *page = fio->page; - struct inode *inode = page->mapping->host; + struct folio *folio = page_folio(fio->page); + struct inode *inode = folio->mapping->host; struct dnode_of_data dn; struct node_info ni; bool ipu_force = false; @@ -2658,14 +2658,14 @@ int f2fs_do_write_data_page(struct f2fs_io_info *fio) /* Use COW inode to make dnode_of_data for atomic write */ atomic_commit = f2fs_is_atomic_file(inode) && - page_private_atomic(fio->page); + page_private_atomic(folio_page(folio, 0)); if (atomic_commit) set_new_dnode(&dn, F2FS_I(inode)->cow_inode, NULL, NULL, 0); else set_new_dnode(&dn, inode, NULL, NULL, 0); if (need_inplace_update(fio) && - f2fs_lookup_read_extent_cache_block(inode, page->index, + f2fs_lookup_read_extent_cache_block(inode, folio->index, &fio->old_blkaddr)) { if (!f2fs_is_valid_blkaddr(fio->sbi, fio->old_blkaddr, DATA_GENERIC_ENHANCE)) @@ -2680,7 +2680,7 @@ int f2fs_do_write_data_page(struct f2fs_io_info *fio) if (fio->need_lock == LOCK_REQ && !f2fs_trylock_op(fio->sbi)) return -EAGAIN; - err = f2fs_get_dnode_of_data(&dn, page->index, LOOKUP_NODE); + err = f2fs_get_dnode_of_data(&dn, folio->index, LOOKUP_NODE); if (err) goto out; @@ -2688,8 +2688,8 @@ int f2fs_do_write_data_page(struct f2fs_io_info *fio) /* This page is already truncated */ if (fio->old_blkaddr == NULL_ADDR) { - ClearPageUptodate(page); - clear_page_private_gcing(page); + folio_clear_uptodate(folio); + clear_page_private_gcing(folio_page(folio, 0)); goto out_writepage; } got_it: @@ -2715,7 +2715,7 @@ int f2fs_do_write_data_page(struct f2fs_io_info *fio) if (err) goto out_writepage; - set_page_writeback(page); + folio_start_writeback(folio); f2fs_put_dnode(&dn); if (fio->need_lock == LOCK_REQ) f2fs_unlock_op(fio->sbi); @@ -2723,11 +2723,11 @@ int f2fs_do_write_data_page(struct f2fs_io_info *fio) if (err) { if (fscrypt_inode_uses_fs_layer_crypto(inode)) fscrypt_finalize_bounce_page(&fio->encrypted_page); - end_page_writeback(page); + folio_end_writeback(folio); } else { set_inode_flag(inode, FI_UPDATE_WRITE); } - trace_f2fs_do_write_data_page(page_folio(page), IPU); + trace_f2fs_do_write_data_page(folio, IPU); return err; } @@ -2749,17 +2749,17 @@ int f2fs_do_write_data_page(struct f2fs_io_info *fio) if (err) goto out_writepage; - set_page_writeback(page); + folio_start_writeback(folio); if (fio->compr_blocks && fio->old_blkaddr == COMPRESS_ADDR) f2fs_i_compr_blocks_update(inode, fio->compr_blocks - 1, false); /* LFS mode write path */ f2fs_outplace_write_data(&dn, fio); - trace_f2fs_do_write_data_page(page_folio(page), OPU); + trace_f2fs_do_write_data_page(folio, OPU); set_inode_flag(inode, FI_APPEND_WRITE); if (atomic_commit) - clear_page_private_atomic(page); + clear_page_private_atomic(folio_page(folio, 0)); out_writepage: f2fs_put_dnode(&dn); out: -- 2.40.1 ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
[f2fs-dev] [PATCH 6/8] f2fs: convert __write_node_page() to use folio
Convert to use folio, so that we can get rid of 'page->index' to prepare for removal of 'index' field in structure page [1]. [1] https://lore.kernel.org/all/zp8fgusibgq1t...@casper.infradead.org/ Cc: Matthew Wilcox Signed-off-by: Chao Yu --- fs/f2fs/node.c | 19 ++- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index 7beaa3690e03..aeda3eecc9e2 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c @@ -1608,6 +1608,7 @@ static int __write_node_page(struct page *page, bool atomic, bool *submitted, enum iostat_type io_type, unsigned int *seq_id) { struct f2fs_sb_info *sbi = F2FS_P_SB(page); + struct folio *folio = page_folio(page); nid_t nid; struct node_info ni; struct f2fs_io_info fio = { @@ -1624,15 +1625,15 @@ static int __write_node_page(struct page *page, bool atomic, bool *submitted, }; unsigned int seq; - trace_f2fs_writepage(page_folio(page), NODE); + trace_f2fs_writepage(folio, NODE); if (unlikely(f2fs_cp_error(sbi))) { /* keep node pages in remount-ro mode */ if (F2FS_OPTION(sbi).errors == MOUNT_ERRORS_READONLY) goto redirty_out; - ClearPageUptodate(page); + folio_clear_uptodate(folio); dec_page_count(sbi, F2FS_DIRTY_NODES); - unlock_page(page); + folio_unlock(folio); return 0; } @@ -1646,7 +1647,7 @@ static int __write_node_page(struct page *page, bool atomic, bool *submitted, /* get old block addr of this node page */ nid = nid_of_node(page); - f2fs_bug_on(sbi, page->index != nid); + f2fs_bug_on(sbi, folio->index != nid); if (f2fs_get_node_info(sbi, nid, &ni, !do_balance)) goto redirty_out; @@ -1660,10 +1661,10 @@ static int __write_node_page(struct page *page, bool atomic, bool *submitted, /* This page is already truncated */ if (unlikely(ni.blk_addr == NULL_ADDR)) { - ClearPageUptodate(page); + folio_clear_uptodate(folio); dec_page_count(sbi, F2FS_DIRTY_NODES); f2fs_up_read(&sbi->node_write); - unlock_page(page); + folio_unlock(folio); return 0; } @@ -1684,7 +1685,7 @@ static int __write_node_page(struct page *page, bool atomic, bool *submitted, *seq_id = seq; } - set_page_writeback(page); + folio_start_writeback(folio); fio.old_blkaddr = ni.blk_addr; f2fs_do_write_node_page(nid, &fio); @@ -1697,7 +1698,7 @@ static int __write_node_page(struct page *page, bool atomic, bool *submitted, submitted = NULL; } - unlock_page(page); + folio_unlock(folio); if (unlikely(f2fs_cp_error(sbi))) { f2fs_submit_merged_write(sbi, NODE); @@ -1711,7 +1712,7 @@ static int __write_node_page(struct page *page, bool atomic, bool *submitted, return 0; redirty_out: - redirty_page_for_writepage(wbc, page); + folio_redirty_for_writepage(wbc, folio); return AOP_WRITEPAGE_ACTIVATE; } -- 2.40.1 ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
[f2fs-dev] [PATCH 2/8] f2fs: convert f2fs_write_end() to use folio
Convert to use folio, so that we can get rid of 'page->index' to prepare for removal of 'index' field in structure page [1]. [1] https://lore.kernel.org/all/zp8fgusibgq1t...@casper.infradead.org/ Cc: Matthew Wilcox Signed-off-by: Chao Yu --- fs/f2fs/data.c | 19 ++- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 9e1ade13060c..e114d738b6b4 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -3378,7 +3378,7 @@ void f2fs_write_failed(struct inode *inode, loff_t to) } static int prepare_write_begin(struct f2fs_sb_info *sbi, - struct page *page, loff_t pos, unsigned len, + struct folio *folio, loff_t pos, unsigned int len, block_t *blk_addr, bool *node_changed) { struct inode *inode = folio->mapping->host; @@ -3425,7 +3425,7 @@ static int prepare_write_begin(struct f2fs_sb_info *sbi, set_page_private_inline(ipage); goto out; } - err = f2fs_convert_inline_page(&dn, page); + err = f2fs_convert_inline_page(&dn, folio_page(folio, 0)); if (err || dn.data_blkaddr != NULL_ADDR) goto out; } @@ -3629,7 +3629,7 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping, folio = page_folio(page); if (f2fs_is_atomic_file(inode)) - err = prepare_atomic_write_begin(sbi, folio, pos, len + err = prepare_atomic_write_begin(sbi, folio, pos, len, &blkaddr, &need_balance, &use_cow); else err = prepare_write_begin(sbi, folio, pos, len, @@ -3698,7 +3698,8 @@ static int f2fs_write_end(struct file *file, loff_t pos, unsigned len, unsigned copied, struct page *page, void *fsdata) { - struct inode *inode = page->mapping->host; + struct folio *folio = page_folio(page); + struct inode *inode = folio->mapping->host; trace_f2fs_write_end(inode, pos, len, copied); @@ -3707,17 +3708,17 @@ static int f2fs_write_end(struct file *file, * should be PAGE_SIZE. Otherwise, we treat it with zero copied and * let generic_perform_write() try to copy data again through copied=0. */ - if (!PageUptodate(page)) { + if (!folio_test_uptodate(folio)) { if (unlikely(copied != len)) copied = 0; else - SetPageUptodate(page); + folio_mark_uptodate(folio); } #ifdef CONFIG_F2FS_FS_COMPRESSION /* overwrite compressed file */ if (f2fs_compressed_file(inode) && fsdata) { - f2fs_compress_write_end(inode, fsdata, page->index, copied); + f2fs_compress_write_end(inode, fsdata, folio->index, copied); f2fs_update_time(F2FS_I_SB(inode), REQ_TIME); if (pos + copied > i_size_read(inode) && @@ -3730,10 +3731,10 @@ static int f2fs_write_end(struct file *file, if (!copied) goto unlock_out; - set_page_dirty(page); + folio_mark_dirty(folio); if (f2fs_is_atomic_file(inode)) - set_page_private_atomic(page); + set_page_private_atomic(folio_page(folio, 0)); if (pos + copied > i_size_read(inode) && !f2fs_verity_in_progress(inode)) { -- 2.40.1 ___ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel