Re: [f2fs-dev] [PATCH v4 1/2] dump.f2fs: Add ability to dump folders

2024-05-23 Thread Daeho Jeong
On Thu, May 23, 2024 at 3:48 PM Daniel Rosenberg via Linux-f2fs-devel
 wrote:
>
> This adds the ability to dump folders as well as files. Folders are
> dumped recursively. Additionally, dumped files/folders may be directed
> to a folder specified by -o [path] instead of ./lost_found. The -r flag
> will dump the entire fs from the root inode. -f or -y will skip the
> prompt before dumping, and -P will preserve the mode/owner info for the
> created file/folder.
>
> Signed-off-by: Daniel Rosenberg 
> Reviewed-by: Daeho Jeong 
> ---
>  fsck/dump.c | 178 ++--
>  fsck/fsck.c |   4 +-
>  fsck/fsck.h |   4 +-
>  fsck/main.c |  29 +++-
>  man/dump.f2fs.8 |  17 -
>  5 files changed, 190 insertions(+), 42 deletions(-)
>
> diff --git a/fsck/dump.c b/fsck/dump.c
> index b2e990b..fa68456 100644
> --- a/fsck/dump.c
> +++ b/fsck/dump.c
> @@ -247,7 +247,26 @@ out:
> printf("\n");
>  }
>
> -static void dump_data_blk(struct f2fs_sb_info *sbi, __u64 offset, u32 
> blkaddr)
> +static void dump_folder_contents(struct f2fs_sb_info *sbi, u8 *bitmap,
> +   struct f2fs_dir_entry *dentry,
> +   __u8 (*filenames)[F2FS_SLOT_LEN], int max)
> +{
> +   int i;
> +   int name_len;
> +
> +   for (i = 0; i < max; i++) {
> +   if (test_bit_le(i, bitmap) == 0)
> +   continue;
> +   name_len = le16_to_cpu(dentry[i].name_len);
> +   if (name_len == 1 && filenames[i][0] == '.')
> +   continue;
> +   if (name_len == 2 && filenames[i][0] == '.' && 
> filenames[i][1] == '.')
> +   continue;
> +   dump_node(sbi, le32_to_cpu(dentry[i].ino), 1, NULL, 0, 1);
> +   }
> +}
> +
> +static void dump_data_blk(struct f2fs_sb_info *sbi, __u64 offset, u32 
> blkaddr, bool is_folder)
>  {
> char buf[F2FS_BLKSIZE];
>
> @@ -288,12 +307,19 @@ static void dump_data_blk(struct f2fs_sb_info *sbi, 
> __u64 offset, u32 blkaddr)
> ASSERT(ret >= 0);
> }
>
> -   /* write blkaddr */
> -   dev_write_dump(buf, offset, F2FS_BLKSIZE);
> +   if (is_folder) {
> +   struct f2fs_dentry_block *d = (struct f2fs_dentry_block *) 
> buf;
> +
> +   dump_folder_contents(sbi, d->dentry_bitmap, 
> F2FS_DENTRY_BLOCK_DENTRIES(d),
> +   F2FS_DENTRY_BLOCK_FILENAMES(d), 
> NR_DENTRY_IN_BLOCK);
> +   } else {
> +   /* write blkaddr */
> +   dev_write_dump(buf, offset, F2FS_BLKSIZE);
> +   }
>  }
>
>  static void dump_node_blk(struct f2fs_sb_info *sbi, int ntype,
> -   u32 nid, u32 addr_per_block, u64 *ofs)
> +   u32 nid, u32 addr_per_block, u64 *ofs, int 
> is_dir)
>  {
> struct node_info ni;
> struct f2fs_node *node_blk;
> @@ -330,20 +356,20 @@ static void dump_node_blk(struct f2fs_sb_info *sbi, int 
> ntype,
> switch (ntype) {
> case TYPE_DIRECT_NODE:
> dump_data_blk(sbi, *ofs * F2FS_BLKSIZE,
> -   le32_to_cpu(node_blk->dn.addr[i]));
> +   le32_to_cpu(node_blk->dn.addr[i]), 
> is_dir);
> (*ofs)++;
> break;
> case TYPE_INDIRECT_NODE:
> dump_node_blk(sbi, TYPE_DIRECT_NODE,
> le32_to_cpu(node_blk->in.nid[i]),
> addr_per_block,
> -   ofs);
> +   ofs, is_dir);
> break;
> case TYPE_DOUBLE_INDIRECT_NODE:
> dump_node_blk(sbi, TYPE_INDIRECT_NODE,
> le32_to_cpu(node_blk->in.nid[i]),
> addr_per_block,
> -   ofs);
> +   ofs, is_dir);
> break;
> }
> }
> @@ -435,8 +461,9 @@ static int dump_inode_blk(struct f2fs_sb_info *sbi, u32 
> nid,
> u32 i = 0;
> u64 ofs = 0;
> u32 addr_per_block;
> +   bool is_dir = S_ISDIR(le16_to_cpu(node_blk->i.i_mode));
>
> -   if((node_blk->i.i_inline & F2FS_INLINE_DATA)) {
> +   if ((node_blk->i.i_inline & F2FS_INLINE_DATA)) {
>   

Re: [f2fs-dev] [PATCH v4 2/2] dump.f2fs: Fix xattr dumping

2024-05-23 Thread Daeho Jeong
On Thu, May 23, 2024 at 3:48 PM Daniel Rosenberg via Linux-f2fs-devel
 wrote:
>
> Xattrs for files with inline data were being skipped. This dumps those,
> as well as xattrs for folders.
>
> Signed-off-by: Daniel Rosenberg 
> Reviewed-by: Daeho Jeong 
> ---
>  fsck/dump.c | 39 +++
>  1 file changed, 27 insertions(+), 12 deletions(-)
>
> diff --git a/fsck/dump.c b/fsck/dump.c
> index fa68456..90e3e0e 100644
> --- a/fsck/dump.c
> +++ b/fsck/dump.c
> @@ -377,7 +377,7 @@ static void dump_node_blk(struct f2fs_sb_info *sbi, int 
> ntype,
>  }
>
>  #ifdef HAVE_FSETXATTR
> -static void dump_xattr(struct f2fs_sb_info *sbi, struct f2fs_node *node_blk)
> +static void dump_xattr(struct f2fs_sb_info *sbi, struct f2fs_node *node_blk, 
> int is_dir)
>  {
> void *xattr;
> void *last_base_addr;
> @@ -431,12 +431,24 @@ static void dump_xattr(struct f2fs_sb_info *sbi, struct 
> f2fs_node *node_blk)
>
> DBG(1, "fd %d xattr_name %s\n", c.dump_fd, xattr_name);
>  #if defined(__linux__)
> -   ret = fsetxattr(c.dump_fd, xattr_name, value,
> -   le16_to_cpu(ent->e_value_size), 0);
> +   if (is_dir) {
> +   ret = setxattr(".", xattr_name, value,
> +   
> le16_to_cpu(ent->e_value_size), 0);
> +   } else {
> +   ret = fsetxattr(c.dump_fd, xattr_name, value,
> +   
> le16_to_cpu(ent->e_value_size), 0);
> +   }
> +
>  #elif defined(__APPLE__)
> -   ret = fsetxattr(c.dump_fd, xattr_name, value,
> -   le16_to_cpu(ent->e_value_size), 0,
> -   XATTR_CREATE);
> +   if (is_dir) {
> +   ret = setxattr(".", xattr_name, value,
> +   le16_to_cpu(ent->e_value_size), 0,
> +   XATTR_CREATE);
> +   } else {
> +   ret = fsetxattr(c.dump_fd, xattr_name, value,
> +   le16_to_cpu(ent->e_value_size), 0,
> +   XATTR_CREATE);
> +   }
>  #endif
> if (ret)
> MSG(0, "XATTR index 0x%x set xattr failed error %d\n",
> @@ -449,7 +461,7 @@ static void dump_xattr(struct f2fs_sb_info *sbi, struct 
> f2fs_node *node_blk)
>  }
>  #else
>  static void dump_xattr(struct f2fs_sb_info *UNUSED(sbi),
> -   struct f2fs_node *UNUSED(node_blk))
> +   struct f2fs_node *UNUSED(node_blk), int 
> UNUSED(is_dir))
>  {
> MSG(0, "XATTR does not support\n");
>  }
> @@ -462,13 +474,15 @@ static int dump_inode_blk(struct f2fs_sb_info *sbi, u32 
> nid,
> u64 ofs = 0;
> u32 addr_per_block;
> bool is_dir = S_ISDIR(le16_to_cpu(node_blk->i.i_mode));
> +   int ret = 0;
>
> if ((node_blk->i.i_inline & F2FS_INLINE_DATA)) {
> DBG(3, "ino[0x%x] has inline data!\n", nid);
> /* recover from inline data */
> dev_write_dump(((unsigned char *)node_blk) + 
> INLINE_DATA_OFFSET,
> 0, MAX_INLINE_DATA(node_blk));
> -   return -1;
> +   ret = -1;
> +   goto dump_xattr;
> }
>
> if ((node_blk->i.i_inline & F2FS_INLINE_DENTRY)) {
> @@ -480,7 +494,8 @@ static int dump_inode_blk(struct f2fs_sb_info *sbi, u32 
> nid,
> DBG(3, "ino[0x%x] has inline dentries!\n", nid);
> /* recover from inline dentry */
> dump_folder_contents(sbi, d.bitmap, d.dentry, d.filename, 
> d.max);
> -   return -1;
> +   ret = -1;
> +   goto dump_xattr;
> }
>
> c.show_file_map_max_offset = f2fs_max_file_offset(_blk->i);
> @@ -516,9 +531,9 @@ static int dump_inode_blk(struct f2fs_sb_info *sbi, u32 
> nid,
> }
> /* last block in extent cache */
> print_extent(true);
> -
> -   dump_xattr(sbi, node_blk);
> -   return 0;
> +dump_xattr:
> +   dump_xattr(sbi, node_blk, is_dir);
> +   return ret;
>  }
>
>  static void dump_file(struct f2fs_sb_info *sbi, struct node_info *ni,
> --
> 2.45.1.288.g0e0cd299f1-goog
>
>

Reviewed-by: Daeho Jeong 

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 v2 1/2] dump.f2fs: Add ability to dump folders

2024-05-20 Thread Daeho Jeong
 __u8 
> *name,
> d = d->next;
> }
> printf("/%s", new);
> -   if (dump_node(sbi, le32_to_cpu(dentry[idx].ino), 0))
> +   if (dump_node(sbi, le32_to_cpu(dentry[idx].ino), 0, NULL, 0, 
> 0))
> printf("\33[2K\r");
> } else {
> for (i = 1; i < depth; i++)
> @@ -3632,7 +3632,7 @@ int fsck_verify(struct f2fs_sb_info *sbi)
> if (!strcasecmp(ans, "y")) {
> for (i = 0; i < fsck->nr_nat_entries; i++) {
> if (f2fs_test_bit(i, fsck->nat_area_bitmap))
> -   dump_node(sbi, i, 1);
> +   dump_node(sbi, i, 1, NULL, 1, 0);
> }
> }
> }
> diff --git a/fsck/fsck.h b/fsck/fsck.h
> index f5282e2..6cac926 100644
> --- a/fsck/fsck.h
> +++ b/fsck/fsck.h
> @@ -270,12 +270,14 @@ struct dump_option {
> int end_ssa;
> int32_t blk_addr;
> nid_t scan_nid;
> +   int use_root_nid;
> +   char *base_path;
>  };
>
>  extern void nat_dump(struct f2fs_sb_info *, nid_t, nid_t);
>  extern void sit_dump(struct f2fs_sb_info *, unsigned int, unsigned int);
>  extern void ssa_dump(struct f2fs_sb_info *, int, int);
> -extern int dump_node(struct f2fs_sb_info *, nid_t, int);
> +extern int dump_node(struct f2fs_sb_info *, nid_t, int, char *, int, int);
>  extern int dump_info_from_blkaddr(struct f2fs_sb_info *, u32);
>  extern unsigned int start_bidx_of_node(unsigned int, struct f2fs_node *);
>  extern void dump_node_scan_disk(struct f2fs_sb_info *sbi, nid_t nid);
> diff --git a/fsck/main.c b/fsck/main.c
> index c4d0956..7d0578a 100644
> --- a/fsck/main.c
> +++ b/fsck/main.c
> @@ -34,7 +34,7 @@ struct f2fs_fsck gfsck;
>
>  INIT_FEATURE_TABLE;
>
> -#ifdef WITH_SLOAD
> +#if defined(WITH_SLOAD) || defined(WITH_DUMP)
>  static char *absolute_path(const char *file)
>  {
> char *ret;
> @@ -384,7 +384,7 @@ void f2fs_parse_options(int argc, char *argv[])
> }
> } else if (!strcmp("dump.f2fs", prog)) {
>  #ifdef WITH_DUMP
> -   const char *option_string = "d:i:I:n:Ms:Sa:b:V";
> +   const char *option_string = "d:fi:I:n:Mo:Prs:Sa:b:Vy";
> static struct dump_option dump_opt = {
> .nid = 0,   /* default root ino */
> .start_nat = -1,
> @@ -395,6 +395,8 @@ void f2fs_parse_options(int argc, char *argv[])
> .end_ssa = -1,
> .blk_addr = -1,
> .scan_nid = 0,
> +   .use_root_nid = 0,
> +   .base_path = NULL,
> };
>
> c.func = DUMP;
> @@ -456,6 +458,19 @@ void f2fs_parse_options(int argc, char *argv[])
> ret = sscanf(optarg, "%x",
> _opt.blk_addr);
> break;
> +   case 'y':
> +   case 'f':
> +   c.force = 1;
> +   break;
> +   case 'r':
> +   dump_opt.use_root_nid = 1;
> +   break;
> +   case 'o':
> +   dump_opt.base_path = absolute_path(optarg);
> +   break;
> +   case 'P':
> +   c.preserve_perms = 1;
> +   break;
> case 'V':
> show_version(prog);
> exit(0);
> @@ -914,6 +929,9 @@ static void do_dump(struct f2fs_sb_info *sbi)
> struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
> u32 flag = le32_to_cpu(ckpt->ckpt_flags);
>
> +   if (opt->use_root_nid)
> +   opt->nid = sbi->root_ino_num;
> +
> if (opt->end_nat == -1)
> opt->end_nat = NM_I(sbi)->max_nid;
> if (opt->end_sit == -1)
> @@ -929,7 +947,7 @@ static void do_dump(struct f2fs_sb_info *sbi)
> if (opt->blk_addr != -1)
> dump_info_from_blkaddr(sbi, opt->blk_addr);
> if (opt->nid)
> -   dump_node(sbi, opt->nid, 0);
> +   dump_node(sbi, opt->nid, c.force, opt->base_path, 1, 1);
> if (opt->scan_nid)
> dump_node_scan_disk(sbi, opt->scan_nid);
>
> diff --git a/man/dump.f2fs.8 b/man/dump.f2fs.8
> index 94bf5f3..60d6783 100644
> --- a/man/dump.f2fs.8
> +++ b/man/dump.f2fs.8
> @@ -44,7 +44,8 @@ is used to retrieve f2fs metadata (usually in a disk 
> partition).
>  \fIdevice\fP is the special file corresponding to the device (e.g.
>  \fI/dev/sdXX\fP).
>
> -Currently, it can retrieve 1) a file given its inode number, 2) NAT
> +Currently, it can retrieve 1) a file or folder given its inode number
> +(folders are dumped recursively), 2) NAT
>  entries into a file, 3) SIT entries into a file, 4) SSA entries into
>  a file, 5) reverse information from the given block address.
>  .PP
> @@ -56,6 +57,20 @@ is 0 on success and -1 on failure.
>  .BI \-i " inode number"
>  Specify an inode number to dump out.
>  .TP
> +.BI \-r
> +Dump out from the root inode.
> +.TP
> +.BI \-f
> +Do not prompt before dumping
> +.TP
> +.BI \-y
> +Alias for \-f
> +.TP
> +.BI \-o " path"
> +Dump inodes to the given path
> +.BI \-P
> +Preserve mode/owner/group for dumped inode
> +.TP
>  .BI \-I " inode number"
>  Specify an inode number and scan full disk to dump out, include history 
> inode block
>  .TP
>
> base-commit: 5da4e5241503b385e4a7e75b1b2bb3367b38be96
> --
> 2.45.0.rc1.225.g2a3ae87e7f-goog
>


Reviewed-by: Daeho Jeong 

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/2] dump.f2fs: Fix xattr dumping

2024-05-20 Thread Daeho Jeong
On Tue, May 7, 2024 at 6:23 PM Daniel Rosenberg via Linux-f2fs-devel
 wrote:
>
> Xattrs for files with inline data were being skipped. This dumps those,
> as well as xattrs for folders.
>
> Signed-off-by: Daniel Rosenberg 
> ---
>  fsck/dump.c | 25 +
>  1 file changed, 17 insertions(+), 8 deletions(-)
>
> diff --git a/fsck/dump.c b/fsck/dump.c
> index f60f6f9..3bd17e3 100644
> --- a/fsck/dump.c
> +++ b/fsck/dump.c
> @@ -377,7 +377,7 @@ static void dump_node_blk(struct f2fs_sb_info *sbi, int 
> ntype,
>  }
>
>  #ifdef HAVE_FSETXATTR
> -static void dump_xattr(struct f2fs_sb_info *sbi, struct f2fs_node *node_blk)
> +static void dump_xattr(struct f2fs_sb_info *sbi, struct f2fs_node *node_blk, 
> int is_dir)
>  {
> void *xattr;
> void *last_base_addr;
> @@ -431,8 +431,14 @@ static void dump_xattr(struct f2fs_sb_info *sbi, struct 
> f2fs_node *node_blk)
>
> DBG(1, "fd %d xattr_name %s\n", c.dump_fd, xattr_name);
>  #if defined(__linux__)
> -   ret = fsetxattr(c.dump_fd, xattr_name, value,
> -   le16_to_cpu(ent->e_value_size), 0);
> +   if (is_dir) {
> +   ret = setxattr(".", xattr_name, value,
> +   
> le16_to_cpu(ent->e_value_size), 0);
> +   } else {
> +   ret = fsetxattr(c.dump_fd, xattr_name, value,
> +   
> le16_to_cpu(ent->e_value_size), 0);
> +   }
> +
>  #elif defined(__APPLE__)
> ret = fsetxattr(c.dump_fd, xattr_name, value,
> le16_to_cpu(ent->e_value_size), 0,
> @@ -462,13 +468,15 @@ static int dump_inode_blk(struct f2fs_sb_info *sbi, u32 
> nid,
> u64 ofs = 0;
> u32 addr_per_block;
> bool is_dir = S_ISDIR(le16_to_cpu(node_blk->i.i_mode));
> +   int ret = 0;
>
> if ((node_blk->i.i_inline & F2FS_INLINE_DATA)) {
> DBG(3, "ino[0x%x] has inline data!\n", nid);
> /* recover from inline data */
> dev_write_dump(((unsigned char *)node_blk) + 
> INLINE_DATA_OFFSET,
> 0, MAX_INLINE_DATA(node_blk));
> -   return -1;
> +   ret = -1;
> +   goto dump_xattr;
> }
>
> if ((node_blk->i.i_inline & F2FS_INLINE_DENTRY)) {
> @@ -480,7 +488,8 @@ static int dump_inode_blk(struct f2fs_sb_info *sbi, u32 
> nid,
> DBG(3, "ino[0x%x] has inline dentries!\n", nid);
> /* recover from inline dentry */
> dump_folder_contents(sbi, d.bitmap, d.dentry, d.filename, 
> d.max);
> -   return -1;
> +   ret = -1;
> +   goto dump_xattr;
> }
>
> c.show_file_map_max_offset = f2fs_max_file_offset(_blk->i);
> @@ -516,9 +525,9 @@ static int dump_inode_blk(struct f2fs_sb_info *sbi, u32 
> nid,
> }
> /* last block in extent cache */
>     print_extent(true);
> -
> -   dump_xattr(sbi, node_blk);
> -   return 0;
> +dump_xattr:
> +   dump_xattr(sbi, node_blk, is_dir);
> +   return ret;
>  }
>
>  static void dump_file(struct f2fs_sb_info *sbi, struct node_info *ni,
> --
> 2.45.0.rc1.225.g2a3ae87e7f-goog
>
>

Reviewed-by: Daeho Jeong 

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 1/2] dump.f2fs: Add ability to dump folders

2024-05-20 Thread Daeho Jeong
On Tue, May 7, 2024 at 6:26 PM Daniel Rosenberg via Linux-f2fs-devel
 wrote:
>
> This adds the ability to dump folders as well as files. Folders are
> dumped recursively. Additionally, dumped files/folders may be directed
> to a folder specified by -o [path] instead of ./lost_found. The -r flag
> will dump the entire fs from the root inode. -f or -y will skip the
> prompt before dumping, and -P will preserve the mode/owner info for the
> created file/folder.
>
> Signed-off-by: Daniel Rosenberg 
> ---
>  fsck/dump.c | 164 +---
>  fsck/fsck.c |   4 +-
>  fsck/fsck.h |   4 +-
>  fsck/main.c |  24 ++-
>  man/dump.f2fs.8 |  17 -
>  5 files changed, 171 insertions(+), 42 deletions(-)
>
> diff --git a/fsck/dump.c b/fsck/dump.c
> index b2e990b..f60f6f9 100644
> --- a/fsck/dump.c
> +++ b/fsck/dump.c
> @@ -247,7 +247,26 @@ out:
> printf("\n");
>  }
>
> -static void dump_data_blk(struct f2fs_sb_info *sbi, __u64 offset, u32 
> blkaddr)
> +static void dump_folder_contents(struct f2fs_sb_info *sbi, u8 *bitmap,
> +   struct f2fs_dir_entry *dentry,
> +   __u8 (*filenames)[F2FS_SLOT_LEN], int max)
> +{
> +   int i;
> +   int name_len;
> +
> +   for (i = 0; i < max; i++) {
> +   if (test_bit_le(i, bitmap) == 0)
> +   continue;
> +   name_len = le16_to_cpu(dentry[i].name_len);
> +   if (name_len == 1 && filenames[i][0] == '.')
> +   continue;
> +   if (name_len == 2 && filenames[i][0] == '.' && 
> filenames[i][1] == '.')
> +   continue;
> +   dump_node(sbi, le32_to_cpu(dentry[i].ino), 1, NULL, 0, 1);
> +   }
> +}
> +
> +static void dump_data_blk(struct f2fs_sb_info *sbi, __u64 offset, u32 
> blkaddr, bool is_folder)
>  {
> char buf[F2FS_BLKSIZE];
>
> @@ -288,12 +307,19 @@ static void dump_data_blk(struct f2fs_sb_info *sbi, 
> __u64 offset, u32 blkaddr)
> ASSERT(ret >= 0);
> }
>
> -   /* write blkaddr */
> -   dev_write_dump(buf, offset, F2FS_BLKSIZE);
> +   if (is_folder) {
> +   struct f2fs_dentry_block *d = (struct f2fs_dentry_block *) 
> buf;
> +
> +   dump_folder_contents(sbi, d->dentry_bitmap, 
> F2FS_DENTRY_BLOCK_DENTRIES(d),
> +   F2FS_DENTRY_BLOCK_FILENAMES(d), 
> NR_DENTRY_IN_BLOCK);
> +   } else {
> +   /* write blkaddr */
> +   dev_write_dump(buf, offset, F2FS_BLKSIZE);
> +   }
>  }
>
>  static void dump_node_blk(struct f2fs_sb_info *sbi, int ntype,
> -   u32 nid, u32 addr_per_block, u64 *ofs)
> +   u32 nid, u32 addr_per_block, u64 *ofs, int 
> is_dir)
>  {
> struct node_info ni;
> struct f2fs_node *node_blk;
> @@ -330,20 +356,20 @@ static void dump_node_blk(struct f2fs_sb_info *sbi, int 
> ntype,
> switch (ntype) {
> case TYPE_DIRECT_NODE:
> dump_data_blk(sbi, *ofs * F2FS_BLKSIZE,
> -   le32_to_cpu(node_blk->dn.addr[i]));
> +   le32_to_cpu(node_blk->dn.addr[i]), 
> is_dir);
> (*ofs)++;
> break;
> case TYPE_INDIRECT_NODE:
> dump_node_blk(sbi, TYPE_DIRECT_NODE,
> le32_to_cpu(node_blk->in.nid[i]),
> addr_per_block,
> -   ofs);
> +   ofs, is_dir);
> break;
> case TYPE_DOUBLE_INDIRECT_NODE:
> dump_node_blk(sbi, TYPE_INDIRECT_NODE,
> le32_to_cpu(node_blk->in.nid[i]),
> addr_per_block,
> -   ofs);
> +   ofs, is_dir);
> break;
> }
> }
> @@ -435,8 +461,9 @@ static int dump_inode_blk(struct f2fs_sb_info *sbi, u32 
> nid,
> u32 i = 0;
> u64 ofs = 0;
> u32 addr_per_block;
> +   bool is_dir = S_ISDIR(le16_to_cpu(node_blk->i.i_mode));
>
> -   if((node_blk->i.i_inline & F2FS_INLINE_DATA)) {
> +   if ((node_blk->i.i_inline & F2FS_INLINE_DATA)) {
> DBG(3, "ino[0x%x] has inline data!\n", nid);
> /* recover from inline data */
> dev_write_dump(((unsigned char *)node_blk) + 
> INLINE_DATA_OFFSET,
> @@ -444,13 +471,25 @@ static int dump_inode_blk(struct f2fs_sb_info *sbi, u32 
> nid,
> return -1;
> }
>
> +   if ((node_blk->i.i_inline & F2FS_INLINE_DENTRY)) {
> +   void *inline_dentry = inline_data_addr(node_blk);
> + 

[f2fs-dev] [PATCH v2] f2fs: allow dirty sections with zero valid block for checkpoint disabled

2024-05-10 Thread Daeho Jeong
From: Daeho Jeong 

Following the semantic for dirty segments in checkpoint disabled mode,
apply the same rule to dirty sections.

Signed-off-by: Daeho Jeong 

---
v2: simplified codes with the same logic
---
 fs/f2fs/segment.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index 6474b7338e81..cb0718cc1e47 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -771,8 +771,10 @@ static void __locate_dirty_segment(struct f2fs_sb_info 
*sbi, unsigned int segno,
block_t valid_blocks =
get_valid_blocks(sbi, segno, true);
 
-   f2fs_bug_on(sbi, unlikely(!valid_blocks ||
-   valid_blocks == CAP_BLKS_PER_SEC(sbi)));
+   f2fs_bug_on(sbi,
+   (!is_sbi_flag_set(sbi, SBI_CP_DISABLED) &&
+   !valid_blocks) ||
+   valid_blocks == CAP_BLKS_PER_SEC(sbi));
 
if (!IS_CURSEC(sbi, secno))
set_bit(secno, dirty_i->dirty_secmap);
-- 
2.45.0.118.g7fe29c98d7-goog



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


[f2fs-dev] [PATCH] f2fs: allow dirty sections with zero valid block for checkpoint disabled

2024-05-07 Thread Daeho Jeong
From: Daeho Jeong 

Following the semantic for dirty segments in checkpoint disabled mode,
apply the same rule to dirty sections.

Signed-off-by: Daeho Jeong 
---
 fs/f2fs/segment.c | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index 6474b7338e81..2463398b243f 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -771,8 +771,11 @@ static void __locate_dirty_segment(struct f2fs_sb_info 
*sbi, unsigned int segno,
block_t valid_blocks =
get_valid_blocks(sbi, segno, true);
 
-   f2fs_bug_on(sbi, unlikely(!valid_blocks ||
-   valid_blocks == CAP_BLKS_PER_SEC(sbi)));
+   if (!is_sbi_flag_set(sbi, SBI_CP_DISABLED))
+   f2fs_bug_on(sbi, unlikely(!valid_blocks));
+
+   f2fs_bug_on(sbi, unlikely(valid_blocks ==
+   CAP_BLKS_PER_SEC(sbi)));
 
if (!IS_CURSEC(sbi, secno))
set_bit(secno, dirty_i->dirty_secmap);
-- 
2.45.0.rc1.225.g2a3ae87e7f-goog



___
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/3] f2fs: fix false alarm on invalid block address

2024-04-27 Thread Daeho Jeong
On Thu, Apr 25, 2024 at 12:30 AM Chao Yu  wrote:
>
> On 2024/4/19 18:27, Juhyung Park wrote:
> > On Sat, Apr 13, 2024 at 5:57 AM Jaegeuk Kim  wrote:
> >>
> >> On 04/11, Chao Yu wrote:
> >>> On 2024/4/10 4:34, Jaegeuk Kim wrote:
>  f2fs_ra_meta_pages can try to read ahead on invalid block address which 
>  is
>  not the corruption case.
> >>>
> >>> In which case we will read ahead invalid meta pages? recovery w/ META_POR?
> >
> > In my case, it seems like it's META_SIT, and it's triggered right after 
> > mount.
>
> Ah, I see, actually it hits at this case, thanks for the information.
>
> Thanks,
>
> > fsck detects invalid_blkaddr, and when the kernel mounts it, it
> > immediately flags invalid_blkaddr again:
> >
> > [6.333498] init: [libfs_mgr] Running /system/bin/fsck.f2fs -a -c
> > 1 --debug-cache /dev/block/sda13
> > [6.337671] fsck.f2fs: Info: Fix the reported corruption.
> > [6.337947] fsck.f2fs: Info: not exist /proc/version!
> > [6.338010] fsck.f2fs: Info: can't find /sys, assuming normal block 
> > device
> > [6.338294] fsck.f2fs: Info: MKFS version
> > [6.338319] fsck.f2fs:   "5.10.160-android12-9-ge5cfec41c8e2"
> > [6.338366] fsck.f2fs: Info: FSCK version
> > [6.338380] fsck.f2fs:   from "5.10-arter97"
> > [6.338393] fsck.f2fs: to "5.10-arter97"
> > [6.338414] fsck.f2fs: Info: superblock features = 1499 :  encrypt
> > verity extra_attr project_quota quota_ino casefold
> > [6.338429] fsck.f2fs: Info: superblock encrypt level = 0, salt =
> > 
> > [6.338442] fsck.f2fs: Info: checkpoint stop reason: shutdown(180)
> > [6.338455] fsck.f2fs: Info: fs errors: invalid_blkaddr
> > [6.338468] fsck.f2fs: Info: Segments per section = 1
> > [6.338480] fsck.f2fs: Info: Sections per zone = 1
> > [6.338492] fsck.f2fs: Info: total FS sectors = 58971571 (230357 MB)
> > [6.340599] fsck.f2fs: Info: CKPT version = 2b7e3b29
> > [6.340620] fsck.f2fs: Info: version timestamp cur: 19789296, prev: 
> > 18407008
> > [6.677041] fsck.f2fs: Info: checkpoint state = 46 :  crc
> > compacted_summary orphan_inodes sudden-power-off
> > [6.677052] fsck.f2fs: [FSCK] Check node 1 / 712937 (0.00%)
> > [8.997922] fsck.f2fs: [FSCK] Check node 71294 / 712937 (10.00%)
> > [   10.629205] fsck.f2fs: [FSCK] Check node 142587 / 712937 (20.00%)
> > [   12.278186] fsck.f2fs: [FSCK] Check node 213880 / 712937 (30.00%)
> > [   13.768177] fsck.f2fs: [FSCK] Check node 285173 / 712937 (40.00%)
> > [   17.446971] fsck.f2fs: [FSCK] Check node 356466 / 712937 (50.00%)
> > [   19.891623] fsck.f2fs: [FSCK] Check node 427759 / 712937 (60.00%)
> > [   23.251327] fsck.f2fs: [FSCK] Check node 499052 / 712937 (70.00%)
> > [   28.493457] fsck.f2fs: [FSCK] Check node 570345 / 712937 (80.00%)
> > [   29.640800] fsck.f2fs: [FSCK] Check node 641638 / 712937 (90.00%)
> > [   30.718347] fsck.f2fs: [FSCK] Check node 712931 / 712937 (100.00%)
> > [   30.724176] fsck.f2fs:
> > [   30.737160] fsck.f2fs: [FSCK] Max image size: 167506 MB, Free space: 
> > 62850 MB
> > [   30.737164] fsck.f2fs: [FSCK] Unreachable nat entries
> >   [Ok..] [0x0]
> > [   30.737638] fsck.f2fs: [FSCK] SIT valid block bitmap checking
> >   [Ok..]
> > [   30.737640] fsck.f2fs: [FSCK] Hard link checking for regular file
> >   [Ok..] [0xd]
> > [   30.737641] fsck.f2fs: [FSCK] valid_block_count matching with CP
> >   [Ok..] [0x28b98e6]
> > [   30.737644] fsck.f2fs: [FSCK] valid_node_count matching with CP (de
> > lookup)  [Ok..] [0xae0e9]
> > [   30.737646] fsck.f2fs: [FSCK] valid_node_count matching with CP
> > (nat lookup) [Ok..] [0xae0e9]
> > [   30.737647] fsck.f2fs: [FSCK] valid_inode_count matched with CP
> >   [Ok..] [0xa74a3]
> > [   30.737649] fsck.f2fs: [FSCK] free segment_count matched with CP
> >   [Ok..] [0x7aa3]
> > [   30.737662] fsck.f2fs: [FSCK] next block offset is free
> >   [Ok..]
> > [   30.737663] fsck.f2fs: [FSCK] fixing SIT types
> > [   30.737867] fsck.f2fs: [FSCK] other corrupted bugs
> >   [Ok..]
> > [   30.737893] fsck.f2fs: [update_superblock: 765] Info: Done to
> > update superblock
> > [   30.960610] fsck.f2fs:
> > [   30.960618] fsck.f2fs: Done: 24.622956 secs
> > [   30.960620] fsck.f2fs:
> > [   30.960622] fsck.f2fs: c, u, RA, CH, CM, Repl=
> > [   30.960627] fsck.f2fs: 1 1 43600517 42605434 995083 985083
> > [   30.963274] F2FS-fs (sda13): Using encoding defined by superblock:
> > utf8-12.1.0 with flags 0x0
> > [   30.995360] __f2fs_is_valid_blkaddr: type=2
> >
> > (Manually added that print ^)
> >
> > [   30.995369] [ cut here ]
> > [   30.995375] WARNING: CPU: 7 PID: 1 at f2fs_handle_error+0x18/0x3c
> > [   30.995378] CPU: 7 PID: 1 Comm: init Tainted: G S  W
> > 5.10.209-arter97-r15-kernelsu-g0867d0e4f1d2 #6
> > [   30.995379] Hardware name: Qualcomm Technologies, Inc. Cape QRD
> > with PM8010 (DT)
> > [   30.995380] pstate: 

Re: [f2fs-dev] [PATCH v2] f2fs: zone: fix to don't trigger OPU on pinfile for direct IO

2024-04-27 Thread Daeho Jeong
On Sat, Apr 27, 2024 at 6:12 PM Chao Yu  wrote:
>
> Otherwise, it breaks pinfile's sematics.
>
> Cc: Daeho Jeong 
> Signed-off-by: Chao Yu 
> ---
> v2:
> - fix to disallow OPU on pinfile no matter what device type f2fs uses.
>  fs/f2fs/data.c | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
> index d8e4434e8801..56600dd43834 100644
> --- a/fs/f2fs/data.c
> +++ b/fs/f2fs/data.c
> @@ -1595,8 +1595,9 @@ int f2fs_map_blocks(struct inode *inode, struct 
> f2fs_map_blocks *map, int flag)
> }
>
> /* use out-place-update for direct IO under LFS mode */
> -   if (map->m_may_create &&
> -   (is_hole || (f2fs_lfs_mode(sbi) && flag == F2FS_GET_BLOCK_DIO))) {
> +   if (map->m_may_create && (is_hole ||
> +   (flag == F2FS_GET_BLOCK_DIO && f2fs_lfs_mode(sbi) &&
> +   !f2fs_is_pinned_file(inode {
> if (unlikely(f2fs_cp_error(sbi))) {
> err = -EIO;
> goto sync_out;
> --
> 2.40.1
>

Reviewed-by: Daeho Jeong 

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: zone: fix to don't trigger OPU on pinfile for direct IO

2024-04-27 Thread Daeho Jeong
On Fri, Apr 26, 2024 at 6:49 PM Chao Yu  wrote:
>
> On 2024/4/26 22:14, Daeho Jeong wrote:
> > On Fri, Apr 26, 2024 at 3:35 AM Chao Yu  wrote:
> >>
> >> Otherwise, it breaks pinfile's sematics.
> >>
> >> Cc: Daeho Jeong 
> >> Signed-off-by: Chao Yu 
> >> ---
> >>   fs/f2fs/data.c | 3 ++-
> >>   1 file changed, 2 insertions(+), 1 deletion(-)
> >>
> >> diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
> >> index bee1e45f76b8..e29000d83d52 100644
> >> --- a/fs/f2fs/data.c
> >> +++ b/fs/f2fs/data.c
> >> @@ -1596,7 +1596,8 @@ int f2fs_map_blocks(struct inode *inode, struct 
> >> f2fs_map_blocks *map, int flag)
> >>
> >>  /* use out-place-update for direct IO under LFS mode */
> >>  if (map->m_may_create &&
> >> -   (is_hole || (f2fs_lfs_mode(sbi) && flag == 
> >> F2FS_GET_BLOCK_DIO))) {
> >> +   (is_hole || (flag == F2FS_GET_BLOCK_DIO && (f2fs_lfs_mode(sbi) 
> >> &&
> >> +   (!f2fs_sb_has_blkzoned(sbi) || 
> >> !f2fs_is_pinned_file(inode)) {
> >>  if (unlikely(f2fs_cp_error(sbi))) {
> >>  err = -EIO;
> >>  goto sync_out;
> >> --
> >> 2.40.1
> >
> > So, we block overwrite io for the pinfile here.
>
> I guess you mean we blocked append write for pinfile, right?
>
> >
> > static ssize_t f2fs_file_write_iter(struct kiocb *iocb, struct iov_iter 
> > *from)
> >
> > {
> > ...
> >  if (f2fs_is_pinned_file(inode) &&
> >  !f2fs_overwrite_io(inode, pos, count)) {
>
> If !f2fs_overwrite_io() is true, it means it may trigger append write on
> pinfile?

Yes, I missed it. Thanks~

>
> Thanks,
>
> >  ret = -EIO;
> >  goto out_unlock;
> >  }
> >
> >
> >>


___
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: zone: fix to don't trigger OPU on pinfile for direct IO

2024-04-26 Thread Daeho Jeong
On Fri, Apr 26, 2024 at 3:35 AM Chao Yu  wrote:
>
> Otherwise, it breaks pinfile's sematics.
>
> Cc: Daeho Jeong 
> Signed-off-by: Chao Yu 
> ---
>  fs/f2fs/data.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
> index bee1e45f76b8..e29000d83d52 100644
> --- a/fs/f2fs/data.c
> +++ b/fs/f2fs/data.c
> @@ -1596,7 +1596,8 @@ int f2fs_map_blocks(struct inode *inode, struct 
> f2fs_map_blocks *map, int flag)
>
> /* use out-place-update for direct IO under LFS mode */
> if (map->m_may_create &&
> -   (is_hole || (f2fs_lfs_mode(sbi) && flag == F2FS_GET_BLOCK_DIO))) {
> +   (is_hole || (flag == F2FS_GET_BLOCK_DIO && (f2fs_lfs_mode(sbi) &&
> +   (!f2fs_sb_has_blkzoned(sbi) || !f2fs_is_pinned_file(inode)) {
> if (unlikely(f2fs_cp_error(sbi))) {
> err = -EIO;
> goto sync_out;
> --
> 2.40.1

So, we block overwrite io for the pinfile here.

static ssize_t f2fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)

{
...
if (f2fs_is_pinned_file(inode) &&
!f2fs_overwrite_io(inode, pos, count)) {
ret = -EIO;
goto out_unlock;
}


>


___
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/3 v2] f2fs: clear writeback when compression failed

2024-04-23 Thread Daeho Jeong
On Tue, Apr 16, 2024 at 9:50 AM Jaegeuk Kim  wrote:
>
> Let's stop issuing compressed writes and clear their writeback flags.
>
> Signed-off-by: Jaegeuk Kim 
> ---
>
>  Now, I don't see any kernel hang for 24hours.
>
>  Change log from v1:
>   - fix bugs
>
>  fs/f2fs/compress.c | 40 ++--
>  1 file changed, 38 insertions(+), 2 deletions(-)
>
> diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c
> index d67c471ab5df..b12d3a49bfda 100644
> --- a/fs/f2fs/compress.c
> +++ b/fs/f2fs/compress.c
> @@ -1031,6 +1031,31 @@ static void set_cluster_writeback(struct compress_ctx 
> *cc)
> }
>  }
>
> +static void cancel_cluster_writeback(struct compress_ctx *cc,
> +   struct compress_io_ctx *cic, int submitted)
> +{
> +   int i;
> +
> +   /* Wait for submitted IOs. */
> +   if (submitted > 1) {
> +   f2fs_submit_merged_write(F2FS_I_SB(cc->inode), DATA);
> +   while (atomic_read(>pending_pages) !=
> +   (cc->valid_nr_cpages - submitted + 1))
> +   f2fs_io_schedule_timeout(DEFAULT_IO_TIMEOUT);
> +   }
> +
> +   /* Cancel writeback and stay locked. */
> +   for (i = 0; i < cc->cluster_size; i++) {
> +   if (i < submitted) {
> +   inode_inc_dirty_pages(cc->inode);
> +   lock_page(cc->rpages[i]);
> +   }
> +   clear_page_private_gcing(cc->rpages[i]);
> +   if (folio_test_writeback(page_folio(cc->rpages[i])))
> +   end_page_writeback(cc->rpages[i]);
> +   }
> +}
> +
>  static void set_cluster_dirty(struct compress_ctx *cc)
>  {
> int i;
> @@ -1232,7 +1257,6 @@ static int f2fs_write_compressed_pages(struct 
> compress_ctx *cc,
> .page = NULL,
> .encrypted_page = NULL,
> .compressed_page = NULL,
> -   .submitted = 0,
> .io_type = io_type,
> .io_wbc = wbc,
> .encrypted = fscrypt_inode_uses_fs_layer_crypto(cc->inode) ?
> @@ -1358,7 +1382,16 @@ static int f2fs_write_compressed_pages(struct 
> compress_ctx *cc,
> fio.compressed_page = cc->cpages[i - 1];
>
> cc->cpages[i - 1] = NULL;
> +   fio.submitted = 0;
> f2fs_outplace_write_data(, );
> +   if (unlikely(!fio.submitted)) {
> +   cancel_cluster_writeback(cc, cic, i);
> +
> +   /* To call fscrypt_finalize_bounce_page */
> +   i = cc->valid_nr_cpages;
> +   *submitted = 0;
> +   goto out_destroy_crypt;
> +   }
> (*submitted)++;
>  unlock_continue:
> inode_dec_dirty_pages(cc->inode);
> @@ -1392,8 +1425,11 @@ static int f2fs_write_compressed_pages(struct 
> compress_ctx *cc,
>  out_destroy_crypt:
> page_array_free(cc->inode, cic->rpages, cc->cluster_size);
>
> -   for (--i; i >= 0; i--)
> +   for (--i; i >= 0; i--) {
> +   if (!cc->cpages[i])
> +   continue;
> fscrypt_finalize_bounce_page(>cpages[i]);
> +   }
>  out_put_cic:
> kmem_cache_free(cic_entry_slab, cic);
>  out_put_dnode:
> --
> 2.44.0.683.g7961c838ac-goog
>
>
>
> ___
> Linux-f2fs-devel mailing list
> Linux-f2fs-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

Reviewed-by: Daeho Jeong 

Thanks,


___
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] f2fs: allow direct io of pinned files for zoned storage

2024-04-11 Thread Daeho Jeong
From: Daeho Jeong 

Since the allocation happens in conventional LU for zoned storage, we
can allow direct io for that.

Signed-off-by: Daeho Jeong 
---
 fs/f2fs/file.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 3ee61bc82c6f..c8e086077a48 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -833,7 +833,8 @@ static bool f2fs_force_buffered_io(struct inode *inode, int 
rw)
 * for blkzoned device, fallback direct IO to buffered IO, so
 * all IOs can be serialized by log-structured write.
 */
-   if (f2fs_sb_has_blkzoned(sbi) && (rw == WRITE))
+   if (f2fs_sb_has_blkzoned(sbi) && (rw == WRITE) &&
+   !f2fs_is_pinned_file(inode))
return true;
if (is_sbi_flag_set(sbi, SBI_CP_DISABLED))
return true;
-- 
2.44.0.683.g7961c838ac-goog



___
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] f2fs: prevent writing without fallocate() for pinned files

2024-04-11 Thread Daeho Jeong
From: Daeho Jeong 

In a case writing without fallocate(), we can't guarantee it's allocated
in the conventional area for zoned stroage. To make it consistent across
storage devices, we disallow it regardless of storage device types.

Signed-off-by: Daeho Jeong 
---
v2: covered the direct io case
v3: covered the mkwrite case
v4: moved pin file check position in prepare_write_begin()
v5: removed unnecessary condition in f2fs_map_blocks() and disallowed
pre-written inodes for file pinning
v6: check a hole for pinned files in mkwrite()
v7: changed data_blkaddr check condition in mkwrite()
v8: replaced overwrite check parts with f2fs_overwrite_io()
---
 fs/f2fs/file.c | 25 -
 1 file changed, 16 insertions(+), 9 deletions(-)

diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 1761ad125f97..3ee61bc82c6f 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -58,7 +58,7 @@ static vm_fault_t f2fs_vm_page_mkwrite(struct vm_fault *vmf)
struct inode *inode = file_inode(vmf->vma->vm_file);
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
struct dnode_of_data dn;
-   bool need_alloc = true;
+   bool need_alloc = !f2fs_is_pinned_file(inode);
int err = 0;
vm_fault_t ret;
 
@@ -115,19 +115,18 @@ static vm_fault_t f2fs_vm_page_mkwrite(struct vm_fault 
*vmf)
goto out_sem;
}
 
+   set_new_dnode(, inode, NULL, NULL, 0);
if (need_alloc) {
/* block allocation */
-   set_new_dnode(, inode, NULL, NULL, 0);
err = f2fs_get_block_locked(, page->index);
-   }
-
-#ifdef CONFIG_F2FS_FS_COMPRESSION
-   if (!need_alloc) {
-   set_new_dnode(, inode, NULL, NULL, 0);
+   } else {
err = f2fs_get_dnode_of_data(, page->index, LOOKUP_NODE);
f2fs_put_dnode();
+   if (f2fs_is_pinned_file(inode) &&
+   !__is_valid_data_blkaddr(dn.data_blkaddr))
+   err = -EIO;
}
-#endif
+
if (err) {
unlock_page(page);
goto out_sem;
@@ -3234,7 +3233,7 @@ static int f2fs_ioc_set_pin_file(struct file *filp, 
unsigned long arg)
goto done;
}
 
-   if (f2fs_sb_has_blkzoned(sbi) && F2FS_HAS_BLOCKS(inode)) {
+   if (F2FS_HAS_BLOCKS(inode)) {
ret = -EFBIG;
goto out;
}
@@ -4798,6 +4797,8 @@ static ssize_t f2fs_file_write_iter(struct kiocb *iocb, 
struct iov_iter *from)
bool dio;
bool may_need_sync = true;
int preallocated;
+   const loff_t pos = iocb->ki_pos;
+   const ssize_t count = iov_iter_count(from);
ssize_t ret;
 
if (unlikely(f2fs_cp_error(F2FS_I_SB(inode {
@@ -4819,6 +4820,12 @@ static ssize_t f2fs_file_write_iter(struct kiocb *iocb, 
struct iov_iter *from)
inode_lock(inode);
}
 
+   if (f2fs_is_pinned_file(inode) &&
+   !f2fs_overwrite_io(inode, pos, count)) {
+   ret = -EIO;
+   goto out_unlock;
+   }
+
ret = f2fs_write_checks(iocb, from);
if (ret <= 0)
goto out_unlock;
-- 
2.44.0.683.g7961c838ac-goog



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


Re: [f2fs-dev] [PATCH v4] f2fs: zone: don't block IO if there is remained open zone

2024-04-11 Thread Daeho Jeong
On Thu, Apr 11, 2024 at 1:32 AM 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 
> ---
> v4:
> - avoid unneeded condition in f2fs_blkzoned_submit_merged_write().
>  fs/f2fs/data.c| 105 ++
>  fs/f2fs/f2fs.h|  34 ---
>  fs/f2fs/iostat.c  |   7 
>  fs/f2fs/iostat.h  |   2 +
>  fs/f2fs/segment.c |  43 ---
>  fs/f2fs/segment.h |  12 +-
>  fs/f2fs/super.c   |   2 +
>  7 files changed, 156 insertions(+), 49 deletions(-)
>
> diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
> index 60056b9a51be..71472ab6b7e7 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(>zone_wait);
> f2fs_write_end_io(bio);
> +   up(>available_open_zones);
>  }
>  #endif
>
> @@ -531,6 +530,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(>sbi->available_open_zones);
> +   io->open_zone = false;
> +   io->zone_openned = true;
> +   }
> +
> +   if (io->close_zone) {
> +   io->bio->bi_end_io = f2fs_zone_write_end_io;
> +   io->zone_openned = 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);
> @@ -601,9 +618,9 @@ int f2fs_init_write_merge_io(struct f2fs_sb_info *sbi)
> INIT_LIST_HEAD(>write_io[i][j].bio_list);
> init_f2fs_rwsem(>write_io[i][j].bio_list_lock);
>  #ifdef CONFIG_BLK_DEV_ZONED
> -   init_completion(>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_openned = false;
> +   sbi->write_io[i][j].close_zone = false;
>  #endif
> }
> }
> @@ -634,6 +651,31 @@ static void __f2fs_submit_merged_write(struct 
> f2fs_sb_info *sbi,
> f2fs_up_write(>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_rwsem);
> +   if (io->zone_openned) {
> +   if (io->bio) {
> +   io->close_zone = true;
> +   __submit_merged_bio(io);
> +   } else {
> +   up(>available_open_zones);
> +   io->zone_openned = false;
> +   }
> +   }
> +   f2fs_up_write(>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)
> @@ -918,22 +960,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(

Re: [f2fs-dev] [PATCH v3] f2fs: zone: don't block IO if there is remained open zone

2024-04-10 Thread Daeho Jeong
On Sun, Apr 7, 2024 at 6:58 AM 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 
> ---
> v3:
> - avoid race condition in between __submit_merged_bio()
> and __allocate_new_segment().
>  fs/f2fs/data.c| 105 ++
>  fs/f2fs/f2fs.h|  34 ---
>  fs/f2fs/iostat.c  |   7 
>  fs/f2fs/iostat.h  |   2 +
>  fs/f2fs/segment.c |  43 ---
>  fs/f2fs/segment.h |  12 +-
>  fs/f2fs/super.c   |   2 +
>  7 files changed, 156 insertions(+), 49 deletions(-)
>
> diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
> index 0d88649c60a5..18a4ac0a06bc 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(>zone_wait);
> f2fs_write_end_io(bio);
> +   up(>available_open_zones);
>  }
>  #endif
>
> @@ -531,6 +530,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(>sbi->available_open_zones);
> +   io->open_zone = false;
> +   io->zone_openned = true;
> +   }
> +
> +   if (io->close_zone) {
> +   io->bio->bi_end_io = f2fs_zone_write_end_io;
> +   io->zone_openned = 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);
> @@ -601,9 +618,9 @@ int f2fs_init_write_merge_io(struct f2fs_sb_info *sbi)
> INIT_LIST_HEAD(>write_io[i][j].bio_list);
> init_f2fs_rwsem(>write_io[i][j].bio_list_lock);
>  #ifdef CONFIG_BLK_DEV_ZONED
> -   init_completion(>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_openned = false;
> +   sbi->write_io[i][j].close_zone = false;
>  #endif
> }
> }
> @@ -634,6 +651,31 @@ static void __f2fs_submit_merged_write(struct 
> f2fs_sb_info *sbi,
> f2fs_up_write(>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_rwsem);
> +   if (io->zone_openned) {
> +   if (io->bio) {
> +   io->close_zone = true;
> +   __submit_merged_bio(io);
> +   } else if (io->zone_openned) {

We already checked if this value is true above.

Thanks,

> +   up(>available_open_zones);
> +   io->zone_openned = false;
> +   }
> +   }
> +   f2fs_up_write(>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)
> @@ -918,22 +960,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,
> + 

Re: [f2fs-dev] [PATCH] f2fs_io: support unset subcommand for pinfile

2024-04-10 Thread Daeho Jeong
On Tue, Apr 9, 2024 at 8:27 PM Chao Yu  wrote:
>
> Ping,
>
> Missed to check this patch?
>
> On 2024/3/29 18:25, Chao Yu wrote:
> > This patch adds unset subcommand for pinfile command.
> >
> > Usage: f2fs_io pinfile unset [target_file]
> >
> > Signed-off-by: Chao Yu 
> > ---
> >   man/f2fs_io.8   |  2 +-
> >   tools/f2fs_io/f2fs_io.c | 11 +--
> >   2 files changed, 10 insertions(+), 3 deletions(-)
> >
> > diff --git a/man/f2fs_io.8 b/man/f2fs_io.8
> > index f097bde..b9c9dc8 100644
> > --- a/man/f2fs_io.8
> > +++ b/man/f2fs_io.8
> > @@ -44,7 +44,7 @@ going down with metadata flush
> >   going down with fsck mark
> >   .RE
> >   .TP
> > -\fBpinfile\fR \fI[get|set] [file]\fR
> > +\fBpinfile\fR \fI[get|set|unset] [file]\fR
> >   Get or set the pinning status on a file.
> >   .TP
> >   \fBfadvise\fR \fI[advice] [offset] [length] [file]\fR
> > diff --git a/tools/f2fs_io/f2fs_io.c b/tools/f2fs_io/f2fs_io.c
> > index b8e4f02..a7b593a 100644
> > --- a/tools/f2fs_io/f2fs_io.c
> > +++ b/tools/f2fs_io/f2fs_io.c
> > @@ -442,7 +442,7 @@ static void do_fadvise(int argc, char **argv, const 
> > struct cmd_desc *cmd)
> >
> >   #define pinfile_desc "pin file control"
> >   #define pinfile_help\
> > -"f2fs_io pinfile [get|set] [file]\n\n"   \
> > +"f2fs_io pinfile [get|set|unset] [file]\n\n" \
> >   "get/set pinning given the file\n"  \
> >
> >   static void do_pinfile(int argc, char **argv, const struct cmd_desc *cmd)
> > @@ -464,7 +464,14 @@ static void do_pinfile(int argc, char **argv, const 
> > struct cmd_desc *cmd)
> >   ret = ioctl(fd, F2FS_IOC_SET_PIN_FILE, );
> >   if (ret != 0)
> >   die_errno("F2FS_IOC_SET_PIN_FILE failed");
> > - printf("set_pin_file: %u blocks moved in %s\n", ret, argv[2]);
> > + printf("%s pinfile: %u blocks moved in %s\n",
> > + argv[1], ret, argv[2]);
> > + } else if (!strcmp(argv[1], "unset")) {
> > + pin = 0;
> > + ret = ioctl(fd, F2FS_IOC_SET_PIN_FILE, );
> > + if (ret != 0)
> > + die_errno("F2FS_IOC_SET_PIN_FILE failed");
> > + printf("%s pinfile in %s\n", argv[1], argv[2]);
> >   } else if (!strcmp(argv[1], "get")) {
> >   unsigned int flags;
> >
>

Reviewed-by: Daeho Jeong 

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 v2] f2fs: don't set RO when shutting down f2fs

2024-04-09 Thread Daeho Jeong
On Tue, Apr 9, 2024 at 9:21 AM Jaegeuk Kim  wrote:
>
> Shutdown does not check the error of thaw_super due to readonly, which
> causes a deadlock like below.
>
> f2fs_ioc_shutdown(F2FS_GOING_DOWN_FULLSYNC)issue_discard_thread
>  - bdev_freeze
>   - freeze_super
>  - f2fs_stop_checkpoint()
>   - f2fs_handle_critical_error - sb_start_write
> - set RO - waiting
>  - bdev_thaw
>   - thaw_super_locked
> - return -EINVAL, if sb_rdonly()
>  - f2fs_stop_discard_thread
>   -> wait for kthread_stop(discard_thread);
>
> Reported-by: "Light Hsieh (謝明燈)" 
> Signed-off-by: Jaegeuk Kim 
> ---
>
>  Change log from v1:
>   - use better variable
>   - fix typo
>
>  fs/f2fs/super.c | 10 --
>  1 file changed, 8 insertions(+), 2 deletions(-)
>
> diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
> index 8ac4734c2df6..df32573d1f62 100644
> --- a/fs/f2fs/super.c
> +++ b/fs/f2fs/super.c
> @@ -4159,9 +4159,15 @@ void f2fs_handle_critical_error(struct f2fs_sb_info 
> *sbi, unsigned char reason,
> if (shutdown)
> set_sbi_flag(sbi, SBI_IS_SHUTDOWN);
>
> -   /* continue filesystem operators if errors=continue */
> -   if (continue_fs || f2fs_readonly(sb))
> +   /*
> +* Continue filesystem operators if errors=continue. Should not set
> +* RO by shutdown, since RO bypasses thaw_super which can hang the
> +* system.
> +*/
> +   if (continue_fs || f2fs_readonly(sb) || shutdown) {
> +   f2fs_warn(sbi, "Stopped filesystem due to reason: %d", 
> reason);
>     return;
> +   }
>
> f2fs_warn(sbi, "Remounting filesystem read-only");
> /*
> --
> 2.44.0.478.gd926399ef9-goog
>
>

Reviewed-by: Daeho Jeong 


>
> ___
> 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] f2fs: write missing last sum blk of file pinning section

2024-04-09 Thread Daeho Jeong
From: Daeho Jeong 

While do not allocating a new section in advance for file pinning area, I
missed that we should write the sum block for the last segment of a file
pinning section.

Fixes: 9703d69d9d15 ("f2fs: support file pinning for zoned devices")
Signed-off-by: Daeho Jeong 
---
 fs/f2fs/segment.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index 4fd76e867e0a..6474b7338e81 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -3559,6 +3559,8 @@ int f2fs_allocate_data_block(struct f2fs_sb_info *sbi, 
struct page *page,
if (segment_full) {
if (type == CURSEG_COLD_DATA_PINNED &&
!((curseg->segno + 1) % sbi->segs_per_sec)) {
+   write_sum_page(sbi, curseg->sum_blk,
+   GET_SUM_BLOCK(sbi, curseg->segno));
reset_curseg_fields(curseg);
goto skip_new_segment;
}
-- 
2.44.0.478.gd926399ef9-goog



___
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: don't set RO when shutting down f2fs

2024-04-09 Thread Daeho Jeong
On Thu, Apr 4, 2024 at 12:54 PM Jaegeuk Kim  wrote:
>
> Shutdown does not check the error of thaw_super due to readonly, which
> causes a deadlock like below.
>
> f2fs_ioc_shutdown(F2FS_GOING_DOWN_FULLSYNC)issue_discard_thread
>  - bdev_freeze
>   - freeze_super
>  - f2fs_stop_checkpoint()
>   - f2fs_handle_critical_error - sb_start_write
> - set RO - waiting
>  - bdev_thaw
>   - thaw_super_locked
> - return -EINVAL, if sb_rdonly()
>  - f2fs_stop_discard_thread
>   -> wait for kthread_stop(discard_thread);
>
> Reported-by: "Light Hsieh (謝明燈)" 
> Signed-off-by: Jaegeuk Kim 
> ---
>  fs/f2fs/super.c | 11 +--
>  1 file changed, 9 insertions(+), 2 deletions(-)
>
> diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
> index df9765b41dac..ba6288e870c5 100644
> --- a/fs/f2fs/super.c
> +++ b/fs/f2fs/super.c
> @@ -4135,9 +4135,16 @@ void f2fs_handle_critical_error(struct f2fs_sb_info 
> *sbi, unsigned char reason,
> if (shutdown)
> set_sbi_flag(sbi, SBI_IS_SHUTDOWN);
>
> -   /* continue filesystem operators if errors=continue */
> -   if (continue_fs || f2fs_readonly(sb))
> +   /*
> +* Continue filesystem operators if errors=continue. Should not set
> +* RO by shutdown, since RO bypasses thaw_super which can hang the
> +* system.
> +*/
> +   if (continue_fs || f2fs_readonly(sb) ||
> +   reason == STOP_CP_REASON_SHUTDOWN) {

I think we can use "shutdown" variable instead of "reason ==
STOP_CP_REASON_SHUTDOWN" to be concise.

> +   f2fs_warn(sbi, "Stopped filesystem due to readon: %d", 
> reason);

readon -> reason?

> return;
> +   }
>
> f2fs_warn(sbi, "Remounting filesystem read-only");
> /*
> --
> 2.44.0.478.gd926399ef9-goog
>
>
>
> ___
> 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 v7] f2fs: fix zoned block device information initialization

2024-04-08 Thread Daeho Jeong
On Sun, Apr 7, 2024 at 12:23 AM Chao Yu  wrote:
>
> From: Wenjie Qi 
>
> If the max open zones of zoned devices are less than
> the active logs of F2FS, the device may error due to
> insufficient zone resources when multiple active logs
> are being written at the same time.
>
> Signed-off-by: Wenjie Qi 
> Signed-off-by: Chao Yu 
> ---
> v7:
> - check f2fs_sb_has_blkzoned() instead of multiple-device condition
> in f2fs_remount().
>  fs/f2fs/f2fs.h  |  1 +
>  fs/f2fs/super.c | 27 +++
>  2 files changed, 28 insertions(+)
>
> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> index 0550929dc6e5..694f8a52cb84 100644
> --- a/fs/f2fs/f2fs.h
> +++ b/fs/f2fs/f2fs.h
> @@ -1559,6 +1559,7 @@ struct f2fs_sb_info {
>
>  #ifdef CONFIG_BLK_DEV_ZONED
> unsigned int blocks_per_blkz;   /* F2FS blocks per zone */
> +   unsigned int max_open_zones;/* max open zone resources of 
> the zoned device */
>  #endif
>
> /* for node-related operations */
> diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
> index ba6288e870c5..fdf358c7f808 100644
> --- a/fs/f2fs/super.c
> +++ b/fs/f2fs/super.c
> @@ -2324,6 +2324,17 @@ static int f2fs_remount(struct super_block *sb, int 
> *flags, char *data)
> if (err)
> goto restore_opts;
>
> +#ifdef CONFIG_BLK_DEV_ZONED
> +   if (f2fs_sb_has_blkzoned(sbi) &&
> +   sbi->max_open_zones < F2FS_OPTION(sbi).active_logs) {
> +   f2fs_err(sbi,
> +   "zoned: max open zones %u is too small, need at least 
> %u open zones",
> +sbi->max_open_zones, 
> F2FS_OPTION(sbi).active_logs);
> +   err = -EINVAL;
> +   goto restore_opts;
> +   }
> +#endif
> +
> /* flush outstanding errors before changing fs state */
> flush_work(>s_error_work);
>
> @@ -3866,11 +3877,24 @@ static int init_blkz_info(struct f2fs_sb_info *sbi, 
> int devi)
> sector_t nr_sectors = bdev_nr_sectors(bdev);
> struct f2fs_report_zones_args rep_zone_arg;
> u64 zone_sectors;
> +   unsigned int max_open_zones;
> int ret;
>
> if (!f2fs_sb_has_blkzoned(sbi))
> return 0;
>
> +   if (bdev_is_zoned(FDEV(devi).bdev)) {
> +   max_open_zones = bdev_max_open_zones(bdev);
> +   if (max_open_zones && (max_open_zones < sbi->max_open_zones))
> +   sbi->max_open_zones = max_open_zones;
> +   if (sbi->max_open_zones < F2FS_OPTION(sbi).active_logs) {
> +   f2fs_err(sbi,
> +   "zoned: max open zones %u is too small, need 
> at least %u open zones",
> +   sbi->max_open_zones, 
> F2FS_OPTION(sbi).active_logs);
> +   return -EINVAL;
> +   }
> +   }
> +
> zone_sectors = bdev_zone_sectors(bdev);
> if (sbi->blocks_per_blkz && sbi->blocks_per_blkz !=
> SECTOR_TO_BLOCK(zone_sectors))
> @@ -4191,6 +4215,9 @@ static int f2fs_scan_devices(struct f2fs_sb_info *sbi)
>
> logical_blksize = bdev_logical_block_size(sbi->sb->s_bdev);
> sbi->aligned_blksize = true;
> +#ifdef CONFIG_BLK_DEV_ZONED
> +   sbi->max_open_zones = UINT_MAX;
> +#endif
>
> for (i = 0; i < max_devices; i++) {
> if (i == 0)
> --
> 2.40.1
>
>

Reviewed-by: Daeho Jeong 


>
> ___
> 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] f2fs-tools: give 6 sections for overprovision buffer

2024-04-08 Thread Daeho Jeong
On Tue, Apr 2, 2024 at 4:56 PM Jaegeuk Kim  wrote:
>
> This addresses high GC cost at runtime.
>
> Signed-off-by: Jaegeuk Kim 
> ---
>  include/f2fs_fs.h  | 8 +++-
>  mkfs/f2fs_format.c | 5 +++--
>  2 files changed, 10 insertions(+), 3 deletions(-)
>
> diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h
> index fc56396fa358..870a6e4823d2 100644
> --- a/include/f2fs_fs.h
> +++ b/include/f2fs_fs.h
> @@ -1775,6 +1775,12 @@ static inline uint32_t get_reserved(struct 
> f2fs_super_block *sb, double ovp)
> return round_up(reserved, segs_per_sec) * segs_per_sec;
>  }
>
> +static inline uint32_t overprovision_segment_buffer(struct f2fs_super_block 
> *sb)
> +{
> +   /* Give 6 current sections to avoid huge GC overheads. */
> +   return 6 * get_sb(segs_per_sec);
> +}
> +
>  static inline double get_best_overprovision(struct f2fs_super_block *sb)
>  {
> double ovp, candidate, end, diff, space;
> @@ -1798,7 +1804,7 @@ static inline double get_best_overprovision(struct 
> f2fs_super_block *sb)
> if (ovp < 0)
> continue;
> space = usable_main_segs - max((double)reserved, ovp) -
> -   2 * get_sb(segs_per_sec);
> +   overprovision_segment_buffer(sb);
> if (max_space < space) {
> max_space = space;
> max_ovp = candidate;
> diff --git a/mkfs/f2fs_format.c b/mkfs/f2fs_format.c
> index 8f632f8d74b4..e26a513ed80c 100644
> --- a/mkfs/f2fs_format.c
> +++ b/mkfs/f2fs_format.c
> @@ -778,7 +778,8 @@ static int f2fs_write_check_point_pack(void)
>  * In non configurable reserved section case, overprovision
>  * segments are always bigger than two sections.
>  */
> -   if (get_cp(overprov_segment_count) < 2 * 
> get_sb(segs_per_sec)) {
> +   if (get_cp(overprov_segment_count) <
> +   overprovision_segment_buffer(sb)) {
> MSG(0, "\tError: Not enough overprovision segments 
> (%u)\n",
> get_cp(overprov_segment_count));
> goto free_cp_payload;
> @@ -787,7 +788,7 @@ static int f2fs_write_check_point_pack(void)
> get_cp(rsvd_segment_count));
>  } else {
> set_cp(overprov_segment_count, get_cp(overprov_segment_count) 
> +
> -   2 * get_sb(segs_per_sec));
> +       overprovision_segment_buffer(sb));
>  }
>
> if (f2fs_get_usable_segments(sb) <= get_cp(overprov_segment_count)) {
> --
> 2.44.0.478.gd926399ef9-goog
>
>
>

Reviewed-by: Daeho Jeong 


> ___
> 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 v6] f2fs: fix zoned block device information initialization

2024-04-04 Thread Daeho Jeong
On Thu, Mar 28, 2024 at 12:23 AM Chao Yu  wrote:
>
> From: Wenjie Qi 
>
> If the max open zones of zoned devices are less than
> the active logs of F2FS, the device may error due to
> insufficient zone resources when multiple active logs
> are being written at the same time.
>
> Signed-off-by: Wenjie Qi 
> Signed-off-by: Chao Yu 
> ---
> v6:
> - add check condition to avoid remount failure.
>  fs/f2fs/f2fs.h  |  1 +
>  fs/f2fs/super.c | 27 +++
>  2 files changed, 28 insertions(+)
>
> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> index 0550929dc6e5..694f8a52cb84 100644
> --- a/fs/f2fs/f2fs.h
> +++ b/fs/f2fs/f2fs.h
> @@ -1559,6 +1559,7 @@ struct f2fs_sb_info {
>
>  #ifdef CONFIG_BLK_DEV_ZONED
> unsigned int blocks_per_blkz;   /* F2FS blocks per zone */
> +   unsigned int max_open_zones;/* max open zone resources of 
> the zoned device */
>  #endif
>
> /* for node-related operations */
> diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
> index 7c45929671ad..642540782471 100644
> --- a/fs/f2fs/super.c
> +++ b/fs/f2fs/super.c
> @@ -2326,6 +2326,17 @@ static int f2fs_remount(struct super_block *sb, int 
> *flags, char *data)
> if (err)
> goto restore_opts;
>
> +#ifdef CONFIG_BLK_DEV_ZONED
> +   if (f2fs_is_multi_device(sbi) &&

Why do we check multiple devices' condition here?

Thanks,

> +   sbi->max_open_zones < F2FS_OPTION(sbi).active_logs) {
> +   f2fs_err(sbi,
> +   "zoned: max open zones %u is too small, need at least 
> %u open zones",
> +sbi->max_open_zones, 
> F2FS_OPTION(sbi).active_logs);
> +   err = -EINVAL;
> +   goto restore_opts;
> +   }
> +#endif
> +
> /* flush outstanding errors before changing fs state */
> flush_work(>s_error_work);
>
> @@ -3868,11 +3879,24 @@ static int init_blkz_info(struct f2fs_sb_info *sbi, 
> int devi)
> sector_t nr_sectors = bdev_nr_sectors(bdev);
> struct f2fs_report_zones_args rep_zone_arg;
> u64 zone_sectors;
> +   unsigned int max_open_zones;
> int ret;
>
> if (!f2fs_sb_has_blkzoned(sbi))
> return 0;
>
> +   if (bdev_is_zoned(FDEV(devi).bdev)) {
> +   max_open_zones = bdev_max_open_zones(bdev);
> +   if (max_open_zones && (max_open_zones < sbi->max_open_zones))
> +   sbi->max_open_zones = max_open_zones;
> +   if (sbi->max_open_zones < F2FS_OPTION(sbi).active_logs) {
> +   f2fs_err(sbi,
> +   "zoned: max open zones %u is too small, need 
> at least %u open zones",
> +   sbi->max_open_zones, 
> F2FS_OPTION(sbi).active_logs);
> +   return -EINVAL;
> +   }
> +   }
> +
> zone_sectors = bdev_zone_sectors(bdev);
> if (sbi->blocks_per_blkz && sbi->blocks_per_blkz !=
> SECTOR_TO_BLOCK(zone_sectors))
> @@ -4186,6 +4210,9 @@ static int f2fs_scan_devices(struct f2fs_sb_info *sbi)
>
> logical_blksize = bdev_logical_block_size(sbi->sb->s_bdev);
> sbi->aligned_blksize = true;
> +#ifdef CONFIG_BLK_DEV_ZONED
> +   sbi->max_open_zones = UINT_MAX;
> +#endif
>
> for (i = 0; i < max_devices; i++) {
> if (i == 0)
> --
> 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] f2fs: zone: don't block IO if there is remained open zone

2024-04-01 Thread Daeho Jeong
On Thu, Mar 28, 2024 at 8:20 PM 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 
> ---
> v2:
> - remove unneeded declaration.
>  fs/f2fs/data.c| 80 +--
>  fs/f2fs/f2fs.h| 33 ---
>  fs/f2fs/iostat.c  |  7 +
>  fs/f2fs/iostat.h  |  2 ++
>  fs/f2fs/segment.c | 58 ++
>  fs/f2fs/segment.h | 12 ++-
>  fs/f2fs/super.c   |  2 ++
>  7 files changed, 145 insertions(+), 49 deletions(-)
>
> diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
> index 0d88649c60a5..132a3ede60b1 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(>zone_wait);
> f2fs_write_end_io(bio);
> +   up(>available_open_zones);
>  }
>  #endif
>
> @@ -531,6 +530,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(>sbi->available_open_zones);
> +   io->open_zone = false;
> +   io->zone_openned = true;
> +   }
> +
> +   if (io->close_zone) {
> +   io->bio->bi_end_io = f2fs_zone_write_end_io;
> +   io->zone_openned = false;

I am not sure this part isn't racy with the part in __allocate_new_segment().

Thanks,

> +   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);
> @@ -601,9 +618,9 @@ int f2fs_init_write_merge_io(struct f2fs_sb_info *sbi)
> INIT_LIST_HEAD(>write_io[i][j].bio_list);
> init_f2fs_rwsem(>write_io[i][j].bio_list_lock);
>  #ifdef CONFIG_BLK_DEV_ZONED
> -   init_completion(>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_openned = false;
> +   sbi->write_io[i][j].close_zone = false;
>  #endif
> }
> }
> @@ -918,22 +935,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, "Invalid block %x", blkaddr);
> -   return false;
> -   }
> -   blkaddr -= FDEV(devi).start_blk;
> -   }
> -   return bdev_is_zoned(FDEV(devi).bdev) &&
> -   f2fs_blkz_is_seq(sbi, devi, blkaddr) &&
> -   (blkaddr % sbi->blocks_per_blkz == sbi->blocks_per_blkz - 1);
>  }
>  #endif
>
> @@ -944,20 +955,14 @@ void f2fs_submit_page_write(struct f2fs_io_info *fio)
> struct f2fs_bio_info *io = sbi->write_io[btype] + fio->temp;
> 

[f2fs-dev] [PATCH v7] f2fs: prevent writing without fallocate() for pinned files

2024-04-01 Thread Daeho Jeong
From: Daeho Jeong 

In a case writing without fallocate(), we can't guarantee it's allocated
in the conventional area for zoned stroage. To make it consistent across
storage devices, we disallow it regardless of storage device types.

Signed-off-by: Daeho Jeong 
---
v2: covered the direct io case
v3: covered the mkwrite case
v4: moved pin file check position in prepare_write_begin()
v5: removed unnecessary condition in f2fs_map_blocks() and disallowed
pre-written inodes for file pinning
v6: check a hole for pinned files in mkwrite()
v7: changed data_blkaddr check condition in mkwrite()
---
 fs/f2fs/data.c | 20 
 fs/f2fs/file.c | 21 -
 2 files changed, 28 insertions(+), 13 deletions(-)

diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index c21b92f18463..1b02a9291176 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -1584,8 +1584,11 @@ int f2fs_map_blocks(struct inode *inode, struct 
f2fs_map_blocks *map, int flag)
 
/* use out-place-update for direct IO under LFS mode */
if (map->m_may_create &&
-   (is_hole || (f2fs_lfs_mode(sbi) && flag == F2FS_GET_BLOCK_DIO))) {
-   if (unlikely(f2fs_cp_error(sbi))) {
+   (is_hole || (f2fs_lfs_mode(sbi) && flag == F2FS_GET_BLOCK_DIO &&
+!f2fs_is_pinned_file(inode {
+   if (unlikely(f2fs_cp_error(sbi)) ||
+   (f2fs_is_pinned_file(inode) &&
+flag != F2FS_GET_BLOCK_PRE_DIO)) {
err = -EIO;
goto sync_out;
}
@@ -3378,6 +3381,8 @@ static int prepare_write_begin(struct f2fs_sb_info *sbi,
f2fs_map_lock(sbi, flag);
locked = true;
} else if ((pos & PAGE_MASK) >= i_size_read(inode)) {
+   if (f2fs_is_pinned_file(inode))
+   return -EIO;
f2fs_map_lock(sbi, flag);
locked = true;
}
@@ -3414,8 +3419,15 @@ static int prepare_write_begin(struct f2fs_sb_info *sbi,
 
/* hole case */
err = f2fs_get_dnode_of_data(, index, LOOKUP_NODE);
-   if (!err && dn.data_blkaddr != NULL_ADDR)
-   goto out;
+   if (!err) {
+   if (dn.data_blkaddr != NULL_ADDR) {
+   goto out;
+   } else if (f2fs_is_pinned_file(inode)) {
+   err = -EIO;
+   goto out;
+   }
+   }
+
f2fs_put_dnode();
f2fs_map_lock(sbi, F2FS_GET_BLOCK_PRE_AIO);
WARN_ON(flag != F2FS_GET_BLOCK_PRE_AIO);
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 82277e95c88f..a8ac546b9abc 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -57,7 +57,7 @@ static vm_fault_t f2fs_vm_page_mkwrite(struct vm_fault *vmf)
struct inode *inode = file_inode(vmf->vma->vm_file);
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
struct dnode_of_data dn;
-   bool need_alloc = true;
+   bool need_alloc = !f2fs_is_pinned_file(inode);
int err = 0;
vm_fault_t ret;
 
@@ -114,19 +114,18 @@ static vm_fault_t f2fs_vm_page_mkwrite(struct vm_fault 
*vmf)
goto out_sem;
}
 
+   set_new_dnode(, inode, NULL, NULL, 0);
if (need_alloc) {
/* block allocation */
-   set_new_dnode(, inode, NULL, NULL, 0);
err = f2fs_get_block_locked(, page->index);
-   }
-
-#ifdef CONFIG_F2FS_FS_COMPRESSION
-   if (!need_alloc) {
-   set_new_dnode(, inode, NULL, NULL, 0);
+   } else {
err = f2fs_get_dnode_of_data(, page->index, LOOKUP_NODE);
f2fs_put_dnode();
+   if (f2fs_is_pinned_file(inode) &&
+   !__is_valid_data_blkaddr(dn.data_blkaddr))
+   err = -EIO;
}
-#endif
+
if (err) {
unlock_page(page);
goto out_sem;
@@ -3235,7 +3234,7 @@ static int f2fs_ioc_set_pin_file(struct file *filp, 
unsigned long arg)
goto done;
}
 
-   if (f2fs_sb_has_blkzoned(sbi) && F2FS_HAS_BLOCKS(inode)) {
+   if (F2FS_HAS_BLOCKS(inode)) {
ret = -EFBIG;
goto out;
}
@@ -4611,6 +4610,10 @@ static int f2fs_preallocate_blocks(struct kiocb *iocb, 
struct iov_iter *iter,
return ret;
}
 
+   /* For pinned files, it should be fallocate()-ed in advance. */
+   if (f2fs_is_pinned_file(inode))
+   return 0;
+
/* Do not preallocate blocks that will be written partially in 4KB. */
map.m_lblk = F2FS_BLK_ALIGN(pos);
map.m_len = F2FS_BYTES_TO_BLK(pos + count);
-- 
2.44.0.478.gd926399ef9-goog




[f2fs-dev] [PATCH v6] f2fs: prevent writing without fallocate() for pinned files

2024-03-29 Thread Daeho Jeong
From: Daeho Jeong 

In a case writing without fallocate(), we can't guarantee it's allocated
in the conventional area for zoned stroage. To make it consistent across
storage devices, we disallow it regardless of storage device types.

Signed-off-by: Daeho Jeong 
---
v2: covered the direct io case
v3: covered the mkwrite case
v4: moved pin file check position in prepare_write_begin()
v5: removed unnecessary condition in f2fs_map_blocks() and disallowed
pre-written inodes for file pinning
v6: check a hole for pinned files in mkwrite()
---
 fs/f2fs/data.c | 20 
 fs/f2fs/file.c | 20 +++-
 2 files changed, 27 insertions(+), 13 deletions(-)

diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index c21b92f18463..1b02a9291176 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -1584,8 +1584,11 @@ int f2fs_map_blocks(struct inode *inode, struct 
f2fs_map_blocks *map, int flag)
 
/* use out-place-update for direct IO under LFS mode */
if (map->m_may_create &&
-   (is_hole || (f2fs_lfs_mode(sbi) && flag == F2FS_GET_BLOCK_DIO))) {
-   if (unlikely(f2fs_cp_error(sbi))) {
+   (is_hole || (f2fs_lfs_mode(sbi) && flag == F2FS_GET_BLOCK_DIO &&
+!f2fs_is_pinned_file(inode {
+   if (unlikely(f2fs_cp_error(sbi)) ||
+   (f2fs_is_pinned_file(inode) &&
+flag != F2FS_GET_BLOCK_PRE_DIO)) {
err = -EIO;
goto sync_out;
}
@@ -3378,6 +3381,8 @@ static int prepare_write_begin(struct f2fs_sb_info *sbi,
f2fs_map_lock(sbi, flag);
locked = true;
} else if ((pos & PAGE_MASK) >= i_size_read(inode)) {
+   if (f2fs_is_pinned_file(inode))
+   return -EIO;
f2fs_map_lock(sbi, flag);
locked = true;
}
@@ -3414,8 +3419,15 @@ static int prepare_write_begin(struct f2fs_sb_info *sbi,
 
/* hole case */
err = f2fs_get_dnode_of_data(, index, LOOKUP_NODE);
-   if (!err && dn.data_blkaddr != NULL_ADDR)
-   goto out;
+   if (!err) {
+   if (dn.data_blkaddr != NULL_ADDR) {
+   goto out;
+   } else if (f2fs_is_pinned_file(inode)) {
+   err = -EIO;
+   goto out;
+   }
+   }
+
f2fs_put_dnode();
f2fs_map_lock(sbi, F2FS_GET_BLOCK_PRE_AIO);
WARN_ON(flag != F2FS_GET_BLOCK_PRE_AIO);
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 82277e95c88f..6793c96019a2 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -57,7 +57,7 @@ static vm_fault_t f2fs_vm_page_mkwrite(struct vm_fault *vmf)
struct inode *inode = file_inode(vmf->vma->vm_file);
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
struct dnode_of_data dn;
-   bool need_alloc = true;
+   bool need_alloc = !f2fs_is_pinned_file(inode);
int err = 0;
vm_fault_t ret;
 
@@ -114,19 +114,17 @@ static vm_fault_t f2fs_vm_page_mkwrite(struct vm_fault 
*vmf)
goto out_sem;
}
 
+   set_new_dnode(, inode, NULL, NULL, 0);
if (need_alloc) {
/* block allocation */
-   set_new_dnode(, inode, NULL, NULL, 0);
err = f2fs_get_block_locked(, page->index);
-   }
-
-#ifdef CONFIG_F2FS_FS_COMPRESSION
-   if (!need_alloc) {
-   set_new_dnode(, inode, NULL, NULL, 0);
+   } else {
err = f2fs_get_dnode_of_data(, page->index, LOOKUP_NODE);
f2fs_put_dnode();
+   if (f2fs_is_pinned_file(inode) && dn.data_blkaddr == NULL_ADDR)
+   err = -EIO;
}
-#endif
+
if (err) {
unlock_page(page);
goto out_sem;
@@ -3235,7 +3233,7 @@ static int f2fs_ioc_set_pin_file(struct file *filp, 
unsigned long arg)
goto done;
}
 
-   if (f2fs_sb_has_blkzoned(sbi) && F2FS_HAS_BLOCKS(inode)) {
+   if (F2FS_HAS_BLOCKS(inode)) {
ret = -EFBIG;
goto out;
}
@@ -4611,6 +4609,10 @@ static int f2fs_preallocate_blocks(struct kiocb *iocb, 
struct iov_iter *iter,
return ret;
}
 
+   /* For pinned files, it should be fallocate()-ed in advance. */
+   if (f2fs_is_pinned_file(inode))
+   return 0;
+
/* Do not preallocate blocks that will be written partially in 4KB. */
map.m_lblk = F2FS_BLK_ALIGN(pos);
map.m_len = F2FS_BYTES_TO_BLK(pos + count);
-- 
2.44.0.478.gd926399ef9-goog



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


[f2fs-dev] [PATCH v5] f2fs: prevent writing without fallocate() for pinned files

2024-03-26 Thread Daeho Jeong
From: Daeho Jeong 

In a case writing without fallocate(), we can't guarantee it's allocated
in the conventional area for zoned stroage. To make it consistent across
storage devices, we disallow it regardless of storage device types.

Signed-off-by: Daeho Jeong 
---
v2: covered the direct io case
v3: covered the mkwrite case
v4: moved pin file check position in prepare_write_begin()
v5: removed unnecessary condition in f2fs_map_blocks() and disallowed
pre-written inodes for file pinning
---
 fs/f2fs/data.c | 20 
 fs/f2fs/file.c | 18 +-
 2 files changed, 25 insertions(+), 13 deletions(-)

diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index c21b92f18463..1b02a9291176 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -1584,8 +1584,11 @@ int f2fs_map_blocks(struct inode *inode, struct 
f2fs_map_blocks *map, int flag)
 
/* use out-place-update for direct IO under LFS mode */
if (map->m_may_create &&
-   (is_hole || (f2fs_lfs_mode(sbi) && flag == F2FS_GET_BLOCK_DIO))) {
-   if (unlikely(f2fs_cp_error(sbi))) {
+   (is_hole || (f2fs_lfs_mode(sbi) && flag == F2FS_GET_BLOCK_DIO &&
+!f2fs_is_pinned_file(inode {
+   if (unlikely(f2fs_cp_error(sbi)) ||
+   (f2fs_is_pinned_file(inode) &&
+flag != F2FS_GET_BLOCK_PRE_DIO)) {
err = -EIO;
goto sync_out;
}
@@ -3378,6 +3381,8 @@ static int prepare_write_begin(struct f2fs_sb_info *sbi,
f2fs_map_lock(sbi, flag);
locked = true;
} else if ((pos & PAGE_MASK) >= i_size_read(inode)) {
+   if (f2fs_is_pinned_file(inode))
+   return -EIO;
f2fs_map_lock(sbi, flag);
locked = true;
}
@@ -3414,8 +3419,15 @@ static int prepare_write_begin(struct f2fs_sb_info *sbi,
 
/* hole case */
err = f2fs_get_dnode_of_data(, index, LOOKUP_NODE);
-   if (!err && dn.data_blkaddr != NULL_ADDR)
-   goto out;
+   if (!err) {
+   if (dn.data_blkaddr != NULL_ADDR) {
+   goto out;
+   } else if (f2fs_is_pinned_file(inode)) {
+   err = -EIO;
+   goto out;
+   }
+   }
+
f2fs_put_dnode();
f2fs_map_lock(sbi, F2FS_GET_BLOCK_PRE_AIO);
WARN_ON(flag != F2FS_GET_BLOCK_PRE_AIO);
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 82277e95c88f..7aa53cf553a1 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -57,7 +57,7 @@ static vm_fault_t f2fs_vm_page_mkwrite(struct vm_fault *vmf)
struct inode *inode = file_inode(vmf->vma->vm_file);
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
struct dnode_of_data dn;
-   bool need_alloc = true;
+   bool need_alloc = !f2fs_is_pinned_file(inode);
int err = 0;
vm_fault_t ret;
 
@@ -114,19 +114,15 @@ static vm_fault_t f2fs_vm_page_mkwrite(struct vm_fault 
*vmf)
goto out_sem;
}
 
+   set_new_dnode(, inode, NULL, NULL, 0);
if (need_alloc) {
/* block allocation */
-   set_new_dnode(, inode, NULL, NULL, 0);
err = f2fs_get_block_locked(, page->index);
-   }
-
-#ifdef CONFIG_F2FS_FS_COMPRESSION
-   if (!need_alloc) {
-   set_new_dnode(, inode, NULL, NULL, 0);
+   } else {
err = f2fs_get_dnode_of_data(, page->index, LOOKUP_NODE);
f2fs_put_dnode();
}
-#endif
+
if (err) {
unlock_page(page);
goto out_sem;
@@ -3235,7 +3231,7 @@ static int f2fs_ioc_set_pin_file(struct file *filp, 
unsigned long arg)
goto done;
}
 
-   if (f2fs_sb_has_blkzoned(sbi) && F2FS_HAS_BLOCKS(inode)) {
+   if (F2FS_HAS_BLOCKS(inode)) {
ret = -EFBIG;
goto out;
}
@@ -4611,6 +4607,10 @@ static int f2fs_preallocate_blocks(struct kiocb *iocb, 
struct iov_iter *iter,
return ret;
}
 
+   /* For pinned files, it should be fallocate()-ed in advance. */
+   if (f2fs_is_pinned_file(inode))
+   return 0;
+
/* Do not preallocate blocks that will be written partially in 4KB. */
map.m_lblk = F2FS_BLK_ALIGN(pos);
map.m_len = F2FS_BYTES_TO_BLK(pos + count);
-- 
2.44.0.396.g6e790dbe36-goog



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


Re: [f2fs-dev] [PATCH v3] f2fs: prevent writing without fallocate() for pinned files

2024-03-26 Thread Daeho Jeong
On Mon, Mar 25, 2024 at 8:39 PM Chao Yu  wrote:
>
> On 2024/3/25 23:02, Daeho Jeong wrote:
> > On Fri, Mar 22, 2024 at 9:26 PM Chao Yu  wrote:
> >>
> >> On 2024/3/21 1:42, Daeho Jeong wrote:
> >>> On Wed, Mar 20, 2024 at 2:38 AM Chao Yu  wrote:
> >>>>
> >>>> On 2024/3/20 5:23, Daeho Jeong wrote:
> >>>>> From: Daeho Jeong 
> >>>>>
> >>>>> In a case writing without fallocate(), we can't guarantee it's allocated
> >>>>> in the conventional area for zoned stroage.
> >>>>>
> >>>>> Signed-off-by: Daeho Jeong 
> >>>>> ---
> >>>>> v2: covered the direct io case
> >>>>> v3: covered the mkwrite case
> >>>>> ---
> >>>>> fs/f2fs/data.c | 14 --
> >>>>> fs/f2fs/file.c | 16 
> >>>>> 2 files changed, 20 insertions(+), 10 deletions(-)
> >>>>>
> >>>>> diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
> >>>>> index c21b92f18463..d3e5ab2736a6 100644
> >>>>> --- a/fs/f2fs/data.c
> >>>>> +++ b/fs/f2fs/data.c
> >>>>> @@ -1584,8 +1584,11 @@ int f2fs_map_blocks(struct inode *inode, struct 
> >>>>> f2fs_map_blocks *map, int flag)
> >>>>>
> >>>>> /* use out-place-update for direct IO under LFS mode */
> >>>>> if (map->m_may_create &&
> >>>>> - (is_hole || (f2fs_lfs_mode(sbi) && flag == 
> >>>>> F2FS_GET_BLOCK_DIO))) {
> >>>>> - if (unlikely(f2fs_cp_error(sbi))) {
> >>>>> + (is_hole || (f2fs_lfs_mode(sbi) && flag == F2FS_GET_BLOCK_DIO 
> >>>>> &&
> >>>>> +  !f2fs_is_pinned_file(inode {
> >>>>> + if (unlikely(f2fs_cp_error(sbi)) ||
> >>>>> + (f2fs_is_pinned_file(inode) && is_hole &&
> >>>>> +  flag != F2FS_GET_BLOCK_PRE_DIO)) {
> >>>>> err = -EIO;
> >>>>> goto sync_out;
> >>>>> }
> >>>>> @@ -3378,6 +3381,8 @@ static int prepare_write_begin(struct 
> >>>>> f2fs_sb_info *sbi,
> >>>>> f2fs_map_lock(sbi, flag);
> >>>>> locked = true;
> >>>>> } else if ((pos & PAGE_MASK) >= i_size_read(inode)) {
> >>>>> + if (f2fs_is_pinned_file(inode))
> >>>>> + return -EIO;
> >>>>> f2fs_map_lock(sbi, flag);
> >>>>> locked = true;
> >>>>> }
> >>>>> @@ -3407,6 +3412,11 @@ static int prepare_write_begin(struct 
> >>>>> f2fs_sb_info *sbi,
> >>>>>
> >>>>> if (!f2fs_lookup_read_extent_cache_block(inode, index,
> >>>>>  _blkaddr)) {
> >>>>> + if (f2fs_is_pinned_file(inode)) {
> >>>>> + err = -EIO;
> >>>>> + goto out;
> >>>>> + }
> >>>>> +
> >>>>> if (locked) {
> >>>>> err = f2fs_reserve_block(, index);
> >>>>> goto out;
> >>>>> diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
> >>>>> index 82277e95c88f..4db3b21c804b 100644
> >>>>> --- a/fs/f2fs/file.c
> >>>>> +++ b/fs/f2fs/file.c
> >>>>> @@ -57,7 +57,7 @@ static vm_fault_t f2fs_vm_page_mkwrite(struct 
> >>>>> vm_fault *vmf)
> >>>>> struct inode *inode = file_inode(vmf->vma->vm_file);
> >>>>> struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
> >>>>> struct dnode_of_data dn;
> >>>>> - bool need_alloc = true;
> >>>>> + bool need_alloc = !f2fs_is_pinned_file(inode);
> >>>>
> >>>> Will this check races w/ pinfile get|set?
> >>>
> >>> Do you mean "set/clear" case? I believe "set" case is okay, since we
> >>
> >> Yup,
> >>
> >>> can't 

Re: [f2fs-dev] [PATCH v3] f2fs: prevent writing without fallocate() for pinned files

2024-03-25 Thread Daeho Jeong
On Fri, Mar 22, 2024 at 9:26 PM Chao Yu  wrote:
>
> On 2024/3/21 1:42, Daeho Jeong wrote:
> > On Wed, Mar 20, 2024 at 2:38 AM Chao Yu  wrote:
> >>
> >> On 2024/3/20 5:23, Daeho Jeong wrote:
> >>> From: Daeho Jeong 
> >>>
> >>> In a case writing without fallocate(), we can't guarantee it's allocated
> >>> in the conventional area for zoned stroage.
> >>>
> >>> Signed-off-by: Daeho Jeong 
> >>> ---
> >>> v2: covered the direct io case
> >>> v3: covered the mkwrite case
> >>> ---
> >>>fs/f2fs/data.c | 14 --
> >>>fs/f2fs/file.c | 16 
> >>>2 files changed, 20 insertions(+), 10 deletions(-)
> >>>
> >>> diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
> >>> index c21b92f18463..d3e5ab2736a6 100644
> >>> --- a/fs/f2fs/data.c
> >>> +++ b/fs/f2fs/data.c
> >>> @@ -1584,8 +1584,11 @@ int f2fs_map_blocks(struct inode *inode, struct 
> >>> f2fs_map_blocks *map, int flag)
> >>>
> >>>/* use out-place-update for direct IO under LFS mode */
> >>>if (map->m_may_create &&
> >>> - (is_hole || (f2fs_lfs_mode(sbi) && flag == 
> >>> F2FS_GET_BLOCK_DIO))) {
> >>> - if (unlikely(f2fs_cp_error(sbi))) {
> >>> + (is_hole || (f2fs_lfs_mode(sbi) && flag == F2FS_GET_BLOCK_DIO &&
> >>> +  !f2fs_is_pinned_file(inode {
> >>> + if (unlikely(f2fs_cp_error(sbi)) ||
> >>> + (f2fs_is_pinned_file(inode) && is_hole &&
> >>> +  flag != F2FS_GET_BLOCK_PRE_DIO)) {
> >>>err = -EIO;
> >>>goto sync_out;
> >>>}
> >>> @@ -3378,6 +3381,8 @@ static int prepare_write_begin(struct f2fs_sb_info 
> >>> *sbi,
> >>>f2fs_map_lock(sbi, flag);
> >>>locked = true;
> >>>} else if ((pos & PAGE_MASK) >= i_size_read(inode)) {
> >>> + if (f2fs_is_pinned_file(inode))
> >>> + return -EIO;
> >>>f2fs_map_lock(sbi, flag);
> >>>locked = true;
> >>>}
> >>> @@ -3407,6 +3412,11 @@ static int prepare_write_begin(struct f2fs_sb_info 
> >>> *sbi,
> >>>
> >>>if (!f2fs_lookup_read_extent_cache_block(inode, index,
> >>> _blkaddr)) {
> >>> + if (f2fs_is_pinned_file(inode)) {
> >>> + err = -EIO;
> >>> + goto out;
> >>> + }
> >>> +
> >>>if (locked) {
> >>>err = f2fs_reserve_block(, index);
> >>>goto out;
> >>> diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
> >>> index 82277e95c88f..4db3b21c804b 100644
> >>> --- a/fs/f2fs/file.c
> >>> +++ b/fs/f2fs/file.c
> >>> @@ -57,7 +57,7 @@ static vm_fault_t f2fs_vm_page_mkwrite(struct vm_fault 
> >>> *vmf)
> >>>struct inode *inode = file_inode(vmf->vma->vm_file);
> >>>struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
> >>>struct dnode_of_data dn;
> >>> - bool need_alloc = true;
> >>> + bool need_alloc = !f2fs_is_pinned_file(inode);
> >>
> >> Will this check races w/ pinfile get|set?
> >
> > Do you mean "set/clear" case? I believe "set" case is okay, since we
>
> Yup,
>
> > can't set if the inode already has a data block. For "clear" case, I
>
> However, we can set pinfile on written inode in regular block device:

You're right. I missed it. Maybe I think we should keep the concept
consistent across devices regardless of zoned storage support. How
about preventing file pinning for already written inodes across all
device types? I am changing the pinfile concept by allowing the users
to write on only fallocate()-ed space.

>
> if (f2fs_sb_has_blkzoned(sbi) && F2FS_HAS_BLOCKS(inode)) {
> ret = -EFBIG;
> goto out;
> }
>
> Should we add the logic only if blkzoned feture is enabled?
>
> > believe mkwrite failure is okay in racy conditions caused by clearing
> > t

[f2fs-dev] [PATCH v4] f2fs: prevent writing without fallocate() for pinned files

2024-03-22 Thread Daeho Jeong
From: Daeho Jeong 

In a case writing without fallocate(), we can't guarantee it's allocated
in the conventional area for zoned stroage.

Signed-off-by: Daeho Jeong 
---
v2: covered the direct io case
v3: covered the mkwrite case
v4: moved pin file check position in prepare_write_begin()
---
 fs/f2fs/data.c | 20 
 fs/f2fs/file.c | 16 
 2 files changed, 24 insertions(+), 12 deletions(-)

diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index c21b92f18463..88896989bb28 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -1584,8 +1584,11 @@ int f2fs_map_blocks(struct inode *inode, struct 
f2fs_map_blocks *map, int flag)
 
/* use out-place-update for direct IO under LFS mode */
if (map->m_may_create &&
-   (is_hole || (f2fs_lfs_mode(sbi) && flag == F2FS_GET_BLOCK_DIO))) {
-   if (unlikely(f2fs_cp_error(sbi))) {
+   (is_hole || (f2fs_lfs_mode(sbi) && flag == F2FS_GET_BLOCK_DIO &&
+!f2fs_is_pinned_file(inode {
+   if (unlikely(f2fs_cp_error(sbi)) ||
+   (f2fs_is_pinned_file(inode) && is_hole &&
+flag != F2FS_GET_BLOCK_PRE_DIO)) {
err = -EIO;
goto sync_out;
}
@@ -3378,6 +3381,8 @@ static int prepare_write_begin(struct f2fs_sb_info *sbi,
f2fs_map_lock(sbi, flag);
locked = true;
} else if ((pos & PAGE_MASK) >= i_size_read(inode)) {
+   if (f2fs_is_pinned_file(inode))
+   return -EIO;
f2fs_map_lock(sbi, flag);
locked = true;
}
@@ -3414,8 +3419,15 @@ static int prepare_write_begin(struct f2fs_sb_info *sbi,
 
/* hole case */
err = f2fs_get_dnode_of_data(, index, LOOKUP_NODE);
-   if (!err && dn.data_blkaddr != NULL_ADDR)
-   goto out;
+   if (!err) {
+   if (dn.data_blkaddr != NULL_ADDR) {
+   goto out;
+   } else if (f2fs_is_pinned_file(inode)) {
+   err = -EIO;
+   goto out;
+   }
+   }
+
f2fs_put_dnode();
f2fs_map_lock(sbi, F2FS_GET_BLOCK_PRE_AIO);
WARN_ON(flag != F2FS_GET_BLOCK_PRE_AIO);
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 82277e95c88f..4db3b21c804b 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -57,7 +57,7 @@ static vm_fault_t f2fs_vm_page_mkwrite(struct vm_fault *vmf)
struct inode *inode = file_inode(vmf->vma->vm_file);
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
struct dnode_of_data dn;
-   bool need_alloc = true;
+   bool need_alloc = !f2fs_is_pinned_file(inode);
int err = 0;
vm_fault_t ret;
 
@@ -114,19 +114,15 @@ static vm_fault_t f2fs_vm_page_mkwrite(struct vm_fault 
*vmf)
goto out_sem;
}
 
+   set_new_dnode(, inode, NULL, NULL, 0);
if (need_alloc) {
/* block allocation */
-   set_new_dnode(, inode, NULL, NULL, 0);
err = f2fs_get_block_locked(, page->index);
-   }
-
-#ifdef CONFIG_F2FS_FS_COMPRESSION
-   if (!need_alloc) {
-   set_new_dnode(, inode, NULL, NULL, 0);
+   } else {
err = f2fs_get_dnode_of_data(, page->index, LOOKUP_NODE);
f2fs_put_dnode();
}
-#endif
+
if (err) {
unlock_page(page);
goto out_sem;
@@ -4611,6 +4607,10 @@ static int f2fs_preallocate_blocks(struct kiocb *iocb, 
struct iov_iter *iter,
return ret;
}
 
+   /* For pinned files, it should be fallocate()-ed in advance. */
+   if (f2fs_is_pinned_file(inode))
+   return 0;
+
/* Do not preallocate blocks that will be written partially in 4KB. */
map.m_lblk = F2FS_BLK_ALIGN(pos);
map.m_len = F2FS_BYTES_TO_BLK(pos + count);
-- 
2.44.0.396.g6e790dbe36-goog



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


Re: [f2fs-dev] [PATCH v3] f2fs: prevent writing without fallocate() for pinned files

2024-03-20 Thread Daeho Jeong
On Wed, Mar 20, 2024 at 2:38 AM Chao Yu  wrote:
>
> On 2024/3/20 5:23, Daeho Jeong wrote:
> > From: Daeho Jeong 
> >
> > In a case writing without fallocate(), we can't guarantee it's allocated
> > in the conventional area for zoned stroage.
> >
> > Signed-off-by: Daeho Jeong 
> > ---
> > v2: covered the direct io case
> > v3: covered the mkwrite case
> > ---
> >   fs/f2fs/data.c | 14 --
> >   fs/f2fs/file.c | 16 
> >   2 files changed, 20 insertions(+), 10 deletions(-)
> >
> > diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
> > index c21b92f18463..d3e5ab2736a6 100644
> > --- a/fs/f2fs/data.c
> > +++ b/fs/f2fs/data.c
> > @@ -1584,8 +1584,11 @@ int f2fs_map_blocks(struct inode *inode, struct 
> > f2fs_map_blocks *map, int flag)
> >
> >   /* use out-place-update for direct IO under LFS mode */
> >   if (map->m_may_create &&
> > - (is_hole || (f2fs_lfs_mode(sbi) && flag == F2FS_GET_BLOCK_DIO))) {
> > - if (unlikely(f2fs_cp_error(sbi))) {
> > + (is_hole || (f2fs_lfs_mode(sbi) && flag == F2FS_GET_BLOCK_DIO &&
> > +  !f2fs_is_pinned_file(inode {
> > + if (unlikely(f2fs_cp_error(sbi)) ||
> > + (f2fs_is_pinned_file(inode) && is_hole &&
> > +  flag != F2FS_GET_BLOCK_PRE_DIO)) {
> >   err = -EIO;
> >   goto sync_out;
> >   }
> > @@ -3378,6 +3381,8 @@ static int prepare_write_begin(struct f2fs_sb_info 
> > *sbi,
> >   f2fs_map_lock(sbi, flag);
> >   locked = true;
> >   } else if ((pos & PAGE_MASK) >= i_size_read(inode)) {
> > + if (f2fs_is_pinned_file(inode))
> > + return -EIO;
> >   f2fs_map_lock(sbi, flag);
> >   locked = true;
> >   }
> > @@ -3407,6 +3412,11 @@ static int prepare_write_begin(struct f2fs_sb_info 
> > *sbi,
> >
> >   if (!f2fs_lookup_read_extent_cache_block(inode, index,
> >_blkaddr)) {
> > + if (f2fs_is_pinned_file(inode)) {
> > + err = -EIO;
> > + goto out;
> > + }
> > +
> >   if (locked) {
> >   err = f2fs_reserve_block(, index);
> >   goto out;
> > diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
> > index 82277e95c88f..4db3b21c804b 100644
> > --- a/fs/f2fs/file.c
> > +++ b/fs/f2fs/file.c
> > @@ -57,7 +57,7 @@ static vm_fault_t f2fs_vm_page_mkwrite(struct vm_fault 
> > *vmf)
> >   struct inode *inode = file_inode(vmf->vma->vm_file);
> >   struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
> >   struct dnode_of_data dn;
> > - bool need_alloc = true;
> > + bool need_alloc = !f2fs_is_pinned_file(inode);
>
> Will this check races w/ pinfile get|set?

Do you mean "set/clear" case? I believe "set" case is okay, since we
can't set if the inode already has a data block. For "clear" case, I
believe mkwrite failure is okay in racy conditions caused by clearing
the pin flag. What do you think?

>
> Thanks,
>
> >   int err = 0;
> >   vm_fault_t ret;
> >
> > @@ -114,19 +114,15 @@ static vm_fault_t f2fs_vm_page_mkwrite(struct 
> > vm_fault *vmf)
> >   goto out_sem;
> >   }
> >
> > + set_new_dnode(, inode, NULL, NULL, 0);
> >   if (need_alloc) {
> >   /* block allocation */
> > - set_new_dnode(, inode, NULL, NULL, 0);
> >   err = f2fs_get_block_locked(, page->index);
> > - }
> > -
> > -#ifdef CONFIG_F2FS_FS_COMPRESSION
> > - if (!need_alloc) {
> > - set_new_dnode(, inode, NULL, NULL, 0);
> > + } else {
> >   err = f2fs_get_dnode_of_data(, page->index, LOOKUP_NODE);
> >   f2fs_put_dnode();
> >   }
> > -#endif
> > +
> >   if (err) {
> >   unlock_page(page);
> >   goto out_sem;
> > @@ -4611,6 +4607,10 @@ static int f2fs_preallocate_blocks(struct kiocb 
> > *iocb, struct iov_iter *iter,
> >   return ret;
> >   }
> >
> > + /* For pinned files, it should be fallocate()-ed in advance. */
> > + if (f2fs_is_pinned_file(inode))
> > + return 0;
> > +
> >   /* Do not preallocate blocks that will be written partially in 4KB. */
> >   map.m_lblk = F2FS_BLK_ALIGN(pos);
> >   map.m_len = F2FS_BYTES_TO_BLK(pos + count);


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


[f2fs-dev] [PATCH v3] f2fs: prevent writing without fallocate() for pinned files

2024-03-19 Thread Daeho Jeong
From: Daeho Jeong 

In a case writing without fallocate(), we can't guarantee it's allocated
in the conventional area for zoned stroage.

Signed-off-by: Daeho Jeong 
---
v2: covered the direct io case
v3: covered the mkwrite case
---
 fs/f2fs/data.c | 14 --
 fs/f2fs/file.c | 16 
 2 files changed, 20 insertions(+), 10 deletions(-)

diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index c21b92f18463..d3e5ab2736a6 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -1584,8 +1584,11 @@ int f2fs_map_blocks(struct inode *inode, struct 
f2fs_map_blocks *map, int flag)
 
/* use out-place-update for direct IO under LFS mode */
if (map->m_may_create &&
-   (is_hole || (f2fs_lfs_mode(sbi) && flag == F2FS_GET_BLOCK_DIO))) {
-   if (unlikely(f2fs_cp_error(sbi))) {
+   (is_hole || (f2fs_lfs_mode(sbi) && flag == F2FS_GET_BLOCK_DIO &&
+!f2fs_is_pinned_file(inode {
+   if (unlikely(f2fs_cp_error(sbi)) ||
+   (f2fs_is_pinned_file(inode) && is_hole &&
+flag != F2FS_GET_BLOCK_PRE_DIO)) {
err = -EIO;
goto sync_out;
}
@@ -3378,6 +3381,8 @@ static int prepare_write_begin(struct f2fs_sb_info *sbi,
f2fs_map_lock(sbi, flag);
locked = true;
} else if ((pos & PAGE_MASK) >= i_size_read(inode)) {
+   if (f2fs_is_pinned_file(inode))
+   return -EIO;
f2fs_map_lock(sbi, flag);
locked = true;
}
@@ -3407,6 +3412,11 @@ static int prepare_write_begin(struct f2fs_sb_info *sbi,
 
if (!f2fs_lookup_read_extent_cache_block(inode, index,
 _blkaddr)) {
+   if (f2fs_is_pinned_file(inode)) {
+   err = -EIO;
+   goto out;
+   }
+
if (locked) {
err = f2fs_reserve_block(, index);
goto out;
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 82277e95c88f..4db3b21c804b 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -57,7 +57,7 @@ static vm_fault_t f2fs_vm_page_mkwrite(struct vm_fault *vmf)
struct inode *inode = file_inode(vmf->vma->vm_file);
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
struct dnode_of_data dn;
-   bool need_alloc = true;
+   bool need_alloc = !f2fs_is_pinned_file(inode);
int err = 0;
vm_fault_t ret;
 
@@ -114,19 +114,15 @@ static vm_fault_t f2fs_vm_page_mkwrite(struct vm_fault 
*vmf)
goto out_sem;
}
 
+   set_new_dnode(, inode, NULL, NULL, 0);
if (need_alloc) {
/* block allocation */
-   set_new_dnode(, inode, NULL, NULL, 0);
err = f2fs_get_block_locked(, page->index);
-   }
-
-#ifdef CONFIG_F2FS_FS_COMPRESSION
-   if (!need_alloc) {
-   set_new_dnode(, inode, NULL, NULL, 0);
+   } else {
err = f2fs_get_dnode_of_data(, page->index, LOOKUP_NODE);
f2fs_put_dnode();
}
-#endif
+
if (err) {
unlock_page(page);
goto out_sem;
@@ -4611,6 +4607,10 @@ static int f2fs_preallocate_blocks(struct kiocb *iocb, 
struct iov_iter *iter,
return ret;
}
 
+   /* For pinned files, it should be fallocate()-ed in advance. */
+   if (f2fs_is_pinned_file(inode))
+   return 0;
+
/* Do not preallocate blocks that will be written partially in 4KB. */
map.m_lblk = F2FS_BLK_ALIGN(pos);
map.m_len = F2FS_BYTES_TO_BLK(pos + count);
-- 
2.44.0.291.gc1ea87d7ee-goog



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


[f2fs-dev] [PATCH v3] f2fs: prevent writing without fallocate() for pinned files

2024-03-19 Thread Daeho Jeong
From: Daeho Jeong 

In a case writing without fallocate(), we can't guarantee it's allocated
in the conventional area for zoned stroage.

Signed-off-by: Daeho Jeong 
---
v2: covered the direct io case
v3: covered the mkwrite case
---
 fs/f2fs/data.c | 14 --
 fs/f2fs/file.c | 16 
 2 files changed, 20 insertions(+), 10 deletions(-)

diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index c21b92f18463..d3e5ab2736a6 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -1584,8 +1584,11 @@ int f2fs_map_blocks(struct inode *inode, struct 
f2fs_map_blocks *map, int flag)
 
/* use out-place-update for direct IO under LFS mode */
if (map->m_may_create &&
-   (is_hole || (f2fs_lfs_mode(sbi) && flag == F2FS_GET_BLOCK_DIO))) {
-   if (unlikely(f2fs_cp_error(sbi))) {
+   (is_hole || (f2fs_lfs_mode(sbi) && flag == F2FS_GET_BLOCK_DIO &&
+!f2fs_is_pinned_file(inode {
+   if (unlikely(f2fs_cp_error(sbi)) ||
+   (f2fs_is_pinned_file(inode) && is_hole &&
+flag != F2FS_GET_BLOCK_PRE_DIO)) {
err = -EIO;
goto sync_out;
}
@@ -3378,6 +3381,8 @@ static int prepare_write_begin(struct f2fs_sb_info *sbi,
f2fs_map_lock(sbi, flag);
locked = true;
} else if ((pos & PAGE_MASK) >= i_size_read(inode)) {
+   if (f2fs_is_pinned_file(inode))
+   return -EIO;
f2fs_map_lock(sbi, flag);
locked = true;
}
@@ -3407,6 +3412,11 @@ static int prepare_write_begin(struct f2fs_sb_info *sbi,
 
if (!f2fs_lookup_read_extent_cache_block(inode, index,
 _blkaddr)) {
+   if (f2fs_is_pinned_file(inode)) {
+   err = -EIO;
+   goto out;
+   }
+
if (locked) {
err = f2fs_reserve_block(, index);
goto out;
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 82277e95c88f..4db3b21c804b 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -57,7 +57,7 @@ static vm_fault_t f2fs_vm_page_mkwrite(struct vm_fault *vmf)
struct inode *inode = file_inode(vmf->vma->vm_file);
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
struct dnode_of_data dn;
-   bool need_alloc = true;
+   bool need_alloc = !f2fs_is_pinned_file(inode);
int err = 0;
vm_fault_t ret;
 
@@ -114,19 +114,15 @@ static vm_fault_t f2fs_vm_page_mkwrite(struct vm_fault 
*vmf)
goto out_sem;
}
 
+   set_new_dnode(, inode, NULL, NULL, 0);
if (need_alloc) {
/* block allocation */
-   set_new_dnode(, inode, NULL, NULL, 0);
err = f2fs_get_block_locked(, page->index);
-   }
-
-#ifdef CONFIG_F2FS_FS_COMPRESSION
-   if (!need_alloc) {
-   set_new_dnode(, inode, NULL, NULL, 0);
+   } else {
err = f2fs_get_dnode_of_data(, page->index, LOOKUP_NODE);
f2fs_put_dnode();
}
-#endif
+
if (err) {
unlock_page(page);
goto out_sem;
@@ -4611,6 +4607,10 @@ static int f2fs_preallocate_blocks(struct kiocb *iocb, 
struct iov_iter *iter,
return ret;
}
 
+   /* For pinned files, it should be fallocate()-ed in advance. */
+   if (f2fs_is_pinned_file(inode))
+   return 0;
+
/* Do not preallocate blocks that will be written partially in 4KB. */
map.m_lblk = F2FS_BLK_ALIGN(pos);
map.m_len = F2FS_BYTES_TO_BLK(pos + count);
-- 
2.44.0.291.gc1ea87d7ee-goog



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


Re: [f2fs-dev] [bug report]WARNING: CPU: 22 PID: 44011 at fs/iomap/iter.c:51 iomap_iter+0x32b observed with blktests zbd/010

2024-03-18 Thread Daeho Jeong
On Sun, Mar 17, 2024 at 10:49 PM Shinichiro Kawasaki via
Linux-f2fs-devel  wrote:
>
> I confirmed that the trigger commit is dbf8e63f48af as Yi reported. I took a
> look in the commit, but it looks fine to me. So I thought the cause is not
> in the commit diff.
>
> I found the WARN is printed when the f2fs is set up with multiple devices,
> and read requests are mapped to the very first block of the second device in 
> the
> direct read path. In this case, f2fs_map_blocks() and f2fs_map_blocks_cached()
> modify map->m_pblk as the physical block address from each block device. It
> becomes zero when it is mapped to the first block of the device. However,
> f2fs_iomap_begin() assumes that map->m_pblk is the physical block address of 
> the
> whole f2fs, across the all block devices. It compares map->m_pblk against
> NULL_ADDR == 0, then go into the unexpected branch and sets the invalid
> iomap->length. The WARN catches the invalid iomap->length.
>
> This WARN is printed even for non-zoned block devices, by following steps.
>
>  - Create two (non-zoned) null_blk devices memory backed with 128MB size each:
>nullb0 and nullb1.
>  # mkfs.f2fs /dev/nullb0 -c /dev/nullb1
>  # mount -t f2fs /dev/nullb0 "${mount_dir}"
>  # dd if=/dev/zero of="${mount_dir}/test.dat" bs=1M count=192
>  # dd if="${mount_dir}/test.dat" of=/dev/null bs=1M count=192 iflag=direct
>
> I created a fix candidate patch [1]. It modifies f2fs_iomap_begin() to handle
> map->m_pblk as the physical block address from each device start, not the
> address of whole f2fs. I confirmed it avoids the WARN.
>
> But I'm not so sure if the fix is good enough. map->m_pblk has dual meanings.
> Sometimes it holds the physical block address of each device, and sometimes
> the address of the whole f2fs. I'm not sure what is the condition for
> map->m_pblk to have which meaning. I guess F2FS_GET_BLOCK_DIO flag is the
> condition, but f2fs_map_blocks_cached() does not ensure it.
>
> Also, I noticed that map->m_pblk is referred to in other functions below, and
> not sure if they need the similar change as I did for f2fs_iomap_begin().
>
>   f2fs_fiemap()
>   f2fs_read_single_page()
>   f2fs_bmap()
>   check_swap_activate()
>
> I would like to hear advices from f2fs experts for the fix.
>
>
> [1]
>
> diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
> index 26e317696b33..5232223a69e5 100644
> --- a/fs/f2fs/data.c
> +++ b/fs/f2fs/data.c
> @@ -1569,6 +1569,7 @@ static bool f2fs_map_blocks_cached(struct inode *inode,
> int bidx = f2fs_target_device_index(sbi, map->m_pblk);
> struct f2fs_dev_info *dev = >devs[bidx];
>
> +   map->m_multidev_dio = true;
> map->m_bdev = dev->bdev;
> map->m_pblk -= dev->start_blk;
> map->m_len = min(map->m_len, dev->end_blk + 1 - map->m_pblk);
> @@ -4211,9 +4212,11 @@ static int f2fs_iomap_begin(struct inode *inode, 
> loff_t offset, loff_t length,
> unsigned int flags, struct iomap *iomap,
> struct iomap *srcmap)
>  {
> +   struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
> struct f2fs_map_blocks map = {};
> pgoff_t next_pgofs = 0;
> -   int err;
> +   block_t pblk;
> +   int err, i;
>
> map.m_lblk = bytes_to_blks(inode, offset);
> map.m_len = bytes_to_blks(inode, offset + length - 1) - map.m_lblk + 
> 1;
> @@ -4239,12 +4242,17 @@ static int f2fs_iomap_begin(struct inode *inode, 
> loff_t offset, loff_t length,
>  * We should never see delalloc or compressed extents here based on
>  * prior flushing and checks.
>  */
> -   if (WARN_ON_ONCE(map.m_pblk == NEW_ADDR))
> +   pblk = map.m_pblk;
> +   if (map.m_multidev_dio && map.m_flags & F2FS_MAP_MAPPED)
> +   for (i = 0; i < sbi->s_ndevs; i++)
> +   if (FDEV(i).bdev == map.m_bdev)
> +   pblk += FDEV(i).start_blk;
> +   if (WARN_ON_ONCE(pblk == NEW_ADDR))
> return -EINVAL;
> -   if (WARN_ON_ONCE(map.m_pblk == COMPRESS_ADDR))
> +   if (WARN_ON_ONCE(pblk == COMPRESS_ADDR))
> return -EINVAL;
>
> -   if (map.m_pblk != NULL_ADDR) {
> +   if (pblk != NULL_ADDR) {

I feel like we should check only whether the block is really mapped or
not by checking F2FS_MAP_MAPPED field without changing the pblk, since
"0" pblk for the secondary device should remain 0 if it's the correct
value.

> iomap->length = blks_to_bytes(inode, map.m_len);
> iomap->type = IOMAP_MAPPED;
> iomap->flags |= IOMAP_F_MERGED;
>
> ___
> 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

Re: [f2fs-dev] [PATCH 1/2] f2fs: mark inode dirty for FI_ATOMIC_COMMITTED flag

2024-03-13 Thread Daeho Jeong
Reviewed-by: Daeho Jeong 

On Wed, Mar 13, 2024 at 4:37 AM Sunmin Jeong  wrote:
>
> In f2fs_update_inode, i_size of the atomic file isn't updated until
> FI_ATOMIC_COMMITTED flag is set. When committing atomic write right
> after the writeback of the inode, i_size of the raw inode will not be
> updated. It can cause the atomicity corruption due to a mismatch between
> old file size and new data.
>
> To prevent the problem, let's mark inode dirty for FI_ATOMIC_COMMITTED
>
> Atomic write thread   Writeback thread
> __writeback_single_inode
>   write_inode
> f2fs_update_inode
>   - skip i_size update
>   f2fs_ioc_commit_atomic_write
> f2fs_commit_atomic_write
>   set_inode_flag(inode, FI_ATOMIC_COMMITTED)
> f2fs_do_sync_file
>   f2fs_fsync_node_pages
> - skip f2fs_update_inode since the inode is clean
>
> Fixes: 3db1de0e582c ("f2fs: change the current atomic write way")
> Cc: sta...@vger.kernel.org #v5.19+
> Reviewed-by: Sungjong Seo 
> Reviewed-by: Yeongjin Gil 
> Signed-off-by: Sunmin Jeong 
> ---
>  fs/f2fs/f2fs.h | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> index 543898482f8b..a000cb024dbe 100644
> --- a/fs/f2fs/f2fs.h
> +++ b/fs/f2fs/f2fs.h
> @@ -3039,6 +3039,7 @@ 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);
> }
>  }
> --
> 2.25.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 2/2] f2fs: truncate page cache before clearing flags when aborting atomic write

2024-03-13 Thread Daeho Jeong
Reviewed-by: Daeho Jeong 

On Wed, Mar 13, 2024 at 4:29 AM Sunmin Jeong  wrote:
>
> In f2fs_do_write_data_page, FI_ATOMIC_FILE flag selects the target inode
> between the original inode and COW inode. When aborting atomic write and
> writeback occur simultaneously, invalid data can be written to original
> inode if the FI_ATOMIC_FILE flag is cleared meanwhile.
>
> To prevent the problem, let's truncate all pages before clearing the flag
>
> Atomic write thread  Writeback thread
>   f2fs_abort_atomic_write
> clear_inode_flag(inode, FI_ATOMIC_FILE)
>   __writeback_single_inode
> do_writepages
>   f2fs_do_write_data_page
> - use dn of original inode
> truncate_inode_pages_final
>
> Fixes: 3db1de0e582c ("f2fs: change the current atomic write way")
> Cc: sta...@vger.kernel.org #v5.19+
> Reviewed-by: Sungjong Seo 
> Reviewed-by: Yeongjin Gil 
> Signed-off-by: Sunmin Jeong 
> ---
>  fs/f2fs/segment.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
> index 7901ede58113..7e47b8054413 100644
> --- a/fs/f2fs/segment.c
> +++ b/fs/f2fs/segment.c
> @@ -192,6 +192,9 @@ void f2fs_abort_atomic_write(struct inode *inode, bool 
> clean)
> if (!f2fs_is_atomic_file(inode))
> return;
>
> +   if (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);
> @@ -201,7 +204,6 @@ void f2fs_abort_atomic_write(struct inode *inode, bool 
> clean)
> F2FS_I(inode)->atomic_write_task = NULL;
>
> if (clean) {
> -   truncate_inode_pages_final(inode->i_mapping);
> f2fs_i_size_write(inode, fi->original_i_size);
> fi->original_i_size = 0;
> }
> --
> 2.25.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


[f2fs-dev] [PATCH v2] f2fs: prevent writing without fallocate() for pinned files

2024-03-12 Thread Daeho Jeong
From: Daeho Jeong 

In a case writing without fallocate(), we can't guarantee it's allocated
in the conventional area for zoned stroage.

Signed-off-by: Daeho Jeong 
---
v2: covered the direct io case
---
 fs/f2fs/data.c | 14 --
 fs/f2fs/file.c |  4 
 2 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index c21b92f18463..d3e5ab2736a6 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -1584,8 +1584,11 @@ int f2fs_map_blocks(struct inode *inode, struct 
f2fs_map_blocks *map, int flag)
 
/* use out-place-update for direct IO under LFS mode */
if (map->m_may_create &&
-   (is_hole || (f2fs_lfs_mode(sbi) && flag == F2FS_GET_BLOCK_DIO))) {
-   if (unlikely(f2fs_cp_error(sbi))) {
+   (is_hole || (f2fs_lfs_mode(sbi) && flag == F2FS_GET_BLOCK_DIO &&
+!f2fs_is_pinned_file(inode {
+   if (unlikely(f2fs_cp_error(sbi)) ||
+   (f2fs_is_pinned_file(inode) && is_hole &&
+flag != F2FS_GET_BLOCK_PRE_DIO)) {
err = -EIO;
goto sync_out;
}
@@ -3378,6 +3381,8 @@ static int prepare_write_begin(struct f2fs_sb_info *sbi,
f2fs_map_lock(sbi, flag);
locked = true;
} else if ((pos & PAGE_MASK) >= i_size_read(inode)) {
+   if (f2fs_is_pinned_file(inode))
+   return -EIO;
f2fs_map_lock(sbi, flag);
locked = true;
}
@@ -3407,6 +3412,11 @@ static int prepare_write_begin(struct f2fs_sb_info *sbi,
 
if (!f2fs_lookup_read_extent_cache_block(inode, index,
 _blkaddr)) {
+   if (f2fs_is_pinned_file(inode)) {
+   err = -EIO;
+   goto out;
+   }
+
if (locked) {
err = f2fs_reserve_block(, index);
goto out;
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 82277e95c88f..f98730932fc4 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -4611,6 +4611,10 @@ static int f2fs_preallocate_blocks(struct kiocb *iocb, 
struct iov_iter *iter,
return ret;
}
 
+   /* For pinned files, it should be fallocate()-ed in advance. */
+   if (f2fs_is_pinned_file(inode))
+   return 0;
+
/* Do not preallocate blocks that will be written partially in 4KB. */
map.m_lblk = F2FS_BLK_ALIGN(pos);
map.m_len = F2FS_BYTES_TO_BLK(pos + count);
-- 
2.44.0.278.ge034bb2e1d-goog



___
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] f2fs: prevent writing without fallocate() for pinned files

2024-03-11 Thread Daeho Jeong
From: Daeho Jeong 

In a case writing without fallocate(), we can't guarantee it's allocated
in the conventional area for zoned stroage.

Signed-off-by: Daeho Jeong 
---
 fs/f2fs/data.c | 7 +++
 fs/f2fs/file.c | 4 
 2 files changed, 11 insertions(+)

diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index c21b92f18463..5e4c11a719a0 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -3378,6 +3378,8 @@ static int prepare_write_begin(struct f2fs_sb_info *sbi,
f2fs_map_lock(sbi, flag);
locked = true;
} else if ((pos & PAGE_MASK) >= i_size_read(inode)) {
+   if (f2fs_is_pinned_file(inode))
+   return -EIO;
f2fs_map_lock(sbi, flag);
locked = true;
}
@@ -3407,6 +3409,11 @@ static int prepare_write_begin(struct f2fs_sb_info *sbi,
 
if (!f2fs_lookup_read_extent_cache_block(inode, index,
 _blkaddr)) {
+   if (f2fs_is_pinned_file(inode)) {
+   err = -EIO;
+   goto out;
+   }
+
if (locked) {
err = f2fs_reserve_block(, index);
goto out;
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 82277e95c88f..f98730932fc4 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -4611,6 +4611,10 @@ static int f2fs_preallocate_blocks(struct kiocb *iocb, 
struct iov_iter *iter,
return ret;
}
 
+   /* For pinned files, it should be fallocate()-ed in advance. */
+   if (f2fs_is_pinned_file(inode))
+   return 0;
+
/* Do not preallocate blocks that will be written partially in 4KB. */
map.m_lblk = F2FS_BLK_ALIGN(pos);
map.m_len = F2FS_BYTES_TO_BLK(pos + count);
-- 
2.44.0.278.ge034bb2e1d-goog



___
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] f2fs: prevent atomic write on pinned file

2024-03-11 Thread Daeho Jeong
From: Daeho Jeong 

Since atomic write way was changed to out-place-update, we should
prevent it on pinned files.

Signed-off-by: Daeho Jeong 
---
 fs/f2fs/file.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 1c044fb19c87..82277e95c88f 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -2085,7 +2085,8 @@ static int f2fs_ioc_start_atomic_write(struct file *filp, 
bool truncate)
 
inode_lock(inode);
 
-   if (!f2fs_disable_compressed_file(inode)) {
+   if (!f2fs_disable_compressed_file(inode) ||
+   f2fs_is_pinned_file(inode)) {
ret = -EINVAL;
goto out;
}
-- 
2.44.0.278.ge034bb2e1d-goog



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


[f2fs-dev] [PATCH] f2fs-tools: reset only current zones

2024-03-08 Thread Daeho Jeong
From: Daeho Jeong 

Send reset commands to only current zones and finish the others.

Signed-off-by: Daeho Jeong 
---
 fsck/fsck.c | 53 +++--
 1 file changed, 27 insertions(+), 26 deletions(-)

diff --git a/fsck/fsck.c b/fsck/fsck.c
index 3461a52..5b32d1f 100644
--- a/fsck/fsck.c
+++ b/fsck/fsck.c
@@ -3288,38 +3288,39 @@ static int chk_and_fix_wp_with_sit(int UNUSED(i), void 
*blkzone, void *opaque)
 
last_valid_blkoff = last_vblk_off_in_zone(sbi, zone_segno);
 
-   /*
-* When there is no valid block in the zone, check write pointer is
-* at zone start. If not, reset the write pointer.
-*/
-   if (last_valid_blkoff < 0 &&
-   blk_zone_wp_sector(blkz) != blk_zone_sector(blkz)) {
-   if (!c.fix_on) {
-   MSG(0, "Inconsistent write pointer: wp[0x%x,0x%x]\n",
-   wp_segno, wp_blkoff);
-   fsck->chk.wp_inconsistent_zones++;
-   return 0;
-   }
-
-   FIX_MSG("Reset write pointer of zone at segment 0x%x",
-   zone_segno);
-   ret = f2fs_reset_zone(wpd->dev_index, blkz);
-   if (ret) {
-   printf("[FSCK] Write pointer reset failed: %s\n",
-  dev->path);
-   return ret;
-   }
-   fsck->chk.wp_fixed = 1;
-   return 0;
-   }
-
/* if a curseg points to the zone, do not finishing zone */
for (i = 0; i < NO_CHECK_TYPE; i++) {
struct curseg_info *cs = CURSEG_I(sbi, i);
 
if (zone_segno <= cs->segno &&
-   cs->segno < zone_segno + segs_per_zone)
+   cs->segno < zone_segno + segs_per_zone) {
+   /*
+* When there is no valid block in the zone, check
+* write pointer is at zone start. If not, reset
+* the write pointer.
+*/
+   if (last_valid_blkoff < 0 &&
+   blk_zone_wp_sector(blkz) != blk_zone_sector(blkz)) {
+   if (!c.fix_on) {
+   MSG(0, "Inconsistent write pointer: "
+  "wp[0x%x,0x%x]\n",
+  wp_segno, wp_blkoff);
+   fsck->chk.wp_inconsistent_zones++;
+   return 0;
+   }
+
+   FIX_MSG("Reset write pointer of zone at "
+   "segment 0x%x", zone_segno);
+   ret = f2fs_reset_zone(wpd->dev_index, blkz);
+   if (ret) {
+   printf("[FSCK] Write pointer reset "
+  "failed: %s\n", dev->path);
+   return ret;
+   }
+   fsck->chk.wp_fixed = 1;
+   }
return 0;
+   }
}
 
/*
-- 
2.44.0.278.ge034bb2e1d-goog



___
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] mkfs.f2fs: should give section-aligned reserved segments

2024-03-08 Thread Daeho Jeong
Reviewed-by: Daeho Jeong 

On Fri, Feb 23, 2024 at 6:02 PM Jaegeuk Kim  wrote:
>
> The reserved segments should be aligned to the section boundary.
>
> Signed-off-by: Jaegeuk Kim 
> ---
>
>   v2:
>   - fix bug
>
>  include/f2fs_fs.h | 12 +++-
>  1 file changed, 7 insertions(+), 5 deletions(-)
>
> diff --git a/include/f2fs_fs.h b/include/f2fs_fs.h
> index 9056e02acd29..fc56396fa358 100644
> --- a/include/f2fs_fs.h
> +++ b/include/f2fs_fs.h
> @@ -1760,25 +1760,27 @@ extern uint32_t f2fs_get_usable_segments(struct 
> f2fs_super_block *sb);
>  #define ZONE_ALIGN(blks)   SIZE_ALIGN(blks, c.blks_per_seg * \
> c.segs_per_zone)
>
> -static inline double get_reserved(struct f2fs_super_block *sb, double ovp)
> +static inline uint32_t get_reserved(struct f2fs_super_block *sb, double ovp)
>  {
> -   double reserved;
> uint32_t usable_main_segs = f2fs_get_usable_segments(sb);
> uint32_t segs_per_sec = round_up(usable_main_segs, 
> get_sb(section_count));
> +   uint32_t reserved;
>
> if (c.conf_reserved_sections)
> reserved = c.conf_reserved_sections * segs_per_sec;
> else
> reserved = (100 / ovp + 1 + NR_CURSEG_TYPE) * segs_per_sec;
>
> -   return reserved;
> +   /* Let's keep the section alignment */
> +   return round_up(reserved, segs_per_sec) * segs_per_sec;
>  }
>
>  static inline double get_best_overprovision(struct f2fs_super_block *sb)
>  {
> -   double reserved, ovp, candidate, end, diff, space;
> +   double ovp, candidate, end, diff, space;
> double max_ovp = 0, max_space = 0;
> uint32_t usable_main_segs = f2fs_get_usable_segments(sb);
> +   uint32_t reserved;
>
> if (get_sb(segment_count_main) < 256) {
> candidate = 10;
> @@ -1795,7 +1797,7 @@ static inline double get_best_overprovision(struct 
> f2fs_super_block *sb)
> ovp = (usable_main_segs - reserved) * candidate / 100;
> if (ovp < 0)
> continue;
> -   space = usable_main_segs - max(reserved, ovp) -
> +   space = usable_main_segs - max((double)reserved, ovp) -
> 2 * get_sb(segs_per_sec);
> if (max_space < space) {
> max_space = space;
> --
> 2.44.0.rc0.258.g7320e95886-goog
>
>
>
> ___
> 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] f2fs-tools: deal with permission denial on non-root user

2024-03-05 Thread Daeho Jeong
Reviewed-by: Daeho Jeong 

On Tue, Mar 5, 2024 at 12:50 PM Jaegeuk Kim  wrote:
>
> This fixes some android build failures due to the missing permission when
> checking the loop device. Until we get a better solution, let's ignore
> the error with warnings.
>
> Signed-off-by: Jaegeuk Kim 
> ---
>  lib/libf2fs.c | 12 +---
>  1 file changed, 9 insertions(+), 3 deletions(-)
>
> diff --git a/lib/libf2fs.c b/lib/libf2fs.c
> index d51e485361ee..1cfbf31a9c85 100644
> --- a/lib/libf2fs.c
> +++ b/lib/libf2fs.c
> @@ -854,9 +854,15 @@ int f2fs_dev_is_umounted(char *path)
>
> loop_fd = open(mnt->mnt_fsname, O_RDONLY);
> if (loop_fd < 0) {
> +   /* non-root users have no permission */
> +   if (errno == EPERM || errno == EACCES) {
> +   MSG(0, "Info: open %s failed errno:%d 
> - be careful to overwrite a mounted loopback file.\n",
> +   mnt->mnt_fsname, 
> errno);
> +   return 0;
> +   }
> MSG(0, "Info: open %s failed errno:%d\n",
> -   mnt->mnt_fsname, errno);
> -   return -1;
> +   mnt->mnt_fsname, 
> errno);
> +   return -errno;
> }
>
> err = ioctl(loop_fd, LOOP_GET_STATUS64, );
> @@ -864,7 +870,7 @@ int f2fs_dev_is_umounted(char *path)
> if (err < 0) {
> MSG(0, "\tError: ioctl LOOP_GET_STATUS64 
> failed errno:%d!\n",
> errno);
> -   return -1;
> +   return -errno;
> }
>
> if (st_buf.st_dev == loopinfo.lo_device &&
> --
> 2.44.0.278.ge034bb2e1d-goog
>
>
>
> ___
> 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 4/4] f2fs: fix to reset fields for unloaded curseg

2024-02-29 Thread Daeho Jeong
Reviewed-by: Daeho Jeong 

Thanks,

On Sun, Feb 25, 2024 at 5:33 PM Chao Yu  wrote:
>
> In f2fs_allocate_data_block(), before skip allocating new segment
> for DATA_PINNED log header, it needs to tag log header as unloaded
> one to avoid skipping logic in locate_dirty_segment() and
> __f2fs_save_inmem_curseg().
>
> Signed-off-by: Chao Yu 
> ---
>  fs/f2fs/segment.c | 19 +++
>  1 file changed, 15 insertions(+), 4 deletions(-)
>
> diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
> index c159b0985596..5e45afd69f3f 100644
> --- a/fs/f2fs/segment.c
> +++ b/fs/f2fs/segment.c
> @@ -3101,12 +3101,16 @@ static int __allocate_new_segment(struct f2fs_sb_info 
> *sbi, int type,
> struct curseg_info *curseg = CURSEG_I(sbi, type);
> unsigned int old_segno;
>
> +   if (type == CURSEG_COLD_DATA_PINNED && !curseg->inited)
> +   goto allocate;
> +
> if (!force && curseg->inited &&
> !curseg->next_blkoff &&
> !get_valid_blocks(sbi, curseg->segno, new_sec) &&
> !get_ckpt_valid_blocks(sbi, curseg->segno, new_sec))
> return 0;
>
> +allocate:
> old_segno = curseg->segno;
> if (new_curseg(sbi, type, true))
> return -EAGAIN;
> @@ -3451,6 +3455,13 @@ static void f2fs_randomize_chunk(struct f2fs_sb_info 
> *sbi,
> get_random_u32_inclusive(1, sbi->max_fragment_hole);
>  }
>
> +static void reset_curseg_fields(struct curseg_info *curseg)
> +{
> +   curseg->inited = false;
> +   curseg->segno = NULL_SEGNO;
> +   curseg->next_segno = 0;
> +}
> +
>  int f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
> block_t old_blkaddr, block_t *new_blkaddr,
> struct f2fs_summary *sum, int type,
> @@ -3516,8 +3527,10 @@ int f2fs_allocate_data_block(struct f2fs_sb_info *sbi, 
> struct page *page,
>  */
> if (segment_full) {
> if (type == CURSEG_COLD_DATA_PINNED &&
> -   !((curseg->segno + 1) % sbi->segs_per_sec))
> +   !((curseg->segno + 1) % sbi->segs_per_sec)) {
> +   reset_curseg_fields(curseg);
> goto skip_new_segment;
> +   }
>
> if (from_gc) {
> get_atssr_segment(sbi, type, se->type,
> @@ -4595,9 +4608,7 @@ static int build_curseg(struct f2fs_sb_info *sbi)
> array[i].seg_type = CURSEG_COLD_DATA;
> else if (i == CURSEG_ALL_DATA_ATGC)
> array[i].seg_type = CURSEG_COLD_DATA;
> -   array[i].segno = NULL_SEGNO;
> -   array[i].next_blkoff = 0;
> -   array[i].inited = false;
> +   reset_curseg_fields([i]);
> }
> return restore_curseg_summaries(sbi);
>  }
> --
> 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 3/4] f2fs: clean up new_curseg()

2024-02-29 Thread Daeho Jeong
Reviewed-by: Daeho Jeong 

Thanks,

On Sun, Feb 25, 2024 at 5:33 PM Chao Yu  wrote:
>
> Move f2fs_valid_pinned_area() check logic from new_curseg() to
> get_new_segment(), it can avoid calling __set_free() if it fails
> to find free segment in conventional zone for pinned file.
>
> Signed-off-by: Chao Yu 
> ---
>  fs/f2fs/segment.c | 23 ++-
>  1 file changed, 14 insertions(+), 9 deletions(-)
>
> diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
> index 847fe0b7f29f..c159b0985596 100644
> --- a/fs/f2fs/segment.c
> +++ b/fs/f2fs/segment.c
> @@ -2715,12 +2715,19 @@ static int get_new_segment(struct f2fs_sb_info *sbi,
>  got_it:
> /* set it as dirty segment in free segmap */
> f2fs_bug_on(sbi, test_bit(segno, free_i->free_segmap));
> +
> +   /* no free section in conventional zone */
> +   if (new_sec && pinning &&
> +   !f2fs_valid_pinned_area(sbi, START_BLOCK(sbi, segno))) {
> +   ret = -EAGAIN;
> +   goto out_unlock;
> +   }
> __set_inuse(sbi, segno);
> *newseg = segno;
>  out_unlock:
> spin_unlock(_i->segmap_lock);
>
> -   if (ret) {
> +   if (ret == -ENOSPC) {
> f2fs_stop_checkpoint(sbi, false, STOP_CP_REASON_NO_SEGMENT);
> f2fs_bug_on(sbi, 1);
> }
> @@ -2796,19 +2803,17 @@ static int new_curseg(struct f2fs_sb_info *sbi, int 
> type, bool new_sec)
> struct curseg_info *curseg = CURSEG_I(sbi, type);
> unsigned int segno = curseg->segno;
> bool pinning = type == CURSEG_COLD_DATA_PINNED;
> +   int ret;
>
> if (curseg->inited)
> write_sum_page(sbi, curseg->sum_blk, GET_SUM_BLOCK(sbi, 
> segno));
>
> segno = __get_next_segno(sbi, type);
> -   if (get_new_segment(sbi, , new_sec, pinning)) {
> -   curseg->segno = NULL_SEGNO;
> -   return -ENOSPC;
> -   }
> -   if (new_sec && pinning &&
> -   !f2fs_valid_pinned_area(sbi, START_BLOCK(sbi, segno))) {
> -   __set_free(sbi, segno);
> -   return -EAGAIN;
> +   ret = get_new_segment(sbi, , new_sec, pinning);
> +   if (ret) {
> +   if (ret == -ENOSPC)
> +   curseg->segno = NULL_SEGNO;
> +   return ret;
> }
>
> curseg->next_segno = segno;
> --
> 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 1/4] f2fs: fix blkofs_end correctly in f2fs_migrate_blocks()

2024-02-29 Thread Daeho Jeong
On Thu, Feb 29, 2024 at 2:11 AM Chao Yu  wrote:
>
> Jaegeuk, Daeho,
>
> Any comments on this serials?
>
> Thanks,

No functional difference here, since start_blk is always aligned with
the section address.
However, this is more clear in itself.

Reviewed-by: Daeho Jeong 

Thanks,

>
> On 2024/2/26 9:32, Chao Yu wrote:
> > In f2fs_migrate_blocks(), when traversing blocks in last section,
> > blkofs_end should be (start_blk + blkcnt - 1) % blk_per_sec, fix it.
> >
> > Signed-off-by: Chao Yu 
> > ---
> >   fs/f2fs/data.c | 5 +++--
> >   1 file changed, 3 insertions(+), 2 deletions(-)
> >
> > diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
> > index c21b92f18463..0c728e82d936 100644
> > --- a/fs/f2fs/data.c
> > +++ b/fs/f2fs/data.c
> > @@ -3841,13 +3841,14 @@ static int f2fs_migrate_blocks(struct inode *inode, 
> > block_t start_blk,
> >   struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
> >   unsigned int blkofs;
> >   unsigned int blk_per_sec = BLKS_PER_SEC(sbi);
> > + unsigned int end_blk = start_blk + blkcnt - 1;
> >   unsigned int secidx = start_blk / blk_per_sec;
> >   unsigned int end_sec;
> >   int ret = 0;
> >
> >   if (!blkcnt)
> >   return 0;
> > - end_sec = secidx + (blkcnt - 1) / blk_per_sec;
> > + end_sec = end_blk / blk_per_sec;
> >
> >   f2fs_down_write(_I(inode)->i_gc_rwsem[WRITE]);
> >   filemap_invalidate_lock(inode->i_mapping);
> > @@ -3857,7 +3858,7 @@ static int f2fs_migrate_blocks(struct inode *inode, 
> > block_t start_blk,
> >
> >   for (; secidx <= end_sec; secidx++) {
> >   unsigned int blkofs_end = secidx == end_sec ?
> > - (blkcnt - 1) % blk_per_sec : blk_per_sec - 1;
> > + end_blk % blk_per_sec : blk_per_sec - 1;
> >
> >   f2fs_down_write(>pin_sem);
> >
>
>
> ___
> 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 2/4] f2fs: relocate f2fs_precache_extents() in f2fs_swap_activate()

2024-02-29 Thread Daeho Jeong
Reviewed-by: Daeho Jeong 

Thanks,

On Sun, Feb 25, 2024 at 5:33 PM Chao Yu  wrote:
>
> This patch exchangs position of f2fs_precache_extents() and
> filemap_fdatawrite(), so that f2fs_precache_extents() can load
> extent info after physical addresses of all data are fixed.
>
> Signed-off-by: Chao Yu 
> ---
>  fs/f2fs/data.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
> index 0c728e82d936..bd8674bf1d84 100644
> --- a/fs/f2fs/data.c
> +++ b/fs/f2fs/data.c
> @@ -4045,12 +4045,12 @@ static int f2fs_swap_activate(struct swap_info_struct 
> *sis, struct file *file,
> if (!f2fs_disable_compressed_file(inode))
> return -EINVAL;
>
> -   f2fs_precache_extents(inode);
> -
> ret = filemap_fdatawrite(inode->i_mapping);
> if (ret < 0)
> return ret;
>
> +   f2fs_precache_extents(inode);
> +
> ret = check_swap_activate(sis, file, span);
> if (ret < 0)
> 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


___
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/5] f2fs: allow to mount if cap is 100

2024-02-27 Thread Daeho Jeong
On Mon, Feb 26, 2024 at 2:47 PM Jaegeuk Kim  wrote:
>
> On 02/26, Daeho Jeong wrote:
> > On Fri, Feb 23, 2024 at 12:56 PM Jaegeuk Kim  wrote:
> > >
> > > Don't block mounting the partition, if cap is 100%.
> > >
> > > Signed-off-by: Jaegeuk Kim 
> > > ---
> > >  fs/f2fs/segment.c | 3 +++
> > >  1 file changed, 3 insertions(+)
> > >
> > > diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
> > > index 6d586ae8b55f..f11361152d2a 100644
> > > --- a/fs/f2fs/segment.c
> > > +++ b/fs/f2fs/segment.c
> > > @@ -904,6 +904,9 @@ int f2fs_disable_cp_again(struct f2fs_sb_info *sbi, 
> > > block_t unusable)
> > >  {
> > > int ovp_hole_segs =
> > > (overprovision_segments(sbi) - reserved_segments(sbi));
> > > +
> > > +   if (F2FS_OPTION(sbi).unusable_cap_perc == 100)
> > > +   return 0;
> >
> > With this, f2fs will not execute GC. What is this 100
> > unusable_cap_perc used for?
>
> Theoritically, it won't, but I was hitting a GC loop, and I suspected a wrong
> section/segment layout. So, I posted the below, and guess we need this patch
> as workaround.
>
> https://patchwork.kernel.org/project/f2fs/patch/20240224011411.3820719-1-jaeg...@kernel.org/

Reviewed-by: Daeho Jeong 

>
> >
> > > if (unusable > F2FS_OPTION(sbi).unusable_cap)
> > > return -EAGAIN;
> > > if (is_sbi_flag_set(sbi, SBI_CP_DISABLED_QUICK) &&
> > > --
> > > 2.44.0.rc0.258.g7320e95886-goog
> > >
> > >
> > >
> > > ___
> > > 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 5/5] f2fs: allow to mount if cap is 100

2024-02-26 Thread Daeho Jeong
On Fri, Feb 23, 2024 at 12:56 PM Jaegeuk Kim  wrote:
>
> Don't block mounting the partition, if cap is 100%.
>
> Signed-off-by: Jaegeuk Kim 
> ---
>  fs/f2fs/segment.c | 3 +++
>  1 file changed, 3 insertions(+)
>
> diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
> index 6d586ae8b55f..f11361152d2a 100644
> --- a/fs/f2fs/segment.c
> +++ b/fs/f2fs/segment.c
> @@ -904,6 +904,9 @@ int f2fs_disable_cp_again(struct f2fs_sb_info *sbi, 
> block_t unusable)
>  {
> int ovp_hole_segs =
> (overprovision_segments(sbi) - reserved_segments(sbi));
> +
> +   if (F2FS_OPTION(sbi).unusable_cap_perc == 100)
> +   return 0;

With this, f2fs will not execute GC. What is this 100
unusable_cap_perc used for?

> if (unusable > F2FS_OPTION(sbi).unusable_cap)
> return -EAGAIN;
> if (is_sbi_flag_set(sbi, SBI_CP_DISABLED_QUICK) &&
> --
> 2.44.0.rc0.258.g7320e95886-goog
>
>
>
> ___
> 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 4/5] f2fs: prevent an f2fs_gc loop during disable_checkpoint

2024-02-26 Thread Daeho Jeong
Reviewed-by: Daeho Jeong 

On Sun, Feb 25, 2024 at 6:59 PM Chao Yu  wrote:
>
> On 2024/2/24 4:55, Jaegeuk Kim wrote:
> > Don't get stuck in the f2fs_gc loop while disabling checkpoint. Instead, we 
> > have
> > a time-based management.
> >
> > 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


___
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/5] f2fs: print zone status in string and some log

2024-02-26 Thread Daeho Jeong
On Fri, Feb 23, 2024 at 12:56 PM Jaegeuk Kim  wrote:
>
> No functional change, but add some more logs.
>
> Signed-off-by: Jaegeuk Kim 
> ---
>  fs/f2fs/segment.c | 34 --
>  fs/f2fs/super.c   |  1 +
>  2 files changed, 25 insertions(+), 10 deletions(-)
>
> diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
> index d4f228e6f771..6d586ae8b55f 100644
> --- a/fs/f2fs/segment.c
> +++ b/fs/f2fs/segment.c
> @@ -4912,6 +4912,16 @@ static int sanity_check_curseg(struct f2fs_sb_info 
> *sbi)
>  }
>
>  #ifdef CONFIG_BLK_DEV_ZONED
> +const char *f2fs_zone_status[BLK_ZONE_COND_OFFLINE + 1] = {
> +   [BLK_ZONE_COND_NOT_WP]  = "NOT_WP",
> +   [BLK_ZONE_COND_EMPTY]   = "EMPTY",
> +   [BLK_ZONE_COND_IMP_OPEN]= "IMPLICITE_OPEN",
> +   [BLK_ZONE_COND_EXP_OPEN]= "EXPLICITE_OPEN",
> +   [BLK_ZONE_COND_CLOSED]  = "CLOSED",
> +   [BLK_ZONE_COND_READONLY]= "READONLY",
> +   [BLK_ZONE_COND_FULL]= "FULL",
> +   [BLK_ZONE_COND_OFFLINE] = "OFFLINE",
> +};
>
>  static int check_zone_write_pointer(struct f2fs_sb_info *sbi,
> struct f2fs_dev_info *fdev,
> @@ -4928,18 +4938,22 @@ static int check_zone_write_pointer(struct 
> f2fs_sb_info *sbi,
> zone_block = fdev->start_blk + (zone->start >> log_sectors_per_block);
> zone_segno = GET_SEGNO(sbi, zone_block);
>
> +   /*
> +* Get # of valid block of the zone.
> +*/
> +   valid_block_cnt = get_valid_blocks(sbi, zone_segno, true);
> +
> /*
>  * Skip check of zones cursegs point to, since
>  * fix_curseg_write_pointer() checks them.
>  */
> if (zone_segno >= MAIN_SEGS(sbi) ||

How about this not to use a wrong segno value for get_valid_blocks()
and not to print a wrong segment info?

if (zone_segno >= MAIN_SEGS(sbi))
return 0;

valid_block_cnt = get_valid_blocks(sbi, zone_segno, true);

> -   IS_CURSEC(sbi, GET_SEC_FROM_SEG(sbi, zone_segno)))
> +   IS_CURSEC(sbi, GET_SEC_FROM_SEG(sbi, zone_segno))) {
> +   f2fs_notice(sbi, "Open zones: valid block[0x%x,0x%x] 
> cond[%s]",
> +   zone_segno, valid_block_cnt,
> +   f2fs_zone_status[zone->cond]);
> return 0;
> -
> -   /*
> -* Get # of valid block of the zone.
> -*/
> -   valid_block_cnt = get_valid_blocks(sbi, zone_segno, true);
> +   }
>
> if ((!valid_block_cnt && zone->cond == BLK_ZONE_COND_EMPTY) ||
> (valid_block_cnt && zone->cond == BLK_ZONE_COND_FULL))
> @@ -4947,8 +4961,8 @@ static int check_zone_write_pointer(struct f2fs_sb_info 
> *sbi,
>
> if (!valid_block_cnt) {
> f2fs_notice(sbi, "Zone without valid block has non-zero write 
> "
> -   "pointer. Reset the write pointer: cond[0x%x]",
> -   zone->cond);
> +   "pointer. Reset the write pointer: cond[%s]",
> +   f2fs_zone_status[zone->cond]);
> ret = __f2fs_issue_discard_zone(sbi, fdev->bdev, zone_block,
> zone->len >> log_sectors_per_block);
> if (ret)
> @@ -4965,8 +4979,8 @@ static int check_zone_write_pointer(struct f2fs_sb_info 
> *sbi,
>  * selected for write operation until it get discarded.
>  */
> f2fs_notice(sbi, "Valid blocks are not aligned with write "
> -   "pointer: valid block[0x%x,0x%x] cond[0x%x]",
> -   zone_segno, valid_block_cnt, zone->cond);
> +   "pointer: valid block[0x%x,0x%x] cond[%s]",
> +   zone_segno, valid_block_cnt, 
> f2fs_zone_status[zone->cond]);
>
> ret = blkdev_zone_mgmt(fdev->bdev, REQ_OP_ZONE_FINISH,
> zone->start, zone->len, GFP_NOFS);
> diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
> index 4d03ce1109ad..fc7f1a9fbbda 100644
> --- a/fs/f2fs/super.c
> +++ b/fs/f2fs/super.c
> @@ -4674,6 +4674,7 @@ static int f2fs_fill_super(struct super_block *sb, void 
> *data, int silent)
>  * check zoned block devices' write pointer consistency.
>  */
> if (!f2fs_readonly(sb) && f2fs_sb_has_blkzoned(sbi)) {
> +   f2fs_notice(sbi, "Checking entire write pointers");
> err = f2fs_check_write_pointer(sbi);
> if (err)
> goto free_meta;
> --
> 2.44.0.rc0.258.g7320e95886-goog
>
>
>
> ___
> 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 2/5] f2fs: fix write pointers all the time

2024-02-26 Thread Daeho Jeong
On Sun, Feb 25, 2024 at 6:49 PM Chao Yu  wrote:
>
> On 2024/2/24 4:55, Jaegeuk Kim wrote:
> > Even if the roll forward recovery stopped due to any error, we have to fix
> > the write pointers in order to mount the disk from the previous checkpoint.
>
> Jaegeuk,
>
> IIUC, we may lost warm node chain once we allocate new section for all logs,
> should we give some notification in log to indicate such condition that
> filesystem doesn't process a full recovery flow?
>
> Thanks,
>
> >
> > Signed-off-by: Jaegeuk Kim 
> > ---
> >   fs/f2fs/recovery.c | 2 +-
> >   fs/f2fs/super.c| 2 +-
> >   2 files changed, 2 insertions(+), 2 deletions(-)
> >
> > diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c
> > index b3baec666afe..8bbecb5f9323 100644
> > --- a/fs/f2fs/recovery.c
> > +++ b/fs/f2fs/recovery.c
> > @@ -913,7 +913,7 @@ int f2fs_recover_fsync_data(struct f2fs_sb_info *sbi, 
> > bool check_only)
> >* and the f2fs is not read only, check and fix zoned block devices'
> >* write pointer consistency.
> >*/
> > - if (!err && fix_curseg_write_pointer && !f2fs_readonly(sbi->sb) &&
> > + if (fix_curseg_write_pointer && !f2fs_readonly(sbi->sb) &&
> >   f2fs_sb_has_blkzoned(sbi)) {
> >   err = f2fs_fix_curseg_write_pointer(sbi);

We might overwrite the previous err value here with a new err from
f2fs_fix_curseg_write_pointer().

> >   if (!err)
> > diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
> > index 2e41142d07c0..4d03ce1109ad 100644
> > --- a/fs/f2fs/super.c
> > +++ b/fs/f2fs/super.c
> > @@ -4673,7 +4673,7 @@ static int f2fs_fill_super(struct super_block *sb, 
> > void *data, int silent)
> >* If the f2fs is not readonly and fsync data recovery succeeds,
> >* check zoned block devices' write pointer consistency.
> >*/
> > - if (!err && !f2fs_readonly(sb) && f2fs_sb_has_blkzoned(sbi)) {
> > + if (!f2fs_readonly(sb) && f2fs_sb_has_blkzoned(sbi)) {
> >   err = f2fs_check_write_pointer(sbi);

ditto

> >   if (err)
> >   goto free_meta;
>
>
> ___
> 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 1/5] f2fs: check number of blocks in a current section

2024-02-26 Thread Daeho Jeong
On Sun, Feb 25, 2024 at 6:42 PM Chao Yu  wrote:
>
> On 2024/2/24 4:55, Jaegeuk Kim wrote:
> > In cfd66bb715fd ("f2fs: fix deadloop in foreground GC"), we needed to check
> > the number of blocks in a section instead of the segment.
> >
> > In addtion, let's check the entire node sections when checking the avaiable
> > node block space. It does not match one to one per temperature, but 
> > currently
>
> I tested this patch w/ testcase in [1], it doesn't complain.
>
> [1] https://bugzilla.kernel.org/show_bug.cgi?id=215914
>
> > we don't have exact dirty page count per temperature. Hence, use a rough
> > estimation.
>
> Do we need more accurate per-temperature dirty node count for extreme
> corner case?
>
> e.g. node_blocks is counted from hot dirty nodes, and current hot_node
> log has no enough free space for it.
>
> Thanks,
>
> >
> > Fixes: cfd66bb715fd ("f2fs: fix deadloop in foreground GC")
> > Signed-off-by: Jaegeuk Kim 
> > ---
> >   fs/f2fs/segment.h | 22 +++---
> >   1 file changed, 11 insertions(+), 11 deletions(-)
> >
> > diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h
> > index 3edd3809b6b5..15bf5edd9b3c 100644
> > --- a/fs/f2fs/segment.h
> > +++ b/fs/f2fs/segment.h
> > @@ -561,23 +561,23 @@ static inline bool has_curseg_enough_space(struct 
> > f2fs_sb_info *sbi,
> >   unsigned int node_blocks, unsigned int dent_blocks)
> >   {
> >
> > - unsigned int segno, left_blocks;
> > + unsigned segno, left_blocks;
> >   int i;
> >
> > - /* check current node segment */
> > + /* check current node sections, which counts very roughly */
> > + left_blocks = 0;
> >   for (i = CURSEG_HOT_NODE; i <= CURSEG_COLD_NODE; i++) {
> >   segno = CURSEG_I(sbi, i)->segno;
> > - left_blocks = f2fs_usable_blks_in_seg(sbi, segno) -
> > - get_seg_entry(sbi, segno)->ckpt_valid_blocks;
> > -
> > - if (node_blocks > left_blocks)
> > - return false;
> > + left_blocks += CAP_BLKS_PER_SEC(sbi) -
> > + get_ckpt_valid_blocks(sbi, segno, true);
> >   }
> > + if (node_blocks > left_blocks)
> > + return false;

I am not sure this is okay. The current implementation of f2fs may not
be optimal when the HOT_NODE section's space requirements exceed its
current capacity. In such cases, f2fs necessitates the creation of a
new free section to accommodate the overflow, even though there might
be free space available in other NODE sections. To address this issue,
it may be necessary to implement a more accurate accounting system for
NODE sections based on their temperature levels.

> >
> > - /* check current data segment */
> > + /* check current data section for dentry blocks. */
> >   segno = CURSEG_I(sbi, CURSEG_HOT_DATA)->segno;
> > - left_blocks = f2fs_usable_blks_in_seg(sbi, segno) -
> > - get_seg_entry(sbi, segno)->ckpt_valid_blocks;
> > + left_blocks = CAP_BLKS_PER_SEC(sbi) -
> > + get_ckpt_valid_blocks(sbi, segno, true);
> >   if (dent_blocks > left_blocks)
> >   return false;
> >   return true;
> > @@ -626,7 +626,7 @@ static inline bool has_not_enough_free_secs(struct 
> > f2fs_sb_info *sbi,
> >
> >   if (free_secs > upper_secs)
> >   return false;
> > - else if (free_secs <= lower_secs)
> > + if (free_secs <= lower_secs)
> >   return true;
> >   return !curseg_space;
> >   }
>
>
> ___
> 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 v6] f2fs: New victim selection for GC

2024-02-20 Thread Daeho Jeong
On Tue, Feb 13, 2024 at 5:36 PM Yonggil Song  wrote:
>
>
> Overview
> 
>
> This patch introduces a new way to preference data sections when selecting
> GC victims. Migration of data blocks causes invalidation of node blocks.
> Therefore, in situations where GC is frequent, selecting data blocks as
> victims can reduce unnecessary block migration by invalidating node blocks.

Your approach will allocate new node blocks despite invalidating
current node blocks while moving data blocks, though. While your
approach may work well relating to WAF in a specific scenario, such as
randomly overwriting an entire storage space with a huge file, it is
important to consider its general applicability. For example, how
about the test performance? Performance optimization should encompass
a wide range of user scenarios. However, I am not convinced that this
is the most efficient solution for most users. Can you provide more
information about how your approach addresses the performance needs of
a broader spectrum of user scenarios?

> For exceptional situations where free sections are insufficient, node blocks
> are selected as victims instead of data blocks to get extra free sections.
>
> Problem
> ===
>
> If the total amount of nodes is larger than the size of one section, nodes
> occupy multiple sections, and node victims are often selected because the
> gc cost is lowered by data block migration in GC. Since moving the data
> section causes frequent node victim selection, victim threshing occurs in
> the node section. This results in an increase in WAF.
>
> Experiment
> ==
>
> Test environment is as follows.
>
> System info
>   - 3.6GHz, 16 core CPU
>   - 36GiB Memory
> Device info
>   - a conventional null_blk with 228MiB
>   - a sequential null_blk with 4068 zones of 8MiB
> Format
>   - mkfs.f2fs  -c  -m -Z 8 -o 3.89
> Mount
>   - mount  
> Fio script
>   - fio --rw=randwrite --bs=4k --ba=4k --filesize=31187m 
> --norandommap --overwrite=1 --name=job1 --filename=./mnt/sustain 
> --io_size=128g
> WAF calculation
>   - (IOs on conv. null_blk + IOs on seq. null_blk) / random write IOs
>
> Conclusion
> ==
>
> This experiment showed that the WAF was reduced by 29% (18.75 -> 13.3) when
> the data section was selected first when selecting GC victims. This was
> achieved by reducing the migration of the node blocks by 69.4%
> (253,131,743 blks -> 77,463,278 blks). It is possible to achieve low WAF
> performance with the GC victim selection method in environments where the
> section size is relatively small.
>
> Signed-off-by: Yonggil Song 
> ---
>  fs/f2fs/f2fs.h |  1 +
>  fs/f2fs/gc.c   | 96 +++---
>  fs/f2fs/gc.h   |  6 
>  3 files changed, 82 insertions(+), 21 deletions(-)
>
> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> index 65294e3b0bef..b129f62ba541 100644
> --- a/fs/f2fs/f2fs.h
> +++ b/fs/f2fs/f2fs.h
> @@ -1654,6 +1654,7 @@ struct f2fs_sb_info {
> struct f2fs_mount_info mount_opt;   /* mount options */
>
> /* for cleaning operations */
> +   bool require_node_gc;   /* flag for node GC */
> struct f2fs_rwsem gc_lock;  /*
>  * semaphore for GC, avoid
>  * race between GC and GC or 
> CP
> diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
> index a079eebfb080..53a51a668567 100644
> --- a/fs/f2fs/gc.c
> +++ b/fs/f2fs/gc.c
> @@ -341,6 +341,14 @@ static unsigned int get_cb_cost(struct f2fs_sb_info 
> *sbi, unsigned int segno)
> unsigned int i;
> unsigned int usable_segs_per_sec = f2fs_usable_segs_in_sec(sbi, 
> segno);
>
> +   /*
> +* When BG_GC selects victims based on age, it prevents node victims
> +* from being selected. This is because node blocks can be invalidated
> +* by moving data blocks.
> +*/
> +   if (__skip_node_gc(sbi, segno))
> +   return UINT_MAX;
> +
> for (i = 0; i < usable_segs_per_sec; i++)
> mtime += get_seg_entry(sbi, start + i)->mtime;
> vblocks = get_valid_blocks(sbi, segno, true);
> @@ -369,10 +377,24 @@ static inline unsigned int get_gc_cost(struct 
> f2fs_sb_info *sbi,
> return get_seg_entry(sbi, segno)->ckpt_valid_blocks;
>
> /* alloc_mode == LFS */
> -   if (p->gc_mode == GC_GREEDY)
> -   return get_valid_blocks(sbi, segno, true);
> -   else if (p->gc_mode == GC_CB)
> +   if (p->gc_mode == GC_GREEDY) {
> +   /*
> +* If the data block that the node block pointed to is GCed,
> +* the node block is invalidated. For this reason, we add a
> +* weight to cost of node victims to give priority to data
> +* victims during the gc process. However, in a 

[f2fs-dev] [PATCH v2] f2fs_io: add lseek command to execute lseek()

2024-02-15 Thread Daeho Jeong
From: Daeho Jeong 

Added lseek command to support lseek() for SEEK_DATA and SEEK_HOLE.

Signed-off-by: Daeho Jeong 
---
v2: add SEEK_SET, SEEK_CUR and SEEK_END
---
 tools/f2fs_io/f2fs_io.c | 47 +
 1 file changed, 47 insertions(+)

diff --git a/tools/f2fs_io/f2fs_io.c b/tools/f2fs_io/f2fs_io.c
index e7d286a..a5e151d 100644
--- a/tools/f2fs_io/f2fs_io.c
+++ b/tools/f2fs_io/f2fs_io.c
@@ -1630,6 +1630,52 @@ static void do_removexattr(int argc, char **argv, const 
struct cmd_desc *cmd)
exit(0);
 }
 
+#define lseek_desc "do lseek for a file"
+#define lseek_help \
+"f2fs_io lseek [whence] [offset] [file_path]\n\n"  \
+"Do lseek file data in file_path and return the adjusted file offset\n"
\
+"whence can be\n"  \
+"  set  : SEEK_SET, The file offset is set to offset bytes\n"  \
+"  cur  : SEEK_CUR, The file offset is set to its current location plus offset 
bytes\n"\
+"  end  : SEEK_END, The file offset is set to the size of the file plus offset 
bytes\n"\
+"  data : SEEK_DATA, set the file offset to the next data location from 
offset\n"  \
+"  hole : SEEK_HOLE, set the file offset to the next hole from offset\n"
+
+static void do_lseek(int argc, char **argv, const struct cmd_desc *cmd)
+{
+   int fd, whence;
+   off_t offset, ret;
+
+   if (argc != 4) {
+   fputs("Excess arguments\n\n", stderr);
+   fputs(cmd->cmd_help, stderr);
+   exit(1);
+   }
+
+   offset = atoi(argv[2]);
+
+   if (!strcmp(argv[1], "set"))
+   whence = SEEK_SET;
+   else if (!strcmp(argv[1], "cur"))
+   whence = SEEK_CUR;
+   else if (!strcmp(argv[1], "end"))
+   whence = SEEK_END;
+   else if (!strcmp(argv[1], "data"))
+   whence = SEEK_DATA;
+   else if (!strcmp(argv[1], "hole"))
+   whence = SEEK_HOLE;
+   else
+   die("Wrong whence type");
+
+   fd = xopen(argv[3], O_RDONLY, 0);
+
+   ret = lseek(fd, offset, whence);
+   if (ret < 0)
+   die_errno("lseek failed");
+   printf("returned offset=%ld\n", ret);
+   exit(0);
+}
+
 #define CMD_HIDDEN 0x0001
 #define CMD(name) { #name, do_##name, name##_desc, name##_help, 0 }
 #define _CMD(name) { #name, do_##name, NULL, NULL, CMD_HIDDEN }
@@ -1671,6 +1717,7 @@ const struct cmd_desc cmd_list[] = {
CMD(listxattr),
CMD(setxattr),
CMD(removexattr),
+   CMD(lseek),
{ NULL, NULL, NULL, NULL, 0 }
 };
 
-- 
2.44.0.rc0.258.g7320e95886-goog



___
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_io: add lseek command to execute lseek()

2024-02-15 Thread Daeho Jeong
On Thu, Feb 15, 2024 at 12:36 PM Jaegeuk Kim  wrote:
>
> On 02/15, Daeho Jeong wrote:
> > From: Daeho Jeong 
> >
> > Added lseek command to support lseek() for SEEK_DATA and SEEK_HOLE.
> >
> > Signed-off-by: Daeho Jeong 
> > ---
> >  tools/f2fs_io/f2fs_io.c | 38 ++
> >  1 file changed, 38 insertions(+)
> >
> > diff --git a/tools/f2fs_io/f2fs_io.c b/tools/f2fs_io/f2fs_io.c
> > index e7d286a..b5c5b97 100644
> > --- a/tools/f2fs_io/f2fs_io.c
> > +++ b/tools/f2fs_io/f2fs_io.c
> > @@ -1630,6 +1630,43 @@ static void do_removexattr(int argc, char **argv, 
> > const struct cmd_desc *cmd)
> >   exit(0);
> >  }
> >
> > +#define lseek_desc "do lseek for SEEK_DATA or SEEK_HOLE for a file"
> > +#define lseek_help   \
> > +"f2fs_io lseek [whence] [offset] [file_path]\n\n"\
> > +"Do lseek file data in file_path\n"  \
> > +"whence can be\n"\
>
> Can we also have all the other options as well?

Sounds good.

>
> > +"  data : SEEK_DATA, return the file offset to the next data location 
> > from offset\n"\
> > +"  hole : SEEK_HOLE, return the file offset to the next hole from 
> > offset\n"
> > +
> > +static void do_lseek(int argc, char **argv, const struct cmd_desc *cmd)
> > +{
> > + int fd, whence;
> > + off_t offset, ret;
> > +
> > + if (argc != 4) {
> > + fputs("Excess arguments\n\n", stderr);
> > + fputs(cmd->cmd_help, stderr);
> > + exit(1);
> > + }
> > +
> > + offset = atoi(argv[2]);
> > +
> > + if (!strcmp(argv[1], "data"))
> > + whence = SEEK_DATA;
> > + else if (!strcmp(argv[1], "hole"))
> > + whence = SEEK_HOLE;
> > + else
> > + die("Wrong whence type");
> > +
> > + fd = xopen(argv[3], O_RDONLY, 0);
> > +
> > + ret = lseek(fd, offset, whence);
> > + if (ret < 0)
> > + die_errno("lseek failed");
> > + printf("returned offset=%ld\n", ret);
> > + exit(0);
> > +}
> > +
> >  #define CMD_HIDDEN   0x0001
> >  #define CMD(name) { #name, do_##name, name##_desc, name##_help, 0 }
> >  #define _CMD(name) { #name, do_##name, NULL, NULL, CMD_HIDDEN }
> > @@ -1671,6 +1708,7 @@ const struct cmd_desc cmd_list[] = {
> >   CMD(listxattr),
> >   CMD(setxattr),
> >   CMD(removexattr),
> > + CMD(lseek),
> >   { NULL, NULL, NULL, NULL, 0 }
> >  };
> >
> > --
> > 2.43.0.687.g38aa6559b0-goog
> >


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


[f2fs-dev] [PATCH] f2fs: support SEEK_DATA and SEEK_HOLE for compression files

2024-02-15 Thread Daeho Jeong
From: Daeho Jeong 

Fix to support SEEK_DATA and SEEK_HOLE for compression files

Signed-off-by: Daeho Jeong 
---
 fs/f2fs/file.c | 21 ++---
 1 file changed, 18 insertions(+), 3 deletions(-)

diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 21c3aa93a8db..aa19d8bed479 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -394,9 +394,20 @@ int f2fs_sync_file(struct file *file, loff_t start, loff_t 
end, int datasync)
return f2fs_do_sync_file(file, start, end, datasync, false);
 }
 
-static bool __found_offset(struct address_space *mapping, block_t blkaddr,
-   pgoff_t index, int whence)
+static bool __found_offset(struct address_space *mapping,
+   struct dnode_of_data *dn, pgoff_t index, int whence)
 {
+   block_t blkaddr = f2fs_data_blkaddr(dn);
+   struct inode *inode = mapping->host;
+   bool compressed_cluster = false;
+
+   if (f2fs_compressed_file(inode)) {
+   block_t first_blkaddr = data_blkaddr(dn->inode, dn->node_page,
+   ALIGN_DOWN(dn->ofs_in_node, F2FS_I(inode)->i_cluster_size));
+
+   compressed_cluster = first_blkaddr == COMPRESS_ADDR;
+   }
+
switch (whence) {
case SEEK_DATA:
if (__is_valid_data_blkaddr(blkaddr))
@@ -404,8 +415,12 @@ static bool __found_offset(struct address_space *mapping, 
block_t blkaddr,
if (blkaddr == NEW_ADDR &&
xa_get_mark(>i_pages, index, PAGECACHE_TAG_DIRTY))
return true;
+   if (compressed_cluster)
+   return true;
break;
case SEEK_HOLE:
+   if (compressed_cluster)
+   return false;
if (blkaddr == NULL_ADDR)
return true;
break;
@@ -474,7 +489,7 @@ static loff_t f2fs_seek_block(struct file *file, loff_t 
offset, int whence)
goto fail;
}
 
-   if (__found_offset(file->f_mapping, blkaddr,
+   if (__found_offset(file->f_mapping, ,
pgofs, whence)) {
f2fs_put_dnode();
goto found;
-- 
2.43.0.687.g38aa6559b0-goog



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


[f2fs-dev] [PATCH] f2fs_io: add lseek command to execute lseek()

2024-02-15 Thread Daeho Jeong
From: Daeho Jeong 

Added lseek command to support lseek() for SEEK_DATA and SEEK_HOLE.

Signed-off-by: Daeho Jeong 
---
 tools/f2fs_io/f2fs_io.c | 38 ++
 1 file changed, 38 insertions(+)

diff --git a/tools/f2fs_io/f2fs_io.c b/tools/f2fs_io/f2fs_io.c
index e7d286a..b5c5b97 100644
--- a/tools/f2fs_io/f2fs_io.c
+++ b/tools/f2fs_io/f2fs_io.c
@@ -1630,6 +1630,43 @@ static void do_removexattr(int argc, char **argv, const 
struct cmd_desc *cmd)
exit(0);
 }
 
+#define lseek_desc "do lseek for SEEK_DATA or SEEK_HOLE for a file"
+#define lseek_help \
+"f2fs_io lseek [whence] [offset] [file_path]\n\n"  \
+"Do lseek file data in file_path\n"\
+"whence can be\n"  \
+"  data : SEEK_DATA, return the file offset to the next data location from 
offset\n"\
+"  hole : SEEK_HOLE, return the file offset to the next hole from offset\n"
+
+static void do_lseek(int argc, char **argv, const struct cmd_desc *cmd)
+{
+   int fd, whence;
+   off_t offset, ret;
+
+   if (argc != 4) {
+   fputs("Excess arguments\n\n", stderr);
+   fputs(cmd->cmd_help, stderr);
+   exit(1);
+   }
+
+   offset = atoi(argv[2]);
+
+   if (!strcmp(argv[1], "data"))
+   whence = SEEK_DATA;
+   else if (!strcmp(argv[1], "hole"))
+   whence = SEEK_HOLE;
+   else
+   die("Wrong whence type");
+
+   fd = xopen(argv[3], O_RDONLY, 0);
+
+   ret = lseek(fd, offset, whence);
+   if (ret < 0)
+   die_errno("lseek failed");
+   printf("returned offset=%ld\n", ret);
+   exit(0);
+}
+
 #define CMD_HIDDEN 0x0001
 #define CMD(name) { #name, do_##name, name##_desc, name##_help, 0 }
 #define _CMD(name) { #name, do_##name, NULL, NULL, CMD_HIDDEN }
@@ -1671,6 +1708,7 @@ const struct cmd_desc cmd_list[] = {
CMD(listxattr),
CMD(setxattr),
CMD(removexattr),
+   CMD(lseek),
{ NULL, NULL, NULL, NULL, 0 }
 };
 
-- 
2.43.0.687.g38aa6559b0-goog



___
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: fix sparse_mode case on stat

2024-02-13 Thread Daeho Jeong
Reviewed-by: Daeho Jeong 

On Tue, Feb 13, 2024 at 3:42 PM Jaegeuk Kim  wrote:
>
> When we turn on sparse_mode, stat() will be failed, as the file will be
> created afterwards. Let's fix.
>
> Fixes: 14197d546b93 ("f2fs-tools: fix to check loop device")
> Signed-off-by: Jaegeuk Kim 
> ---
>  lib/libf2fs.c | 3 +++
>  1 file changed, 3 insertions(+)
>
> diff --git a/lib/libf2fs.c b/lib/libf2fs.c
> index 5c6c5b7bf8a7..d51e485361ee 100644
> --- a/lib/libf2fs.c
> +++ b/lib/libf2fs.c
> @@ -814,6 +814,9 @@ int f2fs_dev_is_umounted(char *path)
>  * the file system. In this case, we should not format.
>  */
> if (stat(path, _buf)) {
> +   /* sparse file will be created after this. */
> +   if (c.sparse_mode)
> +   return 0;
> MSG(0, "Info: stat failed errno:%d\n", errno);
> return -1;
> }
> --
> 2.43.0.687.g38aa6559b0-goog
>
>
>
> ___
> 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 1/2] f2fs: separate f2fs_gc_range() to use GC for a range

2024-02-13 Thread Daeho Jeong
From: Daeho Jeong 

Make f2fs_gc_range() an extenal function to use it for GC for a range.

Signed-off-by: Daeho Jeong 
Signed-off-by: Jaegeuk Kim 
---
 fs/f2fs/gc.c | 49 -
 1 file changed, 28 insertions(+), 21 deletions(-)

diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index 8a9cdc5a72c5..a089a938355b 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -1961,10 +1961,34 @@ void f2fs_build_gc_manager(struct f2fs_sb_info *sbi)
init_atgc_management(sbi);
 }
 
+static int f2fs_gc_range(struct f2fs_sb_info *sbi,
+   unsigned int start_seg, unsigned int end_seg, bool dry_run)
+{
+   unsigned int segno;
+
+   for (segno = start_seg; segno <= end_seg; segno += SEGS_PER_SEC(sbi)) {
+   struct gc_inode_list gc_list = {
+   .ilist = LIST_HEAD_INIT(gc_list.ilist),
+   .iroot = RADIX_TREE_INIT(gc_list.iroot, GFP_NOFS),
+   };
+
+   do_garbage_collect(sbi, segno, _list, FG_GC, true);
+   put_gc_inode(_list);
+
+   if (!dry_run && get_valid_blocks(sbi, segno, true))
+   return -EAGAIN;
+
+   if (fatal_signal_pending(current))
+   return -ERESTARTSYS;
+   }
+
+   return 0;
+}
+
 static int free_segment_range(struct f2fs_sb_info *sbi,
-   unsigned int secs, bool gc_only)
+   unsigned int secs, bool dry_run)
 {
-   unsigned int segno, next_inuse, start, end;
+   unsigned int next_inuse, start, end;
struct cp_control cpc = { CP_RESIZE, 0, 0, 0 };
int gc_mode, gc_type;
int err = 0;
@@ -1990,25 +2014,8 @@ static int free_segment_range(struct f2fs_sb_info *sbi,
f2fs_allocate_segment_for_resize(sbi, type, start, end);
 
/* do GC to move out valid blocks in the range */
-   for (segno = start; segno <= end; segno += SEGS_PER_SEC(sbi)) {
-   struct gc_inode_list gc_list = {
-   .ilist = LIST_HEAD_INIT(gc_list.ilist),
-   .iroot = RADIX_TREE_INIT(gc_list.iroot, GFP_NOFS),
-   };
-
-   do_garbage_collect(sbi, segno, _list, FG_GC, true);
-   put_gc_inode(_list);
-
-   if (!gc_only && get_valid_blocks(sbi, segno, true)) {
-   err = -EAGAIN;
-   goto out;
-   }
-   if (fatal_signal_pending(current)) {
-   err = -ERESTARTSYS;
-   goto out;
-   }
-   }
-   if (gc_only)
+   err = f2fs_gc_range(sbi, start, end, dry_run);
+   if (err || dry_run)
goto out;
 
stat_inc_cp_call_count(sbi, TOTAL_CALL);
-- 
2.43.0.687.g38aa6559b0-goog



___
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/2] f2fs: support file pinning for zoned devices

2024-02-13 Thread Daeho Jeong
From: Daeho Jeong 

Support file pinning with conventional storage area for zoned devices

Signed-off-by: Daeho Jeong 
Signed-off-by: Jaegeuk Kim 
---
v3: check the hole when migrating blocks for swap.
do not use the remainder of cold pin section.
v2: flush previous dirty pages before swapon.
do not re-check for the last extent of swap area.
merge this patch with swap file pinning support patch.
---
 fs/f2fs/data.c| 58 ++-
 fs/f2fs/f2fs.h| 17 +++-
 fs/f2fs/file.c| 24 -
 fs/f2fs/gc.c  | 14 +++---
 fs/f2fs/segment.c | 69 +--
 fs/f2fs/segment.h | 10 +++
 6 files changed, 154 insertions(+), 38 deletions(-)

diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 828c797cd47c..0c9aa3082fcf 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -3839,25 +3839,34 @@ static int f2fs_migrate_blocks(struct inode *inode, 
block_t start_blk,
unsigned int blkofs;
unsigned int blk_per_sec = BLKS_PER_SEC(sbi);
unsigned int secidx = start_blk / blk_per_sec;
-   unsigned int end_sec = secidx + blkcnt / blk_per_sec;
+   unsigned int end_sec;
int ret = 0;
 
+   if (!blkcnt)
+   return 0;
+   end_sec = secidx + (blkcnt - 1) / blk_per_sec;
+
f2fs_down_write(_I(inode)->i_gc_rwsem[WRITE]);
filemap_invalidate_lock(inode->i_mapping);
 
set_inode_flag(inode, FI_ALIGNED_WRITE);
set_inode_flag(inode, FI_OPU_WRITE);
 
-   for (; secidx < end_sec; secidx++) {
+   for (; secidx <= end_sec; secidx++) {
+   unsigned int blkofs_end = secidx == end_sec ?
+   (blkcnt - 1) % blk_per_sec : blk_per_sec - 1;
+
f2fs_down_write(>pin_sem);
 
-   f2fs_lock_op(sbi);
-   f2fs_allocate_new_section(sbi, CURSEG_COLD_DATA_PINNED, false);
-   f2fs_unlock_op(sbi);
+   ret = f2fs_allocate_pinning_section(sbi);
+   if (ret) {
+   f2fs_up_write(>pin_sem);
+   break;
+   }
 
set_inode_flag(inode, FI_SKIP_WRITES);
 
-   for (blkofs = 0; blkofs < blk_per_sec; blkofs++) {
+   for (blkofs = 0; blkofs <= blkofs_end; blkofs++) {
struct page *page;
unsigned int blkidx = secidx * blk_per_sec + blkofs;
 
@@ -3946,27 +3955,34 @@ static int check_swap_activate(struct swap_info_struct 
*sis,
nr_pblocks = map.m_len;
 
if ((pblock - SM_I(sbi)->main_blkaddr) & sec_blks_mask ||
-   nr_pblocks & sec_blks_mask) {
+   nr_pblocks & sec_blks_mask ||
+   !f2fs_valid_pinned_area(sbi, pblock)) {
+   bool last_extent = false;
+
not_aligned++;
 
nr_pblocks = roundup(nr_pblocks, blks_per_sec);
if (cur_lblock + nr_pblocks > sis->max)
nr_pblocks -= blks_per_sec;
 
+   /* this extent is last one */
if (!nr_pblocks) {
-   /* this extent is last one */
-   nr_pblocks = map.m_len;
-   f2fs_warn(sbi, "Swapfile: last extent is not 
aligned to section");
-   goto next;
+   nr_pblocks = last_lblock - cur_lblock;
+   last_extent = true;
}
 
ret = f2fs_migrate_blocks(inode, cur_lblock,
nr_pblocks);
-   if (ret)
+   if (ret) {
+   if (ret == -ENOENT)
+   ret = -EINVAL;
goto out;
-   goto retry;
+   }
+
+   if (!last_extent)
+   goto retry;
}
-next:
+
if (cur_lblock + nr_pblocks >= sis->max)
nr_pblocks = sis->max - cur_lblock;
 
@@ -4004,17 +4020,17 @@ static int f2fs_swap_activate(struct swap_info_struct 
*sis, struct file *file,
sector_t *span)
 {
struct inode *inode = file_inode(file);
+   struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
int ret;
 
if (!S_ISREG(inode->i_mode))
return -EINVAL;
 
-   if (f2fs_readonly(F2FS_I_SB(inode)->sb))
+   if (f2fs_readonly(sbi->sb))
return -EROFS;
 
-   if (f2fs_lfs_mode(F2FS_I_SB(inode))) {
-   f2fs_err(F2FS_I_SB(inode),
-   "Swapfile not suppor

[f2fs-dev] [PATCH v2 2/2] f2fs: support file pinning for zoned devices

2024-02-08 Thread Daeho Jeong
From: Daeho Jeong 

Support file pinning with conventional storage area for zoned devices

Signed-off-by: Daeho Jeong 
Signed-off-by: Jaegeuk Kim 
---
v2: flush previous dirty pages before swapon.
do not re-check for the last extent of swap area.
merge this patch with swap file pinning support patch.
---
 fs/f2fs/data.c| 62 +-
 fs/f2fs/f2fs.h| 17 +++-
 fs/f2fs/file.c| 24 -
 fs/f2fs/gc.c  | 14 +++---
 fs/f2fs/segment.c | 69 +--
 fs/f2fs/segment.h | 10 +++
 6 files changed, 159 insertions(+), 37 deletions(-)

diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 828c797cd47c..a7c5147f3286 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -3836,28 +3836,40 @@ static int f2fs_migrate_blocks(struct inode *inode, 
block_t start_blk,
unsigned int blkcnt)
 {
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
+   struct f2fs_map_blocks map = { .m_next_pgofs = NULL,
+   .m_next_extent = NULL, .m_seg_type = CURSEG_COLD_DATA_PINNED,
+   .m_may_create = true };
unsigned int blkofs;
unsigned int blk_per_sec = BLKS_PER_SEC(sbi);
unsigned int secidx = start_blk / blk_per_sec;
-   unsigned int end_sec = secidx + blkcnt / blk_per_sec;
+   unsigned int end_sec;
int ret = 0;
 
+   if (!blkcnt)
+   return 0;
+   end_sec = secidx + (blkcnt - 1) / blk_per_sec;
+
f2fs_down_write(_I(inode)->i_gc_rwsem[WRITE]);
filemap_invalidate_lock(inode->i_mapping);
 
set_inode_flag(inode, FI_ALIGNED_WRITE);
set_inode_flag(inode, FI_OPU_WRITE);
 
-   for (; secidx < end_sec; secidx++) {
+   for (; secidx <= end_sec; secidx++) {
+   unsigned int blkofs_end = secidx == end_sec ?
+   (blkcnt - 1) % blk_per_sec : blk_per_sec - 1;
+
f2fs_down_write(>pin_sem);
 
-   f2fs_lock_op(sbi);
-   f2fs_allocate_new_section(sbi, CURSEG_COLD_DATA_PINNED, false);
-   f2fs_unlock_op(sbi);
+   ret = f2fs_allocate_pinning_section(sbi);
+   if (ret) {
+   f2fs_up_write(>pin_sem);
+   break;
+   }
 
set_inode_flag(inode, FI_SKIP_WRITES);
 
-   for (blkofs = 0; blkofs < blk_per_sec; blkofs++) {
+   for (blkofs = 0; blkofs <= blkofs_end; blkofs++) {
struct page *page;
unsigned int blkidx = secidx * blk_per_sec + blkofs;
 
@@ -3875,6 +3887,12 @@ static int f2fs_migrate_blocks(struct inode *inode, 
block_t start_blk,
clear_inode_flag(inode, FI_SKIP_WRITES);
 
ret = filemap_fdatawrite(inode->i_mapping);
+   if (!ret && blkofs != blk_per_sec) {
+   map.m_lblk = secidx * blk_per_sec + blkofs;
+   map.m_len = blk_per_sec - blkofs;
+   ret = f2fs_map_blocks(inode, ,
+   F2FS_GET_BLOCK_PRE_DIO);
+   }
 
f2fs_up_write(>pin_sem);
 
@@ -3946,27 +3964,31 @@ static int check_swap_activate(struct swap_info_struct 
*sis,
nr_pblocks = map.m_len;
 
if ((pblock - SM_I(sbi)->main_blkaddr) & sec_blks_mask ||
-   nr_pblocks & sec_blks_mask) {
+   nr_pblocks & sec_blks_mask ||
+   !f2fs_valid_pinned_area(sbi, pblock)) {
+   bool last_extent = false;
+
not_aligned++;
 
nr_pblocks = roundup(nr_pblocks, blks_per_sec);
if (cur_lblock + nr_pblocks > sis->max)
nr_pblocks -= blks_per_sec;
 
+   /* this extent is last one */
if (!nr_pblocks) {
-   /* this extent is last one */
-   nr_pblocks = map.m_len;
-   f2fs_warn(sbi, "Swapfile: last extent is not 
aligned to section");
-   goto next;
+   nr_pblocks = last_lblock - cur_lblock;
+   last_extent = true;
}
 
ret = f2fs_migrate_blocks(inode, cur_lblock,
nr_pblocks);
if (ret)
goto out;
-   goto retry;
+
+   if (!last_extent)
+   goto retry;
}
-next:
+
if (cur_lblock + nr_pblocks >= sis->max)
nr_pblocks = sis->ma

[f2fs-dev] [PATCH v2 1/2] f2fs: separate f2fs_gc_range() to use GC for a range

2024-02-08 Thread Daeho Jeong
From: Daeho Jeong 

Make f2fs_gc_range() an extenal function to use it for GC for a range.

Signed-off-by: Daeho Jeong 
Signed-off-by: Jaegeuk Kim 
---
 fs/f2fs/gc.c | 49 -
 1 file changed, 28 insertions(+), 21 deletions(-)

diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index 8a9cdc5a72c5..a089a938355b 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -1961,10 +1961,34 @@ void f2fs_build_gc_manager(struct f2fs_sb_info *sbi)
init_atgc_management(sbi);
 }
 
+static int f2fs_gc_range(struct f2fs_sb_info *sbi,
+   unsigned int start_seg, unsigned int end_seg, bool dry_run)
+{
+   unsigned int segno;
+
+   for (segno = start_seg; segno <= end_seg; segno += SEGS_PER_SEC(sbi)) {
+   struct gc_inode_list gc_list = {
+   .ilist = LIST_HEAD_INIT(gc_list.ilist),
+   .iroot = RADIX_TREE_INIT(gc_list.iroot, GFP_NOFS),
+   };
+
+   do_garbage_collect(sbi, segno, _list, FG_GC, true);
+   put_gc_inode(_list);
+
+   if (!dry_run && get_valid_blocks(sbi, segno, true))
+   return -EAGAIN;
+
+   if (fatal_signal_pending(current))
+   return -ERESTARTSYS;
+   }
+
+   return 0;
+}
+
 static int free_segment_range(struct f2fs_sb_info *sbi,
-   unsigned int secs, bool gc_only)
+   unsigned int secs, bool dry_run)
 {
-   unsigned int segno, next_inuse, start, end;
+   unsigned int next_inuse, start, end;
struct cp_control cpc = { CP_RESIZE, 0, 0, 0 };
int gc_mode, gc_type;
int err = 0;
@@ -1990,25 +2014,8 @@ static int free_segment_range(struct f2fs_sb_info *sbi,
f2fs_allocate_segment_for_resize(sbi, type, start, end);
 
/* do GC to move out valid blocks in the range */
-   for (segno = start; segno <= end; segno += SEGS_PER_SEC(sbi)) {
-   struct gc_inode_list gc_list = {
-   .ilist = LIST_HEAD_INIT(gc_list.ilist),
-   .iroot = RADIX_TREE_INIT(gc_list.iroot, GFP_NOFS),
-   };
-
-   do_garbage_collect(sbi, segno, _list, FG_GC, true);
-   put_gc_inode(_list);
-
-   if (!gc_only && get_valid_blocks(sbi, segno, true)) {
-   err = -EAGAIN;
-   goto out;
-   }
-   if (fatal_signal_pending(current)) {
-   err = -ERESTARTSYS;
-   goto out;
-   }
-   }
-   if (gc_only)
+   err = f2fs_gc_range(sbi, start, end, dry_run);
+   if (err || dry_run)
goto out;
 
stat_inc_cp_call_count(sbi, TOTAL_CALL);
-- 
2.43.0.687.g38aa6559b0-goog



___
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/3] f2fs: deprecate io_bits

2024-02-07 Thread Daeho Jeong
Reviewed-by: Daeho Jeong 

On Tue, Feb 6, 2024 at 4:54 PM Jaegeuk Kim  wrote:
>
> Let's deprecate an unused io_bits feature to save CPU cycles and memory.
>
> Signed-off-by: Jaegeuk Kim 
> ---
>  Documentation/filesystems/f2fs.rst |  2 -
>  fs/f2fs/data.c | 73 +
>  fs/f2fs/f2fs.h | 25 ++---
>  fs/f2fs/file.c |  2 -
>  fs/f2fs/gc.c   | 10 +---
>  fs/f2fs/segment.c  |  9 +--
>  fs/f2fs/super.c| 88 +-
>  include/linux/f2fs_fs.h|  6 --
>  8 files changed, 10 insertions(+), 205 deletions(-)
>
> diff --git a/Documentation/filesystems/f2fs.rst 
> b/Documentation/filesystems/f2fs.rst
> index 32cbfa864f38..9ac5083dae8e 100644
> --- a/Documentation/filesystems/f2fs.rst
> +++ b/Documentation/filesystems/f2fs.rst
> @@ -229,8 +229,6 @@ mode=%s  Control block allocation 
> mode which supports "adaptive"
>  option for more randomness.
>  Please, use these options for your experiments and 
> we strongly
>  recommend to re-format the filesystem after using 
> these options.
> -io_bits=%u  Set the bit size of write IO requests. It should be 
> set
> -with "mode=lfs".
>  usrquotaEnable plain user disk quota accounting.
>  grpquotaEnable plain group disk quota accounting.
>  prjquotaEnable plain project quota accounting.
> diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
> index 05158f89ef32..828c797cd47c 100644
> --- a/fs/f2fs/data.c
> +++ b/fs/f2fs/data.c
> @@ -338,17 +338,6 @@ static void f2fs_write_end_io(struct bio *bio)
> struct page *page = bvec->bv_page;
> enum count_type type = WB_DATA_TYPE(page, false);
>
> -   if (page_private_dummy(page)) {
> -   clear_page_private_dummy(page);
> -   unlock_page(page);
> -   mempool_free(page, sbi->write_io_dummy);
> -
> -   if (unlikely(bio->bi_status))
> -   f2fs_stop_checkpoint(sbi, true,
> -   STOP_CP_REASON_WRITE_FAIL);
> -   continue;
> -   }
> -
> fscrypt_finalize_bounce_page();
>
>  #ifdef CONFIG_F2FS_FS_COMPRESSION
> @@ -522,50 +511,13 @@ void f2fs_submit_read_bio(struct f2fs_sb_info *sbi, 
> struct bio *bio,
> submit_bio(bio);
>  }
>
> -static void f2fs_align_write_bio(struct f2fs_sb_info *sbi, struct bio *bio)
> -{
> -   unsigned int start =
> -   (bio->bi_iter.bi_size >> F2FS_BLKSIZE_BITS) % 
> F2FS_IO_SIZE(sbi);
> -
> -   if (start == 0)
> -   return;
> -
> -   /* fill dummy pages */
> -   for (; start < F2FS_IO_SIZE(sbi); start++) {
> -   struct page *page =
> -   mempool_alloc(sbi->write_io_dummy,
> - GFP_NOIO | __GFP_NOFAIL);
> -   f2fs_bug_on(sbi, !page);
> -
> -   lock_page(page);
> -
> -   zero_user_segment(page, 0, PAGE_SIZE);
> -   set_page_private_dummy(page);
> -
> -   if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE)
> -   f2fs_bug_on(sbi, 1);
> -   }
> -}
> -
>  static void f2fs_submit_write_bio(struct f2fs_sb_info *sbi, struct bio *bio,
>   enum page_type type)
>  {
> WARN_ON_ONCE(is_read_io(bio_op(bio)));
>
> -   if (type == DATA || type == NODE) {
> -   if (f2fs_lfs_mode(sbi) && current->plug)
> -   blk_finish_plug(current->plug);
> -
> -   if (F2FS_IO_ALIGNED(sbi)) {
> -   f2fs_align_write_bio(sbi, bio);
> -   /*
> -* In the NODE case, we lose next block address chain.
> -* So, we need to do checkpoint in f2fs_sync_file.
> -*/
> -   if (type == NODE)
> -   set_sbi_flag(sbi, SBI_NEED_CP);
> -   }
> -   }
> +   if (f2fs_lfs_mode(sbi) && current->plug && PAGE_TYPE_ON_MAIN(type))
> +   blk_finish_plug(current->plug);
>
> trace_f2fs_submit_write_bio(sbi->sb, type, bio);
> iostat_update_submit_ctx(bio, type);
> @@ -794,16 +746,6 @@ static bool io_is_mergeable(stru

Re: [f2fs-dev] [PATCH 2/3] f2fs: use BLKS_PER_SEG, BLKS_PER_SEC, and SEGS_PER_SEC

2024-02-07 Thread Daeho Jeong
Reviewed-by: Daeho Jeong 

On Tue, Feb 6, 2024 at 4:55 PM Jaegeuk Kim  wrote:
>
> No functional change.
>
> Signed-off-by: Jaegeuk Kim 
> ---
>  fs/f2fs/checkpoint.c |  10 ++--
>  fs/f2fs/debug.c  |   6 +--
>  fs/f2fs/f2fs.h   |  19 +---
>  fs/f2fs/file.c   |  12 ++---
>  fs/f2fs/gc.c |  40 
>  fs/f2fs/node.c   |   4 +-
>  fs/f2fs/node.h   |   4 +-
>  fs/f2fs/recovery.c   |   2 +-
>  fs/f2fs/segment.c| 109 +--
>  fs/f2fs/segment.h|  18 ---
>  fs/f2fs/super.c  |   8 ++--
>  fs/f2fs/sysfs.c  |   6 +--
>  12 files changed, 119 insertions(+), 119 deletions(-)
>
> diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
> index b85820e70f5e..a09a9609e228 100644
> --- a/fs/f2fs/checkpoint.c
> +++ b/fs/f2fs/checkpoint.c
> @@ -900,7 +900,7 @@ static struct page *validate_checkpoint(struct 
> f2fs_sb_info *sbi,
>
> cp_blocks = le32_to_cpu(cp_block->cp_pack_total_block_count);
>
> -   if (cp_blocks > sbi->blocks_per_seg || cp_blocks <= F2FS_CP_PACKS) {
> +   if (cp_blocks > BLKS_PER_SEG(sbi) || cp_blocks <= F2FS_CP_PACKS) {
> f2fs_warn(sbi, "invalid cp_pack_total_block_count:%u",
>   le32_to_cpu(cp_block->cp_pack_total_block_count));
> goto invalid_cp;
> @@ -1335,7 +1335,7 @@ static void update_ckpt_flags(struct f2fs_sb_info *sbi, 
> struct cp_control *cpc)
>
> if (cpc->reason & CP_UMOUNT) {
> if (le32_to_cpu(ckpt->cp_pack_total_block_count) +
> -   NM_I(sbi)->nat_bits_blocks > sbi->blocks_per_seg) {
> +   NM_I(sbi)->nat_bits_blocks > BLKS_PER_SEG(sbi)) {
> clear_ckpt_flags(sbi, CP_NAT_BITS_FLAG);
> f2fs_notice(sbi, "Disable nat_bits due to no space");
> } else if (!is_set_ckpt_flags(sbi, CP_NAT_BITS_FLAG) &&
> @@ -1538,7 +1538,7 @@ static int do_checkpoint(struct f2fs_sb_info *sbi, 
> struct cp_control *cpc)
> cp_ver |= ((__u64)crc32 << 32);
> *(__le64 *)nm_i->nat_bits = cpu_to_le64(cp_ver);
>
> -   blk = start_blk + sbi->blocks_per_seg - nm_i->nat_bits_blocks;
> +   blk = start_blk + BLKS_PER_SEG(sbi) - nm_i->nat_bits_blocks;
> for (i = 0; i < nm_i->nat_bits_blocks; i++)
> f2fs_update_meta_page(sbi, nm_i->nat_bits +
> (i << F2FS_BLKSIZE_BITS), blk + i);
> @@ -1741,9 +1741,9 @@ void f2fs_init_ino_entry_info(struct f2fs_sb_info *sbi)
> im->ino_num = 0;
> }
>
> -   sbi->max_orphans = (sbi->blocks_per_seg - F2FS_CP_PACKS -
> +   sbi->max_orphans = (BLKS_PER_SEG(sbi) - F2FS_CP_PACKS -
> NR_CURSEG_PERSIST_TYPE - __cp_payload(sbi)) *
> -   F2FS_ORPHANS_PER_BLOCK;
> +   F2FS_ORPHANS_PER_BLOCK;
>  }
>
>  int __init f2fs_create_checkpoint_caches(void)
> diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c
> index fdbf994f1271..0d02224b99b7 100644
> --- a/fs/f2fs/debug.c
> +++ b/fs/f2fs/debug.c
> @@ -41,7 +41,7 @@ void f2fs_update_sit_info(struct f2fs_sb_info *sbi)
> total_vblocks = 0;
> blks_per_sec = CAP_BLKS_PER_SEC(sbi);
> hblks_per_sec = blks_per_sec / 2;
> -   for (segno = 0; segno < MAIN_SEGS(sbi); segno += sbi->segs_per_sec) {
> +   for (segno = 0; segno < MAIN_SEGS(sbi); segno += SEGS_PER_SEC(sbi)) {
> vblocks = get_valid_blocks(sbi, segno, true);
> dist = abs(vblocks - hblks_per_sec);
> bimodal += dist * dist;
> @@ -135,7 +135,7 @@ static void update_general_status(struct f2fs_sb_info 
> *sbi)
> si->cur_ckpt_time = sbi->cprc_info.cur_time;
> si->peak_ckpt_time = sbi->cprc_info.peak_time;
> spin_unlock(>cprc_info.stat_lock);
> -   si->total_count = (int)sbi->user_block_count / sbi->blocks_per_seg;
> +   si->total_count = (int)sbi->user_block_count / BLKS_PER_SEG(sbi);
> si->rsvd_segs = reserved_segments(sbi);
> si->overp_segs = overprovision_segments(sbi);
> si->valid_count = valid_user_blocks(sbi);
> @@ -208,7 +208,7 @@ static void update_general_status(struct f2fs_sb_info 
> *sbi)
> if (!blks)
> continue;
>
> -   if (blks == sbi->blocks_per_seg)
> +   if (blks == BLKS_PER_SEG(sbi))
> si->fu

Re: [f2fs-dev] [PATCH 3/3 v2] f2fs: kill zone-capacity support

2024-02-07 Thread Daeho Jeong
Reviewed-by: Daeho Jeong 

On Wed, Feb 7, 2024 at 3:31 PM Jaegeuk Kim  wrote:
>
> Since we don't see any user, let's kill.
>
> Signed-off-by: Jaegeuk Kim 
> ---
>
>  from v1:
>   - keep setting the seq bit
>
>  Documentation/ABI/testing/sysfs-fs-f2fs |  6 --
>  fs/f2fs/debug.c |  7 +-
>  fs/f2fs/f2fs.h  |  5 --
>  fs/f2fs/file.c  |  6 +-
>  fs/f2fs/gc.c| 33 +++--
>  fs/f2fs/gc.h| 26 ---
>  fs/f2fs/segment.c   | 93 +++--
>  fs/f2fs/segment.h   | 41 ---
>  fs/f2fs/super.c | 16 ++---
>  fs/f2fs/sysfs.c |  6 --
>  10 files changed, 44 insertions(+), 195 deletions(-)
>
> diff --git a/Documentation/ABI/testing/sysfs-fs-f2fs 
> b/Documentation/ABI/testing/sysfs-fs-f2fs
> index 48c135e24eb5..dff8c87d87dd 100644
> --- a/Documentation/ABI/testing/sysfs-fs-f2fs
> +++ b/Documentation/ABI/testing/sysfs-fs-f2fs
> @@ -628,12 +628,6 @@ Contact:   "Jaegeuk Kim" 
>  Description:   Controls max # of node block writes to be used for roll 
> forward
> recovery. This can limit the roll forward recovery time.
>
> -What:  /sys/fs/f2fs//unusable_blocks_per_sec
> -Date:  June 2022
> -Contact:   "Jaegeuk Kim" 
> -Description:   Shows the number of unusable blocks in a section which was 
> defined by
> -   the zone capacity reported by underlying zoned device.
> -
>  What:  /sys/fs/f2fs//current_atomic_write
>  Date:  July 2022
>  Contact:   "Daeho Jeong" 
> diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c
> index 0d02224b99b7..6617195bd27e 100644
> --- a/fs/f2fs/debug.c
> +++ b/fs/f2fs/debug.c
> @@ -32,21 +32,20 @@ static struct dentry *f2fs_debugfs_root;
>  void f2fs_update_sit_info(struct f2fs_sb_info *sbi)
>  {
> struct f2fs_stat_info *si = F2FS_STAT(sbi);
> -   unsigned long long blks_per_sec, hblks_per_sec, total_vblocks;
> +   unsigned long long hblks_per_sec, total_vblocks;
> unsigned long long bimodal, dist;
> unsigned int segno, vblocks;
> int ndirty = 0;
>
> bimodal = 0;
> total_vblocks = 0;
> -   blks_per_sec = CAP_BLKS_PER_SEC(sbi);
> -   hblks_per_sec = blks_per_sec / 2;
> +   hblks_per_sec = BLKS_PER_SEC(sbi) / 2;
> for (segno = 0; segno < MAIN_SEGS(sbi); segno += SEGS_PER_SEC(sbi)) {
> vblocks = get_valid_blocks(sbi, segno, true);
> dist = abs(vblocks - hblks_per_sec);
> bimodal += dist * dist;
>
> -   if (vblocks > 0 && vblocks < blks_per_sec) {
> +   if (vblocks > 0 && vblocks < BLKS_PER_SEC(sbi)) {
> total_vblocks += vblocks;
> ndirty++;
> }
> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> index 9a9e858083af..34d718301392 100644
> --- a/fs/f2fs/f2fs.h
> +++ b/fs/f2fs/f2fs.h
> @@ -1618,7 +1618,6 @@ struct f2fs_sb_info {
> unsigned int meta_ino_num;  /* meta inode number*/
> unsigned int log_blocks_per_seg;/* log2 blocks per segment */
> unsigned int blocks_per_seg;/* blocks per segment */
> -   unsigned int unusable_blocks_per_sec;   /* unusable blocks per 
> section */
> unsigned int segs_per_sec;  /* segments per section */
> unsigned int secs_per_zone; /* sections per zone */
> unsigned int total_sections;/* total section count */
> @@ -3743,10 +3742,6 @@ void f2fs_destroy_segment_manager(struct f2fs_sb_info 
> *sbi);
>  int __init f2fs_create_segment_manager_caches(void);
>  void f2fs_destroy_segment_manager_caches(void);
>  int f2fs_rw_hint_to_seg_type(enum rw_hint hint);
> -unsigned int f2fs_usable_segs_in_sec(struct f2fs_sb_info *sbi,
> -   unsigned int segno);
> -unsigned int f2fs_usable_blks_in_seg(struct f2fs_sb_info *sbi,
> -   unsigned int segno);
>
>  #define DEF_FRAGMENT_SIZE  4
>  #define MIN_FRAGMENT_SIZE  1
> diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
> index b0be576b2090..2c13b340c8a0 100644
> --- a/fs/f2fs/file.c
> +++ b/fs/f2fs/file.c
> @@ -1717,7 +1717,7 @@ static int f2fs_expand_inode_data(struct inode *inode, 
> loff_t offset,
> return 0;
>
> if (f2fs_is_pinned_file(inode)) {
> -   block_t sec_blks = CAP_BLKS_PER_SEC(sbi);
> +   block_t sec_blks = BLKS_PER_SEC(sbi);
>   

Re: [f2fs-dev] [PATCH] f2fs: kill heap-based allocation

2024-02-07 Thread Daeho Jeong
Reviewed-by: Daeho Jeong 

On Wed, Feb 7, 2024 at 8:50 AM Jaegeuk Kim  wrote:
>
> No one uses this feature. Let's kill it.
>
> Signed-off-by: Jaegeuk Kim 
> ---
>  Documentation/filesystems/f2fs.rst |  3 --
>  fs/f2fs/f2fs.h | 51 ++--
>  fs/f2fs/gc.c   |  5 ++-
>  fs/f2fs/segment.c  | 54 --
>  fs/f2fs/segment.h  | 10 --
>  fs/f2fs/super.c| 15 -
>  6 files changed, 34 insertions(+), 104 deletions(-)
>
> diff --git a/Documentation/filesystems/f2fs.rst 
> b/Documentation/filesystems/f2fs.rst
> index 9ac5083dae8e..1ff751009c43 100644
> --- a/Documentation/filesystems/f2fs.rst
> +++ b/Documentation/filesystems/f2fs.rst
> @@ -126,9 +126,6 @@ norecovery   Disable the roll-forward recovery 
> routine, mounted read-
>  discard/nodiscard   Enable/disable real-time discard in f2fs, if discard 
> is
>  enabled, f2fs will issue discard/TRIM commands when a
>  segment is cleaned.
> -no_heap Disable heap-style segment allocation which 
> finds free
> -segments for data from the beginning of main area, 
> while
> -for node from the end of main area.
>  nouser_xattrDisable Extended User Attributes. Note: xattr is 
> enabled
>  by default if CONFIG_F2FS_FS_XATTR is selected.
>  noacl   Disable POSIX Access Control List. Note: acl is 
> enabled
> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> index 34d718301392..40eb590ed646 100644
> --- a/fs/f2fs/f2fs.h
> +++ b/fs/f2fs/f2fs.h
> @@ -88,32 +88,31 @@ extern const char *f2fs_fault_name[FAULT_MAX];
>   */
>  #define F2FS_MOUNT_DISABLE_ROLL_FORWARD0x0001
>  #define F2FS_MOUNT_DISCARD 0x0002
> -#define F2FS_MOUNT_NOHEAP  0x0004
> -#define F2FS_MOUNT_XATTR_USER  0x0008
> -#define F2FS_MOUNT_POSIX_ACL   0x0010
> -#define F2FS_MOUNT_DISABLE_EXT_IDENTIFY0x0020
> -#define F2FS_MOUNT_INLINE_XATTR0x0040
> -#define F2FS_MOUNT_INLINE_DATA 0x0080
> -#define F2FS_MOUNT_INLINE_DENTRY   0x0100
> -#define F2FS_MOUNT_FLUSH_MERGE 0x0200
> -#define F2FS_MOUNT_NOBARRIER   0x0400
> -#define F2FS_MOUNT_FASTBOOT0x0800
> -#define F2FS_MOUNT_READ_EXTENT_CACHE   0x1000
> -#define F2FS_MOUNT_DATA_FLUSH  0x2000
> -#define F2FS_MOUNT_FAULT_INJECTION 0x4000
> -#define F2FS_MOUNT_USRQUOTA0x8000
> -#define F2FS_MOUNT_GRPQUOTA0x0001
> -#define F2FS_MOUNT_PRJQUOTA0x0002
> -#define F2FS_MOUNT_QUOTA   0x0004
> -#define F2FS_MOUNT_INLINE_XATTR_SIZE   0x0008
> -#define F2FS_MOUNT_RESERVE_ROOT0x0010
> -#define F2FS_MOUNT_DISABLE_CHECKPOINT  0x0020
> -#define F2FS_MOUNT_NORECOVERY  0x0040
> -#define F2FS_MOUNT_ATGC0x0080
> -#define F2FS_MOUNT_MERGE_CHECKPOINT0x0100
> -#defineF2FS_MOUNT_GC_MERGE 0x0200
> -#define F2FS_MOUNT_COMPRESS_CACHE  0x0400
> -#define F2FS_MOUNT_AGE_EXTENT_CACHE0x0800
> +#define F2FS_MOUNT_XATTR_USER  0x0004
> +#define F2FS_MOUNT_POSIX_ACL   0x0008
> +#define F2FS_MOUNT_DISABLE_EXT_IDENTIFY0x0010
> +#define F2FS_MOUNT_INLINE_XATTR0x0020
> +#define F2FS_MOUNT_INLINE_DATA 0x0040
> +#define F2FS_MOUNT_INLINE_DENTRY   0x0080
> +#define F2FS_MOUNT_FLUSH_MERGE 0x0100
> +#define F2FS_MOUNT_NOBARRIER   0x0200
> +#define F2FS_MOUNT_FASTBOOT0x0400
> +#define F2FS_MOUNT_READ_EXTENT_CACHE   0x0800
> +#define F2FS_MOUNT_DATA_FLUSH  0x1000
> +#define F2FS_MOUNT_FAULT_INJECTION 0x2000
> +#define F2FS_MOUNT_USRQUOTA0x4000
> +#define F2FS_MOUNT_GRPQUOTA0x8000
> +#define F2FS_MOUNT_PRJQUOTA0x0001
> +#define F2FS_MOUNT_QUOTA   0x0002
> +#define F2FS_MOUNT_INLINE_XATTR_SIZE   0x0004
> +#define F2FS_MOUNT_RESERVE_ROOT0x0008
> +#define F2FS_MOUNT_DISABLE_CHECKPOINT  0x0010
> +#define F2FS_MOUNT_NORECOVERY  0x0020
> +#define F2FS_MOUNT_ATGC0x0040
> +#define F2FS_MOUNT_MERGE_CHECKPOINT0x0080
> +#defineF2FS_MOUNT_GC_MERGE 0x0100
> +#define F2FS_MOUNT_COMPRESS_CACHE  0x0200
> +#define F2FS_MOUNT_AGE_EXTENT_CACHE0x0400
>
>  #define 

Re: [f2fs-dev] [PATCH 3/3] f2fs: kill zone-capacity support

2024-02-07 Thread Daeho Jeong
On Tue, Feb 6, 2024 at 6:43 PM Jaegeuk Kim  wrote:
>
> On 02/06, Jaegeuk Kim wrote:
> > Since we don't see any user, let's kill.
> >
> > Signed-off-by: Jaegeuk Kim 
> > ---
> >  Documentation/ABI/testing/sysfs-fs-f2fs |  6 --
> >  fs/f2fs/debug.c |  7 +-
> >  fs/f2fs/f2fs.h  |  5 --
> >  fs/f2fs/file.c  |  6 +-
> >  fs/f2fs/gc.c| 33 +++--
> >  fs/f2fs/gc.h| 26 ---
> >  fs/f2fs/segment.c   | 93 +++--
> >  fs/f2fs/segment.h   | 41 ---
> >  fs/f2fs/super.c | 16 +
> >  fs/f2fs/sysfs.c |  6 --
> >  10 files changed, 43 insertions(+), 196 deletions(-)
> >
> > diff --git a/Documentation/ABI/testing/sysfs-fs-f2fs 
> > b/Documentation/ABI/testing/sysfs-fs-f2fs
> > index 48c135e24eb5..dff8c87d87dd 100644
> > --- a/Documentation/ABI/testing/sysfs-fs-f2fs
> > +++ b/Documentation/ABI/testing/sysfs-fs-f2fs
> > @@ -628,12 +628,6 @@ Contact: "Jaegeuk Kim" 
> >  Description: Controls max # of node block writes to be used for roll 
> > forward
> >   recovery. This can limit the roll forward recovery time.
> >
> > -What:/sys/fs/f2fs//unusable_blocks_per_sec
> > -Date:June 2022
> > -Contact: "Jaegeuk Kim" 
> > -Description: Shows the number of unusable blocks in a section which was 
> > defined by
> > - the zone capacity reported by underlying zoned device.
> > -
> >  What:/sys/fs/f2fs//current_atomic_write
> >  Date:July 2022
> >  Contact: "Daeho Jeong" 
> > diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c
> > index 0d02224b99b7..6617195bd27e 100644
> > --- a/fs/f2fs/debug.c
> > +++ b/fs/f2fs/debug.c
> > @@ -32,21 +32,20 @@ static struct dentry *f2fs_debugfs_root;
> >  void f2fs_update_sit_info(struct f2fs_sb_info *sbi)
> >  {
> >   struct f2fs_stat_info *si = F2FS_STAT(sbi);
> > - unsigned long long blks_per_sec, hblks_per_sec, total_vblocks;
> > + unsigned long long hblks_per_sec, total_vblocks;
> >   unsigned long long bimodal, dist;
> >   unsigned int segno, vblocks;
> >   int ndirty = 0;
> >
> >   bimodal = 0;
> >   total_vblocks = 0;
> > - blks_per_sec = CAP_BLKS_PER_SEC(sbi);
> > - hblks_per_sec = blks_per_sec / 2;
> > + hblks_per_sec = BLKS_PER_SEC(sbi) / 2;
> >   for (segno = 0; segno < MAIN_SEGS(sbi); segno += SEGS_PER_SEC(sbi)) {
> >   vblocks = get_valid_blocks(sbi, segno, true);
> >   dist = abs(vblocks - hblks_per_sec);
> >   bimodal += dist * dist;
> >
> > - if (vblocks > 0 && vblocks < blks_per_sec) {
> > + if (vblocks > 0 && vblocks < BLKS_PER_SEC(sbi)) {
> >   total_vblocks += vblocks;
> >   ndirty++;
> >   }
> > diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> > index 9a9e858083af..34d718301392 100644
> > --- a/fs/f2fs/f2fs.h
> > +++ b/fs/f2fs/f2fs.h
> > @@ -1618,7 +1618,6 @@ struct f2fs_sb_info {
> >   unsigned int meta_ino_num;  /* meta inode number*/
> >   unsigned int log_blocks_per_seg;/* log2 blocks per segment */
> >   unsigned int blocks_per_seg;/* blocks per segment */
> > - unsigned int unusable_blocks_per_sec;   /* unusable blocks per 
> > section */
> >   unsigned int segs_per_sec;  /* segments per section */
> >   unsigned int secs_per_zone; /* sections per zone */
> >   unsigned int total_sections;/* total section count */
> > @@ -3743,10 +3742,6 @@ void f2fs_destroy_segment_manager(struct 
> > f2fs_sb_info *sbi);
> >  int __init f2fs_create_segment_manager_caches(void);
> >  void f2fs_destroy_segment_manager_caches(void);
> >  int f2fs_rw_hint_to_seg_type(enum rw_hint hint);
> > -unsigned int f2fs_usable_segs_in_sec(struct f2fs_sb_info *sbi,
> > - unsigned int segno);
> > -unsigned int f2fs_usable_blks_in_seg(struct f2fs_sb_info *sbi,
> > - unsigned int segno);
> >
> >  #define DEF_FRAGMENT_SIZE4
> >  #define MIN_FRAGMENT_SIZE1
> > diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
> > index b0be576b2090..2c13b340c8a0 100644
> > -

[f2fs-dev] [PATCH 3/3] f2fs: support swap file pinning for zoned devices

2024-02-06 Thread Daeho Jeong
From: Daeho Jeong 

Support swap file pinning for zoned devices

Signed-off-by: Daeho Jeong 
Signed-off-by: Jaegeuk Kim 
---
 fs/f2fs/data.c | 54 --
 1 file changed, 35 insertions(+), 19 deletions(-)

diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 05158f89ef32..5d8ee6e73dbe 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -3905,28 +3905,40 @@ static int f2fs_migrate_blocks(struct inode *inode, 
block_t start_blk,
unsigned int blkcnt)
 {
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
+   struct f2fs_map_blocks map = { .m_next_pgofs = NULL,
+   .m_next_extent = NULL, .m_seg_type = CURSEG_COLD_DATA_PINNED,
+   .m_may_create = true };
unsigned int blkofs;
unsigned int blk_per_sec = BLKS_PER_SEC(sbi);
unsigned int secidx = start_blk / blk_per_sec;
-   unsigned int end_sec = secidx + blkcnt / blk_per_sec;
+   unsigned int end_sec;
int ret = 0;
 
+   if (!blkcnt)
+   return 0;
+   end_sec = secidx + (blkcnt - 1) / blk_per_sec;
+
f2fs_down_write(_I(inode)->i_gc_rwsem[WRITE]);
filemap_invalidate_lock(inode->i_mapping);
 
set_inode_flag(inode, FI_ALIGNED_WRITE);
set_inode_flag(inode, FI_OPU_WRITE);
 
-   for (; secidx < end_sec; secidx++) {
+   for (; secidx <= end_sec; secidx++) {
+   unsigned int blkofs_end = secidx == end_sec ?
+   (blkcnt - 1) % blk_per_sec : blk_per_sec - 1;
+
f2fs_down_write(>pin_sem);
 
-   f2fs_lock_op(sbi);
-   f2fs_allocate_new_section(sbi, CURSEG_COLD_DATA_PINNED, false);
-   f2fs_unlock_op(sbi);
+   ret = f2fs_allocate_pinning_section(sbi);
+   if (ret) {
+   f2fs_up_write(>pin_sem);
+   break;
+   }
 
set_inode_flag(inode, FI_SKIP_WRITES);
 
-   for (blkofs = 0; blkofs < blk_per_sec; blkofs++) {
+   for (blkofs = 0; blkofs <= blkofs_end; blkofs++) {
struct page *page;
unsigned int blkidx = secidx * blk_per_sec + blkofs;
 
@@ -3944,6 +3956,12 @@ static int f2fs_migrate_blocks(struct inode *inode, 
block_t start_blk,
clear_inode_flag(inode, FI_SKIP_WRITES);
 
ret = filemap_fdatawrite(inode->i_mapping);
+   if (!ret && blkofs != blk_per_sec) {
+   map.m_lblk = secidx * blk_per_sec + blkofs;
+   map.m_len = blk_per_sec - blkofs;
+   ret = f2fs_map_blocks(inode, ,
+   F2FS_GET_BLOCK_PRE_DIO);
+   }
 
f2fs_up_write(>pin_sem);
 
@@ -4015,19 +4033,17 @@ static int check_swap_activate(struct swap_info_struct 
*sis,
nr_pblocks = map.m_len;
 
if ((pblock - SM_I(sbi)->main_blkaddr) & sec_blks_mask ||
-   nr_pblocks & sec_blks_mask) {
+   nr_pblocks & sec_blks_mask ||
+   !f2fs_valid_pinned_area(sbi, pblock)) {
not_aligned++;
 
nr_pblocks = roundup(nr_pblocks, blks_per_sec);
if (cur_lblock + nr_pblocks > sis->max)
nr_pblocks -= blks_per_sec;
 
-   if (!nr_pblocks) {
-   /* this extent is last one */
-   nr_pblocks = map.m_len;
-   f2fs_warn(sbi, "Swapfile: last extent is not 
aligned to section");
-   goto next;
-   }
+   /* this extent is last one */
+   if (!nr_pblocks)
+   nr_pblocks = last_lblock - cur_lblock;
 
ret = f2fs_migrate_blocks(inode, cur_lblock,
nr_pblocks);
@@ -4035,7 +4051,7 @@ static int check_swap_activate(struct swap_info_struct 
*sis,
goto out;
goto retry;
}
-next:
+
if (cur_lblock + nr_pblocks >= sis->max)
nr_pblocks = sis->max - cur_lblock;
 
@@ -4073,17 +4089,17 @@ static int f2fs_swap_activate(struct swap_info_struct 
*sis, struct file *file,
sector_t *span)
 {
struct inode *inode = file_inode(file);
+   struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
int ret;
 
if (!S_ISREG(inode->i_mode))
return -EINVAL;
 
-   if (f2fs_readonly(F2FS_I_SB(inode)->sb))
+   if (f2fs_readonly(sbi->sb))
return -EROFS;
 

[f2fs-dev] [PATCH 2/3] f2fs: support file pinning for zoned devices

2024-02-06 Thread Daeho Jeong
From: Daeho Jeong 

Support file pinning with conventional storage area for zoned devices

Signed-off-by: Daeho Jeong 
Signed-off-by: Jaegeuk Kim 
---
 fs/f2fs/f2fs.h| 14 +-
 fs/f2fs/file.c| 24 
 fs/f2fs/gc.c  | 14 +++---
 fs/f2fs/segment.c | 71 +--
 fs/f2fs/segment.h | 10 +++
 5 files changed, 114 insertions(+), 19 deletions(-)

diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 543898482f8b..9b8b4d6a0d61 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -3708,7 +3708,8 @@ void f2fs_get_new_segment(struct f2fs_sb_info *sbi,
unsigned int *newseg, bool new_sec, int dir);
 void f2fs_allocate_segment_for_resize(struct f2fs_sb_info *sbi, int type,
unsigned int start, unsigned int end);
-void f2fs_allocate_new_section(struct f2fs_sb_info *sbi, int type, bool force);
+int f2fs_allocate_new_section(struct f2fs_sb_info *sbi, int type, bool force);
+int f2fs_allocate_pinning_section(struct f2fs_sb_info *sbi);
 void f2fs_allocate_new_segments(struct f2fs_sb_info *sbi);
 int f2fs_trim_fs(struct f2fs_sb_info *sbi, struct fstrim_range *range);
 bool f2fs_exist_trim_candidates(struct f2fs_sb_info *sbi,
@@ -3886,6 +3887,9 @@ void f2fs_stop_gc_thread(struct f2fs_sb_info *sbi);
 block_t f2fs_start_bidx_of_node(unsigned int node_ofs, struct inode *inode);
 int f2fs_gc(struct f2fs_sb_info *sbi, struct f2fs_gc_control *gc_control);
 void f2fs_build_gc_manager(struct f2fs_sb_info *sbi);
+int f2fs_gc_range(struct f2fs_sb_info *sbi,
+   unsigned int start_seg, unsigned int end_seg,
+   bool dry_run, unsigned int dry_run_sections);
 int f2fs_resize_fs(struct file *filp, __u64 block_count);
 int __init f2fs_create_garbage_collection_cache(void);
 void f2fs_destroy_garbage_collection_cache(void);
@@ -4540,6 +4544,14 @@ static inline bool f2fs_lfs_mode(struct f2fs_sb_info 
*sbi)
return F2FS_OPTION(sbi).fs_mode == FS_MODE_LFS;
 }
 
+static inline bool f2fs_valid_pinned_area(struct f2fs_sb_info *sbi,
+ block_t blkaddr)
+{
+   int devi = f2fs_target_device_index(sbi, blkaddr);
+
+   return !bdev_is_zoned(FDEV(devi).bdev);
+}
+
 static inline bool f2fs_low_mem_mode(struct f2fs_sb_info *sbi)
 {
return F2FS_OPTION(sbi).memory_mode == MEMORY_MODE_LOW;
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 25b119cf3499..4078e7616aef 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -1735,9 +1735,11 @@ static int f2fs_expand_inode_data(struct inode *inode, 
loff_t offset,
 
f2fs_down_write(>pin_sem);
 
-   f2fs_lock_op(sbi);
-   f2fs_allocate_new_section(sbi, CURSEG_COLD_DATA_PINNED, false);
-   f2fs_unlock_op(sbi);
+   err = f2fs_allocate_pinning_section(sbi);
+   if (err) {
+   f2fs_up_write(>pin_sem);
+   goto out_err;
+   }
 
map.m_seg_type = CURSEG_COLD_DATA_PINNED;
err = f2fs_map_blocks(inode, , F2FS_GET_BLOCK_PRE_DIO);
@@ -3187,6 +3189,7 @@ int f2fs_pin_file_control(struct inode *inode, bool inc)
 static int f2fs_ioc_set_pin_file(struct file *filp, unsigned long arg)
 {
struct inode *inode = file_inode(filp);
+   struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
__u32 pin;
int ret = 0;
 
@@ -3196,7 +3199,7 @@ static int f2fs_ioc_set_pin_file(struct file *filp, 
unsigned long arg)
if (!S_ISREG(inode->i_mode))
return -EINVAL;
 
-   if (f2fs_readonly(F2FS_I_SB(inode)->sb))
+   if (f2fs_readonly(sbi->sb))
return -EROFS;
 
ret = mnt_want_write_file(filp);
@@ -3209,9 +3212,18 @@ static int f2fs_ioc_set_pin_file(struct file *filp, 
unsigned long arg)
clear_inode_flag(inode, FI_PIN_FILE);
f2fs_i_gc_failures_write(inode, 0);
goto done;
+   } else if (f2fs_is_pinned_file(inode)) {
+   goto done;
}
 
-   if (f2fs_should_update_outplace(inode, NULL)) {
+   if (f2fs_sb_has_blkzoned(sbi) && F2FS_HAS_BLOCKS(inode)) {
+   ret = -EFBIG;
+   goto out;
+   }
+
+   /* Let's allow file pinning on zoned device. */
+   if (!f2fs_sb_has_blkzoned(sbi) &&
+   f2fs_should_update_outplace(inode, NULL)) {
ret = -EINVAL;
goto out;
}
@@ -3233,7 +3245,7 @@ static int f2fs_ioc_set_pin_file(struct file *filp, 
unsigned long arg)
set_inode_flag(inode, FI_PIN_FILE);
ret = F2FS_I(inode)->i_gc_failures[GC_FAILURE_PIN];
 done:
-   f2fs_update_time(F2FS_I_SB(inode), REQ_TIME);
+   f2fs_update_time(sbi, REQ_TIME);
 out:
inode_unlock(inode);
mnt_drop_write_file(filp);
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index a46d5053f965..100695540087 100644
--- a/fs/f2fs/gc.c
+++ b

[f2fs-dev] [PATCH 1/3] f2fs: separate f2fs_gc_range() to use GC for a range

2024-02-06 Thread Daeho Jeong
From: Daeho Jeong 

Make f2fs_gc_range() an extenal function to use it for GC for a range.

Signed-off-by: Daeho Jeong 
Signed-off-by: Jaegeuk Kim 
---
 fs/f2fs/gc.c | 49 -
 1 file changed, 28 insertions(+), 21 deletions(-)

diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index a079eebfb080..a46d5053f965 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -1983,10 +1983,34 @@ void f2fs_build_gc_manager(struct f2fs_sb_info *sbi)
init_atgc_management(sbi);
 }
 
+static int f2fs_gc_range(struct f2fs_sb_info *sbi,
+   unsigned int start_seg, unsigned int end_seg, bool dry_run)
+{
+   unsigned int segno;
+
+   for (segno = start_seg; segno <= end_seg; segno += sbi->segs_per_sec) {
+   struct gc_inode_list gc_list = {
+   .ilist = LIST_HEAD_INIT(gc_list.ilist),
+   .iroot = RADIX_TREE_INIT(gc_list.iroot, GFP_NOFS),
+   };
+
+   do_garbage_collect(sbi, segno, _list, FG_GC, true);
+   put_gc_inode(_list);
+
+   if (!dry_run && get_valid_blocks(sbi, segno, true))
+   return -EAGAIN;
+
+   if (fatal_signal_pending(current))
+   return -ERESTARTSYS;
+   }
+
+   return 0;
+}
+
 static int free_segment_range(struct f2fs_sb_info *sbi,
-   unsigned int secs, bool gc_only)
+   unsigned int secs, bool dry_run)
 {
-   unsigned int segno, next_inuse, start, end;
+   unsigned int next_inuse, start, end;
struct cp_control cpc = { CP_RESIZE, 0, 0, 0 };
int gc_mode, gc_type;
int err = 0;
@@ -2012,25 +2036,8 @@ static int free_segment_range(struct f2fs_sb_info *sbi,
f2fs_allocate_segment_for_resize(sbi, type, start, end);
 
/* do GC to move out valid blocks in the range */
-   for (segno = start; segno <= end; segno += sbi->segs_per_sec) {
-   struct gc_inode_list gc_list = {
-   .ilist = LIST_HEAD_INIT(gc_list.ilist),
-   .iroot = RADIX_TREE_INIT(gc_list.iroot, GFP_NOFS),
-   };
-
-   do_garbage_collect(sbi, segno, _list, FG_GC, true);
-   put_gc_inode(_list);
-
-   if (!gc_only && get_valid_blocks(sbi, segno, true)) {
-   err = -EAGAIN;
-   goto out;
-   }
-   if (fatal_signal_pending(current)) {
-   err = -ERESTARTSYS;
-   goto out;
-   }
-   }
-   if (gc_only)
+   err = f2fs_gc_range(sbi, start, end, dry_run);
+   if (err || dry_run)
goto out;
 
stat_inc_cp_call_count(sbi, TOTAL_CALL);
-- 
2.43.0.594.gd9cf4e227d-goog



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


[f2fs-dev] [PATCH v2] f2fs-tools: allocate logs after conventional area for HM zoned devices

2024-01-31 Thread Daeho Jeong
From: Daeho Jeong 

Make to allocate logs after conventional area for HM zoned devices to
spare them for file pinning support.

Signed-off-by: Daeho Jeong 
---
v2: make current segment numbers relative to main start block. check
zoned block availability before the allocation.
---
 mkfs/f2fs_format.c | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/mkfs/f2fs_format.c b/mkfs/f2fs_format.c
index f2840c8..57ea9ea 100644
--- a/mkfs/f2fs_format.c
+++ b/mkfs/f2fs_format.c
@@ -558,6 +558,16 @@ static int f2fs_prepare_super_block(void)
c.cur_seg[CURSEG_WARM_DATA] = next_zone(CURSEG_COLD_DATA);
} else if (c.zoned_mode) {
c.cur_seg[CURSEG_HOT_NODE] = 0;
+   if (c.zoned_model == F2FS_ZONED_HM) {
+   uint32_t conv_zones =
+   c.devices[0].total_segments / c.segs_per_zone
+   - total_meta_zones;
+
+   if (total_zones - conv_zones >= avail_zones)
+   c.cur_seg[CURSEG_HOT_NODE] =
+   (c.devices[1].start_blkaddr -
+get_sb(main_blkaddr)) / c.blks_per_seg;
+   }
c.cur_seg[CURSEG_WARM_NODE] = next_zone(CURSEG_HOT_NODE);
c.cur_seg[CURSEG_COLD_NODE] = next_zone(CURSEG_WARM_NODE);
c.cur_seg[CURSEG_HOT_DATA] = next_zone(CURSEG_COLD_NODE);
-- 
2.43.0.429.g432eaa2c6b-goog



___
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: zone: fix to wait completion of last bio in zone correctly

2024-01-29 Thread Daeho Jeong
Reviewed-by: Daeho Jeong 

Thanks,

On Mon, Jan 29, 2024 at 3:29 AM Chao Yu  wrote:
>
> It needs to check last zone_pending_bio and wait IO completion before
> traverse next fio in io->io_list, otherwise, bio in next zone may be
> submitted before all IO completion in current zone.
>
> Fixes: e067dc3c6b9c ("f2fs: maintain six open zones for zoned devices")
> Cc: Daeho Jeong 
> Signed-off-by: Chao Yu 
> ---
>  fs/f2fs/data.c | 3 +--
>  1 file changed, 1 insertion(+), 2 deletions(-)
>
> diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
> index f45ecb810ae6..8cdbc5ae44db 100644
> --- a/fs/f2fs/data.c
> +++ b/fs/f2fs/data.c
> @@ -1006,7 +1006,7 @@ void f2fs_submit_page_write(struct f2fs_io_info *fio)
> f2fs_bug_on(sbi, is_read_io(fio->op));
>
> f2fs_down_write(>io_rwsem);
> -
> +next:
>  #ifdef CONFIG_BLK_DEV_ZONED
> if (f2fs_sb_has_blkzoned(sbi) && btype < META && 
> io->zone_pending_bio) {
> wait_for_completion_io(>zone_wait);
> @@ -1016,7 +1016,6 @@ void f2fs_submit_page_write(struct f2fs_io_info *fio)
> }
>  #endif
>
> -next:
> if (fio->in_list) {
> spin_lock(>io_lock);
> if (list_empty(>io_list)) {
> --
> 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] f2fs-tools: allocate logs after conventional area for HM zoned devices

2024-01-29 Thread Daeho Jeong
On Sun, Jan 28, 2024 at 5:27 PM Chao Yu  wrote:
>
> On 2024/1/27 2:17, Daeho Jeong wrote:
> > On Thu, Jan 25, 2024 at 5:27 PM Chao Yu  wrote:
> >>
> >> On 2024/1/26 0:25, Daeho Jeong wrote:
> >>> On Wed, Jan 24, 2024 at 7:34 PM Chao Yu  wrote:
> >>>>
> >>>> +Cc Yongpeng Yang
> >>>>
> >>>> Daeho,
> >>>>
> >>>> Yongpeng reports a potential issue: if c.devices[0].total_segments is
> >>>> larger than segments of mainarea, c.cur_seg[CURSEG_HOT_NODE] will exceed
> >>>> end boundary of mainarea. Could you please check that? though it's a 
> >>>> corner
> >>>> case.
> >>>
> >>> Can you elaborate more?
> >>
> >> Since c.cur_seg[CURSEG_HOT_NODE] is an offset started from main_blkaddr.
> >
> > Oh, Got it.
> > Then, how about this?
> >
> >   c.cur_seg[CURSEG_HOT_NODE] = c.zoned_model == F2FS_ZONED_HM ?
> >   (c.devices[1].start_blkaddr -
> > get_sb(main_blkaddr)) / c.blks_per_seg : 0;
>
> Better, but log header should align to start blkaddr of zone?

It's already aligned here.

if (c.zoned_mode && c.ndevs > 1)
zone_align_start_offset +=
(c.devices[0].total_sectors * c.sector_size) %
zone_size_bytes;

...

for (i = 0; i < c.ndevs; i++) {
if (i == 0) {
c.devices[i].total_segments =
(c.devices[i].total_sectors *
c.sector_size - zone_align_start_offset) /
segment_size_bytes;
c.devices[i].start_blkaddr = 0;
c.devices[i].end_blkaddr = c.devices[i].total_segments *
c.blks_per_seg - 1 +
sb->segment0_blkaddr;
} else {
c.devices[i].total_segments =
c.devices[i].total_sectors /
(c.sectors_per_blk * c.blks_per_seg);
c.devices[i].start_blkaddr =
c.devices[i - 1].end_blkaddr + 1;

...

total_meta_zones = ZONE_ALIGN(total_meta_segments *
c.blks_per_seg);

set_sb(main_blkaddr, get_sb(segment0_blkaddr) + total_meta_zones *
c.segs_per_zone * c.blks_per_seg);

>
> Thanks,
>
> >
> >> If c.cur_seg[CURSEG_HOT_NODE] was assigned w/ c.devices[0].total_segments,
> >> and c.devices[0].total_segments is larger than segments of mainare,
> >> c.cur_seg[CURSEG_HOT_NODE] will exceed the end boundary of mainarea.
> >>
> >>  c.cur_seg[CURSEG_HOT_NODE] = c.zoned_model == F2FS_ZONED_HM ?
> >>  c.devices[0].total_segments : 0;
> >>
> >>> In the case of F2FS_ZONED_HM, we have the devices[1].
> >>> Do you mean the case we format the filesystem intentionally smaller
> >>> than what devices have?
> >>
> >> I mean blew case:
> >> device[0]: conventional device size = 10240 MB
> >> device[1]: zone device size = 2 MB
> >>
> >> Thanks,
> >>
> >>>
> >>>>
> >>>> On 2024/1/18 7:00, Daeho Jeong wrote:
> >>>>> From: Daeho Jeong 
> >>>>>
> >>>>> Make to allocate logs after conventional area for HM zoned devices to
> >>>>> spare them for file pinning support.
> >>>>>
> >>>>> Signed-off-by: Daeho Jeong 
> >>>>> ---
> >>>>> mkfs/f2fs_format.c | 3 ++-
> >>>>> 1 file changed, 2 insertions(+), 1 deletion(-)
> >>>>>
> >>>>> diff --git a/mkfs/f2fs_format.c b/mkfs/f2fs_format.c
> >>>>> index f2840c8..91a7f4b 100644
> >>>>> --- a/mkfs/f2fs_format.c
> >>>>> +++ b/mkfs/f2fs_format.c
> >>>>> @@ -557,7 +557,8 @@ static int f2fs_prepare_super_block(void)
> >>>>> c.cur_seg[CURSEG_COLD_DATA] = 0;
> >>>>> c.cur_seg[CURSEG_WARM_DATA] = 
> >>>>> next_zone(CURSEG_COLD_DATA);
> >>>>> } else if (c.zoned_mode) {
> >>>>> - c.cur_seg[CURSEG_HOT_NODE] = 0;
> >>>>> + c.cur_seg[CURSEG_HOT_NODE] = c.zoned_model == 
> >>>>> F2FS_ZONED_HM ?
> >>>>> + c.devices[0].total_segments : 0;
> >>>>> c.cur_seg[CURSEG_WARM_NODE] = 
> >>>>> next_zone(CURSEG_HOT_NODE);
> >>>>> c.cur_seg[CURSEG_COLD_NODE] = 
> >>>>> next_zone(CURSEG_WARM_NODE);
> >>>>> c.cur_seg[CURSEG_HOT_DATA] = 
> >>>>> next_zone(CURSEG_COLD_NODE);


___
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: allocate logs after conventional area for HM zoned devices

2024-01-26 Thread Daeho Jeong
On Thu, Jan 25, 2024 at 5:27 PM Chao Yu  wrote:
>
> On 2024/1/26 0:25, Daeho Jeong wrote:
> > On Wed, Jan 24, 2024 at 7:34 PM Chao Yu  wrote:
> >>
> >> +Cc Yongpeng Yang
> >>
> >> Daeho,
> >>
> >> Yongpeng reports a potential issue: if c.devices[0].total_segments is
> >> larger than segments of mainarea, c.cur_seg[CURSEG_HOT_NODE] will exceed
> >> end boundary of mainarea. Could you please check that? though it's a corner
> >> case.
> >
> > Can you elaborate more?
>
> Since c.cur_seg[CURSEG_HOT_NODE] is an offset started from main_blkaddr.

Oh, Got it.
Then, how about this?

 c.cur_seg[CURSEG_HOT_NODE] = c.zoned_model == F2FS_ZONED_HM ?
 (c.devices[1].start_blkaddr -
get_sb(main_blkaddr)) / c.blks_per_seg : 0;

> If c.cur_seg[CURSEG_HOT_NODE] was assigned w/ c.devices[0].total_segments,
> and c.devices[0].total_segments is larger than segments of mainare,
> c.cur_seg[CURSEG_HOT_NODE] will exceed the end boundary of mainarea.
>
> c.cur_seg[CURSEG_HOT_NODE] = c.zoned_model == F2FS_ZONED_HM ?
> c.devices[0].total_segments : 0;
>
> > In the case of F2FS_ZONED_HM, we have the devices[1].
> > Do you mean the case we format the filesystem intentionally smaller
> > than what devices have?
>
> I mean blew case:
> device[0]: conventional device size = 10240 MB
> device[1]: zone device size = 2 MB
>
> Thanks,
>
> >
> >>
> >> On 2024/1/18 7:00, Daeho Jeong wrote:
> >>> From: Daeho Jeong 
> >>>
> >>> Make to allocate logs after conventional area for HM zoned devices to
> >>> spare them for file pinning support.
> >>>
> >>> Signed-off-by: Daeho Jeong 
> >>> ---
> >>>mkfs/f2fs_format.c | 3 ++-
> >>>1 file changed, 2 insertions(+), 1 deletion(-)
> >>>
> >>> diff --git a/mkfs/f2fs_format.c b/mkfs/f2fs_format.c
> >>> index f2840c8..91a7f4b 100644
> >>> --- a/mkfs/f2fs_format.c
> >>> +++ b/mkfs/f2fs_format.c
> >>> @@ -557,7 +557,8 @@ static int f2fs_prepare_super_block(void)
> >>>c.cur_seg[CURSEG_COLD_DATA] = 0;
> >>>c.cur_seg[CURSEG_WARM_DATA] = next_zone(CURSEG_COLD_DATA);
> >>>} else if (c.zoned_mode) {
> >>> - c.cur_seg[CURSEG_HOT_NODE] = 0;
> >>> + c.cur_seg[CURSEG_HOT_NODE] = c.zoned_model == F2FS_ZONED_HM 
> >>> ?
> >>> + c.devices[0].total_segments : 0;
> >>>c.cur_seg[CURSEG_WARM_NODE] = next_zone(CURSEG_HOT_NODE);
> >>>c.cur_seg[CURSEG_COLD_NODE] = next_zone(CURSEG_WARM_NODE);
> >>>c.cur_seg[CURSEG_HOT_DATA] = next_zone(CURSEG_COLD_NODE);


___
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: allocate logs after conventional area for HM zoned devices

2024-01-25 Thread Daeho Jeong
On Wed, Jan 24, 2024 at 7:34 PM Chao Yu  wrote:
>
> +Cc Yongpeng Yang
>
> Daeho,
>
> Yongpeng reports a potential issue: if c.devices[0].total_segments is
> larger than segments of mainarea, c.cur_seg[CURSEG_HOT_NODE] will exceed
> end boundary of mainarea. Could you please check that? though it's a corner
> case.

Can you elaborate more?
In the case of F2FS_ZONED_HM, we have the devices[1].
Do you mean the case we format the filesystem intentionally smaller
than what devices have?

>
> On 2024/1/18 7:00, Daeho Jeong wrote:
> > From: Daeho Jeong 
> >
> > Make to allocate logs after conventional area for HM zoned devices to
> > spare them for file pinning support.
> >
> > Signed-off-by: Daeho Jeong 
> > ---
> >   mkfs/f2fs_format.c | 3 ++-
> >   1 file changed, 2 insertions(+), 1 deletion(-)
> >
> > diff --git a/mkfs/f2fs_format.c b/mkfs/f2fs_format.c
> > index f2840c8..91a7f4b 100644
> > --- a/mkfs/f2fs_format.c
> > +++ b/mkfs/f2fs_format.c
> > @@ -557,7 +557,8 @@ static int f2fs_prepare_super_block(void)
> >   c.cur_seg[CURSEG_COLD_DATA] = 0;
> >   c.cur_seg[CURSEG_WARM_DATA] = next_zone(CURSEG_COLD_DATA);
> >   } else if (c.zoned_mode) {
> > - c.cur_seg[CURSEG_HOT_NODE] = 0;
> > + c.cur_seg[CURSEG_HOT_NODE] = c.zoned_model == F2FS_ZONED_HM ?
> > + c.devices[0].total_segments : 0;
> >   c.cur_seg[CURSEG_WARM_NODE] = next_zone(CURSEG_HOT_NODE);
> >   c.cur_seg[CURSEG_COLD_NODE] = next_zone(CURSEG_WARM_NODE);
> >   c.cur_seg[CURSEG_HOT_DATA] = next_zone(CURSEG_COLD_NODE);


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


[f2fs-dev] [PATCH] f2fs-tools: allocate logs after conventional area for HM zoned devices

2024-01-17 Thread Daeho Jeong
From: Daeho Jeong 

Make to allocate logs after conventional area for HM zoned devices to
spare them for file pinning support.

Signed-off-by: Daeho Jeong 
---
 mkfs/f2fs_format.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/mkfs/f2fs_format.c b/mkfs/f2fs_format.c
index f2840c8..91a7f4b 100644
--- a/mkfs/f2fs_format.c
+++ b/mkfs/f2fs_format.c
@@ -557,7 +557,8 @@ static int f2fs_prepare_super_block(void)
c.cur_seg[CURSEG_COLD_DATA] = 0;
c.cur_seg[CURSEG_WARM_DATA] = next_zone(CURSEG_COLD_DATA);
} else if (c.zoned_mode) {
-   c.cur_seg[CURSEG_HOT_NODE] = 0;
+   c.cur_seg[CURSEG_HOT_NODE] = c.zoned_model == F2FS_ZONED_HM ?
+   c.devices[0].total_segments : 0;
c.cur_seg[CURSEG_WARM_NODE] = next_zone(CURSEG_HOT_NODE);
c.cur_seg[CURSEG_COLD_NODE] = next_zone(CURSEG_WARM_NODE);
c.cur_seg[CURSEG_HOT_DATA] = next_zone(CURSEG_COLD_NODE);
-- 
2.43.0.381.gb435a96ce8-goog



___
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] f2fs: fix max open zone constraints

2024-01-16 Thread Daeho Jeong
On Tue, Jan 16, 2024 at 2:58 PM Daeho Jeong  wrote:
>
> On Tue, Jan 16, 2024 at 6:36 AM Wenjie Qi  wrote:
> >
> > We can get the number of remaining available zone
> > resources by subtracting the number of active logs from
> > the number of max active zones of zoned devices. We can
> > use these available zone resources to reduce the number
> > of pending bio when switching zones.
> > If max active zones is 0, there is no limit.
> >
> > Signed-off-by: Wenjie Qi 
> > ---
> >  fs/f2fs/data.c  | 32 +---
> >  fs/f2fs/f2fs.h  |  2 ++
> >  fs/f2fs/super.c | 11 +++
> >  3 files changed, 38 insertions(+), 7 deletions(-)
> >
> > diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
> > index dce8defdf4c7..0b62ca296074 100644
> > --- a/fs/f2fs/data.c
> > +++ b/fs/f2fs/data.c
> > @@ -392,6 +392,19 @@ static void f2fs_zone_write_end_io(struct bio *bio)
> > complete(>zone_wait);
> > f2fs_write_end_io(bio);
> >  }
> > +
> > +static void f2fs_zone_write_end_io_nowait(struct bio *bio)
> > +{
> > +#ifdef CONFIG_F2FS_IOSTAT
> > +   struct bio_iostat_ctx *iostat_ctx = bio->bi_private;
> > +   struct f2fs_sb_info *sbi = iostat_ctx->sbi;
> > +#else
> > +   struct f2fs_sb_info *sbi = (struct f2fs_sb_info *)bio->bi_private;
> > +#endif
> > +
> > +   atomic_inc(>available_active_zones);
> > +   f2fs_write_end_io(bio);
> > +}
> >  #endif
>
> I don't think this works. Let's assume we start with 2
> available_active_zones and 4 active logs.
> How about 4 active logs reach at the end of the zones at the same time?

Sorry, I was confused. It would work. However, it might be a little clumsy.
How about using a data structure like a counting semaphore?
We can decrease it as we open a zone and increase it as we close a zone.

>
> >
> >  struct block_device *f2fs_target_device(struct f2fs_sb_info *sbi,
> > @@ -1085,14 +1098,19 @@ void f2fs_submit_page_write(struct f2fs_io_info 
> > *fio)
> > goto next;
> >  out:
> >  #ifdef CONFIG_BLK_DEV_ZONED
> > -   if (f2fs_sb_has_blkzoned(sbi) && btype < META &&
> > +   if (f2fs_sb_has_blkzoned(sbi) && sbi->max_active_zones && btype < 
> > META &&
> > is_end_zone_blkaddr(sbi, fio->new_blkaddr)) {
> > -   bio_get(io->bio);
> > -   reinit_completion(>zone_wait);
> > -   io->bi_private = io->bio->bi_private;
> > -   io->bio->bi_private = io;
> > -   io->bio->bi_end_io = f2fs_zone_write_end_io;
> > -   io->zone_pending_bio = io->bio;
> > +   if (!atomic_add_negative(-1, >available_active_zones)) 
> > {
> > +   io->bio->bi_end_io = f2fs_zone_write_end_io_nowait;
> > +   } else {
> > +   atomic_inc(>available_active_zones);
> > +   bio_get(io->bio);
> > +   reinit_completion(>zone_wait);
> > +   io->bi_private = io->bio->bi_private;
> > +   io->bio->bi_private = io;
> > +   io->bio->bi_end_io = f2fs_zone_write_end_io;
> > +   io->zone_pending_bio = io->bio;
> > +   }
> > __submit_merged_bio(io);
> > }
> >  #endif
> > diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> > index 65294e3b0bef..2aade367ac66 100644
> > --- a/fs/f2fs/f2fs.h
> > +++ b/fs/f2fs/f2fs.h
> > @@ -1551,6 +1551,8 @@ struct f2fs_sb_info {
> >
> >  #ifdef CONFIG_BLK_DEV_ZONED
> > unsigned int blocks_per_blkz;   /* F2FS blocks per zone */
> > +   unsigned int max_active_zones;  /* max zone resources of 
> > the zoned device */
> > +   atomic_t available_active_zones;/* remaining zone resources 
> > for zone switch */
> >  #endif
> >
> > /* for node-related operations */
> > diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
> > index 206d03c82d96..6711283ff187 100644
> > --- a/fs/f2fs/super.c
> > +++ b/fs/f2fs/super.c
> > @@ -2385,6 +2385,12 @@ static int f2fs_remount(struct super_block *sb, int 
> > *flags, char *data)
> > if (err)
> > goto restore_opts;
> >
> > +#ifdef CONFIG_BLK_DEV_ZONED
> > +   if (sbi->max_active_zones)
> > +

Re: [f2fs-dev] [PATCH v1] f2fs: fix max open zone constraints

2024-01-16 Thread Daeho Jeong
On Tue, Jan 16, 2024 at 6:36 AM Wenjie Qi  wrote:
>
> We can get the number of remaining available zone
> resources by subtracting the number of active logs from
> the number of max active zones of zoned devices. We can
> use these available zone resources to reduce the number
> of pending bio when switching zones.
> If max active zones is 0, there is no limit.
>
> Signed-off-by: Wenjie Qi 
> ---
>  fs/f2fs/data.c  | 32 +---
>  fs/f2fs/f2fs.h  |  2 ++
>  fs/f2fs/super.c | 11 +++
>  3 files changed, 38 insertions(+), 7 deletions(-)
>
> diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
> index dce8defdf4c7..0b62ca296074 100644
> --- a/fs/f2fs/data.c
> +++ b/fs/f2fs/data.c
> @@ -392,6 +392,19 @@ static void f2fs_zone_write_end_io(struct bio *bio)
> complete(>zone_wait);
> f2fs_write_end_io(bio);
>  }
> +
> +static void f2fs_zone_write_end_io_nowait(struct bio *bio)
> +{
> +#ifdef CONFIG_F2FS_IOSTAT
> +   struct bio_iostat_ctx *iostat_ctx = bio->bi_private;
> +   struct f2fs_sb_info *sbi = iostat_ctx->sbi;
> +#else
> +   struct f2fs_sb_info *sbi = (struct f2fs_sb_info *)bio->bi_private;
> +#endif
> +
> +   atomic_inc(>available_active_zones);
> +   f2fs_write_end_io(bio);
> +}
>  #endif

I don't think this works. Let's assume we start with 2
available_active_zones and 4 active logs.
How about 4 active logs reach at the end of the zones at the same time?

>
>  struct block_device *f2fs_target_device(struct f2fs_sb_info *sbi,
> @@ -1085,14 +1098,19 @@ void f2fs_submit_page_write(struct f2fs_io_info *fio)
> goto next;
>  out:
>  #ifdef CONFIG_BLK_DEV_ZONED
> -   if (f2fs_sb_has_blkzoned(sbi) && btype < META &&
> +   if (f2fs_sb_has_blkzoned(sbi) && sbi->max_active_zones && btype < 
> META &&
> is_end_zone_blkaddr(sbi, fio->new_blkaddr)) {
> -   bio_get(io->bio);
> -   reinit_completion(>zone_wait);
> -   io->bi_private = io->bio->bi_private;
> -   io->bio->bi_private = io;
> -   io->bio->bi_end_io = f2fs_zone_write_end_io;
> -   io->zone_pending_bio = io->bio;
> +   if (!atomic_add_negative(-1, >available_active_zones)) {
> +   io->bio->bi_end_io = f2fs_zone_write_end_io_nowait;
> +   } else {
> +   atomic_inc(>available_active_zones);
> +   bio_get(io->bio);
> +   reinit_completion(>zone_wait);
> +   io->bi_private = io->bio->bi_private;
> +   io->bio->bi_private = io;
> +   io->bio->bi_end_io = f2fs_zone_write_end_io;
> +   io->zone_pending_bio = io->bio;
> +   }
> __submit_merged_bio(io);
> }
>  #endif
> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> index 65294e3b0bef..2aade367ac66 100644
> --- a/fs/f2fs/f2fs.h
> +++ b/fs/f2fs/f2fs.h
> @@ -1551,6 +1551,8 @@ struct f2fs_sb_info {
>
>  #ifdef CONFIG_BLK_DEV_ZONED
> unsigned int blocks_per_blkz;   /* F2FS blocks per zone */
> +   unsigned int max_active_zones;  /* max zone resources of the 
> zoned device */
> +   atomic_t available_active_zones;/* remaining zone resources 
> for zone switch */
>  #endif
>
> /* for node-related operations */
> diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
> index 206d03c82d96..6711283ff187 100644
> --- a/fs/f2fs/super.c
> +++ b/fs/f2fs/super.c
> @@ -2385,6 +2385,12 @@ static int f2fs_remount(struct super_block *sb, int 
> *flags, char *data)
> if (err)
> goto restore_opts;
>
> +#ifdef CONFIG_BLK_DEV_ZONED
> +   if (sbi->max_active_zones)
> +   atomic_set(>available_active_zones,
> +   sbi->max_active_zones - 
> F2FS_OPTION(sbi).active_logs);
> +#endif
> +
> /* flush outstanding errors before changing fs state */
> flush_work(>s_error_work);
>
> @@ -3932,6 +3938,11 @@ static int init_blkz_info(struct f2fs_sb_info *sbi, 
> int devi)
> if (!f2fs_sb_has_blkzoned(sbi))
> return 0;
>
> +   sbi->max_active_zones = bdev_max_active_zones(bdev);
> +   if (sbi->max_active_zones)
> +   atomic_set(>available_active_zones,
> +   sbi->max_active_zones - 
> F2FS_OPTION(sbi).active_logs);
> +

Need to make available_active_zones not be negative, right?
Hmm, need to make sure active_logs should be equal or less than
max_active_zones.

> zone_sectors = bdev_zone_sectors(bdev);
> if (!is_power_of_2(zone_sectors)) {
> f2fs_err(sbi, "F2FS does not support non power of 2 zone 
> sizes\n");
> --
> 2.34.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 v1] f2fs: fix NULL pointer dereference in f2fs_submit_page_write()

2024-01-16 Thread Daeho Jeong
On Tue, Jan 16, 2024 at 6:13 AM Wenjie Qi  wrote:
>
> BUG: kernel NULL pointer dereference, address: 0014
> RIP: 0010:f2fs_submit_page_write+0x6cf/0x780 [f2fs]
> Call Trace:
> 
> ? show_regs+0x6e/0x80
> ? __die+0x29/0x70
> ? page_fault_oops+0x154/0x4a0
> ? prb_read_valid+0x20/0x30
> ? __irq_work_queue_local+0x39/0xd0
> ? irq_work_queue+0x36/0x70
> ? do_user_addr_fault+0x314/0x6c0
> ? exc_page_fault+0x7d/0x190
> ? asm_exc_page_fault+0x2b/0x30
> ? f2fs_submit_page_write+0x6cf/0x780 [f2fs]
> ? f2fs_submit_page_write+0x736/0x780 [f2fs]
> do_write_page+0x50/0x170 [f2fs]
> f2fs_outplace_write_data+0x61/0xb0 [f2fs]
> f2fs_do_write_data_page+0x3f8/0x660 [f2fs]
> f2fs_write_single_data_page+0x5bb/0x7a0 [f2fs]
> f2fs_write_cache_pages+0x3da/0xbe0 [f2fs]
> ...
> It is possible that other threads have added this fio to io->bio
> and submitted the io->bio before entering f2fs_submit_page_write().
> At this point io->bio = NULL.
> If is_end_zone_blkaddr(sbi, fio->new_blkaddr) of this fio is true,
> then an NULL pointer dereference error occurs at bio_get(io->bio).
> The original code for determining zone end was after "out:",
> which would have missed some fio who is zone end. I've moved
>  this code before "skip:" to make sure it's done for each fio.
>
> Signed-off-by: Wenjie Qi 
> ---
>  fs/f2fs/data.c | 8 
>  1 file changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
> index dce8defdf4c7..4f445906db8b 100644
> --- a/fs/f2fs/data.c
> +++ b/fs/f2fs/data.c
> @@ -1080,10 +1080,6 @@ void f2fs_submit_page_write(struct f2fs_io_info *fio)
> io->last_block_in_bio = fio->new_blkaddr;
>
> trace_f2fs_submit_page_write(fio->page, fio);
> -skip:
> -   if (fio->in_list)
> -   goto next;
> -out:
>  #ifdef CONFIG_BLK_DEV_ZONED
> if (f2fs_sb_has_blkzoned(sbi) && btype < META &&
> is_end_zone_blkaddr(sbi, fio->new_blkaddr)) {
> @@ -1096,6 +1092,10 @@ void f2fs_submit_page_write(struct f2fs_io_info *fio)
> __submit_merged_bio(io);
> }
>  #endif
> +skip:
> +   if (fio->in_list)
> +   goto next;
> +out:

How about moving only the "out" label instead of the whole block from
"skip" to "out"?

> if (is_sbi_flag_set(sbi, SBI_IS_SHUTDOWN) ||
> !f2fs_is_checkpoint_ready(sbi))
> __submit_merged_bio(io);
> --
> 2.34.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 v4 6/6] f2fs: introduce FAULT_BLKADDR_CONSISTENCE

2024-01-12 Thread Daeho Jeong
Reviewed-by: Daeho Jeong 

On Wed, Jan 10, 2024 at 10:43 PM Chao Yu  wrote:
>
> We will encounter below inconsistent status when FAULT_BLKADDR type
> fault injection is on.
>
> Info: checkpoint state = d6 :  nat_bits crc fsck compacted_summary 
> orphan_inodes sudden-power-off
> [ASSERT] (fsck_chk_inode_blk:1254)  --> ino: 0x1c100 has i_blocks: 00c0, 
> but has 191 blocks
> [FIX] (fsck_chk_inode_blk:1260)  --> [0x1c100] i_blocks=0x00c0 -> 0xbf
> [FIX] (fsck_chk_inode_blk:1269)  --> [0x1c100] i_compr_blocks=0x0026 -> 
> 0x27
> [ASSERT] (fsck_chk_inode_blk:1254)  --> ino: 0x1cadb has i_blocks: 002f, 
> but has 46 blocks
> [FIX] (fsck_chk_inode_blk:1260)  --> [0x1cadb] i_blocks=0x002f -> 0x2e
> [FIX] (fsck_chk_inode_blk:1269)  --> [0x1cadb] i_compr_blocks=0x0011 -> 
> 0x12
> [ASSERT] (fsck_chk_inode_blk:1254)  --> ino: 0x1c62c has i_blocks: 0002, 
> but has 1 blocks
> [FIX] (fsck_chk_inode_blk:1260)  --> [0x1c62c] i_blocks=0x0002 -> 0x1
>
> After we inject fault into f2fs_is_valid_blkaddr() during truncation,
> a) it missed to increase @nr_free or @valid_blocks
> b) it can cause in blkaddr leak in truncated dnode
> Which may cause inconsistent status.
>
> This patch separates FAULT_BLKADDR_CONSISTENCE from FAULT_BLKADDR,
> and rename FAULT_BLKADDR to FAULT_BLKADDR_VALIDITY
> so that we can:
> a) use FAULT_BLKADDR_CONSISTENCE in f2fs_truncate_data_blocks_range()
> to simulate inconsistent issue independently, then it can verify fsck
> repair flow.
> b) FAULT_BLKADDR_VALIDITY fault will not cause any inconsistent status,
> we can just use it to check error path handling in kernel side.
>
> Signed-off-by: Chao Yu 
> ---
> v4:
> - rename macro to FAULT_BLKADDR_CONSISTENCE and FAULT_BLKADDR_VALIDITY
> suggested by Jaegeuk.
>  Documentation/ABI/testing/sysfs-fs-f2fs | 47 +
>  Documentation/filesystems/f2fs.rst  | 47 +
>  fs/f2fs/checkpoint.c| 19 +++---
>  fs/f2fs/f2fs.h  |  5 ++-
>  fs/f2fs/file.c  |  8 +++--
>  fs/f2fs/super.c | 37 +--
>  6 files changed, 92 insertions(+), 71 deletions(-)
>
> diff --git a/Documentation/ABI/testing/sysfs-fs-f2fs 
> b/Documentation/ABI/testing/sysfs-fs-f2fs
> index 99fa87a43926..48c135e24eb5 100644
> --- a/Documentation/ABI/testing/sysfs-fs-f2fs
> +++ b/Documentation/ABI/testing/sysfs-fs-f2fs
> @@ -701,29 +701,30 @@ Description:  Support configuring fault injection 
> type, should be
> enabled with fault_injection option, fault type value
> is shown below, it supports single or combined type.
>
> -   ===  ===
> -   Type_NameType_Value
> -   ===  ===
> -   FAULT_KMALLOC0x1
> -   FAULT_KVMALLOC   0x2
> -   FAULT_PAGE_ALLOC 0x4
> -   FAULT_PAGE_GET   0x8
> -   FAULT_ALLOC_BIO  0x00010 (obsolete)
> -   FAULT_ALLOC_NID  0x00020
> -   FAULT_ORPHAN 0x00040
> -   FAULT_BLOCK  0x00080
> -   FAULT_DIR_DEPTH  0x00100
> -   FAULT_EVICT_INODE0x00200
> -   FAULT_TRUNCATE   0x00400
> -   FAULT_READ_IO0x00800
> -   FAULT_CHECKPOINT 0x01000
> -   FAULT_DISCARD0x02000
> -   FAULT_WRITE_IO   0x04000
> -   FAULT_SLAB_ALLOC 0x08000
> -   FAULT_DQUOT_INIT 0x1
> -   FAULT_LOCK_OP0x2
> -   FAULT_BLKADDR0x4
> -   ===  ===
> +   ===  ===
> +   Type_NameType_Value
> +   ===  ===
> +   FAULT_KMALLOC0x1
> +   FAULT_KVMALLOC   0x2
> +   FAULT_PAGE_ALLOC 0x4
> +   FAULT_PAGE_GET   0x8
> +   FAULT_ALLOC_BIO  0x00010 (obsolete)
> +   FAULT_ALLOC_NID  0x00020
> +   FAULT_ORPHAN 0x00040
> +   FAULT_BLOCK  0x00080
&g

Re: [f2fs-dev] [PATCH v4 5/6] f2fs: fix to remove unnecessary f2fs_bug_on() to avoid panic

2024-01-12 Thread Daeho Jeong
Reviewed-by: Daeho Jeong 

On Wed, Jan 10, 2024 at 10:43 PM Chao Yu  wrote:
>
> verify_blkaddr() will trigger panic once we inject fault into
> f2fs_is_valid_blkaddr(), fix to remove this unnecessary f2fs_bug_on().
>
> Fixes: 18792e64c86d ("f2fs: support fault injection for 
> f2fs_is_valid_blkaddr()")
> Signed-off-by: Chao Yu 
> ---
>  fs/f2fs/f2fs.h | 4 +---
>  1 file changed, 1 insertion(+), 3 deletions(-)
>
> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> index 69e71460a950..ab710bb6d8b3 100644
> --- a/fs/f2fs/f2fs.h
> +++ b/fs/f2fs/f2fs.h
> @@ -3470,11 +3470,9 @@ bool f2fs_is_valid_blkaddr(struct f2fs_sb_info *sbi,
>  static inline void verify_blkaddr(struct f2fs_sb_info *sbi,
> block_t blkaddr, int type)
>  {
> -   if (!f2fs_is_valid_blkaddr(sbi, blkaddr, type)) {
> +   if (!f2fs_is_valid_blkaddr(sbi, blkaddr, type))
> f2fs_err(sbi, "invalid blkaddr: %u, type: %d, run fsck to 
> fix.",
>  blkaddr, type);
> -   f2fs_bug_on(sbi, 1);
> -   }
>  }
>
>  static inline bool __is_valid_data_blkaddr(block_t blkaddr)
> --
> 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 v4 4/6] f2fs: compress: fix to avoid inconsistence bewteen i_blocks and dnode

2024-01-12 Thread Daeho Jeong
Reviewed-by: Daeho Jeong 

On Wed, Jan 10, 2024 at 10:43 PM Chao Yu  wrote:
>
> In reserve_compress_blocks(), we update blkaddrs of dnode in prior to
> inc_valid_block_count(), it may cause inconsistent status bewteen
> i_blocks and blkaddrs once inc_valid_block_count() fails.
>
> To fix this issue, it needs to reverse their invoking order.
>
> Fixes: c75488fb4d82 ("f2fs: introduce F2FS_IOC_RESERVE_COMPRESS_BLOCKS")
> Signed-off-by: Chao Yu 
> ---
>  fs/f2fs/data.c|  5 +++--
>  fs/f2fs/f2fs.h|  7 ++-
>  fs/f2fs/file.c| 26 ++
>  fs/f2fs/segment.c |  2 +-
>  4 files changed, 24 insertions(+), 16 deletions(-)
>
> diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
> index b171a9980f6a..8d2ace723310 100644
> --- a/fs/f2fs/data.c
> +++ b/fs/f2fs/data.c
> @@ -1219,7 +1219,8 @@ int f2fs_reserve_new_blocks(struct dnode_of_data *dn, 
> blkcnt_t count)
>
> if (unlikely(is_inode_flag_set(dn->inode, FI_NO_ALLOC)))
> return -EPERM;
> -   if (unlikely((err = inc_valid_block_count(sbi, dn->inode, 
> +   err = inc_valid_block_count(sbi, dn->inode, , true);
> +   if (unlikely(err))
> return err;
>
> trace_f2fs_reserve_new_blocks(dn->inode, dn->nid,
> @@ -1476,7 +1477,7 @@ static int __allocate_data_block(struct dnode_of_data 
> *dn, int seg_type)
>
> dn->data_blkaddr = f2fs_data_blkaddr(dn);
> if (dn->data_blkaddr == NULL_ADDR) {
> -   err = inc_valid_block_count(sbi, dn->inode, );
> +   err = inc_valid_block_count(sbi, dn->inode, , true);
> if (unlikely(err))
> return err;
> }
> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> index 50f3d546ded8..69e71460a950 100644
> --- a/fs/f2fs/f2fs.h
> +++ b/fs/f2fs/f2fs.h
> @@ -2252,7 +2252,7 @@ static inline bool __allow_reserved_blocks(struct 
> f2fs_sb_info *sbi,
>
>  static inline void f2fs_i_blocks_write(struct inode *, block_t, bool, bool);
>  static inline int inc_valid_block_count(struct f2fs_sb_info *sbi,
> -struct inode *inode, blkcnt_t *count)
> +struct inode *inode, blkcnt_t *count, bool 
> partial)
>  {
> blkcnt_t diff = 0, release = 0;
> block_t avail_user_block_count;
> @@ -2292,6 +2292,11 @@ static inline int inc_valid_block_count(struct 
> f2fs_sb_info *sbi,
> avail_user_block_count = 0;
> }
> if (unlikely(sbi->total_valid_block_count > avail_user_block_count)) {
> +   if (!partial) {
> +   spin_unlock(>stat_lock);
> +   goto enospc;
> +   }
> +
> diff = sbi->total_valid_block_count - avail_user_block_count;
> if (diff > *count)
> diff = *count;
> diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
> index 80d9c4c096f0..53c495651789 100644
> --- a/fs/f2fs/file.c
> +++ b/fs/f2fs/file.c
> @@ -3614,14 +3614,16 @@ static int reserve_compress_blocks(struct 
> dnode_of_data *dn, pgoff_t count)
> blkcnt_t reserved;
> int ret;
>
> -   for (i = 0; i < cluster_size; i++, dn->ofs_in_node++) {
> -   blkaddr = f2fs_data_blkaddr(dn);
> +   for (i = 0; i < cluster_size; i++) {
> +   blkaddr = data_blkaddr(dn->inode, dn->node_page,
> +   dn->ofs_in_node + i);
>
> if (i == 0) {
> -   if (blkaddr == COMPRESS_ADDR)
> -   continue;
> -   dn->ofs_in_node += cluster_size;
> -   goto next;
> +   if (blkaddr != COMPRESS_ADDR) {
> +   dn->ofs_in_node += cluster_size;
> +   goto next;
> +   }
> +   continue;
> }
>
> /*
> @@ -3634,20 +3636,20 @@ static int reserve_compress_blocks(struct 
> dnode_of_data *dn, pgoff_t count)
> compr_blocks++;
> continue;
> }
> -
> -   f2fs_set_data_blkaddr(dn, NEW_ADDR);
> }
>
> reserved = cluster_size - compr_blocks;
> if (!reserved)
> goto next;
>
> -  

Re: [f2fs-dev] [PATCH v3 3/6] f2fs: compress: fix to check unreleased compressed cluster

2024-01-12 Thread Daeho Jeong
On Thu, Jan 11, 2024 at 5:06 PM Chao Yu  wrote:
>
> On 2024/1/12 1:15, Daeho Jeong wrote:
> > On Wed, Jan 10, 2024 at 5:33 PM Chao Yu  wrote:
> >>
> >> On 2024/1/11 9:18, Daeho Jeong wrote:
> >>> On Thu, Dec 28, 2023 at 6:33 AM Chao Yu  wrote:
> >>>>
> >>>> From: Sheng Yong 
> >>>>
> >>>> Compressed cluster may not be released due to we can fail in
> >>>> release_compress_blocks(), fix to handle reserved compressed
> >>>> cluster correctly in reserve_compress_blocks().
> >>>>
> >>>> Fixes: 4c8ff7095bef ("f2fs: support data compression")
> >>>> Signed-off-by: Sheng Yong 
> >>>> Signed-off-by: Chao Yu 
> >>>> ---
> >>>>fs/f2fs/file.c | 12 
> >>>>1 file changed, 12 insertions(+)
> >>>>
> >>>> diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
> >>>> index 026d05a7edd8..782ae3be48f6 100644
> >>>> --- a/fs/f2fs/file.c
> >>>> +++ b/fs/f2fs/file.c
> >>>> @@ -3624,6 +3624,15 @@ static int reserve_compress_blocks(struct 
> >>>> dnode_of_data *dn, pgoff_t count)
> >>>>   goto next;
> >>>>   }
> >>>>
> >>>> +   /*
> >>>> +* compressed cluster was not released due to
> >>>> +* it fails in release_compress_blocks().
> >>>> +*/
> >>>> +   if (blkaddr == NEW_ADDR) {
> >>>> +   compr_blocks++;
> >>>> +   continue;
> >>>> +   }
> >>>> +
> >>>>   if (__is_valid_data_blkaddr(blkaddr)) {
> >>>>   compr_blocks++;
> >>>>   continue;
> >>>
> >>> How about merging two conditions like "blkaddr == NEW_ADDR ||
> >>> __is_valid_data_blkaddr(blkaddr)"?
> >>
> >> Oh, sure.
> >>
> >>>
> >>>> @@ -3633,6 +3642,9 @@ static int reserve_compress_blocks(struct 
> >>>> dnode_of_data *dn, pgoff_t count)
> >>>>   }
> >>>>
> >>>>   reserved = cluster_size - compr_blocks;
> >>>> +   if (!reserved)
> >>>> +   goto next;
> >>>> +
> >>>
> >>> How can the reserved variable be zero?
> >>
> >> I guess it can happen if a cluster was not released during
> >> release_compress_blocks(), then all blocks in the cluster should
> >> has been reserved, so, in this round of reserving, it needs to skip
> >> reserve blocks, right?
> >
> > Let's assume cluster_size is 4. How can compr_blocks be 4?
> >
> >  if (i == 0) {
> >  if (blkaddr == COMPRESS_ADDR)
> >  continue;
> >  dn->ofs_in_node += cluster_size;
> >  goto next;
> >  }
> >
> > We skip the block having COMPRESS_ADDR when counting compr_blocks.
> > So, the maximum value of compr_blocks should be 3, right?
>
> Ah, got it, and I think you're right.
>
> Should fix the condition as below?
>
> /* for the case all blocks in cluster were reserved */
> if (reserved == 1)
> goto next;

It looks good to me.

>
> Thanks,
>
> >
> >>
> >> Thanks,
> >>
> >>>
> >>>>   ret = inc_valid_block_count(sbi, dn->inode, );
> >>>>   if (ret)
> >>>>   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


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


Re: [f2fs-dev] [PATCH v3 1/6] f2fs: compress: fix to guarantee persisting compressed blocks by CP

2024-01-12 Thread Daeho Jeong
Reviewed-by: Daeho Jeong 

On Thu, Jan 11, 2024 at 9:17 AM Daeho Jeong  wrote:
>
> On Wed, Jan 10, 2024 at 5:26 PM Chao Yu  wrote:
> >
> > On 2024/1/11 8:55, Daeho Jeong wrote:
> > > On Thu, Dec 28, 2023 at 6:33 AM Chao Yu  wrote:
> > >>
> > >> If data block in compressed cluster is not persisted with metadata
> > >> during checkpoint, after SPOR, the data may be corrupted, let's
> > >> guarantee to write compressed page by checkpoint.
> > >>
> > >> Fixes: 4c8ff7095bef ("f2fs: support data compression")
> > >> Signed-off-by: Chao Yu 
> > >> ---
> > >> v3:
> > >> - treat compressed page as CP guaranteed data explictly.
> > >>   fs/f2fs/compress.c |  4 +++-
> > >>   fs/f2fs/data.c | 17 +
> > >>   fs/f2fs/f2fs.h |  4 +++-
> > >>   3 files changed, 15 insertions(+), 10 deletions(-)
> > >>
> > >> diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c
> > >> index c5a4364c4482..9940b7886e5d 100644
> > >> --- a/fs/f2fs/compress.c
> > >> +++ b/fs/f2fs/compress.c
> > >> @@ -1418,6 +1418,8 @@ void f2fs_compress_write_end_io(struct bio *bio, 
> > >> struct page *page)
> > >>  struct f2fs_sb_info *sbi = bio->bi_private;
> > >>  struct compress_io_ctx *cic =
> > >>  (struct compress_io_ctx *)page_private(page);
> > >> +   enum count_type type = WB_DATA_TYPE(page,
> > >> +   f2fs_is_compressed_page(page));
> > >>  int i;
> > >>
> > >>  if (unlikely(bio->bi_status))
> > >> @@ -1425,7 +1427,7 @@ void f2fs_compress_write_end_io(struct bio *bio, 
> > >> struct page *page)
> > >>
> > >>  f2fs_compress_free_page(page);
> > >>
> > >> -   dec_page_count(sbi, F2FS_WB_DATA);
> > >> +   dec_page_count(sbi, type);
> > >>
> > >>  if (atomic_dec_return(>pending_pages))
> > >>  return;
> > >> diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
> > >> index dce8defdf4c7..81f9e2cc49e2 100644
> > >> --- a/fs/f2fs/data.c
> > >> +++ b/fs/f2fs/data.c
> > >> @@ -48,7 +48,7 @@ void f2fs_destroy_bioset(void)
> > >>  bioset_exit(_bioset);
> > >>   }
> > >>
> > >> -static bool __is_cp_guaranteed(struct page *page)
> > >> +bool f2fs_is_cp_guaranteed(struct page *page)
> > >>   {
> > >>  struct address_space *mapping = page->mapping;
> > >>  struct inode *inode;
> > >> @@ -65,8 +65,6 @@ static bool __is_cp_guaranteed(struct page *page)
> > >>  S_ISDIR(inode->i_mode))
> > >>  return true;
> > >>
> > >> -   if (f2fs_is_compressed_page(page))
> > >> -   return false;
> > >
> > > Out of curiosity, why don't we simply change the above to "return true"?
> >
> > Daeho,
> >
> > I used the implementation, please check v1 and related comments
> > from Jaegeuk and me, let me know if that was not clear enough. :)
> >
> > https://lore.kernel.org/linux-f2fs-devel/aae654e7-8a7e-478d-9f5a-65807a0e0...@kernel.org/
>
> Oh, I missed it. Sorry~
>
> >
> > >
> > >>  if ((S_ISREG(inode->i_mode) && IS_NOQUOTA(inode)) ||
> > >>  page_private_gcing(page))
> > >>  return true;
> > >> @@ -338,7 +336,7 @@ static void f2fs_write_end_io(struct bio *bio)
> > >>
> > >>  bio_for_each_segment_all(bvec, bio, iter_all) {
> > >>  struct page *page = bvec->bv_page;
> > >> -   enum count_type type = WB_DATA_TYPE(page);
> > >> +   enum count_type type = WB_DATA_TYPE(page, false);
> > >>
> > >>  if (page_private_dummy(page)) {
> > >>  clear_page_private_dummy(page);
> > >> @@ -762,7 +760,7 @@ int f2fs_submit_page_bio(struct f2fs_io_info *fio)
> > >>  wbc_account_cgroup_owner(fio->io_wbc, fio->page, 
> > >> PAGE_SIZE);
> > >>
> > >>  inc_page_count(fio->sbi, is_read_io(fio->op) ?
> > >> -   __read_io_type(page) : WB_DATA

Re: [f2fs-dev] [PATCH v4 2/6] f2fs: compress: fix to cover normal cluster write with cp_rwsem

2024-01-12 Thread Daeho Jeong
Reviewed-by: Daeho Jeong 

On Wed, Jan 10, 2024 at 10:43 PM Chao Yu  wrote:
>
> When we overwrite compressed cluster w/ normal cluster, we should
> not unlock cp_rwsem during f2fs_write_raw_pages(), otherwise data
> will be corrupted if partial blocks were persisted before CP & SPOR,
> due to cluster metadata wasn't updated atomically.
>
> Fixes: 4c8ff7095bef ("f2fs: support data compression")
> Signed-off-by: Chao Yu 
> ---
>  fs/f2fs/compress.c | 20 ++--
>  fs/f2fs/data.c |  3 ++-
>  2 files changed, 16 insertions(+), 7 deletions(-)
>
> diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c
> index 9940b7886e5d..bf4cfab67aec 100644
> --- a/fs/f2fs/compress.c
> +++ b/fs/f2fs/compress.c
> @@ -1448,7 +1448,8 @@ static int f2fs_write_raw_pages(struct compress_ctx *cc,
> enum iostat_type io_type)
>  {
> struct address_space *mapping = cc->inode->i_mapping;
> -   int _submitted, compr_blocks, ret, i;
> +   struct f2fs_sb_info *sbi = F2FS_M_SB(mapping);
> +   int _submitted, compr_blocks, ret = 0, i;
>
> compr_blocks = f2fs_compressed_blocks(cc);
>
> @@ -1463,6 +1464,10 @@ static int f2fs_write_raw_pages(struct compress_ctx 
> *cc,
> if (compr_blocks < 0)
> return compr_blocks;
>
> +   /* overwrite compressed cluster w/ normal cluster */
> +   if (compr_blocks > 0)
> +   f2fs_lock_op(sbi);
> +
> for (i = 0; i < cc->cluster_size; i++) {
> if (!cc->rpages[i])
> continue;
> @@ -1495,26 +1500,29 @@ static int f2fs_write_raw_pages(struct compress_ctx 
> *cc,
> unlock_page(cc->rpages[i]);
> ret = 0;
> } else if (ret == -EAGAIN) {
> +   ret = 0;
> /*
>  * for quota file, just redirty left pages to
>  * avoid deadlock caused by cluster update 
> race
>  * from foreground operation.
>  */
> if (IS_NOQUOTA(cc->inode))
> -   return 0;
> -   ret = 0;
> +   goto out;
> f2fs_io_schedule_timeout(DEFAULT_IO_TIMEOUT);
> goto retry_write;
> }
> -   return ret;
> +   goto out;
> }
>
> *submitted += _submitted;
> }
>
> -   f2fs_balance_fs(F2FS_M_SB(mapping), true);
> +out:
> +   if (compr_blocks > 0)
> +   f2fs_unlock_op(sbi);
>
> -   return 0;
> +   f2fs_balance_fs(sbi, true);
> +   return ret;
>  }
>
>  int f2fs_write_multi_pages(struct compress_ctx *cc,
> diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
> index 81f9e2cc49e2..b171a9980f6a 100644
> --- a/fs/f2fs/data.c
> +++ b/fs/f2fs/data.c
> @@ -2839,7 +2839,7 @@ int f2fs_write_single_data_page(struct page *page, int 
> *submitted,
> .encrypted_page = NULL,
> .submitted = 0,
> .compr_blocks = compr_blocks,
> -   .need_lock = LOCK_RETRY,
> +   .need_lock = compr_blocks ? LOCK_DONE : LOCK_RETRY,
> .post_read = f2fs_post_read_required(inode) ? 1 : 0,
> .io_type = io_type,
> .io_wbc = wbc,
> @@ -2920,6 +2920,7 @@ int f2fs_write_single_data_page(struct page *page, int 
> *submitted,
> if (err == -EAGAIN) {
> err = f2fs_do_write_data_page();
> if (err == -EAGAIN) {
> +   f2fs_bug_on(sbi, compr_blocks);
> fio.need_lock = LOCK_REQ;
> err = f2fs_do_write_data_page();
> }
> --
> 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 v3 1/6] f2fs: compress: fix to guarantee persisting compressed blocks by CP

2024-01-11 Thread Daeho Jeong
On Wed, Jan 10, 2024 at 5:26 PM Chao Yu  wrote:
>
> On 2024/1/11 8:55, Daeho Jeong wrote:
> > On Thu, Dec 28, 2023 at 6:33 AM Chao Yu  wrote:
> >>
> >> If data block in compressed cluster is not persisted with metadata
> >> during checkpoint, after SPOR, the data may be corrupted, let's
> >> guarantee to write compressed page by checkpoint.
> >>
> >> Fixes: 4c8ff7095bef ("f2fs: support data compression")
> >> Signed-off-by: Chao Yu 
> >> ---
> >> v3:
> >> - treat compressed page as CP guaranteed data explictly.
> >>   fs/f2fs/compress.c |  4 +++-
> >>   fs/f2fs/data.c | 17 +
> >>   fs/f2fs/f2fs.h |  4 +++-
> >>   3 files changed, 15 insertions(+), 10 deletions(-)
> >>
> >> diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c
> >> index c5a4364c4482..9940b7886e5d 100644
> >> --- a/fs/f2fs/compress.c
> >> +++ b/fs/f2fs/compress.c
> >> @@ -1418,6 +1418,8 @@ void f2fs_compress_write_end_io(struct bio *bio, 
> >> struct page *page)
> >>  struct f2fs_sb_info *sbi = bio->bi_private;
> >>  struct compress_io_ctx *cic =
> >>  (struct compress_io_ctx *)page_private(page);
> >> +   enum count_type type = WB_DATA_TYPE(page,
> >> +   f2fs_is_compressed_page(page));
> >>  int i;
> >>
> >>  if (unlikely(bio->bi_status))
> >> @@ -1425,7 +1427,7 @@ void f2fs_compress_write_end_io(struct bio *bio, 
> >> struct page *page)
> >>
> >>  f2fs_compress_free_page(page);
> >>
> >> -   dec_page_count(sbi, F2FS_WB_DATA);
> >> +   dec_page_count(sbi, type);
> >>
> >>  if (atomic_dec_return(>pending_pages))
> >>  return;
> >> diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
> >> index dce8defdf4c7..81f9e2cc49e2 100644
> >> --- a/fs/f2fs/data.c
> >> +++ b/fs/f2fs/data.c
> >> @@ -48,7 +48,7 @@ void f2fs_destroy_bioset(void)
> >>  bioset_exit(_bioset);
> >>   }
> >>
> >> -static bool __is_cp_guaranteed(struct page *page)
> >> +bool f2fs_is_cp_guaranteed(struct page *page)
> >>   {
> >>  struct address_space *mapping = page->mapping;
> >>  struct inode *inode;
> >> @@ -65,8 +65,6 @@ static bool __is_cp_guaranteed(struct page *page)
> >>  S_ISDIR(inode->i_mode))
> >>  return true;
> >>
> >> -   if (f2fs_is_compressed_page(page))
> >> -   return false;
> >
> > Out of curiosity, why don't we simply change the above to "return true"?
>
> Daeho,
>
> I used the implementation, please check v1 and related comments
> from Jaegeuk and me, let me know if that was not clear enough. :)
>
> https://lore.kernel.org/linux-f2fs-devel/aae654e7-8a7e-478d-9f5a-65807a0e0...@kernel.org/

Oh, I missed it. Sorry~

>
> >
> >>  if ((S_ISREG(inode->i_mode) && IS_NOQUOTA(inode)) ||
> >>  page_private_gcing(page))
> >>  return true;
> >> @@ -338,7 +336,7 @@ static void f2fs_write_end_io(struct bio *bio)
> >>
> >>  bio_for_each_segment_all(bvec, bio, iter_all) {
> >>  struct page *page = bvec->bv_page;
> >> -   enum count_type type = WB_DATA_TYPE(page);
> >> +   enum count_type type = WB_DATA_TYPE(page, false);
> >>
> >>  if (page_private_dummy(page)) {
> >>  clear_page_private_dummy(page);
> >> @@ -762,7 +760,7 @@ int f2fs_submit_page_bio(struct f2fs_io_info *fio)
> >>  wbc_account_cgroup_owner(fio->io_wbc, fio->page, 
> >> PAGE_SIZE);
> >>
> >>  inc_page_count(fio->sbi, is_read_io(fio->op) ?
> >> -   __read_io_type(page) : WB_DATA_TYPE(fio->page));
> >> +   __read_io_type(page) : WB_DATA_TYPE(fio->page, 
> >> false));
> >>
> >>  if (is_read_io(bio_op(bio)))
> >>  f2fs_submit_read_bio(fio->sbi, bio, fio->type);
> >> @@ -973,7 +971,7 @@ int f2fs_merge_page_bio(struct f2fs_io_info *fio)
> >>  if (fio->io_wbc)
> >>  wbc_account_cgroup_owner(fio->io_wbc, fio->page, 
> >> PAGE_SIZE);
> >>

Re: [f2fs-dev] [PATCH v3 3/6] f2fs: compress: fix to check unreleased compressed cluster

2024-01-11 Thread Daeho Jeong
On Wed, Jan 10, 2024 at 5:33 PM Chao Yu  wrote:
>
> On 2024/1/11 9:18, Daeho Jeong wrote:
> > On Thu, Dec 28, 2023 at 6:33 AM Chao Yu  wrote:
> >>
> >> From: Sheng Yong 
> >>
> >> Compressed cluster may not be released due to we can fail in
> >> release_compress_blocks(), fix to handle reserved compressed
> >> cluster correctly in reserve_compress_blocks().
> >>
> >> Fixes: 4c8ff7095bef ("f2fs: support data compression")
> >> Signed-off-by: Sheng Yong 
> >> Signed-off-by: Chao Yu 
> >> ---
> >>   fs/f2fs/file.c | 12 
> >>   1 file changed, 12 insertions(+)
> >>
> >> diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
> >> index 026d05a7edd8..782ae3be48f6 100644
> >> --- a/fs/f2fs/file.c
> >> +++ b/fs/f2fs/file.c
> >> @@ -3624,6 +3624,15 @@ static int reserve_compress_blocks(struct 
> >> dnode_of_data *dn, pgoff_t count)
> >>  goto next;
> >>  }
> >>
> >> +   /*
> >> +* compressed cluster was not released due to
> >> +* it fails in release_compress_blocks().
> >> +*/
> >> +   if (blkaddr == NEW_ADDR) {
> >> +   compr_blocks++;
> >> +   continue;
> >> +   }
> >> +
> >>  if (__is_valid_data_blkaddr(blkaddr)) {
> >>  compr_blocks++;
> >>  continue;
> >
> > How about merging two conditions like "blkaddr == NEW_ADDR ||
> > __is_valid_data_blkaddr(blkaddr)"?
>
> Oh, sure.
>
> >
> >> @@ -3633,6 +3642,9 @@ static int reserve_compress_blocks(struct 
> >> dnode_of_data *dn, pgoff_t count)
> >>  }
> >>
> >>  reserved = cluster_size - compr_blocks;
> >> +   if (!reserved)
> >> +   goto next;
> >> +
> >
> > How can the reserved variable be zero?
>
> I guess it can happen if a cluster was not released during
> release_compress_blocks(), then all blocks in the cluster should
> has been reserved, so, in this round of reserving, it needs to skip
> reserve blocks, right?

Let's assume cluster_size is 4. How can compr_blocks be 4?

if (i == 0) {
if (blkaddr == COMPRESS_ADDR)
continue;
dn->ofs_in_node += cluster_size;
goto next;
}

We skip the block having COMPRESS_ADDR when counting compr_blocks.
So, the maximum value of compr_blocks should be 3, right?

>
> Thanks,
>
> >
> >>  ret = inc_valid_block_count(sbi, dn->inode, );
> >>  if (ret)
> >>  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


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


Re: [f2fs-dev] [PATCH v3 3/6] f2fs: compress: fix to check unreleased compressed cluster

2024-01-10 Thread Daeho Jeong
On Thu, Dec 28, 2023 at 6:33 AM Chao Yu  wrote:
>
> From: Sheng Yong 
>
> Compressed cluster may not be released due to we can fail in
> release_compress_blocks(), fix to handle reserved compressed
> cluster correctly in reserve_compress_blocks().
>
> Fixes: 4c8ff7095bef ("f2fs: support data compression")
> Signed-off-by: Sheng Yong 
> Signed-off-by: Chao Yu 
> ---
>  fs/f2fs/file.c | 12 
>  1 file changed, 12 insertions(+)
>
> diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
> index 026d05a7edd8..782ae3be48f6 100644
> --- a/fs/f2fs/file.c
> +++ b/fs/f2fs/file.c
> @@ -3624,6 +3624,15 @@ static int reserve_compress_blocks(struct 
> dnode_of_data *dn, pgoff_t count)
> goto next;
> }
>
> +   /*
> +* compressed cluster was not released due to
> +* it fails in release_compress_blocks().
> +*/
> +   if (blkaddr == NEW_ADDR) {
> +   compr_blocks++;
> +   continue;
> +   }
> +
> if (__is_valid_data_blkaddr(blkaddr)) {
> compr_blocks++;
> continue;

How about merging two conditions like "blkaddr == NEW_ADDR ||
__is_valid_data_blkaddr(blkaddr)"?

> @@ -3633,6 +3642,9 @@ static int reserve_compress_blocks(struct dnode_of_data 
> *dn, pgoff_t count)
> }
>
> reserved = cluster_size - compr_blocks;
> +   if (!reserved)
> +   goto next;
> +

How can the reserved variable be zero?

> ret = inc_valid_block_count(sbi, dn->inode, );
> if (ret)
> 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


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


Re: [f2fs-dev] [PATCH v3 1/6] f2fs: compress: fix to guarantee persisting compressed blocks by CP

2024-01-10 Thread Daeho Jeong
On Thu, Dec 28, 2023 at 6:33 AM Chao Yu  wrote:
>
> If data block in compressed cluster is not persisted with metadata
> during checkpoint, after SPOR, the data may be corrupted, let's
> guarantee to write compressed page by checkpoint.
>
> Fixes: 4c8ff7095bef ("f2fs: support data compression")
> Signed-off-by: Chao Yu 
> ---
> v3:
> - treat compressed page as CP guaranteed data explictly.
>  fs/f2fs/compress.c |  4 +++-
>  fs/f2fs/data.c | 17 +
>  fs/f2fs/f2fs.h |  4 +++-
>  3 files changed, 15 insertions(+), 10 deletions(-)
>
> diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c
> index c5a4364c4482..9940b7886e5d 100644
> --- a/fs/f2fs/compress.c
> +++ b/fs/f2fs/compress.c
> @@ -1418,6 +1418,8 @@ void f2fs_compress_write_end_io(struct bio *bio, struct 
> page *page)
> struct f2fs_sb_info *sbi = bio->bi_private;
> struct compress_io_ctx *cic =
> (struct compress_io_ctx *)page_private(page);
> +   enum count_type type = WB_DATA_TYPE(page,
> +   f2fs_is_compressed_page(page));
> int i;
>
> if (unlikely(bio->bi_status))
> @@ -1425,7 +1427,7 @@ void f2fs_compress_write_end_io(struct bio *bio, struct 
> page *page)
>
> f2fs_compress_free_page(page);
>
> -   dec_page_count(sbi, F2FS_WB_DATA);
> +   dec_page_count(sbi, type);
>
> if (atomic_dec_return(>pending_pages))
> return;
> diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
> index dce8defdf4c7..81f9e2cc49e2 100644
> --- a/fs/f2fs/data.c
> +++ b/fs/f2fs/data.c
> @@ -48,7 +48,7 @@ void f2fs_destroy_bioset(void)
> bioset_exit(_bioset);
>  }
>
> -static bool __is_cp_guaranteed(struct page *page)
> +bool f2fs_is_cp_guaranteed(struct page *page)
>  {
> struct address_space *mapping = page->mapping;
> struct inode *inode;
> @@ -65,8 +65,6 @@ static bool __is_cp_guaranteed(struct page *page)
> S_ISDIR(inode->i_mode))
> return true;
>
> -   if (f2fs_is_compressed_page(page))
> -   return false;

Out of curiosity, why don't we simply change the above to "return true"?

> if ((S_ISREG(inode->i_mode) && IS_NOQUOTA(inode)) ||
> page_private_gcing(page))
> return true;
> @@ -338,7 +336,7 @@ static void f2fs_write_end_io(struct bio *bio)
>
> bio_for_each_segment_all(bvec, bio, iter_all) {
> struct page *page = bvec->bv_page;
> -   enum count_type type = WB_DATA_TYPE(page);
> +   enum count_type type = WB_DATA_TYPE(page, false);
>
> if (page_private_dummy(page)) {
> clear_page_private_dummy(page);
> @@ -762,7 +760,7 @@ int f2fs_submit_page_bio(struct f2fs_io_info *fio)
> wbc_account_cgroup_owner(fio->io_wbc, fio->page, PAGE_SIZE);
>
> inc_page_count(fio->sbi, is_read_io(fio->op) ?
> -   __read_io_type(page) : WB_DATA_TYPE(fio->page));
> +   __read_io_type(page) : WB_DATA_TYPE(fio->page, 
> false));
>
> if (is_read_io(bio_op(bio)))
> f2fs_submit_read_bio(fio->sbi, bio, fio->type);
> @@ -973,7 +971,7 @@ int f2fs_merge_page_bio(struct f2fs_io_info *fio)
> if (fio->io_wbc)
> wbc_account_cgroup_owner(fio->io_wbc, fio->page, PAGE_SIZE);
>
> -   inc_page_count(fio->sbi, WB_DATA_TYPE(page));
> +   inc_page_count(fio->sbi, WB_DATA_TYPE(page, false));
>
> *fio->last_block = fio->new_blkaddr;
> *fio->bio = bio;
> @@ -1007,6 +1005,7 @@ void f2fs_submit_page_write(struct f2fs_io_info *fio)
> enum page_type btype = PAGE_TYPE_OF_BIO(fio->type);
> struct f2fs_bio_info *io = sbi->write_io[btype] + fio->temp;
> struct page *bio_page;
> +   enum count_type type;
>
> f2fs_bug_on(sbi, is_read_io(fio->op));
>
> @@ -1046,7 +1045,8 @@ void f2fs_submit_page_write(struct f2fs_io_info *fio)
> /* set submitted = true as a return value */
> fio->submitted = 1;
>
> -   inc_page_count(sbi, WB_DATA_TYPE(bio_page));
> +   type = WB_DATA_TYPE(bio_page, fio->compressed_page);
> +   inc_page_count(sbi, type);
>
> if (io->bio &&
> (!io_is_mergeable(sbi, io->bio, io, fio, io->last_block_in_bio,
> @@ -1059,7 +1059,8 @@ void f2fs_submit_page_write(struct f2fs_io_info *fio)
> if (F2FS_IO_ALIGNED(sbi) &&
> (fio->type == DATA || fio->type == NODE) &&
> fio->new_blkaddr & F2FS_IO_SIZE_MASK(sbi)) {
> -   dec_page_count(sbi, WB_DATA_TYPE(bio_page));
> +   dec_page_count(sbi, WB_DATA_TYPE(bio_page,
> +   fio->compressed_page));
> fio->retry = 1;
> goto skip;
> }
> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> index 

Re: [f2fs-dev] [PATCH 2/4] f2fs: fix write pointers on zoned device after roll forward

2023-12-04 Thread Daeho Jeong
LGTM

On Mon, Dec 4, 2023 at 10:06 AM Jaegeuk Kim  wrote:
>
> 1. do roll forward recovery
> 2. update current segments pointers
> 3. fix the entire zones' write pointers
> 4. do checkpoint
>
> Signed-off-by: Jaegeuk Kim 
> ---
>  fs/f2fs/recovery.c | 2 ++
>  1 file changed, 2 insertions(+)
>
> diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c
> index 16415c770b45..d0f24ccbd1ac 100644
> --- a/fs/f2fs/recovery.c
> +++ b/fs/f2fs/recovery.c
> @@ -917,6 +917,8 @@ int f2fs_recover_fsync_data(struct f2fs_sb_info *sbi, 
> bool check_only)
> if (!err && fix_curseg_write_pointer && !f2fs_readonly(sbi->sb) &&
> f2fs_sb_has_blkzoned(sbi)) {
> err = f2fs_fix_curseg_write_pointer(sbi);
> +   if (!err)
> +   err = f2fs_check_write_pointer(sbi);
> ret = err;
> }
>
> --
> 2.43.0.rc2.451.g8631bc7472-goog
>
>
>
> ___
> 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] f2fs-tools: skip finishing zones for current zones

2023-12-04 Thread Daeho Jeong
From: Daeho Jeong 

Do not finishing zones for current zones.

Signed-off-by: Daeho Jeong 
Fixes: 06a25b021d15 ("f2fs-tools: make six open zone check resilient")
---
 fsck/fsck.c | 12 +++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/fsck/fsck.c b/fsck/fsck.c
index 8acb822..5121a56 100644
--- a/fsck/fsck.c
+++ b/fsck/fsck.c
@@ -3265,8 +3265,9 @@ static int chk_and_fix_wp_with_sit(int UNUSED(i), void 
*blkzone, void *opaque)
struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
block_t zone_block, wp_block, wp_blkoff;
unsigned int zone_segno, wp_segno;
-   int ret, last_valid_blkoff;
+   int i, ret, last_valid_blkoff;
int log_sectors_per_block = sbi->log_blocksize - SECTOR_SHIFT;
+   unsigned int segs_per_zone = sbi->segs_per_sec * sbi->secs_per_zone;
 
if (blk_zone_conv(blkz))
return 0;
@@ -3309,6 +3310,15 @@ static int chk_and_fix_wp_with_sit(int UNUSED(i), void 
*blkzone, void *opaque)
return 0;
}
 
+   /* if a curseg points to the zone, do not finishing zone */
+   for (i = 0; i < NO_CHECK_TYPE; i++) {
+   struct curseg_info *cs = CURSEG_I(sbi, i);
+
+   if (zone_segno <= cs->segno &&
+   cs->segno < zone_segno + segs_per_zone)
+   return 0;
+   }
+
/*
 * If valid blocks exist in the zone beyond the write pointer, it
 * is a bug. No need to fix because the zone is not selected for the
-- 
2.43.0.rc2.451.g8631bc7472-goog



___
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/4] f2fs: check write pointers when checkpoint=disable

2023-12-04 Thread Daeho Jeong
LGTM

On Mon, Dec 4, 2023 at 10:06 AM Jaegeuk Kim  wrote:
>
> Even if f2fs was rebooted as staying checkpoint=disable, let's match the write
> pointers all the time.
>
> Signed-off-by: Jaegeuk Kim 
> ---
>  fs/f2fs/super.c | 3 +--
>  1 file changed, 1 insertion(+), 2 deletions(-)
>
> diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
> index 617340e9ea7f..9a874b4d1501 100644
> --- a/fs/f2fs/super.c
> +++ b/fs/f2fs/super.c
> @@ -4741,7 +4741,7 @@ static int f2fs_fill_super(struct super_block *sb, void 
> *data, int silent)
>  #ifdef CONFIG_QUOTA
> f2fs_recover_quota_end(sbi, quota_enabled);
>  #endif
> -
> +reset_checkpoint:
> /*
>  * If the f2fs is not readonly and fsync data recovery succeeds,
>  * check zoned block devices' write pointer consistency.
> @@ -4752,7 +4752,6 @@ static int f2fs_fill_super(struct super_block *sb, void 
> *data, int silent)
> goto free_meta;
> }
>
> -reset_checkpoint:
> f2fs_init_inmem_curseg(sbi);
>
> /* f2fs_recover_fsync_data() cleared this already */
> --
> 2.43.0.rc2.451.g8631bc7472-goog
>
>
>
> ___
> 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] fsck.f2fs: run full scan if checkpoint is disabled

2023-12-04 Thread Daeho Jeong
LGTM

On Mon, Dec 4, 2023 at 10:07 AM Jaegeuk Kim  wrote:
>
> Let's fix any inconsistency until checkpint being enabled back.
>
> Signed-off-by: Jaegeuk Kim 
> ---
>  fsck/mount.c | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/fsck/mount.c b/fsck/mount.c
> index e957904494ef..30c62280b281 100644
> --- a/fsck/mount.c
> +++ b/fsck/mount.c
> @@ -1435,6 +1435,7 @@ static int f2fs_should_proceed(struct f2fs_super_block 
> *sb, u32 flag)
>  {
> if (!c.fix_on && (c.auto_fix || c.preen_mode)) {
> if (flag & CP_FSCK_FLAG ||
> +   flag & CP_DISABLED_FLAG ||
> flag & CP_QUOTA_NEED_FSCK_FLAG ||
> c.abnormal_stop || c.fs_errors ||
> (exist_qf_ino(sb) && (flag & CP_ERROR_FLAG))) {
> --
> 2.43.0.rc2.451.g8631bc7472-goog
>
>
>
> ___
> 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 4/4] f2fs: let's finish or reset zones all the time

2023-12-04 Thread Daeho Jeong
LGTM

On Mon, Dec 4, 2023 at 10:07 AM Jaegeuk Kim  wrote:
>
> In order to limit # of open zones, let's finish or reset zones given # of
> valid blocks per section and its zone condition.
>
> Signed-off-by: Jaegeuk Kim 
> ---
>  fs/f2fs/segment.c | 74 +++
>  1 file changed, 17 insertions(+), 57 deletions(-)
>
> diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
> index 9081c9af977a..5696a4d381ff 100644
> --- a/fs/f2fs/segment.c
> +++ b/fs/f2fs/segment.c
> @@ -4870,82 +4870,44 @@ static int check_zone_write_pointer(struct 
> f2fs_sb_info *sbi,
> struct f2fs_dev_info *fdev,
> struct blk_zone *zone)
>  {
> -   unsigned int wp_segno, wp_blkoff, zone_secno, zone_segno, segno;
> -   block_t zone_block, wp_block, last_valid_block;
> +   unsigned int zone_segno;
> +   block_t zone_block, wp_block, valid_block_cnt;
> unsigned int log_sectors_per_block = sbi->log_blocksize - 
> SECTOR_SHIFT;
> -   int i, s, b, ret;
> -   struct seg_entry *se;
> +   int ret;
>
> if (zone->type != BLK_ZONE_TYPE_SEQWRITE_REQ)
> return 0;
>
> wp_block = fdev->start_blk + (zone->wp >> log_sectors_per_block);
> -   wp_segno = GET_SEGNO(sbi, wp_block);
> -   wp_blkoff = wp_block - START_BLOCK(sbi, wp_segno);
> zone_block = fdev->start_blk + (zone->start >> log_sectors_per_block);
> zone_segno = GET_SEGNO(sbi, zone_block);
> -   zone_secno = GET_SEC_FROM_SEG(sbi, zone_segno);
> -
> -   if (zone_segno >= MAIN_SEGS(sbi))
> -   return 0;
>
> /*
>  * Skip check of zones cursegs point to, since
>  * fix_curseg_write_pointer() checks them.
>  */
> -   for (i = 0; i < NO_CHECK_TYPE; i++)
> -   if (zone_secno == GET_SEC_FROM_SEG(sbi,
> -  CURSEG_I(sbi, i)->segno))
> -   return 0;
> +   if (zone_segno >= MAIN_SEGS(sbi) ||
> +   IS_CURSEC(sbi, GET_SEC_FROM_SEG(sbi, zone_segno)))
> +   return 0;
>
> /*
> -* Get last valid block of the zone.
> +* Get # of valid block of the zone.
>  */
> -   last_valid_block = zone_block - 1;
> -   for (s = sbi->segs_per_sec - 1; s >= 0; s--) {
> -   segno = zone_segno + s;
> -   se = get_seg_entry(sbi, segno);
> -   for (b = sbi->blocks_per_seg - 1; b >= 0; b--)
> -   if (f2fs_test_bit(b, se->cur_valid_map)) {
> -   last_valid_block = START_BLOCK(sbi, segno) + 
> b;
> -   break;
> -   }
> -   if (last_valid_block >= zone_block)
> -   break;
> -   }
> +   valid_block_cnt = get_valid_blocks(sbi, zone_segno, true);
>
> -   /*
> -* When safely unmounted in the previous mount, we can trust write
> -* pointers. Otherwise, finish zones.
> -*/
> -   if (is_set_ckpt_flags(sbi, CP_UMOUNT_FLAG)) {
> -   /*
> -* The write pointer matches with the valid blocks or
> -* already points to the end of the zone.
> -*/
> -   if ((last_valid_block + 1 == wp_block) ||
> -   (zone->wp == zone->start + zone->len))
> -   return 0;
> -   }
> +   if ((!valid_block_cnt && zone->cond == BLK_ZONE_COND_EMPTY) ||
> +   (valid_block_cnt && zone->cond == BLK_ZONE_COND_FULL))
> +   return 0;
>
> -   if (last_valid_block + 1 == zone_block) {
> -   if (is_set_ckpt_flags(sbi, CP_UMOUNT_FLAG)) {
> -   /*
> -* If there is no valid block in the zone and if write
> -* pointer is not at zone start, reset the write
> -* pointer.
> -*/
> -   f2fs_notice(sbi,
> - "Zone without valid block has non-zero write "
> - "pointer. Reset the write pointer: 
> wp[0x%x,0x%x]",
> - wp_segno, wp_blkoff);
> -   }
> +   if (!valid_block_cnt) {
> +   f2fs_notice(sbi, "Zone without valid block has non-zero write 
> "
> +   "pointer. Reset the write pointer: cond[0x%x]",
> +   zone->cond);
> ret = __f2fs_issue_discard_zone(sbi, fdev->bdev, zone_block,
> zone->len >> log_sectors_per_block);
> if (ret)
> f2fs_err(sbi, "Discard zone failed: %s (errno=%d)",
>  fdev->path, ret);
> -
> return ret;
> }
>
> @@ -4957,10 +4919,8 @@ static int check_zone_write_pointer(struct 
> f2fs_sb_info 

Re: [f2fs-dev] [PATCH 1/4] f2fs: allocate new section if it's not new

2023-12-04 Thread Daeho Jeong
LGTM

On Mon, Dec 4, 2023 at 10:06 AM Jaegeuk Kim  wrote:
>
> If fsck can allocate a new zone, it'd be better to use that instead of
> allocating a new one.
>
> And, it modifies kernel messages.
>
> Signed-off-by: Jaegeuk Kim 
> ---
>  fs/f2fs/segment.c | 33 +
>  1 file changed, 17 insertions(+), 16 deletions(-)
>
> diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
> index 08e2f44a1264..9081c9af977a 100644
> --- a/fs/f2fs/segment.c
> +++ b/fs/f2fs/segment.c
> @@ -4949,20 +4949,18 @@ static int check_zone_write_pointer(struct 
> f2fs_sb_info *sbi,
> return ret;
> }
>
> -   if (is_set_ckpt_flags(sbi, CP_UMOUNT_FLAG)) {
> -   /*
> -* If there are valid blocks and the write pointer doesn't 
> match
> -* with them, we need to report the inconsistency and fill
> -* the zone till the end to close the zone. This inconsistency
> -* does not cause write error because the zone will not be
> -* selected for write operation until it get discarded.
> -*/
> -   f2fs_notice(sbi, "Valid blocks are not aligned with write "
> +   /*
> +* If there are valid blocks and the write pointer doesn't match
> +* with them, we need to report the inconsistency and fill
> +* the zone till the end to close the zone. This inconsistency
> +* does not cause write error because the zone will not be
> +* selected for write operation until it get discarded.
> +*/
> +   f2fs_notice(sbi, "Valid blocks are not aligned with write "
> "pointer: valid block[0x%x,0x%x] wp[0x%x,0x%x]",
> GET_SEGNO(sbi, last_valid_block),
> GET_BLKOFF_FROM_SEG0(sbi, last_valid_block),
> wp_segno, wp_blkoff);
> -   }
>
> ret = blkdev_zone_mgmt(fdev->bdev, REQ_OP_ZONE_FINISH,
> zone->start, zone->len, GFP_NOFS);
> @@ -5053,15 +5051,18 @@ static int fix_curseg_write_pointer(struct 
> f2fs_sb_info *sbi, int type)
> f2fs_notice(sbi, "Unaligned curseg[%d] with write pointer: "
> "curseg[0x%x,0x%x] wp[0x%x,0x%x]", type, 
> cs->segno,
> cs->next_blkoff, wp_segno, wp_blkoff);
> -   } else {
> -   f2fs_notice(sbi, "Not successfully unmounted in the previous "
> -   "mount");
> }
>
> -   f2fs_notice(sbi, "Assign new section to curseg[%d]: "
> -   "curseg[0x%x,0x%x]", type, cs->segno, cs->next_blkoff);
> +   /* Allocate a new section if it's not new. */
> +   if (cs->next_blkoff) {
> +   unsigned int old_segno = cs->segno, old_blkoff = 
> cs->next_blkoff;
>
> -   f2fs_allocate_new_section(sbi, type, true);
> +   f2fs_allocate_new_section(sbi, type, true);
> +   f2fs_notice(sbi, "Assign new section to curseg[%d]: "
> +   "[0x%x,0x%x] -> [0x%x,0x%x]",
> +   type, old_segno, old_blkoff,
> +   cs->segno, cs->next_blkoff);
> +   }
>
> /* check consistency of the zone curseg pointed to */
> if (check_zone_write_pointer(sbi, zbd, ))
> --
> 2.43.0.rc2.451.g8631bc7472-goog
>
>
>
> ___
> 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] f2fs-tools: support zoned ufs devices

2023-11-30 Thread Daeho Jeong
From: Daeho Jeong 

Support zoned ufs devices.
1. implemented out-place updates
2. keep roll forward recovery intact
3. open block device files with O_SYNC to comply with zoned device's
   write rules

Signed-off-by: Daeho Jeong 
---
 fsck/defrag.c  |   2 +-
 fsck/dir.c |  47 +++
 fsck/f2fs.h|   3 +-
 fsck/fsck.c|  96 +++
 fsck/fsck.h|  31 +++---
 fsck/main.c|   3 +
 fsck/mount.c   | 151 -
 fsck/node.c|  30 --
 fsck/node.h|   1 +
 fsck/resize.c  |   2 +-
 fsck/segment.c | 120 ++-
 fsck/xattr.c   |   7 ++-
 lib/libf2fs.c  |  32 +++
 13 files changed, 405 insertions(+), 120 deletions(-)

diff --git a/fsck/defrag.c b/fsck/defrag.c
index 90c2962..361fe73 100644
--- a/fsck/defrag.c
+++ b/fsck/defrag.c
@@ -49,7 +49,7 @@ static int migrate_block(struct f2fs_sb_info *sbi, u64 from, 
u64 to)
/* if data block, read node and update node block */
if (IS_DATASEG(type))
update_data_blkaddr(sbi, le32_to_cpu(sum.nid),
-   le16_to_cpu(sum.ofs_in_node), to);
+   le16_to_cpu(sum.ofs_in_node), to, NULL);
else
update_nat_blkaddr(sbi, 0, le32_to_cpu(sum.nid), to);
 
diff --git a/fsck/dir.c b/fsck/dir.c
index d51176a..3fac850 100644
--- a/fsck/dir.c
+++ b/fsck/dir.c
@@ -220,7 +220,7 @@ static void f2fs_update_dentry(nid_t ino, int file_type,
  */
 int f2fs_add_link(struct f2fs_sb_info *sbi, struct f2fs_node *parent,
const unsigned char *name, int name_len, nid_t ino,
-   int file_type, block_t p_blkaddr, int inc_link)
+   int file_type, block_t *p_blkaddr, int inc_link)
 {
int level = 0, current_depth, bit_pos;
int nbucket, nblock, bidx, block;
@@ -232,6 +232,7 @@ int f2fs_add_link(struct f2fs_sb_info *sbi, struct 
f2fs_node *parent,
nid_t pino;
unsigned int dir_level;
int ret;
+   bool datablk_alloced = false;
 
if (parent == NULL)
return -EINVAL;
@@ -278,6 +279,7 @@ start:
 
if (dn.data_blkaddr == NULL_ADDR) {
new_data_block(sbi, dentry_blk, , CURSEG_HOT_DATA);
+   datablk_alloced = true;
} else {
ret = dev_read_block(dentry_blk, dn.data_blkaddr);
ASSERT(ret >= 0);
@@ -295,7 +297,20 @@ add_dentry:
make_dentry_ptr(, NULL, (void *)dentry_blk, 1);
f2fs_update_dentry(ino, file_type, , name, name_len, dentry_hash, 
bit_pos);
 
-   ret = dev_write_block(dentry_blk, dn.data_blkaddr);
+   if (c.zoned_model == F2FS_ZONED_HM) {
+   if (datablk_alloced) {
+   ret = dev_write_block(dentry_blk, dn.data_blkaddr);
+   } else {
+   ret = update_block(sbi, dentry_blk, _blkaddr,
+   dn.node_blk);
+   if (dn.inode_blk == dn.node_blk)
+   dn.idirty = 1;
+   else
+   dn.ndirty = 1;
+   }
+   } else {
+   ret = dev_write_block(dentry_blk, dn.data_blkaddr);
+   }
ASSERT(ret >= 0);
 
/*
@@ -321,13 +336,15 @@ add_dentry:
}
 
if (dn.ndirty) {
-   ret = dev_write_block(dn.node_blk, dn.node_blkaddr);
+   ret = dn.alloced ?
+   dev_write_block(dn.node_blk, dn.node_blkaddr) :
+   update_block(sbi, dn.node_blk, _blkaddr, NULL);
ASSERT(ret >= 0);
}
 
if (dn.idirty) {
ASSERT(parent == dn.inode_blk);
-   ret = write_inode(dn.inode_blk, p_blkaddr);
+   ret = update_inode(sbi, dn.inode_blk, p_blkaddr);
ASSERT(ret >= 0);
}
 
@@ -552,7 +569,7 @@ static void init_inode_block(struct f2fs_sb_info *sbi,
 }
 
 int convert_inline_dentry(struct f2fs_sb_info *sbi, struct f2fs_node *node,
-   block_t p_blkaddr)
+   block_t *p_blkaddr)
 {
struct f2fs_inode *inode = &(node->i);
unsigned int dir_level = node->i.i_dir_level;
@@ -562,6 +579,7 @@ int convert_inline_dentry(struct f2fs_sb_info *sbi, struct 
f2fs_node *node,
struct f2fs_dentry_ptr d;
unsigned long bit_pos = 0;
int ret = 0;
+   bool datablk_alloced = false;
 
if (!(inode->i_inline & F2FS_INLINE_DENTRY))
return 0;
@@ -570,7 +588,7 @@ int convert_inline_dentry(struct f2fs_sb_info *sbi, struct 
f2fs_node *node,
memset(inline_data_addr(node), 0, MAX_INLINE_DATA(node));
inode->i_inline &= ~F2FS_INLINE_DENTRY;
 
-   ret = dev_write

[f2fs-dev] [PATCH] f2fs-tools: convert lost+found dir to regular dentry before adding nodes

2023-11-29 Thread Daeho Jeong
From: Daeho Jeong 

fsck doesn't support adding inodes to inline dentries. So, need to
convert inline lost+found dentry before adding missing inodes.

Signed-off-by: Daeho Jeong 
---
 fsck/fsck.c | 8 
 fsck/fsck.h | 4 
 2 files changed, 12 insertions(+)

diff --git a/fsck/fsck.c b/fsck/fsck.c
index 55eddca..f40b4cd 100644
--- a/fsck/fsck.c
+++ b/fsck/fsck.c
@@ -2849,6 +2849,14 @@ static struct f2fs_node *fsck_get_lpf(struct 
f2fs_sb_info *sbi)
/* FIXME: give up? */
goto out;
}
+
+   /* Must convert inline dentry before adding inodes */
+   err = convert_inline_dentry(sbi, node, ni.blk_addr);
+   if (err) {
+   MSG(0, "Convert inline dentry for ino=%x failed.\n",
+   lpf_ino);
+   goto out;
+   }
} else { /* not found, create it */
struct dentry de;
 
diff --git a/fsck/fsck.h b/fsck/fsck.h
index f6f15e7..d6abf18 100644
--- a/fsck/fsck.h
+++ b/fsck/fsck.h
@@ -330,4 +330,8 @@ void *read_all_xattrs(struct f2fs_sb_info *, struct 
f2fs_node *, bool);
 void write_all_xattrs(struct f2fs_sb_info *sbi,
struct f2fs_node *inode, __u32 hsize, void *txattr_addr);
 
+/* dir.c */
+int convert_inline_dentry(struct f2fs_sb_info *sbi, struct f2fs_node *node,
+   block_t p_blkaddr);
+
 #endif /* _FSCK_H_ */
-- 
2.43.0.rc2.451.g8631bc7472-goog



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


[f2fs-dev] [PATCH] f2fs-tools: adjust nat and block release logic

2023-11-17 Thread Daeho Jeong
From: Daeho Jeong 

Fixes: 0f503e443ccb ("f2fs-tools: do not reuse corrupted quota inodes")
Signed-off-by: Daeho Jeong 
---
 fsck/fsck.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/fsck/fsck.c b/fsck/fsck.c
index 55eddca..2bb759c 100644
--- a/fsck/fsck.c
+++ b/fsck/fsck.c
@@ -3094,10 +3094,13 @@ static void fsck_disconnect_file(struct f2fs_sb_info 
*sbi, nid_t ino,
release_block_cnt(sbi, dealloc);
get_node_info(sbi, nid, );
release_block(sbi, ni.blk_addr, dealloc);
+
+   if (dealloc)
+   release_nat_entry(sbi, nid);
}
 
/* clear data counters */
-   if(!(node->i.i_inline & F2FS_INLINE_DATA)) {
+   if (!(node->i.i_inline & (F2FS_INLINE_DATA | F2FS_INLINE_DENTRY))) {
ofs = get_extra_isize(node);
for (i = 0; i < ADDRS_PER_INODE(>i); i++) {
block_t addr = le32_to_cpu(node->i.i_addr[ofs + i]);
-- 
2.43.0.rc0.421.g78406f8d94-goog



___
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: do not reuse corrupted quota inodes

2023-11-17 Thread Daeho Jeong
On Fri, Nov 17, 2023 at 9:24 AM Jaegeuk Kim  wrote:
>
> On 11/15, Chao Yu wrote:
> > On 2023/10/27 8:21, Daeho Jeong wrote:
> > > From: Daeho Jeong 
> > >
> > > When we detect quota inode corruption, we better deallocate the current
> > > space and allocate new ones for a clean start.
> > >
> > > Signed-off-by: Daeho Jeong 
> > >
> > > ---
> > > v2: change node count check when creating a new node block
> > > ---
> > >   fsck/fsck.c| 148 +++--
> > >   fsck/segment.c |   5 +-
> > >   2 files changed, 109 insertions(+), 44 deletions(-)
> > >
> > > diff --git a/fsck/fsck.c b/fsck/fsck.c
> > > index 99cface..dc8e282 100644
> > > --- a/fsck/fsck.c
> > > +++ b/fsck/fsck.c
> > > @@ -67,6 +67,14 @@ int f2fs_set_sit_bitmap(struct f2fs_sb_info *sbi, u32 
> > > blk)
> > > return f2fs_set_bit(BLKOFF_FROM_MAIN(sbi, blk), 
> > > fsck->sit_area_bitmap);
> > >   }
> > > +static inline int f2fs_clear_sit_bitmap(struct f2fs_sb_info *sbi, u32 
> > > blk)
> > > +{
> > > +   struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
> > > +
> > > +   return f2fs_clear_bit(BLKOFF_FROM_MAIN(sbi, blk),
> > > +   fsck->sit_area_bitmap);
> > > +}
> > > +
> > >   static int add_into_hard_link_list(struct f2fs_sb_info *sbi,
> > > u32 nid, u32 link_cnt)
> > >   {
> > > @@ -2150,6 +2158,9 @@ int fsck_chk_quota_node(struct f2fs_sb_info *sbi)
> > > return ret;
> > >   }
> > > +static void fsck_disconnect_file(struct f2fs_sb_info *sbi, nid_t ino,
> > > +   bool dealloc);
> > > +
> > >   int fsck_chk_quota_files(struct f2fs_sb_info *sbi)
> > >   {
> > > struct f2fs_fsck *fsck = F2FS_FSCK(sbi);
> > > @@ -2181,6 +2192,8 @@ int fsck_chk_quota_files(struct f2fs_sb_info *sbi)
> > > if (c.fix_on) {
> > > DBG(0, "Fixing Quota file ([%3d] ino [0x%x])\n",
> > > qtype, ino);
> > > +   fsck_disconnect_file(sbi, ino, true);
> > > +   f2fs_rebuild_qf_inode(sbi, qtype);
> > > f2fs_filesize_update(sbi, ino, 0);
> > > ret = quota_write_inode(sbi, qtype);
> > > if (!ret) {
> > > @@ -2874,10 +2887,53 @@ static int fsck_do_reconnect_file(struct 
> > > f2fs_sb_info *sbi,
> > > return 0;
> > >   }
> > > -static void fsck_failed_reconnect_file_dnode(struct f2fs_sb_info *sbi,
> > > -   struct f2fs_inode *inode, nid_t nid)
> > > +static inline void release_inode_cnt(struct f2fs_sb_info *sbi, bool 
> > > dealloc)
> > > +{
> > > +   F2FS_FSCK(sbi)->chk.valid_inode_cnt--;
> > > +   if (dealloc)
> > > +   sbi->total_valid_inode_count--;
> > > +}
> > > +
> > > +static inline void release_node_cnt(struct f2fs_sb_info *sbi, bool 
> > > dealloc)
> > > +{
> > > +   F2FS_FSCK(sbi)->chk.valid_node_cnt--;
> > > +   if (dealloc)
> > > +   sbi->total_valid_node_count--;
> > > +}
> > > +
> > > +static inline void release_block_cnt(struct f2fs_sb_info *sbi, bool 
> > > dealloc)
> > > +{
> > > +   F2FS_FSCK(sbi)->chk.valid_blk_cnt--;
> > > +   if (dealloc)
> > > +   sbi->total_valid_block_count--;
> > > +}
> > > +
> > > +static inline void release_block(struct f2fs_sb_info *sbi, u64 blkaddr,
> > > +   bool dealloc)
> > > +{
> > > +   f2fs_clear_main_bitmap(sbi, blkaddr);
> > > +   if (dealloc) {
> > > +   struct seg_entry *se;
> > > +   u64 offset;
> > > +
> > > +   se = get_seg_entry(sbi, GET_SEGNO(sbi, blkaddr));
> > > +   offset = OFFSET_IN_SEG(sbi, blkaddr);
> > > +   se->valid_blocks--;
> > > +   f2fs_clear_bit(offset, (char *)se->cur_valid_map);
> > > +   se->dirty = 1;
> > > +   f2fs_clear_sit_bitmap(sbi, blkaddr);
> > > +   }
> > > +}
> > > +
> > > +static inline void release_nat_entry(struct f2fs_sb_info *sbi, u32 nid)
> > > +{
> > > +   nul

[f2fs-dev] [PATCH] f2fs-tools: initialize user cache valid values

2023-11-09 Thread Daeho Jeong
From: Daeho Jeong 

Need to initialize user cache valid values to prevent from providing
false cache entries.

Signed-off-by: Daeho Jeong 
---
 lib/libf2fs_io.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/libf2fs_io.c b/lib/libf2fs_io.c
index 39d3777..d76da83 100644
--- a/lib/libf2fs_io.c
+++ b/lib/libf2fs_io.c
@@ -165,7 +165,7 @@ static int dcache_alloc_all(long n)
|| (dcache_lastused = (uint64_t *)
malloc(sizeof(uint64_t) * n)) == NULL
|| (dcache_buf = (char *) malloc (F2FS_BLKSIZE * n)) == NULL
-   || (dcache_valid = (bool *) malloc(sizeof(bool) * n)) == NULL)
+   || (dcache_valid = (bool *) calloc(sizeof(bool) * n, 1)) == 
NULL)
{
dcache_release();
return -1;
-- 
2.42.0.869.gea05f2083d-goog



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


  1   2   3   4   5   >