[f2fs-dev] [PATCH v2] f2fs: check validation of fault attrs in f2fs_build_fault_attr()

2024-05-06 Thread Chao Yu
- It missed to check validation of fault attrs in parse_options(),
let's fix to add check condition in f2fs_build_fault_attr().
- Use f2fs_build_fault_attr() in __sbi_store() to clean up code.

Signed-off-by: Chao Yu 
---
v2:
- add static for f2fs_build_fault_attr().
 fs/f2fs/f2fs.h  | 12 
 fs/f2fs/super.c | 27 ---
 fs/f2fs/sysfs.c | 14 ++
 3 files changed, 38 insertions(+), 15 deletions(-)

diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 95a40d4f778f..a29576f46796 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -72,7 +72,7 @@ enum {
 
 struct f2fs_fault_info {
atomic_t inject_ops;
-   unsigned int inject_rate;
+   int inject_rate;
unsigned int inject_type;
 };
 
@@ -4597,10 +4597,14 @@ static inline bool f2fs_need_verity(const struct inode 
*inode, pgoff_t idx)
 }
 
 #ifdef CONFIG_F2FS_FAULT_INJECTION
-extern void f2fs_build_fault_attr(struct f2fs_sb_info *sbi, unsigned int rate,
-   unsigned int type);
+extern int f2fs_build_fault_attr(struct f2fs_sb_info *sbi, unsigned long rate,
+   unsigned long type);
 #else
-#define f2fs_build_fault_attr(sbi, rate, type) do { } while (0)
+static int f2fs_build_fault_attr(struct f2fs_sb_info *sbi, unsigned long rate,
+   unsigned long type)
+{
+   return 0;
+}
 #endif
 
 static inline bool is_journalled_quota(struct f2fs_sb_info *sbi)
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index a4bc26dfdb1a..94918ae7eddb 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -66,21 +66,31 @@ const char *f2fs_fault_name[FAULT_MAX] = {
[FAULT_NO_SEGMENT]  = "no free segment",
 };
 
-void f2fs_build_fault_attr(struct f2fs_sb_info *sbi, unsigned int rate,
-   unsigned int type)
+int f2fs_build_fault_attr(struct f2fs_sb_info *sbi, unsigned long rate,
+   unsigned long type)
 {
struct f2fs_fault_info *ffi = _OPTION(sbi).fault_info;
 
if (rate) {
+   if (rate > INT_MAX)
+   return -EINVAL;
atomic_set(>inject_ops, 0);
-   ffi->inject_rate = rate;
+   ffi->inject_rate = (int)rate;
}
 
-   if (type)
-   ffi->inject_type = type;
+   if (type) {
+   if (type >= BIT(FAULT_MAX))
+   return -EINVAL;
+   ffi->inject_type = (unsigned int)type;
+   }
 
if (!rate && !type)
memset(ffi, 0, sizeof(struct f2fs_fault_info));
+   else
+   f2fs_info(sbi,
+   "build fault injection attr: rate: %lu, type: 0x%lx",
+   rate, type);
+   return 0;
 }
 #endif
 
@@ -886,14 +896,17 @@ static int parse_options(struct super_block *sb, char 
*options, bool is_remount)
case Opt_fault_injection:
if (args->from && match_int(args, ))
return -EINVAL;
-   f2fs_build_fault_attr(sbi, arg, F2FS_ALL_FAULT_TYPE);
+   if (f2fs_build_fault_attr(sbi, arg,
+   F2FS_ALL_FAULT_TYPE))
+   return -EINVAL;
set_opt(sbi, FAULT_INJECTION);
break;
 
case Opt_fault_type:
if (args->from && match_int(args, ))
return -EINVAL;
-   f2fs_build_fault_attr(sbi, 0, arg);
+   if (f2fs_build_fault_attr(sbi, 0, arg))
+   return -EINVAL;
set_opt(sbi, FAULT_INJECTION);
break;
 #else
diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c
index a568ce96cf56..7aa3844e7a80 100644
--- a/fs/f2fs/sysfs.c
+++ b/fs/f2fs/sysfs.c
@@ -484,10 +484,16 @@ static ssize_t __sbi_store(struct f2fs_attr *a,
if (ret < 0)
return ret;
 #ifdef CONFIG_F2FS_FAULT_INJECTION
-   if (a->struct_type == FAULT_INFO_TYPE && t >= BIT(FAULT_MAX))
-   return -EINVAL;
-   if (a->struct_type == FAULT_INFO_RATE && t >= UINT_MAX)
-   return -EINVAL;
+   if (a->struct_type == FAULT_INFO_TYPE) {
+   if (f2fs_build_fault_attr(sbi, 0, t))
+   return -EINVAL;
+   return count;
+   }
+   if (a->struct_type == FAULT_INFO_RATE) {
+   if (f2fs_build_fault_attr(sbi, t, 0))
+   return -EINVAL;
+   return count;
+   }
 #endif
if (a->struct_type == RESERVED_BLOCKS) {
spin_lock(>stat_lock);
-- 
2.40.1



___
Linux-f2fs-devel mailing list

[f2fs-dev] [PATCH v2 1/3] f2fs: fix to release node block count in error path of f2fs_new_node_page()

2024-05-06 Thread Chao Yu
It missed to call dec_valid_node_count() to release node block count
in error path, fix it.

Fixes: 141170b759e0 ("f2fs: fix to avoid use f2fs_bug_on() in 
f2fs_new_node_page()")
Signed-off-by: Chao Yu 
---
v2:
- avoid comppile warning if CONFIG_F2FS_CHECK_FS is off.
 fs/f2fs/node.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
index b3de6d6cdb02..7df5ad84cb5e 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -1319,6 +1319,7 @@ struct page *f2fs_new_node_page(struct dnode_of_data *dn, 
unsigned int ofs)
}
if (unlikely(new_ni.blk_addr != NULL_ADDR)) {
err = -EFSCORRUPTED;
+   dec_valid_node_count(sbi, dn->inode, !ofs);
set_sbi_flag(sbi, SBI_NEED_FSCK);
f2fs_handle_error(sbi, ERROR_INVALID_BLKADDR);
goto fail;
@@ -1345,7 +1346,6 @@ struct page *f2fs_new_node_page(struct dnode_of_data *dn, 
unsigned int ofs)
if (ofs == 0)
inc_valid_inode_count(sbi);
return page;
-
 fail:
clear_node_page_dirty(page);
f2fs_put_page(page, 1);
-- 
2.40.1



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


[f2fs-dev] [PATCH] f2fs: use f2fs_{err, info}_ratelimited() for cleanup

2024-05-06 Thread Chao Yu
Commit b1c9d3f833ba ("f2fs: support printk_ratelimited() in f2fs_printk()")
missed some cases, cover all remains for cleanup.

Signed-off-by: Chao Yu 
---
 fs/f2fs/compress.c | 54 +-
 fs/f2fs/segment.c  |  5 ++---
 2 files changed, 26 insertions(+), 33 deletions(-)

diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c
index 8892c8262141..3c70a9697063 100644
--- a/fs/f2fs/compress.c
+++ b/fs/f2fs/compress.c
@@ -198,8 +198,8 @@ static int lzo_compress_pages(struct compress_ctx *cc)
ret = lzo1x_1_compress(cc->rbuf, cc->rlen, cc->cbuf->cdata,
>clen, cc->private);
if (ret != LZO_E_OK) {
-   printk_ratelimited("%sF2FS-fs (%s): lzo compress failed, 
ret:%d\n",
-   KERN_ERR, F2FS_I_SB(cc->inode)->sb->s_id, ret);
+   f2fs_err_ratelimited(F2FS_I_SB(cc->inode),
+   "lzo compress failed, ret:%d", ret);
return -EIO;
}
return 0;
@@ -212,17 +212,15 @@ static int lzo_decompress_pages(struct decompress_io_ctx 
*dic)
ret = lzo1x_decompress_safe(dic->cbuf->cdata, dic->clen,
dic->rbuf, >rlen);
if (ret != LZO_E_OK) {
-   printk_ratelimited("%sF2FS-fs (%s): lzo decompress failed, 
ret:%d\n",
-   KERN_ERR, F2FS_I_SB(dic->inode)->sb->s_id, ret);
+   f2fs_err_ratelimited(F2FS_I_SB(dic->inode),
+   "lzo decompress failed, ret:%d", ret);
return -EIO;
}
 
if (dic->rlen != PAGE_SIZE << dic->log_cluster_size) {
-   printk_ratelimited("%sF2FS-fs (%s): lzo invalid rlen:%zu, "
-   "expected:%lu\n", KERN_ERR,
-   F2FS_I_SB(dic->inode)->sb->s_id,
-   dic->rlen,
-   PAGE_SIZE << dic->log_cluster_size);
+   f2fs_err_ratelimited(F2FS_I_SB(dic->inode),
+   "lzo invalid rlen:%zu, expected:%lu",
+   dic->rlen, PAGE_SIZE << dic->log_cluster_size);
return -EIO;
}
return 0;
@@ -294,16 +292,15 @@ static int lz4_decompress_pages(struct decompress_io_ctx 
*dic)
ret = LZ4_decompress_safe(dic->cbuf->cdata, dic->rbuf,
dic->clen, dic->rlen);
if (ret < 0) {
-   printk_ratelimited("%sF2FS-fs (%s): lz4 decompress failed, 
ret:%d\n",
-   KERN_ERR, F2FS_I_SB(dic->inode)->sb->s_id, ret);
+   f2fs_err_ratelimited(F2FS_I_SB(dic->inode),
+   "lz4 decompress failed, ret:%d", ret);
return -EIO;
}
 
if (ret != PAGE_SIZE << dic->log_cluster_size) {
-   printk_ratelimited("%sF2FS-fs (%s): lz4 invalid ret:%d, "
-   "expected:%lu\n", KERN_ERR,
-   F2FS_I_SB(dic->inode)->sb->s_id, ret,
-   PAGE_SIZE << dic->log_cluster_size);
+   f2fs_err_ratelimited(F2FS_I_SB(dic->inode),
+   "lz4 invalid ret:%d, expected:%lu",
+   ret, PAGE_SIZE << dic->log_cluster_size);
return -EIO;
}
return 0;
@@ -350,9 +347,8 @@ static int zstd_init_compress_ctx(struct compress_ctx *cc)
 
stream = zstd_init_cstream(, 0, workspace, workspace_size);
if (!stream) {
-   printk_ratelimited("%sF2FS-fs (%s): %s zstd_init_cstream 
failed\n",
-   KERN_ERR, F2FS_I_SB(cc->inode)->sb->s_id,
-   __func__);
+   f2fs_err_ratelimited(F2FS_I_SB(cc->inode),
+   "%s zstd_init_cstream failed", __func__);
kvfree(workspace);
return -EIO;
}
@@ -390,16 +386,16 @@ static int zstd_compress_pages(struct compress_ctx *cc)
 
ret = zstd_compress_stream(stream, , );
if (zstd_is_error(ret)) {
-   printk_ratelimited("%sF2FS-fs (%s): %s zstd_compress_stream 
failed, ret: %d\n",
-   KERN_ERR, F2FS_I_SB(cc->inode)->sb->s_id,
+   f2fs_err_ratelimited(F2FS_I_SB(cc->inode),
+   "%s zstd_compress_stream failed, ret: %d",
__func__, zstd_get_error_code(ret));
return -EIO;
}
 
ret = zstd_end_stream(stream, );
if (zstd_is_error(ret)) {
-   printk_ratelimited("%sF2FS-fs (%s): %s zstd_end_stream returned 
%d\n",
-   KERN_ERR, F2FS_I_SB(cc->inode)->sb->s_id,
+   f2fs_err_ratelimited(F2FS_I_SB(cc->inode),
+   "%s 

[f2fs-dev] [PATCH] f2fs: check validation of fault attrs in f2fs_build_fault_attr()

2024-05-06 Thread Chao Yu
- It missed to check validation of fault attrs in parse_options(),
let's fix to add check condition in f2fs_build_fault_attr().
- Use f2fs_build_fault_attr() in __sbi_store() to clean up code.

Signed-off-by: Chao Yu 
---
 fs/f2fs/f2fs.h  | 12 
 fs/f2fs/super.c | 27 ---
 fs/f2fs/sysfs.c | 14 ++
 3 files changed, 38 insertions(+), 15 deletions(-)

diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 95a40d4f778f..b03d75e4eedc 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -72,7 +72,7 @@ enum {
 
 struct f2fs_fault_info {
atomic_t inject_ops;
-   unsigned int inject_rate;
+   int inject_rate;
unsigned int inject_type;
 };
 
@@ -4597,10 +4597,14 @@ static inline bool f2fs_need_verity(const struct inode 
*inode, pgoff_t idx)
 }
 
 #ifdef CONFIG_F2FS_FAULT_INJECTION
-extern void f2fs_build_fault_attr(struct f2fs_sb_info *sbi, unsigned int rate,
-   unsigned int type);
+extern int f2fs_build_fault_attr(struct f2fs_sb_info *sbi, unsigned long rate,
+   unsigned long type);
 #else
-#define f2fs_build_fault_attr(sbi, rate, type) do { } while (0)
+int f2fs_build_fault_attr(struct f2fs_sb_info *sbi, unsigned long rate,
+   unsigned long type)
+{
+   return 0;
+}
 #endif
 
 static inline bool is_journalled_quota(struct f2fs_sb_info *sbi)
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index a4bc26dfdb1a..94918ae7eddb 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -66,21 +66,31 @@ const char *f2fs_fault_name[FAULT_MAX] = {
[FAULT_NO_SEGMENT]  = "no free segment",
 };
 
-void f2fs_build_fault_attr(struct f2fs_sb_info *sbi, unsigned int rate,
-   unsigned int type)
+int f2fs_build_fault_attr(struct f2fs_sb_info *sbi, unsigned long rate,
+   unsigned long type)
 {
struct f2fs_fault_info *ffi = _OPTION(sbi).fault_info;
 
if (rate) {
+   if (rate > INT_MAX)
+   return -EINVAL;
atomic_set(>inject_ops, 0);
-   ffi->inject_rate = rate;
+   ffi->inject_rate = (int)rate;
}
 
-   if (type)
-   ffi->inject_type = type;
+   if (type) {
+   if (type >= BIT(FAULT_MAX))
+   return -EINVAL;
+   ffi->inject_type = (unsigned int)type;
+   }
 
if (!rate && !type)
memset(ffi, 0, sizeof(struct f2fs_fault_info));
+   else
+   f2fs_info(sbi,
+   "build fault injection attr: rate: %lu, type: 0x%lx",
+   rate, type);
+   return 0;
 }
 #endif
 
@@ -886,14 +896,17 @@ static int parse_options(struct super_block *sb, char 
*options, bool is_remount)
case Opt_fault_injection:
if (args->from && match_int(args, ))
return -EINVAL;
-   f2fs_build_fault_attr(sbi, arg, F2FS_ALL_FAULT_TYPE);
+   if (f2fs_build_fault_attr(sbi, arg,
+   F2FS_ALL_FAULT_TYPE))
+   return -EINVAL;
set_opt(sbi, FAULT_INJECTION);
break;
 
case Opt_fault_type:
if (args->from && match_int(args, ))
return -EINVAL;
-   f2fs_build_fault_attr(sbi, 0, arg);
+   if (f2fs_build_fault_attr(sbi, 0, arg))
+   return -EINVAL;
set_opt(sbi, FAULT_INJECTION);
break;
 #else
diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c
index a568ce96cf56..7aa3844e7a80 100644
--- a/fs/f2fs/sysfs.c
+++ b/fs/f2fs/sysfs.c
@@ -484,10 +484,16 @@ static ssize_t __sbi_store(struct f2fs_attr *a,
if (ret < 0)
return ret;
 #ifdef CONFIG_F2FS_FAULT_INJECTION
-   if (a->struct_type == FAULT_INFO_TYPE && t >= BIT(FAULT_MAX))
-   return -EINVAL;
-   if (a->struct_type == FAULT_INFO_RATE && t >= UINT_MAX)
-   return -EINVAL;
+   if (a->struct_type == FAULT_INFO_TYPE) {
+   if (f2fs_build_fault_attr(sbi, 0, t))
+   return -EINVAL;
+   return count;
+   }
+   if (a->struct_type == FAULT_INFO_RATE) {
+   if (f2fs_build_fault_attr(sbi, t, 0))
+   return -EINVAL;
+   return count;
+   }
 #endif
if (a->struct_type == RESERVED_BLOCKS) {
spin_lock(>stat_lock);
-- 
2.40.1



___
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net

[f2fs-dev] [PATCH 2/2] f2fs: fix to limit gc_pin_file_threshold

2024-05-06 Thread Chao Yu
type of f2fs_inode.i_gc_failures, f2fs_inode_info.i_gc_failures, and
f2fs_sb_info.gc_pin_file_threshold is __le16, unsigned int, and u64,
so it will cause truncation during comparison and persistence.

Unifying variable of these three variables to unsigned short, and
add an upper boundary limitation for gc_pin_file_threshold.

Signed-off-by: Chao Yu 
---
 Documentation/ABI/testing/sysfs-fs-f2fs |  2 +-
 fs/f2fs/f2fs.h  |  4 ++--
 fs/f2fs/file.c  | 11 ++-
 fs/f2fs/gc.h|  1 +
 fs/f2fs/sysfs.c |  7 +++
 5 files changed, 17 insertions(+), 8 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-fs-f2fs 
b/Documentation/ABI/testing/sysfs-fs-f2fs
index 1a4d83953379..cad6c3dc1f9c 100644
--- a/Documentation/ABI/testing/sysfs-fs-f2fs
+++ b/Documentation/ABI/testing/sysfs-fs-f2fs
@@ -331,7 +331,7 @@ Date:   January 2018
 Contact:   Jaegeuk Kim 
 Description:   This indicates how many GC can be failed for the pinned
file. If it exceeds this, F2FS doesn't guarantee its pinning
-   state. 2048 trials is set by default.
+   state. 2048 trials is set by default, and 65535 as maximum.
 
 What:  /sys/fs/f2fs//extension_list
 Date:  February 2018
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 400ff8e1abe0..3dff45cd6cde 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -813,7 +813,7 @@ struct f2fs_inode_info {
unsigned char i_dir_level;  /* use for dentry level for large dir */
union {
unsigned int i_current_depth;   /* only for directory depth */
-   unsigned int i_gc_failures; /* for gc failure statistic */
+   unsigned short i_gc_failures;   /* for gc failure statistic */
};
unsigned int i_pino;/* parent inode number */
umode_t i_acl_mode; /* keep file acl mode temporarily */
@@ -1672,7 +1672,7 @@ struct f2fs_sb_info {
unsigned long long skipped_gc_rwsem;/* FG_GC only */
 
/* threshold for gc trials on pinned files */
-   u64 gc_pin_file_threshold;
+   unsigned short gc_pin_file_threshold;
struct f2fs_rwsem pin_sem;
 
/* maximum # of trials to find a victim segment for SSR and GC */
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 200cafc75dce..1b1b08923f7d 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -3194,16 +3194,17 @@ int f2fs_pin_file_control(struct inode *inode, bool inc)
struct f2fs_inode_info *fi = F2FS_I(inode);
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
 
-   /* Use i_gc_failures for normal file as a risk signal. */
-   if (inc)
-   f2fs_i_gc_failures_write(inode, fi->i_gc_failures + 1);
-
-   if (fi->i_gc_failures > sbi->gc_pin_file_threshold) {
+   if (fi->i_gc_failures >= sbi->gc_pin_file_threshold) {
f2fs_warn(sbi, "%s: Enable GC = ino %lx after %x GC trials",
  __func__, inode->i_ino, fi->i_gc_failures);
clear_inode_flag(inode, FI_PIN_FILE);
return -EAGAIN;
}
+
+   /* Use i_gc_failures for normal file as a risk signal. */
+   if (inc)
+   f2fs_i_gc_failures_write(inode, fi->i_gc_failures + 1);
+
return 0;
 }
 
diff --git a/fs/f2fs/gc.h b/fs/f2fs/gc.h
index 9c0d06c4d19a..a8ea3301b815 100644
--- a/fs/f2fs/gc.h
+++ b/fs/f2fs/gc.h
@@ -26,6 +26,7 @@
 #define LIMIT_FREE_BLOCK   40 /* percentage over invalid + free space */
 
 #define DEF_GC_FAILED_PINNED_FILES 2048
+#define MAX_GC_FAILED_PINNED_FILES USHRT_MAX
 
 /* Search max. number of dirty segments to select a victim segment */
 #define DEF_MAX_VICTIM_SEARCH 4096 /* covers 8GB */
diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c
index 7aa3844e7a80..09d3ecfaa4f1 100644
--- a/fs/f2fs/sysfs.c
+++ b/fs/f2fs/sysfs.c
@@ -681,6 +681,13 @@ static ssize_t __sbi_store(struct f2fs_attr *a,
return count;
}
 
+   if (!strcmp(a->attr.name, "gc_pin_file_threshold")) {
+   if (t > MAX_GC_FAILED_PINNED_FILES)
+   return -EINVAL;
+   sbi->gc_pin_file_threshold = t;
+   return count;
+   }
+
if (!strcmp(a->attr.name, "gc_reclaimed_segments")) {
if (t != 0)
return -EINVAL;
-- 
2.40.1



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


[f2fs-dev] [PATCH 1/2] f2fs: remove unused GC_FAILURE_PIN

2024-05-06 Thread Chao Yu
After commit 3db1de0e582c ("f2fs: change the current atomic write way"),
we removed all GC_FAILURE_ATOMIC usage, let's change i_gc_failures[]
array to i_pin_failure for cleanup.

Meanwhile, let's define i_current_depth and i_gc_failures as union
variable due to they won't be valid at the same time.

Signed-off-by: Chao Yu 
---
 fs/f2fs/f2fs.h | 14 +-
 fs/f2fs/file.c | 12 +---
 fs/f2fs/inode.c|  6 ++
 fs/f2fs/recovery.c |  3 +--
 4 files changed, 13 insertions(+), 22 deletions(-)

diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index b03d75e4eedc..400ff8e1abe0 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -765,11 +765,6 @@ enum {
 
 #define DEF_DIR_LEVEL  0
 
-enum {
-   GC_FAILURE_PIN,
-   MAX_GC_FAILURE
-};
-
 /* used for f2fs_inode_info->flags */
 enum {
FI_NEW_INODE,   /* indicate newly allocated inode */
@@ -816,9 +811,10 @@ struct f2fs_inode_info {
unsigned long i_flags;  /* keep an inode flags for ioctl */
unsigned char i_advise; /* use to give file attribute hints */
unsigned char i_dir_level;  /* use for dentry level for large dir */
-   unsigned int i_current_depth;   /* only for directory depth */
-   /* for gc failure statistic */
-   unsigned int i_gc_failures[MAX_GC_FAILURE];
+   union {
+   unsigned int i_current_depth;   /* only for directory depth */
+   unsigned int i_gc_failures; /* for gc failure statistic */
+   };
unsigned int i_pino;/* parent inode number */
umode_t i_acl_mode; /* keep file acl mode temporarily */
 
@@ -3133,7 +3129,7 @@ static inline void f2fs_i_depth_write(struct inode 
*inode, unsigned int depth)
 static inline void f2fs_i_gc_failures_write(struct inode *inode,
unsigned int count)
 {
-   F2FS_I(inode)->i_gc_failures[GC_FAILURE_PIN] = count;
+   F2FS_I(inode)->i_gc_failures = count;
f2fs_mark_inode_dirty_sync(inode, true);
 }
 
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index ac9d6380e433..200cafc75dce 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -3196,13 +3196,11 @@ int f2fs_pin_file_control(struct inode *inode, bool inc)
 
/* Use i_gc_failures for normal file as a risk signal. */
if (inc)
-   f2fs_i_gc_failures_write(inode,
-   fi->i_gc_failures[GC_FAILURE_PIN] + 1);
+   f2fs_i_gc_failures_write(inode, fi->i_gc_failures + 1);
 
-   if (fi->i_gc_failures[GC_FAILURE_PIN] > sbi->gc_pin_file_threshold) {
+   if (fi->i_gc_failures > sbi->gc_pin_file_threshold) {
f2fs_warn(sbi, "%s: Enable GC = ino %lx after %x GC trials",
- __func__, inode->i_ino,
- fi->i_gc_failures[GC_FAILURE_PIN]);
+ __func__, inode->i_ino, fi->i_gc_failures);
clear_inode_flag(inode, FI_PIN_FILE);
return -EAGAIN;
}
@@ -3266,7 +3264,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];
+   ret = F2FS_I(inode)->i_gc_failures;
 done:
f2fs_update_time(sbi, REQ_TIME);
 out:
@@ -3281,7 +3279,7 @@ static int f2fs_ioc_get_pin_file(struct file *filp, 
unsigned long arg)
__u32 pin = 0;
 
if (is_inode_flag_set(inode, FI_PIN_FILE))
-   pin = F2FS_I(inode)->i_gc_failures[GC_FAILURE_PIN];
+   pin = F2FS_I(inode)->i_gc_failures;
return put_user(pin, (u32 __user *)arg);
 }
 
diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
index 1423cd27a477..9a8c2b63f56d 100644
--- a/fs/f2fs/inode.c
+++ b/fs/f2fs/inode.c
@@ -408,8 +408,7 @@ static int do_read_inode(struct inode *inode)
if (S_ISDIR(inode->i_mode))
fi->i_current_depth = le32_to_cpu(ri->i_current_depth);
else if (S_ISREG(inode->i_mode))
-   fi->i_gc_failures[GC_FAILURE_PIN] =
-   le16_to_cpu(ri->i_gc_failures);
+   fi->i_gc_failures = le16_to_cpu(ri->i_gc_failures);
fi->i_xattr_nid = le32_to_cpu(ri->i_xattr_nid);
fi->i_flags = le32_to_cpu(ri->i_flags);
if (S_ISREG(inode->i_mode))
@@ -679,8 +678,7 @@ void f2fs_update_inode(struct inode *inode, struct page 
*node_page)
ri->i_current_depth =
cpu_to_le32(F2FS_I(inode)->i_current_depth);
else if (S_ISREG(inode->i_mode))
-   ri->i_gc_failures =
-   
cpu_to_le16(F2FS_I(inode)->i_gc_failures[GC_FAILURE_PIN]);
+   ri->i_gc_failures = cpu_to_le16(F2FS_I(inode)->i_gc_failures);
ri->i_xattr_nid = cpu_to_le32(F2FS_I(inode)->i_xattr_nid);
ri->i_flags = cpu_to_le32(F2FS_I(inode)->i_flags);
ri->i_pino = cpu_to_le32(F2FS_I(inode)->i_pino);
diff 

[f2fs-dev] [PATCH 1/5] f2fs: compress: fix to update i_compr_blocks correctly

2024-05-06 Thread Chao Yu
Previously, we account reserved blocks and compressed blocks into
@compr_blocks, then, f2fs_i_compr_blocks_update(,compr_blocks) will
update i_compr_blocks incorrectly, fix it.

Meanwhile, for the case all blocks in cluster were reserved, fix to
update dn->ofs_in_node correctly.

Fixes: eb8fbaa53374 ("f2fs: compress: fix to check unreleased compressed 
cluster")
Signed-off-by: Chao Yu 
---
 fs/f2fs/file.c | 21 ++---
 1 file changed, 14 insertions(+), 7 deletions(-)

diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 1761ad125f97..6c84485687d3 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -3641,7 +3641,8 @@ static int reserve_compress_blocks(struct dnode_of_data 
*dn, pgoff_t count,
 
while (count) {
int compr_blocks = 0;
-   blkcnt_t reserved;
+   blkcnt_t reserved = 0;
+   blkcnt_t to_reserved;
int ret;
 
for (i = 0; i < cluster_size; i++) {
@@ -3661,20 +3662,26 @@ static int reserve_compress_blocks(struct dnode_of_data 
*dn, pgoff_t count,
 * fails in release_compress_blocks(), so NEW_ADDR
 * is a possible case.
 */
-   if (blkaddr == NEW_ADDR ||
-   __is_valid_data_blkaddr(blkaddr)) {
+   if (blkaddr == NEW_ADDR) {
+   reserved++;
+   continue;
+   }
+   if (__is_valid_data_blkaddr(blkaddr)) {
compr_blocks++;
continue;
}
}
 
-   reserved = cluster_size - compr_blocks;
+   to_reserved = cluster_size - compr_blocks - reserved;
 
/* for the case all blocks in cluster were reserved */
-   if (reserved == 1)
+   if (to_reserved == 1) {
+   dn->ofs_in_node += cluster_size;
goto next;
+   }
 
-   ret = inc_valid_block_count(sbi, dn->inode, , false);
+   ret = inc_valid_block_count(sbi, dn->inode,
+   _reserved, false);
if (unlikely(ret))
return ret;
 
@@ -3685,7 +3692,7 @@ static int reserve_compress_blocks(struct dnode_of_data 
*dn, pgoff_t count,
 
f2fs_i_compr_blocks_update(dn->inode, compr_blocks, true);
 
-   *reserved_blocks += reserved;
+   *reserved_blocks += to_reserved;
 next:
count -= cluster_size;
}
-- 
2.40.1



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


[f2fs-dev] [PATCH 2/5] f2fs: compress: fix error path of inc_valid_block_count()

2024-05-06 Thread Chao Yu
If inc_valid_block_count() can not allocate all requested blocks,
it needs to release block count in .total_valid_block_count and
resevation blocks in inode.

Fixes: 54607494875e ("f2fs: compress: fix to avoid inconsistence bewteen 
i_blocks and dnode")
Signed-off-by: Chao Yu 
---
 fs/f2fs/f2fs.h | 15 ---
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index c876813b5532..95a40d4f778f 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -2309,7 +2309,7 @@ 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, bool 
partial)
 {
-   blkcnt_t diff = 0, release = 0;
+   long long diff = 0, release = 0;
block_t avail_user_block_count;
int ret;
 
@@ -2329,26 +2329,27 @@ static inline int inc_valid_block_count(struct 
f2fs_sb_info *sbi,
percpu_counter_add(>alloc_valid_block_count, (*count));
 
spin_lock(>stat_lock);
-   sbi->total_valid_block_count += (block_t)(*count);
-   avail_user_block_count = get_available_block_count(sbi, inode, true);
 
-   if (unlikely(sbi->total_valid_block_count > avail_user_block_count)) {
+   avail_user_block_count = get_available_block_count(sbi, inode, true);
+   diff = (long long)sbi->total_valid_block_count + *count -
+   avail_user_block_count;
+   if (unlikely(diff > 0)) {
if (!partial) {
spin_unlock(>stat_lock);
+   release = *count;
goto enospc;
}
-
-   diff = sbi->total_valid_block_count - avail_user_block_count;
if (diff > *count)
diff = *count;
*count -= diff;
release = diff;
-   sbi->total_valid_block_count -= diff;
if (!*count) {
spin_unlock(>stat_lock);
goto enospc;
}
}
+   sbi->total_valid_block_count += (block_t)(*count);
+
spin_unlock(>stat_lock);
 
if (unlikely(release)) {
-- 
2.40.1



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


[f2fs-dev] [PATCH 5/5] f2fs: compress: don't allow unaligned truncation on released compress inode

2024-05-06 Thread Chao Yu
f2fs image may be corrupted after below testcase:
- mkfs.f2fs -O extra_attr,compression -f /dev/vdb
- mount /dev/vdb /mnt/f2fs
- touch /mnt/f2fs/file
- f2fs_io setflags compression /mnt/f2fs/file
- dd if=/dev/zero of=/mnt/f2fs/file bs=4k count=4
- f2fs_io release_cblocks /mnt/f2fs/file
- truncate -s 8192 /mnt/f2fs/file
- umount /mnt/f2fs
- fsck.f2fs /dev/vdb

[ASSERT] (fsck_chk_inode_blk:1256)  --> ino: 0x5 has i_blocks: 0x0002, but 
has 0x3 blocks
[FSCK] valid_block_count matching with CP [Fail] [0x4, 0x5]
[FSCK] other corrupted bugs   [Fail]

The reason is: partial truncation assume compressed inode has reserved
blocks, after partial truncation, valid block count may change w/
.i_blocks and .total_valid_block_count update, result in corruption.

This patch only allow cluster size aligned truncation on released
compress inode for fixing.

Fixes: c61404153eb6 ("f2fs: introduce FI_COMPRESS_RELEASED instead of using 
IMMUTABLE bit")
Signed-off-by: Chao Yu 
---
 fs/f2fs/file.c | 11 ---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 3f0db351e976..ac9d6380e433 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -952,9 +952,14 @@ int f2fs_setattr(struct mnt_idmap *idmap, struct dentry 
*dentry,
  ATTR_GID | ATTR_TIMES_SET
return -EPERM;
 
-   if ((attr->ia_valid & ATTR_SIZE) &&
-   !f2fs_is_compress_backend_ready(inode))
-   return -EOPNOTSUPP;
+   if ((attr->ia_valid & ATTR_SIZE)) {
+   if (!f2fs_is_compress_backend_ready(inode))
+   return -EOPNOTSUPP;
+   if (is_inode_flag_set(inode, FI_COMPRESS_RELEASED) &&
+   (attr->ia_size %
+   F2FS_BLK_TO_BYTES(F2FS_I(inode)->i_cluster_size)))
+   return -EINVAL;
+   }
 
err = setattr_prepare(idmap, dentry, attr);
if (err)
-- 
2.40.1



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


[f2fs-dev] [PATCH 3/5] f2fs: compress: fix typo in f2fs_reserve_compress_blocks()

2024-05-06 Thread Chao Yu
s/released/reserved.

Signed-off-by: Chao Yu 
---
 fs/f2fs/file.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 6c84485687d3..e77e958a9f92 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -3785,7 +3785,7 @@ static int f2fs_reserve_compress_blocks(struct file 
*filp, unsigned long arg)
} else if (reserved_blocks &&
atomic_read(_I(inode)->i_compr_blocks)) {
set_sbi_flag(sbi, SBI_NEED_FSCK);
-   f2fs_warn(sbi, "%s: partial blocks were released i_ino=%lx "
+   f2fs_warn(sbi, "%s: partial blocks were reserved i_ino=%lx "
"iblocks=%llu, reserved=%u, compr_blocks=%u, "
"run fsck to fix.",
__func__, inode->i_ino, inode->i_blocks,
-- 
2.40.1



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


[f2fs-dev] [PATCH 4/5] f2fs: compress: fix to cover {reserve, release}_compress_blocks() w/ cp_rwsem lock

2024-05-06 Thread Chao Yu
It needs to cover {reserve,release}_compress_blocks() w/ cp_rwsem lock
to avoid racing with checkpoint, otherwise, filesystem metadata including
blkaddr in dnode, inode fields and .total_valid_block_count may be
corrupted after SPO case.

Fixes: ef8d563f184e ("f2fs: introduce F2FS_IOC_RELEASE_COMPRESS_BLOCKS")
Fixes: c75488fb4d82 ("f2fs: introduce F2FS_IOC_RESERVE_COMPRESS_BLOCKS")
Signed-off-by: Chao Yu 
---
 fs/f2fs/file.c | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index e77e958a9f92..3f0db351e976 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -3570,9 +3570,12 @@ static int f2fs_release_compress_blocks(struct file 
*filp, unsigned long arg)
struct dnode_of_data dn;
pgoff_t end_offset, count;
 
+   f2fs_lock_op(sbi);
+
set_new_dnode(, inode, NULL, NULL, 0);
ret = f2fs_get_dnode_of_data(, page_idx, LOOKUP_NODE);
if (ret) {
+   f2fs_unlock_op(sbi);
if (ret == -ENOENT) {
page_idx = f2fs_get_next_page_offset(,
page_idx);
@@ -3590,6 +3593,8 @@ static int f2fs_release_compress_blocks(struct file 
*filp, unsigned long arg)
 
f2fs_put_dnode();
 
+   f2fs_unlock_op(sbi);
+
if (ret < 0)
break;
 
@@ -3742,9 +3747,12 @@ static int f2fs_reserve_compress_blocks(struct file 
*filp, unsigned long arg)
struct dnode_of_data dn;
pgoff_t end_offset, count;
 
+   f2fs_lock_op(sbi);
+
set_new_dnode(, inode, NULL, NULL, 0);
ret = f2fs_get_dnode_of_data(, page_idx, LOOKUP_NODE);
if (ret) {
+   f2fs_unlock_op(sbi);
if (ret == -ENOENT) {
page_idx = f2fs_get_next_page_offset(,
page_idx);
@@ -3762,6 +3770,8 @@ static int f2fs_reserve_compress_blocks(struct file 
*filp, unsigned long arg)
 
f2fs_put_dnode();
 
+   f2fs_unlock_op(sbi);
+
if (ret < 0)
break;
 
-- 
2.40.1



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


[f2fs-dev] [PATCH 2/3] f2fs: fix to add missing iput() in gc_data_segment()

2024-05-06 Thread Chao Yu
During gc_data_segment(), if inode state is abnormal, it missed to call
iput(), fix it.

Fixes: 132e3209789c ("f2fs: remove false alarm on iget failure during GC")
Fixes: 9056d6489f5a ("f2fs: fix to do sanity check on inode type during garbage 
collection")
Signed-off-by: Chao Yu 
---
 fs/f2fs/gc.c | 9 +++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index 8852814dab7f..e86c7f01539a 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -1554,10 +1554,15 @@ static int gc_data_segment(struct f2fs_sb_info *sbi, 
struct f2fs_summary *sum,
int err;
 
inode = f2fs_iget(sb, dni.ino);
-   if (IS_ERR(inode) || is_bad_inode(inode) ||
-   special_file(inode->i_mode))
+   if (IS_ERR(inode))
continue;
 
+   if (is_bad_inode(inode) ||
+   special_file(inode->i_mode)) {
+   iput(inode);
+   continue;
+   }
+
err = f2fs_gc_pinned_control(inode, gc_type, segno);
if (err == -EAGAIN) {
iput(inode);
-- 
2.40.1



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


[f2fs-dev] [PATCH 3/3] f2fs: fix to do sanity check on i_nid for inline_data inode

2024-05-06 Thread Chao Yu
syzbot reports a f2fs bug as below:

[ cut here ]
kernel BUG at fs/f2fs/inline.c:258!
CPU: 1 PID: 34 Comm: kworker/u8:2 Not tainted 
6.9.0-rc6-syzkaller-00012-g9e4bc4bcae01 #0
RIP: 0010:f2fs_write_inline_data+0x781/0x790 fs/f2fs/inline.c:258
Call Trace:
 f2fs_write_single_data_page+0xb65/0x1d60 fs/f2fs/data.c:2834
 f2fs_write_cache_pages fs/f2fs/data.c:3133 [inline]
 __f2fs_write_data_pages fs/f2fs/data.c:3288 [inline]
 f2fs_write_data_pages+0x1efe/0x3a90 fs/f2fs/data.c:3315
 do_writepages+0x35b/0x870 mm/page-writeback.c:2612
 __writeback_single_inode+0x165/0x10b0 fs/fs-writeback.c:1650
 writeback_sb_inodes+0x905/0x1260 fs/fs-writeback.c:1941
 wb_writeback+0x457/0xce0 fs/fs-writeback.c:2117
 wb_do_writeback fs/fs-writeback.c:2264 [inline]
 wb_workfn+0x410/0x1090 fs/fs-writeback.c:2304
 process_one_work kernel/workqueue.c:3254 [inline]
 process_scheduled_works+0xa12/0x17c0 kernel/workqueue.c:3335
 worker_thread+0x86d/0xd70 kernel/workqueue.c:3416
 kthread+0x2f2/0x390 kernel/kthread.c:388
 ret_from_fork+0x4d/0x80 arch/x86/kernel/process.c:147
 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244

The root cause is: inline_data inode can be fuzzed, so that there may
be valid blkaddr in its direct node, once f2fs triggers background GC
to migrate the block, it will hit f2fs_bug_on() during dirty page
writeback.

Let's add sanity check on i_nid field for inline_data inode, meanwhile,
forbid to migrate inline_data inode's data block to fix this issue.

Reported-by: syzbot+848062ba19c8782ca...@syzkaller.appspotmail.com
Closes: 
https://lore.kernel.org/linux-f2fs-devel/d103ce06174d7...@google.com
Signed-off-by: Chao Yu 
---
 fs/f2fs/f2fs.h   |  2 +-
 fs/f2fs/gc.c |  6 ++
 fs/f2fs/inline.c | 17 -
 fs/f2fs/inode.c  |  2 +-
 4 files changed, 24 insertions(+), 3 deletions(-)

diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index fced2b7652f4..c876813b5532 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -4146,7 +4146,7 @@ extern struct kmem_cache *f2fs_inode_entry_slab;
  * inline.c
  */
 bool f2fs_may_inline_data(struct inode *inode);
-bool f2fs_sanity_check_inline_data(struct inode *inode);
+bool f2fs_sanity_check_inline_data(struct inode *inode, struct page *ipage);
 bool f2fs_may_inline_dentry(struct inode *inode);
 void f2fs_do_read_inline_data(struct page *page, struct page *ipage);
 void f2fs_truncate_inline_inode(struct inode *inode,
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index e86c7f01539a..041957750478 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -1563,6 +1563,12 @@ static int gc_data_segment(struct f2fs_sb_info *sbi, 
struct f2fs_summary *sum,
continue;
}
 
+   if (f2fs_has_inline_data(inode)) {
+   iput(inode);
+   set_sbi_flag(sbi, SBI_NEED_FSCK);
+   continue;
+   }
+
err = f2fs_gc_pinned_control(inode, gc_type, segno);
if (err == -EAGAIN) {
iput(inode);
diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c
index ac00423f117b..067600fed3d4 100644
--- a/fs/f2fs/inline.c
+++ b/fs/f2fs/inline.c
@@ -33,11 +33,26 @@ bool f2fs_may_inline_data(struct inode *inode)
return !f2fs_post_read_required(inode);
 }
 
-bool f2fs_sanity_check_inline_data(struct inode *inode)
+static bool has_node_blocks(struct inode *inode, struct page *ipage)
+{
+   struct f2fs_inode *ri = F2FS_INODE(ipage);
+   int i;
+
+   for (i = 0; i < DEF_NIDS_PER_INODE; i++) {
+   if (ri->i_nid[i])
+   return true;
+   }
+   return false;
+}
+
+bool f2fs_sanity_check_inline_data(struct inode *inode, struct page *ipage)
 {
if (!f2fs_has_inline_data(inode))
return false;
 
+   if (has_node_blocks(inode, ipage))
+   return false;
+
if (!support_inline_data(inode))
return true;
 
diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
index c26effdce9aa..1423cd27a477 100644
--- a/fs/f2fs/inode.c
+++ b/fs/f2fs/inode.c
@@ -343,7 +343,7 @@ static bool sanity_check_inode(struct inode *inode, struct 
page *node_page)
}
}
 
-   if (f2fs_sanity_check_inline_data(inode)) {
+   if (f2fs_sanity_check_inline_data(inode, node_page)) {
f2fs_warn(sbi, "%s: inode (ino=%lx, mode=%u) should not have 
inline_data, run fsck to fix",
  __func__, inode->i_ino, inode->i_mode);
return false;
-- 
2.40.1



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


[f2fs-dev] [PATCH 1/3] f2fs: fix to release node block count in error path of f2fs_new_node_page()

2024-05-06 Thread Chao Yu
It missed to call dec_valid_node_count() to release node block count
in error path, fix it.

Fixes: 141170b759e0 ("f2fs: fix to avoid use f2fs_bug_on() in 
f2fs_new_node_page()")
Signed-off-by: Chao Yu 
---
 fs/f2fs/node.c | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
index b3de6d6cdb02..ae39971825bc 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -1313,15 +1313,14 @@ struct page *f2fs_new_node_page(struct dnode_of_data 
*dn, unsigned int ofs)
 
 #ifdef CONFIG_F2FS_CHECK_FS
err = f2fs_get_node_info(sbi, dn->nid, _ni, false);
-   if (err) {
-   dec_valid_node_count(sbi, dn->inode, !ofs);
-   goto fail;
-   }
+   if (err)
+   goto out_dec;
+
if (unlikely(new_ni.blk_addr != NULL_ADDR)) {
err = -EFSCORRUPTED;
set_sbi_flag(sbi, SBI_NEED_FSCK);
f2fs_handle_error(sbi, ERROR_INVALID_BLKADDR);
-   goto fail;
+   goto out_dec;
}
 #endif
new_ni.nid = dn->nid;
@@ -1345,7 +1344,8 @@ struct page *f2fs_new_node_page(struct dnode_of_data *dn, 
unsigned int ofs)
if (ofs == 0)
inc_valid_inode_count(sbi);
return page;
-
+out_dec:
+   dec_valid_node_count(sbi, dn->inode, !ofs);
 fail:
clear_node_page_dirty(page);
f2fs_put_page(page, 1);
-- 
2.40.1



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