Hello,
On Mon, 5 Oct 2026 23:37:13 Samuel Thibault wrote:
> And indeed, trivfs_S_io_map has disappeared, but netfs_S_io_map was not
> introduced.
It is not strictly necessary to implement the netfs_S_io_map function,
because we could implement netfs_get_filemap instead, which would be called
by the netfs_S_io_map function in libnetfs. However, in our case, we
need to
implement netfs_S_io_map specifically because the behavior of
trivfs_S_io_map
from storeio differs from the netfs_S_io_map implementation in libnetfs.
Examining the code reveals that trivfs_S_io_map returned an error only
if the
dev_get_memory_object function failed, even though memobj could be
MACH_PORT_NULL. In the netfs_S_io_map implementation, an error is returned
if memobj is MACH_PORT_NULL. I do not know which behavior is more correct.
We can either modify the behavior of netfs_S_io_map to match trivfs_S_io_map
or simply override netfs_S_io_map in storeio.
> Also, ls -l /dev/zero returns
>
> ls: reading directory '/dev/zero': Not a directory
>
> I guess it should be fixed into not showing the directory type when
> there is not partition table.
We can override netfs_S_io_stat and return the desired mode when
netfs_root_node is accessed. We need to override this function because
modifying netfs_root_node->nn_stat.st_mode directly is not allowed, as it
leads to errors.
> Also,
>
> € sudo ls /dev/sd0/ -l
> total 1
> b--------- 1 root root 86, 77 oct. 5 21:39 1
> b--------- 1 root root 86, 77 oct. 5 21:39 2
>
> It's missing some permissions 🙂
This was resolved by adding code to netfs_report_access instead of returning
EOPNOTSUPP.
Thanks,
--
Mikhail Karpov
From 50b3b85fe2fc4b8a741bd28bf846d1b972e092b4 Mon Sep 17 00:00:00 2001
From: Mikhail Karpov <[email protected]>
Date: Tue, 6 Oct 2026 21:18:05 +0700
Subject: [PATCH 3/3] Fixing the mmap and st_mode issue
---
storeio/dev.h | 4 +-
storeio/part.c | 1 +
storeio/storeio.c | 134 ++++++++++++++++++++++++++++++++++++++--------
3 files changed, 114 insertions(+), 25 deletions(-)
diff --git a/storeio/dev.h b/storeio/dev.h
index beeb1fe..aae008e 100644
--- a/storeio/dev.h
+++ b/storeio/dev.h
@@ -27,8 +27,6 @@
#include <stdio.h>
#include <unistd.h>
-extern mach_port_t underlying_node;
-
/* Information about backend store, which we presumptively call a "device". */
struct dev
{
@@ -94,6 +92,8 @@ struct storeio_stat
};
extern struct storeio_stat storeio_stat;
+extern mach_port_t underlying_node;
+extern mode_t root_node_mode;
error_t create_node (struct node **node, char *name, struct node *dir);
error_t check_dev (struct node *node, struct store *store, int flags);
diff --git a/storeio/part.c b/storeio/part.c
index 5c9c6a2..47d37df 100644
--- a/storeio/part.c
+++ b/storeio/part.c
@@ -114,6 +114,7 @@ create_partitions (void)
const int flags = ((storeio_stat.readonly ? STORE_READONLY : 0)
| (storeio_stat.no_fileio ? STORE_NO_FILEIO : 0));
+ root_node_mode = S_IFDIR;
struct store *source, *store;
struct node **part;
char *node_name;
diff --git a/storeio/storeio.c b/storeio/storeio.c
index 3302c5c..348afde 100644
--- a/storeio/storeio.c
+++ b/storeio/storeio.c
@@ -64,6 +64,7 @@ const char *argp_program_version = STANDARD_HURD_VERSION (storeio);
char *netfs_server_name = "storeio";
char *netfs_server_version = HURD_VERSION;
int netfs_maxsymlinks = 0; /* arbitrary */
+mode_t root_node_mode = 0;
char *debug_file_name = NULL;
FILE *debug_file;
@@ -153,18 +154,24 @@ create_node (struct node **node, char *name, struct node *dir)
static inline void
change_node_mode (struct node *node)
{
- node->nn_stat.st_mode &= S_IFMT;
-
+ mode_t mode;
if (storeio_stat.inhibit_cache)
+ mode = S_IFCHR;
+ else
{
- node->nn_stat.st_mode |= S_IFCHR;
- return;
+ if (node->nn->dev->store && node->nn->dev->store->block_size == 1)
+ mode = S_IFCHR;
+ else
+ mode = S_IFBLK;
}
- if (node->nn->dev->store && node->nn->dev->store->block_size == 1)
- node->nn_stat.st_mode |= S_IFCHR;
+ if (node == netfs_root_node)
+ {
+ if (root_node_mode != S_IFDIR)
+ root_node_mode = mode;
+ }
else
- node->nn_stat.st_mode |= S_IFBLK;
+ node->nn_stat.st_mode = mode | (node->nn_stat.st_mode & ~S_IFMT);
}
error_t
@@ -215,8 +222,7 @@ check_dev (struct node *node, struct store *store, int flags)
if (dev->store->block_size > 1)
node->nn_stat.st_blksize = dev->store->block_size;
- if (node != netfs_root_node)
- change_node_mode (node);
+ change_node_mode (node);
}
pthread_mutex_unlock (&dev->lock);
@@ -553,6 +559,7 @@ netfs_validate_stat (struct node *np, struct iouser *cred)
np->nn_stat.st_blksize = 0;
}
+ np->nn_translated = np->nn_stat.st_mode;
return 0;
}
@@ -870,22 +877,17 @@ netfs_attempt_write (struct iouser *cred, struct node *np, loff_t offset,
error_t
netfs_report_access (struct iouser *cred, struct node *np, int *types)
{
- return EOPNOTSUPP;
-}
+ *types = 0;
+ if (fshelp_access (&np->nn_stat, S_IREAD, cred) == 0)
+ *types |= O_READ;
-mach_port_t
-netfs_get_filemap (struct node *np, vm_prot_t prot)
-{
- mach_port_t memobj;
- errno = dev_get_memory_object (np->nn->dev, prot, &memobj);
- if (errno)
- {
- debug ("netfs_get_filemap (np: %p, vm_prot_t: %d):\n", np, prot);
- memobj = MACH_PORT_NULL;
- debug ("dev_get_memory_object return err: %d\n", errno);
- }
+ if (fshelp_access (&np->nn_stat, S_IWRITE, cred) == 0)
+ *types |= O_WRITE;
+
+ if (fshelp_access (&np->nn_stat, S_IEXEC, cred) == 0)
+ *types |= O_EXEC;
- return memobj;
+ return 0;
}
struct iouser *
@@ -1109,3 +1111,89 @@ netfs_file_get_storage_info (struct iouser *cred, struct node *np,
return err;
}
+
+kern_return_t
+netfs_S_io_stat (struct protid *user, io_statbuf_t *statbuf)
+{
+ if (!user)
+ return EOPNOTSUPP;
+
+ struct node *node = user->po->np;
+ pthread_mutex_lock (&node->lock);
+
+ error_t err = netfs_validate_stat (node, user->user);
+ if (err)
+ {
+ pthread_mutex_unlock (&node->lock);
+ return err;
+ }
+
+ memcpy (statbuf, &node->nn_stat, sizeof (struct stat));
+
+ if (node == netfs_root_node)
+ statbuf->st_mode = root_node_mode | (statbuf->st_mode & ~S_IFMT);
+
+ /* Set S_IATRANS and S_IROOT bits as appropriate. */
+ statbuf->st_mode &= ~(S_IATRANS | S_IROOT);
+ if (fshelp_translated (&node->transbox))
+ statbuf->st_mode |= S_IATRANS; /* Has an active translator. */
+
+ if (user->po->shadow_root == node || node == netfs_root_node)
+ statbuf->st_mode |= S_IROOT; /* Is a root node. */
+
+ pthread_mutex_unlock (&node->lock);
+ return 0;
+}
+
+kern_return_t
+netfs_S_io_map (struct protid *user,
+ mach_port_t *rdobj, mach_msg_type_name_t *rdobjtype,
+ mach_port_t *wrobj, mach_msg_type_name_t *wrobjtype)
+{
+ if (!user)
+ return EOPNOTSUPP;
+
+ if (user->po->openstat & (O_READ | O_WRITE) == 0)
+ return EBADF;
+
+ *wrobj = *rdobj = MACH_PORT_NULL;
+
+ struct node *node = user->po->np;
+ int flags = user->po->openstat & (O_READ | O_WRITE);
+ vm_prot_t prot = ((flags & O_READ) ? VM_PROT_READ : 0)
+ | ((flags & O_WRITE) ? VM_PROT_WRITE : 0);
+
+ pthread_mutex_lock (&node->lock);
+ memory_object_t memobj;
+ error_t err = dev_get_memory_object (node->nn->dev, prot, &memobj);
+ if (err)
+ {
+ pthread_mutex_unlock (&node->lock);
+ return err;
+ }
+
+ switch (flags)
+ {
+ case O_READ | O_WRITE:
+ *wrobj = *rdobj = memobj;
+ if (memobj != MACH_PORT_NULL)
+ mach_port_mod_refs (mach_task_self (), memobj,
+ MACH_PORT_RIGHT_SEND, 1);
+ break;
+
+ case O_READ:
+ *rdobj = memobj;
+ break;
+
+ case O_WRITE:
+ *wrobj = memobj;
+ break;
+ }
+
+ pthread_mutex_unlock (&node->lock);
+
+ *rdobjtype = MACH_MSG_TYPE_MOVE_SEND;
+ *wrobjtype = MACH_MSG_TYPE_MOVE_SEND;
+
+ return 0;
+}
--
2.43.0