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