Skip to content

Commit

Permalink
erofs: fix refcount on the metabuf used for inode lookup
Browse files Browse the repository at this point in the history
commit 56ee7db upstream.

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: 500edd0 ("erofs: use meta buffers for inode lookup")
Cc: <stable@vger.kernel.org> # 5.18+
Signed-off-by: Sandeep Dhavale <dhavale@google.com>
Reviewed-by: Gao Xiang <hsiangkao@linux.alibaba.com>
Reviewed-by: Jingbo Xu <jefflexu@linux.alibaba.com>
Reviewed-by: Chao Yu <chao@kernel.org>
Link: https://lore.kernel.org/r/20240221210348.3667795-1-dhavale@google.com
Signed-off-by: Gao Xiang <hsiangkao@linux.alibaba.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Sandeep Dhavale authored and gregkh committed Mar 1, 2024
1 parent 763f1f1 commit ba84bbb
Showing 1 changed file with 14 additions and 14 deletions.
28 changes: 14 additions & 14 deletions fs/erofs/namei.c
Original file line number Diff line number Diff line change
Expand Up @@ -130,24 +130,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 */
Expand Down

0 comments on commit ba84bbb

Please sign in to comment.