[f2fs-dev] [PATCH] f2fs: fix to create selinux label during whiteout initialization

2024-02-06 Thread Chao Yu
generic/700   - output mismatch (see 
/media/fstests/results//generic/700.out.bad)
--- tests/generic/700.out   2023-03-28 10:40:42.735529223 +
+++ /media/fstests/results//generic/700.out.bad 2024-02-06 
04:37:56.0 +
@@ -1,2 +1,4 @@
 QA output created by 700
+/mnt/scratch_f2fs/f1: security.selinux: No such attribute
+/mnt/scratch_f2fs/f2: security.selinux: No such attribute
 Silence is golden
...
(Run 'diff -u /media/fstests/tests/generic/700.out 
/media/fstests/results//generic/700.out.bad'  to see the entire diff)

HINT: You _MAY_ be missing kernel fix:
  70b589a37e1a xfs: add selinux labels to whiteout inodes

Previously, it missed to create selinux labels during whiteout inode
initialization, fix this issue.

Fixes: 7e01e7ad746b ("f2fs: support RENAME_WHITEOUT")
Signed-off-by: Chao Yu 
---
 fs/f2fs/dir.c   |  5 +++--
 fs/f2fs/f2fs.h  |  3 ++-
 fs/f2fs/namei.c | 25 +
 3 files changed, 22 insertions(+), 11 deletions(-)

diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c
index 3f20d94e12f9..02c9355176d3 100644
--- a/fs/f2fs/dir.c
+++ b/fs/f2fs/dir.c
@@ -830,13 +830,14 @@ int f2fs_do_add_link(struct inode *dir, const struct qstr 
*name,
return err;
 }
 
-int f2fs_do_tmpfile(struct inode *inode, struct inode *dir)
+int f2fs_do_tmpfile(struct inode *inode, struct inode *dir,
+   struct f2fs_filename *fname)
 {
struct page *page;
int err = 0;
 
f2fs_down_write(_I(inode)->i_sem);
-   page = f2fs_init_inode_metadata(inode, dir, NULL, NULL);
+   page = f2fs_init_inode_metadata(inode, dir, fname, NULL);
if (IS_ERR(page)) {
err = PTR_ERR(page);
goto fail;
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index d44e2c43d8ab..af766404f454 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -3589,7 +3589,8 @@ int f2fs_do_add_link(struct inode *dir, const struct qstr 
*name,
struct inode *inode, nid_t ino, umode_t mode);
 void f2fs_delete_entry(struct f2fs_dir_entry *dentry, struct page *page,
struct inode *dir, struct inode *inode);
-int f2fs_do_tmpfile(struct inode *inode, struct inode *dir);
+int f2fs_do_tmpfile(struct inode *inode, struct inode *dir,
+   struct f2fs_filename *fname);
 bool f2fs_empty_dir(struct inode *dir);
 
 static inline int f2fs_add_link(struct dentry *dentry, struct inode *inode)
diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c
index ba11298b7837..0875602e2406 100644
--- a/fs/f2fs/namei.c
+++ b/fs/f2fs/namei.c
@@ -852,7 +852,7 @@ static int f2fs_mknod(struct mnt_idmap *idmap, struct inode 
*dir,
 
 static int __f2fs_tmpfile(struct mnt_idmap *idmap, struct inode *dir,
  struct file *file, umode_t mode, bool is_whiteout,
- struct inode **new_inode)
+ struct inode **new_inode, struct f2fs_filename *fname)
 {
struct f2fs_sb_info *sbi = F2FS_I_SB(dir);
struct inode *inode;
@@ -880,7 +880,7 @@ static int __f2fs_tmpfile(struct mnt_idmap *idmap, struct 
inode *dir,
if (err)
goto out;
 
-   err = f2fs_do_tmpfile(inode, dir);
+   err = f2fs_do_tmpfile(inode, dir, fname);
if (err)
goto release_out;
 
@@ -931,22 +931,24 @@ static int f2fs_tmpfile(struct mnt_idmap *idmap, struct 
inode *dir,
if (!f2fs_is_checkpoint_ready(sbi))
return -ENOSPC;
 
-   err = __f2fs_tmpfile(idmap, dir, file, mode, false, NULL);
+   err = __f2fs_tmpfile(idmap, dir, file, mode, false, NULL, NULL);
 
return finish_open_simple(file, err);
 }
 
 static int f2fs_create_whiteout(struct mnt_idmap *idmap,
-   struct inode *dir, struct inode **whiteout)
+   struct inode *dir, struct inode **whiteout,
+   struct f2fs_filename *fname)
 {
-   return __f2fs_tmpfile(idmap, dir, NULL,
-   S_IFCHR | WHITEOUT_MODE, true, whiteout);
+   return __f2fs_tmpfile(idmap, dir, NULL, S_IFCHR | WHITEOUT_MODE,
+   true, whiteout, fname);
 }
 
 int f2fs_get_tmpfile(struct mnt_idmap *idmap, struct inode *dir,
 struct inode **new_inode)
 {
-   return __f2fs_tmpfile(idmap, dir, NULL, S_IFREG, false, new_inode);
+   return __f2fs_tmpfile(idmap, dir, NULL, S_IFREG,
+   false, new_inode, NULL);
 }
 
 static int f2fs_rename(struct mnt_idmap *idmap, struct inode *old_dir,
@@ -990,7 +992,14 @@ static int f2fs_rename(struct mnt_idmap *idmap, struct 
inode *old_dir,
}
 
if (flags & RENAME_WHITEOUT) {
-   err = f2fs_create_whiteout(idmap, old_dir, );
+   struct f2fs_filename fname;
+
+   err = f2fs_setup_filename(old_dir, _dentry->d_name,
+  

[f2fs-dev] [RESEND PATCH v9 2/2] f2fs: Simplify the handling of cached insensitive names

2024-02-06 Thread Eugen Hristev via Linux-f2fs-devel
From: Gabriel Krisman Bertazi 

Keeping it as qstr avoids the unnecessary conversion in f2fs_match

Reviewed-by: Eric Biggers 
Signed-off-by: Gabriel Krisman Bertazi 
[eugen.hris...@collabora.com: port to 6.8-rc3]
Signed-off-by: Eugen Hristev 
---
 fs/f2fs/dir.c  | 53 ++
 fs/f2fs/f2fs.h | 17 ++-
 fs/f2fs/recovery.c |  5 +
 3 files changed, 47 insertions(+), 28 deletions(-)

diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c
index 3f20d94e12f9..f5b65cf36393 100644
--- a/fs/f2fs/dir.c
+++ b/fs/f2fs/dir.c
@@ -42,35 +42,49 @@ static unsigned int bucket_blocks(unsigned int level)
return 4;
 }
 
+#if IS_ENABLED(CONFIG_UNICODE)
 /* If @dir is casefolded, initialize @fname->cf_name from @fname->usr_fname. */
 int f2fs_init_casefolded_name(const struct inode *dir,
  struct f2fs_filename *fname)
 {
-#if IS_ENABLED(CONFIG_UNICODE)
struct super_block *sb = dir->i_sb;
+   unsigned char *buf;
+   int len;
 
if (IS_CASEFOLDED(dir) &&
!is_dot_dotdot(fname->usr_fname->name, fname->usr_fname->len)) {
-   fname->cf_name.name = f2fs_kmem_cache_alloc(f2fs_cf_name_slab,
-   GFP_NOFS, false, F2FS_SB(sb));
-   if (!fname->cf_name.name)
+   buf = f2fs_kmem_cache_alloc(f2fs_cf_name_slab,
+   GFP_NOFS, false, F2FS_SB(sb));
+   if (!buf)
return -ENOMEM;
-   fname->cf_name.len = utf8_casefold(sb->s_encoding,
-  fname->usr_fname,
-  fname->cf_name.name,
-  F2FS_NAME_LEN);
-   if ((int)fname->cf_name.len <= 0) {
-   kmem_cache_free(f2fs_cf_name_slab, fname->cf_name.name);
-   fname->cf_name.name = NULL;
+
+   len = utf8_casefold(sb->s_encoding, fname->usr_fname,
+   buf, F2FS_NAME_LEN);
+   if (len <= 0) {
+   kmem_cache_free(f2fs_cf_name_slab, buf);
if (sb_has_strict_encoding(sb))
return -EINVAL;
/* fall back to treating name as opaque byte sequence */
+   return 0;
}
+   fname->cf_name.name = buf;
+   fname->cf_name.len = len;
}
-#endif
+
return 0;
 }
 
+void f2fs_free_casefolded_name(struct f2fs_filename *fname)
+{
+   unsigned char *buf = (unsigned char *)fname->cf_name.name;
+
+   if (buf) {
+   kmem_cache_free(f2fs_cf_name_slab, buf);
+   fname->cf_name.name = NULL;
+   }
+}
+#endif /* CONFIG_UNICODE */
+
 static int __f2fs_setup_filename(const struct inode *dir,
 const struct fscrypt_name *crypt_name,
 struct f2fs_filename *fname)
@@ -142,12 +156,7 @@ void f2fs_free_filename(struct f2fs_filename *fname)
kfree(fname->crypto_buf.name);
fname->crypto_buf.name = NULL;
 #endif
-#if IS_ENABLED(CONFIG_UNICODE)
-   if (fname->cf_name.name) {
-   kmem_cache_free(f2fs_cf_name_slab, fname->cf_name.name);
-   fname->cf_name.name = NULL;
-   }
-#endif
+   f2fs_free_casefolded_name(fname);
 }
 
 static unsigned long dir_block_index(unsigned int level,
@@ -235,11 +244,9 @@ static inline int f2fs_match_name(const struct inode *dir,
struct fscrypt_name f;
 
 #if IS_ENABLED(CONFIG_UNICODE)
-   if (fname->cf_name.name) {
-   struct qstr cf = FSTR_TO_QSTR(>cf_name);
-
-   return f2fs_match_ci_name(dir, , de_name, de_name_len);
-   }
+   if (fname->cf_name.name)
+   return f2fs_match_ci_name(dir, >cf_name,
+ de_name, de_name_len);
 #endif
f.usr_fname = fname->usr_fname;
f.disk_name = fname->disk_name;
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 84c9fead3ad4..2ff8e52642ec 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -530,7 +530,7 @@ struct f2fs_filename {
 * internal operation where usr_fname is also NULL.  In all these cases
 * we fall back to treating the name as an opaque byte sequence.
 */
-   struct fscrypt_str cf_name;
+   struct qstr cf_name;
 #endif
 };
 
@@ -3533,8 +3533,23 @@ int f2fs_get_tmpfile(struct mnt_idmap *idmap, struct 
inode *dir,
 /*
  * dir.c
  */
+unsigned char f2fs_get_de_type(struct f2fs_dir_entry *de);
+#if IS_ENABLED(CONFIG_UNICODE)
 int f2fs_init_casefolded_name(const struct inode *dir,
  struct f2fs_filename *fname);
+void f2fs_free_casefolded_name(struct f2fs_filename *fname);
+#else
+static inline int f2fs_init_casefolded_name(const struct inode *dir,
+   

[f2fs-dev] [RESEND PATCH v9 1/2] ext4: Simplify the handling of cached insensitive names

2024-02-06 Thread Eugen Hristev via Linux-f2fs-devel
From: Gabriel Krisman Bertazi 

Keeping it as qstr avoids the unnecessary conversion in ext4_match

Reviewed-by: Eric Biggers 
Signed-off-by: Gabriel Krisman Bertazi 
[eugen.hris...@collabora.com: port to 6.8-rc3]
Signed-off-by: Eugen Hristev 
---
 fs/ext4/ext4.h  |  2 +-
 fs/ext4/namei.c | 23 +++
 2 files changed, 12 insertions(+), 13 deletions(-)

diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 023571f8dd1b..932bae88b4a7 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -2508,7 +2508,7 @@ struct ext4_filename {
struct fscrypt_str crypto_buf;
 #endif
 #if IS_ENABLED(CONFIG_UNICODE)
-   struct fscrypt_str cf_name;
+   struct qstr cf_name;
 #endif
 };
 
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 05b647e6bc19..e554c5a62ba9 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -1445,7 +1445,8 @@ static int ext4_ci_compare(const struct inode *parent, 
const struct qstr *name,
 int ext4_fname_setup_ci_filename(struct inode *dir, const struct qstr *iname,
  struct ext4_filename *name)
 {
-   struct fscrypt_str *cf_name = >cf_name;
+   struct qstr *cf_name = >cf_name;
+   unsigned char *buf;
struct dx_hash_info *hinfo = >hinfo;
int len;
 
@@ -1455,18 +1456,18 @@ int ext4_fname_setup_ci_filename(struct inode *dir, 
const struct qstr *iname,
return 0;
}
 
-   cf_name->name = kmalloc(EXT4_NAME_LEN, GFP_NOFS);
-   if (!cf_name->name)
+   buf = kmalloc(EXT4_NAME_LEN, GFP_NOFS);
+   if (!buf)
return -ENOMEM;
 
-   len = utf8_casefold(dir->i_sb->s_encoding,
-   iname, cf_name->name,
-   EXT4_NAME_LEN);
+   len = utf8_casefold(dir->i_sb->s_encoding, iname, buf, EXT4_NAME_LEN);
if (len <= 0) {
-   kfree(cf_name->name);
-   cf_name->name = NULL;
+   kfree(buf);
+   buf = NULL;
}
+   cf_name->name = buf;
cf_name->len = (unsigned) len;
+
if (!IS_ENCRYPTED(dir))
return 0;
 
@@ -1503,8 +1504,6 @@ static bool ext4_match(struct inode *parent,
if (IS_CASEFOLDED(parent) &&
(!IS_ENCRYPTED(parent) || fscrypt_has_encryption_key(parent))) {
if (fname->cf_name.name) {
-   struct qstr cf = {.name = fname->cf_name.name,
- .len = fname->cf_name.len};
if (IS_ENCRYPTED(parent)) {
if (fname->hinfo.hash != EXT4_DIRENT_HASH(de) ||
fname->hinfo.minor_hash !=
@@ -1513,8 +1512,8 @@ static bool ext4_match(struct inode *parent,
return false;
}
}
-   return !ext4_ci_compare(parent, , de->name,
-   de->name_len, true);
+   return !ext4_ci_compare(parent, >cf_name,
+   de->name, de->name_len, true);
}
return !ext4_ci_compare(parent, fname->usr_fname, de->name,
de->name_len, false);
-- 
2.34.1



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


[f2fs-dev] [RESEND PATCH v9 0/2] Minor cleanup for case insensitive path

2024-02-06 Thread Eugen Hristev via Linux-f2fs-devel
Hello,

I am trying to respin the series here :
https://www.spinics.net/lists/linux-ext4/msg85081.html

To make it easier to apply I split it into smaller chunks which address
one single thing.
This series will just convert to qstr the storage of the filename
currently using fscrypt_str .

Gabriel Krisman Bertazi (2):
  ext4: Simplify the handling of cached insensitive names
  f2fs: Simplify the handling of cached insensitive names

 fs/ext4/ext4.h |  2 +-
 fs/ext4/namei.c| 23 ++--
 fs/f2fs/dir.c  | 53 ++
 fs/f2fs/f2fs.h | 16 +-
 fs/f2fs/recovery.c |  5 +
 5 files changed, 58 insertions(+), 41 deletions(-)

-- 
2.34.1



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


[f2fs-dev] [PATCH] f2fs: support compress extension update via sysfs interface

2024-02-06 Thread Chao Yu
Introduce /sys/fs/f2fs//compress_extension to support
adding/deleting compress extension via sysfs interface, in
comparison to mount option, it's more easy to use and less
authority issue for applications.

Usage:
- Query: cat /sys/fs/f2fs//compress_extension
- Add: echo '[c|n]extension' > /sys/fs/f2fs//compress_extension
- Del: echo '[c|n]!extension' > /sys/fs/f2fs//compress_extension
- [c] means add/del compress extension
- [n] means add/del nocompress extension

Signed-off-by: Sheng Yong 
Signed-off-by: Chao Yu 
---
 Documentation/ABI/testing/sysfs-fs-f2fs | 10 
 Documentation/filesystems/f2fs.rst  |  6 ++-
 fs/f2fs/compress.c  | 61 +++
 fs/f2fs/f2fs.h  |  4 +-
 fs/f2fs/sysfs.c | 65 +++--
 5 files changed, 139 insertions(+), 7 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-fs-f2fs 
b/Documentation/ABI/testing/sysfs-fs-f2fs
index 48c135e24eb5..1f2cc0913e45 100644
--- a/Documentation/ABI/testing/sysfs-fs-f2fs
+++ b/Documentation/ABI/testing/sysfs-fs-f2fs
@@ -762,3 +762,13 @@ Date:  November 2023
 Contact:   "Chao Yu" 
 Description:   It controls to enable/disable IO aware feature for background 
discard.
By default, the value is 1 which indicates IO aware is on.
+
+What:  /sys/fs/f2fs//compress_extension
+Date:  October 2023
+Contact:   "Chao Yu" 
+Description:   Used to control configure [|no]compress_extension list:
+   - Query: cat /sys/fs/f2fs//compress_extension
+   - Add: echo '[c|n]extension' > 
/sys/fs/f2fs//compress_extension
+   - Del: echo '[c|n]!extension' > 
/sys/fs/f2fs//compress_extension
+   - [c] means add/del compress extension
+   - [n] means add/del nocompress extension
diff --git a/Documentation/filesystems/f2fs.rst 
b/Documentation/filesystems/f2fs.rst
index 32cbfa864f38..c82a8fd7316b 100644
--- a/Documentation/filesystems/f2fs.rst
+++ b/Documentation/filesystems/f2fs.rst
@@ -821,17 +821,19 @@ Compression implementation
   all logical blocks in cluster contain valid data and compress ratio of
   cluster data is lower than specified threshold.
 
-- To enable compression on regular inode, there are four ways:
+- To enable compression on regular inode, there are five ways:
 
   * chattr +c file
   * chattr +c dir; touch dir/file
   * mount w/ -o compress_extension=ext; touch file.ext
   * mount w/ -o compress_extension=*; touch any_file
+  * echo '[c]ext' > /sys/fs/f2fs//compress_extension; touch file.ext
 
-- To disable compression on regular inode, there are two ways:
+- To disable compression on regular inode, there are three ways:
 
   * chattr -c file
   * mount w/ -o nocompress_extension=ext; touch file.ext
+  * echo '[n]ext' > /sys/fs/f2fs//compress_extension; touch file.ext
 
 - Priority in between FS_COMPR_FL, FS_NOCOMP_FS, extensions:
 
diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c
index 3dc488ce882b..a5257882c772 100644
--- a/fs/f2fs/compress.c
+++ b/fs/f2fs/compress.c
@@ -20,6 +20,67 @@
 #include "segment.h"
 #include 
 
+static int is_compress_extension_exist(struct f2fs_sb_info *sbi,
+   unsigned char (*ext)[F2FS_EXTENSION_LEN],
+   int ext_cnt, unsigned char *new_ext)
+{
+   int i;
+
+   for (i = 0; i < ext_cnt; i++) {
+   if (!strcasecmp(new_ext, ext[i]))
+   return i;
+   }
+   return -1;
+}
+
+int f2fs_update_compress_extension(struct f2fs_sb_info *sbi,
+   unsigned char *new_ext, bool is_ext, bool set)
+{
+   unsigned char (*ext)[F2FS_EXTENSION_LEN];
+   unsigned char *ext_cnt;
+
+   if (is_ext) {
+   ext = F2FS_OPTION(sbi).extensions;
+   ext_cnt = _OPTION(sbi).compress_ext_cnt;
+   } else {
+   ext = F2FS_OPTION(sbi).noextensions;
+   ext_cnt = _OPTION(sbi).nocompress_ext_cnt;
+   }
+
+   if (set) {
+   if (*ext_cnt >= COMPRESS_EXT_NUM)
+   return -EINVAL;
+
+   if (is_compress_extension_exist(sbi,
+   F2FS_OPTION(sbi).extensions,
+   F2FS_OPTION(sbi).compress_ext_cnt,
+   new_ext) >= 0)
+   return -EEXIST;
+
+   if (is_compress_extension_exist(sbi,
+   F2FS_OPTION(sbi).noextensions,
+   F2FS_OPTION(sbi).nocompress_ext_cnt,
+   new_ext) >= 0)
+   return -EEXIST;
+
+   strcpy(ext[*ext_cnt], new_ext);
+   (*ext_cnt)++;
+   } else {
+   int pos = is_compress_extension_exist(sbi, ext,
+   *ext_cnt, new_ext);
+   if (pos < 0)
+ 

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

2024-02-06 Thread Jaegeuk Kim
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
> --- 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);
>   block_t sec_len = roundup(map.m_len, sec_blks);
>  
>   map.m_len = sec_blks;
> @@ -2525,7 +2525,7 @@ static int __f2fs_ioc_gc_range(struct file *filp, 
> struct f2fs_gc_range *range)
>   ret = -EAGAIN;
>   goto out;
>   }
> - range->start += CAP_BLKS_PER_SEC(sbi);
> + range->start += BLKS_PER_SEC(sbi);
>   if (range->start <= end)
>   goto do_more;
>  out:
> @@ -2654,7 +2654,7 @@ static int f2fs_defragment_range(struct f2fs_sb_info 
> *sbi,
>   

[f2fs-dev] [PATCH v2 2/4] f2fs: fix panic issue in update_sit_entry

2024-02-06 Thread Zhiguo Niu
When CONFIG_F2FS_CHECK_FS is not enabled, f2fs_bug_on just printing
warning, get_new_segment may get an out-of-bounds segment when there
is no free segments. Then a block is allocated from this invalid
segment, update_sit_entry will access the invalid bitmap address,
cause system panic. Just as below call stack:

f2fs_allocate_data_block get a block address with 0x4000 and
partition size is 64MB

[   13.401997] Unable to handle kernel NULL pointer dereference at virtual 
address 
[   13.402003] Mem abort info:
[   13.402006]   ESR = 0x9605
[   13.402009]   EC = 0x25: DABT (current EL), IL = 32 bits
[   13.402015]   SET = 0, FnV = 0
[   13.402018]   EA = 0, S1PTW = 0
[   13.402021]   FSC = 0x05: level 1 translation fault
[   13.402025] Data abort info:
[   13.402027]   ISV = 0, ISS = 0x0005
[   13.402030]   CM = 0, WnR = 0
[   13.402034] user pgtable: 4k pages, 39-bit VAs, pgdp=0001066ab000
[   13.402038] [] pgd=, p4d=, 
pud=
[   13.402052] Internal error: Oops: 9605 [#1] PREEMPT SMP
[   13.489854] pc : update_sit_entry+0x128/0x420
[   13.490497] lr : f2fs_allocate_data_block+0x6b0/0xc2c
[   13.491218] sp : ffc00e023440
[   13.501530] Call trace:
[   13.501930]  update_sit_entry+0x128/0x420
[   13.502523]  f2fs_allocate_data_block+0x6b0/0xc2c
[   13.503203]  do_write_page+0xf0/0x1d4
[   13.503752]  f2fs_outplace_write_data+0x68/0xfc
[   13.504408]  f2fs_do_write_data_page+0x3a8/0x65c
[   13.505076]  move_data_page+0x294/0x7a8
[   13.505647]  gc_data_segment+0x4b8/0x800
[   13.506229]  do_garbage_collect+0x354/0x674
[   13.506843]  f2fs_gc+0x280/0x68c
[   13.507340]  f2fs_balance_fs+0x104/0x144
[   13.507921]  f2fs_create+0x310/0x3d8
[   13.508458]  path_openat+0x53c/0xc28
[   13.508997]  do_filp_open+0xbc/0x16c
[   13.509535]  do_sys_openat2+0xa0/0x2a0

So sanity check should be add in update_sit_entry.
Also remove some redundant judgment code.

Signed-off-by: Zhiguo Niu 
---
 fs/f2fs/segment.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index ad6511f..f373ff7 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -2399,6 +2399,8 @@ static void update_sit_entry(struct f2fs_sb_info *sbi, 
block_t blkaddr, int del)
 #endif
 
segno = GET_SEGNO(sbi, blkaddr);
+   if (segno == NULL_SEGNO)
+   return;
 
se = get_seg_entry(sbi, segno);
new_vblocks = se->valid_blocks + del;
@@ -3464,8 +3466,7 @@ void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, 
struct page *page,
 * since SSR needs latest valid block information.
 */
update_sit_entry(sbi, *new_blkaddr, 1);
-   if (GET_SEGNO(sbi, old_blkaddr) != NULL_SEGNO)
-   update_sit_entry(sbi, old_blkaddr, -1);
+   update_sit_entry(sbi, old_blkaddr, -1);
 
/*
 * If the current segment is full, flush it out and replace it with a
-- 
1.9.1



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


[f2fs-dev] [PATCH v2 1/4] f2fs: correct counting methods of free_segments in __set_inuse

2024-02-06 Thread Zhiguo Niu
There is a corner scenario on a small-capacity partition with 64MB size:
1. The main area has a total of 24 segments, and there are no free
segments left shown from the free_segmap bitmap and free_secmap in
free_segmap_info.
-
bitmap value: 
-
2. When doing gc, an out-of-bounds segment with segno=24 is allocated.
Because CONFIG_F2FS_CHECK_FS is not enabled, f2fs_bug_on in get_new_segment
just print warning log but the subsequent process continues to run.
-
got_it:
/* set it as dirty segment in free segmap */
f2fs_bug_on(sbi, test_bit(segno, free_i->free_segmap));
__set_inuse(sbi, segno);
--
3. __set_inuse directly sets free_i->free_segments--,
As a result, free_i->free_segments=-1, as shown in the following
coredump information:
--
  crash_arm64> struct free_segmap_info 0xff8084d9a000 -x
  struct free_segmap_info {
  start_segno = 0x7,
  free_segments = 0x,
  free_sections = 0x0,
--
This is unreasonable and will cause free_segments and free_sections
counts mismatch if there are segments released as free.

So same counting methods like free_sections should be used to
free_segments.

Signed-off-by: Zhiguo Niu 
---
 fs/f2fs/segment.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h
index 8129be7..f2847f1 100644
--- a/fs/f2fs/segment.h
+++ b/fs/f2fs/segment.h
@@ -463,8 +463,8 @@ static inline void __set_inuse(struct f2fs_sb_info *sbi,
struct free_segmap_info *free_i = FREE_I(sbi);
unsigned int secno = GET_SEC_FROM_SEG(sbi, segno);
 
-   set_bit(segno, free_i->free_segmap);
-   free_i->free_segments--;
+   if (!test_and_set_bit(segno, free_i->free_segmap))
+   free_i->free_segments--;
if (!test_and_set_bit(secno, free_i->free_secmap))
free_i->free_sections--;
 }
-- 
1.9.1



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


[f2fs-dev] [PATCH v2 3/4] f2fs: enhance judgment conditions of GET_SEGNO

2024-02-06 Thread Zhiguo Niu
NULL_SEGNO should also be returned when the blk_addr value is
out-of-bound main area even __is_valid_data_blkaddr return true.

For example, a 64MB partition with total 24 main segments has no
any free segments left, then a new wrtie request use get_new_segment
may get a out-of-bound segno 24 if CONFIG_F2FS_CHECK_FS is not enabled.
GET_SEGNO should also return NULL_SEGNO in this case rather than treating
is as valid segment.

Besides, if the caller of GET_SEGNO does not ensure blk_addr pass to
GET_SEGNO is valid, it should do sanity check about return value of
GET_SEGNO, avoid causing some unexpected problems later.

Signed-off-by: Zhiguo Niu 
---
 fs/f2fs/file.c| 7 ++-
 fs/f2fs/segment.c | 4 +++-
 fs/f2fs/segment.h | 3 ++-
 3 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 23cd6a1..2cd3cd9 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -2985,9 +2985,14 @@ static int f2fs_ioc_flush_device(struct file *filp, 
unsigned long arg)
if (ret)
return ret;
 
-   if (range.dev_num != 0)
+   if (range.dev_num != 0) {
dev_start_segno = GET_SEGNO(sbi, FDEV(range.dev_num).start_blk);
+   if (dev_start_segno == NULL_SEGNO)
+   return -EINVAL;
+   }
dev_end_segno = GET_SEGNO(sbi, FDEV(range.dev_num).end_blk);
+   if (dev_end_segno == NULL_SEGNO)
+   return -EINVAL;
 
start_segno = sm->last_victim[FLUSH_DEVICE];
if (start_segno < dev_start_segno || start_segno >= dev_end_segno)
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index f373ff7..6772ad4 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -2496,7 +2496,7 @@ void f2fs_invalidate_blocks(struct f2fs_sb_info *sbi, 
block_t addr)
struct sit_info *sit_i = SIT_I(sbi);
 
f2fs_bug_on(sbi, addr == NULL_ADDR);
-   if (addr == NEW_ADDR || addr == COMPRESS_ADDR)
+   if (segno == NULL_SEGNO)
return;
 
f2fs_invalidate_internal_cache(sbi, addr);
@@ -3708,6 +3708,8 @@ void f2fs_do_replace_block(struct f2fs_sb_info *sbi, 
struct f2fs_summary *sum,
unsigned char old_alloc_type;
 
segno = GET_SEGNO(sbi, new_blkaddr);
+   if (segno == NULL_SEGNO)
+   return;
se = get_seg_entry(sbi, segno);
type = se->type;
 
diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h
index f2847f1..b0ea315 100644
--- a/fs/f2fs/segment.h
+++ b/fs/f2fs/segment.h
@@ -96,7 +96,8 @@ static inline void sanity_check_seg_type(struct f2fs_sb_info 
*sbi,
(GET_SEGOFF_FROM_SEG0(sbi, blk_addr) & ((sbi)->blocks_per_seg - 1))
 
 #define GET_SEGNO(sbi, blk_addr)   \
-   ((!__is_valid_data_blkaddr(blk_addr)) ? \
+   ((!__is_valid_data_blkaddr(blk_addr) || \
+   !f2fs_is_valid_blkaddr(sbi, blk_addr, DATA_GENERIC)) ?  \
NULL_SEGNO : GET_L2R_SEGNO(FREE_I(sbi), \
GET_SEGNO_FROM_SEG0(sbi, blk_addr)))
 #define BLKS_PER_SEC(sbi)  \
-- 
1.9.1



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


[f2fs-dev] [PATCH v2 4/4] f2fs: stop checkpoint when get a out-of-bounds segment

2024-02-06 Thread Zhiguo Niu
There is low probability that an out-of-bounds segment will be got
on a small-capacity device. In order to prevent subsequent write requests
allocating block address from this invalid segment, which may cause
unexpected issue, stop checkpoint should be performed.

Also introduce a new stop cp reason:  STOP_CP_REASON_OUTOF_RAGNE.

Signed-off-by: Zhiguo Niu 
---
 fs/f2fs/segment.c   | 12 ++--
 include/linux/f2fs_fs.h |  1 +
 2 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index 6772ad4..6fe2baf 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -2666,7 +2666,11 @@ static void get_new_segment(struct f2fs_sb_info *sbi,
if (dir == ALLOC_RIGHT) {
secno = find_first_zero_bit(free_i->free_secmap,
MAIN_SECS(sbi));
-   f2fs_bug_on(sbi, secno >= MAIN_SECS(sbi));
+   if (secno >= MAIN_SECS(sbi)) {
+   f2fs_stop_checkpoint(sbi, false,
+   STOP_CP_REASON_OUTOF_RAGNE);
+   f2fs_bug_on(sbi, 1);
+   }
} else {
go_left = 1;
left_start = hint - 1;
@@ -2682,7 +2686,11 @@ static void get_new_segment(struct f2fs_sb_info *sbi,
}
left_start = find_first_zero_bit(free_i->free_secmap,
MAIN_SECS(sbi));
-   f2fs_bug_on(sbi, left_start >= MAIN_SECS(sbi));
+   if (left_start >= MAIN_SECS(sbi)) {
+   f2fs_stop_checkpoint(sbi, false,
+   STOP_CP_REASON_OUTOF_RAGNE);
+   f2fs_bug_on(sbi, 1);
+   }
break;
}
secno = left_start;
diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h
index 053137a0..72c6782 100644
--- a/include/linux/f2fs_fs.h
+++ b/include/linux/f2fs_fs.h
@@ -81,6 +81,7 @@ enum stop_cp_reason {
STOP_CP_REASON_CORRUPTED_SUMMARY,
STOP_CP_REASON_UPDATE_INODE,
STOP_CP_REASON_FLUSH_FAIL,
+   STOP_CP_REASON_OUTOF_RAGNE,
STOP_CP_REASON_MAX,
 };
 
-- 
1.9.1



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


[f2fs-dev] [PATCH v2 0/4] f2fs: fix panic issue in small capacity device

2024-02-06 Thread Zhiguo Niu
A panic issue happened in a reboot test in small capacity device
as following:
1.The device size is 64MB, and main area has 24 segments, and
CONFIG_F2FS_CHECK_FS is not enabled.
2.There is no any free segments left shown in free_segmap_info,
then another write request cause get_new_segment get a out-of-bound
segment with segno 24.
3.panic happen in update_sit_entry because access invalid bitmap
pointer.

More detail shown in following patch sets.
The three patches are splited here because the modifications are
relatively independent and more readable.

---
Changes of v2: stop checkpoint when get a out-of-bound segment
---

Zhiguo Niu (4):
  f2fs: correct counting methods of free_segments in __set_inuse
  f2fs: fix panic issue in update_sit_entry
  f2fs: enhance judgment conditions of GET_SEGNO
  f2fs: stop checkpoint when get a out-of-bounds segment

 fs/f2fs/file.c  |  7 ++-
 fs/f2fs/segment.c   | 21 -
 fs/f2fs/segment.h   |  7 ---
 include/linux/f2fs_fs.h |  1 +
 4 files changed, 27 insertions(+), 9 deletions(-)

-- 
1.9.1



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


[f2fs-dev] [PATCH 1/3] f2fs: deprecate io_bits

2024-02-06 Thread Jaegeuk Kim
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(struct f2fs_sb_info *sbi, 
struct bio *bio,
block_t last_blkaddr,
block_t cur_blkaddr)
 {
-   if (F2FS_IO_ALIGNED(sbi) && (fio->type == DATA || fio->type == NODE)) {
-   unsigned int filled_blocks =
-   F2FS_BYTES_TO_BLK(bio->bi_iter.bi_size);
-   unsigned int io_size = F2FS_IO_SIZE(sbi);
-   unsigned int left_vecs = bio->bi_max_vecs - bio->bi_vcnt;
-
-   /* IOs in bio is aligned and left space of vectors is not 
enough */
-   if (!(filled_blocks % io_size) && left_vecs < io_size)
-   return false;
-   }
if 

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

2024-02-06 Thread Jaegeuk Kim
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_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);
block_t sec_len = roundup(map.m_len, sec_blks);
 
map.m_len = sec_blks;
@@ -2525,7 +2525,7 @@ static int __f2fs_ioc_gc_range(struct file *filp, struct 
f2fs_gc_range *range)
ret = -EAGAIN;
goto out;
}
-   range->start += CAP_BLKS_PER_SEC(sbi);
+   range->start += BLKS_PER_SEC(sbi);
if (range->start <= end)
goto do_more;
 out:
@@ -2654,7 +2654,7 @@ static int f2fs_defragment_range(struct f2fs_sb_info *sbi,
goto out;
}
 
-   sec_num = DIV_ROUND_UP(total, CAP_BLKS_PER_SEC(sbi));
+   sec_num = DIV_ROUND_UP(total, BLKS_PER_SEC(sbi));
 
/*
 * make sure there 

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

2024-02-06 Thread Jaegeuk Kim
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->full_seg[type]++;
else
si->dirty_seg[type]++;
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 4c52136cbc10..9a9e858083af 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -1813,6 +1813,14 @@ struct f2fs_sb_info {
 #endif
 };
 
+/* Definitions to access f2fs_sb_info */
+#define BLKS_PER_SEG(sbi)  \
+   ((sbi)->blocks_per_seg)
+#define BLKS_PER_SEC(sbi)  \
+   ((sbi)->segs_per_sec << (sbi)->log_blocks_per_seg)
+#define SEGS_PER_SEC(sbi)  \
+   ((sbi)->segs_per_sec)
+
 __printf(3, 4)
 void f2fs_printk(struct f2fs_sb_info *sbi, bool limit_rate, const char *fmt, 
...);
 

Re: [f2fs-dev] [PATCH v7] f2fs: unify the error handling of f2fs_is_valid_blkaddr

2024-02-06 Thread Zhiguo Niu
On Tue, Feb 6, 2024 at 11:36 AM Chao Yu  wrote:
>
> On 2024/2/6 11:32, Jaegeuk Kim wrote:
> > On 02/05, Chao Yu wrote:
> >> On 2024/2/5 11:30, Zhiguo Niu wrote:
> >>> There are some cases of f2fs_is_valid_blkaddr not handled as
> >>> ERROR_INVALID_BLKADDR,so unify the error handling about all of
> >>> f2fs_is_valid_blkaddr.
> >>>
> >>> Signed-off-by: Zhiguo Niu 
> >>> Signed-off-by: Chao Yu 
> >>> ---
> >>> changes of v7: update patch according to sync with Chao
> >>> -restore some code to original
> >>> -modify err handle of __is_bitmap_valid for covering all cases
> >>> changes of v6: improve patch according to Chao's suggestions
> >>> -restore dump_stack to original position
> >>> -adjuest code sequence of __is_bitmap_check_valid
> >>> changes of v5: improve patch according to Jaegeuk's suggestiongs
> >>> -restore return value of some f2fs_is_valid_blkaddr error case to 
> >>> original
> >>> -move cp_err checking to outermost for unified processing
> >>> -return true directly for case (type=DATA_GENERIC_ENHANCE_READ) in
> >>>  __is_bitmap_valid to avoid meaningless flow
> >>> -rename __is_bitmap_valid to __is_bitmap_check_valid for avoiding 
> >>> ambiguity
> >>>  and handling its return value in the caller uniformly, also cooperate
> >>>  switch checking true to false for error case of
> >>>  f2fs_is_valid_blkaddr(type=DATA_GENERIC_ENHANCE_UPDATE) in 
> >>> do_recover_data
> >>>  for more readable
> >>> changes of v4: update according to the latest code
> >>> changes of v3:
> >>> -rebase patch to dev-test
> >>> -correct return value for some f2fs_is_valid_blkaddr error case
> >>> changes of v2: improve patch according Chao's suggestions.
> >>> ---
> >>> ---
> >>>fs/f2fs/checkpoint.c   | 33 ++---
> >>>fs/f2fs/data.c | 22 +++---
> >>>fs/f2fs/extent_cache.c |  5 +
> >>>fs/f2fs/file.c | 16 +++-
> >>>fs/f2fs/gc.c   |  2 --
> >>>fs/f2fs/recovery.c |  4 
> >>>fs/f2fs/segment.c  |  2 --
> >>>7 files changed, 25 insertions(+), 59 deletions(-)
> >>>
> >>> diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
> >>> index b85820e..3335619 100644
> >>> --- a/fs/f2fs/checkpoint.c
> >>> +++ b/fs/f2fs/checkpoint.c
> >>> @@ -154,46 +154,43 @@ static bool __is_bitmap_valid(struct f2fs_sb_info 
> >>> *sbi, block_t blkaddr,
> >>> if (unlikely(f2fs_cp_error(sbi)))
> >>> return exist;
> >>> -   if (exist && type == DATA_GENERIC_ENHANCE_UPDATE) {
> >>> -   f2fs_err(sbi, "Inconsistent error blkaddr:%u, sit bitmap:%d",
> >>> -blkaddr, exist);
> >>> -   set_sbi_flag(sbi, SBI_NEED_FSCK);
> >>> -   return exist;
> >>> -   }
> >>> -
> >>> -   if (!exist && type == DATA_GENERIC_ENHANCE) {
> >>> +   if ((exist && type == DATA_GENERIC_ENHANCE_UPDATE) ||
> >>> +   (!exist && type == DATA_GENERIC_ENHANCE)) {
> >>> f2fs_err(sbi, "Inconsistent error blkaddr:%u, sit bitmap:%d",
> >>>  blkaddr, exist);
> >>> set_sbi_flag(sbi, SBI_NEED_FSCK);
> >>> dump_stack();
> >>> }
> >>> +
> >>
> >> No need to add one blank line.
> >>
> >> Otherwise, it looks good to me.
> >>
> >> Reviewed-by: Chao Yu 
> >>
> >> Thanks,
> >>
> >>> return exist;
> >>>}
> >>>static bool __f2fs_is_valid_blkaddr(struct f2fs_sb_info *sbi,
> >>> block_t blkaddr, int type)
> >>>{
> >>> +   bool valid = false;
> >>> +
> >>> switch (type) {
> >>> case META_NAT:
> >>> break;
> >>> case META_SIT:
> >>> if (unlikely(blkaddr >= SIT_BLK_CNT(sbi)))
> >>> -   return false;
> >>> +   goto err;
> >>> break;
> >>> case META_SSA:
> >>> if (unlikely(blkaddr >= MAIN_BLKADDR(sbi) ||
> >>> blkaddr < SM_I(sbi)->ssa_blkaddr))
> >>> -   return false;
> >>> +   goto err;
> >>> break;
> >>> case META_CP:
> >>> if (unlikely(blkaddr >= SIT_I(sbi)->sit_base_addr ||
> >>> blkaddr < __start_cp_addr(sbi)))
> >>> -   return false;
> >>> +   goto err;
> >>> break;
> >>> case META_POR:
> >>> if (unlikely(blkaddr >= MAX_BLKADDR(sbi) ||
> >>> blkaddr < MAIN_BLKADDR(sbi)))
> >>> -   return false;
> >>> +   goto err;
> >>> break;
> >>> case DATA_GENERIC:
> >>> case DATA_GENERIC_ENHANCE:
> >>> @@ -210,21 +207,27 @@ static bool __f2fs_is_valid_blkaddr(struct 
> >>> f2fs_sb_info *sbi,
> >>>   blkaddr);
> >>> set_sbi_flag(sbi, SBI_NEED_FSCK);
> >>> dump_stack();
> >>> -   return false;
> >>> +   goto err;
> >>> } else 

[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;
 
-   if (f2fs_lfs_mode(F2FS_I_SB(inode))) {
-   f2fs_err(F2FS_I_SB(inode),
-  

[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/fs/f2fs/gc.c
@@ -1983,10 +1983,12 

[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