* eth-multiplexer/device_impl.c (ds_device_open): Handle the .MASTER node specially. * eth-multiplexer/multiplexer.c (main): Create the .MASTER node. * eth-multiplexer/netfs_impl.c (master_node): New variable. (lookup): Handle the lookups for .MASTER specially. (netfs_add_dirents): Add the .MASTER node. * eth-multiplexer/netfs_impl.h (MASTER_NODE_NAME): New definition. (master_node): New variable. ---
Hello, In this patch I tried to take into consideration the corrections to the original version suggested by Zheng and, probably, other people whom I don't remember :-( Regards, Sergiu --- eth-multiplexer/device_impl.c | 49 +++++++++++++++++++++++++++++----------- eth-multiplexer/multiplexer.c | 6 ++++- eth-multiplexer/netfs_impl.c | 15 +++++++++++- eth-multiplexer/netfs_impl.h | 8 ++++++ 4 files changed, 62 insertions(+), 16 deletions(-) diff --git a/eth-multiplexer/device_impl.c b/eth-multiplexer/device_impl.c index 8c82606..8830093 100644 --- a/eth-multiplexer/device_impl.c +++ b/eth-multiplexer/device_impl.c @@ -92,31 +92,52 @@ ds_device_open (mach_port_t master_port, mach_port_t reply_port, if (pi == NULL) return D_NO_SUCH_DEVICE; - /* If the virtual device hasn't been created yet, - * create it now. */ - if (pi->po->np->nn->ln == NULL) + if (pi->po->np == master_node) { + /* This device_open RPC was invoked on a port the .MASTER node, + so we don't care about light nodes (because the .MASTER node + does not have one). */ extern struct port_bucket *port_bucket; extern struct port_class *vdev_portclass; - /* Create a new light node (virtual device). */ - struct lnode *ln = (struct lnode *) add_vdev (pi->po->np->nn->name, - sizeof (*ln), - vdev_portclass, - port_bucket); - if (ln == NULL) + + /* Create a new virtual device. */ + dev = (struct lnode *) add_vdev (name, sizeof (*dev), vdev_portclass, + port_bucket); + if (dev == NULL) { ports_port_deref (pi); return D_NO_MEMORY; } + } + else + { + /* If the virtual device hasn't been created yet, + * create it now. */ + if (pi->po->np->nn->ln == NULL) + { + extern struct port_bucket *port_bucket; + extern struct port_class *vdev_portclass; + /* Create a new light node (virtual device). */ + struct lnode *ln = (struct lnode *) add_vdev (pi->po->np->nn->name, + sizeof (*ln), + vdev_portclass, + port_bucket); + if (ln == NULL) + { + ports_port_deref (pi); + return D_NO_MEMORY; + } + + /* Connect the libnetfs node and the light node together. */ + ln->n = pi->po->np; + ln->n->nn->ln = ln; - /* Connect the libnetfs node and the light node together. */ - ln->n = pi->po->np; - ln->n->nn->ln = ln; + ln->st = ln->n->nn_stat; + } - ln->st = ln->n->nn_stat; + dev = (struct vether_device *) pi->po->np->nn->ln; } - dev = (struct vether_device *) pi->po->np->nn->ln; /* check the mode */ openstat = pi->po->openstat; if (mode & D_READ && !(openstat & O_READ)) diff --git a/eth-multiplexer/multiplexer.c b/eth-multiplexer/multiplexer.c index 173a8f9..a87c9c4 100644 --- a/eth-multiplexer/multiplexer.c +++ b/eth-multiplexer/multiplexer.c @@ -162,9 +162,13 @@ main (int argc, char *argv[]) if (err) error (5, err, "Cannot create root node"); + err = new_node (NULL, &master_node); + if (err) + error (6, err, "Cannot create the .MASTER node"); + err = io_stat (root_file, &underlying_node_stat); if (err) - error (6, err, "Cannot stat underlying node"); + error (7, err, "Cannot stat underlying node"); struct stat stat = underlying_node_stat; /* If the underlying node is not a directory, increase its permissions */ diff --git a/eth-multiplexer/netfs_impl.c b/eth-multiplexer/netfs_impl.c index c70701b..257cf9d 100644 --- a/eth-multiplexer/netfs_impl.c +++ b/eth-multiplexer/netfs_impl.c @@ -31,6 +31,10 @@ #include "vdev.h" #include "util.h" +/* The .MASTER node which will be used by static instances of + devnode. */ +struct node * master_node; + #define DIRENTS_CHUNK_SIZE (8*1024) /* Returned directory entries are aligned to blocks this many bytes long. * Must be a power of two. */ @@ -85,6 +89,12 @@ new_node (struct lnode *ln, struct node **np) struct node * lookup (char *name) { + if (strcmp(name, MASTER_NODE_NAME) == 0) + { + netfs_nref (master_node); + return master_node; + } + struct lnode *ln = (struct lnode *) lookup_dev_by_name (name); char *copied_name = malloc (strlen (name) + 1); @@ -276,10 +286,13 @@ netfs_get_dirents (struct iouser *cred, struct node *dir, if (!err) { data_p = *data; - if (first_entry < 2 + get_dev_num ()) + /* Count the .MASTER node, too. */ + if (first_entry < 2 + get_dev_num () + 1) { add_dirent (".", 2, DT_DIR); add_dirent ("..", 2, DT_DIR); + add_dirent (MASTER_NODE_NAME, 2, DT_CHR); + foreach_dev_do (add_each_dev); } diff --git a/eth-multiplexer/netfs_impl.h b/eth-multiplexer/netfs_impl.h index ec3b389..1c9662a 100644 --- a/eth-multiplexer/netfs_impl.h +++ b/eth-multiplexer/netfs_impl.h @@ -29,6 +29,10 @@ /* Shows the stat information in the node is invalid. */ #define NODE_STAT_INVALID 0x0001 +/* The name of the node which provides the pseudo master device port + functionality for static instances of devnode. */ +#define MASTER_NODE_NAME ".MASTER" + struct netnode { struct lnode *ln; @@ -47,6 +51,10 @@ struct lnode extern file_t root_file; volatile struct mapped_time_value *multiplexer_maptime; +/* The .MASTER node which will be used by static instances of + devnode. */ +extern struct node * master_node; + error_t new_node (struct lnode *ln, struct node **np); #endif -- 1.6.6