Print this page
2976 remove useless offsetof() macros
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/lvm/libmeta/common/meta_statconcise.c
+++ new/usr/src/lib/lvm/libmeta/common/meta_statconcise.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
↓ open down ↓ |
15 lines elided |
↑ open up ↑ |
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25
26 -#pragma ident "%Z%%M% %I% %E% SMI"
27 -
28 26 #include <meta.h>
29 27 #include <assert.h>
30 28 #include <ctype.h>
31 29 #include <mdiox.h>
32 30 #include <meta.h>
33 31 #include <stdio.h>
34 32 #include <stdlib.h>
33 +#include <stddef.h>
35 34 #include <strings.h>
36 35 #include <sys/lvm/md_mddb.h>
37 36 #include <sys/lvm/md_names.h>
38 37 #include <sys/lvm/md_crc.h>
39 38 #include <sys/lvm/md_convert.h>
40 39
41 40
42 41 /*
43 42 * Design Notes:
44 43 *
45 44 * All of the code in this file supports the addition of metastat -c output
46 45 * for the verbose option of metaimport. Some of this code is also used by
47 46 * the command metastat for concise output(cmd/lvm/util/metastat.c).
48 47 * The code is designed to produce the same output as metastat -c does for a
49 48 * given diskset--with a couple exceptions.
50 49 * The primary differences between the output for the metastat -c command and
51 50 * metastat output for metaimport -v are:
52 51 * - the set name is not printed next to each metadevice
53 52 * - top-level state information is not printed for some metadevices
54 53 * - the percent that a disk has completed resyncing is not listed
55 54 * in metaimport -v.
56 55 *
57 56 *
58 57 * The general layout of this file is as follows:
59 58 *
60 59 * - report_metastat_info()
61 60 * This is the primary entry point for the functions in this file, with
62 61 * the exception of several functions that are also called from
63 62 * cmd/io/lvm/util/metastat.c
64 63 * report_metastat_info() calls functions to read in all the the
65 64 * Directory blocks and Record blocks and then process the information
66 65 * needed to print out the metadevice records in the same format as
67 66 * metastat -c.
68 67 *
69 68 * - read_all_mdrecords()
70 69 * Reads in all the Directory blocks in the diskset and verifies their
71 70 * validity. For each Directly block, it loops through all Directory
72 71 * Entries and for each one that contains a metadevice record calls
73 72 * read_md_record(). Because the output is designed to imitate the
74 73 * output of metastat -c, we ignore metadevice records for
75 74 * optimized resync, changelog, and translog.
76 75 *
77 76 * - read_md_record()
78 77 * Reads in a Directory Entry and its associated Record block. The
79 78 * revision information for the Record block is checked and it is
80 79 * determined whether or not it is a 64bit Record block or a 32bit record
81 80 * block. For each valid Record block, it allocates an md_im_rec_t
82 81 * structure and calls extract_mduser_data().
83 82 *
84 83 * - extract_mduser_data()
85 84 * Populates the md_im_rec_t data structure with information about the
86 85 * record's associated metadevice. Also, the name of the metadevice is
87 86 * either copied from the NM namespace(if it exists there) or is generated
88 87 * from the record's un_self_id.
89 88 *
90 89 * - process_toplevel_devices()
91 90 * For a given metadevice type, searchs through the md_im_rec_t **mdimpp,
92 91 * list of all metadevices in the set, to find all records of the
93 92 * specified type that do not have a parent and puts them on a temp list.
94 93 * The temp list is then iterated through and the associated processing
95 94 * function is called.
96 95 *
97 96 * - process_(trans, hotspare, hotspare_pool, soft_part, mirror, stripe, raid)
98 97 * These functions are called by using the dfunc field in the mdimpp list.
99 98 * Each process function only understands its own type of metadevice. Once
100 99 * it processes the metadevice it was called for, it then loops through
101 100 * all of the underlying metadevices. After printing the name of the
102 101 * underlying metadevice, it puts in on a list to be processed. If the
103 102 * underlying device is a physical device, then print_physical_device is
104 103 * called.
105 104 * Once all information about the original metadevice is processed, it
106 105 * loops through the list of underlying metadevices and calls the
107 106 * appropriate function to process them.
108 107 *
109 108 * - process_toplevel_softparts()
110 109 * To match the output for metastat -c, all top-level softpartions
111 110 * are printed out in groups based on their underlying metadevice--so that
112 111 * the underlying metadevice only needs to be processed once.
113 112 *
114 113 * - meta_get_(sm_state, raid_col_state, stripe_state, hs_state)
115 114 * These functions are used to retrieve the metadevice state information.
116 115 * They are also used by the metastat concise routines in
117 116 * cmd/lvm/util/metastat.c.
118 117 *
119 118 */
120 119
121 120
122 121 /*
123 122 * md_im_rec is a doubly linked list used to store the rb_data for each
124 123 * directory entry that corresponds to a metadevice.
125 124 * n_key: is set, if there is an associated entry in the NM namespace.
126 125 * dfunc: is set to point to the function that processes the particular
127 126 * metadevice associated with the record.
128 127 * hs_record_id: is only set, if the metadevice is a hotspare.
129 128 * un_self_id: is set for all other records. This is also used to generate
130 129 * the name of the metadevice if there is no entry for the metadevice in
131 130 * the NM namespace--n_key is not set.
132 131 */
133 132 typedef struct md_im_rec {
134 133 mdkey_t n_key; /* NM namespace key */
135 134 struct md_im_rec *next;
136 135 struct md_im_rec *prev;
137 136 uint_t md_type;
138 137 uint_t has_parent; /* either 0(no parent) or 1 */
139 138 minor_t un_self_id;
140 139 mddb_recid_t hs_record_id; /* hotspare recid */
141 140 char *n_name; /* name of metadevice */
142 141 void (*dfunc) ();
143 142 ushort_t record_len;
144 143 /* pointer to the unit structure for the metadevice, e.g. rb_data[0] */
145 144 void *record;
146 145 } md_im_rec_t;
147 146
148 147 /*
149 148 * md_im_list is used to group toplevel metadevices by type and to group
150 149 * the underlying devices for a particular metadevice.
151 150 */
152 151 typedef struct md_im_list {
153 152 struct md_im_list *next;
↓ open down ↓ |
109 lines elided |
↑ open up ↑ |
154 153 struct md_im_rec *mdrec;
155 154 } md_im_list_t;
156 155
157 156
158 157 /*
159 158 * MAXSIZEMDRECNAME is the value that has historically been used to allocate
160 159 * space for the metadevice name
161 160 */
162 161 #define MAXSIZEMDRECNAME 20
163 162 #define NAMEWIDTH 16
164 -#define offsetof(s, m) ((size_t)(&(((s *)0)->m)))
165 163 #define NOT_PHYSICAL_DEV 0
166 164 #define PHYSICAL_DEV 1
167 165
168 166
169 167 /*
170 168 * strip_blacks()
171 169 *
172 170 * Strip blanks from string. Used for size field in concise output.
173 171 */
174 172 static char *
175 173 strip_blanks(char *s)
176 174 {
177 175 char *p;
178 176
179 177 for (p = s; *p; ) {
180 178 if (*p == ' ') {
181 179 char *t;
182 180 for (t = p; *t; t++) {
183 181 *t = *(t + 1);
184 182 }
185 183 } else {
186 184 p++;
187 185 }
188 186 }
189 187
190 188 return (s);
191 189 }
192 190
193 191
194 192 /*
195 193 * print_concise_entry()
196 194 *
197 195 * Print properly indented metadevice name, type and size for concise output.
198 196 * This function is also called from: cmd/lvm/util/metastat.c.
199 197 */
200 198 void
201 199 print_concise_entry(int indent, char *name, diskaddr_t size, char mtype)
202 200 {
203 201 int i;
204 202 int width = NAMEWIDTH; /* minumum field width for name */
205 203 char in[MAXPATHLEN];
206 204 char *sz;
207 205
208 206 in[0] = 0;
209 207 for (i = 0; i < indent; i++)
210 208 (void) strlcat(in, " ", sizeof (in));
211 209
212 210 /* set up minimum field width. negative for left justified */
213 211 width -= indent;
214 212 if (width < 0)
215 213 width = 0; /* overflowed; no minimum field needed */
216 214 else
217 215 width = 0 - width; /* negative for left justification */
218 216
219 217 if (size == 0) {
220 218 sz = "-";
221 219 } else {
222 220 sz = strip_blanks(meta_number_to_string(size, DEV_BSIZE));
223 221 }
224 222
225 223 (void) printf("%s%*s %c %6s", in, width, name, mtype, sz);
226 224 }
227 225
228 226
229 227 /*
230 228 * free_mdrec_list_entry()
231 229 *
232 230 * Removing entry from the list of metadevices in the diskset(mdimpp).
233 231 * This function will not remove the dummy entry at the head of the
234 232 * list, so we don't have to set mdrec equal to NULL.
235 233 */
236 234 static void
237 235 free_mdrec_list_entry(md_im_rec_t **mdrec)
238 236 {
239 237 (*mdrec)->prev->next = (*mdrec)->next;
240 238 if ((*mdrec)->next != NULL) {
241 239 (*mdrec)->next->prev = (*mdrec)->prev;
242 240 }
243 241 Free((*mdrec)->record);
244 242 Free((*mdrec)->n_name);
245 243 Free(*mdrec);
246 244 }
247 245
248 246
249 247 /*
250 248 * ucomponent_append()
251 249 *
252 250 * Appending entry to the underlying component list. The list
253 251 * is used to group all of the underlying devices before
254 252 * processing them.
255 253 */
256 254 static void
257 255 ucomponent_append(
258 256 md_im_list_t **ucomp_head,
259 257 md_im_list_t **ucomp_tail,
260 258 md_im_list_t *ucomp
261 259 )
262 260 {
263 261 ucomp->next = NULL;
264 262 if (*ucomp_head == NULL) {
265 263 *ucomp_head = ucomp;
266 264 *ucomp_tail = ucomp;
267 265 } else {
268 266 (*ucomp_tail)->next = ucomp;
269 267 *ucomp_tail = (*ucomp_tail)->next;
270 268 }
271 269 }
272 270
273 271
274 272 /*
275 273 * free_md_im_list_entries()
276 274 *
277 275 * Freeing entries on an md_im_list_t. This list is used to group
278 276 * underlying components for processing and to group top-level metadevices
279 277 * by type.
280 278 */
281 279 static void
282 280 free_md_im_list_entries(md_im_list_t **list_head)
283 281 {
284 282 md_im_list_t *tmp_list_entry = *list_head;
285 283 md_im_list_t *rm_list_entry;
286 284
287 285 while (tmp_list_entry != NULL) {
288 286 rm_list_entry = tmp_list_entry;
289 287 tmp_list_entry = tmp_list_entry->next;
290 288 Free(rm_list_entry);
291 289 }
292 290 }
293 291
294 292
295 293 /*
296 294 * print_physical_device()
297 295 *
298 296 * If a metadevice has an underlying component that is a physical
299 297 * device, then this searches the pnm_rec_t list to match an entry's
300 298 * n_key to the key for the underlying component. The ctd name of the
301 299 * physical device is printed on the same line as the metadevice.
302 300 */
303 301 static void
304 302 print_physical_device(
305 303 pnm_rec_t *phys_nm,
306 304 mdkey_t key
307 305 )
308 306 {
309 307 pnm_rec_t *tmpphys_nm;
310 308
311 309 for (tmpphys_nm = phys_nm; tmpphys_nm != NULL;
312 310 tmpphys_nm = tmpphys_nm->next) {
313 311 if (tmpphys_nm->n_key == key) {
314 312 (void) printf(" %s", tmpphys_nm->n_name);
315 313 break;
316 314 }
317 315 }
318 316 }
319 317
320 318
321 319 /*
322 320 * get_stripe_req_size()
323 321 *
324 322 * Given a 64bit stripe unit, compute the size of the stripe unit.
325 323 * This function is a derivation of:
326 324 * common/lvm/md_convert.c:get_big_stripe_req_size()
327 325 * and any changes made to either this function or get_big_stripe_req_size()
328 326 * should be reviewed to make sure the functionality in both places is correct.
329 327 *
330 328 * Returns:
331 329 * total size of the 64bit stripe
332 330 */
333 331 size_t
334 332 get_stripe_req_size(ms_unit_t *un)
335 333 {
336 334 struct ms_row *mdr;
337 335 uint_t row;
338 336 uint_t ncomps = 0;
339 337 size_t mdsize = 0;
340 338 size_t first_comp = 0;
341 339
342 340
343 341 /* Compute the offset of the first component */
344 342 first_comp = sizeof (ms_unit_t) +
345 343 sizeof (struct ms_row) * (un->un_nrows - 1);
346 344 first_comp = roundup(first_comp, sizeof (long long));
347 345
348 346 /*
349 347 * Requestor wants to have the total size, add the sizes of
350 348 * all components
351 349 */
352 350 mdr = &un->un_row[0];
353 351 for (row = 0; (row < un->un_nrows); row++)
354 352 ncomps += mdr[row].un_ncomp;
355 353 mdsize = first_comp + sizeof (ms_comp_t) * ncomps;
356 354 return (mdsize);
357 355 }
358 356
359 357
360 358 /*
361 359 * meta_get_sm_state()
362 360 *
363 361 * Gets the state for the underlying components(submirrors) of a mirror.
364 362 * This function is also called from: cmd/lvm/util/metastat.c.
365 363 *
366 364 * Returns:
367 365 * string for state of the sub-mirror
368 366 */
369 367 static char *
370 368 meta_get_sm_state(
371 369 sm_state_t state
372 370 )
373 371 {
374 372 /* all is well */
375 373 if (state & SMS_RUNNING) {
376 374 return (NULL);
377 375 }
378 376
379 377 /* resyncing, needs repair */
380 378 if ((state & (SMS_COMP_RESYNC | SMS_ATTACHED_RESYNC |
381 379 SMS_OFFLINE_RESYNC))) {
382 380 return (gettext("resyncing"));
383 381 }
384 382
385 383 /* needs repair */
386 384 if (state & (SMS_COMP_ERRED | SMS_ATTACHED | SMS_OFFLINE))
387 385 return (gettext("maint"));
388 386
389 387 /* unknown */
390 388 return (gettext("unknown"));
391 389 }
392 390
393 391
394 392 /*
395 393 * meta_get_raid_col_state()
396 394 *
397 395 * Gets the state for the underlying components(columns) of a raid.
398 396 * This function is also called from: cmd/lvm/util/metastat.c.
399 397 *
400 398 * Returns:
401 399 * string for state of the raid column
402 400 *
403 401 */
404 402 char *
405 403 meta_get_raid_col_state(
406 404 rcs_state_t state
407 405 )
408 406 {
409 407 switch (state) {
410 408 case RCS_INIT:
411 409 return (gettext("initializing"));
412 410 case RCS_OKAY:
413 411 return (NULL);
414 412 case RCS_INIT_ERRED:
415 413 /*FALLTHROUGH*/
416 414 case RCS_ERRED:
417 415 return (gettext("maint"));
418 416 case RCS_LAST_ERRED:
419 417 return (gettext("last-erred"));
420 418 case RCS_RESYNC:
421 419 return (gettext("resyncing"));
422 420 default:
423 421 return (gettext("unknown"));
424 422 }
425 423 }
426 424
427 425
428 426 /*
429 427 * meta_get_stripe_state()
430 428 *
431 429 * Gets the state for the underlying components of a stripe.
432 430 * This function is also called from: cmd/lvm/util/metastat.c.
433 431 *
434 432 * Returns:
435 433 * string for state of the stripe
436 434 *
437 435 */
438 436 char *
439 437 meta_get_stripe_state(
440 438 comp_state_t state
441 439 )
442 440 {
443 441 switch (state) {
444 442 case CS_OKAY:
445 443 return (NULL);
446 444 case CS_ERRED:
447 445 return (gettext("maint"));
448 446 case CS_LAST_ERRED:
449 447 return (gettext("last-erred"));
450 448 case CS_RESYNC:
451 449 return (gettext("resyncing"));
452 450 default:
453 451 return (gettext("invalid"));
454 452 }
455 453 }
456 454
457 455
458 456 /*
459 457 * meta_get_hs_state()
460 458 *
461 459 * Gets the state for the underlying components(hotspares) of a hotspare pool.
462 460 * This function is also called from: cmd/lvm/util/metastat.c.
463 461 *
464 462 * Returns:
465 463 * string for state of the hotspare
466 464 *
467 465 */
468 466 char *
469 467 meta_get_hs_state(
470 468 hotspare_states_t state
471 469 )
472 470 {
473 471 switch (state) {
474 472 case HSS_AVAILABLE:
475 473 return (NULL);
476 474 case HSS_RESERVED:
477 475 return (gettext("in-use"));
478 476 case HSS_BROKEN:
479 477 return (gettext("broken"));
480 478 case HSS_UNUSED:
481 479 /* FALLTHROUGH */
482 480 default:
483 481 return (gettext("invalid"));
484 482 }
485 483 }
486 484
487 485
488 486 /*
489 487 * process_trans()
490 488 *
491 489 * Prints unit information for a trans metadevice and calls the respective
492 490 * functions to process the underlying metadevices.
493 491 *
494 492 */
495 493 static void
496 494 process_trans(
497 495 md_im_rec_t **mdimpp,
498 496 int indent,
499 497 pnm_rec_t *phys_nm,
500 498 md_im_rec_t *mdrec
501 499 )
502 500 {
503 501 mt_unit_t *mt;
504 502 mdc_unit_t uc;
505 503 md_im_rec_t *tmpmdrec;
506 504 int underlying_device = PHYSICAL_DEV;
507 505
508 506 mt = (mt_unit_t *)mdrec->record;
509 507 uc = mt->c;
510 508
511 509 /* Printing name, size, and type of metadevice */
512 510 print_concise_entry(indent, mdrec->n_name,
513 511 uc.un_total_blocks, 't');
514 512
515 513 /*
516 514 * Loops through md_im_rec_t **mdimpp list of all metadevices to find
517 515 * record that matches the underlying device.
518 516 * Trans devices can only have one underlying device, so once a
519 517 * match is found, we are done.
520 518 */
521 519 for (tmpmdrec = *mdimpp; tmpmdrec != NULL;
522 520 tmpmdrec = tmpmdrec->next) {
523 521 if (tmpmdrec->n_key == mt->un_m_key) {
524 522 /* Printing name of the underlying metadevice */
525 523 (void) printf(" %s", tmpmdrec->n_name);
526 524 underlying_device = NOT_PHYSICAL_DEV;
527 525 break;
528 526 }
529 527 }
530 528
531 529 /*
532 530 * If a metadevice was not found, then the underlying device must be a
533 531 * physical device. Otherwise, call the functions to process the
534 532 * underlying devices.
535 533 */
536 534 if (underlying_device == PHYSICAL_DEV) {
537 535 print_physical_device(phys_nm, mt->un_m_key);
538 536 (void) printf("\n");
539 537 } else {
540 538 /* process underlying component */
541 539 (void) printf("\n");
542 540 indent += META_INDENT;
543 541 tmpmdrec->dfunc(mdimpp, indent, phys_nm, tmpmdrec);
544 542 }
545 543
546 544 /*
547 545 * Removing the md_entry from the list
548 546 * of all metadevices
549 547 */
550 548 free_mdrec_list_entry(&mdrec);
551 549 }
552 550
553 551
554 552 /*
555 553 * process_hotspare()
556 554 *
557 555 * Searches though list of physical devices to match hotspare record.
558 556 * Prints physical device name and state of a hotspare unit.
559 557 *
560 558 */
561 559 /*ARGSUSED*/
562 560 static void
563 561 process_hotspare(
564 562 md_im_rec_t **mdimpp,
565 563 int indent,
566 564 pnm_rec_t *phys_nm,
567 565 md_im_rec_t *mdrec
568 566 )
569 567 {
570 568 hot_spare_t *hs;
571 569 pnm_rec_t *tmpphys_nm;
572 570 char *state = NULL;
573 571
574 572 hs = (hot_spare_t *)mdrec->record;
575 573
576 574 /*
577 575 * Loops through physical namespace to find the device that matches
578 576 * the hotspare entry.
579 577 */
580 578 for (tmpphys_nm = phys_nm; tmpphys_nm != NULL;
581 579 tmpphys_nm = tmpphys_nm->next) {
582 580 if (tmpphys_nm->n_key ==
583 581 ((hot_spare_t *)hs)->hs_key) {
584 582 /* Printing name of hotspare device */
585 583 (void) printf(" %s", tmpphys_nm->n_name);
586 584 break;
587 585 }
588 586 }
589 587
590 588 state = meta_get_hs_state(hs->hs_state);
591 589 if (state != NULL)
592 590 (void) printf(" (%s)", state);
593 591
594 592 /* Not removing entry, because it can be processed more than once. */
595 593 }
596 594
597 595
598 596 /*
599 597 * process_hotspare_pool()
600 598 *
601 599 * Prints concise unit information for a hotspare pool metadevice and calls a
602 600 * function to process each attached hotspare device.
603 601 *
604 602 */
605 603 static void
606 604 process_hotspare_pool(
607 605 md_im_rec_t **mdimpp,
608 606 int indent,
609 607 pnm_rec_t *phys_nm,
610 608 md_im_rec_t *mdrec
611 609 )
612 610 {
613 611 hot_spare_pool_ond_t *hsp;
614 612 int i;
615 613 md_im_rec_t *tmpmdrec;
616 614
617 615 hsp = (hot_spare_pool_ond_t *)mdrec->record;
618 616
619 617 /*
620 618 * Printing name, size, and type of metadevice. Setting size field to
621 619 * 0, so that output is the as metastat -c.
622 620 */
623 621 print_concise_entry(indent, mdrec->n_name,
624 622 0, 'h');
625 623
626 624 /* Looping through list of attached hotspare devices. */
627 625 for (i = 0; i < hsp->hsp_nhotspares; i++) {
628 626 /* Looking for the matching record for the hotspare device. */
629 627 for (tmpmdrec = *mdimpp; tmpmdrec != NULL;
630 628 tmpmdrec = tmpmdrec->next) {
631 629 if (tmpmdrec->hs_record_id == hsp->hsp_hotspares[i]) {
632 630 /* Calling function to print name of hotspare */
633 631 tmpmdrec->dfunc(mdimpp, indent, phys_nm,
634 632 tmpmdrec);
635 633 }
636 634 }
637 635 }
638 636 (void) printf("\n");
639 637
640 638 /*
641 639 * Removing the md_entry from the list
642 640 * of all metadevices
643 641 */
644 642 free_mdrec_list_entry(&mdrec);
645 643 }
646 644
647 645
648 646 /*
649 647 * process_raid()
650 648 *
651 649 * Prints concise unit information for a raid metadevice and calls the
652 650 * respective functions to process the underlying metadevices.
653 651 *
654 652 */
655 653 static void
656 654 process_raid(
657 655 md_im_rec_t **mdimpp,
658 656 int indent,
659 657 pnm_rec_t *phys_nm,
660 658 md_im_rec_t *mdrec
661 659 )
662 660 {
663 661 mr_unit_t *mr;
664 662 mr_column_t *mc;
665 663 mdc_unit_t uc;
666 664 int i;
667 665 md_im_rec_t *tmpmdrec;
668 666 md_im_rec_t *hstmpmdrec;
669 667 md_im_list_t *ucomp_head = NULL;
670 668 md_im_list_t *ucomp_tail = NULL;
671 669 md_im_list_t *ucomp = NULL;
672 670 pnm_rec_t *tmpphys_nm;
673 671 int underlying_device;
674 672
675 673 mr = (mr_unit_t *)mdrec->record;
676 674 uc = mr->c;
677 675
678 676 /* Printing name, size, and type of metadevice */
679 677 print_concise_entry(indent, mdrec->n_name,
680 678 uc.un_total_blocks, 'r');
681 679
682 680 /* Loops through raid columns to find underlying metadevices */
683 681 for (i = 0, mc = &mr->un_column[0]; i < mr->un_totalcolumncnt;
684 682 i++, mc++) {
685 683 char *state = NULL;
686 684 char *hsname = NULL;
687 685
688 686 /*
689 687 * Need to assume that underlying device is a physical device,
690 688 * unless we find a matching metadevice record.
691 689 */
692 690 underlying_device = PHYSICAL_DEV;
693 691
694 692 /*
695 693 * Loops through list of metadevices to find record that matches
696 694 * the underlying device.
697 695 */
698 696 for (tmpmdrec = *mdimpp; tmpmdrec != NULL;
699 697 tmpmdrec = tmpmdrec->next) {
700 698 if (tmpmdrec->n_key == mc->un_orig_key) {
701 699 /* check if hotspare device enabled */
702 700 if (mc->un_hs_id != NULL) {
703 701 /*
704 702 * Find matching metadevice record
705 703 * for the hotspare device.
706 704 */
707 705 for (hstmpmdrec = *mdimpp;
708 706 hstmpmdrec != NULL;
709 707 hstmpmdrec = hstmpmdrec->next) {
710 708 if (hstmpmdrec->hs_record_id ==
711 709 mc->un_hs_id) {
712 710 /* print name of hs */
713 711 hstmpmdrec->dfunc(
714 712 mdimpp, indent,
715 713 phys_nm,
716 714 hstmpmdrec);
717 715 break;
718 716 }
719 717 }
720 718 }
721 719 /* print name of underlying metadevice */
722 720 (void) printf(" %s", tmpmdrec->n_name);
723 721 underlying_device = NOT_PHYSICAL_DEV;
724 722 ucomp = Zalloc(sizeof (md_im_list_t));
725 723 ucomp->mdrec = tmpmdrec;
726 724 ucomponent_append(&ucomp_head, &ucomp_tail,
727 725 ucomp);
728 726 }
729 727 }
730 728
731 729 if (underlying_device == PHYSICAL_DEV) {
732 730 print_physical_device(phys_nm, mc->un_orig_key);
733 731 }
734 732 state = meta_get_raid_col_state(mc->un_devstate);
735 733
736 734 /*
737 735 * An underlying hotspare must be a physical device.
738 736 * If support is ever added for soft-partitions under
739 737 * hotspare pools, then this code should be updated to
740 738 * include a search for underlying metadevices.
741 739 */
742 740 if (mc->un_hs_id != 0) {
743 741 for (tmpphys_nm = phys_nm; tmpphys_nm != NULL;
744 742 tmpphys_nm = tmpphys_nm->next) {
745 743 if (tmpphys_nm->n_key == mc->un_hs_key) {
746 744 hsname = tmpphys_nm->n_name;
747 745 break;
748 746 }
749 747 }
750 748 }
751 749
752 750 if (state != NULL) {
753 751 if (hsname != NULL)
754 752 (void) printf(" (%s-%s)", state,
755 753 hsname);
756 754 else
757 755 (void) printf(" (%s)", state);
758 756 } else if (hsname != NULL) {
759 757 (void) printf(gettext(" (spared-%s)"), hsname);
760 758 }
761 759 }
762 760 (void) printf("\n");
763 761
764 762 /* process underlying components */
765 763 indent += META_INDENT;
766 764 for (ucomp = ucomp_head; ucomp != NULL;
767 765 ucomp = ucomp->next) {
768 766 ucomp->mdrec->dfunc(mdimpp, indent, phys_nm,
769 767 ucomp->mdrec);
770 768 }
771 769 free_md_im_list_entries(&ucomp_head);
772 770
773 771 /*
774 772 * Removing the md_entry from the list
775 773 * of all metadevices
776 774 */
777 775 free_mdrec_list_entry(&mdrec);
778 776 }
779 777
780 778
781 779 /*
782 780 * process_mirror()
783 781 *
784 782 * Prints concise unit information for a mirror metadevice and calls the
785 783 * respective functions to process the underlying metadevices.
786 784 *
787 785 */
788 786 static void
789 787 process_mirror(
790 788 md_im_rec_t **mdimpp,
791 789 int indent,
792 790 pnm_rec_t *phys_nm,
793 791 md_im_rec_t *mdrec
794 792 )
795 793 {
796 794 mm_unit_t *mm;
797 795 mm_submirror_t *sm;
798 796 mdc_unit_t uc;
799 797 int i;
800 798 md_im_rec_t *tmpmdrec;
801 799 md_im_list_t *ucomp_head = NULL;
802 800 md_im_list_t *ucomp_tail = NULL;
803 801 md_im_list_t *ucomp = NULL;
804 802
805 803 mm = (mm_unit_t *)mdrec->record;
806 804 uc = mm->c;
807 805
808 806 /* Printing name, size, and type of metadevice */
809 807 print_concise_entry(indent, mdrec->n_name,
810 808 uc.un_total_blocks, 'm');
811 809
812 810 /* Looping through sub-mirrors to find underlying devices */
813 811 for (i = 0, sm = &mm->un_sm[0]; i < mm->un_nsm; i++, sm++) {
814 812 char *state = NULL;
815 813
816 814 for (tmpmdrec = *mdimpp; tmpmdrec != NULL;
817 815 tmpmdrec = tmpmdrec->next) {
818 816 if (tmpmdrec->n_key == sm->sm_key) {
819 817 (void) printf(" %s", tmpmdrec->n_name);
820 818 ucomp = Zalloc(sizeof (md_im_list_t));
821 819 ucomp->mdrec = tmpmdrec;
822 820 ucomponent_append(&ucomp_head, &ucomp_tail,
823 821 ucomp);
824 822 }
825 823 }
826 824
827 825 /*
828 826 * It is not possible to have an underlying physical device
829 827 * for a submirror, so there is no need to search the phys_nm
830 828 * list.
831 829 */
832 830
833 831 /* Printing the state for the submirror */
834 832 state = meta_get_sm_state(sm->sm_state);
835 833 if (state != NULL) {
836 834 (void) printf(" (%s)", state);
837 835 }
838 836 }
839 837 (void) printf("\n");
840 838
841 839 /* process underlying components */
842 840 indent += META_INDENT;
843 841 for (ucomp = ucomp_head; ucomp != NULL;
844 842 ucomp = ucomp->next) {
845 843 ucomp->mdrec->dfunc(mdimpp, indent, phys_nm,
846 844 ucomp->mdrec);
847 845 }
848 846 free_md_im_list_entries(&ucomp_head);
849 847
850 848 /*
851 849 * Removing the md_entry from the list
852 850 * of all metadevices
853 851 */
854 852 free_mdrec_list_entry(&mdrec);
855 853 }
856 854
857 855
858 856 /*
859 857 * process_stripe()
860 858 *
861 859 * Prints concise unit information for a stripe metadevice and calls the
862 860 * respective functions to process the underlying metadevices.
863 861 *
864 862 */
865 863 static void
866 864 process_stripe(
867 865 md_im_rec_t **mdimpp,
868 866 int indent,
869 867 pnm_rec_t *phys_nm,
870 868 md_im_rec_t *mdrec
871 869 )
872 870 {
873 871 ms_unit_t *ms;
874 872 mdc_unit_t uc;
875 873 md_im_rec_t *tmpmdrec;
876 874 md_im_list_t *ucomp_head = NULL;
877 875 md_im_list_t *ucomp_tail = NULL;
878 876 md_im_list_t *ucomp = NULL;
879 877 pnm_rec_t *tmpphys_nm;
880 878 int underlying_device;
881 879 uint_t row;
882 880
883 881 ms = (ms_unit_t *)mdrec->record;
884 882 uc = ms->c;
885 883
886 884 /* Printing name, size, and type of metadevice */
887 885 print_concise_entry(indent, mdrec->n_name,
888 886 uc.un_total_blocks, 's');
889 887
890 888 /* Looping through stripe rows */
891 889 for (row = 0; (row < ms->un_nrows); ++row) {
892 890 struct ms_row *mdr = &ms->un_row[row];
893 891 ms_comp_t *mdcomp = (void *)&((char *)ms)
894 892 [ms->un_ocomp];
895 893 uint_t comp, c;
896 894
897 895 /*
898 896 * Looping through the components in each row to find the
899 897 * underlying devices.
900 898 */
901 899 for (comp = 0, c = mdr->un_icomp; (comp < mdr->un_ncomp);
902 900 ++comp, ++c) {
903 901 char *state = NULL;
904 902 char *hsname = NULL;
905 903 ms_comp_t *mdc = &mdcomp[c];
906 904 md_m_shared_t *mdm = &mdc->un_mirror;
907 905
908 906 /*
909 907 * Need to assume that underlying device is a
910 908 * physical device, unless we find a matching
911 909 * metadevice record.
912 910 */
913 911 underlying_device = PHYSICAL_DEV;
914 912
915 913 for (tmpmdrec = *mdimpp; tmpmdrec != NULL;
916 914 tmpmdrec = tmpmdrec->next) {
917 915 if (tmpmdrec->n_key == mdc->un_key) {
918 916 (void) printf(" %s", tmpmdrec->n_name);
919 917 underlying_device = NOT_PHYSICAL_DEV;
920 918 ucomp = Zalloc(sizeof (md_im_list_t));
921 919 ucomp->mdrec = tmpmdrec;
922 920 ucomponent_append(&ucomp_head,
923 921 &ucomp_tail, ucomp);
924 922 }
925 923 }
926 924 /* if an underlying metadevice was not found */
927 925 if (underlying_device == PHYSICAL_DEV) {
928 926 print_physical_device(phys_nm, mdc->un_key);
929 927 }
930 928 state = meta_get_stripe_state(mdm->ms_state);
931 929
932 930 /*
933 931 * An underlying hotspare must be a physical device.
934 932 * If support is ever added for soft-partitions under
935 933 * hotspare pools, then this code should be updated to
936 934 * include a search for underlying metadevices.
937 935 */
938 936 if (mdm->ms_hs_key != 0) {
939 937 for (tmpphys_nm = phys_nm; tmpphys_nm != NULL;
940 938 tmpphys_nm = tmpphys_nm->next) {
941 939 if (tmpphys_nm->n_key ==
942 940 mdm->ms_hs_key) {
943 941 hsname = tmpphys_nm->n_name;
944 942 break;
945 943 }
946 944 }
947 945 }
948 946 if (state != NULL) {
949 947 if (hsname != NULL) {
950 948 (void) printf(" (%s-%s)", state,
951 949 hsname);
952 950 } else {
953 951 (void) printf(" (%s)", state);
954 952 }
955 953 } else if (hsname != NULL) {
956 954 (void) printf(gettext(" (spared-%s)"), hsname);
957 955 }
958 956 }
959 957 }
960 958 (void) printf("\n");
961 959
962 960 /* Process underlying metadevices */
963 961 indent += META_INDENT;
964 962 for (ucomp = ucomp_head; ucomp != NULL;
965 963 ucomp = ucomp->next) {
966 964 ucomp->mdrec->dfunc(mdimpp, indent, phys_nm,
967 965 ucomp->mdrec);
968 966 }
969 967 free_md_im_list_entries(&ucomp_head);
970 968
971 969 /*
972 970 * Removing the md_entry from the list
973 971 * of all metadevices
974 972 */
975 973 free_mdrec_list_entry(&mdrec);
976 974 }
977 975
978 976
979 977 /*
980 978 * process_softpart()
981 979 *
982 980 * Prints concise unit information for a softpart metadevice and calls the
983 981 * respective functions to process the underlying metadevices.
984 982 *
985 983 */
986 984 static void
987 985 process_softpart(
988 986 md_im_rec_t **mdimpp,
989 987 int indent,
990 988 pnm_rec_t *phys_nm,
991 989 md_im_rec_t *mdrec
992 990 )
993 991 {
994 992 mp_unit_t *mp;
995 993 mdc_unit_t uc;
996 994 md_im_rec_t *tmpmdrec;
997 995 int underlying_device = PHYSICAL_DEV;
998 996
999 997 mp = (mp_unit_t *)mdrec->record;
1000 998 uc = mp->c;
1001 999
1002 1000 /* Printing name, size, and type of metadevice */
1003 1001 print_concise_entry(indent, mdrec->n_name,
1004 1002 uc.un_total_blocks, 'p');
1005 1003
1006 1004 /*
1007 1005 * Loops through md_im_rec_t **mdimpp list of all metadevices to find
1008 1006 * record that matches the underlying device.
1009 1007 * Softpartitions can only have one underlying device, so once a
1010 1008 * match is found, we are done.
1011 1009 */
1012 1010 for (tmpmdrec = *mdimpp; tmpmdrec != NULL;
1013 1011 tmpmdrec = tmpmdrec->next) {
1014 1012 if (tmpmdrec->n_key == mp->un_key) {
1015 1013 /* Printing name of the underlying metadevice */
1016 1014 (void) printf(" %s", tmpmdrec->n_name);
1017 1015 underlying_device = NOT_PHYSICAL_DEV;
1018 1016 break;
1019 1017 }
1020 1018 }
1021 1019
1022 1020 /* This is only executed if an underlying metadevice was not found */
1023 1021 if (underlying_device == PHYSICAL_DEV) {
1024 1022 print_physical_device(phys_nm, mp->un_key);
1025 1023 (void) printf("\n");
1026 1024 } else {
1027 1025 /* Process underlying metadevice */
1028 1026 (void) printf("\n");
1029 1027 indent += META_INDENT;
1030 1028 tmpmdrec->dfunc(mdimpp, indent, phys_nm,
1031 1029 tmpmdrec);
1032 1030 }
1033 1031
1034 1032 /*
1035 1033 * Removing the md_entry from the list
1036 1034 * of all metadevices
1037 1035 */
1038 1036 free_mdrec_list_entry(&mdrec);
1039 1037 }
1040 1038
1041 1039
1042 1040 /*
1043 1041 * process_toplevel_softparts()
1044 1042 *
1045 1043 * Toplevel softpartions need to be grouped so that their underlying devices
1046 1044 * can be printed just once.
1047 1045 */
1048 1046 static void
1049 1047 process_toplevel_softparts(
1050 1048 md_im_rec_t **mdimpp,
1051 1049 int indent,
1052 1050 pnm_rec_t *phys_nm
1053 1051 )
1054 1052 {
1055 1053 mp_unit_t *mp;
1056 1054 mdc_unit_t uc;
1057 1055 md_im_rec_t *mdrec;
1058 1056 md_im_rec_t *comp_mdrec; /* pntr to underlying component's record */
1059 1057 md_im_rec_t *tmp_mdrec, *rm_mdrec;
1060 1058 mp_unit_t *tmp_mp;
1061 1059 int underlying_device;
1062 1060
1063 1061 /*
1064 1062 * Loops through md_im_rec_t **mdimpp list of all metadevices to find
1065 1063 * all softpartions that are toplevel softpartitions(softparts w/out
1066 1064 * a parent). Groups output for these entries so that the function to
1067 1065 * process the underlying metadevice is only called once.
1068 1066 */
1069 1067 for (mdrec = *mdimpp; mdrec != NULL; mdrec = mdrec->next) {
1070 1068
1071 1069 underlying_device = PHYSICAL_DEV;
1072 1070 if ((mdrec->md_type == MDDB_F_SOFTPART) &&
1073 1071 (mdrec->has_parent == 0)) {
1074 1072 mp = (mp_unit_t *)mdrec->record;
1075 1073 uc = mp->c;
1076 1074 /* Printing name, size, and type of metadevice */
1077 1075 print_concise_entry(indent, mdrec->n_name,
1078 1076 uc.un_total_blocks, 'p');
1079 1077 /*
1080 1078 * Looking for record that matches underlying
1081 1079 * component.
1082 1080 */
1083 1081 for (comp_mdrec = *mdimpp; comp_mdrec != NULL;
1084 1082 comp_mdrec = comp_mdrec->next) {
1085 1083 if (comp_mdrec->n_key == mp->un_key) {
1086 1084 /* Print name of underlying device */
1087 1085 (void) printf(" %s",
1088 1086 comp_mdrec->n_name);
1089 1087 underlying_device = NOT_PHYSICAL_DEV;
1090 1088 break;
1091 1089 }
1092 1090 }
1093 1091 if (underlying_device == PHYSICAL_DEV) {
1094 1092 print_physical_device(phys_nm, mp->un_key);
1095 1093 }
1096 1094 (void) printf("\n");
1097 1095
1098 1096 /*
1099 1097 * Looking for any other toplevel softpartitions with
1100 1098 * same underlying device. We know that all other
1101 1099 * matching metadevices, that share the same underlying
1102 1100 * metadevice, are also soft-partitions.
1103 1101 */
1104 1102 for (tmp_mdrec = mdrec->next; tmp_mdrec != NULL; ) {
1105 1103 tmp_mp = (mp_unit_t *)tmp_mdrec->record;
1106 1104 if ((tmp_mdrec->has_parent == 0) &&
1107 1105 (tmp_mp->un_key == mp->un_key)) {
1108 1106 uc = tmp_mp->c;
1109 1107 print_concise_entry(indent,
1110 1108 tmp_mdrec->n_name,
1111 1109 uc.un_total_blocks, 'p');
1112 1110 if (underlying_device ==
1113 1111 NOT_PHYSICAL_DEV) {
1114 1112 (void) printf(" %s",
1115 1113 comp_mdrec->n_name);
1116 1114 } else {
1117 1115 print_physical_device(
1118 1116 phys_nm, tmp_mp->un_key);
1119 1117 }
1120 1118 (void) printf("\n");
1121 1119 /*
1122 1120 * Need to advance so that will not lose
1123 1121 * position after removing processed
1124 1122 * record.
1125 1123 */
1126 1124 rm_mdrec = tmp_mdrec;
1127 1125 tmp_mdrec = tmp_mdrec->next;
1128 1126 /*
1129 1127 * Removing the md_entry from the list
1130 1128 * of all metadevices.
1131 1129 */
1132 1130 free_mdrec_list_entry(&rm_mdrec);
1133 1131 } else {
1134 1132 tmp_mdrec = tmp_mdrec->next;
1135 1133 }
1136 1134 }
1137 1135 /* Process the underlying device */
1138 1136 if (underlying_device == NOT_PHYSICAL_DEV) {
1139 1137 indent += META_INDENT;
1140 1138 comp_mdrec->dfunc(mdimpp, indent, phys_nm,
1141 1139 comp_mdrec);
1142 1140 }
1143 1141 }
1144 1142 }
1145 1143 }
1146 1144
1147 1145
1148 1146 /*
1149 1147 * process_toplevel_devices()
1150 1148 *
1151 1149 * Search through list of metadevices for metadevices of md_type that do not
1152 1150 * have a parent.
1153 1151 *
1154 1152 */
1155 1153 static void
1156 1154 process_toplevel_devices(
1157 1155 md_im_rec_t **mdimpp,
1158 1156 pnm_rec_t *pnm,
1159 1157 uint_t md_type
1160 1158 )
1161 1159 {
1162 1160 md_im_rec_t *mdrec;
1163 1161 md_im_list_t *mdrec_tl_tail = NULL;
1164 1162 md_im_list_t *mdrec_tl_head = NULL;
1165 1163 md_im_list_t *tmp_tl_list = NULL;
1166 1164 int indent = 0;
1167 1165
1168 1166 indent += META_INDENT;
1169 1167
1170 1168 /*
1171 1169 * Need to group soft partitions so that common underlying device
1172 1170 * are only processed once.
1173 1171 */
1174 1172 if (md_type == MDDB_F_SOFTPART) {
1175 1173 process_toplevel_softparts(mdimpp, indent, pnm);
1176 1174 return;
1177 1175 }
1178 1176
1179 1177 /*
1180 1178 * Search the list of metadevices to find all metadevices that match
1181 1179 * the type and don't have a parent. Put them on a separate list
1182 1180 * that will be processed.
1183 1181 */
1184 1182 for (mdrec = *mdimpp; mdrec != NULL; mdrec = mdrec->next) {
1185 1183 if ((mdrec->md_type == md_type)&&(mdrec->has_parent == 0)) {
1186 1184 tmp_tl_list = Zalloc(sizeof (md_im_list_t));
1187 1185 tmp_tl_list->mdrec = mdrec;
1188 1186 tmp_tl_list->next = NULL;
1189 1187 if (mdrec_tl_tail == NULL) {
1190 1188 mdrec_tl_tail = tmp_tl_list;
1191 1189 mdrec_tl_head = mdrec_tl_tail;
1192 1190 } else {
1193 1191 mdrec_tl_tail->next = tmp_tl_list;
1194 1192 mdrec_tl_tail = mdrec_tl_tail->next;
1195 1193 }
1196 1194 }
1197 1195
1198 1196 }
1199 1197
1200 1198 /*
1201 1199 * Loop through list and process all top-level metadevices of a
1202 1200 * given type.
1203 1201 */
1204 1202 for (tmp_tl_list = mdrec_tl_head; tmp_tl_list != NULL;
1205 1203 tmp_tl_list = tmp_tl_list->next) {
1206 1204 tmp_tl_list->mdrec->dfunc(mdimpp, indent, pnm,
1207 1205 tmp_tl_list->mdrec);
1208 1206 }
1209 1207
1210 1208 free_md_im_list_entries(&mdrec_tl_head);
1211 1209 }
1212 1210
1213 1211
1214 1212 /*
1215 1213 * extract_mduser_data()
1216 1214 *
1217 1215 * Converts or copies the (mddb_rb_t->rb_data) metadevice record to a 64bit
1218 1216 * record.
1219 1217 * Sets the dfunc field to point to the appropriate function to process the
1220 1218 * metadevice.
1221 1219 * Sets the parent field for the metadevice.
1222 1220 * Extracts the name from the NM namespace if it is available, otherwise
1223 1221 * generates it from the metadevice's minor number.
1224 1222 *
1225 1223 * Returns:
1226 1224 * < 0 for failure
1227 1225 * 0 for success
1228 1226 *
1229 1227 */
1230 1228 static int
1231 1229 extract_mduser_data(
1232 1230 mddb_rb_t *nm,
1233 1231 md_im_rec_t *mdrec,
1234 1232 void *rbp,
1235 1233 int is_32bit_record,
1236 1234 md_error_t *ep
1237 1235 )
1238 1236 {
1239 1237 mdc_unit_t uc;
1240 1238 hot_spare_t *hs;
1241 1239 hot_spare_pool_ond_t *hsp;
1242 1240 size_t newreqsize;
1243 1241 mddb_rb_t *rbp_nm = nm;
1244 1242 struct nm_rec *nm_record;
1245 1243 struct nm_name *nmname;
1246 1244 char *uname = NULL;
1247 1245
1248 1246
1249 1247 /*LINTED*/
1250 1248 nm_record = (struct nm_rec *)((caddr_t)(&rbp_nm->rb_data));
1251 1249
1252 1250 /*
1253 1251 * Setting the un_self_id or the hs_self_id, in the case of hotspare
1254 1252 * records, for each metadevice entry. Also setting has_parent and
1255 1253 * setting dfunc so that it points to the correct function to process
1256 1254 * the record type.
1257 1255 * If the record was stored ondisk in 32bit format, then it is
1258 1256 * converted to the 64bits equivalent 64bit format and the memory
1259 1257 * for the 32bit pointer is freed.
1260 1258 */
1261 1259 switch (mdrec->md_type) {
1262 1260 case MDDB_F_SOFTPART:
1263 1261 if (is_32bit_record) {
1264 1262 mp_unit32_od_t *small_un;
1265 1263 mp_unit_t *big_un;
1266 1264
1267 1265 small_un = (mp_unit32_od_t *)((uintptr_t)rbp +
1268 1266 (sizeof (mddb_rb_t) - sizeof (int)));
1269 1267 newreqsize = sizeof (mp_unit_t) +
1270 1268 ((small_un->un_numexts - 1) *
1271 1269 sizeof (struct mp_ext));
1272 1270 big_un = (void *)Zalloc(newreqsize);
1273 1271 softpart_convert((caddr_t)small_un,
1274 1272 (caddr_t)big_un, SMALL_2_BIG);
1275 1273 mdrec->record = (void *)big_un;
1276 1274 } else {
1277 1275 mp_unit_t *big_un;
1278 1276
1279 1277 big_un = (mp_unit_t *)((uintptr_t)rbp +
1280 1278 (sizeof (mddb_rb_t) - sizeof (int)));
1281 1279 newreqsize = sizeof (mp_unit_t) +
1282 1280 ((big_un->un_numexts - 1) *
1283 1281 sizeof (struct mp_ext));
1284 1282 mdrec->record = (void *)Zalloc(newreqsize);
1285 1283 bcopy(big_un, mdrec->record, newreqsize);
1286 1284 }
1287 1285 uc = ((mp_unit_t *)mdrec->record)->c;
1288 1286 mdrec->dfunc = &process_softpart;
1289 1287 mdrec->un_self_id = uc.un_self_id;
1290 1288 mdrec->has_parent = MD_HAS_PARENT(
1291 1289 uc.un_parent);
1292 1290 break;
1293 1291 case MDDB_F_STRIPE:
1294 1292 if (is_32bit_record) {
1295 1293 ms_unit32_od_t *small_un;
1296 1294 ms_unit_t *big_un;
1297 1295
1298 1296 small_un = (ms_unit32_od_t *)((uintptr_t)rbp +
1299 1297 (sizeof (mddb_rb_t) - sizeof (int)));
1300 1298 newreqsize = get_big_stripe_req_size(
1301 1299 small_un, COMPLETE_STRUCTURE);
1302 1300 big_un = (void *)Zalloc(newreqsize);
1303 1301 stripe_convert((caddr_t)small_un,
1304 1302 (caddr_t)big_un, SMALL_2_BIG);
1305 1303 mdrec->record = (void *)big_un;
1306 1304 } else {
1307 1305 ms_unit_t *big_un;
1308 1306
1309 1307 big_un = (ms_unit_t *)((uintptr_t)rbp +
1310 1308 (sizeof (mddb_rb_t) - sizeof (int)));
1311 1309 newreqsize = get_stripe_req_size(big_un);
1312 1310 mdrec->record = (void *)Zalloc(newreqsize);
1313 1311 bcopy(big_un, mdrec->record, newreqsize);
1314 1312 }
1315 1313 uc = ((ms_unit_t *)mdrec->record)->c;
1316 1314 mdrec->dfunc = &process_stripe;
1317 1315 mdrec->un_self_id = uc.un_self_id;
1318 1316 mdrec->has_parent = MD_HAS_PARENT(
1319 1317 uc.un_parent);
1320 1318 break;
1321 1319 case MDDB_F_MIRROR:
1322 1320 if (is_32bit_record) {
1323 1321 mm_unit32_od_t *small_un;
1324 1322 mm_unit_t *big_un;
1325 1323
1326 1324 small_un = (mm_unit32_od_t *)((uintptr_t)rbp +
1327 1325 (sizeof (mddb_rb_t) - sizeof (int)));
1328 1326 newreqsize = sizeof (mm_unit_t);
1329 1327 big_un = (void *)Zalloc(newreqsize);
1330 1328 mirror_convert((caddr_t)small_un,
1331 1329 (caddr_t)big_un, SMALL_2_BIG);
1332 1330 mdrec->record = (void *)big_un;
1333 1331 } else {
1334 1332 mm_unit_t *big_un;
1335 1333
1336 1334 big_un = (mm_unit_t *)((uintptr_t)rbp +
1337 1335 (sizeof (mddb_rb_t) - sizeof (int)));
1338 1336 newreqsize = sizeof (mm_unit_t);
1339 1337 mdrec->record = (void *)Zalloc(newreqsize);
1340 1338 bcopy(big_un, mdrec->record, newreqsize);
1341 1339 }
1342 1340 uc = ((mm_unit_t *)mdrec->record)->c;
1343 1341 mdrec->dfunc = &process_mirror;
1344 1342 mdrec->un_self_id = uc.un_self_id;
1345 1343 mdrec->has_parent = MD_HAS_PARENT(
1346 1344 uc.un_parent);
1347 1345 break;
1348 1346 case MDDB_F_RAID:
1349 1347 if (is_32bit_record) {
1350 1348 mr_unit32_od_t *small_un;
1351 1349 mr_unit_t *big_un;
1352 1350 uint_t ncol;
1353 1351
1354 1352 small_un = (mr_unit32_od_t *)((uintptr_t)rbp +
1355 1353 (sizeof (mddb_rb_t) - sizeof (int)));
1356 1354 ncol = small_un->un_totalcolumncnt;
1357 1355 newreqsize = sizeof (mr_unit_t) +
1358 1356 ((ncol - 1) * sizeof (mr_column_t));
1359 1357 big_un = (void *)Zalloc(newreqsize);
1360 1358 raid_convert((caddr_t)small_un,
1361 1359 (caddr_t)big_un, SMALL_2_BIG);
1362 1360 mdrec->record = (void *)big_un;
1363 1361 } else {
1364 1362 mr_unit_t *big_un;
1365 1363 uint_t ncol;
1366 1364
1367 1365 big_un = (mr_unit_t *)((uintptr_t)rbp +
1368 1366 (sizeof (mddb_rb_t) - sizeof (int)));
1369 1367 ncol = big_un->un_totalcolumncnt;
1370 1368 newreqsize = sizeof (mr_unit_t) +
1371 1369 ((ncol - 1) * sizeof (mr_column_t));
1372 1370 mdrec->record = (void *)Zalloc(newreqsize);
1373 1371 bcopy(big_un, mdrec->record, newreqsize);
1374 1372 }
1375 1373 uc = ((mr_unit_t *)mdrec->record)->c;
1376 1374 mdrec->dfunc = &process_raid;
1377 1375 mdrec->un_self_id = uc.un_self_id;
1378 1376 mdrec->has_parent = MD_HAS_PARENT(
1379 1377 uc.un_parent);
1380 1378 break;
1381 1379 case MDDB_F_TRANS_MASTER:
1382 1380 if (is_32bit_record) {
1383 1381 mt_unit32_od_t *small_un;
1384 1382 mt_unit_t *big_un;
1385 1383
1386 1384 small_un = (mt_unit32_od_t *)((uintptr_t)rbp +
1387 1385 (sizeof (mddb_rb_t) - sizeof (int)));
1388 1386 newreqsize = sizeof (mt_unit_t);
1389 1387 big_un = (void *)Zalloc(newreqsize);
1390 1388 trans_master_convert((caddr_t)small_un,
1391 1389 (caddr_t)big_un, SMALL_2_BIG);
1392 1390 mdrec->record = (void *)big_un;
1393 1391 } else {
1394 1392 mt_unit_t *big_un;
1395 1393
1396 1394 big_un = (mt_unit_t *)((uintptr_t)rbp +
1397 1395 (sizeof (mddb_rb_t) - sizeof (int)));
1398 1396 newreqsize = sizeof (mt_unit_t);
1399 1397 mdrec->record = (void *)Zalloc(newreqsize);
1400 1398 bcopy(big_un, mdrec->record, newreqsize);
1401 1399 }
1402 1400 uc = ((mt_unit_t *)mdrec->record)->c;
1403 1401 mdrec->dfunc = &process_trans;
1404 1402 mdrec->un_self_id = uc.un_self_id;
1405 1403 mdrec->has_parent = MD_HAS_PARENT(
1406 1404 uc.un_parent);
1407 1405 break;
1408 1406 case MDDB_F_HOTSPARE:
1409 1407 if (is_32bit_record) {
1410 1408 hot_spare32_od_t *small_un;
1411 1409 hot_spare_t *big_un;
1412 1410
1413 1411 small_un = (hot_spare32_od_t *)((uintptr_t)rbp +
1414 1412 (sizeof (mddb_rb_t) - sizeof (int)));
1415 1413 newreqsize = sizeof (hot_spare_t);
1416 1414 big_un = (void *)Zalloc(newreqsize);
1417 1415 hs_convert((caddr_t)small_un,
1418 1416 (caddr_t)big_un, SMALL_2_BIG);
1419 1417 mdrec->record = (void *)big_un;
1420 1418 } else {
1421 1419 hot_spare_t *big_un;
1422 1420
1423 1421 big_un = (hot_spare_t *)((uintptr_t)rbp +
1424 1422 (sizeof (mddb_rb_t) - sizeof (int)));
1425 1423 newreqsize = sizeof (hot_spare_t);
1426 1424 mdrec->record = (void *)Zalloc(newreqsize);
1427 1425 bcopy(big_un, mdrec->record, newreqsize);
1428 1426 }
1429 1427 hs = (hot_spare_t *)mdrec->record;
1430 1428 mdrec->dfunc = &process_hotspare;
1431 1429 mdrec->un_self_id = NULL;
1432 1430 mdrec->hs_record_id = hs->hs_record_id;
1433 1431 mdrec->has_parent = 1;
1434 1432 break;
1435 1433 case MDDB_F_HOTSPARE_POOL:
1436 1434 /*
1437 1435 * Ondisk and incore records are always same size.
1438 1436 */
1439 1437 hsp = (hot_spare_pool_ond_t *)((uintptr_t)rbp +
1440 1438 (sizeof (mddb_rb_t) - sizeof (int)));
1441 1439 newreqsize = sizeof (hot_spare_pool_ond_t) +
1442 1440 (sizeof (mddb_recid_t) * hsp->hsp_nhotspares);
1443 1441 mdrec->record = (void *)Zalloc(newreqsize);
1444 1442 bcopy(hsp, mdrec->record, newreqsize);
1445 1443 hsp = (hot_spare_pool_ond_t *)mdrec->record;
1446 1444 mdrec->dfunc = &process_hotspare_pool;
1447 1445 /*
1448 1446 * If the hsp has descriptive name we'll get
1449 1447 * the un_self_id
1450 1448 */
1451 1449 if (HSP_ID_IS_FN(hsp->hsp_self_id))
1452 1450 mdrec->un_self_id = hsp->hsp_self_id;
1453 1451 else
1454 1452 mdrec->un_self_id = NULL;
1455 1453 mdrec->has_parent = 0;
1456 1454 break;
1457 1455 /* All valid cases have been dealt with */
1458 1456 default:
1459 1457 (void) mdmddberror(ep, MDE_DB_NODB, 0, 0, 0, NULL);
1460 1458 return (-1);
1461 1459 }
1462 1460
1463 1461 /*
1464 1462 * If metadevice record has an entry in the NM namespace
1465 1463 * then it is copied into the mdrec->n_name field.
1466 1464 */
1467 1465 if (mdrec->un_self_id != NULL) {
1468 1466 for (nmname = &nm_record->r_name[0]; nmname->n_key != 0;
1469 1467 /*LINTED*/
1470 1468 nmname = (struct nm_name *)((char *)nmname +
1471 1469 NAMSIZ(nmname))) {
1472 1470 /*
1473 1471 * Extract the metadevice/hsp name if it is
1474 1472 * in the namespace.
1475 1473 *
1476 1474 * If it is a hot spare pool we will find our
1477 1475 * match by comparing the NM record's n_key
1478 1476 * with the extracted key from the hsp_self_id
1479 1477 * Else, match the un_self_id for the record
1480 1478 * to the n_minor name in the NM record.
1481 1479 */
1482 1480 if (mdrec->md_type == MDDB_F_HOTSPARE_POOL) {
1483 1481 if (nmname->n_key ==
1484 1482 HSP_ID_TO_KEY(hsp->hsp_self_id)) {
1485 1483 mdrec->n_key = nmname->n_key;
1486 1484 uname = Strdup(nmname->n_name);
1487 1485 mdrec->n_name = uname;
1488 1486 break;
1489 1487 }
1490 1488 } else {
1491 1489 if ((nmname->n_minor) == (uc.un_self_id)) {
1492 1490 (*mdrec).n_key = nmname->n_key;
1493 1491 uname = Strdup(nmname->n_name);
1494 1492 mdrec->n_name = uname;
1495 1493 break;
1496 1494 }
1497 1495 }
1498 1496 }
1499 1497 }
1500 1498
1501 1499 /*
1502 1500 * If the metadevice name is not in the namespace, then
1503 1501 * then we will generate the name from the minor number
1504 1502 * for the metadevice. In the case of records for a hotspare
1505 1503 * pool we use hsp_self_id, otherwise we use un_self_id.
1506 1504 */
1507 1505 if (uname == NULL) {
1508 1506 if (mdrec->md_type == MDDB_F_HOTSPARE_POOL) {
1509 1507 uname = Malloc(MAXSIZEMDRECNAME);
1510 1508 (void) sprintf(uname, "hsp%03u",
1511 1509 HSP_ID(hsp->hsp_self_id));
1512 1510 mdrec->n_name = uname;
1513 1511 } else if (mdrec->md_type != MDDB_F_HOTSPARE) {
1514 1512 /*
1515 1513 * Generate the metadevice name for all other records
1516 1514 * (except for hotspares, because hotspares can only
1517 1515 * be physical devices.)
1518 1516 */
1519 1517 uname = Malloc(MAXSIZEMDRECNAME);
1520 1518 (void) sprintf(uname, "d%lu",
1521 1519 MD_MIN2UNIT(mdrec->un_self_id));
1522 1520 mdrec->n_name = uname;
1523 1521 }
1524 1522 }
1525 1523
1526 1524 return (0);
1527 1525 }
1528 1526
1529 1527
1530 1528 /*
1531 1529 * read_mdrecord()
1532 1530 *
1533 1531 * Reads the mddb_rb32_od_t or mddb_rb_t and the associated metadevice record
1534 1532 * from the disk. Runs magic, checksum, and revision checks on the record
1535 1533 * block.
1536 1534 *
1537 1535 * Returns:
1538 1536 * < 0 for failure
1539 1537 * 0 for success
1540 1538 *
1541 1539 */
1542 1540 static int
1543 1541 read_mdrecord(
1544 1542 md_im_rec_t **mdimpp,
1545 1543 mddb_mb_t *mbp,
1546 1544 mddb_rb_t *nm,
1547 1545 mddb_de_t *dep,
1548 1546 char *diskname,
1549 1547 int fd,
1550 1548 md_timeval32_t *lastaccess,
1551 1549 md_error_t *ep
1552 1550 )
1553 1551 {
1554 1552 int cnt, rval = 0;
1555 1553 daddr_t pblk;
1556 1554 md_im_rec_t *tmp_mdrec;
1557 1555 void *rbp = NULL;
1558 1556 char *rbp_tmp = NULL;
1559 1557 mddb_rb32_t *rbp_32;
1560 1558 mddb_rb_t *rbp_64;
1561 1559 crc_skip_t *skip = NULL;
1562 1560 int is_32bit_record;
1563 1561
1564 1562 tmp_mdrec = Zalloc(sizeof (md_im_rec_t));
1565 1563 rbp = (void *)Zalloc(dbtob(dep->de_blkcount));
1566 1564 rbp_tmp = (char *)rbp;
1567 1565
1568 1566 /* Read in the appropriate record and return configurations */
1569 1567 for (cnt = 0; cnt < dep->de_blkcount; cnt++) {
1570 1568 if ((pblk = getphysblk(dep->de_blks[cnt], mbp)) < 0) {
1571 1569 rval = mdmddberror(ep, MDE_DB_BLKRANGE,
1572 1570 NODEV32, MD_LOCAL_SET,
1573 1571 dep->de_blks[cnt], diskname);
1574 1572 return (rval);
1575 1573 }
1576 1574
1577 1575 if (lseek(fd, (off_t)dbtob(pblk), SEEK_SET) < 0) {
1578 1576 rval = mdsyserror(ep, errno, diskname);
1579 1577 return (rval);
1580 1578 }
1581 1579
1582 1580 if (read(fd, rbp_tmp, DEV_BSIZE) != DEV_BSIZE) {
1583 1581 rval = mdsyserror(ep, errno, diskname);
1584 1582 return (rval);
1585 1583 }
1586 1584
1587 1585 rbp_tmp += DEV_BSIZE;
1588 1586 }
1589 1587 tmp_mdrec->md_type = dep->de_flags;
1590 1588
1591 1589 /*
1592 1590 * The only place to discover whether or not the record is a
1593 1591 * 32bit or 64bit record is from the record's rb_revision field.
1594 1592 * The mddb_rb_t and mddb_rb32_t structures are identical for the
1595 1593 * following fields:
1596 1594 * rb_magic, rb_revision, rb_checksum, and rb_checksum_fiddle.
1597 1595 * So we can assume that the record is a 32bit structure when we
1598 1596 * check the record's magic number and revision and when we calculate
1599 1597 * the records checksum.
1600 1598 */
1601 1599 rbp_32 = (mddb_rb32_t *)rbp;
1602 1600
1603 1601 /*
1604 1602 * Checking the magic number for the record block.
1605 1603 */
1606 1604 if (rbp_32->rb_magic != MDDB_MAGIC_RB) {
1607 1605 rval = -1;
1608 1606 (void) mdmddberror(ep, MDE_DB_NODB, 0, 0, 0, NULL);
1609 1607 goto out;
1610 1608 }
1611 1609
1612 1610 /*
1613 1611 * Checking the revision for the record block. Must match either
1614 1612 * revision for the current 64bit or 32bit record block. Also,
1615 1613 * setting the flag for whether or not it is a 32bit record.
1616 1614 */
1617 1615 is_32bit_record = 0;
1618 1616 switch (rbp_32->rb_revision) {
1619 1617 case MDDB_REV_RB:
1620 1618 case MDDB_REV_RBFN:
1621 1619 is_32bit_record = 1;
1622 1620 break;
1623 1621 case MDDB_REV_RB64:
1624 1622 case MDDB_REV_RB64FN:
1625 1623 break;
1626 1624 default:
1627 1625 rval = -1;
1628 1626 (void) mdmddberror(ep, MDE_DB_NODB, 0, 0, 0, NULL);
1629 1627 goto out;
1630 1628 }
1631 1629
1632 1630 /*
1633 1631 * Calculating the checksum for this record block. Need
1634 1632 * to skip the rb's checksum fiddle.
1635 1633 */
1636 1634 skip = (crc_skip_t *)Malloc(sizeof (crc_skip_t));
1637 1635 skip->skip_next = NULL;
1638 1636 skip->skip_offset = offsetof(mddb_rb_t, rb_checksum_fiddle);
1639 1637 skip->skip_size = 3 * sizeof (uint_t);
1640 1638 if (crcchk(rbp_32, &rbp_32->rb_checksum, dep->de_recsize, skip)) {
1641 1639 rval = -1;
1642 1640 (void) mdmddberror(ep, MDE_DB_NODB, 0, 0, 0, NULL);
1643 1641 goto out;
1644 1642 }
1645 1643
1646 1644 /* mddb_rb_t and mddb_rb32_t differ before the rb_timestamp field */
1647 1645 if (!is_32bit_record) {
1648 1646 if ((*lastaccess).tv_sec < rbp_32->rb_timestamp.tv_sec) {
1649 1647 *lastaccess = rbp_32->rb_timestamp;
1650 1648 } else if ((*lastaccess).tv_sec ==
1651 1649 rbp_32->rb_timestamp.tv_sec) {
1652 1650 if ((*lastaccess).tv_usec <
1653 1651 rbp_32->rb_timestamp.tv_usec)
1654 1652 *lastaccess = rbp_32->rb_timestamp;
1655 1653 }
1656 1654 } else {
1657 1655 rbp_64 = (mddb_rb_t *)rbp;
1658 1656 if ((*lastaccess).tv_sec < rbp_64->rb_timestamp.tv_sec) {
1659 1657 *lastaccess = rbp_64->rb_timestamp;
1660 1658 } else if ((*lastaccess).tv_sec ==
1661 1659 rbp_64->rb_timestamp.tv_sec) {
1662 1660 if ((*lastaccess).tv_usec <
1663 1661 rbp_64->rb_timestamp.tv_usec)
1664 1662 *lastaccess = rbp_64->rb_timestamp;
1665 1663 }
1666 1664 }
1667 1665
1668 1666 /* Populates the fields in md_im_rec_t *tmp_mdrec. */
1669 1667 rval = extract_mduser_data(nm, tmp_mdrec, rbp, is_32bit_record, ep);
1670 1668 if (rval < 0)
1671 1669 goto out;
1672 1670
1673 1671 /* Adding record to the head of the list of all metadevices. */
1674 1672 tmp_mdrec->prev = NULL;
1675 1673 if (*mdimpp == NULL) {
1676 1674 tmp_mdrec->next = NULL;
1677 1675 *mdimpp = tmp_mdrec;
1678 1676 } else {
1679 1677 (*mdimpp)->prev = tmp_mdrec;
1680 1678 tmp_mdrec->next = *mdimpp;
1681 1679 *mdimpp = tmp_mdrec;
1682 1680 }
1683 1681
1684 1682 out:
1685 1683 /* Free the skip list */
1686 1684 while (skip) {
1687 1685 crc_skip_t *skip_rm = skip;
1688 1686
1689 1687 skip = skip->skip_next;
1690 1688 Free(skip_rm);
1691 1689 }
1692 1690
1693 1691 if (rbp)
1694 1692 Free(rbp);
1695 1693
1696 1694 return (rval);
1697 1695 }
1698 1696
1699 1697
1700 1698 /*
1701 1699 * read_all_mdrecords()
1702 1700 *
1703 1701 * Reads the directory block and directory entries.
1704 1702 * Runs magic, checksum, and revision checks on the directory block.
1705 1703 *
1706 1704 * Returns:
1707 1705 * < 0 for failure
1708 1706 * 0 for success
1709 1707 */
1710 1708 static int
1711 1709 read_all_mdrecords(
1712 1710 md_im_rec_t **mdimpp,
1713 1711 mddb_mb_t *mbp,
1714 1712 mddb_lb_t *lbp,
1715 1713 mddb_rb_t *nm,
1716 1714 mdname_t *rsp,
1717 1715 int fd,
1718 1716 md_timeval32_t *lastaccess,
1719 1717 md_error_t *ep
1720 1718 )
1721 1719 {
1722 1720 int dbblk, rval = 0;
1723 1721 char db[DEV_BSIZE];
1724 1722 mddb_de_t *dep;
1725 1723 int desize;
1726 1724 /*LINTED*/
1727 1725 mddb_db_t *dbp = (mddb_db_t *)&db;
1728 1726
1729 1727 /* Read in all directory blocks */
1730 1728 for (dbblk = lbp->lb_dbfirstblk;
1731 1729 dbblk != 0;
1732 1730 dbblk = dbp->db_nextblk) {
1733 1731
1734 1732 if ((rval = read_database_block(ep, fd, mbp, dbblk,
1735 1733 dbp, sizeof (db))) <= 0)
1736 1734 goto out;
1737 1735
1738 1736 /*
1739 1737 * Set ep with error code for MDE_DB_NODB. This is the
1740 1738 * error code used in the kernel when there is a problem
1741 1739 * with reading records in. Checks the magic number, the
1742 1740 * revision, and the checksum for each directory block.
1743 1741 */
1744 1742 if (dbp->db_magic != MDDB_MAGIC_DB) {
1745 1743 rval = -1;
1746 1744 (void) mdmddberror(ep, MDE_DB_NODB, 0, 0, 0, NULL);
1747 1745 goto out;
1748 1746 }
1749 1747
1750 1748 if (revchk(MDDB_REV_DB, dbp->db_revision)) {
1751 1749 rval = -1;
1752 1750 (void) mdmddberror(ep, MDE_DB_NODB, 0, 0, 0, NULL);
1753 1751 goto out;
1754 1752 }
1755 1753
1756 1754 if (crcchk(dbp, &dbp->db_checksum, MDDB_BSIZE, NULL)) {
1757 1755 rval = -1;
1758 1756 (void) mdmddberror(ep, MDE_DB_NODB, 0, 0, 0, NULL);
1759 1757 goto out;
1760 1758 }
1761 1759
1762 1760 /*
1763 1761 * If db timestamp is more recent than the previously recorded
1764 1762 * last modified timestamp, then update last modified.
1765 1763 */
1766 1764 if ((*lastaccess).tv_sec < dbp->db_timestamp.tv_sec) {
1767 1765 *lastaccess = dbp->db_timestamp;
1768 1766 } else if ((*lastaccess).tv_sec == dbp->db_timestamp.tv_sec) {
1769 1767 if ((*lastaccess).tv_usec < dbp->db_timestamp.tv_usec)
1770 1768 *lastaccess = dbp->db_timestamp;
1771 1769 }
1772 1770
1773 1771 /* Creates dep list of all directory entries in the db */
1774 1772 if (dbp->db_firstentry != NULL) {
1775 1773 /* LINTED */
1776 1774 dep = (mddb_de_t *)((caddr_t)(&dbp->db_firstentry)
1777 1775 + sizeof (dbp->db_firstentry));
1778 1776 dbp->db_firstentry = dep;
1779 1777 while (dep && dep->de_next) {
1780 1778 desize = sizeof (*dep) -
1781 1779 sizeof (dep->de_blks) +
1782 1780 sizeof (daddr_t) * dep->de_blkcount;
1783 1781 /* LINTED */
1784 1782 dep->de_next = (mddb_de_t *)
1785 1783 ((caddr_t)dep + desize);
1786 1784 dep = dep->de_next;
1787 1785 }
1788 1786 }
1789 1787
1790 1788 /*
1791 1789 * Process all directory entries in the directory block.
1792 1790 * For each directory entry, read_mdrec is called to read
1793 1791 * in the record data.
1794 1792 */
1795 1793 for (dep = dbp->db_firstentry; dep != NULL;
1796 1794 dep = dep->de_next) {
1797 1795
1798 1796 /*
1799 1797 * de_flags is set to the type of metadevice.
1800 1798 * If directory entry does not correspond to a
1801 1799 * specific metadevice then it is set to zero.
1802 1800 * All namespace records(NM, SHR_NM, DID_SHR_NM) have a
1803 1801 * value of zero in their de_flags field.
1804 1802 */
1805 1803 if ((dep->de_flags != 0)&&
1806 1804 (dep->de_flags != MDDB_F_OPT) &&
1807 1805 (dep->de_flags != MDDB_F_TRANS_LOG) &&
1808 1806 (dep->de_flags != MDDB_F_CHANGELOG)) {
1809 1807 rval = read_mdrecord(mdimpp, mbp, nm, dep,
1810 1808 rsp->cname, fd, lastaccess, ep);
1811 1809 if (rval < 0)
1812 1810 goto out;
1813 1811 }
1814 1812 }
1815 1813 }
1816 1814
1817 1815 out:
1818 1816 return (rval);
1819 1817 }
1820 1818
1821 1819
1822 1820 /*
1823 1821 * report_metastat_info()
1824 1822 *
1825 1823 * Generates the metastat -c output. Also, updates the global variable
1826 1824 * for a last accessed timestamp.
1827 1825 *
1828 1826 * Returns:
1829 1827 * < 0 for failure
1830 1828 * 0 for success
1831 1829 *
1832 1830 */
1833 1831 int
1834 1832 report_metastat_info(
1835 1833 mddb_mb_t *mb,
1836 1834 mddb_lb_t *lbp,
1837 1835 mddb_rb_t *nm,
1838 1836 pnm_rec_t **pnm,
1839 1837 mdname_t *rsp,
1840 1838 int fd,
1841 1839 md_timeval32_t *lastaccess,
1842 1840 md_error_t *ep
1843 1841 )
1844 1842 {
1845 1843 int rval = 0;
1846 1844 /* list of all metadevices in diskset */
1847 1845 md_im_rec_t *mdimp = NULL;
1848 1846 md_im_rec_t *tmp_mdrec, *rm_mdrec;
1849 1847
1850 1848 /* Read in metadevice records and add entries to mdimp list. */
1851 1849 rval = read_all_mdrecords(&mdimp, mb, lbp, nm, rsp, fd, lastaccess,
1852 1850 ep);
1853 1851 if (rval < 0)
1854 1852 goto out;
1855 1853
1856 1854 /* Adding a fake record to the head of the list of all metadevices. */
1857 1855 if (mdimp != NULL) {
1858 1856 tmp_mdrec = Zalloc(sizeof (md_im_rec_t));
1859 1857 tmp_mdrec->prev = NULL;
1860 1858 mdimp->prev = tmp_mdrec;
1861 1859 tmp_mdrec->next = mdimp;
1862 1860 mdimp = tmp_mdrec;
1863 1861 }
1864 1862
1865 1863 /* Calling functions to process all metadevices on mdimp list */
1866 1864 process_toplevel_devices(&mdimp, *pnm, MDDB_F_SOFTPART);
1867 1865 process_toplevel_devices(&mdimp, *pnm, MDDB_F_TRANS_MASTER);
1868 1866 process_toplevel_devices(&mdimp, *pnm, MDDB_F_MIRROR);
1869 1867 process_toplevel_devices(&mdimp, *pnm, MDDB_F_RAID);
1870 1868 process_toplevel_devices(&mdimp, *pnm, MDDB_F_STRIPE);
1871 1869 process_toplevel_devices(&mdimp, *pnm, MDDB_F_HOTSPARE_POOL);
1872 1870 (void) printf("\n");
1873 1871
1874 1872 out:
1875 1873 /*
1876 1874 * If mdreclist is not null, then this will walk through all
1877 1875 * elements and free them.
1878 1876 */
1879 1877 tmp_mdrec = mdimp;
1880 1878 while (tmp_mdrec != NULL) {
1881 1879 rm_mdrec = tmp_mdrec;
1882 1880 tmp_mdrec = tmp_mdrec->next;
1883 1881 if (rm_mdrec->record != NULL)
1884 1882 Free(rm_mdrec->record);
1885 1883 if (rm_mdrec->n_name != NULL)
1886 1884 Free(rm_mdrec->n_name);
1887 1885 Free(rm_mdrec);
1888 1886 }
1889 1887
1890 1888 free_pnm_rec_list(pnm);
1891 1889 return (rval);
1892 1890 }
↓ open down ↓ |
1718 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX