Skip to contentSkip to conversation

erofs: fix refcount on the metabuf used for inode lookup

PATCH Superseded Sandeep Dhavale 2 participants 3 messages Feb 20, 2024 – Feb 21, 2024

Subsystems (2)

v1 of 2 Superseded Latest is v2 →

lore
Share & tools
lore

Sandeep Dhavale

author reviewer
#0 lore raw

PATCH 1/1 erofs: fix refcount on the metabuf used for inode lookup

In erofs_find_target_block() when erofs_dirnamecmp() returns 0, we do not assign the target metabuf. This causes the caller erofs_namei()'s erofs_put_metabuf() at the end to be not effective leaving the refcount on the page.
As the page from metabuf (buf->page) is never put, such page cannot be migrated or reclaimed. Fix it now by putting the metabuf from previous loop and assigning the current metabuf to target before returning so caller erofs_namei() can do the final put as it was intended.

Fixes 500edd095648 ("erofs: use meta buffers for inode lookup")
---
 fs/erofs/namei.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
fs/erofs/namei.c +4 -1
index d4f631d39f0f..bfe1c926436b 100644
@@ -132,7 +132,10 @@ static void *erofs_find_target_block(struct erofs_buf *target,
 
 			if (!diff) {
 				*_ndirents = 0;
-				goto out;
+				if (!IS_ERR(candidate))
+					erofs_put_metabuf(target);
+				*target = buf;
+				return de;
 			} else if (diff > 0) {
 				head = mid + 1;
 				startprfx = matched;
Signature · 1 line
2.44.0.rc0.258.g7320e95886-goog
#1 lore raw

Hi Sandeep,

Quoted 10 lines · Sandeep Dhavale

In erofs_find_target_block() when erofs_dirnamecmp() returns 0, we do not assign the target metabuf. This causes the caller erofs_namei()'s erofs_put_metabuf() at the end to be not effective leaving the refcount on the page.
As the page from metabuf (buf->page) is never put, such page cannot be migrated or reclaimed. Fix it now by putting the metabuf from previous loop and assigning the current metabuf to target before returning so caller erofs_namei() can do the final put as it was intended.

Quoted 3 lines
Fixes 500edd095648 ("erofs: use meta buffers for inode lookup")

Many thanks for the catch!

Quoted 10 lines
---
  fs/erofs/namei.c | 5 ++++-
  1 file changed, 4 insertions(+), 1 deletion(-)
fs/erofs/namei.c +0 -0
index d4f631d39f0f..bfe1c926436b 100644
@@ -132,7 +132,10 @@ static void *erofs_find_target_block(struct erofs_buf *target,
 

fs/erofs/namei.c static void *erofs_find_target_block(struct erofs_buf *target, · line 141

Quoted 10 lines
fs/erofs/namei.c +4 -1
  			if (!diff) {
  				*_ndirents = 0;
-				goto out;
+				if (!IS_ERR(candidate))
+					erofs_put_metabuf(target);
+				*target = buf;
+				return de;
  			} else if (diff > 0) {
  				head = mid + 1;
  				startprfx = matched;

The fix is correct, yet I tend to try to reorganize this snippet for simplicity, how about the following diff (untested)?

If it looks good to you, could you resend a formal patch? Thanks!

Thanks,
Gao Xiang

 fs/erofs/namei.c | 29 ++++++++++++++---------------
 1 file changed, 14 insertions(+), 15 deletions(-)
fs/erofs/namei.c +14 -15
index d4f631d39f0f..9fb2d627578e 100644
@@ -129,25 +129,24 @@ static void *erofs_find_target_block(struct erofs_buf *target,
 
 			/* string comparison without already matched prefix */
 			diff = erofs_dirnamecmp(name, &dname, &matched);
-
-			if (!diff) {
-				*_ndirents = 0;
-				goto out;
-			} else if (diff > 0) {
-				head = mid + 1;
-				startprfx = matched;
-
-				if (!IS_ERR(candidate))
-					erofs_put_metabuf(target);
-				*target = buf;
-				candidate = de;
-				*_ndirents = ndirents;
-			} else {
+			if (diff < 0) {
 				erofs_put_metabuf(&buf);
-
 				back = mid - 1;
 				endprfx = matched;
+				continue;
 			}
+
+			if (!IS_ERR(candidate))
+				erofs_put_metabuf(target);
+			*target = buf;
+			if (!diff) {
+				*_ndirents = 0;
+				return de;
+			}
+			head = mid + 1;
+			startprfx = matched;
+			candidate = de;
+			*_ndirents = ndirents;
 			continue;
 		}
 out:		/* free if the candidate is valid */

--
2.39.3

author reviewer
#2 lore raw
Quoted 3 lines

If it looks good to you, could you resend a formal patch? Thanks!

Hi Gao,
This looks better and more readable. I will send a v2.

Thanks,
Sandeep.

Quoted 2 lines

Thanks,
Gao Xiang