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