
This directory is filled dynamically with regular files, one for each service that RS knows about, named after its label. Its contents are still subject to (heavy) change, but currently expose the service's endpoint and number of restarts so far. Change-Id: Ie58c824bcb6382c8da7a714e59fee87329970b4b
146 lines
3.2 KiB
C
146 lines
3.2 KiB
C
/* ProcFS - service.c - the service subdirectory */
|
|
|
|
#include "inc.h"
|
|
|
|
#include <minix/rs.h>
|
|
#include "rs/const.h"
|
|
#include "rs/type.h"
|
|
|
|
static struct rprocpub rprocpub[NR_SYS_PROCS];
|
|
static struct rproc rproc[NR_SYS_PROCS];
|
|
|
|
static struct inode *service_node;
|
|
|
|
/*
|
|
* Initialize the service directory.
|
|
*/
|
|
void
|
|
service_init(void)
|
|
{
|
|
struct inode *root, *node;
|
|
struct inode_stat stat;
|
|
|
|
root = get_root_inode();
|
|
|
|
memset(&stat, 0, sizeof(stat));
|
|
stat.mode = DIR_ALL_MODE;
|
|
stat.uid = SUPER_USER;
|
|
stat.gid = SUPER_USER;
|
|
|
|
service_node = add_inode(root, "service", NO_INDEX, &stat,
|
|
NR_SYS_PROCS, NULL);
|
|
|
|
if (service_node == NULL)
|
|
panic("unable to create service node");
|
|
}
|
|
|
|
/*
|
|
* Update the contents of the service directory, by first updating the RS
|
|
* tables and then updating the directory contents.
|
|
*/
|
|
void
|
|
service_update(void)
|
|
{
|
|
struct inode *node;
|
|
struct inode_stat stat;
|
|
index_t slot;
|
|
|
|
/* There is not much we can do if either of these calls fails. */
|
|
(void)getsysinfo(RS_PROC_NR, SI_PROCPUB_TAB, rprocpub,
|
|
sizeof(rprocpub));
|
|
(void)getsysinfo(RS_PROC_NR, SI_PROC_TAB, rproc, sizeof(rproc));
|
|
|
|
/*
|
|
* As with PIDs, we make two passes. Delete first, then add. This
|
|
* prevents problems in the hypothetical case that between updates, one
|
|
* slot ends up with the label name of a previous, different slot.
|
|
*/
|
|
for (slot = 0; slot < NR_SYS_PROCS; slot++) {
|
|
if ((node = get_inode_by_index(service_node, slot)) == NULL)
|
|
continue;
|
|
|
|
/*
|
|
* If the slot is no longer in use, or the label name does not
|
|
* match, the node must be deleted.
|
|
*/
|
|
if (!(rproc[slot].r_flags & RS_IN_USE) ||
|
|
strcmp(get_inode_name(node), rprocpub[slot].label))
|
|
delete_inode(node);
|
|
}
|
|
|
|
memset(&stat, 0, sizeof(stat));
|
|
stat.mode = REG_ALL_MODE;
|
|
stat.uid = SUPER_USER;
|
|
stat.gid = SUPER_USER;
|
|
|
|
for (slot = 0; slot < NR_SYS_PROCS; slot++) {
|
|
if (!(rproc[slot].r_flags & RS_IN_USE) ||
|
|
get_inode_by_index(service_node, slot) != NULL)
|
|
continue;
|
|
|
|
node = add_inode(service_node, rprocpub[slot].label, slot,
|
|
&stat, (index_t)0, (cbdata_t)slot);
|
|
|
|
if (node == NULL)
|
|
out_of_inodes();
|
|
}
|
|
}
|
|
|
|
/*
|
|
* A lookup request is being performed. If it is in the service directory,
|
|
* update the tables. We do this lazily, to reduce overhead.
|
|
*/
|
|
void
|
|
service_lookup(struct inode * parent, clock_t now)
|
|
{
|
|
static clock_t last_update = 0;
|
|
|
|
if (parent != service_node)
|
|
return;
|
|
|
|
if (last_update != now) {
|
|
service_update();
|
|
|
|
last_update = now;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* A getdents request is being performed. If it is in the service directory,
|
|
* update the tables.
|
|
*/
|
|
void
|
|
service_getdents(struct inode * node)
|
|
{
|
|
|
|
if (node != service_node)
|
|
return;
|
|
|
|
service_update();
|
|
}
|
|
|
|
/*
|
|
* A read request is being performed. If it is on a file in the service
|
|
* directory, process the read request. We rely on the fact that any read
|
|
* call will have been preceded by a lookup, so its table entry has been
|
|
* updated very recently.
|
|
*/
|
|
void
|
|
service_read(struct inode * node)
|
|
{
|
|
struct inode *parent;
|
|
index_t slot;
|
|
struct rprocpub *rpub;
|
|
struct rproc *rp;
|
|
|
|
if (get_parent_inode(node) != service_node)
|
|
return;
|
|
|
|
slot = get_inode_index(node);
|
|
rpub = &rprocpub[slot];
|
|
rp = &rproc[slot];
|
|
|
|
/* TODO: add a large number of other fields! */
|
|
buf_printf("%d %d\n", rpub->endpoint, rp->r_restarts);
|
|
}
|