linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/4] f2fs: delete f2fs_get_new_segment() declaration
@ 2024-02-22 12:18 Chao Yu
  2024-02-22 12:18 ` [PATCH 2/4] f2fs: fix to don't call f2fs_stop_checkpoint in spinlock coverage Chao Yu
                   ` (3 more replies)
  0 siblings, 4 replies; 9+ messages in thread
From: Chao Yu @ 2024-02-22 12:18 UTC (permalink / raw)
  To: jaegeuk; +Cc: linux-f2fs-devel, linux-kernel, Chao Yu

Commit 093749e296e2 ("f2fs: support age threshold based garbage
collection") added this declaration, but w/ definition, delete
it.

Signed-off-by: Chao Yu <chao@kernel.org>
---
 fs/f2fs/f2fs.h | 2 --
 1 file changed, 2 deletions(-)

diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 8a6fd4352a0e..fbbe9a0a4221 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -3701,8 +3701,6 @@ bool f2fs_segment_has_free_slot(struct f2fs_sb_info *sbi, int segno);
 void f2fs_init_inmem_curseg(struct f2fs_sb_info *sbi);
 void f2fs_save_inmem_curseg(struct f2fs_sb_info *sbi);
 void f2fs_restore_inmem_curseg(struct f2fs_sb_info *sbi);
-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);
 int f2fs_allocate_new_section(struct f2fs_sb_info *sbi, int type, bool force);
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 2/4] f2fs: fix to don't call f2fs_stop_checkpoint in spinlock coverage
  2024-02-22 12:18 [PATCH 1/4] f2fs: delete f2fs_get_new_segment() declaration Chao Yu
@ 2024-02-22 12:18 ` Chao Yu
  2024-02-27 17:50   ` Jaegeuk Kim
  2024-02-22 12:18 ` [PATCH 3/4] f2fs: fix to handle segment allocation failure correctly Chao Yu
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 9+ messages in thread
From: Chao Yu @ 2024-02-22 12:18 UTC (permalink / raw)
  To: jaegeuk; +Cc: linux-f2fs-devel, linux-kernel, Chao Yu

f2fs_stop_checkpoint(, false) is complex and it may sleep, so we should
move it outside segmap_lock spinlock coverage in get_new_segment().

Signed-off-by: Chao Yu <chao@kernel.org>
---
 fs/f2fs/segment.c | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index d0209ea77dd2..8edc42071e6f 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -2646,6 +2646,7 @@ static void get_new_segment(struct f2fs_sb_info *sbi,
 	unsigned int old_zoneno = GET_ZONE_FROM_SEG(sbi, *newseg);
 	bool init = true;
 	int i;
+	int ret = 0;
 
 	spin_lock(&free_i->segmap_lock);
 
@@ -2671,9 +2672,8 @@ static void get_new_segment(struct f2fs_sb_info *sbi,
 		secno = find_first_zero_bit(free_i->free_secmap,
 							MAIN_SECS(sbi));
 		if (secno >= MAIN_SECS(sbi)) {
-			f2fs_stop_checkpoint(sbi, false,
-				STOP_CP_REASON_NO_SEGMENT);
-			f2fs_bug_on(sbi, 1);
+			ret = -ENOSPC;
+			goto out_unlock;
 		}
 	}
 	segno = GET_SEG_FROM_SEC(sbi, secno);
@@ -2704,7 +2704,13 @@ static void get_new_segment(struct f2fs_sb_info *sbi,
 	f2fs_bug_on(sbi, test_bit(segno, free_i->free_segmap));
 	__set_inuse(sbi, segno);
 	*newseg = segno;
+out_unlock:
 	spin_unlock(&free_i->segmap_lock);
+
+	if (ret) {
+		f2fs_stop_checkpoint(sbi, false, STOP_CP_REASON_NO_SEGMENT);
+		f2fs_bug_on(sbi, 1);
+	}
 }
 
 static void reset_curseg(struct f2fs_sb_info *sbi, int type, int modified)
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 3/4] f2fs: fix to handle segment allocation failure correctly
  2024-02-22 12:18 [PATCH 1/4] f2fs: delete f2fs_get_new_segment() declaration Chao Yu
  2024-02-22 12:18 ` [PATCH 2/4] f2fs: fix to don't call f2fs_stop_checkpoint in spinlock coverage Chao Yu
@ 2024-02-22 12:18 ` Chao Yu
  2024-02-26  7:46   ` Chao Yu
  2024-02-22 12:18 ` [PATCH 4/4] f2fs: introduce FAULT_NO_SEGMENT Chao Yu
  2024-02-28 22:50 ` [f2fs-dev] [PATCH 1/4] f2fs: delete f2fs_get_new_segment() declaration patchwork-bot+f2fs
  3 siblings, 1 reply; 9+ messages in thread
From: Chao Yu @ 2024-02-22 12:18 UTC (permalink / raw)
  To: jaegeuk; +Cc: linux-f2fs-devel, linux-kernel, Chao Yu

If CONFIG_F2FS_CHECK_FS is off, and for very rare corner case that
we run out of free segment, we should not panic kernel, instead,
let's handle such error correctly in its caller.

Signed-off-by: Chao Yu <chao@kernel.org>
---
 fs/f2fs/data.c    |  7 +++++--
 fs/f2fs/f2fs.h    |  2 +-
 fs/f2fs/file.c    |  7 ++++++-
 fs/f2fs/gc.c      |  7 ++++++-
 fs/f2fs/segment.c | 46 +++++++++++++++++++++++++++++++++++++++-------
 5 files changed, 57 insertions(+), 12 deletions(-)

diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 0c9aa3082fcf..c21b92f18463 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -1416,8 +1416,11 @@ static int __allocate_data_block(struct dnode_of_data *dn, int seg_type)
 
 	set_summary(&sum, dn->nid, dn->ofs_in_node, ni.version);
 	old_blkaddr = dn->data_blkaddr;
-	f2fs_allocate_data_block(sbi, NULL, old_blkaddr, &dn->data_blkaddr,
-				&sum, seg_type, NULL);
+	err = f2fs_allocate_data_block(sbi, NULL, old_blkaddr,
+				&dn->data_blkaddr, &sum, seg_type, NULL);
+	if (err)
+		return err;
+
 	if (GET_SEGNO(sbi, old_blkaddr) != NULL_SEGNO)
 		f2fs_invalidate_internal_cache(sbi, old_blkaddr);
 
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index fbbe9a0a4221..6390c3d551cb 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -3726,7 +3726,7 @@ void f2fs_replace_block(struct f2fs_sb_info *sbi, struct dnode_of_data *dn,
 			block_t old_addr, block_t new_addr,
 			unsigned char version, bool recover_curseg,
 			bool recover_newaddr);
-void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
+int f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
 			block_t old_blkaddr, block_t *new_blkaddr,
 			struct f2fs_summary *sum, int type,
 			struct f2fs_io_info *fio);
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 088d0e79fbbc..d6ec744f1545 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -2262,8 +2262,11 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg)
 	case F2FS_GOING_DOWN_METASYNC:
 		/* do checkpoint only */
 		ret = f2fs_sync_fs(sb, 1);
-		if (ret)
+		if (ret) {
+			if (ret == -EIO)
+				ret = 0;
 			goto out;
+		}
 		f2fs_stop_checkpoint(sbi, false, STOP_CP_REASON_SHUTDOWN);
 		break;
 	case F2FS_GOING_DOWN_NOSYNC:
@@ -2279,6 +2282,8 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg)
 		set_sbi_flag(sbi, SBI_IS_DIRTY);
 		/* do checkpoint only */
 		ret = f2fs_sync_fs(sb, 1);
+		if (ret == -EIO)
+			ret = 0;
 		goto out;
 	default:
 		ret = -EINVAL;
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index 6d160d50e14e..42e75e9b8b6b 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -1358,8 +1358,13 @@ static int move_data_block(struct inode *inode, block_t bidx,
 	set_summary(&sum, dn.nid, dn.ofs_in_node, ni.version);
 
 	/* allocate block address */
-	f2fs_allocate_data_block(fio.sbi, NULL, fio.old_blkaddr, &newaddr,
+	err = f2fs_allocate_data_block(fio.sbi, NULL, fio.old_blkaddr, &newaddr,
 				&sum, type, NULL);
+	if (err) {
+		f2fs_put_page(mpage, 1);
+		/* filesystem should shutdown, no need to recovery block */
+		goto up_out;
+	}
 
 	fio.encrypted_page = f2fs_pagecache_get_page(META_MAPPING(fio.sbi),
 				newaddr, FGP_LOCK | FGP_CREAT, GFP_NOFS);
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index 8edc42071e6f..71f523431e87 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -400,6 +400,9 @@ int f2fs_commit_atomic_write(struct inode *inode)
  */
 void f2fs_balance_fs(struct f2fs_sb_info *sbi, bool need)
 {
+	if (f2fs_cp_error(sbi))
+		return;
+
 	if (time_to_inject(sbi, FAULT_CHECKPOINT))
 		f2fs_stop_checkpoint(sbi, false, STOP_CP_REASON_FAULT_INJECT);
 
@@ -2636,7 +2639,7 @@ static int is_next_segment_free(struct f2fs_sb_info *sbi,
  * Find a new segment from the free segments bitmap to right order
  * This function should be returned with success, otherwise BUG
  */
-static void get_new_segment(struct f2fs_sb_info *sbi,
+static int get_new_segment(struct f2fs_sb_info *sbi,
 			unsigned int *newseg, bool new_sec, bool pinning)
 {
 	struct free_segmap_info *free_i = FREE_I(sbi);
@@ -2711,6 +2714,7 @@ static void get_new_segment(struct f2fs_sb_info *sbi,
 		f2fs_stop_checkpoint(sbi, false, STOP_CP_REASON_NO_SEGMENT);
 		f2fs_bug_on(sbi, 1);
 	}
+	return ret;
 }
 
 static void reset_curseg(struct f2fs_sb_info *sbi, int type, int modified)
@@ -2719,6 +2723,10 @@ static void reset_curseg(struct f2fs_sb_info *sbi, int type, int modified)
 	struct summary_footer *sum_footer;
 	unsigned short seg_type = curseg->seg_type;
 
+	/* only happen when get_new_segment() fails */
+	if (curseg->next_segno == NULL_SEGNO)
+		return;
+
 	curseg->inited = true;
 	curseg->segno = curseg->next_segno;
 	curseg->zone = GET_ZONE_FROM_SEG(sbi, curseg->segno);
@@ -2783,7 +2791,10 @@ static int new_curseg(struct f2fs_sb_info *sbi, int type, bool new_sec)
 		write_sum_page(sbi, curseg->sum_blk, GET_SUM_BLOCK(sbi, segno));
 
 	segno = __get_next_segno(sbi, type);
-	get_new_segment(sbi, &segno, new_sec, pinning);
+	if (get_new_segment(sbi, &segno, new_sec, pinning)) {
+		curseg->segno = NULL_SEGNO;
+		return -ENOSPC;
+	}
 	if (new_sec && pinning &&
 	    !f2fs_valid_pinned_area(sbi, START_BLOCK(sbi, segno))) {
 		__set_free(sbi, segno);
@@ -3425,7 +3436,7 @@ static void f2fs_randomize_chunk(struct f2fs_sb_info *sbi,
 		get_random_u32_inclusive(1, sbi->max_fragment_hole);
 }
 
-void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
+int f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
 		block_t old_blkaddr, block_t *new_blkaddr,
 		struct f2fs_summary *sum, int type,
 		struct f2fs_io_info *fio)
@@ -3442,6 +3453,9 @@ void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
 	mutex_lock(&curseg->curseg_mutex);
 	down_write(&sit_i->sentry_lock);
 
+	if (curseg->segno == NULL_SEGNO)
+		goto out_err;
+
 	if (from_gc) {
 		f2fs_bug_on(sbi, GET_SEGNO(sbi, old_blkaddr) == NULL_SEGNO);
 		se = get_seg_entry(sbi, GET_SEGNO(sbi, old_blkaddr));
@@ -3500,6 +3514,9 @@ void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
 				change_curseg(sbi, type);
 			stat_inc_seg_type(sbi, curseg);
 		}
+
+		if (curseg->segno == NULL_SEGNO)
+			goto out_err;
 	}
 
 skip_new_segment:
@@ -3534,8 +3551,15 @@ void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
 	}
 
 	mutex_unlock(&curseg->curseg_mutex);
-
 	f2fs_up_read(&SM_I(sbi)->curseg_lock);
+	return 0;
+out_err:
+	*new_blkaddr = NULL_ADDR;
+	up_write(&sit_i->sentry_lock);
+	mutex_unlock(&curseg->curseg_mutex);
+	f2fs_up_read(&SM_I(sbi)->curseg_lock);
+	return -ENOSPC;
+
 }
 
 void f2fs_update_device_state(struct f2fs_sb_info *sbi, nid_t ino,
@@ -3573,8 +3597,16 @@ static void do_write_page(struct f2fs_summary *sum, struct f2fs_io_info *fio)
 	if (keep_order)
 		f2fs_down_read(&fio->sbi->io_order_lock);
 
-	f2fs_allocate_data_block(fio->sbi, fio->page, fio->old_blkaddr,
-			&fio->new_blkaddr, sum, type, fio);
+	if (f2fs_allocate_data_block(fio->sbi, fio->page, fio->old_blkaddr,
+			&fio->new_blkaddr, sum, type, fio)) {
+		if (fscrypt_inode_uses_fs_layer_crypto(fio->page->mapping->host))
+			fscrypt_finalize_bounce_page(&fio->encrypted_page);
+		if (PageWriteback(fio->page))
+			end_page_writeback(fio->page);
+		if (f2fs_in_warm_node_list(fio->sbi, fio->page))
+			f2fs_del_fsync_node_entry(fio->sbi, fio->page);
+		goto out;
+	}
 	if (GET_SEGNO(fio->sbi, fio->old_blkaddr) != NULL_SEGNO)
 		f2fs_invalidate_internal_cache(fio->sbi, fio->old_blkaddr);
 
@@ -3582,7 +3614,7 @@ static void do_write_page(struct f2fs_summary *sum, struct f2fs_io_info *fio)
 	f2fs_submit_page_write(fio);
 
 	f2fs_update_device_state(fio->sbi, fio->ino, fio->new_blkaddr, 1);
-
+out:
 	if (keep_order)
 		f2fs_up_read(&fio->sbi->io_order_lock);
 }
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 4/4] f2fs: introduce FAULT_NO_SEGMENT
  2024-02-22 12:18 [PATCH 1/4] f2fs: delete f2fs_get_new_segment() declaration Chao Yu
  2024-02-22 12:18 ` [PATCH 2/4] f2fs: fix to don't call f2fs_stop_checkpoint in spinlock coverage Chao Yu
  2024-02-22 12:18 ` [PATCH 3/4] f2fs: fix to handle segment allocation failure correctly Chao Yu
@ 2024-02-22 12:18 ` Chao Yu
  2024-02-28 22:50 ` [f2fs-dev] [PATCH 1/4] f2fs: delete f2fs_get_new_segment() declaration patchwork-bot+f2fs
  3 siblings, 0 replies; 9+ messages in thread
From: Chao Yu @ 2024-02-22 12:18 UTC (permalink / raw)
  To: jaegeuk; +Cc: linux-f2fs-devel, linux-kernel, Chao Yu

Use it to simulate no free segment case during block allocation.

Signed-off-by: Chao Yu <chao@kernel.org>
---
 Documentation/ABI/testing/sysfs-fs-f2fs | 1 +
 Documentation/filesystems/f2fs.rst      | 1 +
 fs/f2fs/f2fs.h                          | 1 +
 fs/f2fs/segment.c                       | 5 +++++
 fs/f2fs/super.c                         | 1 +
 5 files changed, 9 insertions(+)

diff --git a/Documentation/ABI/testing/sysfs-fs-f2fs b/Documentation/ABI/testing/sysfs-fs-f2fs
index 15044d7d4977..96b54259a02a 100644
--- a/Documentation/ABI/testing/sysfs-fs-f2fs
+++ b/Documentation/ABI/testing/sysfs-fs-f2fs
@@ -718,6 +718,7 @@ Description:	Support configuring fault injection type, should be
 		FAULT_LOCK_OP                    0x000020000
 		FAULT_BLKADDR_VALIDITY           0x000040000
 		FAULT_BLKADDR_CONSISTENCE        0x000080000
+		FAULT_NO_SEGMENT                 0x000100000
 		===========================      ===========
 
 What:		/sys/fs/f2fs/<disk>/discard_io_aware_gran
diff --git a/Documentation/filesystems/f2fs.rst b/Documentation/filesystems/f2fs.rst
index 1b3b73aa3ab9..bc074b8eedbb 100644
--- a/Documentation/filesystems/f2fs.rst
+++ b/Documentation/filesystems/f2fs.rst
@@ -205,6 +205,7 @@ fault_type=%d		 Support configuring fault injection type, should be
 			 FAULT_LOCK_OP                    0x000020000
 			 FAULT_BLKADDR_VALIDITY           0x000040000
 			 FAULT_BLKADDR_CONSISTENCE        0x000080000
+			 FAULT_NO_SEGMENT                 0x000100000
 			 ===========================      ===========
 mode=%s			 Control block allocation mode which supports "adaptive"
 			 and "lfs". In "lfs" mode, there should be no random
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 6390c3d551cb..fdc9a4dc981d 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -62,6 +62,7 @@ enum {
 	FAULT_LOCK_OP,
 	FAULT_BLKADDR_VALIDITY,
 	FAULT_BLKADDR_CONSISTENCE,
+	FAULT_NO_SEGMENT,
 	FAULT_MAX,
 };
 
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index 71f523431e87..8ad88d5d4d1d 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -2653,6 +2653,11 @@ static int get_new_segment(struct f2fs_sb_info *sbi,
 
 	spin_lock(&free_i->segmap_lock);
 
+	if (time_to_inject(sbi, FAULT_NO_SEGMENT)) {
+		ret = -ENOSPC;
+		goto out_unlock;
+	}
+
 	if (!new_sec && ((*newseg + 1) % SEGS_PER_SEC(sbi))) {
 		segno = find_next_zero_bit(free_i->free_segmap,
 			GET_SEG_FROM_SEC(sbi, hint + 1), *newseg + 1);
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index bb056700b459..dc4fb9a661f2 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -63,6 +63,7 @@ const char *f2fs_fault_name[FAULT_MAX] = {
 	[FAULT_LOCK_OP]			= "lock_op",
 	[FAULT_BLKADDR_VALIDITY]	= "invalid blkaddr",
 	[FAULT_BLKADDR_CONSISTENCE]	= "inconsistent blkaddr",
+	[FAULT_NO_SEGMENT]		= "no free segment",
 };
 
 void f2fs_build_fault_attr(struct f2fs_sb_info *sbi, unsigned int rate,
-- 
2.40.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH 3/4] f2fs: fix to handle segment allocation failure correctly
  2024-02-22 12:18 ` [PATCH 3/4] f2fs: fix to handle segment allocation failure correctly Chao Yu
@ 2024-02-26  7:46   ` Chao Yu
  2024-02-26 10:28     ` Zhiguo Niu
  0 siblings, 1 reply; 9+ messages in thread
From: Chao Yu @ 2024-02-26  7:46 UTC (permalink / raw)
  To: Zhiguo Niu, Zhiguo Niu; +Cc: linux-f2fs-devel, linux-kernel, jaegeuk

Loop to Zhiguo,

On 2024/2/22 20:18, Chao Yu wrote:
> If CONFIG_F2FS_CHECK_FS is off, and for very rare corner case that
> we run out of free segment, we should not panic kernel, instead,
> let's handle such error correctly in its caller.
> 
> Signed-off-by: Chao Yu <chao@kernel.org>
> ---
>   fs/f2fs/data.c    |  7 +++++--
>   fs/f2fs/f2fs.h    |  2 +-
>   fs/f2fs/file.c    |  7 ++++++-
>   fs/f2fs/gc.c      |  7 ++++++-
>   fs/f2fs/segment.c | 46 +++++++++++++++++++++++++++++++++++++++-------
>   5 files changed, 57 insertions(+), 12 deletions(-)
> 
> diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
> index 0c9aa3082fcf..c21b92f18463 100644
> --- a/fs/f2fs/data.c
> +++ b/fs/f2fs/data.c
> @@ -1416,8 +1416,11 @@ static int __allocate_data_block(struct dnode_of_data *dn, int seg_type)
>   
>   	set_summary(&sum, dn->nid, dn->ofs_in_node, ni.version);
>   	old_blkaddr = dn->data_blkaddr;
> -	f2fs_allocate_data_block(sbi, NULL, old_blkaddr, &dn->data_blkaddr,
> -				&sum, seg_type, NULL);
> +	err = f2fs_allocate_data_block(sbi, NULL, old_blkaddr,
> +				&dn->data_blkaddr, &sum, seg_type, NULL);
> +	if (err)
> +		return err;
> +
>   	if (GET_SEGNO(sbi, old_blkaddr) != NULL_SEGNO)
>   		f2fs_invalidate_internal_cache(sbi, old_blkaddr);
>   
> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> index fbbe9a0a4221..6390c3d551cb 100644
> --- a/fs/f2fs/f2fs.h
> +++ b/fs/f2fs/f2fs.h
> @@ -3726,7 +3726,7 @@ void f2fs_replace_block(struct f2fs_sb_info *sbi, struct dnode_of_data *dn,
>   			block_t old_addr, block_t new_addr,
>   			unsigned char version, bool recover_curseg,
>   			bool recover_newaddr);
> -void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
> +int f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
>   			block_t old_blkaddr, block_t *new_blkaddr,
>   			struct f2fs_summary *sum, int type,
>   			struct f2fs_io_info *fio);
> diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
> index 088d0e79fbbc..d6ec744f1545 100644
> --- a/fs/f2fs/file.c
> +++ b/fs/f2fs/file.c
> @@ -2262,8 +2262,11 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg)
>   	case F2FS_GOING_DOWN_METASYNC:
>   		/* do checkpoint only */
>   		ret = f2fs_sync_fs(sb, 1);
> -		if (ret)
> +		if (ret) {
> +			if (ret == -EIO)
> +				ret = 0;
>   			goto out;
> +		}
>   		f2fs_stop_checkpoint(sbi, false, STOP_CP_REASON_SHUTDOWN);
>   		break;
>   	case F2FS_GOING_DOWN_NOSYNC:
> @@ -2279,6 +2282,8 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg)
>   		set_sbi_flag(sbi, SBI_IS_DIRTY);
>   		/* do checkpoint only */
>   		ret = f2fs_sync_fs(sb, 1);
> +		if (ret == -EIO)
> +			ret = 0;
>   		goto out;
>   	default:
>   		ret = -EINVAL;
> diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
> index 6d160d50e14e..42e75e9b8b6b 100644
> --- a/fs/f2fs/gc.c
> +++ b/fs/f2fs/gc.c
> @@ -1358,8 +1358,13 @@ static int move_data_block(struct inode *inode, block_t bidx,
>   	set_summary(&sum, dn.nid, dn.ofs_in_node, ni.version);
>   
>   	/* allocate block address */
> -	f2fs_allocate_data_block(fio.sbi, NULL, fio.old_blkaddr, &newaddr,
> +	err = f2fs_allocate_data_block(fio.sbi, NULL, fio.old_blkaddr, &newaddr,
>   				&sum, type, NULL);
> +	if (err) {
> +		f2fs_put_page(mpage, 1);
> +		/* filesystem should shutdown, no need to recovery block */
> +		goto up_out;
> +	}
>   
>   	fio.encrypted_page = f2fs_pagecache_get_page(META_MAPPING(fio.sbi),
>   				newaddr, FGP_LOCK | FGP_CREAT, GFP_NOFS);
> diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
> index 8edc42071e6f..71f523431e87 100644
> --- a/fs/f2fs/segment.c
> +++ b/fs/f2fs/segment.c
> @@ -400,6 +400,9 @@ int f2fs_commit_atomic_write(struct inode *inode)
>    */
>   void f2fs_balance_fs(struct f2fs_sb_info *sbi, bool need)
>   {
> +	if (f2fs_cp_error(sbi))
> +		return;
> +
>   	if (time_to_inject(sbi, FAULT_CHECKPOINT))
>   		f2fs_stop_checkpoint(sbi, false, STOP_CP_REASON_FAULT_INJECT);
>   
> @@ -2636,7 +2639,7 @@ static int is_next_segment_free(struct f2fs_sb_info *sbi,
>    * Find a new segment from the free segments bitmap to right order
>    * This function should be returned with success, otherwise BUG
>    */
> -static void get_new_segment(struct f2fs_sb_info *sbi,
> +static int get_new_segment(struct f2fs_sb_info *sbi,
>   			unsigned int *newseg, bool new_sec, bool pinning)
>   {
>   	struct free_segmap_info *free_i = FREE_I(sbi);
> @@ -2711,6 +2714,7 @@ static void get_new_segment(struct f2fs_sb_info *sbi,
>   		f2fs_stop_checkpoint(sbi, false, STOP_CP_REASON_NO_SEGMENT);
>   		f2fs_bug_on(sbi, 1);
>   	}
> +	return ret;
>   }
>   
>   static void reset_curseg(struct f2fs_sb_info *sbi, int type, int modified)
> @@ -2719,6 +2723,10 @@ static void reset_curseg(struct f2fs_sb_info *sbi, int type, int modified)
>   	struct summary_footer *sum_footer;
>   	unsigned short seg_type = curseg->seg_type;
>   
> +	/* only happen when get_new_segment() fails */
> +	if (curseg->next_segno == NULL_SEGNO)
> +		return;
> +
>   	curseg->inited = true;
>   	curseg->segno = curseg->next_segno;
>   	curseg->zone = GET_ZONE_FROM_SEG(sbi, curseg->segno);
> @@ -2783,7 +2791,10 @@ static int new_curseg(struct f2fs_sb_info *sbi, int type, bool new_sec)
>   		write_sum_page(sbi, curseg->sum_blk, GET_SUM_BLOCK(sbi, segno));
>   
>   	segno = __get_next_segno(sbi, type);
> -	get_new_segment(sbi, &segno, new_sec, pinning);
> +	if (get_new_segment(sbi, &segno, new_sec, pinning)) {
> +		curseg->segno = NULL_SEGNO;
> +		return -ENOSPC;
> +	}
>   	if (new_sec && pinning &&
>   	    !f2fs_valid_pinned_area(sbi, START_BLOCK(sbi, segno))) {
>   		__set_free(sbi, segno);
> @@ -3425,7 +3436,7 @@ static void f2fs_randomize_chunk(struct f2fs_sb_info *sbi,
>   		get_random_u32_inclusive(1, sbi->max_fragment_hole);
>   }
>   
> -void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
> +int f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
>   		block_t old_blkaddr, block_t *new_blkaddr,
>   		struct f2fs_summary *sum, int type,
>   		struct f2fs_io_info *fio)
> @@ -3442,6 +3453,9 @@ void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
>   	mutex_lock(&curseg->curseg_mutex);
>   	down_write(&sit_i->sentry_lock);
>   
> +	if (curseg->segno == NULL_SEGNO)
> +		goto out_err;
> +
>   	if (from_gc) {
>   		f2fs_bug_on(sbi, GET_SEGNO(sbi, old_blkaddr) == NULL_SEGNO);
>   		se = get_seg_entry(sbi, GET_SEGNO(sbi, old_blkaddr));
> @@ -3500,6 +3514,9 @@ void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
>   				change_curseg(sbi, type);
>   			stat_inc_seg_type(sbi, curseg);
>   		}
> +
> +		if (curseg->segno == NULL_SEGNO)
> +			goto out_err;
>   	}
>   
>   skip_new_segment:
> @@ -3534,8 +3551,15 @@ void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
>   	}
>   
>   	mutex_unlock(&curseg->curseg_mutex);
> -
>   	f2fs_up_read(&SM_I(sbi)->curseg_lock);
> +	return 0;
> +out_err:
> +	*new_blkaddr = NULL_ADDR;
> +	up_write(&sit_i->sentry_lock);
> +	mutex_unlock(&curseg->curseg_mutex);
> +	f2fs_up_read(&SM_I(sbi)->curseg_lock);
> +	return -ENOSPC;
> +
>   }
>   
>   void f2fs_update_device_state(struct f2fs_sb_info *sbi, nid_t ino,
> @@ -3573,8 +3597,16 @@ static void do_write_page(struct f2fs_summary *sum, struct f2fs_io_info *fio)
>   	if (keep_order)
>   		f2fs_down_read(&fio->sbi->io_order_lock);
>   
> -	f2fs_allocate_data_block(fio->sbi, fio->page, fio->old_blkaddr,
> -			&fio->new_blkaddr, sum, type, fio);
> +	if (f2fs_allocate_data_block(fio->sbi, fio->page, fio->old_blkaddr,
> +			&fio->new_blkaddr, sum, type, fio)) {
> +		if (fscrypt_inode_uses_fs_layer_crypto(fio->page->mapping->host))
> +			fscrypt_finalize_bounce_page(&fio->encrypted_page);
> +		if (PageWriteback(fio->page))
> +			end_page_writeback(fio->page);
> +		if (f2fs_in_warm_node_list(fio->sbi, fio->page))
> +			f2fs_del_fsync_node_entry(fio->sbi, fio->page);
> +		goto out;
> +	}
>   	if (GET_SEGNO(fio->sbi, fio->old_blkaddr) != NULL_SEGNO)
>   		f2fs_invalidate_internal_cache(fio->sbi, fio->old_blkaddr);
>   
> @@ -3582,7 +3614,7 @@ static void do_write_page(struct f2fs_summary *sum, struct f2fs_io_info *fio)
>   	f2fs_submit_page_write(fio);
>   
>   	f2fs_update_device_state(fio->sbi, fio->ino, fio->new_blkaddr, 1);
> -
> +out:
>   	if (keep_order)
>   		f2fs_up_read(&fio->sbi->io_order_lock);
>   }

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 3/4] f2fs: fix to handle segment allocation failure correctly
  2024-02-26  7:46   ` Chao Yu
@ 2024-02-26 10:28     ` Zhiguo Niu
  0 siblings, 0 replies; 9+ messages in thread
From: Zhiguo Niu @ 2024-02-26 10:28 UTC (permalink / raw)
  To: Chao Yu; +Cc: Zhiguo Niu, linux-f2fs-devel, linux-kernel, jaegeuk

On Mon, Feb 26, 2024 at 3:46 PM Chao Yu <chao@kernel.org> wrote:
>
> Loop to Zhiguo,
>
> On 2024/2/22 20:18, Chao Yu wrote:
> > If CONFIG_F2FS_CHECK_FS is off, and for very rare corner case that
> > we run out of free segment, we should not panic kernel, instead,
> > let's handle such error correctly in its caller.
> >
> > Signed-off-by: Chao Yu <chao@kernel.org>
Tested-by: Zhiguo Niu <zhiguo.niu@unisoc.com>
Thanks!
> > ---
> >   fs/f2fs/data.c    |  7 +++++--
> >   fs/f2fs/f2fs.h    |  2 +-
> >   fs/f2fs/file.c    |  7 ++++++-
> >   fs/f2fs/gc.c      |  7 ++++++-
> >   fs/f2fs/segment.c | 46 +++++++++++++++++++++++++++++++++++++++-------
> >   5 files changed, 57 insertions(+), 12 deletions(-)
> >
> > diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
> > index 0c9aa3082fcf..c21b92f18463 100644
> > --- a/fs/f2fs/data.c
> > +++ b/fs/f2fs/data.c
> > @@ -1416,8 +1416,11 @@ static int __allocate_data_block(struct dnode_of_data *dn, int seg_type)
> >
> >       set_summary(&sum, dn->nid, dn->ofs_in_node, ni.version);
> >       old_blkaddr = dn->data_blkaddr;
> > -     f2fs_allocate_data_block(sbi, NULL, old_blkaddr, &dn->data_blkaddr,
> > -                             &sum, seg_type, NULL);
> > +     err = f2fs_allocate_data_block(sbi, NULL, old_blkaddr,
> > +                             &dn->data_blkaddr, &sum, seg_type, NULL);
> > +     if (err)
> > +             return err;
> > +
> >       if (GET_SEGNO(sbi, old_blkaddr) != NULL_SEGNO)
> >               f2fs_invalidate_internal_cache(sbi, old_blkaddr);
> >
> > diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
> > index fbbe9a0a4221..6390c3d551cb 100644
> > --- a/fs/f2fs/f2fs.h
> > +++ b/fs/f2fs/f2fs.h
> > @@ -3726,7 +3726,7 @@ void f2fs_replace_block(struct f2fs_sb_info *sbi, struct dnode_of_data *dn,
> >                       block_t old_addr, block_t new_addr,
> >                       unsigned char version, bool recover_curseg,
> >                       bool recover_newaddr);
> > -void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
> > +int f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
> >                       block_t old_blkaddr, block_t *new_blkaddr,
> >                       struct f2fs_summary *sum, int type,
> >                       struct f2fs_io_info *fio);
> > diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
> > index 088d0e79fbbc..d6ec744f1545 100644
> > --- a/fs/f2fs/file.c
> > +++ b/fs/f2fs/file.c
> > @@ -2262,8 +2262,11 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg)
> >       case F2FS_GOING_DOWN_METASYNC:
> >               /* do checkpoint only */
> >               ret = f2fs_sync_fs(sb, 1);
> > -             if (ret)
> > +             if (ret) {
> > +                     if (ret == -EIO)
> > +                             ret = 0;
> >                       goto out;
> > +             }
> >               f2fs_stop_checkpoint(sbi, false, STOP_CP_REASON_SHUTDOWN);
> >               break;
> >       case F2FS_GOING_DOWN_NOSYNC:
> > @@ -2279,6 +2282,8 @@ static int f2fs_ioc_shutdown(struct file *filp, unsigned long arg)
> >               set_sbi_flag(sbi, SBI_IS_DIRTY);
> >               /* do checkpoint only */
> >               ret = f2fs_sync_fs(sb, 1);
> > +             if (ret == -EIO)
> > +                     ret = 0;
> >               goto out;
> >       default:
> >               ret = -EINVAL;
> > diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
> > index 6d160d50e14e..42e75e9b8b6b 100644
> > --- a/fs/f2fs/gc.c
> > +++ b/fs/f2fs/gc.c
> > @@ -1358,8 +1358,13 @@ static int move_data_block(struct inode *inode, block_t bidx,
> >       set_summary(&sum, dn.nid, dn.ofs_in_node, ni.version);
> >
> >       /* allocate block address */
> > -     f2fs_allocate_data_block(fio.sbi, NULL, fio.old_blkaddr, &newaddr,
> > +     err = f2fs_allocate_data_block(fio.sbi, NULL, fio.old_blkaddr, &newaddr,
> >                               &sum, type, NULL);
> > +     if (err) {
> > +             f2fs_put_page(mpage, 1);
> > +             /* filesystem should shutdown, no need to recovery block */
> > +             goto up_out;
> > +     }
> >
> >       fio.encrypted_page = f2fs_pagecache_get_page(META_MAPPING(fio.sbi),
> >                               newaddr, FGP_LOCK | FGP_CREAT, GFP_NOFS);
> > diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
> > index 8edc42071e6f..71f523431e87 100644
> > --- a/fs/f2fs/segment.c
> > +++ b/fs/f2fs/segment.c
> > @@ -400,6 +400,9 @@ int f2fs_commit_atomic_write(struct inode *inode)
> >    */
> >   void f2fs_balance_fs(struct f2fs_sb_info *sbi, bool need)
> >   {
> > +     if (f2fs_cp_error(sbi))
> > +             return;
> > +
> >       if (time_to_inject(sbi, FAULT_CHECKPOINT))
> >               f2fs_stop_checkpoint(sbi, false, STOP_CP_REASON_FAULT_INJECT);
> >
> > @@ -2636,7 +2639,7 @@ static int is_next_segment_free(struct f2fs_sb_info *sbi,
> >    * Find a new segment from the free segments bitmap to right order
> >    * This function should be returned with success, otherwise BUG
> >    */
> > -static void get_new_segment(struct f2fs_sb_info *sbi,
> > +static int get_new_segment(struct f2fs_sb_info *sbi,
> >                       unsigned int *newseg, bool new_sec, bool pinning)
> >   {
> >       struct free_segmap_info *free_i = FREE_I(sbi);
> > @@ -2711,6 +2714,7 @@ static void get_new_segment(struct f2fs_sb_info *sbi,
> >               f2fs_stop_checkpoint(sbi, false, STOP_CP_REASON_NO_SEGMENT);
> >               f2fs_bug_on(sbi, 1);
> >       }
> > +     return ret;
> >   }
> >
> >   static void reset_curseg(struct f2fs_sb_info *sbi, int type, int modified)
> > @@ -2719,6 +2723,10 @@ static void reset_curseg(struct f2fs_sb_info *sbi, int type, int modified)
> >       struct summary_footer *sum_footer;
> >       unsigned short seg_type = curseg->seg_type;
> >
> > +     /* only happen when get_new_segment() fails */
> > +     if (curseg->next_segno == NULL_SEGNO)
> > +             return;
> > +
> >       curseg->inited = true;
> >       curseg->segno = curseg->next_segno;
> >       curseg->zone = GET_ZONE_FROM_SEG(sbi, curseg->segno);
> > @@ -2783,7 +2791,10 @@ static int new_curseg(struct f2fs_sb_info *sbi, int type, bool new_sec)
> >               write_sum_page(sbi, curseg->sum_blk, GET_SUM_BLOCK(sbi, segno));
> >
> >       segno = __get_next_segno(sbi, type);
> > -     get_new_segment(sbi, &segno, new_sec, pinning);
> > +     if (get_new_segment(sbi, &segno, new_sec, pinning)) {
> > +             curseg->segno = NULL_SEGNO;
> > +             return -ENOSPC;
> > +     }
> >       if (new_sec && pinning &&
> >           !f2fs_valid_pinned_area(sbi, START_BLOCK(sbi, segno))) {
> >               __set_free(sbi, segno);
> > @@ -3425,7 +3436,7 @@ static void f2fs_randomize_chunk(struct f2fs_sb_info *sbi,
> >               get_random_u32_inclusive(1, sbi->max_fragment_hole);
> >   }
> >
> > -void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
> > +int f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
> >               block_t old_blkaddr, block_t *new_blkaddr,
> >               struct f2fs_summary *sum, int type,
> >               struct f2fs_io_info *fio)
> > @@ -3442,6 +3453,9 @@ void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
> >       mutex_lock(&curseg->curseg_mutex);
> >       down_write(&sit_i->sentry_lock);
> >
> > +     if (curseg->segno == NULL_SEGNO)
> > +             goto out_err;
> > +
> >       if (from_gc) {
> >               f2fs_bug_on(sbi, GET_SEGNO(sbi, old_blkaddr) == NULL_SEGNO);
> >               se = get_seg_entry(sbi, GET_SEGNO(sbi, old_blkaddr));
> > @@ -3500,6 +3514,9 @@ void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
> >                               change_curseg(sbi, type);
> >                       stat_inc_seg_type(sbi, curseg);
> >               }
> > +
> > +             if (curseg->segno == NULL_SEGNO)
> > +                     goto out_err;
> >       }
> >
> >   skip_new_segment:
> > @@ -3534,8 +3551,15 @@ void f2fs_allocate_data_block(struct f2fs_sb_info *sbi, struct page *page,
> >       }
> >
> >       mutex_unlock(&curseg->curseg_mutex);
> > -
> >       f2fs_up_read(&SM_I(sbi)->curseg_lock);
> > +     return 0;
> > +out_err:
> > +     *new_blkaddr = NULL_ADDR;
> > +     up_write(&sit_i->sentry_lock);
> > +     mutex_unlock(&curseg->curseg_mutex);
> > +     f2fs_up_read(&SM_I(sbi)->curseg_lock);
> > +     return -ENOSPC;
> > +
> >   }
> >
> >   void f2fs_update_device_state(struct f2fs_sb_info *sbi, nid_t ino,
> > @@ -3573,8 +3597,16 @@ static void do_write_page(struct f2fs_summary *sum, struct f2fs_io_info *fio)
> >       if (keep_order)
> >               f2fs_down_read(&fio->sbi->io_order_lock);
> >
> > -     f2fs_allocate_data_block(fio->sbi, fio->page, fio->old_blkaddr,
> > -                     &fio->new_blkaddr, sum, type, fio);
> > +     if (f2fs_allocate_data_block(fio->sbi, fio->page, fio->old_blkaddr,
> > +                     &fio->new_blkaddr, sum, type, fio)) {
> > +             if (fscrypt_inode_uses_fs_layer_crypto(fio->page->mapping->host))
> > +                     fscrypt_finalize_bounce_page(&fio->encrypted_page);
> > +             if (PageWriteback(fio->page))
> > +                     end_page_writeback(fio->page);
> > +             if (f2fs_in_warm_node_list(fio->sbi, fio->page))
> > +                     f2fs_del_fsync_node_entry(fio->sbi, fio->page);
> > +             goto out;
> > +     }
> >       if (GET_SEGNO(fio->sbi, fio->old_blkaddr) != NULL_SEGNO)
> >               f2fs_invalidate_internal_cache(fio->sbi, fio->old_blkaddr);
> >
> > @@ -3582,7 +3614,7 @@ static void do_write_page(struct f2fs_summary *sum, struct f2fs_io_info *fio)
> >       f2fs_submit_page_write(fio);
> >
> >       f2fs_update_device_state(fio->sbi, fio->ino, fio->new_blkaddr, 1);
> > -
> > +out:
> >       if (keep_order)
> >               f2fs_up_read(&fio->sbi->io_order_lock);
> >   }

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 2/4] f2fs: fix to don't call f2fs_stop_checkpoint in spinlock coverage
  2024-02-22 12:18 ` [PATCH 2/4] f2fs: fix to don't call f2fs_stop_checkpoint in spinlock coverage Chao Yu
@ 2024-02-27 17:50   ` Jaegeuk Kim
  2024-02-28  1:23     ` Chao Yu
  0 siblings, 1 reply; 9+ messages in thread
From: Jaegeuk Kim @ 2024-02-27 17:50 UTC (permalink / raw)
  To: Chao Yu; +Cc: linux-f2fs-devel, linux-kernel

On 02/22, Chao Yu wrote:
> f2fs_stop_checkpoint(, false) is complex and it may sleep, so we should
> move it outside segmap_lock spinlock coverage in get_new_segment().

Chao, I merged this patch into

https://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs.git/commit/?h=dev-test&id=f3b576d209983b5d6e1cb130bfc8ca1f0bbcad6d

> 
> Signed-off-by: Chao Yu <chao@kernel.org>
> ---
>  fs/f2fs/segment.c | 12 +++++++++---
>  1 file changed, 9 insertions(+), 3 deletions(-)
> 
> diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
> index d0209ea77dd2..8edc42071e6f 100644
> --- a/fs/f2fs/segment.c
> +++ b/fs/f2fs/segment.c
> @@ -2646,6 +2646,7 @@ static void get_new_segment(struct f2fs_sb_info *sbi,
>  	unsigned int old_zoneno = GET_ZONE_FROM_SEG(sbi, *newseg);
>  	bool init = true;
>  	int i;
> +	int ret = 0;
>  
>  	spin_lock(&free_i->segmap_lock);
>  
> @@ -2671,9 +2672,8 @@ static void get_new_segment(struct f2fs_sb_info *sbi,
>  		secno = find_first_zero_bit(free_i->free_secmap,
>  							MAIN_SECS(sbi));
>  		if (secno >= MAIN_SECS(sbi)) {
> -			f2fs_stop_checkpoint(sbi, false,
> -				STOP_CP_REASON_NO_SEGMENT);
> -			f2fs_bug_on(sbi, 1);
> +			ret = -ENOSPC;
> +			goto out_unlock;
>  		}
>  	}
>  	segno = GET_SEG_FROM_SEC(sbi, secno);
> @@ -2704,7 +2704,13 @@ static void get_new_segment(struct f2fs_sb_info *sbi,
>  	f2fs_bug_on(sbi, test_bit(segno, free_i->free_segmap));
>  	__set_inuse(sbi, segno);
>  	*newseg = segno;
> +out_unlock:
>  	spin_unlock(&free_i->segmap_lock);
> +
> +	if (ret) {
> +		f2fs_stop_checkpoint(sbi, false, STOP_CP_REASON_NO_SEGMENT);
> +		f2fs_bug_on(sbi, 1);
> +	}
>  }
>  
>  static void reset_curseg(struct f2fs_sb_info *sbi, int type, int modified)
> -- 
> 2.40.1

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 2/4] f2fs: fix to don't call f2fs_stop_checkpoint in spinlock coverage
  2024-02-27 17:50   ` Jaegeuk Kim
@ 2024-02-28  1:23     ` Chao Yu
  0 siblings, 0 replies; 9+ messages in thread
From: Chao Yu @ 2024-02-28  1:23 UTC (permalink / raw)
  To: Jaegeuk Kim; +Cc: linux-f2fs-devel, linux-kernel

On 2024/2/28 1:50, Jaegeuk Kim wrote:
> On 02/22, Chao Yu wrote:
>> f2fs_stop_checkpoint(, false) is complex and it may sleep, so we should
>> move it outside segmap_lock spinlock coverage in get_new_segment().
> 
> Chao, I merged this patch into
> 
> https://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs.git/commit/?h=dev-test&id=f3b576d209983b5d6e1cb130bfc8ca1f0bbcad6d

It's fine to me.

Thanks,

> 
>>
>> Signed-off-by: Chao Yu <chao@kernel.org>
>> ---
>>   fs/f2fs/segment.c | 12 +++++++++---
>>   1 file changed, 9 insertions(+), 3 deletions(-)
>>
>> diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
>> index d0209ea77dd2..8edc42071e6f 100644
>> --- a/fs/f2fs/segment.c
>> +++ b/fs/f2fs/segment.c
>> @@ -2646,6 +2646,7 @@ static void get_new_segment(struct f2fs_sb_info *sbi,
>>   	unsigned int old_zoneno = GET_ZONE_FROM_SEG(sbi, *newseg);
>>   	bool init = true;
>>   	int i;
>> +	int ret = 0;
>>   
>>   	spin_lock(&free_i->segmap_lock);
>>   
>> @@ -2671,9 +2672,8 @@ static void get_new_segment(struct f2fs_sb_info *sbi,
>>   		secno = find_first_zero_bit(free_i->free_secmap,
>>   							MAIN_SECS(sbi));
>>   		if (secno >= MAIN_SECS(sbi)) {
>> -			f2fs_stop_checkpoint(sbi, false,
>> -				STOP_CP_REASON_NO_SEGMENT);
>> -			f2fs_bug_on(sbi, 1);
>> +			ret = -ENOSPC;
>> +			goto out_unlock;
>>   		}
>>   	}
>>   	segno = GET_SEG_FROM_SEC(sbi, secno);
>> @@ -2704,7 +2704,13 @@ static void get_new_segment(struct f2fs_sb_info *sbi,
>>   	f2fs_bug_on(sbi, test_bit(segno, free_i->free_segmap));
>>   	__set_inuse(sbi, segno);
>>   	*newseg = segno;
>> +out_unlock:
>>   	spin_unlock(&free_i->segmap_lock);
>> +
>> +	if (ret) {
>> +		f2fs_stop_checkpoint(sbi, false, STOP_CP_REASON_NO_SEGMENT);
>> +		f2fs_bug_on(sbi, 1);
>> +	}
>>   }
>>   
>>   static void reset_curseg(struct f2fs_sb_info *sbi, int type, int modified)
>> -- 
>> 2.40.1

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [f2fs-dev] [PATCH 1/4] f2fs: delete f2fs_get_new_segment() declaration
  2024-02-22 12:18 [PATCH 1/4] f2fs: delete f2fs_get_new_segment() declaration Chao Yu
                   ` (2 preceding siblings ...)
  2024-02-22 12:18 ` [PATCH 4/4] f2fs: introduce FAULT_NO_SEGMENT Chao Yu
@ 2024-02-28 22:50 ` patchwork-bot+f2fs
  3 siblings, 0 replies; 9+ messages in thread
From: patchwork-bot+f2fs @ 2024-02-28 22:50 UTC (permalink / raw)
  To: Chao Yu; +Cc: jaegeuk, linux-kernel, linux-f2fs-devel

Hello:

This series was applied to jaegeuk/f2fs.git (dev)
by Jaegeuk Kim <jaegeuk@kernel.org>:

On Thu, 22 Feb 2024 20:18:48 +0800 you wrote:
> Commit 093749e296e2 ("f2fs: support age threshold based garbage
> collection") added this declaration, but w/ definition, delete
> it.
> 
> Signed-off-by: Chao Yu <chao@kernel.org>
> ---
>  fs/f2fs/f2fs.h | 2 --
>  1 file changed, 2 deletions(-)

Here is the summary with links:
  - [f2fs-dev,1/4] f2fs: delete f2fs_get_new_segment() declaration
    https://git.kernel.org/jaegeuk/f2fs/c/134c289f5e7d
  - [f2fs-dev,2/4] f2fs: fix to don't call f2fs_stop_checkpoint in spinlock coverage
    (no matching commit)
  - [f2fs-dev,3/4] f2fs: fix to handle segment allocation failure correctly
    https://git.kernel.org/jaegeuk/f2fs/c/6ca83e9cdc51
  - [f2fs-dev,4/4] f2fs: introduce FAULT_NO_SEGMENT
    https://git.kernel.org/jaegeuk/f2fs/c/251a769d3f50

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2024-02-28 22:50 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-02-22 12:18 [PATCH 1/4] f2fs: delete f2fs_get_new_segment() declaration Chao Yu
2024-02-22 12:18 ` [PATCH 2/4] f2fs: fix to don't call f2fs_stop_checkpoint in spinlock coverage Chao Yu
2024-02-27 17:50   ` Jaegeuk Kim
2024-02-28  1:23     ` Chao Yu
2024-02-22 12:18 ` [PATCH 3/4] f2fs: fix to handle segment allocation failure correctly Chao Yu
2024-02-26  7:46   ` Chao Yu
2024-02-26 10:28     ` Zhiguo Niu
2024-02-22 12:18 ` [PATCH 4/4] f2fs: introduce FAULT_NO_SEGMENT Chao Yu
2024-02-28 22:50 ` [f2fs-dev] [PATCH 1/4] f2fs: delete f2fs_get_new_segment() declaration patchwork-bot+f2fs

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).