xref: /onnv-gate/usr/src/lib/libcmd/common/vmstate.c (revision 12068:08a39a083754)
1*12068SRoger.Faulkner@Oracle.COM /***********************************************************************
2*12068SRoger.Faulkner@Oracle.COM *                                                                      *
3*12068SRoger.Faulkner@Oracle.COM *               This software is part of the ast package               *
4*12068SRoger.Faulkner@Oracle.COM *          Copyright (c) 1992-2010 AT&T Intellectual Property          *
5*12068SRoger.Faulkner@Oracle.COM *                      and is licensed under the                       *
6*12068SRoger.Faulkner@Oracle.COM *                  Common Public License, Version 1.0                  *
7*12068SRoger.Faulkner@Oracle.COM *                    by AT&T Intellectual Property                     *
8*12068SRoger.Faulkner@Oracle.COM *                                                                      *
9*12068SRoger.Faulkner@Oracle.COM *                A copy of the License is available at                 *
10*12068SRoger.Faulkner@Oracle.COM *            http://www.opensource.org/licenses/cpl1.0.txt             *
11*12068SRoger.Faulkner@Oracle.COM *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
12*12068SRoger.Faulkner@Oracle.COM *                                                                      *
13*12068SRoger.Faulkner@Oracle.COM *              Information and Software Systems Research               *
14*12068SRoger.Faulkner@Oracle.COM *                            AT&T Research                             *
15*12068SRoger.Faulkner@Oracle.COM *                           Florham Park NJ                            *
16*12068SRoger.Faulkner@Oracle.COM *                                                                      *
17*12068SRoger.Faulkner@Oracle.COM *                 Glenn Fowler <gsf@research.att.com>                  *
18*12068SRoger.Faulkner@Oracle.COM *                  David Korn <dgk@research.att.com>                   *
19*12068SRoger.Faulkner@Oracle.COM *                                                                      *
20*12068SRoger.Faulkner@Oracle.COM ***********************************************************************/
21*12068SRoger.Faulkner@Oracle.COM #pragma prototyped
22*12068SRoger.Faulkner@Oracle.COM 
23*12068SRoger.Faulkner@Oracle.COM #define FORMAT		"region=%(region)p size=%(size)d segments=%(segments)d busy=(%(busy_size)d,%(busy_blocks)d,%(busy_max)d) free=(%(free_size)d,%(free_blocks)d,%(free_max)d)"
24*12068SRoger.Faulkner@Oracle.COM 
25*12068SRoger.Faulkner@Oracle.COM static const char usage[] =
26*12068SRoger.Faulkner@Oracle.COM "[-?\n@(#)$Id: vmstate (AT&T Research) 2010-03-05 $\n]"
27*12068SRoger.Faulkner@Oracle.COM USAGE_LICENSE
28*12068SRoger.Faulkner@Oracle.COM "[+NAME?vmstate - list the calling process vmalloc region state]"
29*12068SRoger.Faulkner@Oracle.COM "[+DESCRIPTION?When invoked as a shell builtin, \bvmstate\b lists the "
30*12068SRoger.Faulkner@Oracle.COM     "calling process \bvmalloc\b(3) state for all regions.]"
31*12068SRoger.Faulkner@Oracle.COM "[f:format?List the ids specified by \aformat\a. \aformat\a follows "
32*12068SRoger.Faulkner@Oracle.COM     "\bprintf\b(3) conventions, except that \bsfio\b(3) inline ids are used "
33*12068SRoger.Faulkner@Oracle.COM     "instead of arguments: "
34*12068SRoger.Faulkner@Oracle.COM     "%[-+]][\awidth\a[.\aprecis\a[.\abase\a]]]]]](\aid\a)\achar\a. The "
35*12068SRoger.Faulkner@Oracle.COM     "supported \aid\as are:]:[format:=" FORMAT "]"
36*12068SRoger.Faulkner@Oracle.COM     "{"
37*12068SRoger.Faulkner@Oracle.COM         "[+size?The total region size.]"
38*12068SRoger.Faulkner@Oracle.COM         "[+segments?The number of segments in the region.]"
39*12068SRoger.Faulkner@Oracle.COM         "[+busy_size?The total busy block size.]"
40*12068SRoger.Faulkner@Oracle.COM         "[+busy_blocks?The number of busy blocks.]"
41*12068SRoger.Faulkner@Oracle.COM         "[+busy_max?The maximum busy block size.]"
42*12068SRoger.Faulkner@Oracle.COM         "[+free_size?The total free block size.]"
43*12068SRoger.Faulkner@Oracle.COM         "[+free_blocks?The number of free blocks.]"
44*12068SRoger.Faulkner@Oracle.COM         "[+free_max?The maximum free block size.]"
45*12068SRoger.Faulkner@Oracle.COM     "}"
46*12068SRoger.Faulkner@Oracle.COM "[+SEE ALSO?\bvmalloc\b(3)]"
47*12068SRoger.Faulkner@Oracle.COM ;
48*12068SRoger.Faulkner@Oracle.COM 
49*12068SRoger.Faulkner@Oracle.COM #include <cmd.h>
50*12068SRoger.Faulkner@Oracle.COM #include <vmalloc.h>
51*12068SRoger.Faulkner@Oracle.COM 
52*12068SRoger.Faulkner@Oracle.COM typedef struct State_s
53*12068SRoger.Faulkner@Oracle.COM {
54*12068SRoger.Faulkner@Oracle.COM 	char*		format;
55*12068SRoger.Faulkner@Oracle.COM 	Vmalloc_t*	vm;
56*12068SRoger.Faulkner@Oracle.COM 	Vmstat_t	vs;
57*12068SRoger.Faulkner@Oracle.COM 	unsigned int	regions;
58*12068SRoger.Faulkner@Oracle.COM 	Vmalloc_t*	region[256];
59*12068SRoger.Faulkner@Oracle.COM } State_t;
60*12068SRoger.Faulkner@Oracle.COM 
61*12068SRoger.Faulkner@Oracle.COM /*
62*12068SRoger.Faulkner@Oracle.COM  * sfkeyprintf() lookup
63*12068SRoger.Faulkner@Oracle.COM  * handle==0 for heading
64*12068SRoger.Faulkner@Oracle.COM  */
65*12068SRoger.Faulkner@Oracle.COM 
66*12068SRoger.Faulkner@Oracle.COM static int
key(void * handle,Sffmt_t * fp,const char * arg,char ** ps,Sflong_t * pn)67*12068SRoger.Faulkner@Oracle.COM key(void* handle, Sffmt_t* fp, const char* arg, char** ps, Sflong_t* pn)
68*12068SRoger.Faulkner@Oracle.COM {
69*12068SRoger.Faulkner@Oracle.COM 	register State_t*	state = (State_t*)handle;
70*12068SRoger.Faulkner@Oracle.COM 	register char*		s;
71*12068SRoger.Faulkner@Oracle.COM 
72*12068SRoger.Faulkner@Oracle.COM 	if (!(s = fp->t_str) || streq(s, "size"))
73*12068SRoger.Faulkner@Oracle.COM 		*pn = state->vs.extent;
74*12068SRoger.Faulkner@Oracle.COM 	else if (streq(s, "region"))
75*12068SRoger.Faulkner@Oracle.COM 		*pn = integralof(state->vm);
76*12068SRoger.Faulkner@Oracle.COM 	else if (streq(s, "segments"))
77*12068SRoger.Faulkner@Oracle.COM 		*pn = state->vs.n_seg;
78*12068SRoger.Faulkner@Oracle.COM 	else if (streq(s, "busy_size"))
79*12068SRoger.Faulkner@Oracle.COM 		*pn = state->vs.s_busy;
80*12068SRoger.Faulkner@Oracle.COM 	else if (streq(s, "busy_blocks"))
81*12068SRoger.Faulkner@Oracle.COM 		*pn = state->vs.n_busy;
82*12068SRoger.Faulkner@Oracle.COM 	else if (streq(s, "busy_max"))
83*12068SRoger.Faulkner@Oracle.COM 		*pn = state->vs.m_busy;
84*12068SRoger.Faulkner@Oracle.COM 	else if (streq(s, "free_size"))
85*12068SRoger.Faulkner@Oracle.COM 		*pn = state->vs.s_free;
86*12068SRoger.Faulkner@Oracle.COM 	else if (streq(s, "free_blocks"))
87*12068SRoger.Faulkner@Oracle.COM 		*pn = state->vs.n_free;
88*12068SRoger.Faulkner@Oracle.COM 	else if (streq(s, "free_max"))
89*12068SRoger.Faulkner@Oracle.COM 		*pn = state->vs.m_free;
90*12068SRoger.Faulkner@Oracle.COM 	else if (streq(s, "format"))
91*12068SRoger.Faulkner@Oracle.COM 		*ps = (char*)state->format;
92*12068SRoger.Faulkner@Oracle.COM 	else
93*12068SRoger.Faulkner@Oracle.COM 	{
94*12068SRoger.Faulkner@Oracle.COM 		error(2, "%s: unknown format identifier", s);
95*12068SRoger.Faulkner@Oracle.COM 		return 0;
96*12068SRoger.Faulkner@Oracle.COM 	}
97*12068SRoger.Faulkner@Oracle.COM 	return 1;
98*12068SRoger.Faulkner@Oracle.COM }
99*12068SRoger.Faulkner@Oracle.COM 
100*12068SRoger.Faulkner@Oracle.COM static int
visit(Vmalloc_t * vm,void * addr,size_t size,Vmdisc_t * disc,void * handle)101*12068SRoger.Faulkner@Oracle.COM visit(Vmalloc_t* vm, void* addr, size_t size, Vmdisc_t* disc, void* handle)
102*12068SRoger.Faulkner@Oracle.COM {
103*12068SRoger.Faulkner@Oracle.COM 	State_t*	state = (State_t*)handle;
104*12068SRoger.Faulkner@Oracle.COM 	Vmstat_t	vs;
105*12068SRoger.Faulkner@Oracle.COM 
106*12068SRoger.Faulkner@Oracle.COM 	if (vm != state->vm)
107*12068SRoger.Faulkner@Oracle.COM 	{
108*12068SRoger.Faulkner@Oracle.COM 		state->vm = vm;
109*12068SRoger.Faulkner@Oracle.COM 		if (state->regions < elementsof(state->region))
110*12068SRoger.Faulkner@Oracle.COM 			state->region[state->regions++] = vm;
111*12068SRoger.Faulkner@Oracle.COM 	}
112*12068SRoger.Faulkner@Oracle.COM 	return 0;
113*12068SRoger.Faulkner@Oracle.COM }
114*12068SRoger.Faulkner@Oracle.COM 
115*12068SRoger.Faulkner@Oracle.COM int
b_vmstate(int argc,char ** argv,void * context)116*12068SRoger.Faulkner@Oracle.COM b_vmstate(int argc, char** argv, void* context)
117*12068SRoger.Faulkner@Oracle.COM {
118*12068SRoger.Faulkner@Oracle.COM 	register int	i;
119*12068SRoger.Faulkner@Oracle.COM 	State_t		state;
120*12068SRoger.Faulkner@Oracle.COM 
121*12068SRoger.Faulkner@Oracle.COM 	memset(&state, 0, sizeof(state));
122*12068SRoger.Faulkner@Oracle.COM 	cmdinit(argc, argv, context, ERROR_CATALOG, 0);
123*12068SRoger.Faulkner@Oracle.COM 	for (;;)
124*12068SRoger.Faulkner@Oracle.COM 	{
125*12068SRoger.Faulkner@Oracle.COM 		switch (optget(argv, usage))
126*12068SRoger.Faulkner@Oracle.COM 		{
127*12068SRoger.Faulkner@Oracle.COM 		case 'f':
128*12068SRoger.Faulkner@Oracle.COM 			state.format = opt_info.arg;
129*12068SRoger.Faulkner@Oracle.COM 			continue;
130*12068SRoger.Faulkner@Oracle.COM 		case '?':
131*12068SRoger.Faulkner@Oracle.COM 			error(ERROR_USAGE|4, "%s", opt_info.arg);
132*12068SRoger.Faulkner@Oracle.COM 			continue;
133*12068SRoger.Faulkner@Oracle.COM 		case ':':
134*12068SRoger.Faulkner@Oracle.COM 			error(2, "%s", opt_info.arg);
135*12068SRoger.Faulkner@Oracle.COM 			continue;
136*12068SRoger.Faulkner@Oracle.COM 		}
137*12068SRoger.Faulkner@Oracle.COM 		break;
138*12068SRoger.Faulkner@Oracle.COM 	}
139*12068SRoger.Faulkner@Oracle.COM 	argv += opt_info.index;
140*12068SRoger.Faulkner@Oracle.COM 	if (error_info.errors || *argv)
141*12068SRoger.Faulkner@Oracle.COM 		error(ERROR_USAGE|4, "%s", optusage(NiL));
142*12068SRoger.Faulkner@Oracle.COM 	if (!state.format)
143*12068SRoger.Faulkner@Oracle.COM 		state.format = FORMAT;
144*12068SRoger.Faulkner@Oracle.COM 
145*12068SRoger.Faulkner@Oracle.COM 	/*
146*12068SRoger.Faulkner@Oracle.COM 	 * the walk must do no allocations because it locks the regions
147*12068SRoger.Faulkner@Oracle.COM 	 */
148*12068SRoger.Faulkner@Oracle.COM 
149*12068SRoger.Faulkner@Oracle.COM 	vmwalk(NiL, visit, &state);
150*12068SRoger.Faulkner@Oracle.COM 
151*12068SRoger.Faulkner@Oracle.COM 	/*
152*12068SRoger.Faulkner@Oracle.COM 	 * now we can compute and list the state of each region
153*12068SRoger.Faulkner@Oracle.COM 	 */
154*12068SRoger.Faulkner@Oracle.COM 
155*12068SRoger.Faulkner@Oracle.COM 	for (i = 0; i < state.regions; i++)
156*12068SRoger.Faulkner@Oracle.COM 	{
157*12068SRoger.Faulkner@Oracle.COM 		state.vm = state.region[i];
158*12068SRoger.Faulkner@Oracle.COM 		vmstat(state.vm, &state.vs);
159*12068SRoger.Faulkner@Oracle.COM 		sfkeyprintf(sfstdout, &state, state.format, key, NiL);
160*12068SRoger.Faulkner@Oracle.COM 		sfprintf(sfstdout, "\n");
161*12068SRoger.Faulkner@Oracle.COM 	}
162*12068SRoger.Faulkner@Oracle.COM 	return 0;
163*12068SRoger.Faulkner@Oracle.COM }
164