linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [f2fs-dev] [PATCH v2 1/2] f2fs: avoid redundant clean nat entry move in lru list
@ 2025-07-22 14:36 wangzijie
  2025-07-22 14:36 ` [f2fs-dev] [PATCH v2 2/2] f2fs: directly add newly allocated pre-dirty nat entry to dirty set list wangzijie
  2025-07-24  6:00 ` [f2fs-dev] [PATCH v2 1/2] f2fs: avoid redundant clean nat entry move in lru list Chao Yu
  0 siblings, 2 replies; 7+ messages in thread
From: wangzijie @ 2025-07-22 14:36 UTC (permalink / raw)
  To: jaegeuk, chao
  Cc: linux-f2fs-devel, linux-kernel, bintian.wang, feng.han, wangzijie

__lookup_nat_cache follows LRU manner to move clean nat entry, when nat
entries are going to be dirty, no need to move them to tail of lru list.
Introduce a parameter 'for_dirty' to avoid it.

Signed-off-by: wangzijie <wangzijie1@honor.com>
---
v2:
- followed by Jaegeuk's suggestion to add a parameter in __lookup_nat_cache
---
 fs/f2fs/node.c | 24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
index 76aba1961..a23db6238 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -204,14 +204,14 @@ static struct nat_entry *__init_nat_entry(struct f2fs_nm_info *nm_i,
 	return ne;
 }
 
-static struct nat_entry *__lookup_nat_cache(struct f2fs_nm_info *nm_i, nid_t n)
+static struct nat_entry *__lookup_nat_cache(struct f2fs_nm_info *nm_i, nid_t n, bool for_dirty)
 {
 	struct nat_entry *ne;
 
 	ne = radix_tree_lookup(&nm_i->nat_root, n);
 
-	/* for recent accessed nat entry, move it to tail of lru list */
-	if (ne && !get_nat_flag(ne, IS_DIRTY)) {
+	/* for recent accessed(not used to set dirty) nat entry, move it to tail of lru list */
+	if (ne && !get_nat_flag(ne, IS_DIRTY) && !for_dirty) {
 		spin_lock(&nm_i->nat_list_lock);
 		if (!list_empty(&ne->list))
 			list_move_tail(&ne->list, &nm_i->nat_entries);
@@ -383,7 +383,7 @@ int f2fs_need_dentry_mark(struct f2fs_sb_info *sbi, nid_t nid)
 	bool need = false;
 
 	f2fs_down_read(&nm_i->nat_tree_lock);
-	e = __lookup_nat_cache(nm_i, nid);
+	e = __lookup_nat_cache(nm_i, nid, false);
 	if (e) {
 		if (!get_nat_flag(e, IS_CHECKPOINTED) &&
 				!get_nat_flag(e, HAS_FSYNCED_INODE))
@@ -400,7 +400,7 @@ bool f2fs_is_checkpointed_node(struct f2fs_sb_info *sbi, nid_t nid)
 	bool is_cp = true;
 
 	f2fs_down_read(&nm_i->nat_tree_lock);
-	e = __lookup_nat_cache(nm_i, nid);
+	e = __lookup_nat_cache(nm_i, nid, false);
 	if (e && !get_nat_flag(e, IS_CHECKPOINTED))
 		is_cp = false;
 	f2fs_up_read(&nm_i->nat_tree_lock);
@@ -414,7 +414,7 @@ bool f2fs_need_inode_block_update(struct f2fs_sb_info *sbi, nid_t ino)
 	bool need_update = true;
 
 	f2fs_down_read(&nm_i->nat_tree_lock);
-	e = __lookup_nat_cache(nm_i, ino);
+	e = __lookup_nat_cache(nm_i, ino, false);
 	if (e && get_nat_flag(e, HAS_LAST_FSYNC) &&
 			(get_nat_flag(e, IS_CHECKPOINTED) ||
 			 get_nat_flag(e, HAS_FSYNCED_INODE)))
@@ -439,7 +439,7 @@ static void cache_nat_entry(struct f2fs_sb_info *sbi, nid_t nid,
 		return;
 
 	f2fs_down_write(&nm_i->nat_tree_lock);
-	e = __lookup_nat_cache(nm_i, nid);
+	e = __lookup_nat_cache(nm_i, nid, false);
 	if (!e)
 		e = __init_nat_entry(nm_i, new, ne, false);
 	else
@@ -460,7 +460,7 @@ static void set_node_addr(struct f2fs_sb_info *sbi, struct node_info *ni,
 	struct nat_entry *new = __alloc_nat_entry(sbi, ni->nid, true);
 
 	f2fs_down_write(&nm_i->nat_tree_lock);
-	e = __lookup_nat_cache(nm_i, ni->nid);
+	e = __lookup_nat_cache(nm_i, ni->nid, true);
 	if (!e) {
 		e = __init_nat_entry(nm_i, new, NULL, true);
 		copy_node_info(&e->ni, ni);
@@ -502,7 +502,7 @@ static void set_node_addr(struct f2fs_sb_info *sbi, struct node_info *ni,
 
 	/* update fsync_mark if its inode nat entry is still alive */
 	if (ni->nid != ni->ino)
-		e = __lookup_nat_cache(nm_i, ni->ino);
+		e = __lookup_nat_cache(nm_i, ni->ino, false);
 	if (e) {
 		if (fsync_done && ni->nid == ni->ino)
 			set_nat_flag(e, HAS_FSYNCED_INODE, true);
@@ -562,7 +562,7 @@ int f2fs_get_node_info(struct f2fs_sb_info *sbi, nid_t nid,
 retry:
 	/* Check nat cache */
 	f2fs_down_read(&nm_i->nat_tree_lock);
-	e = __lookup_nat_cache(nm_i, nid);
+	e = __lookup_nat_cache(nm_i, nid, false);
 	if (e) {
 		ni->ino = nat_get_ino(e);
 		ni->blk_addr = nat_get_blkaddr(e);
@@ -2371,7 +2371,7 @@ static bool add_free_nid(struct f2fs_sb_info *sbi,
 		 *   - __remove_nid_from_list(PREALLOC_NID)
 		 *                         - __insert_nid_to_list(FREE_NID)
 		 */
-		ne = __lookup_nat_cache(nm_i, nid);
+		ne = __lookup_nat_cache(nm_i, nid, false);
 		if (ne && (!get_nat_flag(ne, IS_CHECKPOINTED) ||
 				nat_get_blkaddr(ne) != NULL_ADDR))
 			goto err_out;
@@ -2936,7 +2936,7 @@ static void remove_nats_in_journal(struct f2fs_sb_info *sbi)
 
 		raw_ne = nat_in_journal(journal, i);
 
-		ne = __lookup_nat_cache(nm_i, nid);
+		ne = __lookup_nat_cache(nm_i, nid, true);
 		if (!ne) {
 			ne = __alloc_nat_entry(sbi, nid, true);
 			__init_nat_entry(nm_i, ne, &raw_ne, true);
-- 
2.25.1


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

* [f2fs-dev] [PATCH v2 2/2] f2fs: directly add newly allocated pre-dirty nat entry to dirty set list
  2025-07-22 14:36 [f2fs-dev] [PATCH v2 1/2] f2fs: avoid redundant clean nat entry move in lru list wangzijie
@ 2025-07-22 14:36 ` wangzijie
  2025-07-24  8:26   ` Chao Yu
  2025-07-24  6:00 ` [f2fs-dev] [PATCH v2 1/2] f2fs: avoid redundant clean nat entry move in lru list Chao Yu
  1 sibling, 1 reply; 7+ messages in thread
From: wangzijie @ 2025-07-22 14:36 UTC (permalink / raw)
  To: jaegeuk, chao
  Cc: linux-f2fs-devel, linux-kernel, bintian.wang, feng.han, wangzijie

When we need to alloc nat entry and set it dirty, we can directly add it to
dirty set list(or initialize its list_head for new_ne) instead of adding it
to clean list and make a move. Introduce init_dirty flag to do it.

Signed-off-by: wangzijie <wangzijie1@honor.com>
---
 fs/f2fs/node.c | 37 ++++++++++++++++++++++++++++++-------
 1 file changed, 30 insertions(+), 7 deletions(-)

diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
index a23db6238..20bcf8559 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -185,7 +185,7 @@ static void __free_nat_entry(struct nat_entry *e)
 
 /* must be locked by nat_tree_lock */
 static struct nat_entry *__init_nat_entry(struct f2fs_nm_info *nm_i,
-	struct nat_entry *ne, struct f2fs_nat_entry *raw_ne, bool no_fail)
+	struct nat_entry *ne, struct f2fs_nat_entry *raw_ne, bool no_fail, bool init_dirty)
 {
 	if (no_fail)
 		f2fs_radix_tree_insert(&nm_i->nat_root, nat_get_nid(ne), ne);
@@ -195,6 +195,11 @@ static struct nat_entry *__init_nat_entry(struct f2fs_nm_info *nm_i,
 	if (raw_ne)
 		node_info_from_raw_nat(&ne->ni, raw_ne);
 
+	if (init_dirty) {
+		nm_i->nat_cnt[TOTAL_NAT]++;
+		return ne;
+	}
+
 	spin_lock(&nm_i->nat_list_lock);
 	list_add_tail(&ne->list, &nm_i->nat_entries);
 	spin_unlock(&nm_i->nat_list_lock);
@@ -256,7 +261,7 @@ static struct nat_entry_set *__grab_nat_entry_set(struct f2fs_nm_info *nm_i,
 }
 
 static void __set_nat_cache_dirty(struct f2fs_nm_info *nm_i,
-						struct nat_entry *ne)
+					struct nat_entry *ne, bool init_dirty)
 {
 	struct nat_entry_set *head;
 	bool new_ne = nat_get_blkaddr(ne) == NEW_ADDR;
@@ -275,6 +280,18 @@ static void __set_nat_cache_dirty(struct f2fs_nm_info *nm_i,
 
 	set_nat_flag(ne, IS_PREALLOC, new_ne);
 
+	if (init_dirty) {
+		nm_i->nat_cnt[DIRTY_NAT]++;
+		set_nat_flag(ne, IS_DIRTY, true);
+		spin_lock(&nm_i->nat_list_lock);
+		if (new_ne)
+			INIT_LIST_HEAD(&ne->list);
+		else
+			list_add_tail(&ne->list, &head->entry_list);
+		spin_unlock(&nm_i->nat_list_lock);
+		return;
+    }
+
 	if (get_nat_flag(ne, IS_DIRTY))
 		goto refresh_list;
 
@@ -441,7 +458,7 @@ static void cache_nat_entry(struct f2fs_sb_info *sbi, nid_t nid,
 	f2fs_down_write(&nm_i->nat_tree_lock);
 	e = __lookup_nat_cache(nm_i, nid, false);
 	if (!e)
-		e = __init_nat_entry(nm_i, new, ne, false);
+		e = __init_nat_entry(nm_i, new, ne, false, false);
 	else
 		f2fs_bug_on(sbi, nat_get_ino(e) != le32_to_cpu(ne->ino) ||
 				nat_get_blkaddr(e) !=
@@ -458,11 +475,13 @@ static void set_node_addr(struct f2fs_sb_info *sbi, struct node_info *ni,
 	struct f2fs_nm_info *nm_i = NM_I(sbi);
 	struct nat_entry *e;
 	struct nat_entry *new = __alloc_nat_entry(sbi, ni->nid, true);
+	bool init_dirty = false;
 
 	f2fs_down_write(&nm_i->nat_tree_lock);
 	e = __lookup_nat_cache(nm_i, ni->nid, true);
 	if (!e) {
-		e = __init_nat_entry(nm_i, new, NULL, true);
+		init_dirty = true;
+		e = __init_nat_entry(nm_i, new, NULL, true, true);
 		copy_node_info(&e->ni, ni);
 		f2fs_bug_on(sbi, ni->blk_addr == NEW_ADDR);
 	} else if (new_blkaddr == NEW_ADDR) {
@@ -498,7 +517,7 @@ static void set_node_addr(struct f2fs_sb_info *sbi, struct node_info *ni,
 	nat_set_blkaddr(e, new_blkaddr);
 	if (!__is_valid_data_blkaddr(new_blkaddr))
 		set_nat_flag(e, IS_CHECKPOINTED, false);
-	__set_nat_cache_dirty(nm_i, e);
+	__set_nat_cache_dirty(nm_i, e, init_dirty);
 
 	/* update fsync_mark if its inode nat entry is still alive */
 	if (ni->nid != ni->ino)
@@ -2924,6 +2943,7 @@ static void remove_nats_in_journal(struct f2fs_sb_info *sbi)
 	struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA);
 	struct f2fs_journal *journal = curseg->journal;
 	int i;
+	bool init_dirty;
 
 	down_write(&curseg->journal_rwsem);
 	for (i = 0; i < nats_in_cursum(journal); i++) {
@@ -2934,12 +2954,15 @@ static void remove_nats_in_journal(struct f2fs_sb_info *sbi)
 		if (f2fs_check_nid_range(sbi, nid))
 			continue;
 
+		init_dirty = false;
+
 		raw_ne = nat_in_journal(journal, i);
 
 		ne = __lookup_nat_cache(nm_i, nid, true);
 		if (!ne) {
+			init_dirty = true;
 			ne = __alloc_nat_entry(sbi, nid, true);
-			__init_nat_entry(nm_i, ne, &raw_ne, true);
+			__init_nat_entry(nm_i, ne, &raw_ne, true, true);
 		}
 
 		/*
@@ -2954,7 +2977,7 @@ static void remove_nats_in_journal(struct f2fs_sb_info *sbi)
 			spin_unlock(&nm_i->nid_list_lock);
 		}
 
-		__set_nat_cache_dirty(nm_i, ne);
+		__set_nat_cache_dirty(nm_i, ne, init_dirty);
 	}
 	update_nats_in_cursum(journal, -i);
 	up_write(&curseg->journal_rwsem);
-- 
2.25.1


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

* Re: [f2fs-dev] [PATCH v2 1/2] f2fs: avoid redundant clean nat entry move in lru list
  2025-07-22 14:36 [f2fs-dev] [PATCH v2 1/2] f2fs: avoid redundant clean nat entry move in lru list wangzijie
  2025-07-22 14:36 ` [f2fs-dev] [PATCH v2 2/2] f2fs: directly add newly allocated pre-dirty nat entry to dirty set list wangzijie
@ 2025-07-24  6:00 ` Chao Yu
  2025-07-24  6:57   ` wangzijie
  1 sibling, 1 reply; 7+ messages in thread
From: Chao Yu @ 2025-07-24  6:00 UTC (permalink / raw)
  To: wangzijie, jaegeuk
  Cc: chao, linux-f2fs-devel, linux-kernel, bintian.wang, feng.han

On 7/22/25 22:36, wangzijie wrote:
> __lookup_nat_cache follows LRU manner to move clean nat entry, when nat
> entries are going to be dirty, no need to move them to tail of lru list.
> Introduce a parameter 'for_dirty' to avoid it.
> 
> Signed-off-by: wangzijie <wangzijie1@honor.com>
> ---
> v2:
> - followed by Jaegeuk's suggestion to add a parameter in __lookup_nat_cache
> ---
>  fs/f2fs/node.c | 24 ++++++++++++------------
>  1 file changed, 12 insertions(+), 12 deletions(-)
> 
> diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
> index 76aba1961..a23db6238 100644
> --- a/fs/f2fs/node.c
> +++ b/fs/f2fs/node.c
> @@ -204,14 +204,14 @@ static struct nat_entry *__init_nat_entry(struct f2fs_nm_info *nm_i,
>  	return ne;
>  }
>  
> -static struct nat_entry *__lookup_nat_cache(struct f2fs_nm_info *nm_i, nid_t n)
> +static struct nat_entry *__lookup_nat_cache(struct f2fs_nm_info *nm_i, nid_t n, bool for_dirty)
>  {
>  	struct nat_entry *ne;
>  
>  	ne = radix_tree_lookup(&nm_i->nat_root, n);
>  
> -	/* for recent accessed nat entry, move it to tail of lru list */
> -	if (ne && !get_nat_flag(ne, IS_DIRTY)) {
> +	/* for recent accessed(not used to set dirty) nat entry, move it to tail of lru list */

What do you think of this?

	/*
	 * for recent accessed nat entry which will not be dirtied soon
	 * later, move it to tail of lru list.
	 */

Thanks,

> +	if (ne && !get_nat_flag(ne, IS_DIRTY) && !for_dirty) {
>  		spin_lock(&nm_i->nat_list_lock);
>  		if (!list_empty(&ne->list))
>  			list_move_tail(&ne->list, &nm_i->nat_entries);
> @@ -383,7 +383,7 @@ int f2fs_need_dentry_mark(struct f2fs_sb_info *sbi, nid_t nid)
>  	bool need = false;
>  
>  	f2fs_down_read(&nm_i->nat_tree_lock);
> -	e = __lookup_nat_cache(nm_i, nid);
> +	e = __lookup_nat_cache(nm_i, nid, false);
>  	if (e) {
>  		if (!get_nat_flag(e, IS_CHECKPOINTED) &&
>  				!get_nat_flag(e, HAS_FSYNCED_INODE))
> @@ -400,7 +400,7 @@ bool f2fs_is_checkpointed_node(struct f2fs_sb_info *sbi, nid_t nid)
>  	bool is_cp = true;
>  
>  	f2fs_down_read(&nm_i->nat_tree_lock);
> -	e = __lookup_nat_cache(nm_i, nid);
> +	e = __lookup_nat_cache(nm_i, nid, false);
>  	if (e && !get_nat_flag(e, IS_CHECKPOINTED))
>  		is_cp = false;
>  	f2fs_up_read(&nm_i->nat_tree_lock);
> @@ -414,7 +414,7 @@ bool f2fs_need_inode_block_update(struct f2fs_sb_info *sbi, nid_t ino)
>  	bool need_update = true;
>  
>  	f2fs_down_read(&nm_i->nat_tree_lock);
> -	e = __lookup_nat_cache(nm_i, ino);
> +	e = __lookup_nat_cache(nm_i, ino, false);
>  	if (e && get_nat_flag(e, HAS_LAST_FSYNC) &&
>  			(get_nat_flag(e, IS_CHECKPOINTED) ||
>  			 get_nat_flag(e, HAS_FSYNCED_INODE)))
> @@ -439,7 +439,7 @@ static void cache_nat_entry(struct f2fs_sb_info *sbi, nid_t nid,
>  		return;
>  
>  	f2fs_down_write(&nm_i->nat_tree_lock);
> -	e = __lookup_nat_cache(nm_i, nid);
> +	e = __lookup_nat_cache(nm_i, nid, false);
>  	if (!e)
>  		e = __init_nat_entry(nm_i, new, ne, false);
>  	else
> @@ -460,7 +460,7 @@ static void set_node_addr(struct f2fs_sb_info *sbi, struct node_info *ni,
>  	struct nat_entry *new = __alloc_nat_entry(sbi, ni->nid, true);
>  
>  	f2fs_down_write(&nm_i->nat_tree_lock);
> -	e = __lookup_nat_cache(nm_i, ni->nid);
> +	e = __lookup_nat_cache(nm_i, ni->nid, true);
>  	if (!e) {
>  		e = __init_nat_entry(nm_i, new, NULL, true);
>  		copy_node_info(&e->ni, ni);
> @@ -502,7 +502,7 @@ static void set_node_addr(struct f2fs_sb_info *sbi, struct node_info *ni,
>  
>  	/* update fsync_mark if its inode nat entry is still alive */
>  	if (ni->nid != ni->ino)
> -		e = __lookup_nat_cache(nm_i, ni->ino);
> +		e = __lookup_nat_cache(nm_i, ni->ino, false);
>  	if (e) {
>  		if (fsync_done && ni->nid == ni->ino)
>  			set_nat_flag(e, HAS_FSYNCED_INODE, true);
> @@ -562,7 +562,7 @@ int f2fs_get_node_info(struct f2fs_sb_info *sbi, nid_t nid,
>  retry:
>  	/* Check nat cache */
>  	f2fs_down_read(&nm_i->nat_tree_lock);
> -	e = __lookup_nat_cache(nm_i, nid);
> +	e = __lookup_nat_cache(nm_i, nid, false);
>  	if (e) {
>  		ni->ino = nat_get_ino(e);
>  		ni->blk_addr = nat_get_blkaddr(e);
> @@ -2371,7 +2371,7 @@ static bool add_free_nid(struct f2fs_sb_info *sbi,
>  		 *   - __remove_nid_from_list(PREALLOC_NID)
>  		 *                         - __insert_nid_to_list(FREE_NID)
>  		 */
> -		ne = __lookup_nat_cache(nm_i, nid);
> +		ne = __lookup_nat_cache(nm_i, nid, false);
>  		if (ne && (!get_nat_flag(ne, IS_CHECKPOINTED) ||
>  				nat_get_blkaddr(ne) != NULL_ADDR))
>  			goto err_out;
> @@ -2936,7 +2936,7 @@ static void remove_nats_in_journal(struct f2fs_sb_info *sbi)
>  
>  		raw_ne = nat_in_journal(journal, i);
>  
> -		ne = __lookup_nat_cache(nm_i, nid);
> +		ne = __lookup_nat_cache(nm_i, nid, true);
>  		if (!ne) {
>  			ne = __alloc_nat_entry(sbi, nid, true);
>  			__init_nat_entry(nm_i, ne, &raw_ne, true);


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

* Re: [f2fs-dev] [PATCH v2 1/2] f2fs: avoid redundant clean nat entry move in lru list
  2025-07-24  6:00 ` [f2fs-dev] [PATCH v2 1/2] f2fs: avoid redundant clean nat entry move in lru list Chao Yu
@ 2025-07-24  6:57   ` wangzijie
  0 siblings, 0 replies; 7+ messages in thread
From: wangzijie @ 2025-07-24  6:57 UTC (permalink / raw)
  To: linux-f2fs-devel; +Cc: chao, feng.han, jaegeuk, linux-kernel, wangzijie1

> On 7/22/25 22:36, wangzijie wrote:
> > __lookup_nat_cache follows LRU manner to move clean nat entry, when nat
> > entries are going to be dirty, no need to move them to tail of lru list.
> > Introduce a parameter 'for_dirty' to avoid it.
> > 
> > Signed-off-by: wangzijie <wangzijie1@honor.com>
> > ---
> > v2:
> > - followed by Jaegeuk's suggestion to add a parameter in __lookup_nat_cache
> > ---
> >  fs/f2fs/node.c | 24 ++++++++++++------------
> >  1 file changed, 12 insertions(+), 12 deletions(-)
> > 
> > diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
> > index 76aba1961..a23db6238 100644
> > --- a/fs/f2fs/node.c
> > +++ b/fs/f2fs/node.c
> > @@ -204,14 +204,14 @@ static struct nat_entry *__init_nat_entry(struct f2fs_nm_info *nm_i,
> >  	return ne;
> >  }
> >  
> > -static struct nat_entry *__lookup_nat_cache(struct f2fs_nm_info *nm_i, nid_t n)
> > +static struct nat_entry *__lookup_nat_cache(struct f2fs_nm_info *nm_i, nid_t n, bool for_dirty)
> >  {
> >  	struct nat_entry *ne;
> >  
> >  	ne = radix_tree_lookup(&nm_i->nat_root, n);
> >  
> > -	/* for recent accessed nat entry, move it to tail of lru list */
> > -	if (ne && !get_nat_flag(ne, IS_DIRTY)) {
> > +	/* for recent accessed(not used to set dirty) nat entry, move it to tail of lru list */
> 
> What do you think of this?
> 
> 	/*
> 	 * for recent accessed nat entry which will not be dirtied soon
> 	 * later, move it to tail of lru list.
> 	 */
> 
> Thanks,

Hi, Chao
Thank you for your suggestion. Let me update comment in next version.

> > +	if (ne && !get_nat_flag(ne, IS_DIRTY) && !for_dirty) {
> >  		spin_lock(&nm_i->nat_list_lock);
> >  		if (!list_empty(&ne->list))
> >  			list_move_tail(&ne->list, &nm_i->nat_entries);
> > @@ -383,7 +383,7 @@ int f2fs_need_dentry_mark(struct f2fs_sb_info *sbi, nid_t nid)
> >  	bool need = false;
> >  
> >  	f2fs_down_read(&nm_i->nat_tree_lock);
> > -	e = __lookup_nat_cache(nm_i, nid);
> > +	e = __lookup_nat_cache(nm_i, nid, false);
> >  	if (e) {
> >  		if (!get_nat_flag(e, IS_CHECKPOINTED) &&
> >  				!get_nat_flag(e, HAS_FSYNCED_INODE))
> > @@ -400,7 +400,7 @@ bool f2fs_is_checkpointed_node(struct f2fs_sb_info *sbi, nid_t nid)
> >  	bool is_cp = true;
> >  
> >  	f2fs_down_read(&nm_i->nat_tree_lock);
> > -	e = __lookup_nat_cache(nm_i, nid);
> > +	e = __lookup_nat_cache(nm_i, nid, false);
> >  	if (e && !get_nat_flag(e, IS_CHECKPOINTED))
> >  		is_cp = false;
> >  	f2fs_up_read(&nm_i->nat_tree_lock);
> > @@ -414,7 +414,7 @@ bool f2fs_need_inode_block_update(struct f2fs_sb_info *sbi, nid_t ino)
> >  	bool need_update = true;
> >  
> >  	f2fs_down_read(&nm_i->nat_tree_lock);
> > -	e = __lookup_nat_cache(nm_i, ino);
> > +	e = __lookup_nat_cache(nm_i, ino, false);
> >  	if (e && get_nat_flag(e, HAS_LAST_FSYNC) &&
> >  			(get_nat_flag(e, IS_CHECKPOINTED) ||
> >  			 get_nat_flag(e, HAS_FSYNCED_INODE)))
> > @@ -439,7 +439,7 @@ static void cache_nat_entry(struct f2fs_sb_info *sbi, nid_t nid,
> >  		return;
> >  
> >  	f2fs_down_write(&nm_i->nat_tree_lock);
> > -	e = __lookup_nat_cache(nm_i, nid);
> > +	e = __lookup_nat_cache(nm_i, nid, false);
> >  	if (!e)
> >  		e = __init_nat_entry(nm_i, new, ne, false);
> >  	else
> > @@ -460,7 +460,7 @@ static void set_node_addr(struct f2fs_sb_info *sbi, struct node_info *ni,
> >  	struct nat_entry *new = __alloc_nat_entry(sbi, ni->nid, true);
> >  
> >  	f2fs_down_write(&nm_i->nat_tree_lock);
> > -	e = __lookup_nat_cache(nm_i, ni->nid);
> > +	e = __lookup_nat_cache(nm_i, ni->nid, true);
> >  	if (!e) {
> >  		e = __init_nat_entry(nm_i, new, NULL, true);
> >  		copy_node_info(&e->ni, ni);
> > @@ -502,7 +502,7 @@ static void set_node_addr(struct f2fs_sb_info *sbi, struct node_info *ni,
> >  
> >  	/* update fsync_mark if its inode nat entry is still alive */
> >  	if (ni->nid != ni->ino)
> > -		e = __lookup_nat_cache(nm_i, ni->ino);
> > +		e = __lookup_nat_cache(nm_i, ni->ino, false);
> >  	if (e) {
> >  		if (fsync_done && ni->nid == ni->ino)
> >  			set_nat_flag(e, HAS_FSYNCED_INODE, true);
> > @@ -562,7 +562,7 @@ int f2fs_get_node_info(struct f2fs_sb_info *sbi, nid_t nid,
> >  retry:
> >  	/* Check nat cache */
> >  	f2fs_down_read(&nm_i->nat_tree_lock);
> > -	e = __lookup_nat_cache(nm_i, nid);
> > +	e = __lookup_nat_cache(nm_i, nid, false);
> >  	if (e) {
> >  		ni->ino = nat_get_ino(e);
> >  		ni->blk_addr = nat_get_blkaddr(e);
> > @@ -2371,7 +2371,7 @@ static bool add_free_nid(struct f2fs_sb_info *sbi,
> >  		 *   - __remove_nid_from_list(PREALLOC_NID)
> >  		 *                         - __insert_nid_to_list(FREE_NID)
> >  		 */
> > -		ne = __lookup_nat_cache(nm_i, nid);
> > +		ne = __lookup_nat_cache(nm_i, nid, false);
> >  		if (ne && (!get_nat_flag(ne, IS_CHECKPOINTED) ||
> >  				nat_get_blkaddr(ne) != NULL_ADDR))
> >  			goto err_out;
> > @@ -2936,7 +2936,7 @@ static void remove_nats_in_journal(struct f2fs_sb_info *sbi)
> >  
> >  		raw_ne = nat_in_journal(journal, i);
> >  
> > -		ne = __lookup_nat_cache(nm_i, nid);
> > +		ne = __lookup_nat_cache(nm_i, nid, true);
> >  		if (!ne) {
> >  			ne = __alloc_nat_entry(sbi, nid, true);
> >  			__init_nat_entry(nm_i, ne, &raw_ne, true);

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

* Re: [f2fs-dev] [PATCH v2 2/2] f2fs: directly add newly allocated pre-dirty nat entry to dirty set list
  2025-07-22 14:36 ` [f2fs-dev] [PATCH v2 2/2] f2fs: directly add newly allocated pre-dirty nat entry to dirty set list wangzijie
@ 2025-07-24  8:26   ` Chao Yu
  2025-07-25  2:17     ` wangzijie
  0 siblings, 1 reply; 7+ messages in thread
From: Chao Yu @ 2025-07-24  8:26 UTC (permalink / raw)
  To: wangzijie, jaegeuk
  Cc: chao, linux-f2fs-devel, linux-kernel, bintian.wang, feng.han

On 7/22/25 22:36, wangzijie wrote:
> When we need to alloc nat entry and set it dirty, we can directly add it to
> dirty set list(or initialize its list_head for new_ne) instead of adding it
> to clean list and make a move. Introduce init_dirty flag to do it.
> 
> Signed-off-by: wangzijie <wangzijie1@honor.com>
> ---
>  fs/f2fs/node.c | 37 ++++++++++++++++++++++++++++++-------
>  1 file changed, 30 insertions(+), 7 deletions(-)
> 
> diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
> index a23db6238..20bcf8559 100644
> --- a/fs/f2fs/node.c
> +++ b/fs/f2fs/node.c
> @@ -185,7 +185,7 @@ static void __free_nat_entry(struct nat_entry *e)
>  
>  /* must be locked by nat_tree_lock */
>  static struct nat_entry *__init_nat_entry(struct f2fs_nm_info *nm_i,
> -	struct nat_entry *ne, struct f2fs_nat_entry *raw_ne, bool no_fail)
> +	struct nat_entry *ne, struct f2fs_nat_entry *raw_ne, bool no_fail, bool init_dirty)
>  {
>  	if (no_fail)
>  		f2fs_radix_tree_insert(&nm_i->nat_root, nat_get_nid(ne), ne);
> @@ -195,6 +195,11 @@ static struct nat_entry *__init_nat_entry(struct f2fs_nm_info *nm_i,
>  	if (raw_ne)
>  		node_info_from_raw_nat(&ne->ni, raw_ne);
>  
> +	if (init_dirty) {
> +		nm_i->nat_cnt[TOTAL_NAT]++;
> +		return ne;
> +	}
> +
>  	spin_lock(&nm_i->nat_list_lock);
>  	list_add_tail(&ne->list, &nm_i->nat_entries);
>  	spin_unlock(&nm_i->nat_list_lock);
> @@ -256,7 +261,7 @@ static struct nat_entry_set *__grab_nat_entry_set(struct f2fs_nm_info *nm_i,
>  }
>  
>  static void __set_nat_cache_dirty(struct f2fs_nm_info *nm_i,
> -						struct nat_entry *ne)
> +					struct nat_entry *ne, bool init_dirty)
>  {
>  	struct nat_entry_set *head;
>  	bool new_ne = nat_get_blkaddr(ne) == NEW_ADDR;
> @@ -275,6 +280,18 @@ static void __set_nat_cache_dirty(struct f2fs_nm_info *nm_i,
>  
>  	set_nat_flag(ne, IS_PREALLOC, new_ne);
>  
> +	if (init_dirty) {
> +		nm_i->nat_cnt[DIRTY_NAT]++;
> +		set_nat_flag(ne, IS_DIRTY, true);
> +		spin_lock(&nm_i->nat_list_lock);
> +		if (new_ne)
> +			INIT_LIST_HEAD(&ne->list);
> +		else
> +			list_add_tail(&ne->list, &head->entry_list);
> +		spin_unlock(&nm_i->nat_list_lock);
> +		return;
> +    }

Nit issue, above blanks should be replaced w/ tab.

Can we clean up like this?

diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
index de99b42437c6..60fc2c7b8e10 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -280,30 +280,23 @@ static void __set_nat_cache_dirty(struct f2fs_nm_info *nm_i,

 	set_nat_flag(ne, IS_PREALLOC, new_ne);

-	if (init_dirty) {
-		nm_i->nat_cnt[DIRTY_NAT]++;
-		set_nat_flag(ne, IS_DIRTY, true);
-		spin_lock(&nm_i->nat_list_lock);
-		if (new_ne)
-			INIT_LIST_HEAD(&ne->list);
-		else
-			list_add_tail(&ne->list, &head->entry_list);
-		spin_unlock(&nm_i->nat_list_lock);
-		return;
-    }
-
 	if (get_nat_flag(ne, IS_DIRTY))
 		goto refresh_list;

 	nm_i->nat_cnt[DIRTY_NAT]++;
-	nm_i->nat_cnt[RECLAIMABLE_NAT]--;
+	if (!init_dirty)
+		nm_i->nat_cnt[RECLAIMABLE_NAT]--;
 	set_nat_flag(ne, IS_DIRTY, true);
 refresh_list:
 	spin_lock(&nm_i->nat_list_lock);
-	if (new_ne)
-		list_del_init(&ne->list);
-	else
+	if (new_ne) {
+		if (init_dirty)
+			INIT_LIST_HEAD(&ne->list);
+		else
+			list_del_init(&ne->list);
+	} else {
 		list_move_tail(&ne->list, &head->entry_list);
+	}
 	spin_unlock(&nm_i->nat_list_lock);
 }

Thanks,

> +
>  	if (get_nat_flag(ne, IS_DIRTY))
>  		goto refresh_list;
>  
> @@ -441,7 +458,7 @@ static void cache_nat_entry(struct f2fs_sb_info *sbi, nid_t nid,
>  	f2fs_down_write(&nm_i->nat_tree_lock);
>  	e = __lookup_nat_cache(nm_i, nid, false);
>  	if (!e)
> -		e = __init_nat_entry(nm_i, new, ne, false);
> +		e = __init_nat_entry(nm_i, new, ne, false, false);
>  	else
>  		f2fs_bug_on(sbi, nat_get_ino(e) != le32_to_cpu(ne->ino) ||
>  				nat_get_blkaddr(e) !=
> @@ -458,11 +475,13 @@ static void set_node_addr(struct f2fs_sb_info *sbi, struct node_info *ni,
>  	struct f2fs_nm_info *nm_i = NM_I(sbi);
>  	struct nat_entry *e;
>  	struct nat_entry *new = __alloc_nat_entry(sbi, ni->nid, true);
> +	bool init_dirty = false;
>  
>  	f2fs_down_write(&nm_i->nat_tree_lock);
>  	e = __lookup_nat_cache(nm_i, ni->nid, true);
>  	if (!e) {
> -		e = __init_nat_entry(nm_i, new, NULL, true);
> +		init_dirty = true;
> +		e = __init_nat_entry(nm_i, new, NULL, true, true);
>  		copy_node_info(&e->ni, ni);
>  		f2fs_bug_on(sbi, ni->blk_addr == NEW_ADDR);
>  	} else if (new_blkaddr == NEW_ADDR) {
> @@ -498,7 +517,7 @@ static void set_node_addr(struct f2fs_sb_info *sbi, struct node_info *ni,
>  	nat_set_blkaddr(e, new_blkaddr);
>  	if (!__is_valid_data_blkaddr(new_blkaddr))
>  		set_nat_flag(e, IS_CHECKPOINTED, false);
> -	__set_nat_cache_dirty(nm_i, e);
> +	__set_nat_cache_dirty(nm_i, e, init_dirty);
>  
>  	/* update fsync_mark if its inode nat entry is still alive */
>  	if (ni->nid != ni->ino)
> @@ -2924,6 +2943,7 @@ static void remove_nats_in_journal(struct f2fs_sb_info *sbi)
>  	struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA);
>  	struct f2fs_journal *journal = curseg->journal;
>  	int i;
> +	bool init_dirty;
>  
>  	down_write(&curseg->journal_rwsem);
>  	for (i = 0; i < nats_in_cursum(journal); i++) {
> @@ -2934,12 +2954,15 @@ static void remove_nats_in_journal(struct f2fs_sb_info *sbi)
>  		if (f2fs_check_nid_range(sbi, nid))
>  			continue;
>  
> +		init_dirty = false;
> +
>  		raw_ne = nat_in_journal(journal, i);
>  
>  		ne = __lookup_nat_cache(nm_i, nid, true);
>  		if (!ne) {
> +			init_dirty = true;
>  			ne = __alloc_nat_entry(sbi, nid, true);
> -			__init_nat_entry(nm_i, ne, &raw_ne, true);
> +			__init_nat_entry(nm_i, ne, &raw_ne, true, true);
>  		}
>  
>  		/*
> @@ -2954,7 +2977,7 @@ static void remove_nats_in_journal(struct f2fs_sb_info *sbi)
>  			spin_unlock(&nm_i->nid_list_lock);
>  		}
>  
> -		__set_nat_cache_dirty(nm_i, ne);
> +		__set_nat_cache_dirty(nm_i, ne, init_dirty);
>  	}
>  	update_nats_in_cursum(journal, -i);
>  	up_write(&curseg->journal_rwsem);


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

* Re: [f2fs-dev] [PATCH v2 2/2] f2fs: directly add newly allocated pre-dirty nat entry to dirty set list
  2025-07-24  8:26   ` Chao Yu
@ 2025-07-25  2:17     ` wangzijie
  2025-07-25  2:36       ` Chao Yu
  0 siblings, 1 reply; 7+ messages in thread
From: wangzijie @ 2025-07-25  2:17 UTC (permalink / raw)
  To: linux-f2fs-devel; +Cc: chao, feng.han, jaegeuk, linux-kernel, wangzijie1

> On 7/22/25 22:36, wangzijie wrote:
> > When we need to alloc nat entry and set it dirty, we can directly add it to
> > dirty set list(or initialize its list_head for new_ne) instead of adding it
> > to clean list and make a move. Introduce init_dirty flag to do it.
> > 
> > Signed-off-by: wangzijie <wangzijie1@honor.com>
> > ---
> >  fs/f2fs/node.c | 37 ++++++++++++++++++++++++++++++-------
> >  1 file changed, 30 insertions(+), 7 deletions(-)
> > 
> > diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
> > index a23db6238..20bcf8559 100644
> > --- a/fs/f2fs/node.c
> > +++ b/fs/f2fs/node.c
> > @@ -185,7 +185,7 @@ static void __free_nat_entry(struct nat_entry *e)
> >  
> >  /* must be locked by nat_tree_lock */
> >  static struct nat_entry *__init_nat_entry(struct f2fs_nm_info *nm_i,
> > -	struct nat_entry *ne, struct f2fs_nat_entry *raw_ne, bool no_fail)
> > +	struct nat_entry *ne, struct f2fs_nat_entry *raw_ne, bool no_fail, bool init_dirty)
> >  {
> >  	if (no_fail)
> >  		f2fs_radix_tree_insert(&nm_i->nat_root, nat_get_nid(ne), ne);
> > @@ -195,6 +195,11 @@ static struct nat_entry *__init_nat_entry(struct f2fs_nm_info *nm_i,
> >  	if (raw_ne)
> >  		node_info_from_raw_nat(&ne->ni, raw_ne);
> >  
> > +	if (init_dirty) {
> > +		nm_i->nat_cnt[TOTAL_NAT]++;
> > +		return ne;
> > +	}
> > +
> >  	spin_lock(&nm_i->nat_list_lock);
> >  	list_add_tail(&ne->list, &nm_i->nat_entries);
> >  	spin_unlock(&nm_i->nat_list_lock);
> > @@ -256,7 +261,7 @@ static struct nat_entry_set *__grab_nat_entry_set(struct f2fs_nm_info *nm_i,
> >  }
> >  
> >  static void __set_nat_cache_dirty(struct f2fs_nm_info *nm_i,
> > -						struct nat_entry *ne)
> > +					struct nat_entry *ne, bool init_dirty)
> >  {
> >  	struct nat_entry_set *head;
> >  	bool new_ne = nat_get_blkaddr(ne) == NEW_ADDR;
> > @@ -275,6 +280,18 @@ static void __set_nat_cache_dirty(struct f2fs_nm_info *nm_i,
> >  
> >  	set_nat_flag(ne, IS_PREALLOC, new_ne);
> >  
> > +	if (init_dirty) {
> > +		nm_i->nat_cnt[DIRTY_NAT]++;
> > +		set_nat_flag(ne, IS_DIRTY, true);
> > +		spin_lock(&nm_i->nat_list_lock);
> > +		if (new_ne)
> > +			INIT_LIST_HEAD(&ne->list);
> > +		else
> > +			list_add_tail(&ne->list, &head->entry_list);
> > +		spin_unlock(&nm_i->nat_list_lock);
> > +		return;
> > +    }
> 
> Nit issue, above blanks should be replaced w/ tab.

Ah...my bad :-(

> Can we clean up like this?
> 
> diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
> index de99b42437c6..60fc2c7b8e10 100644
> --- a/fs/f2fs/node.c
> +++ b/fs/f2fs/node.c
> @@ -280,30 +280,23 @@ static void __set_nat_cache_dirty(struct f2fs_nm_info *nm_i,
> 
>  	set_nat_flag(ne, IS_PREALLOC, new_ne);
> 
> -	if (init_dirty) {
> -		nm_i->nat_cnt[DIRTY_NAT]++;
> -		set_nat_flag(ne, IS_DIRTY, true);
> -		spin_lock(&nm_i->nat_list_lock);
> -		if (new_ne)
> -			INIT_LIST_HEAD(&ne->list);
> -		else
> -			list_add_tail(&ne->list, &head->entry_list);
> -		spin_unlock(&nm_i->nat_list_lock);
> -		return;
> -    }
> -
>  	if (get_nat_flag(ne, IS_DIRTY))
>  		goto refresh_list;
> 
>  	nm_i->nat_cnt[DIRTY_NAT]++;
> -	nm_i->nat_cnt[RECLAIMABLE_NAT]--;
> +	if (!init_dirty)
> +		nm_i->nat_cnt[RECLAIMABLE_NAT]--;
>  	set_nat_flag(ne, IS_DIRTY, true);
>  refresh_list:
>  	spin_lock(&nm_i->nat_list_lock);
> -	if (new_ne)
> -		list_del_init(&ne->list);
> -	else
> +	if (new_ne) {
> +		if (init_dirty)
> +			INIT_LIST_HEAD(&ne->list);
> +		else
> +			list_del_init(&ne->list);
> +	} else {
>  		list_move_tail(&ne->list, &head->entry_list);
> +	}
>  	spin_unlock(&nm_i->nat_list_lock);
>  }
> 
> Thanks,

We need to init list_head before using list_move_tail.
I think we can do more clean up like this, keep refresh_list part code.

diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
index 20bcf8559..ebb624fa1 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -196,6 +196,7 @@ static struct nat_entry *__init_nat_entry(struct f2fs_nm_info *nm_i,
 		node_info_from_raw_nat(&ne->ni, raw_ne);
 
 	if (init_dirty) {
+		INIT_LIST_HEAD(&ne->list);
 		nm_i->nat_cnt[TOTAL_NAT]++;
 		return ne;
 	}
@@ -280,23 +281,12 @@ static void __set_nat_cache_dirty(struct f2fs_nm_info *nm_i,
 
 	set_nat_flag(ne, IS_PREALLOC, new_ne);
 
-	if (init_dirty) {
-		nm_i->nat_cnt[DIRTY_NAT]++;
-		set_nat_flag(ne, IS_DIRTY, true);
-		spin_lock(&nm_i->nat_list_lock);
-		if (new_ne)
-			INIT_LIST_HEAD(&ne->list);
-		else
-			list_add_tail(&ne->list, &head->entry_list);
-		spin_unlock(&nm_i->nat_list_lock);
-		return;
-    }
-
 	if (get_nat_flag(ne, IS_DIRTY))
 		goto refresh_list;
 
 	nm_i->nat_cnt[DIRTY_NAT]++;
-	nm_i->nat_cnt[RECLAIMABLE_NAT]--;
+	if (!init_dirty)
+		nm_i->nat_cnt[RECLAIMABLE_NAT]--;
 	set_nat_flag(ne, IS_DIRTY, true);
 refresh_list:
 	spin_lock(&nm_i->nat_list_lock);

> > +
> >  	if (get_nat_flag(ne, IS_DIRTY))
> >  		goto refresh_list;
> >  
> > @@ -441,7 +458,7 @@ static void cache_nat_entry(struct f2fs_sb_info *sbi, nid_t nid,
> >  	f2fs_down_write(&nm_i->nat_tree_lock);
> >  	e = __lookup_nat_cache(nm_i, nid, false);
> >  	if (!e)
> > -		e = __init_nat_entry(nm_i, new, ne, false);
> > +		e = __init_nat_entry(nm_i, new, ne, false, false);
> >  	else
> >  		f2fs_bug_on(sbi, nat_get_ino(e) != le32_to_cpu(ne->ino) ||
> >  				nat_get_blkaddr(e) !=
> > @@ -458,11 +475,13 @@ static void set_node_addr(struct f2fs_sb_info *sbi, struct node_info *ni,
> >  	struct f2fs_nm_info *nm_i = NM_I(sbi);
> >  	struct nat_entry *e;
> >  	struct nat_entry *new = __alloc_nat_entry(sbi, ni->nid, true);
> > +	bool init_dirty = false;
> >  
> >  	f2fs_down_write(&nm_i->nat_tree_lock);
> >  	e = __lookup_nat_cache(nm_i, ni->nid, true);
> >  	if (!e) {
> > -		e = __init_nat_entry(nm_i, new, NULL, true);
> > +		init_dirty = true;
> > +		e = __init_nat_entry(nm_i, new, NULL, true, true);
> >  		copy_node_info(&e->ni, ni);
> >  		f2fs_bug_on(sbi, ni->blk_addr == NEW_ADDR);
> >  	} else if (new_blkaddr == NEW_ADDR) {
> > @@ -498,7 +517,7 @@ static void set_node_addr(struct f2fs_sb_info *sbi, struct node_info *ni,
> >  	nat_set_blkaddr(e, new_blkaddr);
> >  	if (!__is_valid_data_blkaddr(new_blkaddr))
> >  		set_nat_flag(e, IS_CHECKPOINTED, false);
> > -	__set_nat_cache_dirty(nm_i, e);
> > +	__set_nat_cache_dirty(nm_i, e, init_dirty);
> >  
> >  	/* update fsync_mark if its inode nat entry is still alive */
> >  	if (ni->nid != ni->ino)
> > @@ -2924,6 +2943,7 @@ static void remove_nats_in_journal(struct f2fs_sb_info *sbi)
> >  	struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA);
> >  	struct f2fs_journal *journal = curseg->journal;
> >  	int i;
> > +	bool init_dirty;
> >  
> >  	down_write(&curseg->journal_rwsem);
> >  	for (i = 0; i < nats_in_cursum(journal); i++) {
> > @@ -2934,12 +2954,15 @@ static void remove_nats_in_journal(struct f2fs_sb_info *sbi)
> >  		if (f2fs_check_nid_range(sbi, nid))
> >  			continue;
> >  
> > +		init_dirty = false;
> > +
> >  		raw_ne = nat_in_journal(journal, i);
> >  
> >  		ne = __lookup_nat_cache(nm_i, nid, true);
> >  		if (!ne) {
> > +			init_dirty = true;
> >  			ne = __alloc_nat_entry(sbi, nid, true);
> > -			__init_nat_entry(nm_i, ne, &raw_ne, true);
> > +			__init_nat_entry(nm_i, ne, &raw_ne, true, true);
> >  		}
> >  
> >  		/*
> > @@ -2954,7 +2977,7 @@ static void remove_nats_in_journal(struct f2fs_sb_info *sbi)
> >  			spin_unlock(&nm_i->nid_list_lock);
> >  		}
> >  
> > -		__set_nat_cache_dirty(nm_i, ne);
> > +		__set_nat_cache_dirty(nm_i, ne, init_dirty);
> >  	}
> >  	update_nats_in_cursum(journal, -i);
> >  	up_write(&curseg->journal_rwsem);


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

* Re: [f2fs-dev] [PATCH v2 2/2] f2fs: directly add newly allocated pre-dirty nat entry to dirty set list
  2025-07-25  2:17     ` wangzijie
@ 2025-07-25  2:36       ` Chao Yu
  0 siblings, 0 replies; 7+ messages in thread
From: Chao Yu @ 2025-07-25  2:36 UTC (permalink / raw)
  To: wangzijie, linux-f2fs-devel; +Cc: chao, feng.han, jaegeuk, linux-kernel

On 7/25/2025 10:17 AM, wangzijie wrote:
>> On 7/22/25 22:36, wangzijie wrote:
>>> When we need to alloc nat entry and set it dirty, we can directly add it to
>>> dirty set list(or initialize its list_head for new_ne) instead of adding it
>>> to clean list and make a move. Introduce init_dirty flag to do it.
>>>
>>> Signed-off-by: wangzijie <wangzijie1@honor.com>
>>> ---
>>>   fs/f2fs/node.c | 37 ++++++++++++++++++++++++++++++-------
>>>   1 file changed, 30 insertions(+), 7 deletions(-)
>>>
>>> diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
>>> index a23db6238..20bcf8559 100644
>>> --- a/fs/f2fs/node.c
>>> +++ b/fs/f2fs/node.c
>>> @@ -185,7 +185,7 @@ static void __free_nat_entry(struct nat_entry *e)
>>>   
>>>   /* must be locked by nat_tree_lock */
>>>   static struct nat_entry *__init_nat_entry(struct f2fs_nm_info *nm_i,
>>> -	struct nat_entry *ne, struct f2fs_nat_entry *raw_ne, bool no_fail)
>>> +	struct nat_entry *ne, struct f2fs_nat_entry *raw_ne, bool no_fail, bool init_dirty)
>>>   {
>>>   	if (no_fail)
>>>   		f2fs_radix_tree_insert(&nm_i->nat_root, nat_get_nid(ne), ne);
>>> @@ -195,6 +195,11 @@ static struct nat_entry *__init_nat_entry(struct f2fs_nm_info *nm_i,
>>>   	if (raw_ne)
>>>   		node_info_from_raw_nat(&ne->ni, raw_ne);
>>>   
>>> +	if (init_dirty) {
>>> +		nm_i->nat_cnt[TOTAL_NAT]++;
>>> +		return ne;
>>> +	}
>>> +
>>>   	spin_lock(&nm_i->nat_list_lock);
>>>   	list_add_tail(&ne->list, &nm_i->nat_entries);
>>>   	spin_unlock(&nm_i->nat_list_lock);
>>> @@ -256,7 +261,7 @@ static struct nat_entry_set *__grab_nat_entry_set(struct f2fs_nm_info *nm_i,
>>>   }
>>>   
>>>   static void __set_nat_cache_dirty(struct f2fs_nm_info *nm_i,
>>> -						struct nat_entry *ne)
>>> +					struct nat_entry *ne, bool init_dirty)
>>>   {
>>>   	struct nat_entry_set *head;
>>>   	bool new_ne = nat_get_blkaddr(ne) == NEW_ADDR;
>>> @@ -275,6 +280,18 @@ static void __set_nat_cache_dirty(struct f2fs_nm_info *nm_i,
>>>   
>>>   	set_nat_flag(ne, IS_PREALLOC, new_ne);
>>>   
>>> +	if (init_dirty) {
>>> +		nm_i->nat_cnt[DIRTY_NAT]++;
>>> +		set_nat_flag(ne, IS_DIRTY, true);
>>> +		spin_lock(&nm_i->nat_list_lock);
>>> +		if (new_ne)
>>> +			INIT_LIST_HEAD(&ne->list);
>>> +		else
>>> +			list_add_tail(&ne->list, &head->entry_list);
>>> +		spin_unlock(&nm_i->nat_list_lock);
>>> +		return;
>>> +    }
>>
>> Nit issue, above blanks should be replaced w/ tab.
> 
> Ah...my bad :-(
> 
>> Can we clean up like this?
>>
>> diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
>> index de99b42437c6..60fc2c7b8e10 100644
>> --- a/fs/f2fs/node.c
>> +++ b/fs/f2fs/node.c
>> @@ -280,30 +280,23 @@ static void __set_nat_cache_dirty(struct f2fs_nm_info *nm_i,
>>
>>   	set_nat_flag(ne, IS_PREALLOC, new_ne);
>>
>> -	if (init_dirty) {
>> -		nm_i->nat_cnt[DIRTY_NAT]++;
>> -		set_nat_flag(ne, IS_DIRTY, true);
>> -		spin_lock(&nm_i->nat_list_lock);
>> -		if (new_ne)
>> -			INIT_LIST_HEAD(&ne->list);
>> -		else
>> -			list_add_tail(&ne->list, &head->entry_list);
>> -		spin_unlock(&nm_i->nat_list_lock);
>> -		return;
>> -    }
>> -
>>   	if (get_nat_flag(ne, IS_DIRTY))
>>   		goto refresh_list;
>>
>>   	nm_i->nat_cnt[DIRTY_NAT]++;
>> -	nm_i->nat_cnt[RECLAIMABLE_NAT]--;
>> +	if (!init_dirty)
>> +		nm_i->nat_cnt[RECLAIMABLE_NAT]--;
>>   	set_nat_flag(ne, IS_DIRTY, true);
>>   refresh_list:
>>   	spin_lock(&nm_i->nat_list_lock);
>> -	if (new_ne)
>> -		list_del_init(&ne->list);
>> -	else
>> +	if (new_ne) {
>> +		if (init_dirty)
>> +			INIT_LIST_HEAD(&ne->list);
>> +		else
>> +			list_del_init(&ne->list);
>> +	} else {
>>   		list_move_tail(&ne->list, &head->entry_list);
>> +	}
>>   	spin_unlock(&nm_i->nat_list_lock);
>>   }
>>
>> Thanks,
> 
> We need to init list_head before using list_move_tail.
> I think we can do more clean up like this, keep refresh_list part code.

Ah, that's better.

Thanks,

> 
> diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
> index 20bcf8559..ebb624fa1 100644
> --- a/fs/f2fs/node.c
> +++ b/fs/f2fs/node.c
> @@ -196,6 +196,7 @@ static struct nat_entry *__init_nat_entry(struct f2fs_nm_info *nm_i,
>   		node_info_from_raw_nat(&ne->ni, raw_ne);
>   
>   	if (init_dirty) {
> +		INIT_LIST_HEAD(&ne->list);
>   		nm_i->nat_cnt[TOTAL_NAT]++;
>   		return ne;
>   	}
> @@ -280,23 +281,12 @@ static void __set_nat_cache_dirty(struct f2fs_nm_info *nm_i,
>   
>   	set_nat_flag(ne, IS_PREALLOC, new_ne);
>   
> -	if (init_dirty) {
> -		nm_i->nat_cnt[DIRTY_NAT]++;
> -		set_nat_flag(ne, IS_DIRTY, true);
> -		spin_lock(&nm_i->nat_list_lock);
> -		if (new_ne)
> -			INIT_LIST_HEAD(&ne->list);
> -		else
> -			list_add_tail(&ne->list, &head->entry_list);
> -		spin_unlock(&nm_i->nat_list_lock);
> -		return;
> -    }
> -
>   	if (get_nat_flag(ne, IS_DIRTY))
>   		goto refresh_list;
>   
>   	nm_i->nat_cnt[DIRTY_NAT]++;
> -	nm_i->nat_cnt[RECLAIMABLE_NAT]--;
> +	if (!init_dirty)
> +		nm_i->nat_cnt[RECLAIMABLE_NAT]--;
>   	set_nat_flag(ne, IS_DIRTY, true);
>   refresh_list:
>   	spin_lock(&nm_i->nat_list_lock);
> 
>>> +
>>>   	if (get_nat_flag(ne, IS_DIRTY))
>>>   		goto refresh_list;
>>>   
>>> @@ -441,7 +458,7 @@ static void cache_nat_entry(struct f2fs_sb_info *sbi, nid_t nid,
>>>   	f2fs_down_write(&nm_i->nat_tree_lock);
>>>   	e = __lookup_nat_cache(nm_i, nid, false);
>>>   	if (!e)
>>> -		e = __init_nat_entry(nm_i, new, ne, false);
>>> +		e = __init_nat_entry(nm_i, new, ne, false, false);
>>>   	else
>>>   		f2fs_bug_on(sbi, nat_get_ino(e) != le32_to_cpu(ne->ino) ||
>>>   				nat_get_blkaddr(e) !=
>>> @@ -458,11 +475,13 @@ static void set_node_addr(struct f2fs_sb_info *sbi, struct node_info *ni,
>>>   	struct f2fs_nm_info *nm_i = NM_I(sbi);
>>>   	struct nat_entry *e;
>>>   	struct nat_entry *new = __alloc_nat_entry(sbi, ni->nid, true);
>>> +	bool init_dirty = false;
>>>   
>>>   	f2fs_down_write(&nm_i->nat_tree_lock);
>>>   	e = __lookup_nat_cache(nm_i, ni->nid, true);
>>>   	if (!e) {
>>> -		e = __init_nat_entry(nm_i, new, NULL, true);
>>> +		init_dirty = true;
>>> +		e = __init_nat_entry(nm_i, new, NULL, true, true);
>>>   		copy_node_info(&e->ni, ni);
>>>   		f2fs_bug_on(sbi, ni->blk_addr == NEW_ADDR);
>>>   	} else if (new_blkaddr == NEW_ADDR) {
>>> @@ -498,7 +517,7 @@ static void set_node_addr(struct f2fs_sb_info *sbi, struct node_info *ni,
>>>   	nat_set_blkaddr(e, new_blkaddr);
>>>   	if (!__is_valid_data_blkaddr(new_blkaddr))
>>>   		set_nat_flag(e, IS_CHECKPOINTED, false);
>>> -	__set_nat_cache_dirty(nm_i, e);
>>> +	__set_nat_cache_dirty(nm_i, e, init_dirty);
>>>   
>>>   	/* update fsync_mark if its inode nat entry is still alive */
>>>   	if (ni->nid != ni->ino)
>>> @@ -2924,6 +2943,7 @@ static void remove_nats_in_journal(struct f2fs_sb_info *sbi)
>>>   	struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA);
>>>   	struct f2fs_journal *journal = curseg->journal;
>>>   	int i;
>>> +	bool init_dirty;
>>>   
>>>   	down_write(&curseg->journal_rwsem);
>>>   	for (i = 0; i < nats_in_cursum(journal); i++) {
>>> @@ -2934,12 +2954,15 @@ static void remove_nats_in_journal(struct f2fs_sb_info *sbi)
>>>   		if (f2fs_check_nid_range(sbi, nid))
>>>   			continue;
>>>   
>>> +		init_dirty = false;
>>> +
>>>   		raw_ne = nat_in_journal(journal, i);
>>>   
>>>   		ne = __lookup_nat_cache(nm_i, nid, true);
>>>   		if (!ne) {
>>> +			init_dirty = true;
>>>   			ne = __alloc_nat_entry(sbi, nid, true);
>>> -			__init_nat_entry(nm_i, ne, &raw_ne, true);
>>> +			__init_nat_entry(nm_i, ne, &raw_ne, true, true);
>>>   		}
>>>   
>>>   		/*
>>> @@ -2954,7 +2977,7 @@ static void remove_nats_in_journal(struct f2fs_sb_info *sbi)
>>>   			spin_unlock(&nm_i->nid_list_lock);
>>>   		}
>>>   
>>> -		__set_nat_cache_dirty(nm_i, ne);
>>> +		__set_nat_cache_dirty(nm_i, ne, init_dirty);
>>>   	}
>>>   	update_nats_in_cursum(journal, -i);
>>>   	up_write(&curseg->journal_rwsem);
> 


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

end of thread, other threads:[~2025-07-25  2:36 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-07-22 14:36 [f2fs-dev] [PATCH v2 1/2] f2fs: avoid redundant clean nat entry move in lru list wangzijie
2025-07-22 14:36 ` [f2fs-dev] [PATCH v2 2/2] f2fs: directly add newly allocated pre-dirty nat entry to dirty set list wangzijie
2025-07-24  8:26   ` Chao Yu
2025-07-25  2:17     ` wangzijie
2025-07-25  2:36       ` Chao Yu
2025-07-24  6:00 ` [f2fs-dev] [PATCH v2 1/2] f2fs: avoid redundant clean nat entry move in lru list Chao Yu
2025-07-24  6:57   ` wangzijie

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