Re: [f2fs-dev] [PATCH] f2fs: introduce device aliasing file

2024-09-19 Thread Chao Yu via Linux-f2fs-devel

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

2024-09-19 Thread Chao Yu via Linux-f2fs-devel

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

2024-09-18 Thread Chao Yu via Linux-f2fs-devel

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

2024-09-18 Thread Chao Yu via Linux-f2fs-devel

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

2024-09-18 Thread Chao Yu via Linux-f2fs-devel

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

2024-09-18 Thread Chao Yu via Linux-f2fs-devel

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

2024-09-17 Thread Chao Yu via Linux-f2fs-devel

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

2024-09-17 Thread Chao Yu via Linux-f2fs-devel

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

2024-09-17 Thread Chao Yu via Linux-f2fs-devel

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

2024-09-12 Thread Chao Yu via Linux-f2fs-devel

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

2024-09-12 Thread Chao Yu via Linux-f2fs-devel

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

2024-09-12 Thread Chao Yu via Linux-f2fs-devel

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

2024-09-11 Thread Chao Yu via Linux-f2fs-devel

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

2024-09-11 Thread Chao Yu via Linux-f2fs-devel

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

2024-09-11 Thread Chao Yu via Linux-f2fs-devel

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

2024-09-11 Thread Chao Yu via Linux-f2fs-devel

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

2024-09-10 Thread Chao Yu via Linux-f2fs-devel

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

2024-09-10 Thread Chao Yu via Linux-f2fs-devel

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

2024-09-10 Thread Chao Yu via Linux-f2fs-devel

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

2024-09-10 Thread Chao Yu via Linux-f2fs-devel

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

2024-09-10 Thread Chao Yu via Linux-f2fs-devel

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

2024-09-10 Thread Chao Yu via Linux-f2fs-devel

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

2024-09-10 Thread Chao Yu via Linux-f2fs-devel

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

2024-09-10 Thread Chao Yu via Linux-f2fs-devel

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

2024-09-10 Thread Chao Yu via Linux-f2fs-devel

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

2024-09-10 Thread Chao Yu via Linux-f2fs-devel

#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

2024-09-10 Thread Chao Yu via Linux-f2fs-devel
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()

2024-09-09 Thread Chao Yu via Linux-f2fs-devel
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

2024-09-09 Thread Chao Yu via Linux-f2fs-devel
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

2024-09-09 Thread Chao Yu via Linux-f2fs-devel

#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

2024-09-09 Thread Chao Yu via Linux-f2fs-devel

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

2024-09-09 Thread Chao Yu via Linux-f2fs-devel

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

2024-09-09 Thread Chao Yu via Linux-f2fs-devel

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

2024-09-08 Thread Chao Yu via Linux-f2fs-devel

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"

2024-09-06 Thread Chao Yu via Linux-f2fs-devel

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

2024-09-05 Thread Chao Yu via Linux-f2fs-devel

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

2024-09-05 Thread Chao Yu via Linux-f2fs-devel

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

2024-09-05 Thread Chao Yu via Linux-f2fs-devel
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

2024-09-05 Thread Chao Yu via Linux-f2fs-devel

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

2024-09-05 Thread Chao Yu via Linux-f2fs-devel

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

2024-09-05 Thread Chao Yu via Linux-f2fs-devel

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

2024-09-05 Thread Chao Yu via Linux-f2fs-devel

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

2024-09-05 Thread Chao Yu via Linux-f2fs-devel

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

2024-09-04 Thread Chao Yu via Linux-f2fs-devel

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

2024-09-04 Thread Chao Yu via Linux-f2fs-devel

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)

2024-09-04 Thread Chao Yu via Linux-f2fs-devel

#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

2024-09-04 Thread Chao Yu via Linux-f2fs-devel

#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

2024-09-04 Thread Chao Yu via Linux-f2fs-devel

#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

2024-09-04 Thread Chao Yu via Linux-f2fs-devel

#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

2024-09-04 Thread Chao Yu via Linux-f2fs-devel

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

2024-09-04 Thread Chao Yu via Linux-f2fs-devel

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.

2024-09-04 Thread Chao Yu via Linux-f2fs-devel

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

2024-09-03 Thread Chao Yu via Linux-f2fs-devel

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

2024-09-03 Thread Chao Yu via Linux-f2fs-devel

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

2024-09-03 Thread Chao Yu via Linux-f2fs-devel
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

2024-09-03 Thread Chao Yu via Linux-f2fs-devel
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 '..'

2024-09-03 Thread Chao Yu via Linux-f2fs-devel
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

2024-09-03 Thread Chao Yu via Linux-f2fs-devel

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)

2024-09-03 Thread Chao Yu via Linux-f2fs-devel

#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.

2024-09-03 Thread Chao Yu via Linux-f2fs-devel

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

2024-09-02 Thread Chao Yu via Linux-f2fs-devel
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

2024-09-02 Thread Chao Yu via Linux-f2fs-devel

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.

2024-09-02 Thread Chao Yu via Linux-f2fs-devel

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

2024-09-02 Thread 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,



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

2024-09-01 Thread Chao Yu via Linux-f2fs-devel

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

2024-09-01 Thread Chao Yu via Linux-f2fs-devel

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

2024-08-21 Thread Chao Yu via Linux-f2fs-devel

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

2024-08-20 Thread 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 | 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

2024-08-20 Thread 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/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

2024-08-20 Thread 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 | 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

2024-08-20 Thread 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/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

2024-08-20 Thread 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/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

2024-08-20 Thread 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 | 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

2024-08-20 Thread 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 | 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

2024-08-20 Thread 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/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

2024-08-20 Thread 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 | 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

2024-08-19 Thread Chao Yu

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

2024-08-19 Thread 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/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

2024-08-19 Thread 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/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

2024-08-19 Thread 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 | 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

2024-08-19 Thread 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/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

2024-08-19 Thread 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 
---
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

2024-08-19 Thread 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 | 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

2024-08-19 Thread 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 
---
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

2024-08-19 Thread 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/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

2024-08-19 Thread Chao Yu

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

2024-08-19 Thread Chao Yu

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

2024-08-19 Thread Chao Yu

#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

2024-08-19 Thread Chao Yu

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

2024-08-18 Thread 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/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

2024-08-18 Thread 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/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

2024-08-18 Thread 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 | 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

2024-08-18 Thread 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 | 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

2024-08-18 Thread 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 | 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

2024-08-18 Thread 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/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

2024-08-18 Thread 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,
&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


[f2fs-dev] [PATCH 3/8] f2fs: convert f2fs_set_compressed_page() to use folio

2024-08-18 Thread 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/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] (2) [PATCH] f2fs: avoid unused block when dio write in LFS mode

2024-08-15 Thread Chao Yu

On 2024/8/16 8:17, Daejun Park wrote:

Hi Chao Yu,
  
- Original Message -

Sender : Chao Yu 
Date : 2024-08-14 18:50 (GMT+9)
Title : Re: [PATCH] f2fs: avoid unused block when dio write in LFS mode
  
On 2024/8/1 15:47, 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


I didn't get it, why below condition in map_is_mergeable() can not catch this
case? Can you please explain more?

        if (map->m_pblk != NEW_ADDR && blkaddr == (map->m_pblk + ofs))
                return true;



Thank you for your review.
map_is_mergeable() returns true when the last block in the section is merged.
The problem is the next block allocation, which happens consecutively.
Since it will be allocated a new section, its block will be the first
block in the section.
If the newly allocated section is not contiguous with the previous section,
map_is_mergeable() will return false.
So the block is allocated but unused.
However, it is not freed, so the block is unusable.
If my explanation was not clear enough, please feel free to ask questions.


It's clear to me now, thanks for your explanation.



Thanks
Daejun


Thanks,


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 
---
   fs/f2fs/data.c 13 +
   1 file changed, 13 insertions(+)

diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index b6dcb3bcaef7..b27a3f448f32 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -1711,6 +1711,19 @@ int f2fs_map_blocks(struct inode *inode, struct 
f2fs_map_blocks *map, int flag)
                    dn.ofs_in_node = end_offset;
            }
  
+        if (flag == F2FS_GET_BLOCK_DIO && f2fs_lfs_mode(sbi)) {


The condition should check map->m_may_create as well, otherwise 
f2fs_map_blocks()
from read path will break here?


+                int segno = GET_SEGNO(sbi, blkaddr);
+                bool last_seg, last_blk;
+
+                last_seg = !((segno + 1) % SEGS_PER_SEC(sbi));


Should consider the case that segno #(SEGS_PER_SEC - 1) is not valid?
e.g. SEGS_PER_SEC is 4, CAP_SEGS_PER_SEC is 2?


+                last_blk = (f2fs_usable_blks_in_seg(sbi, segno) - 1) ==
+                                GET_BLKOFF_FROM_SEG0(sbi, blkaddr);


if (GET_SEGOFF_FROM_SEG0() % BLKS_PER_SEC() == CAP_BLKS_PER_SEC() - 1)
goto sync_out;

Thanks,


+
+                /* LBA of the next block to be allocated may not be 
contiguous. */
+                if (last_seg && last_blk)
+                        goto sync_out;
+        }
+
            if (pgofs >= end)
                    goto sync_out;
            else if (dn.ofs_in_node < end_offset)




___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel


[f2fs-dev] [PATCH v2 4/4] f2fs: atomic: fix to forbid dio in atomic_file

2024-08-15 Thread Chao Yu
atomic write can only be used via buffered IO, let's fail direct IO on
atomic_file and return -EOPNOTSUPP.

Signed-off-by: Chao Yu 
---
v2:
- fix error path handling.
 fs/f2fs/file.c | 36 
 1 file changed, 24 insertions(+), 12 deletions(-)

diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 6b4f417f3474..b50ebebbbaab 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -2162,6 +2162,7 @@ static int f2fs_ioc_start_atomic_write(struct file *filp, 
bool truncate)
goto out;
 
f2fs_down_write(&fi->i_gc_rwsem[WRITE]);
+   f2fs_down_write(&fi->i_gc_rwsem[READ]);
 
/*
 * Should wait end_io to count F2FS_WB_CP_DATA correctly by
@@ -2171,10 +2172,8 @@ static int f2fs_ioc_start_atomic_write(struct file 
*filp, bool truncate)
f2fs_warn(sbi, "Unexpected flush for atomic writes: ino=%lu, 
npages=%u",
  inode->i_ino, get_dirty_pages(inode));
ret = filemap_write_and_wait_range(inode->i_mapping, 0, LLONG_MAX);
-   if (ret) {
-   f2fs_up_write(&fi->i_gc_rwsem[WRITE]);
-   goto out;
-   }
+   if (ret)
+   goto out_unlock;
 
/* Check if the inode already has a COW inode */
if (fi->cow_inode == NULL) {
@@ -2183,10 +2182,8 @@ static int f2fs_ioc_start_atomic_write(struct file 
*filp, bool truncate)
struct inode *dir = d_inode(dentry->d_parent);
 
ret = f2fs_get_tmpfile(idmap, dir, &fi->cow_inode);
-   if (ret) {
-   f2fs_up_write(&fi->i_gc_rwsem[WRITE]);
-   goto out;
-   }
+   if (ret)
+   goto out_unlock;
 
set_inode_flag(fi->cow_inode, FI_COW_FILE);
clear_inode_flag(fi->cow_inode, FI_INLINE_DATA);
@@ -2200,10 +2197,8 @@ static int f2fs_ioc_start_atomic_write(struct file 
*filp, bool truncate)
invalidate_mapping_pages(fi->cow_inode->i_mapping, 0, -1);
 
ret = f2fs_do_truncate_blocks(fi->cow_inode, 0, true);
-   if (ret) {
-   f2fs_up_write(&fi->i_gc_rwsem[WRITE]);
-   goto out;
-   }
+   if (ret)
+   goto out_unlock;
}
 
f2fs_write_inode(inode, NULL);
@@ -,7 +2217,11 @@ static int f2fs_ioc_start_atomic_write(struct file 
*filp, bool truncate)
}
f2fs_i_size_write(fi->cow_inode, isize);
 
+out_unlock:
+   f2fs_up_write(&fi->i_gc_rwsem[READ]);
f2fs_up_write(&fi->i_gc_rwsem[WRITE]);
+   if (ret)
+   goto out;
 
f2fs_update_time(sbi, REQ_TIME);
fi->atomic_write_task = current;
@@ -4567,6 +4566,13 @@ static ssize_t f2fs_dio_read_iter(struct kiocb *iocb, 
struct iov_iter *to)
f2fs_down_read(&fi->i_gc_rwsem[READ]);
}
 
+   /* dio is not compatible w/ atomic file */
+   if (f2fs_is_atomic_file(inode)) {
+   f2fs_up_read(&fi->i_gc_rwsem[READ]);
+   ret = -EOPNOTSUPP;
+   goto out;
+   }
+
/*
 * We have to use __iomap_dio_rw() and iomap_dio_complete() instead of
 * the higher-level function iomap_dio_rw() in order to ensure that the
@@ -4982,6 +4988,12 @@ static ssize_t f2fs_file_write_iter(struct kiocb *iocb, 
struct iov_iter *from)
/* Determine whether we will do a direct write or a buffered write. */
dio = f2fs_should_use_dio(inode, iocb, from);
 
+   /* dio is not compatible w/ atomic write */
+   if (dio && f2fs_is_atomic_file(inode)) {
+   ret = -EOPNOTSUPP;
+   goto out_unlock;
+   }
+
/* Possibly preallocate the blocks for the write. */
target_size = iocb->ki_pos + iov_iter_count(from);
preallocated = f2fs_preallocate_blocks(iocb, from, dio);
-- 
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: compress: don't redirty sparse cluster during {, de}compress

2024-08-15 Thread Chao Yu

On 2024/8/13 14:11, 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


Good catch!



To prevent the problem, let's check whether the cluster is fully
allocated before redirty its pages.

Reviewed-by: Sungjong Seo 
Reviewed-by: Sunmin Jeong 
Tested-by: Jaewook Kim 
Signed-off-by: Yeongjin Gil 


Need a fixes line?


---
  fs/f2fs/compress.c | 34 ++
  fs/f2fs/f2fs.h | 12 
  fs/f2fs/file.c | 39 +--
  3 files changed, 59 insertions(+), 26 deletions(-)

diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c
index 990b93689b46..09b91d725807 100644
--- a/fs/f2fs/compress.c
+++ b/fs/f2fs/compress.c
@@ -945,7 +945,7 @@ static int __f2fs_get_cluster_blocks(struct inode *inode,
unsigned int cluster_size = F2FS_I(inode)->i_cluster_size;
int count, i;
  
-	for (i = 1, count = 1; i < cluster_size; i++) {

+   for (i = 0, count = 0; i < cluster_size; i++) {
block_t blkaddr = data_blkaddr(dn->inode, dn->node_page,
dn->ofs_in_node + i);
  
@@ -956,8 +956,8 @@ static int __f2fs_get_cluster_blocks(struct inode *inode,

return count;
  }
  
-static int __f2fs_cluster_blocks(struct inode *inode,

-   unsigned int cluster_idx, bool compr_blks)
+static int __f2fs_cluster_blocks(struct inode *inode, unsigned int cluster_idx,
+   enum cluster_check_type type)
  {
struct dnode_of_data dn;
unsigned int start_idx = cluster_idx <<
@@ -978,10 +978,12 @@ static int __f2fs_cluster_blocks(struct inode *inode,
}
  
  	if (dn.data_blkaddr == COMPRESS_ADDR) {

-   if (compr_blks)
-   ret = __f2fs_get_cluster_blocks(inode, &dn);
-   else
+   if (type == COMPR_BLKS)
+   ret = 1 + __f2fs_get_cluster_blocks(inode, &dn);
+   else if (type == COMPR_CLUSTER)
ret = 1;
+   } else if (type == DECOMPR_BLKS) {
+   ret = __f2fs_get_cluster_blocks(inode, &dn);
}
  fail:
f2fs_put_dnode(&dn);
@@ -991,7 +993,14 @@ static int __f2fs_cluster_blocks(struct inode *inode,
  /* return # of compressed blocks in compressed cluster */
  static int f2fs_compressed_blocks(struct compress_ctx *cc)
  {
-   return __f2fs_cluster_blocks(cc->inode, cc->cluster_idx, true);
+   return __f2fs_cluster_blocks(cc->inode, cc->cluster_idx, COMPR_BLKS);
+}
+
+/* return # of raw blocks in non-compressed cluster */
+static int f2fs_decompressed_blocks(struct inode *inode,
+   unsigned int cluster_idx)
+{
+   return __f2fs_cluster_blocks(inode, cluster_idx, DECOMPR_BLKS);
  }
  
  /* return whether cluster is compressed one or not */

@@ -999,7 +1008,16 @@ int f2fs_is_compressed_cluster(struct inode *inode, 
pgoff_t index)
  {
return __f2fs_cluster_blocks(inode,
index >> F2FS_I(inode)->i_log_cluster_size,
-   false);
+   COMPR_CLUSTER);
+}
+
+/* return whether the cluster is filled with raw blocks */
+bool f2fs_is_non_sparse_cluster(struct inode *inode, pgoff_t index)


f2fs_is_sparse_cluster()?


+{
+   unsigned int cluster_idx = index >> F2FS_I(inode)->i_log_cluster_size;
+
+   return f2fs_decompressed_blocks(inode, cluster_idx) ==
+   F2FS_I(inode)->i_cluster_size;
  }
  
  static bool cluster_may_compress(struct compress_ctx *cc)

diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 51fd5063a69c..6f26c8cb8857 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -4302,6 +4302,11 @@ static inline bool f2fs_meta_inode_gc_required(struct 
inode *inode)
   * compress.c
   */
  #ifdef CONFIG_F2FS_FS_COMPRESSION
+enum cluster_check_type {
+   COMPR_CLUSTER,
+   COMPR_BLKS,
+   DECOMPR_BLKS


How about?

CLUSTER_IS_COMPR,
CLUSTER_COMPR_BLKS,
CLUSTER_RAW_BLKS


+};


Can you please add some comments for these enums?


  bool f2fs_is_compressed_page(struct page *page);
  struct page *f2fs_compress_control_page(struct page *page);
  int f2fs_prepare_compress_overwrite(struct inode *inode,
@@ -4328,6 +4333,7 @@ int f2fs_write_multi_pages(struct compress_ctx *cc,
struct writeback_control *wbc,
enum iostat_type io_type);
  int f2fs_is_compressed_cluster(struct inode *inode, pgoff_t index);
+bool f2fs

  1   2   3   4   5   6   7   8   9   10   >