Hi Kuan-Wei,

On 2026-07-06T21:54:42, Kuan-Wei Chiu <[email protected]> wrote:
> fs: 9p: Add 9P filesystem support
>
> Implement the VFS interface for the 9P filesystem.
>
> Map the U-Boot filesystem operations to the underlying 9P protocol
> client. It also registers the 9P filesystem type within the U-Boot
> generic fs framework, allowing it to bypass standard block device
> partition checks since 9P is a network/host-backed filesystem.
>
> Signed-off-by: Kuan-Wei Chiu <[email protected]>
>
> fs/9p/9p.c     | 137 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  fs/9p/Kconfig  |   8 ++++
>  fs/9p/Makefile |   5 +++
>  fs/Kconfig     |   2 +
>  fs/Makefile    |   1 +
>  fs/fs.c        |  35 +++++++++++++++
>  include/fs.h   |   1 +
>  7 files changed, 189 insertions(+)

> diff --git a/fs/fs.c b/fs/fs.c
> @@ -466,6 +487,20 @@ int fs_set_blk_dev(const char *ifname, const char 
> *dev_part_str, int fstype)
> +     /* Intercept 9p to bypass block device partition checks */
> +     if (CONFIG_IS_ENABLED(FS_9P) && !strncmp(ifname, '9p', 2)) {
> +             for (i = 0, info = fstypes; i < ARRAY_SIZE(fstypes); i++, 
> info++) {
> +                     if (info->fstype == FS_TYPE_9P) {
> +                             fs_dev_desc = NULL;
> +                             fs_type = FS_TYPE_9P;
> +                             if (info->probe(fs_dev_desc, NULL))
> +                                     return -1;
> +                             return 0;
> +                     }
> +             }
> +             return -1;
> +     }

There is already a mechanism for pseudo block devices: the hostfs and
ubi special cases in blk_get_device_part_str() in disk/part.c return
success with a NULL desc, and the normal loop below then probes any
filesystem with null_dev_desc_ok set, which you have already done for
the 9p entry. Please can you add a 9p case there instead of
duplicating the probe loop here? That also fixes two problems with
this version: strncmp() matches any ifname starting with 9p (strcmp()
is what you want), and fs_type is set before probe() succeeds, so a
failed probe leaves stale state behind (the generic loop only sets it
on success).

> diff --git a/fs/9p/9p.c b/fs/9p/9p.c
> @@ -0,0 +1,137 @@
> +     if (p9_client_walk(c, p9_root_fid, fid, dirname))
> +             return -ENOENT;
> +     if (p9_client_lopen(c, fid, P9_O_RDONLY))
> +             return -EIO;

If the walk succeeds but the open fails, the fid is left allocated on
the server. Please clunk it before returning, as in the
readdir-failure path just below and in p9_fs_read()

> diff --git a/fs/9p/9p.c b/fs/9p/9p.c
> @@ -0,0 +1,137 @@
> +     if (p9_client_readdir(c, fid, 0, sizeof(buf), buf, &actread)) {
> +             p9_client_clunk(c, fid);
> +             return -EIO;
> +     }

This issues a single Treaddir at offset 0, so any directory whose
entries do not fit in 4KB is silently truncated. Each dirent carries
an offset field (the 8 bytes skipped within P9_DIRENT_OFFSET), so
please loop, passing the last entry's offset back in, until the
server returns zero bytes. BTW a 4KB stack buffer is quite large for
some boards - since it would be reused across iterations anyway,
consider malloc() / free() here.

> diff --git a/fs/9p/9p.c b/fs/9p/9p.c
> @@ -0,0 +1,137 @@
> +     *actread = total_read;
> +     p9_client_clunk(c, fid);
> +
> +     return (total_read > 0 || ret == 0) ? 0 : ret;

If a read fails part-way through, this returns 0 with a short actread,
so the caller (e.g. the load command) reports success on a partially
loaded file, which could go unnoticed until the image fails to boot.
Other filesystems propagate the error here, so please return ret
whenever it is non-zero.

Regards,
Simon

Reply via email to