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