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
dumpsetaddr(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)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
snarf_ui_anchor(int i)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
snarf_sets(void)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