xref: /titanic_41/usr/src/cmd/mdb/common/modules/md/snarf.c (revision 4eaa471005973e11a6110b69fe990530b3b95a38)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include "mdinclude.h"
30 
31 /* array of the sets */
32 md_set_t	mdset[MD_MAXSETS];
33 mddb_set_t	set_dbs[MD_MAXSETS];
34 /* for the addresses of each set above */
35 uintptr_t	mdset_addrs[MD_MAXSETS];
36 
37 unit_t		md_nunits = 0;
38 set_t		md_nsets = 0;
39 int		snarfed = 0;
40 int		active_sets = 0;
41 
42 /*
43  * routines to snarf the metaset information
44  *
45  * usage: ::dumpsetaddr [-s setname]
46  */
47 /* ARGSUSED */
48 int
49 dumpsetaddr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
50 {
51 	int	i;
52 	int	setno;
53 	char	*s_opt = (char *)NULL;
54 
55 	if (mdb_getopts(argc, argv, 's', MDB_OPT_STR, &s_opt,
56 	    NULL) != argc) {
57 		/* left over arguments ?? */
58 		return (DCMD_USAGE);
59 	}
60 
61 	if (!snarfed) {
62 		mdb_warn("No sets read in yet - try ::metaset\n");
63 		return (DCMD_ERR);
64 	}
65 	if (argc == 0) {	/* dump all sets */
66 		for (i = 0; i < md_nsets; i++) {
67 			if (mdset_addrs[i] != (uintptr_t)0)
68 				mdb_printf("%d %p\n", i, mdset_addrs[i]);
69 		}
70 	} else {
71 		setno = findset(s_opt);
72 		if (setno == -1) {
73 			mdb_warn("no such set: %s\n", s_opt);
74 			return (DCMD_ERR);
75 		}
76 		if (mdset_addrs[setno] != (uintptr_t)0)
77 			mdb_printf("%d %p\n", setno,
78 			    mdset_addrs[setno]);
79 	}
80 	return (DCMD_OK);
81 }
82 
83 
84 /*
85  * Function: snarf_ui_anchor
86  * Purpose:  to read in the s_ui part of a metaset.
87  * Returns:  <n> - number of configured metadevices
88  *           -1  - not configured
89  */
90 int
91 snarf_ui_anchor(int i)
92 {
93 	int	j;
94 	int	num_found = 0;
95 	void	**ptr = mdset[i].s_ui;
96 	void	*addr;
97 
98 	for (j = 0; j < md_nunits; j++) {
99 		if (mdb_vread(&addr, sizeof (void *), (uintptr_t)ptr) == -1) {
100 			ptr++;
101 			continue;
102 		}
103 		if (addr != NULL) {
104 			num_found++;
105 		}
106 		ptr++;
107 	}
108 	return (num_found);
109 }
110 
111 /*
112  * Function: snarf_sets
113  * Purpose:  Entry point into the module that reads the kernel's version
114  *           of the SVM configuration.
115  *           First of all populates the mdset array and then for each
116  *           component that makes up an "md_set_t" reads it in, via calls
117  *           to other functions.
118  */
119 int
120 snarf_sets(void)
121 {
122 	GElf_Sym	setsym;
123 	GElf_Sym	nmdsym;
124 	GElf_Sym	mdsetsym;
125 	int		i;
126 	size_t		offset = 0;
127 
128 	if (snarfed)
129 		return (DCMD_OK);
130 
131 	/* find the SVM hook - md_set */
132 	if (mdb_lookup_by_name("md_set", &setsym) == -1) {
133 		mdb_warn("SVM is not configured on this machine\n");
134 		return (DCMD_ERR);
135 	}
136 	/* find out how many metadevices are configured per set */
137 	if (mdb_lookup_by_name("md_nunits", &nmdsym) == -1) {
138 		mdb_warn("unable to find md_nunits\n");
139 		return (DCMD_ERR);
140 	}
141 	if (mdb_vread(&md_nunits, sizeof (unit_t), nmdsym.st_value) == -1) {
142 		mdb_warn("failed to read md_nunits at %p\n", nmdsym.st_value);
143 		return (DCMD_ERR);
144 	}
145 
146 	if (mdb_lookup_by_name("md_nsets", &mdsetsym) == -1) {
147 		mdb_warn("unable to find md_nsets\n");
148 		return (DCMD_ERR);
149 	}
150 	if (mdb_vread(&md_nsets, sizeof (set_t), mdsetsym.st_value) == -1) {
151 		mdb_warn("failed to read md_nsets at %p\n", mdsetsym.st_value);
152 		return (DCMD_ERR);
153 	}
154 
155 	if (md_verbose) {
156 		mdb_printf("mdset array addr: 0x%lx size is: 0x%lx\n",
157 		    (uintptr_t)setsym.st_value, sizeof (md_set_t));
158 	}
159 
160 	offset = setsym.st_value;
161 
162 	for (i = 0; i < md_nsets; i++) {
163 		if (mdb_vread(&mdset[i], sizeof (md_set_t), offset) == -1) {
164 			mdb_warn("failed to read md_set_t at 0x%lx\n",
165 			    (uintptr_t)(setsym.st_value + offset));
166 		}
167 		/* Should check the status flags */
168 		if (mdset[i].s_status & MD_SET_NM_LOADED) {
169 			if (md_verbose)
170 				mdb_printf("Set %d (0x%lx) has a name space\n",
171 				    i, (uintptr_t)(setsym.st_value + offset));
172 		} else {
173 			offset += sizeof (md_set_t);
174 			continue;
175 		}
176 
177 		if (mdb_vread(&set_dbs[i], sizeof (mddb_set_t),
178 		    (uintptr_t)mdset[i].s_db) == -1) {
179 			if (mdset[i].s_db != 0) {
180 				mdb_warn("failed to read mddb_set_t at 0x%p\n",
181 				    mdset[i].s_db);
182 				return (DCMD_ERR);
183 			} else {
184 				mdb_warn("%d - no set configured\n", i);
185 				return (DCMD_ERR);
186 			}
187 		}
188 		active_sets++;
189 
190 		mdset_addrs[i] = (uintptr_t)(offset);
191 
192 		(void) snarf_ui_anchor(i);
193 
194 		/* have the set now read in the various bits and pieces */
195 		offset += sizeof (md_set_t);
196 	}
197 	snarfed = 1;
198 
199 	if (md_verbose) {
200 		mdb_printf("Number of active sets: %d\n", active_sets);
201 		mdb_printf("Max number of metadevices: %u\n", md_nunits);
202 		mdb_printf("Max number of sets: %u\n", md_nsets);
203 	}
204 	return (DCMD_OK);
205 }
206