1 /* $NetBSD: rstat_proc.c,v 1.43 2006/04/14 13:19:03 blymn Exp $ */
4 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
5 * unrestricted use provided that this legend is included on all tape
6 * media and as a part of the software program in whole or part. Users
7 * may copy or modify Sun RPC without charge, but are not authorized
8 * to license or distribute it to anyone else except as part of a product or
9 * program developed by the user.
11 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
12 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
13 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
15 * Sun RPC is provided with no support and without any obligation on the
16 * part of Sun Microsystems, Inc. to assist in its use, correction,
17 * modification or enhancement.
19 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
20 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
21 * OR ANY PART THEREOF.
23 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
24 * or profits or other special, indirect and consequential damages, even if
25 * Sun has been advised of the possibility of such damages.
27 * Sun Microsystems, Inc.
29 * Mountain View, California 94043
32 #include <sys/cdefs.h>
35 static char sccsid
[] = "from: @(#)rpc.rstatd.c 1.1 86/09/25 Copyr 1984 Sun Micro";
36 static char sccsid
[] = "from: @(#)rstat_proc.c 2.2 88/08/01 4.0 RPCSRC";
38 __RCSID("$NetBSD: rstat_proc.c,v 1.43 2006/04/14 13:19:03 blymn Exp $");
43 * rstat service: built with rstat.x and derived from rpc.rstatd.c
45 * Copyright (c) 1984 by Sun Microsystems, Inc.
48 #include <sys/param.h>
49 #include <sys/sched.h>
50 #include <sys/socket.h>
63 #include <sys/sysctl.h>
64 #include <uvm/uvm_extern.h>
75 * this is a huge hack to stop `struct pmap' being
78 #define _RPC_PMAP_PROT_H_
81 #undef FSHIFT /* Use protocol's shift and scale values */
90 #include <rpcsvc/rstat.h>
93 #define BSD_CPUSTATES 5 /* Use protocol's idea of CPU states */
94 int cp_xlat
[CPUSTATES
] = { CP_USER
, CP_NICE
, CP_SYS
, CP_IDLE
};
99 { "_ifnet", 0, 0, 0, 0 },
100 { NULL
, 0, 0, 0, 0 },
104 char *memf
= NULL
, *nlistf
= NULL
;
106 struct ifnet_head ifnetq
; /* chain of ethernet interfaces */
107 unsigned int numintfs
;
109 extern int from_inetd
;
110 int sincelastreq
= 0; /* number of alarms since last request */
111 extern int closedown
;
116 struct statsswtch s2
;
120 void updatestat(int);
122 void setup_kd_once(void);
123 void stat_init(void);
125 void rstat_service(struct svc_req
*, SVCXPRT
*);
127 static int stat_is_init
= 0;
130 #define FSCALE (1 << 8)
139 (void) signal(SIGALRM
, updatestat
);
144 rstatproc_stats_3_svc(void *arg
, struct svc_req
*rqstp
)
149 return (&stats_all
.s3
);
153 rstatproc_stats_2_svc(void *arg
, struct svc_req
*rqstp
)
158 stats_all
.s2
.if_opackets
= stats_all
.s3
.if_opackets
;
159 return (&stats_all
.s2
);
163 rstatproc_stats_1_svc(void *arg
, struct svc_req
*rqstp
)
168 stats_all
.s1
.if_opackets
= stats_all
.s3
.if_opackets
;
169 return (&stats_all
.s1
);
173 rstatproc_havedisk_3_svc(void *arg
, struct svc_req
*rqstp
)
185 rstatproc_havedisk_2_svc(void *arg
, struct svc_req
*rqstp
)
187 return (rstatproc_havedisk_3_svc(arg
, rqstp
));
191 rstatproc_havedisk_1_svc(void *arg
, struct svc_req
*rqstp
)
193 return (rstatproc_havedisk_3_svc(arg
, rqstp
));
197 updatestat(int dummy
)
203 struct uvmexp_sysctl uvmexp
;
206 struct timeval tm
, btm
;
209 syslog(LOG_DEBUG
, "entering updatestat");
211 if (sincelastreq
>= closedown
) {
213 syslog(LOG_DEBUG
, "about to closedown");
225 * drvreadstats reads in the "disk_count" as well as the "disklist"
226 * statistics. It also retrieves "hz" and the "cp_time" array.
229 memset(stats_all
.s3
.dk_xfer
, 0, sizeof(stats_all
.s3
.dk_xfer
));
230 for (i
= 0; i
< ndrive
&& i
< DK_NDRIVE
; i
++)
231 stats_all
.s3
.dk_xfer
[i
] = cur
.rxfer
[i
] + cur
.wxfer
[i
];
234 for (i
= 0; i
< CPUSTATES
; i
++)
235 stats_all
.s3
.cp_time
[i
] = cur
.cp_time
[cp_xlat
[i
]];
237 if (kvm_read(kfd
, (long)nl
[X_CPTIME
].n_value
,
238 (char *)stats_all
.s3
.cp_time
,
239 sizeof (stats_all
.s3
.cp_time
))
240 != sizeof (stats_all
.s3
.cp_time
)) {
241 syslog(LOG_ERR
, "can't read cp_time from kmem");
246 (void)getloadavg(avrun
, sizeof(avrun
) / sizeof(avrun
[0]));
248 stats_all
.s3
.avenrun
[0] = avrun
[0] * FSCALE
;
249 stats_all
.s3
.avenrun
[1] = avrun
[1] * FSCALE
;
250 stats_all
.s3
.avenrun
[2] = avrun
[2] * FSCALE
;
252 mib
[1] = KERN_BOOTTIME
;
254 if (sysctl(mib
, 2, &btm
, &len
, NULL
, 0) < 0) {
255 syslog(LOG_ERR
, "can't sysctl kern.boottime");
258 stats_all
.s3
.boottime
.tv_sec
= btm
.tv_sec
;
259 stats_all
.s3
.boottime
.tv_usec
= btm
.tv_usec
;
263 syslog(LOG_DEBUG
, "%d %d %d %d %d\n", stats_all
.s3
.cp_time
[0],
264 stats_all
.s3
.cp_time
[1], stats_all
.s3
.cp_time
[2],
265 stats_all
.s3
.cp_time
[3], stats_all
.s3
.cp_time
[4]);
270 len
= sizeof(uvmexp
);
271 if (sysctl(mib
, 2, &uvmexp
, &len
, NULL
, 0) < 0) {
272 syslog(LOG_ERR
, "can't sysctl vm.uvmexp2");
275 stats_all
.s3
.v_pgpgin
= uvmexp
.fltanget
;
276 stats_all
.s3
.v_pgpgout
= uvmexp
.pdpageouts
;
277 stats_all
.s3
.v_pswpin
= uvmexp
.swapins
;
278 stats_all
.s3
.v_pswpout
= uvmexp
.swapouts
;
279 stats_all
.s3
.v_intr
= uvmexp
.intrs
;
280 stats_all
.s3
.v_swtch
= uvmexp
.swtch
;
281 gettimeofday(&tm
, (struct timezone
*) 0);
282 stats_all
.s3
.v_intr
-= hz
*(tm
.tv_sec
- btm
.tv_sec
) +
283 hz
*(tm
.tv_usec
- btm
.tv_usec
)/1000000;
285 stats_all
.s3
.if_ipackets
= 0;
286 stats_all
.s3
.if_opackets
= 0;
287 stats_all
.s3
.if_ierrors
= 0;
288 stats_all
.s3
.if_oerrors
= 0;
289 stats_all
.s3
.if_collisions
= 0;
290 for (off
= (long)ifnetq
.tqh_first
, i
= 0; off
&& i
< numintfs
; i
++) {
291 if (kvm_read(kfd
, off
, (char *)&ifnet
, sizeof ifnet
) !=
293 syslog(LOG_ERR
, "can't read ifnet from kmem");
296 stats_all
.s3
.if_ipackets
+= ifnet
.if_data
.ifi_ipackets
;
297 stats_all
.s3
.if_opackets
+= ifnet
.if_data
.ifi_opackets
;
298 stats_all
.s3
.if_ierrors
+= ifnet
.if_data
.ifi_ierrors
;
299 stats_all
.s3
.if_oerrors
+= ifnet
.if_data
.ifi_oerrors
;
300 stats_all
.s3
.if_collisions
+= ifnet
.if_data
.ifi_collisions
;
301 off
= (long)ifnet
.if_list
.tqe_next
;
303 stats_all
.s3
.curtime
.tv_sec
= tm
.tv_sec
;
304 stats_all
.s3
.curtime
.tv_usec
= tm
.tv_usec
;
311 char errbuf
[_POSIX2_LINE_MAX
];
312 kfd
= kvm_openfiles(NULL
, NULL
, NULL
, O_RDONLY
, errbuf
);
314 syslog(LOG_ERR
, "%s", errbuf
);
324 static int is_kfd_setup
= 0;
326 /* setup() is called after each dormant->active
327 * transition. Since we never close the kvm files
328 * (there's no reason), make sure we don't open them
329 * each time, as that can lead to exhaustion of all open
336 if (kvm_nlist(kfd
, nl
) != 0) {
337 syslog(LOG_ERR
, "can't get namelist");
341 if (kvm_read(kfd
, (long)nl
[X_IFNET
].n_value
, &ifnetq
,
342 sizeof ifnetq
) != sizeof ifnetq
) {
343 syslog(LOG_ERR
, "can't read ifnet queue head from kmem");
348 for (off
= (long)ifnetq
.tqh_first
; off
;) {
349 if (kvm_read(kfd
, off
, (char *)&ifnet
, sizeof ifnet
) !=
351 syslog(LOG_ERR
, "can't read ifnet from kmem");
355 off
= (long)ifnet
.if_list
.tqe_next
;
361 * returns true if have a disk
370 rstat_service(struct svc_req
*rqstp
, SVCXPRT
*transp
)
376 xdrproc_t xdr_argument
, xdr_result
;
377 char *(*local
)(void *, struct svc_req
*);
379 switch (rqstp
->rq_proc
) {
381 (void)svc_sendreply(transp
, xdr_void
, (char *)NULL
);
384 case RSTATPROC_STATS
:
385 xdr_argument
= (xdrproc_t
)xdr_void
;
386 xdr_result
= (xdrproc_t
)xdr_statstime
;
387 switch (rqstp
->rq_vers
) {
389 local
= (char *(*)(void *, struct svc_req
*))
390 rstatproc_stats_1_svc
;
392 case RSTATVERS_SWTCH
:
393 local
= (char *(*)(void *, struct svc_req
*))
394 rstatproc_stats_2_svc
;
397 local
= (char *(*)(void *, struct svc_req
*))
398 rstatproc_stats_3_svc
;
401 svcerr_progvers(transp
, RSTATVERS_ORIG
, RSTATVERS_TIME
);
406 case RSTATPROC_HAVEDISK
:
407 xdr_argument
= (xdrproc_t
)xdr_void
;
408 xdr_result
= (xdrproc_t
)xdr_u_int
;
409 switch (rqstp
->rq_vers
) {
411 local
= (char *(*)(void *, struct svc_req
*))
412 rstatproc_havedisk_1_svc
;
414 case RSTATVERS_SWTCH
:
415 local
= (char *(*)(void *, struct svc_req
*))
416 rstatproc_havedisk_2_svc
;
419 local
= (char *(*)(void *, struct svc_req
*))
420 rstatproc_havedisk_3_svc
;
423 svcerr_progvers(transp
, RSTATVERS_ORIG
, RSTATVERS_TIME
);
429 svcerr_noproc(transp
);
432 memset((char *)&argument
, 0, sizeof(argument
));
433 if (!svc_getargs(transp
, xdr_argument
, (caddr_t
)&argument
)) {
434 svcerr_decode(transp
);
437 result
= (*local
)(&argument
, rqstp
);
438 if (result
!= NULL
&& !svc_sendreply(transp
, xdr_result
, result
)) {
439 svcerr_systemerr(transp
);
441 if (!svc_freeargs(transp
, xdr_argument
, (caddr_t
)&argument
)) {
442 (void)fprintf(stderr
, "unable to free arguments\n");