xref: /minix/minix/fs/procfs/service.c (revision e3b78ef1)
1 /* ProcFS - service.c - the service subdirectory */
2 
3 #include "inc.h"
4 
5 #include <minix/rs.h>
6 #include "rs/const.h"
7 #include "rs/type.h"
8 
9 enum policy {
10 	POL_NONE	= 0x00,	/*     user	| endpoint	*/
11 	POL_RESET	= 0x01,	/* visible	|  change	*/
12 	POL_RESTART	= 0x02,	/* transparent	| preserved	*/
13 	POL_LIVE_UPDATE	= 0x04	/* transparent	| preserved	*/
14 };
15 
16 struct policies {
17 	#define MAX_POL_FORMAT_SZ 20
18 	char formatted[MAX_POL_FORMAT_SZ];
19 	enum policy supported;
20 };
21 
22 static struct rprocpub rprocpub[NR_SYS_PROCS];
23 static struct rproc rproc[NR_SYS_PROCS];
24 static struct policies policies[NR_SYS_PROCS];
25 
26 static struct inode *service_node;
27 
28 /* Updates the policies state from RS. Always returns an ASCIIZ string.  */
29 static const char *
30 service_get_policies(struct policies * pol, index_t slot)
31 {
32 #if 1 /* The following should be retrieved from RS and formated instead. */
33 	int pos;
34 	char *ref_label;
35 	static const struct {
36 		const char *label;
37 		const char *policy_str;
38 	} def_pol[] = {
39 		/* audio */
40                 { .label = "es1370", .policy_str = "reset" },
41                 { .label = "es1371", .policy_str = "reset" },
42                 { .label = "sb16", .policy_str = "reset" },
43 		/* bus */
44                 { .label = "i2c", .policy_str = "restart" },
45                 { .label = "pci", .policy_str = "restart" },
46                 { .label = "ti1225", .policy_str = "restart" },
47 		/* clock */
48                 { .label = "readclock.drv", .policy_str = "restart" },
49 		/* eeprom */
50                 { .label = "cat24c256", .policy_str = "restart" },
51 		/* examples */
52                 { .label = "hello", .policy_str = "restart" },
53 		/* hid */
54                 { .label = "pckbd", .policy_str = "reset" },
55 		/* iommu */
56                 { .label = "amddev", .policy_str = "" },
57 		/* net */
58 		{ .label = "3c90x", .policy_str = "restart" },
59                 { .label = "atl2", .policy_str = "restart" },
60                 { .label = "dec21140A", .policy_str = "restart" },
61                 { .label = "dp8390", .policy_str = "restart" },
62                 { .label = "dpeth", .policy_str = "restart" },
63                 { .label = "e1000", .policy_str = "restart" },
64                 { .label = "fxp", .policy_str = "restart" },
65                 { .label = "lance", .policy_str = "restart" },
66                 { .label = "lan8710a", .policy_str = "restart" },
67                 { .label = "orinoco", .policy_str = "restart" },
68                 { .label = "rtl8139", .policy_str = "restart" },
69                 { .label = "rtl8169", .policy_str = "restart" },
70                 { .label = "uds", .policy_str = "reset" },
71                 { .label = "virtio_net", .policy_str = "restart" },
72 		/* power */
73                 { .label = "acpi", .policy_str = "" },
74                 { .label = "tps65217", .policy_str = "" },
75                 { .label = "tps65590", .policy_str = "" },
76 		/* printer */
77                 { .label = "printer", .policy_str = "restart" },
78 		/* sensors */
79                 { .label = "bmp085", .policy_str = "" },
80                 { .label = "sht21", .policy_str = "restart" },
81                 { .label = "tsl2550", .policy_str = "restart" },
82 		/* storage */
83                 { .label = "ahci", .policy_str = "reset" },
84                 { .label = "at_wini", .policy_str = "reset" },
85                 { .label = "fbd", .policy_str = "reset" },
86                 { .label = "filter", .policy_str = "reset" },
87                 { .label = "floppy", .policy_str = "reset" },
88                 { .label = "memory", .policy_str = "restart" },
89                 { .label = "mmc", .policy_str = "reset" },
90                 { .label = "virtio_blk", .policy_str = "reset" },
91                 { .label = "vnd", .policy_str = "reset" },
92 		/* system */
93                 { .label = "gpio", .policy_str = "restart" },
94                 { .label = "log", .policy_str = "restart" },
95                 { .label = "random", .policy_str = "restart" },
96 		/* tty */
97                 { .label = "pty", .policy_str = "restart" },
98                 { .label = "tty", .policy_str = "" },
99 		/* usb */
100                 { .label = "usbd", .policy_str = "" },
101                 { .label = "usb_hub", .policy_str = "" },
102                 { .label = "usb_storage", .policy_str = "" },
103 		/* video */
104                 { .label = "fb", .policy_str = "" },
105                 { .label = "tda19988", .policy_str = "" },
106 		/* vmm_guest */
107                 { .label = "vbox", .policy_str = "" },
108 		/* fs */
109                 { .label = "ext2", .policy_str = "" },
110                 { .label = "hgfs", .policy_str = "" },
111                 { .label = "isofs", .policy_str = "" },
112                 { .label = "mfs", .policy_str = "" },
113                 { .label = "pfs", .policy_str = "" },
114                 { .label = "procfs", .policy_str = "" },
115                 { .label = "vbfs", .policy_str = "" },
116 		/* net */
117                 { .label = "inet", .policy_str = "reset" },
118                 { .label = "lwip", .policy_str = "" },
119 		/* servers */
120                 { .label = "devman", .policy_str = "" },
121                 { .label = "ds", .policy_str = "" },
122                 { .label = "input", .policy_str = "reset" },
123                 { .label = "ipc", .policy_str = "restart" },
124                 { .label = "is", .policy_str = "restart" },
125                 { .label = "pm", .policy_str = "" },
126                 { .label = "rs", .policy_str = "" },
127                 { .label = "sched", .policy_str = "" },
128                 { .label = "vfs", .policy_str = "" },
129                 { .label = "vm", .policy_str = "" },
130 		//{ .label = "", .policy_str = "" },
131 	};
132 
133 	/* Find the related policy, based on the file name of the service. */
134 	ref_label = strrchr(rprocpub[slot].proc_name, '/');
135 	if (NULL == ref_label)
136 		ref_label = rprocpub[slot].proc_name;
137 
138 	memset(pol[slot].formatted, 0, MAX_POL_FORMAT_SZ);
139 	for(pos = 0; pos < (sizeof(def_pol) / sizeof(def_pol[0])); pos++) {
140 		if (0 == strcmp(ref_label, def_pol[pos].label)) {
141 			(void)strncpy(pol[slot].formatted, def_pol[pos].policy_str, MAX_POL_FORMAT_SZ);
142 			pol[slot].formatted[MAX_POL_FORMAT_SZ-1] = '\0';
143 			break;
144 		}
145 	}
146 #else
147 	/* Should do something sensible, based on flags from RS/SEF. */
148 #endif
149 
150 	return pol[slot].formatted;
151 }
152 
153 /*
154  * Update the contents of the service directory, by first updating the RS
155  * tables and then updating the directory contents.
156  */
157 static void
158 service_update(void)
159 {
160 	struct inode *node;
161 	struct inode_stat stat;
162 	index_t slot;
163 
164 	/* There is not much we can do if either of these calls fails. */
165 	(void)getsysinfo(RS_PROC_NR, SI_PROCPUB_TAB, rprocpub,
166 	    sizeof(rprocpub));
167 	(void)getsysinfo(RS_PROC_NR, SI_PROC_TAB, rproc, sizeof(rproc));
168 
169 	/*
170 	 * As with PIDs, we make two passes.  Delete first, then add.  This
171 	 * prevents problems in the hypothetical case that between updates, one
172 	 * slot ends up with the label name of a previous, different slot.
173 	 */
174 	for (slot = 0; slot < NR_SYS_PROCS; slot++) {
175 		if ((node = get_inode_by_index(service_node, slot)) == NULL)
176 			continue;
177 
178 		/*
179 		 * If the slot is no longer in use, or the label name does not
180 		 * match, the node must be deleted.
181 		 */
182 		if (!(rproc[slot].r_flags & RS_IN_USE) ||
183 		    strcmp(get_inode_name(node), rprocpub[slot].label))
184 			delete_inode(node);
185 	}
186 
187 	memset(&stat, 0, sizeof(stat));
188 	stat.mode = REG_ALL_MODE;
189 	stat.uid = SUPER_USER;
190 	stat.gid = SUPER_USER;
191 
192 	for (slot = 0; slot < NR_SYS_PROCS; slot++) {
193 		if (!(rproc[slot].r_flags & RS_IN_USE) ||
194 		    get_inode_by_index(service_node, slot) != NULL)
195 			continue;
196 
197 		node = add_inode(service_node, rprocpub[slot].label, slot,
198 		    &stat, (index_t)0, (cbdata_t)slot);
199 
200 		if (node == NULL)
201 			out_of_inodes();
202 	}
203 }
204 
205 /*
206  * Initialize the service directory.
207  */
208 void
209 service_init(void)
210 {
211 	struct inode *root, *node;
212 	struct inode_stat stat;
213 
214 	root = get_root_inode();
215 
216 	memset(&stat, 0, sizeof(stat));
217 	stat.mode = DIR_ALL_MODE;
218 	stat.uid = SUPER_USER;
219 	stat.gid = SUPER_USER;
220 
221 	service_node = add_inode(root, "service", NO_INDEX, &stat,
222 	    NR_SYS_PROCS, NULL);
223 
224 	if (service_node == NULL)
225 		panic("unable to create service node");
226 }
227 
228 /*
229  * A lookup request is being performed.  If it is in the service directory,
230  * update the tables.  We do this lazily, to reduce overhead.
231  */
232 void
233 service_lookup(struct inode * parent, clock_t now)
234 {
235 	static clock_t last_update = 0;
236 
237 	if (parent != service_node)
238 		return;
239 
240 	if (last_update != now) {
241 		service_update();
242 
243 		last_update = now;
244 	}
245 }
246 
247 /*
248  * A getdents request is being performed.  If it is in the service directory,
249  * update the tables.
250  */
251 void
252 service_getdents(struct inode * node)
253 {
254 
255 	if (node != service_node)
256 		return;
257 
258 	service_update();
259 }
260 
261 /*
262  * A read request is being performed.  If it is on a file in the service
263  * directory, process the read request.  We rely on the fact that any read
264  * call will have been preceded by a lookup, so its table entry has been
265  * updated very recently.
266  */
267 void
268 service_read(struct inode * node)
269 {
270 	struct inode *parent;
271 	index_t slot;
272 	struct rprocpub *rpub;
273 	struct rproc *rp;
274 
275 	if (get_parent_inode(node) != service_node)
276 		return;
277 
278 	slot = get_inode_index(node);
279 	rpub = &rprocpub[slot];
280 	rp = &rproc[slot];
281 
282 	/* TODO: add a large number of other fields! */
283 	buf_printf("filename: %s\n", rpub->proc_name);
284 	buf_printf("endpoint: %d\n", rpub->endpoint);
285 	buf_printf("restarts: %d\n", rp->r_restarts);
286 	buf_printf("policies: %s\n", service_get_policies(policies, slot));
287 }
288