1*31b6611aSDavid van Moolenbroek /* ProcFS - service.c - the service subdirectory */ 2*31b6611aSDavid van Moolenbroek 3*31b6611aSDavid van Moolenbroek #include "inc.h" 4*31b6611aSDavid van Moolenbroek 5*31b6611aSDavid van Moolenbroek #include <minix/rs.h> 6*31b6611aSDavid van Moolenbroek #include "rs/const.h" 7*31b6611aSDavid van Moolenbroek #include "rs/type.h" 8*31b6611aSDavid van Moolenbroek 9*31b6611aSDavid van Moolenbroek static struct rprocpub rprocpub[NR_SYS_PROCS]; 10*31b6611aSDavid van Moolenbroek static struct rproc rproc[NR_SYS_PROCS]; 11*31b6611aSDavid van Moolenbroek 12*31b6611aSDavid van Moolenbroek static struct inode *service_node; 13*31b6611aSDavid van Moolenbroek 14*31b6611aSDavid van Moolenbroek /* 15*31b6611aSDavid van Moolenbroek * Initialize the service directory. 16*31b6611aSDavid van Moolenbroek */ 17*31b6611aSDavid van Moolenbroek void 18*31b6611aSDavid van Moolenbroek service_init(void) 19*31b6611aSDavid van Moolenbroek { 20*31b6611aSDavid van Moolenbroek struct inode *root, *node; 21*31b6611aSDavid van Moolenbroek struct inode_stat stat; 22*31b6611aSDavid van Moolenbroek 23*31b6611aSDavid van Moolenbroek root = get_root_inode(); 24*31b6611aSDavid van Moolenbroek 25*31b6611aSDavid van Moolenbroek memset(&stat, 0, sizeof(stat)); 26*31b6611aSDavid van Moolenbroek stat.mode = DIR_ALL_MODE; 27*31b6611aSDavid van Moolenbroek stat.uid = SUPER_USER; 28*31b6611aSDavid van Moolenbroek stat.gid = SUPER_USER; 29*31b6611aSDavid van Moolenbroek 30*31b6611aSDavid van Moolenbroek service_node = add_inode(root, "service", NO_INDEX, &stat, 31*31b6611aSDavid van Moolenbroek NR_SYS_PROCS, NULL); 32*31b6611aSDavid van Moolenbroek 33*31b6611aSDavid van Moolenbroek if (service_node == NULL) 34*31b6611aSDavid van Moolenbroek panic("unable to create service node"); 35*31b6611aSDavid van Moolenbroek } 36*31b6611aSDavid van Moolenbroek 37*31b6611aSDavid van Moolenbroek /* 38*31b6611aSDavid van Moolenbroek * Update the contents of the service directory, by first updating the RS 39*31b6611aSDavid van Moolenbroek * tables and then updating the directory contents. 40*31b6611aSDavid van Moolenbroek */ 41*31b6611aSDavid van Moolenbroek void 42*31b6611aSDavid van Moolenbroek service_update(void) 43*31b6611aSDavid van Moolenbroek { 44*31b6611aSDavid van Moolenbroek struct inode *node; 45*31b6611aSDavid van Moolenbroek struct inode_stat stat; 46*31b6611aSDavid van Moolenbroek index_t slot; 47*31b6611aSDavid van Moolenbroek 48*31b6611aSDavid van Moolenbroek /* There is not much we can do if either of these calls fails. */ 49*31b6611aSDavid van Moolenbroek (void)getsysinfo(RS_PROC_NR, SI_PROCPUB_TAB, rprocpub, 50*31b6611aSDavid van Moolenbroek sizeof(rprocpub)); 51*31b6611aSDavid van Moolenbroek (void)getsysinfo(RS_PROC_NR, SI_PROC_TAB, rproc, sizeof(rproc)); 52*31b6611aSDavid van Moolenbroek 53*31b6611aSDavid van Moolenbroek /* 54*31b6611aSDavid van Moolenbroek * As with PIDs, we make two passes. Delete first, then add. This 55*31b6611aSDavid van Moolenbroek * prevents problems in the hypothetical case that between updates, one 56*31b6611aSDavid van Moolenbroek * slot ends up with the label name of a previous, different slot. 57*31b6611aSDavid van Moolenbroek */ 58*31b6611aSDavid van Moolenbroek for (slot = 0; slot < NR_SYS_PROCS; slot++) { 59*31b6611aSDavid van Moolenbroek if ((node = get_inode_by_index(service_node, slot)) == NULL) 60*31b6611aSDavid van Moolenbroek continue; 61*31b6611aSDavid van Moolenbroek 62*31b6611aSDavid van Moolenbroek /* 63*31b6611aSDavid van Moolenbroek * If the slot is no longer in use, or the label name does not 64*31b6611aSDavid van Moolenbroek * match, the node must be deleted. 65*31b6611aSDavid van Moolenbroek */ 66*31b6611aSDavid van Moolenbroek if (!(rproc[slot].r_flags & RS_IN_USE) || 67*31b6611aSDavid van Moolenbroek strcmp(get_inode_name(node), rprocpub[slot].label)) 68*31b6611aSDavid van Moolenbroek delete_inode(node); 69*31b6611aSDavid van Moolenbroek } 70*31b6611aSDavid van Moolenbroek 71*31b6611aSDavid van Moolenbroek memset(&stat, 0, sizeof(stat)); 72*31b6611aSDavid van Moolenbroek stat.mode = REG_ALL_MODE; 73*31b6611aSDavid van Moolenbroek stat.uid = SUPER_USER; 74*31b6611aSDavid van Moolenbroek stat.gid = SUPER_USER; 75*31b6611aSDavid van Moolenbroek 76*31b6611aSDavid van Moolenbroek for (slot = 0; slot < NR_SYS_PROCS; slot++) { 77*31b6611aSDavid van Moolenbroek if (!(rproc[slot].r_flags & RS_IN_USE) || 78*31b6611aSDavid van Moolenbroek get_inode_by_index(service_node, slot) != NULL) 79*31b6611aSDavid van Moolenbroek continue; 80*31b6611aSDavid van Moolenbroek 81*31b6611aSDavid van Moolenbroek node = add_inode(service_node, rprocpub[slot].label, slot, 82*31b6611aSDavid van Moolenbroek &stat, (index_t)0, (cbdata_t)slot); 83*31b6611aSDavid van Moolenbroek 84*31b6611aSDavid van Moolenbroek if (node == NULL) 85*31b6611aSDavid van Moolenbroek out_of_inodes(); 86*31b6611aSDavid van Moolenbroek } 87*31b6611aSDavid van Moolenbroek } 88*31b6611aSDavid van Moolenbroek 89*31b6611aSDavid van Moolenbroek /* 90*31b6611aSDavid van Moolenbroek * A lookup request is being performed. If it is in the service directory, 91*31b6611aSDavid van Moolenbroek * update the tables. We do this lazily, to reduce overhead. 92*31b6611aSDavid van Moolenbroek */ 93*31b6611aSDavid van Moolenbroek void 94*31b6611aSDavid van Moolenbroek service_lookup(struct inode * parent, clock_t now) 95*31b6611aSDavid van Moolenbroek { 96*31b6611aSDavid van Moolenbroek static clock_t last_update = 0; 97*31b6611aSDavid van Moolenbroek 98*31b6611aSDavid van Moolenbroek if (parent != service_node) 99*31b6611aSDavid van Moolenbroek return; 100*31b6611aSDavid van Moolenbroek 101*31b6611aSDavid van Moolenbroek if (last_update != now) { 102*31b6611aSDavid van Moolenbroek service_update(); 103*31b6611aSDavid van Moolenbroek 104*31b6611aSDavid van Moolenbroek last_update = now; 105*31b6611aSDavid van Moolenbroek } 106*31b6611aSDavid van Moolenbroek } 107*31b6611aSDavid van Moolenbroek 108*31b6611aSDavid van Moolenbroek /* 109*31b6611aSDavid van Moolenbroek * A getdents request is being performed. If it is in the service directory, 110*31b6611aSDavid van Moolenbroek * update the tables. 111*31b6611aSDavid van Moolenbroek */ 112*31b6611aSDavid van Moolenbroek void 113*31b6611aSDavid van Moolenbroek service_getdents(struct inode * node) 114*31b6611aSDavid van Moolenbroek { 115*31b6611aSDavid van Moolenbroek 116*31b6611aSDavid van Moolenbroek if (node != service_node) 117*31b6611aSDavid van Moolenbroek return; 118*31b6611aSDavid van Moolenbroek 119*31b6611aSDavid van Moolenbroek service_update(); 120*31b6611aSDavid van Moolenbroek } 121*31b6611aSDavid van Moolenbroek 122*31b6611aSDavid van Moolenbroek /* 123*31b6611aSDavid van Moolenbroek * A read request is being performed. If it is on a file in the service 124*31b6611aSDavid van Moolenbroek * directory, process the read request. We rely on the fact that any read 125*31b6611aSDavid van Moolenbroek * call will have been preceded by a lookup, so its table entry has been 126*31b6611aSDavid van Moolenbroek * updated very recently. 127*31b6611aSDavid van Moolenbroek */ 128*31b6611aSDavid van Moolenbroek void 129*31b6611aSDavid van Moolenbroek service_read(struct inode * node) 130*31b6611aSDavid van Moolenbroek { 131*31b6611aSDavid van Moolenbroek struct inode *parent; 132*31b6611aSDavid van Moolenbroek index_t slot; 133*31b6611aSDavid van Moolenbroek struct rprocpub *rpub; 134*31b6611aSDavid van Moolenbroek struct rproc *rp; 135*31b6611aSDavid van Moolenbroek 136*31b6611aSDavid van Moolenbroek if (get_parent_inode(node) != service_node) 137*31b6611aSDavid van Moolenbroek return; 138*31b6611aSDavid van Moolenbroek 139*31b6611aSDavid van Moolenbroek slot = get_inode_index(node); 140*31b6611aSDavid van Moolenbroek rpub = &rprocpub[slot]; 141*31b6611aSDavid van Moolenbroek rp = &rproc[slot]; 142*31b6611aSDavid van Moolenbroek 143*31b6611aSDavid van Moolenbroek /* TODO: add a large number of other fields! */ 144*31b6611aSDavid van Moolenbroek buf_printf("%d %d\n", rpub->endpoint, rp->r_restarts); 145*31b6611aSDavid van Moolenbroek } 146