All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] fs: btrfs: report file sizes from readdir
@ 2026-08-02  5:42 Cole Munz
  2026-08-02  6:02 ` Alexey Charkov
  0 siblings, 1 reply; 12+ messages in thread
From: Cole Munz @ 2026-08-02  5:42 UTC (permalink / raw)
  To: u-boot; +Cc: Alexey Charkov, Qu Wenruo, Marek Behun, Tom Rini

btrfs_readdir() zeroes the dirent and fills in only the name and the
type, so dent->size stays 0 and every file is listed as zero bytes:

  => ls host 0 /
          0   f_192k.bin
          0   small_3k.bin

Reads themselves are fine, since btrfs_read() takes the size from
btrfs_size(), which does its own inode item lookup. It affects EFI
too: dir_read() in lib/efi_loader/efi_file.c copies dent->size into
both file_size and physical_size, so an EFI application enumerating a
directory on btrfs sees every file as empty, which is the generic-code
path Alexey's readdir series moves btrfs onto.

The custom listing that fs_ls_generic() replaced looked the inode item
up and printed the real size, and every other filesystem in the tree
fills dent->size in its own readdir: ext4fs.c:327, exfat io.c:805,
erofs fs.c:186, squashfs sqfs.c:1095 and fat.c:1555.

btrfs_next_dir_entry() already has the dir item mapped, so read the
key it points at while we are there and hand it back to the caller,
and use that to reach the inode item. A subvolume entry points at a
root item instead and has no size of its own, so leave that one at 0.

  => ls host 0 /
     196608   f_192k.bin
       3000   small_3k.bin

Fixes: 31cf3f177823 ("fs: btrfs: use fs_ls_generic() and drop custom implementation")
Signed-off-by: Cole Munz <Munzzyy1@proton.me>
---
The Fixes: commit is in Tom's tree, applied 2026-07-10 (b4-ty
178372904690.2905849.8798963092987519032.b4-ty@konsulko.com); it has not
reached master yet, so that SHA will not resolve on a public clone today.

Found by a btrfs test suite I am preparing for test/py; I will send that
separately once the pending zstd inline extent fix is applied, since it
depends on it.
 fs/btrfs/btrfs.c    | 24 +++++++++++++++++++++++-
 fs/btrfs/ctree.h    |  3 ++-
 fs/btrfs/dir-item.c |  7 ++++++-
 3 files changed, 31 insertions(+), 3 deletions(-)

diff --git a/fs/btrfs/btrfs.c b/fs/btrfs/btrfs.c
index e663dda12e80..b2856be0662f 100644
--- a/fs/btrfs/btrfs.c
+++ b/fs/btrfs/btrfs.c
@@ -93,7 +93,10 @@ int btrfs_readdir(struct fs_dir_stream *fs_dirs, struct fs_dirent **dentp)
 	struct btrfs_dir_stream *dirs = container_of(fs_dirs, struct btrfs_dir_stream, parent);
 	struct btrfs_fs_info *fs_info = current_fs_info;
 	struct fs_dirent *dent = &dirs->dirent;
+	struct btrfs_inode_item *ii;
 	struct btrfs_root *root;
+	struct btrfs_path path;
+	struct btrfs_key location;
 	struct btrfs_key key;
 	u8 type;
 	int ret;
@@ -110,13 +113,32 @@ int btrfs_readdir(struct fs_dir_stream *fs_dirs, struct fs_dirent **dentp)
 
 	memset(dent, 0, sizeof(*dent));
 	ret = btrfs_next_dir_entry(root, dirs->ino, &dirs->offset, dent->name,
-				   sizeof(dent->name), &type);
+				   sizeof(dent->name), &type, &location);
 	if (ret < 0)
 		return ret;
 	if (ret > 0)
 		return -ENOENT;
 
 	dent->type = btrfs_dirent_type_to_fs_type(type);
+
+	/*
+	 * A subvolume entry points at a root item rather than an inode, and
+	 * has no size of its own.  Everything else carries one, and the fs
+	 * layer prints it, so look it up.
+	 */
+	if (location.type == BTRFS_INODE_ITEM_KEY) {
+		btrfs_init_path(&path);
+		ret = btrfs_search_slot(NULL, root, &location, &path, 0, 0);
+		if (ret == 0) {
+			ii = btrfs_item_ptr(path.nodes[0], path.slots[0],
+					    struct btrfs_inode_item);
+			dent->size = btrfs_inode_size(path.nodes[0], ii);
+		}
+		btrfs_release_path(&path);
+		if (ret < 0)
+			return ret;
+	}
+
 	*dentp = dent;
 	return 0;
 }
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 3fa9a8c9c020..cd3fd669f9ae 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -1221,7 +1221,8 @@ struct btrfs_dir_item *btrfs_lookup_dir_item(struct btrfs_trans_handle *trans,
 					     const char *name, int name_len,
 					     int mod);
 int btrfs_next_dir_entry(struct btrfs_root *root, u64 ino, u64 *offset,
-			 char *namebuf, int namebuf_len, u8 *ftype);
+			 char *namebuf, int namebuf_len, u8 *ftype,
+			 struct btrfs_key *location);
 /* inode.c */
 int btrfs_lookup_path(struct btrfs_root *root, u64 ino, const char *filename,
 			struct btrfs_root **root_ret, u64 *ino_ret,
diff --git a/fs/btrfs/dir-item.c b/fs/btrfs/dir-item.c
index c7b87d60d986..6edda34818b8 100644
--- a/fs/btrfs/dir-item.c
+++ b/fs/btrfs/dir-item.c
@@ -126,12 +126,16 @@ struct btrfs_dir_item *btrfs_lookup_dir_item(struct btrfs_trans_handle *trans,
  * @namebuf:		caller buffer that receives the NUL-terminated name
  * @namebuf_len:	size of @namebuf in bytes
  * @ftype:		receives the BTRFS_FT_* type of the entry
+ * @location:		receives the key the entry points at, so the caller can
+ *			reach the inode item without searching for the name
+ *			again
  *
  * Return: 0 if an entry was returned, 1 when the directory is exhausted,
  *	   -ve on error.
  */
 int btrfs_next_dir_entry(struct btrfs_root *root, u64 ino, u64 *offset,
-			 char *namebuf, int namebuf_len, u8 *ftype)
+			 char *namebuf, int namebuf_len, u8 *ftype,
+			 struct btrfs_key *location)
 {
 	struct btrfs_path path;
 	struct btrfs_key key;
@@ -180,6 +184,7 @@ int btrfs_next_dir_entry(struct btrfs_root *root, u64 ino, u64 *offset,
 			   (unsigned long)(di + 1), name_len);
 	namebuf[name_len] = '\0';
 	*ftype = btrfs_dir_type(path.nodes[0], di);
+	btrfs_dir_item_key_to_cpu(path.nodes[0], di, location);
 	ret = 0;
 
 out:
-- 
2.55.0



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

* Re: [PATCH] fs: btrfs: report file sizes from readdir
  2026-08-02  5:42 [PATCH] fs: btrfs: report file sizes from readdir Cole Munz
@ 2026-08-02  6:02 ` Alexey Charkov
  2026-08-02  6:44   ` [PATCH v2] " Cole Munz
  2026-08-02  6:47   ` [PATCH] " Qu Wenruo
  0 siblings, 2 replies; 12+ messages in thread
From: Alexey Charkov @ 2026-08-02  6:02 UTC (permalink / raw)
  To: Cole Munz; +Cc: u-boot, Qu Wenruo, Marek Behun, Tom Rini

Hi Cole,

On Sun, Aug 2, 2026 at 9:42 AM Cole Munz <Munzzyy1@proton.me> wrote:
>
> btrfs_readdir() zeroes the dirent and fills in only the name and the
> type, so dent->size stays 0 and every file is listed as zero bytes:
>
>   => ls host 0 /
>           0   f_192k.bin
>           0   small_3k.bin
>
> Reads themselves are fine, since btrfs_read() takes the size from
> btrfs_size(), which does its own inode item lookup. It affects EFI
> too: dir_read() in lib/efi_loader/efi_file.c copies dent->size into
> both file_size and physical_size, so an EFI application enumerating a
> directory on btrfs sees every file as empty, which is the generic-code
> path Alexey's readdir series moves btrfs onto.
>
> The custom listing that fs_ls_generic() replaced looked the inode item
> up and printed the real size, and every other filesystem in the tree
> fills dent->size in its own readdir: ext4fs.c:327, exfat io.c:805,
> erofs fs.c:186, squashfs sqfs.c:1095 and fat.c:1555.
>
> btrfs_next_dir_entry() already has the dir item mapped, so read the
> key it points at while we are there and hand it back to the caller,
> and use that to reach the inode item. A subvolume entry points at a
> root item instead and has no size of its own, so leave that one at 0.
>
>   => ls host 0 /
>      196608   f_192k.bin
>        3000   small_3k.bin
>
> Fixes: 31cf3f177823 ("fs: btrfs: use fs_ls_generic() and drop custom implementation")
> Signed-off-by: Cole Munz <Munzzyy1@proton.me>
> ---
> The Fixes: commit is in Tom's tree, applied 2026-07-10 (b4-ty
> 178372904690.2905849.8798963092987519032.b4-ty@konsulko.com); it has not
> reached master yet, so that SHA will not resolve on a public clone today.
>
> Found by a btrfs test suite I am preparing for test/py; I will send that
> separately once the pending zstd inline extent fix is applied, since it
> depends on it.
>  fs/btrfs/btrfs.c    | 24 +++++++++++++++++++++++-
>  fs/btrfs/ctree.h    |  3 ++-
>  fs/btrfs/dir-item.c |  7 ++++++-
>  3 files changed, 31 insertions(+), 3 deletions(-)
>
> diff --git a/fs/btrfs/btrfs.c b/fs/btrfs/btrfs.c
> index e663dda12e80..b2856be0662f 100644
> --- a/fs/btrfs/btrfs.c
> +++ b/fs/btrfs/btrfs.c
> @@ -93,7 +93,10 @@ int btrfs_readdir(struct fs_dir_stream *fs_dirs, struct fs_dirent **dentp)
>         struct btrfs_dir_stream *dirs = container_of(fs_dirs, struct btrfs_dir_stream, parent);
>         struct btrfs_fs_info *fs_info = current_fs_info;
>         struct fs_dirent *dent = &dirs->dirent;
> +       struct btrfs_inode_item *ii;
>         struct btrfs_root *root;
> +       struct btrfs_path path;
> +       struct btrfs_key location;
>         struct btrfs_key key;
>         u8 type;
>         int ret;
> @@ -110,13 +113,32 @@ int btrfs_readdir(struct fs_dir_stream *fs_dirs, struct fs_dirent **dentp)
>
>         memset(dent, 0, sizeof(*dent));
>         ret = btrfs_next_dir_entry(root, dirs->ino, &dirs->offset, dent->name,
> -                                  sizeof(dent->name), &type);
> +                                  sizeof(dent->name), &type, &location);
>         if (ret < 0)
>                 return ret;
>         if (ret > 0)
>                 return -ENOENT;
>
>         dent->type = btrfs_dirent_type_to_fs_type(type);
> +
> +       /*
> +        * A subvolume entry points at a root item rather than an inode, and
> +        * has no size of its own.  Everything else carries one, and the fs
> +        * layer prints it, so look it up.
> +        */
> +       if (location.type == BTRFS_INODE_ITEM_KEY) {
> +               btrfs_init_path(&path);
> +               ret = btrfs_search_slot(NULL, root, &location, &path, 0, 0);
> +               if (ret == 0) {
> +                       ii = btrfs_item_ptr(path.nodes[0], path.slots[0],
> +                                           struct btrfs_inode_item);
> +                       dent->size = btrfs_inode_size(path.nodes[0], ii);
> +               }
> +               btrfs_release_path(&path);

The above repeats much of the calls that have just been done for this
exact entry several lines above inside btrfs_read_next_dir_enrty()

Can you perhaps refactor to avoid this repetition?

Best regards,
Alexey

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

* [PATCH v2] fs: btrfs: report file sizes from readdir
  2026-08-02  6:02 ` Alexey Charkov
@ 2026-08-02  6:44   ` Cole Munz
  2026-08-02  6:47   ` [PATCH] " Qu Wenruo
  1 sibling, 0 replies; 12+ messages in thread
From: Cole Munz @ 2026-08-02  6:44 UTC (permalink / raw)
  To: u-boot; +Cc: Alexey Charkov, Qu Wenruo, Marek Behun, Tom Rini

btrfs_readdir() zeroes the dirent and fills in only the name and the
type, so dent->size stays 0 and every file is listed as zero bytes:

  => ls host 0 /
          0   f_192k.bin
          0   small_3k.bin

Reads themselves are fine, since btrfs_read() takes the size from
btrfs_size(), which does its own inode item lookup. It affects EFI
too: dir_read() in lib/efi_loader/efi_file.c copies dent->size into
both file_size and physical_size, so an EFI application enumerating a
directory on btrfs sees every file as empty, which is the generic-code
path Alexey's readdir series moves btrfs onto.

The custom listing that fs_ls_generic() replaced looked the inode item
up and printed the real size, and every other filesystem in the tree
fills dent->size in its own readdir: ext4fs.c:327, exfat io.c:805,
erofs fs.c:186, squashfs sqfs.c:1095 and fat.c:1555.

btrfs_next_dir_entry() already has the dir item mapped, so read the
key it points at while we are there and hand it back to the caller.
The inode item is a separate key, so reaching it still takes a second
search, but btrfs_size() already open-codes that exact search, so pull
it into a helper both callers share. That also closes a path leak in
btrfs_size(), which returned without releasing on a search error. A
subvolume entry points at a root item instead and has no size of its
own, so leave that one at 0.

  => ls host 0 /
     196608   f_192k.bin
       3000   small_3k.bin

Fixes: 31cf3f177823 ("fs: btrfs: use fs_ls_generic() and drop custom implementation")
Signed-off-by: Cole Munz <Munzzyy1@proton.me>
---
The second search itself cannot go away, since the dir index item and
the inode item it points at are separate keys, and the old custom
lister did the same two lookups per entry. What can go away is the
open-coded machinery: btrfs_size() carries an identical search, so v2
moves it into one helper both callers use. That also fixes btrfs_size()
returning without releasing the path when the search errors out.

Changes in v2:
- pull the inode item search into a helper shared with btrfs_size()
  instead of open-coding a second copy (Alexey)

Still passes the btrfs suite from the pending test series on top of
this patch plus the readdir series: 5 passed.
 fs/btrfs/btrfs.c    | 75 +++++++++++++++++++++++++++++++--------------
 fs/btrfs/ctree.h    |  3 +-
 fs/btrfs/dir-item.c |  7 ++++-
 3 files changed, 60 insertions(+), 25 deletions(-)

diff --git a/fs/btrfs/btrfs.c b/fs/btrfs/btrfs.c
index e663dda12e80..dea155bd150e 100644
--- a/fs/btrfs/btrfs.c
+++ b/fs/btrfs/btrfs.c
@@ -88,12 +88,41 @@ static unsigned int btrfs_dirent_type_to_fs_type(u8 dirent_type)
 	}
 }
 
+/*
+ * Read the size stored in an inode item.  A missing item is -ENOENT and
+ * leaves *size untouched.
+ */
+static int btrfs_get_inode_size(struct btrfs_root *root, u64 ino, u64 *size)
+{
+	struct btrfs_inode_item *ii;
+	struct btrfs_path path;
+	struct btrfs_key key;
+	int ret;
+
+	key.objectid = ino;
+	key.type = BTRFS_INODE_ITEM_KEY;
+	key.offset = 0;
+
+	btrfs_init_path(&path);
+	ret = btrfs_search_slot(NULL, root, &key, &path, 0, 0);
+	if (ret > 0)
+		ret = -ENOENT;
+	if (!ret) {
+		ii = btrfs_item_ptr(path.nodes[0], path.slots[0],
+				    struct btrfs_inode_item);
+		*size = btrfs_inode_size(path.nodes[0], ii);
+	}
+	btrfs_release_path(&path);
+	return ret;
+}
+
 int btrfs_readdir(struct fs_dir_stream *fs_dirs, struct fs_dirent **dentp)
 {
 	struct btrfs_dir_stream *dirs = container_of(fs_dirs, struct btrfs_dir_stream, parent);
 	struct btrfs_fs_info *fs_info = current_fs_info;
 	struct fs_dirent *dent = &dirs->dirent;
 	struct btrfs_root *root;
+	struct btrfs_key location;
 	struct btrfs_key key;
 	u8 type;
 	int ret;
@@ -110,13 +139,29 @@ int btrfs_readdir(struct fs_dir_stream *fs_dirs, struct fs_dirent **dentp)
 
 	memset(dent, 0, sizeof(*dent));
 	ret = btrfs_next_dir_entry(root, dirs->ino, &dirs->offset, dent->name,
-				   sizeof(dent->name), &type);
+				   sizeof(dent->name), &type, &location);
 	if (ret < 0)
 		return ret;
 	if (ret > 0)
 		return -ENOENT;
 
 	dent->type = btrfs_dirent_type_to_fs_type(type);
+
+	/*
+	 * A subvolume entry points at a root item rather than an inode, and
+	 * has no size of its own.  Everything else carries one, and the fs
+	 * layer prints it, so look it up.
+	 */
+	if (location.type == BTRFS_INODE_ITEM_KEY) {
+		u64 size;
+
+		ret = btrfs_get_inode_size(root, location.objectid, &size);
+		if (ret < 0 && ret != -ENOENT)
+			return ret;
+		if (!ret)
+			dent->size = size;
+	}
+
 	*dentp = dent;
 	return 0;
 }
@@ -151,10 +196,8 @@ int btrfs_exists(const char *file)
 int btrfs_size(const char *file, loff_t *size)
 {
 	struct btrfs_fs_info *fs_info = current_fs_info;
-	struct btrfs_inode_item *ii;
 	struct btrfs_root *root;
-	struct btrfs_path path;
-	struct btrfs_key key;
+	u64 isize;
 	u64 ino;
 	u8 type;
 	int ret;
@@ -169,27 +212,13 @@ int btrfs_size(const char *file, loff_t *size)
 		printf("Not a regular file: %s\n", file);
 		return -ENOENT;
 	}
-	btrfs_init_path(&path);
-	key.objectid = ino;
-	key.type = BTRFS_INODE_ITEM_KEY;
-	key.offset = 0;
-
-	ret = btrfs_search_slot(NULL, root, &key, &path, 0, 0);
-	if (ret < 0) {
-		printf("Cannot lookup ino %llu\n", ino);
+	ret = btrfs_get_inode_size(root, ino, &isize);
+	if (ret) {
+		printf("Cannot read size of ino %llu\n", ino);
 		return ret;
 	}
-	if (ret > 0) {
-		printf("Ino %llu does not exist\n", ino);
-		ret = -ENOENT;
-		goto out;
-	}
-	ii = btrfs_item_ptr(path.nodes[0], path.slots[0],
-			    struct btrfs_inode_item);
-	*size = btrfs_inode_size(path.nodes[0], ii);
-out:
-	btrfs_release_path(&path);
-	return ret;
+	*size = isize;
+	return 0;
 }
 
 int btrfs_read(const char *file, void *buf, loff_t offset, loff_t len,
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 3fa9a8c9c020..cd3fd669f9ae 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -1221,7 +1221,8 @@ struct btrfs_dir_item *btrfs_lookup_dir_item(struct btrfs_trans_handle *trans,
 					     const char *name, int name_len,
 					     int mod);
 int btrfs_next_dir_entry(struct btrfs_root *root, u64 ino, u64 *offset,
-			 char *namebuf, int namebuf_len, u8 *ftype);
+			 char *namebuf, int namebuf_len, u8 *ftype,
+			 struct btrfs_key *location);
 /* inode.c */
 int btrfs_lookup_path(struct btrfs_root *root, u64 ino, const char *filename,
 			struct btrfs_root **root_ret, u64 *ino_ret,
diff --git a/fs/btrfs/dir-item.c b/fs/btrfs/dir-item.c
index c7b87d60d986..6edda34818b8 100644
--- a/fs/btrfs/dir-item.c
+++ b/fs/btrfs/dir-item.c
@@ -126,12 +126,16 @@ struct btrfs_dir_item *btrfs_lookup_dir_item(struct btrfs_trans_handle *trans,
  * @namebuf:		caller buffer that receives the NUL-terminated name
  * @namebuf_len:	size of @namebuf in bytes
  * @ftype:		receives the BTRFS_FT_* type of the entry
+ * @location:		receives the key the entry points at, so the caller can
+ *			reach the inode item without searching for the name
+ *			again
  *
  * Return: 0 if an entry was returned, 1 when the directory is exhausted,
  *	   -ve on error.
  */
 int btrfs_next_dir_entry(struct btrfs_root *root, u64 ino, u64 *offset,
-			 char *namebuf, int namebuf_len, u8 *ftype)
+			 char *namebuf, int namebuf_len, u8 *ftype,
+			 struct btrfs_key *location)
 {
 	struct btrfs_path path;
 	struct btrfs_key key;
@@ -180,6 +184,7 @@ int btrfs_next_dir_entry(struct btrfs_root *root, u64 ino, u64 *offset,
 			   (unsigned long)(di + 1), name_len);
 	namebuf[name_len] = '\0';
 	*ftype = btrfs_dir_type(path.nodes[0], di);
+	btrfs_dir_item_key_to_cpu(path.nodes[0], di, location);
 	ret = 0;
 
 out:
-- 
2.55.0



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

* Re: [PATCH] fs: btrfs: report file sizes from readdir
  2026-08-02  6:02 ` Alexey Charkov
  2026-08-02  6:44   ` [PATCH v2] " Cole Munz
@ 2026-08-02  6:47   ` Qu Wenruo
  2026-08-02  7:37     ` Cole Munz
  1 sibling, 1 reply; 12+ messages in thread
From: Qu Wenruo @ 2026-08-02  6:47 UTC (permalink / raw)
  To: Alexey Charkov, Cole Munz; +Cc: u-boot, Marek Behun, Tom Rini



在 2026/8/2 15:32, Alexey Charkov 写道:
> Hi Cole,
> 
> On Sun, Aug 2, 2026 at 9:42 AM Cole Munz <Munzzyy1@proton.me> wrote:
>>
>> btrfs_readdir() zeroes the dirent and fills in only the name and the
>> type, so dent->size stays 0 and every file is listed as zero bytes:
>>
>>    => ls host 0 /
>>            0   f_192k.bin
>>            0   small_3k.bin
>>
>> Reads themselves are fine, since btrfs_read() takes the size from
>> btrfs_size(), which does its own inode item lookup. It affects EFI
>> too: dir_read() in lib/efi_loader/efi_file.c copies dent->size into
>> both file_size and physical_size, so an EFI application enumerating a
>> directory on btrfs sees every file as empty, which is the generic-code
>> path Alexey's readdir series moves btrfs onto.
>>
>> The custom listing that fs_ls_generic() replaced looked the inode item
>> up and printed the real size, and every other filesystem in the tree
>> fills dent->size in its own readdir: ext4fs.c:327, exfat io.c:805,
>> erofs fs.c:186, squashfs sqfs.c:1095 and fat.c:1555.
>>
>> btrfs_next_dir_entry() already has the dir item mapped, so read the
>> key it points at while we are there and hand it back to the caller,
>> and use that to reach the inode item. A subvolume entry points at a
>> root item instead and has no size of its own, so leave that one at 0.
>>
>>    => ls host 0 /
>>       196608   f_192k.bin
>>         3000   small_3k.bin
>>
>> Fixes: 31cf3f177823 ("fs: btrfs: use fs_ls_generic() and drop custom implementation")
>> Signed-off-by: Cole Munz <Munzzyy1@proton.me>
>> ---
>> The Fixes: commit is in Tom's tree, applied 2026-07-10 (b4-ty
>> 178372904690.2905849.8798963092987519032.b4-ty@konsulko.com); it has not
>> reached master yet, so that SHA will not resolve on a public clone today.
>>
>> Found by a btrfs test suite I am preparing for test/py; I will send that
>> separately once the pending zstd inline extent fix is applied, since it
>> depends on it.
>>   fs/btrfs/btrfs.c    | 24 +++++++++++++++++++++++-
>>   fs/btrfs/ctree.h    |  3 ++-
>>   fs/btrfs/dir-item.c |  7 ++++++-
>>   3 files changed, 31 insertions(+), 3 deletions(-)
>>
>> diff --git a/fs/btrfs/btrfs.c b/fs/btrfs/btrfs.c
>> index e663dda12e80..b2856be0662f 100644
>> --- a/fs/btrfs/btrfs.c
>> +++ b/fs/btrfs/btrfs.c
>> @@ -93,7 +93,10 @@ int btrfs_readdir(struct fs_dir_stream *fs_dirs, struct fs_dirent **dentp)
>>          struct btrfs_dir_stream *dirs = container_of(fs_dirs, struct btrfs_dir_stream, parent);
>>          struct btrfs_fs_info *fs_info = current_fs_info;
>>          struct fs_dirent *dent = &dirs->dirent;
>> +       struct btrfs_inode_item *ii;
>>          struct btrfs_root *root;
>> +       struct btrfs_path path;
>> +       struct btrfs_key location;
>>          struct btrfs_key key;
>>          u8 type;
>>          int ret;
>> @@ -110,13 +113,32 @@ int btrfs_readdir(struct fs_dir_stream *fs_dirs, struct fs_dirent **dentp)
>>
>>          memset(dent, 0, sizeof(*dent));
>>          ret = btrfs_next_dir_entry(root, dirs->ino, &dirs->offset, dent->name,
>> -                                  sizeof(dent->name), &type);
>> +                                  sizeof(dent->name), &type, &location);
>>          if (ret < 0)
>>                  return ret;
>>          if (ret > 0)
>>                  return -ENOENT;
>>
>>          dent->type = btrfs_dirent_type_to_fs_type(type);
>> +
>> +       /*
>> +        * A subvolume entry points at a root item rather than an inode, and
>> +        * has no size of its own.  Everything else carries one, and the fs
>> +        * layer prints it, so look it up.
>> +        */
>> +       if (location.type == BTRFS_INODE_ITEM_KEY) {
>> +               btrfs_init_path(&path);
>> +               ret = btrfs_search_slot(NULL, root, &location, &path, 0, 0);
>> +               if (ret == 0) {
>> +                       ii = btrfs_item_ptr(path.nodes[0], path.slots[0],
>> +                                           struct btrfs_inode_item);
>> +                       dent->size = btrfs_inode_size(path.nodes[0], ii);
>> +               }
>> +               btrfs_release_path(&path);
> 
> The above repeats much of the calls that have just been done for this
> exact entry several lines above inside btrfs_read_next_dir_enrty()
> 
> Can you perhaps refactor to avoid this repetition?

Sorry I didn't see the point.

The function btrfs_read_next_dirty_entry() is search the key inside the 
parent directory.

Meanwhile this one is search for the inode item of the child entry.

They are completely different and I didn't see why "refactor" can improve.

In fact, this version is much simpler:

  fs/btrfs/btrfs.c    | 24 +++++++++++++++++++++++-
  fs/btrfs/ctree.h    |  3 ++-
  fs/btrfs/dir-item.c |  7 ++++++-
  3 files changed, 31 insertions(+), 3 deletions(-)

Compared to the v2:

  fs/btrfs/btrfs.c    | 75 +++++++++++++++++++++++++++++++--------------
  fs/btrfs/ctree.h    |  3 +-
  fs/btrfs/dir-item.c |  7 ++++-
  3 files changed, 60 insertions(+), 25 deletions(-)

Thanks,
Qu
> 
> Best regards,
> Alexey


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

* Re: [PATCH] fs: btrfs: report file sizes from readdir
  2026-08-02  6:47   ` [PATCH] " Qu Wenruo
@ 2026-08-02  7:37     ` Cole Munz
  2026-08-02  7:55       ` Qu Wenruo
  0 siblings, 1 reply; 12+ messages in thread
From: Cole Munz @ 2026-08-02  7:37 UTC (permalink / raw)
  To: Qu Wenruo, Alexey Charkov; +Cc: u-boot, Marek Behun, Tom Rini

On 2026/8/2 16:17, Qu Wenruo wrote:
> The function btrfs_read_next_dirty_entry() is search the key inside the
> parent directory.
>
> Meanwhile this one is search for the inode item of the child entry.
>
> They are completely different and I didn't see why "refactor" can improve.

Right, the two searches are for different keys and cannot be merged.
The repetition v2 removes is elsewhere. btrfs_size() open codes the
same inode item search, and its error path never releases the path.
That leaks the extent buffers btrfs_search_slot() attached before
failing. So v2 mixed a cleanup into a fix, which was the real
mistake here.

How about a v3 with the fix back in the v1 shape, plus a second patch
for the btrfs_size() helper and the missing release?


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

* Re: [PATCH] fs: btrfs: report file sizes from readdir
  2026-08-02  7:37     ` Cole Munz
@ 2026-08-02  7:55       ` Qu Wenruo
  2026-08-02  9:35         ` [PATCH v3 0/3] " Cole Munz
  0 siblings, 1 reply; 12+ messages in thread
From: Qu Wenruo @ 2026-08-02  7:55 UTC (permalink / raw)
  To: Cole Munz, Alexey Charkov; +Cc: u-boot, Marek Behun, Tom Rini



在 2026/8/2 17:07, Cole Munz 写道:
> On 2026/8/2 16:17, Qu Wenruo wrote:
>> The function btrfs_read_next_dirty_entry() is search the key inside the
>> parent directory.
>>
>> Meanwhile this one is search for the inode item of the child entry.
>>
>> They are completely different and I didn't see why "refactor" can improve.
> 
> Right, the two searches are for different keys and cannot be merged.
> The repetition v2 removes is elsewhere. btrfs_size() open codes the
> same inode item search, and its error path never releases the path.

OK, the u-boot's btrfs_search_slot() is different from kernel and progs, 
that on error it doesn't release the path.
So indeed we need to properly clean it up.

Although I'd prefer to change btrfs_search_slot() in u-boot to follow 
the same kernel/progs behavior.


For the new helper, btrfs_get_inode_size(), is indeed called in both 
btrfs_size() and btrfs_readdir(), so there is indeed some duplication.

> That leaks the extent buffers btrfs_search_slot() attached before
> failing. So v2 mixed a cleanup into a fix, which was the real
> mistake here.
> 
> How about a v3 with the fix back in the v1 shape, plus a second patch
> for the btrfs_size() helper and the missing release?
> 

That sounds very reasonable to me.

Thanks,
Qu

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

* [PATCH v3 0/3] fs: btrfs: report file sizes from readdir
  2026-08-02  7:55       ` Qu Wenruo
@ 2026-08-02  9:35         ` Cole Munz
  2026-08-02  9:35           ` [PATCH v3 1/3] " Cole Munz
                             ` (4 more replies)
  0 siblings, 5 replies; 12+ messages in thread
From: Cole Munz @ 2026-08-02  9:35 UTC (permalink / raw)
  To: u-boot; +Cc: Alexey Charkov, Qu Wenruo, Marek Behun, Tom Rini

As agreed on the v1 thread, the fix and the cleanups are now separate
patches:

- patch 1 is the fix in the v1 shape
- patch 2 makes btrfs_search_slot() release the path on error like
  the kernel version does. That is where the btrfs_size() leak came
  from. Suggested by Qu.
- patch 3 is the dedup Alexey asked about. One helper shared by
  btrfs_readdir() and btrfs_size().

The pending btrfs test suite still passes on top of the readdir
series: 5 passed.

Changes in v3: split the fix from the cleanups. The release moved
into btrfs_search_slot() itself.
Changes in v2: helper shared with btrfs_size() plus the leak fix in
one patch.

Cole Munz (3):
  fs: btrfs: report file sizes from readdir
  fs: btrfs: release the path when btrfs_search_slot() fails
  fs: btrfs: deduplicate the inode size lookup

 fs/btrfs/btrfs.c    | 77 +++++++++++++++++++++++++++++++--------------
 fs/btrfs/ctree.c    | 16 +++++++---
 fs/btrfs/ctree.h    |  3 +-
 fs/btrfs/dir-item.c |  7 ++++-
 4 files changed, 74 insertions(+), 29 deletions(-)

-- 
2.55.0



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

* [PATCH v3 1/3] fs: btrfs: report file sizes from readdir
  2026-08-02  9:35         ` [PATCH v3 0/3] " Cole Munz
@ 2026-08-02  9:35           ` Cole Munz
  2026-08-02  9:35           ` [PATCH v3 2/3] fs: btrfs: release the path when btrfs_search_slot() fails Cole Munz
                             ` (3 subsequent siblings)
  4 siblings, 0 replies; 12+ messages in thread
From: Cole Munz @ 2026-08-02  9:35 UTC (permalink / raw)
  To: u-boot; +Cc: Alexey Charkov, Qu Wenruo, Marek Behun, Tom Rini

btrfs_readdir() zeroes the dirent and fills in only the name and the
type, so dent->size stays 0 and every file is listed as zero bytes:

  => ls host 0 /
          0   f_192k.bin
          0   small_3k.bin

Reads themselves are fine, since btrfs_read() takes the size from
btrfs_size(), which does its own inode item lookup. It affects EFI
too: dir_read() in lib/efi_loader/efi_file.c copies dent->size into
both file_size and physical_size, so an EFI application enumerating a
directory on btrfs sees every file as empty, which is the generic-code
path Alexey's readdir series moves btrfs onto.

The custom listing that fs_ls_generic() replaced looked the inode item
up and printed the real size, and every other filesystem in the tree
fills dent->size in its own readdir: ext4fs.c:327, exfat io.c:805,
erofs fs.c:186, squashfs sqfs.c:1095 and fat.c:1555.

btrfs_next_dir_entry() already has the dir item mapped, so read the
key it points at while we are there and hand it back to the caller,
and use that to reach the inode item. A subvolume entry points at a
root item instead and has no size of its own, so leave that one at 0.

  => ls host 0 /
     196608   f_192k.bin
       3000   small_3k.bin

Fixes: 31cf3f177823 ("fs: btrfs: use fs_ls_generic() and drop custom implementation")
Signed-off-by: Cole Munz <Munzzyy1@proton.me>
---
 fs/btrfs/btrfs.c    | 24 +++++++++++++++++++++++-
 fs/btrfs/ctree.h    |  3 ++-
 fs/btrfs/dir-item.c |  7 ++++++-
 3 files changed, 31 insertions(+), 3 deletions(-)

diff --git a/fs/btrfs/btrfs.c b/fs/btrfs/btrfs.c
index e663dda12e80..b2856be0662f 100644
--- a/fs/btrfs/btrfs.c
+++ b/fs/btrfs/btrfs.c
@@ -93,7 +93,10 @@ int btrfs_readdir(struct fs_dir_stream *fs_dirs, struct fs_dirent **dentp)
 	struct btrfs_dir_stream *dirs = container_of(fs_dirs, struct btrfs_dir_stream, parent);
 	struct btrfs_fs_info *fs_info = current_fs_info;
 	struct fs_dirent *dent = &dirs->dirent;
+	struct btrfs_inode_item *ii;
 	struct btrfs_root *root;
+	struct btrfs_path path;
+	struct btrfs_key location;
 	struct btrfs_key key;
 	u8 type;
 	int ret;
@@ -110,13 +113,32 @@ int btrfs_readdir(struct fs_dir_stream *fs_dirs, struct fs_dirent **dentp)
 
 	memset(dent, 0, sizeof(*dent));
 	ret = btrfs_next_dir_entry(root, dirs->ino, &dirs->offset, dent->name,
-				   sizeof(dent->name), &type);
+				   sizeof(dent->name), &type, &location);
 	if (ret < 0)
 		return ret;
 	if (ret > 0)
 		return -ENOENT;
 
 	dent->type = btrfs_dirent_type_to_fs_type(type);
+
+	/*
+	 * A subvolume entry points at a root item rather than an inode, and
+	 * has no size of its own.  Everything else carries one, and the fs
+	 * layer prints it, so look it up.
+	 */
+	if (location.type == BTRFS_INODE_ITEM_KEY) {
+		btrfs_init_path(&path);
+		ret = btrfs_search_slot(NULL, root, &location, &path, 0, 0);
+		if (ret == 0) {
+			ii = btrfs_item_ptr(path.nodes[0], path.slots[0],
+					    struct btrfs_inode_item);
+			dent->size = btrfs_inode_size(path.nodes[0], ii);
+		}
+		btrfs_release_path(&path);
+		if (ret < 0)
+			return ret;
+	}
+
 	*dentp = dent;
 	return 0;
 }
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 3fa9a8c9c020..cd3fd669f9ae 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -1221,7 +1221,8 @@ struct btrfs_dir_item *btrfs_lookup_dir_item(struct btrfs_trans_handle *trans,
 					     const char *name, int name_len,
 					     int mod);
 int btrfs_next_dir_entry(struct btrfs_root *root, u64 ino, u64 *offset,
-			 char *namebuf, int namebuf_len, u8 *ftype);
+			 char *namebuf, int namebuf_len, u8 *ftype,
+			 struct btrfs_key *location);
 /* inode.c */
 int btrfs_lookup_path(struct btrfs_root *root, u64 ino, const char *filename,
 			struct btrfs_root **root_ret, u64 *ino_ret,
diff --git a/fs/btrfs/dir-item.c b/fs/btrfs/dir-item.c
index c7b87d60d986..6edda34818b8 100644
--- a/fs/btrfs/dir-item.c
+++ b/fs/btrfs/dir-item.c
@@ -126,12 +126,16 @@ struct btrfs_dir_item *btrfs_lookup_dir_item(struct btrfs_trans_handle *trans,
  * @namebuf:		caller buffer that receives the NUL-terminated name
  * @namebuf_len:	size of @namebuf in bytes
  * @ftype:		receives the BTRFS_FT_* type of the entry
+ * @location:		receives the key the entry points at, so the caller can
+ *			reach the inode item without searching for the name
+ *			again
  *
  * Return: 0 if an entry was returned, 1 when the directory is exhausted,
  *	   -ve on error.
  */
 int btrfs_next_dir_entry(struct btrfs_root *root, u64 ino, u64 *offset,
-			 char *namebuf, int namebuf_len, u8 *ftype)
+			 char *namebuf, int namebuf_len, u8 *ftype,
+			 struct btrfs_key *location)
 {
 	struct btrfs_path path;
 	struct btrfs_key key;
@@ -180,6 +184,7 @@ int btrfs_next_dir_entry(struct btrfs_root *root, u64 ino, u64 *offset,
 			   (unsigned long)(di + 1), name_len);
 	namebuf[name_len] = '\0';
 	*ftype = btrfs_dir_type(path.nodes[0], di);
+	btrfs_dir_item_key_to_cpu(path.nodes[0], di, location);
 	ret = 0;
 
 out:
-- 
2.55.0



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

* [PATCH v3 2/3] fs: btrfs: release the path when btrfs_search_slot() fails
  2026-08-02  9:35         ` [PATCH v3 0/3] " Cole Munz
  2026-08-02  9:35           ` [PATCH v3 1/3] " Cole Munz
@ 2026-08-02  9:35           ` Cole Munz
  2026-08-02  9:35           ` [PATCH v3 3/3] fs: btrfs: deduplicate the inode size lookup Cole Munz
                             ` (2 subsequent siblings)
  4 siblings, 0 replies; 12+ messages in thread
From: Cole Munz @ 2026-08-02  9:35 UTC (permalink / raw)
  To: u-boot; +Cc: Alexey Charkov, Qu Wenruo, Marek Behun, Tom Rini

The U-Boot copy of btrfs_search_slot() returns on error with the nodes
it has descended through still attached to the path. The kernel one
releases the path on any error unless p->skip_release_on_error is set,
and callers written against that convention treat a failed search as
owning nothing. btrfs_size() is one: it returns straight away on a
search error and never reaches its btrfs_release_path() call, so the
attached extent buffer references leak.

Route both error exits through a release of the path. The error
returns of read_node_slot() carry no extra reference, so the path is
the only thing to clean up.

Suggested-by: Qu Wenruo <quwenruo.btrfs@gmx.com>
Signed-off-by: Cole Munz <Munzzyy1@proton.me>
---
 fs/btrfs/ctree.c | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index 8e932adc425d..48c50e556b16 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -425,8 +425,10 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans,
 		level = btrfs_header_level(b);
 		p->nodes[level] = b;
 		ret = check_block(fs_info, p, level);
-		if (ret)
-			return -1;
+		if (ret) {
+			ret = -1;
+			goto err;
+		}
 		ret = btrfs_bin_search(b, key, &slot);
 		if (level != 0) {
 			if (ret && slot > 0)
@@ -461,8 +463,10 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans,
 				break;
 
 			b = read_node_slot(fs_info, b, slot);
-			if (!extent_buffer_uptodate(b))
-				return -EIO;
+			if (!extent_buffer_uptodate(b)) {
+				ret = -EIO;
+				goto err;
+			}
 		} else {
 			p->slots[level] = slot;
 			/*
@@ -479,6 +483,10 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans,
 		}
 	}
 	return 1;
+
+err:
+	btrfs_release_path(p);
+	return ret;
 }
 
 /*
-- 
2.55.0



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

* [PATCH v3 3/3] fs: btrfs: deduplicate the inode size lookup
  2026-08-02  9:35         ` [PATCH v3 0/3] " Cole Munz
  2026-08-02  9:35           ` [PATCH v3 1/3] " Cole Munz
  2026-08-02  9:35           ` [PATCH v3 2/3] fs: btrfs: release the path when btrfs_search_slot() fails Cole Munz
@ 2026-08-02  9:35           ` Cole Munz
  2026-08-02 22:08           ` [PATCH v3 0/3] fs: btrfs: report file sizes from readdir Qu Wenruo
  2026-08-10 20:53           ` Tom Rini
  4 siblings, 0 replies; 12+ messages in thread
From: Cole Munz @ 2026-08-02  9:35 UTC (permalink / raw)
  To: u-boot; +Cc: Alexey Charkov, Qu Wenruo, Marek Behun, Tom Rini

btrfs_readdir() and btrfs_size() both open code the same search for an
inode item to read its size field. Move it into one helper.

Signed-off-by: Cole Munz <Munzzyy1@proton.me>
---
 fs/btrfs/btrfs.c | 75 +++++++++++++++++++++++++++---------------------
 1 file changed, 42 insertions(+), 33 deletions(-)

diff --git a/fs/btrfs/btrfs.c b/fs/btrfs/btrfs.c
index b2856be0662f..f5f6d638ffd3 100644
--- a/fs/btrfs/btrfs.c
+++ b/fs/btrfs/btrfs.c
@@ -88,14 +88,42 @@ static unsigned int btrfs_dirent_type_to_fs_type(u8 dirent_type)
 	}
 }
 
+/*
+ * Read the size stored in an inode item.  A missing item is -ENOENT and
+ * leaves *size untouched.
+ */
+static int btrfs_get_inode_size(struct btrfs_root *root, u64 ino, u64 *size)
+{
+	struct btrfs_inode_item *ii;
+	struct btrfs_path path;
+	struct btrfs_key key;
+	int ret;
+
+	key.objectid = ino;
+	key.type = BTRFS_INODE_ITEM_KEY;
+	key.offset = 0;
+
+	btrfs_init_path(&path);
+	ret = btrfs_search_slot(NULL, root, &key, &path, 0, 0);
+	if (ret < 0)
+		return ret;
+	if (ret > 0)
+		ret = -ENOENT;
+	if (!ret) {
+		ii = btrfs_item_ptr(path.nodes[0], path.slots[0],
+				    struct btrfs_inode_item);
+		*size = btrfs_inode_size(path.nodes[0], ii);
+	}
+	btrfs_release_path(&path);
+	return ret;
+}
+
 int btrfs_readdir(struct fs_dir_stream *fs_dirs, struct fs_dirent **dentp)
 {
 	struct btrfs_dir_stream *dirs = container_of(fs_dirs, struct btrfs_dir_stream, parent);
 	struct btrfs_fs_info *fs_info = current_fs_info;
 	struct fs_dirent *dent = &dirs->dirent;
-	struct btrfs_inode_item *ii;
 	struct btrfs_root *root;
-	struct btrfs_path path;
 	struct btrfs_key location;
 	struct btrfs_key key;
 	u8 type;
@@ -127,16 +155,13 @@ int btrfs_readdir(struct fs_dir_stream *fs_dirs, struct fs_dirent **dentp)
 	 * layer prints it, so look it up.
 	 */
 	if (location.type == BTRFS_INODE_ITEM_KEY) {
-		btrfs_init_path(&path);
-		ret = btrfs_search_slot(NULL, root, &location, &path, 0, 0);
-		if (ret == 0) {
-			ii = btrfs_item_ptr(path.nodes[0], path.slots[0],
-					    struct btrfs_inode_item);
-			dent->size = btrfs_inode_size(path.nodes[0], ii);
-		}
-		btrfs_release_path(&path);
-		if (ret < 0)
+		u64 size;
+
+		ret = btrfs_get_inode_size(root, location.objectid, &size);
+		if (ret < 0 && ret != -ENOENT)
 			return ret;
+		if (!ret)
+			dent->size = size;
 	}
 
 	*dentp = dent;
@@ -173,10 +198,8 @@ int btrfs_exists(const char *file)
 int btrfs_size(const char *file, loff_t *size)
 {
 	struct btrfs_fs_info *fs_info = current_fs_info;
-	struct btrfs_inode_item *ii;
 	struct btrfs_root *root;
-	struct btrfs_path path;
-	struct btrfs_key key;
+	u64 isize;
 	u64 ino;
 	u8 type;
 	int ret;
@@ -191,27 +214,13 @@ int btrfs_size(const char *file, loff_t *size)
 		printf("Not a regular file: %s\n", file);
 		return -ENOENT;
 	}
-	btrfs_init_path(&path);
-	key.objectid = ino;
-	key.type = BTRFS_INODE_ITEM_KEY;
-	key.offset = 0;
-
-	ret = btrfs_search_slot(NULL, root, &key, &path, 0, 0);
-	if (ret < 0) {
-		printf("Cannot lookup ino %llu\n", ino);
+	ret = btrfs_get_inode_size(root, ino, &isize);
+	if (ret) {
+		printf("Cannot read size of ino %llu\n", ino);
 		return ret;
 	}
-	if (ret > 0) {
-		printf("Ino %llu does not exist\n", ino);
-		ret = -ENOENT;
-		goto out;
-	}
-	ii = btrfs_item_ptr(path.nodes[0], path.slots[0],
-			    struct btrfs_inode_item);
-	*size = btrfs_inode_size(path.nodes[0], ii);
-out:
-	btrfs_release_path(&path);
-	return ret;
+	*size = isize;
+	return 0;
 }
 
 int btrfs_read(const char *file, void *buf, loff_t offset, loff_t len,
-- 
2.55.0



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

* Re: [PATCH v3 0/3] fs: btrfs: report file sizes from readdir
  2026-08-02  9:35         ` [PATCH v3 0/3] " Cole Munz
                             ` (2 preceding siblings ...)
  2026-08-02  9:35           ` [PATCH v3 3/3] fs: btrfs: deduplicate the inode size lookup Cole Munz
@ 2026-08-02 22:08           ` Qu Wenruo
  2026-08-10 20:53           ` Tom Rini
  4 siblings, 0 replies; 12+ messages in thread
From: Qu Wenruo @ 2026-08-02 22:08 UTC (permalink / raw)
  To: Cole Munz, u-boot; +Cc: Alexey Charkov, Marek Behun, Tom Rini



在 2026/8/2 19:05, Cole Munz 写道:
> As agreed on the v1 thread, the fix and the cleanups are now separate
> patches:
> 
> - patch 1 is the fix in the v1 shape
> - patch 2 makes btrfs_search_slot() release the path on error like
>    the kernel version does. That is where the btrfs_size() leak came
>    from. Suggested by Qu.
> - patch 3 is the dedup Alexey asked about. One helper shared by
>    btrfs_readdir() and btrfs_size().
> 
> The pending btrfs test suite still passes on top of the readdir
> series: 5 passed.
> 
> Changes in v3: split the fix from the cleanups. The release moved
> into btrfs_search_slot() itself.
> Changes in v2: helper shared with btrfs_size() plus the leak fix in
> one patch.
> 

Reviewed-by: Qu Wenruo <wqu@suse.com>

Thanks,
Qu

> Cole Munz (3):
>    fs: btrfs: report file sizes from readdir
>    fs: btrfs: release the path when btrfs_search_slot() fails
>    fs: btrfs: deduplicate the inode size lookup
> 
>   fs/btrfs/btrfs.c    | 77 +++++++++++++++++++++++++++++++--------------
>   fs/btrfs/ctree.c    | 16 +++++++---
>   fs/btrfs/ctree.h    |  3 +-
>   fs/btrfs/dir-item.c |  7 ++++-
>   4 files changed, 74 insertions(+), 29 deletions(-)
> 


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

* Re: [PATCH v3 0/3] fs: btrfs: report file sizes from readdir
  2026-08-02  9:35         ` [PATCH v3 0/3] " Cole Munz
                             ` (3 preceding siblings ...)
  2026-08-02 22:08           ` [PATCH v3 0/3] fs: btrfs: report file sizes from readdir Qu Wenruo
@ 2026-08-10 20:53           ` Tom Rini
  4 siblings, 0 replies; 12+ messages in thread
From: Tom Rini @ 2026-08-10 20:53 UTC (permalink / raw)
  To: u-boot, Cole Munz; +Cc: Alexey Charkov, Qu Wenruo, Marek Behun

On Sun, 02 Aug 2026 09:35:16 +0000, Cole Munz wrote:

> As agreed on the v1 thread, the fix and the cleanups are now separate
> patches:
> 
> - patch 1 is the fix in the v1 shape
> - patch 2 makes btrfs_search_slot() release the path on error like
>   the kernel version does. That is where the btrfs_size() leak came
>   from. Suggested by Qu.
> - patch 3 is the dedup Alexey asked about. One helper shared by
>   btrfs_readdir() and btrfs_size().
> 
> [...]

Applied to u-boot/main, thanks!

[1/3] fs: btrfs: report file sizes from readdir
      commit: 1cf825afd0d7ebb4857002833658574efbef6626
[2/3] fs: btrfs: release the path when btrfs_search_slot() fails
      commit: 1a5c8af2d4e4b4029739eb8787ce259d74977dfd
[3/3] fs: btrfs: deduplicate the inode size lookup
      commit: a11f8659f451c5601bac6fdf5b48594d347db38d
-- 
Tom



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

end of thread, other threads:[~2026-08-10 20:53 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-02  5:42 [PATCH] fs: btrfs: report file sizes from readdir Cole Munz
2026-08-02  6:02 ` Alexey Charkov
2026-08-02  6:44   ` [PATCH v2] " Cole Munz
2026-08-02  6:47   ` [PATCH] " Qu Wenruo
2026-08-02  7:37     ` Cole Munz
2026-08-02  7:55       ` Qu Wenruo
2026-08-02  9:35         ` [PATCH v3 0/3] " Cole Munz
2026-08-02  9:35           ` [PATCH v3 1/3] " Cole Munz
2026-08-02  9:35           ` [PATCH v3 2/3] fs: btrfs: release the path when btrfs_search_slot() fails Cole Munz
2026-08-02  9:35           ` [PATCH v3 3/3] fs: btrfs: deduplicate the inode size lookup Cole Munz
2026-08-02 22:08           ` [PATCH v3 0/3] fs: btrfs: report file sizes from readdir Qu Wenruo
2026-08-10 20:53           ` Tom Rini

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.