xref: /freebsd/libexec/rpc.rstatd/rstat_proc.c (revision a6fe717c2a876105123214c05176cd74106fb94b)
10c0b205cSGeoff Rehmet /*
20c0b205cSGeoff Rehmet  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
30c0b205cSGeoff Rehmet  * unrestricted use provided that this legend is included on all tape
40c0b205cSGeoff Rehmet  * media and as a part of the software program in whole or part.  Users
50c0b205cSGeoff Rehmet  * may copy or modify Sun RPC without charge, but are not authorized
60c0b205cSGeoff Rehmet  * to license or distribute it to anyone else except as part of a product or
70c0b205cSGeoff Rehmet  * program developed by the user.
80c0b205cSGeoff Rehmet  *
90c0b205cSGeoff Rehmet  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
100c0b205cSGeoff Rehmet  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
110c0b205cSGeoff Rehmet  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
120c0b205cSGeoff Rehmet  *
130c0b205cSGeoff Rehmet  * Sun RPC is provided with no support and without any obligation on the
140c0b205cSGeoff Rehmet  * part of Sun Microsystems, Inc. to assist in its use, correction,
150c0b205cSGeoff Rehmet  * modification or enhancement.
160c0b205cSGeoff Rehmet  *
170c0b205cSGeoff Rehmet  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
180c0b205cSGeoff Rehmet  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
190c0b205cSGeoff Rehmet  * OR ANY PART THEREOF.
200c0b205cSGeoff Rehmet  *
210c0b205cSGeoff Rehmet  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
220c0b205cSGeoff Rehmet  * or profits or other special, indirect and consequential damages, even if
230c0b205cSGeoff Rehmet  * Sun has been advised of the possibility of such damages.
240c0b205cSGeoff Rehmet  *
250c0b205cSGeoff Rehmet  * Sun Microsystems, Inc.
260c0b205cSGeoff Rehmet  * 2550 Garcia Avenue
270c0b205cSGeoff Rehmet  * Mountain View, California  94043
280c0b205cSGeoff Rehmet  */
29754c3c57SPhilippe Charnier 
300c0b205cSGeoff Rehmet /*
310c0b205cSGeoff Rehmet  * rstat service:  built with rstat.x and derived from rpc.rstatd.c
320c0b205cSGeoff Rehmet  *
330c0b205cSGeoff Rehmet  * Copyright (c) 1984 by Sun Microsystems, Inc.
340c0b205cSGeoff Rehmet  */
350c0b205cSGeoff Rehmet 
36e831f308SGarrett Wollman #include <sys/types.h>
37e831f308SGarrett Wollman #include <sys/socket.h>
38e831f308SGarrett Wollman #include <sys/sysctl.h>
39e831f308SGarrett Wollman #include <sys/time.h>
40fd3a502dSPoul-Henning Kamp #include <sys/resource.h>
41b2dfb1f9SJustin T. Gibbs #include <sys/param.h>
42e831f308SGarrett Wollman 
43754c3c57SPhilippe Charnier #include <err.h>
44b9d45cebSBill Fenner #include <errno.h>
450c0b205cSGeoff Rehmet #include <fcntl.h>
460c0b205cSGeoff Rehmet #include <limits.h>
470c0b205cSGeoff Rehmet #include <signal.h>
480c0b205cSGeoff Rehmet #include <stdio.h>
490c0b205cSGeoff Rehmet #include <stdlib.h>
500c0b205cSGeoff Rehmet #include <string.h>
510c0b205cSGeoff Rehmet #include <syslog.h>
52754c3c57SPhilippe Charnier #include <unistd.h>
53b2dfb1f9SJustin T. Gibbs #include <devstat.h>
540c0b205cSGeoff Rehmet 
550c0b205cSGeoff Rehmet #include <net/if.h>
56e831f308SGarrett Wollman #include <net/if_mib.h>
57e831f308SGarrett Wollman 
580c0b205cSGeoff Rehmet #undef FSHIFT			 /* Use protocol's shift and scale values */
590c0b205cSGeoff Rehmet #undef FSCALE
600c0b205cSGeoff Rehmet #undef if_ipackets
610c0b205cSGeoff Rehmet #undef if_ierrors
620c0b205cSGeoff Rehmet #undef if_opackets
630c0b205cSGeoff Rehmet #undef if_oerrors
640c0b205cSGeoff Rehmet #undef if_collisions
650c0b205cSGeoff Rehmet #include <rpcsvc/rstat.h>
660c0b205cSGeoff Rehmet 
67821aa3b4SMike Barcroft int haveadisk(void);
68a174e5b1SWarner Losh void updatexfers(int, int *);
69a174e5b1SWarner Losh int stats_service(void);
700c0b205cSGeoff Rehmet 
710c0b205cSGeoff Rehmet extern int from_inetd;
720c0b205cSGeoff Rehmet int sincelastreq = 0;		/* number of alarms since last request */
730c0b205cSGeoff Rehmet extern int closedown;
740c0b205cSGeoff Rehmet 
750c0b205cSGeoff Rehmet union {
760c0b205cSGeoff Rehmet     struct stats s1;
770c0b205cSGeoff Rehmet     struct statsswtch s2;
780c0b205cSGeoff Rehmet     struct statstime s3;
790c0b205cSGeoff Rehmet } stats_all;
800c0b205cSGeoff Rehmet 
810c0b205cSGeoff Rehmet void updatestat();
82bd273f0cSDavid E. O'Brien static int stat_is_init = 0;
830c0b205cSGeoff Rehmet 
840c0b205cSGeoff Rehmet static int	cp_time_xlat[RSTAT_CPUSTATES] = { CP_USER, CP_NICE, CP_SYS,
850c0b205cSGeoff Rehmet 							CP_IDLE };
860c0b205cSGeoff Rehmet static long	bsd_cp_time[CPUSTATES];
870c0b205cSGeoff Rehmet 
880c0b205cSGeoff Rehmet 
890c0b205cSGeoff Rehmet #ifndef FSCALE
900c0b205cSGeoff Rehmet #define FSCALE (1 << 8)
910c0b205cSGeoff Rehmet #endif
920c0b205cSGeoff Rehmet 
93754c3c57SPhilippe Charnier void
stat_init(void)94a174e5b1SWarner Losh stat_init(void)
950c0b205cSGeoff Rehmet {
960c0b205cSGeoff Rehmet     stat_is_init = 1;
97685233abSJonathan Chen     alarm(0);
980c0b205cSGeoff Rehmet     updatestat();
990c0b205cSGeoff Rehmet     (void) signal(SIGALRM, updatestat);
1000c0b205cSGeoff Rehmet     alarm(1);
1010c0b205cSGeoff Rehmet }
1020c0b205cSGeoff Rehmet 
1030c0b205cSGeoff Rehmet statstime *
rstatproc_stats_3_svc(void * argp,struct svc_req * rqstp)104a174e5b1SWarner Losh rstatproc_stats_3_svc(void *argp, struct svc_req *rqstp)
1050c0b205cSGeoff Rehmet {
1060c0b205cSGeoff Rehmet     if (! stat_is_init)
1070c0b205cSGeoff Rehmet         stat_init();
1080c0b205cSGeoff Rehmet     sincelastreq = 0;
1090c0b205cSGeoff Rehmet     return(&stats_all.s3);
1100c0b205cSGeoff Rehmet }
1110c0b205cSGeoff Rehmet 
1120c0b205cSGeoff Rehmet statsswtch *
rstatproc_stats_2_svc(void * argp,struct svc_req * rqstp)113a174e5b1SWarner Losh rstatproc_stats_2_svc(void *argp, struct svc_req *rqstp)
1140c0b205cSGeoff Rehmet {
1150c0b205cSGeoff Rehmet     if (! stat_is_init)
1160c0b205cSGeoff Rehmet         stat_init();
1170c0b205cSGeoff Rehmet     sincelastreq = 0;
1180c0b205cSGeoff Rehmet     return(&stats_all.s2);
1190c0b205cSGeoff Rehmet }
1200c0b205cSGeoff Rehmet 
1210c0b205cSGeoff Rehmet stats *
rstatproc_stats_1_svc(void * argp,struct svc_req * rqstp)122a174e5b1SWarner Losh rstatproc_stats_1_svc(void *argp, struct svc_req *rqstp)
1230c0b205cSGeoff Rehmet {
1240c0b205cSGeoff Rehmet     if (! stat_is_init)
1250c0b205cSGeoff Rehmet         stat_init();
1260c0b205cSGeoff Rehmet     sincelastreq = 0;
1270c0b205cSGeoff Rehmet     return(&stats_all.s1);
1280c0b205cSGeoff Rehmet }
1290c0b205cSGeoff Rehmet 
1300c0b205cSGeoff Rehmet u_int *
rstatproc_havedisk_3_svc(void * argp,struct svc_req * rqstp)131a174e5b1SWarner Losh rstatproc_havedisk_3_svc(void *argp, struct svc_req *rqstp)
1320c0b205cSGeoff Rehmet {
1330c0b205cSGeoff Rehmet     static u_int have;
1340c0b205cSGeoff Rehmet 
1350c0b205cSGeoff Rehmet     if (! stat_is_init)
1360c0b205cSGeoff Rehmet         stat_init();
1370c0b205cSGeoff Rehmet     sincelastreq = 0;
138821aa3b4SMike Barcroft     have = haveadisk();
1390c0b205cSGeoff Rehmet 	return(&have);
1400c0b205cSGeoff Rehmet }
1410c0b205cSGeoff Rehmet 
1420c0b205cSGeoff Rehmet u_int *
rstatproc_havedisk_2_svc(void * argp,struct svc_req * rqstp)143a174e5b1SWarner Losh rstatproc_havedisk_2_svc(void *argp, struct svc_req *rqstp)
1440c0b205cSGeoff Rehmet {
145e4a0e42bSBill Paul     return(rstatproc_havedisk_3_svc(argp, rqstp));
1460c0b205cSGeoff Rehmet }
1470c0b205cSGeoff Rehmet 
1480c0b205cSGeoff Rehmet u_int *
rstatproc_havedisk_1_svc(void * argp,struct svc_req * rqstp)149a174e5b1SWarner Losh rstatproc_havedisk_1_svc(void *argp, struct svc_req *rqstp)
1500c0b205cSGeoff Rehmet {
151e4a0e42bSBill Paul     return(rstatproc_havedisk_3_svc(argp, rqstp));
1520c0b205cSGeoff Rehmet }
1530c0b205cSGeoff Rehmet 
1540c0b205cSGeoff Rehmet void
updatestat(void)155a174e5b1SWarner Losh updatestat(void)
1560c0b205cSGeoff Rehmet {
157754c3c57SPhilippe Charnier 	int i, hz;
158e831f308SGarrett Wollman 	struct clockinfo clockrate;
159e831f308SGarrett Wollman 	struct ifmibdata ifmd;
1600c0b205cSGeoff Rehmet 	double avrun[3];
1610c0b205cSGeoff Rehmet 	struct timeval tm, btm;
162e831f308SGarrett Wollman 	int mib[6];
163e831f308SGarrett Wollman 	size_t len;
16483c9dea1SGleb Smirnoff 	uint64_t val;
165e831f308SGarrett Wollman 	int ifcount;
1660c0b205cSGeoff Rehmet 
1670c0b205cSGeoff Rehmet #ifdef DEBUG
1680c0b205cSGeoff Rehmet 	fprintf(stderr, "entering updatestat\n");
1690c0b205cSGeoff Rehmet #endif
1700c0b205cSGeoff Rehmet 	if (sincelastreq >= closedown) {
1710c0b205cSGeoff Rehmet #ifdef DEBUG
1720c0b205cSGeoff Rehmet                 fprintf(stderr, "about to closedown\n");
1730c0b205cSGeoff Rehmet #endif
1740c0b205cSGeoff Rehmet                 if (from_inetd)
1750c0b205cSGeoff Rehmet                         exit(0);
1760c0b205cSGeoff Rehmet                 else {
1770c0b205cSGeoff Rehmet                         stat_is_init = 0;
1780c0b205cSGeoff Rehmet                         return;
1790c0b205cSGeoff Rehmet                 }
1800c0b205cSGeoff Rehmet 	}
1810c0b205cSGeoff Rehmet 	sincelastreq++;
1820c0b205cSGeoff Rehmet 
183e831f308SGarrett Wollman 	mib[0] = CTL_KERN;
184e831f308SGarrett Wollman 	mib[1] = KERN_CLOCKRATE;
185e831f308SGarrett Wollman 	len = sizeof clockrate;
186e831f308SGarrett Wollman 	if (sysctl(mib, 2, &clockrate, &len, 0, 0) < 0) {
187e831f308SGarrett Wollman 		syslog(LOG_ERR, "sysctl(kern.clockrate): %m");
1880c0b205cSGeoff Rehmet 		exit(1);
1890c0b205cSGeoff Rehmet 	}
190e831f308SGarrett Wollman 	hz = clockrate.hz;
191e831f308SGarrett Wollman 
19287f2ff4fSJohn Baldwin 	len = sizeof(bsd_cp_time);
19387f2ff4fSJohn Baldwin 	if (sysctlbyname("kern.cp_time", bsd_cp_time, &len, 0, 0) < 0) {
19487f2ff4fSJohn Baldwin 		syslog(LOG_ERR, "sysctl(kern.cp_time): %m");
1950c0b205cSGeoff Rehmet 		exit(1);
1960c0b205cSGeoff Rehmet 	}
1970c0b205cSGeoff Rehmet 	for(i = 0; i < RSTAT_CPUSTATES ; i++)
1980c0b205cSGeoff Rehmet 		stats_all.s1.cp_time[i] = bsd_cp_time[cp_time_xlat[i]];
199e831f308SGarrett Wollman 
2000c0b205cSGeoff Rehmet         (void)getloadavg(avrun, sizeof(avrun) / sizeof(avrun[0]));
201e831f308SGarrett Wollman 
2020c0b205cSGeoff Rehmet 	stats_all.s2.avenrun[0] = avrun[0] * FSCALE;
2030c0b205cSGeoff Rehmet 	stats_all.s2.avenrun[1] = avrun[1] * FSCALE;
2040c0b205cSGeoff Rehmet 	stats_all.s2.avenrun[2] = avrun[2] * FSCALE;
205e831f308SGarrett Wollman 
206e831f308SGarrett Wollman 	mib[0] = CTL_KERN;
207e831f308SGarrett Wollman 	mib[1] = KERN_BOOTTIME;
208e831f308SGarrett Wollman 	len = sizeof btm;
209e831f308SGarrett Wollman 	if (sysctl(mib, 2, &btm, &len, 0, 0) < 0) {
210e831f308SGarrett Wollman 		syslog(LOG_ERR, "sysctl(kern.boottime): %m");
2110c0b205cSGeoff Rehmet 		exit(1);
2120c0b205cSGeoff Rehmet 	}
213e831f308SGarrett Wollman 
2140c0b205cSGeoff Rehmet 	stats_all.s2.boottime.tv_sec = btm.tv_sec;
2150c0b205cSGeoff Rehmet 	stats_all.s2.boottime.tv_usec = btm.tv_usec;
2160c0b205cSGeoff Rehmet 
2170c0b205cSGeoff Rehmet 
2180c0b205cSGeoff Rehmet #ifdef DEBUG
2190c0b205cSGeoff Rehmet 	fprintf(stderr, "%d %d %d %d\n", stats_all.s1.cp_time[0],
2200c0b205cSGeoff Rehmet 	    stats_all.s1.cp_time[1], stats_all.s1.cp_time[2], stats_all.s1.cp_time[3]);
2210c0b205cSGeoff Rehmet #endif
2220c0b205cSGeoff Rehmet 
22387f2ff4fSJohn Baldwin #define	FETCH_CNT(stat, cnt) do {					\
22483c9dea1SGleb Smirnoff 	len = sizeof(uint64_t);						\
22583c9dea1SGleb Smirnoff 	if (sysctlbyname("vm.stats." #cnt , &val, &len, NULL, 0) < 0) {	\
22687f2ff4fSJohn Baldwin 		syslog(LOG_ERR, "sysctl(vm.stats." #cnt "): %m");	\
22787f2ff4fSJohn Baldwin 		exit(1);						\
22887f2ff4fSJohn Baldwin 	}								\
22983c9dea1SGleb Smirnoff 	stat = val;							\
23087f2ff4fSJohn Baldwin } while (0)
23187f2ff4fSJohn Baldwin 
23287f2ff4fSJohn Baldwin 	FETCH_CNT(stats_all.s1.v_pgpgin, vm.v_vnodepgsin);
23387f2ff4fSJohn Baldwin 	FETCH_CNT(stats_all.s1.v_pgpgout, vm.v_vnodepgsout);
23487f2ff4fSJohn Baldwin 	FETCH_CNT(stats_all.s1.v_pswpin, vm.v_swappgsin);
23587f2ff4fSJohn Baldwin 	FETCH_CNT(stats_all.s1.v_pswpout, vm.v_swappgsout);
23687f2ff4fSJohn Baldwin 	FETCH_CNT(stats_all.s1.v_intr, sys.v_intr);
23787f2ff4fSJohn Baldwin 	FETCH_CNT(stats_all.s2.v_swtch, sys.v_swtch);
238902d9eafSEd Schouten 	(void)gettimeofday(&tm, NULL);
2390c0b205cSGeoff Rehmet 	stats_all.s1.v_intr -= hz*(tm.tv_sec - btm.tv_sec) +
2400c0b205cSGeoff Rehmet 	    hz*(tm.tv_usec - btm.tv_usec)/1000000;
2410c0b205cSGeoff Rehmet 
242b2dfb1f9SJustin T. Gibbs 	/* update disk transfers */
243b2dfb1f9SJustin T. Gibbs 	updatexfers(RSTAT_DK_NDRIVE, stats_all.s1.dk_xfer);
2440c0b205cSGeoff Rehmet 
245e831f308SGarrett Wollman 	mib[0] = CTL_NET;
246e831f308SGarrett Wollman 	mib[1] = PF_LINK;
247e831f308SGarrett Wollman 	mib[2] = NETLINK_GENERIC;
248e831f308SGarrett Wollman 	mib[3] = IFMIB_SYSTEM;
249e831f308SGarrett Wollman 	mib[4] = IFMIB_IFCOUNT;
250e831f308SGarrett Wollman 	len = sizeof ifcount;
251e831f308SGarrett Wollman 	if (sysctl(mib, 5, &ifcount, &len, 0, 0) < 0) {
252e831f308SGarrett Wollman 		syslog(LOG_ERR, "sysctl(net.link.generic.system.ifcount): %m");
253e831f308SGarrett Wollman 		exit(1);
254e831f308SGarrett Wollman 	}
255e831f308SGarrett Wollman 
2560c0b205cSGeoff Rehmet 	stats_all.s1.if_ipackets = 0;
2570c0b205cSGeoff Rehmet 	stats_all.s1.if_opackets = 0;
2580c0b205cSGeoff Rehmet 	stats_all.s1.if_ierrors = 0;
2590c0b205cSGeoff Rehmet 	stats_all.s1.if_oerrors = 0;
2600c0b205cSGeoff Rehmet 	stats_all.s1.if_collisions = 0;
261e831f308SGarrett Wollman 	for (i = 1; i <= ifcount; i++) {
262e831f308SGarrett Wollman 		len = sizeof ifmd;
263e831f308SGarrett Wollman 		mib[3] = IFMIB_IFDATA;
264e831f308SGarrett Wollman 		mib[4] = i;
265e831f308SGarrett Wollman 		mib[5] = IFDATA_GENERAL;
266e831f308SGarrett Wollman 		if (sysctl(mib, 6, &ifmd, &len, 0, 0) < 0) {
267b9d45cebSBill Fenner 			if (errno == ENOENT)
268b9d45cebSBill Fenner 				continue;
269b9d45cebSBill Fenner 
270e831f308SGarrett Wollman 			syslog(LOG_ERR, "sysctl(net.link.ifdata.%d.general)"
271e831f308SGarrett Wollman 			       ": %m", i);
2720c0b205cSGeoff Rehmet 			exit(1);
2730c0b205cSGeoff Rehmet 		}
274e831f308SGarrett Wollman 
275e831f308SGarrett Wollman 		stats_all.s1.if_ipackets += ifmd.ifmd_data.ifi_ipackets;
276e831f308SGarrett Wollman 		stats_all.s1.if_opackets += ifmd.ifmd_data.ifi_opackets;
277e831f308SGarrett Wollman 		stats_all.s1.if_ierrors += ifmd.ifmd_data.ifi_ierrors;
278e831f308SGarrett Wollman 		stats_all.s1.if_oerrors += ifmd.ifmd_data.ifi_oerrors;
279e831f308SGarrett Wollman 		stats_all.s1.if_collisions += ifmd.ifmd_data.ifi_collisions;
2800c0b205cSGeoff Rehmet 	}
281902d9eafSEd Schouten 	(void)gettimeofday(&tm, NULL);
282902d9eafSEd Schouten 	stats_all.s3.curtime.tv_sec = tm.tv_sec;
283902d9eafSEd Schouten 	stats_all.s3.curtime.tv_usec = tm.tv_usec;
2840c0b205cSGeoff Rehmet 	alarm(1);
2850c0b205cSGeoff Rehmet }
2860c0b205cSGeoff Rehmet 
2870c0b205cSGeoff Rehmet /*
2880c0b205cSGeoff Rehmet  * returns true if have a disk
2890c0b205cSGeoff Rehmet  */
290754c3c57SPhilippe Charnier int
haveadisk(void)291821aa3b4SMike Barcroft haveadisk(void)
2920c0b205cSGeoff Rehmet {
293b2dfb1f9SJustin T. Gibbs 	register int i;
294b2dfb1f9SJustin T. Gibbs 	struct statinfo stats;
295b2dfb1f9SJustin T. Gibbs 	int num_devices, retval = 0;
2960c0b205cSGeoff Rehmet 
297a57042dfSPoul-Henning Kamp 	if ((num_devices = devstat_getnumdevs(NULL)) < 0) {
298b2dfb1f9SJustin T. Gibbs 		syslog(LOG_ERR, "rstatd: can't get number of devices: %s",
299b2dfb1f9SJustin T. Gibbs 		       devstat_errbuf);
3000c0b205cSGeoff Rehmet 		exit(1);
3010c0b205cSGeoff Rehmet 	}
3020c0b205cSGeoff Rehmet 
303a57042dfSPoul-Henning Kamp 	if (devstat_checkversion(NULL) < 0) {
304b2dfb1f9SJustin T. Gibbs 		syslog(LOG_ERR, "rstatd: %s", devstat_errbuf);
3050c0b205cSGeoff Rehmet 		exit(1);
3060c0b205cSGeoff Rehmet 	}
307b2dfb1f9SJustin T. Gibbs 
308b2dfb1f9SJustin T. Gibbs 	stats.dinfo = (struct devinfo *)malloc(sizeof(struct devinfo));
309b2dfb1f9SJustin T. Gibbs 	bzero(stats.dinfo, sizeof(struct devinfo));
310b2dfb1f9SJustin T. Gibbs 
311a57042dfSPoul-Henning Kamp 	if (devstat_getdevs(NULL, &stats) == -1) {
312b2dfb1f9SJustin T. Gibbs 		syslog(LOG_ERR, "rstatd: can't get device list: %s",
313b2dfb1f9SJustin T. Gibbs 		       devstat_errbuf);
314b2dfb1f9SJustin T. Gibbs 		exit(1);
315b2dfb1f9SJustin T. Gibbs 	}
316b2dfb1f9SJustin T. Gibbs 	for (i = 0; i < stats.dinfo->numdevs; i++) {
317b2dfb1f9SJustin T. Gibbs 		if (((stats.dinfo->devices[i].device_type
318b2dfb1f9SJustin T. Gibbs 		      & DEVSTAT_TYPE_MASK) == DEVSTAT_TYPE_DIRECT)
319b2dfb1f9SJustin T. Gibbs 		 && ((stats.dinfo->devices[i].device_type
320b2dfb1f9SJustin T. Gibbs 		      & DEVSTAT_TYPE_PASS) == 0)) {
321b2dfb1f9SJustin T. Gibbs 			retval = 1;
322b2dfb1f9SJustin T. Gibbs 			break;
323b2dfb1f9SJustin T. Gibbs 		}
324b2dfb1f9SJustin T. Gibbs 	}
325b2dfb1f9SJustin T. Gibbs 
326b994e535SKenneth D. Merry 	if (stats.dinfo->mem_ptr)
327b994e535SKenneth D. Merry 		free(stats.dinfo->mem_ptr);
328b994e535SKenneth D. Merry 
329b2dfb1f9SJustin T. Gibbs 	free(stats.dinfo);
330b2dfb1f9SJustin T. Gibbs 	return(retval);
331b2dfb1f9SJustin T. Gibbs }
332b2dfb1f9SJustin T. Gibbs 
333b2dfb1f9SJustin T. Gibbs void
updatexfers(int numdevs,int * devs)334a174e5b1SWarner Losh updatexfers(int numdevs, int *devs)
335b2dfb1f9SJustin T. Gibbs {
3367194d335SPoul-Henning Kamp 	register int i, j, k, t;
337b2dfb1f9SJustin T. Gibbs 	struct statinfo stats;
338b2dfb1f9SJustin T. Gibbs 	int num_devices = 0;
339b2dfb1f9SJustin T. Gibbs 	u_int64_t total_transfers;
340b2dfb1f9SJustin T. Gibbs 
341a57042dfSPoul-Henning Kamp 	if ((num_devices = devstat_getnumdevs(NULL)) < 0) {
342b2dfb1f9SJustin T. Gibbs 		syslog(LOG_ERR, "rstatd: can't get number of devices: %s",
343b2dfb1f9SJustin T. Gibbs 		       devstat_errbuf);
344b2dfb1f9SJustin T. Gibbs 		exit(1);
345b2dfb1f9SJustin T. Gibbs 	}
346b2dfb1f9SJustin T. Gibbs 
347a57042dfSPoul-Henning Kamp 	if (devstat_checkversion(NULL) < 0) {
348b2dfb1f9SJustin T. Gibbs 		syslog(LOG_ERR, "rstatd: %s", devstat_errbuf);
349b2dfb1f9SJustin T. Gibbs 		exit(1);
350b2dfb1f9SJustin T. Gibbs 	}
351b2dfb1f9SJustin T. Gibbs 
352b2dfb1f9SJustin T. Gibbs 	stats.dinfo = (struct devinfo *)malloc(sizeof(struct devinfo));
353b2dfb1f9SJustin T. Gibbs 	bzero(stats.dinfo, sizeof(struct devinfo));
354b2dfb1f9SJustin T. Gibbs 
355a57042dfSPoul-Henning Kamp 	if (devstat_getdevs(NULL, &stats) == -1) {
356b2dfb1f9SJustin T. Gibbs 		syslog(LOG_ERR, "rstatd: can't get device list: %s",
357b2dfb1f9SJustin T. Gibbs 		       devstat_errbuf);
358b2dfb1f9SJustin T. Gibbs 		exit(1);
359b2dfb1f9SJustin T. Gibbs 	}
360b2dfb1f9SJustin T. Gibbs 
361b2dfb1f9SJustin T. Gibbs 	for (i = 0, j = 0; i < stats.dinfo->numdevs && j < numdevs; i++) {
362b2dfb1f9SJustin T. Gibbs 		if (((stats.dinfo->devices[i].device_type
363b2dfb1f9SJustin T. Gibbs 		      & DEVSTAT_TYPE_MASK) == DEVSTAT_TYPE_DIRECT)
364b2dfb1f9SJustin T. Gibbs 		 && ((stats.dinfo->devices[i].device_type
365b2dfb1f9SJustin T. Gibbs 		      & DEVSTAT_TYPE_PASS) == 0)) {
3667194d335SPoul-Henning Kamp 			total_transfers = 0;
3677194d335SPoul-Henning Kamp 			for (k = 0; k < DEVSTAT_N_TRANS_FLAGS; k++)
3687194d335SPoul-Henning Kamp 				total_transfers +=
3697194d335SPoul-Henning Kamp 				    stats.dinfo->devices[i].operations[k];
370b2dfb1f9SJustin T. Gibbs 			/*
371b2dfb1f9SJustin T. Gibbs 			 * XXX KDM If the total transfers for this device
372b2dfb1f9SJustin T. Gibbs 			 * are greater than the amount we can fit in a
373b2dfb1f9SJustin T. Gibbs 			 * signed integer, just set them to the maximum
374b2dfb1f9SJustin T. Gibbs 			 * amount we can fit in a signed integer.  I have a
375b2dfb1f9SJustin T. Gibbs 			 * feeling that the rstat protocol assumes 32-bit
376b2dfb1f9SJustin T. Gibbs 			 * integers, so this could well break on a 64-bit
377b2dfb1f9SJustin T. Gibbs 			 * architecture like the Alpha.
378b2dfb1f9SJustin T. Gibbs 			 */
379b2dfb1f9SJustin T. Gibbs 			if (total_transfers > INT_MAX)
3808223b746SDoug Rabson 				t = INT_MAX;
381b2dfb1f9SJustin T. Gibbs 			else
3828223b746SDoug Rabson 				t = total_transfers;
3838223b746SDoug Rabson 			devs[j] = t;
384b2dfb1f9SJustin T. Gibbs 			j++;
385b2dfb1f9SJustin T. Gibbs 		}
386b2dfb1f9SJustin T. Gibbs 	}
387b2dfb1f9SJustin T. Gibbs 
388b994e535SKenneth D. Merry 	if (stats.dinfo->mem_ptr)
389b994e535SKenneth D. Merry 		free(stats.dinfo->mem_ptr);
390b994e535SKenneth D. Merry 
391b2dfb1f9SJustin T. Gibbs 	free(stats.dinfo);
3920c0b205cSGeoff Rehmet }
3930c0b205cSGeoff Rehmet 
3940c0b205cSGeoff Rehmet void
rstat_service(struct svc_req * rqstp,SVCXPRT * transp)395a174e5b1SWarner Losh rstat_service(struct svc_req *rqstp, SVCXPRT *transp)
3960c0b205cSGeoff Rehmet {
3970c0b205cSGeoff Rehmet 	union {
3980c0b205cSGeoff Rehmet 		int fill;
3990c0b205cSGeoff Rehmet 	} argument;
400*e4253ae8SJohn Baldwin 	void *result;
401*e4253ae8SJohn Baldwin 	xdrproc_t xdr_argument, xdr_result;
402*e4253ae8SJohn Baldwin 	typedef void *(svc_cb)(void *arg, struct svc_req *rqstp);
403*e4253ae8SJohn Baldwin 	svc_cb *local;
4040c0b205cSGeoff Rehmet 
4050c0b205cSGeoff Rehmet 	switch (rqstp->rq_proc) {
4060c0b205cSGeoff Rehmet 	case NULLPROC:
407f249dbccSDag-Erling Smørgrav 		(void)svc_sendreply(transp, (xdrproc_t)xdr_void, NULL);
4080c0b205cSGeoff Rehmet 		goto leave;
4090c0b205cSGeoff Rehmet 
4100c0b205cSGeoff Rehmet 	case RSTATPROC_STATS:
411*e4253ae8SJohn Baldwin 		xdr_argument = (xdrproc_t)xdr_void;
412*e4253ae8SJohn Baldwin 		xdr_result = (xdrproc_t)xdr_statstime;
4130c0b205cSGeoff Rehmet                 switch (rqstp->rq_vers) {
4140c0b205cSGeoff Rehmet                 case RSTATVERS_ORIG:
415*e4253ae8SJohn Baldwin                         local = (svc_cb *)rstatproc_stats_1_svc;
4160c0b205cSGeoff Rehmet                         break;
4170c0b205cSGeoff Rehmet                 case RSTATVERS_SWTCH:
418*e4253ae8SJohn Baldwin                         local = (svc_cb *)rstatproc_stats_2_svc;
4190c0b205cSGeoff Rehmet                         break;
4200c0b205cSGeoff Rehmet                 case RSTATVERS_TIME:
421*e4253ae8SJohn Baldwin                         local = (svc_cb *)rstatproc_stats_3_svc;
4220c0b205cSGeoff Rehmet                         break;
4230c0b205cSGeoff Rehmet                 default:
4240c0b205cSGeoff Rehmet                         svcerr_progvers(transp, RSTATVERS_ORIG, RSTATVERS_TIME);
4250c0b205cSGeoff Rehmet                         goto leave;
4260c0b205cSGeoff Rehmet                         /*NOTREACHED*/
4270c0b205cSGeoff Rehmet                 }
4280c0b205cSGeoff Rehmet 		break;
4290c0b205cSGeoff Rehmet 
4300c0b205cSGeoff Rehmet 	case RSTATPROC_HAVEDISK:
431*e4253ae8SJohn Baldwin 		xdr_argument = (xdrproc_t)xdr_void;
432*e4253ae8SJohn Baldwin 		xdr_result = (xdrproc_t)xdr_u_int;
4330c0b205cSGeoff Rehmet                 switch (rqstp->rq_vers) {
4340c0b205cSGeoff Rehmet                 case RSTATVERS_ORIG:
435*e4253ae8SJohn Baldwin                         local = (svc_cb *)rstatproc_havedisk_1_svc;
4360c0b205cSGeoff Rehmet                         break;
4370c0b205cSGeoff Rehmet                 case RSTATVERS_SWTCH:
438*e4253ae8SJohn Baldwin                         local = (svc_cb *)rstatproc_havedisk_2_svc;
4390c0b205cSGeoff Rehmet                         break;
4400c0b205cSGeoff Rehmet                 case RSTATVERS_TIME:
441*e4253ae8SJohn Baldwin                         local = (svc_cb *)rstatproc_havedisk_3_svc;
4420c0b205cSGeoff Rehmet                         break;
4430c0b205cSGeoff Rehmet                 default:
4440c0b205cSGeoff Rehmet                         svcerr_progvers(transp, RSTATVERS_ORIG, RSTATVERS_TIME);
4450c0b205cSGeoff Rehmet                         goto leave;
4460c0b205cSGeoff Rehmet                         /*NOTREACHED*/
4470c0b205cSGeoff Rehmet                 }
4480c0b205cSGeoff Rehmet 		break;
4490c0b205cSGeoff Rehmet 
4500c0b205cSGeoff Rehmet 	default:
4510c0b205cSGeoff Rehmet 		svcerr_noproc(transp);
4520c0b205cSGeoff Rehmet 		goto leave;
4530c0b205cSGeoff Rehmet 	}
4540c0b205cSGeoff Rehmet 	bzero((char *)&argument, sizeof(argument));
455*e4253ae8SJohn Baldwin 	if (!svc_getargs(transp, xdr_argument, &argument)) {
4560c0b205cSGeoff Rehmet 		svcerr_decode(transp);
4570c0b205cSGeoff Rehmet 		goto leave;
4580c0b205cSGeoff Rehmet 	}
4590c0b205cSGeoff Rehmet 	result = (*local)(&argument, rqstp);
460f249dbccSDag-Erling Smørgrav 	if (result != NULL &&
461*e4253ae8SJohn Baldwin 	    !svc_sendreply(transp, xdr_result, result)) {
4620c0b205cSGeoff Rehmet 		svcerr_systemerr(transp);
4630c0b205cSGeoff Rehmet 	}
464*e4253ae8SJohn Baldwin 	if (!svc_freeargs(transp, xdr_argument, &argument))
465754c3c57SPhilippe Charnier 		errx(1, "unable to free arguments");
4660c0b205cSGeoff Rehmet leave:
4670c0b205cSGeoff Rehmet         if (from_inetd)
4680c0b205cSGeoff Rehmet                 exit(0);
4690c0b205cSGeoff Rehmet }
470