From: Qu Wenruo <quwenruo.btrfs@gmx.com>
To: Alexey Charkov <alchark@flipper.net>, Cole Munz <Munzzyy1@proton.me>
Cc: u-boot@lists.denx.de, Marek Behun <kabel@kernel.org>,
Tom Rini <trini@konsulko.com>
Subject: Re: [PATCH] fs: btrfs: report file sizes from readdir
Date: Sun, 2 Aug 2026 16:17:59 +0930 [thread overview]
Message-ID: <7bcd492f-7e1e-4fd9-970d-857ca5460ddd@gmx.com> (raw)
In-Reply-To: <CAKTNdwGCYjr+2vaBc6kArQokqTF=Gc23mF17B_22Fdcg1O=7hQ@mail.gmail.com>
在 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
next prev parent reply other threads:[~2026-08-02 6:48 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
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 ` Qu Wenruo [this message]
2026-08-02 7:37 ` [PATCH] " 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
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=7bcd492f-7e1e-4fd9-970d-857ca5460ddd@gmx.com \
--to=quwenruo.btrfs@gmx.com \
--cc=Munzzyy1@proton.me \
--cc=alchark@flipper.net \
--cc=kabel@kernel.org \
--cc=trini@konsulko.com \
--cc=u-boot@lists.denx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox