xref: /onnv-gate/usr/src/lib/lvm/libmeta/common/meta_statconcise.c (revision 1623:7bac4a816ebe)
1734Smw145384 /*
2734Smw145384  * CDDL HEADER START
3734Smw145384  *
4734Smw145384  * The contents of this file are subject to the terms of the
5*1623Stw21770  * Common Development and Distribution License (the "License").
6*1623Stw21770  * You may not use this file except in compliance with the License.
7734Smw145384  *
8734Smw145384  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9734Smw145384  * or http://www.opensolaris.org/os/licensing.
10734Smw145384  * See the License for the specific language governing permissions
11734Smw145384  * and limitations under the License.
12734Smw145384  *
13734Smw145384  * When distributing Covered Code, include this CDDL HEADER in each
14734Smw145384  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15734Smw145384  * If applicable, add the following below this CDDL HEADER, with the
16734Smw145384  * fields enclosed by brackets "[]" replaced with your own identifying
17734Smw145384  * information: Portions Copyright [yyyy] [name of copyright owner]
18734Smw145384  *
19734Smw145384  * CDDL HEADER END
20734Smw145384  */
21734Smw145384 /*
22*1623Stw21770  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23734Smw145384  * Use is subject to license terms.
24734Smw145384  */
25734Smw145384 
26734Smw145384 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27734Smw145384 
28734Smw145384 #include <meta.h>
29734Smw145384 #include <assert.h>
30734Smw145384 #include <ctype.h>
31734Smw145384 #include <mdiox.h>
32734Smw145384 #include <meta.h>
33734Smw145384 #include <stdio.h>
34734Smw145384 #include <stdlib.h>
35734Smw145384 #include <strings.h>
36734Smw145384 #include <sys/lvm/md_mddb.h>
37734Smw145384 #include <sys/lvm/md_names.h>
38734Smw145384 #include <sys/lvm/md_crc.h>
39734Smw145384 #include <sys/lvm/md_convert.h>
40734Smw145384 
41734Smw145384 
42734Smw145384 /*
43734Smw145384  * Design Notes:
44734Smw145384  *
45734Smw145384  * All of the code in this file supports the addition of metastat -c output
46734Smw145384  * for the verbose option of metaimport.  Some of this code is also used by
47734Smw145384  * the command metastat for concise output(cmd/lvm/util/metastat.c).
48734Smw145384  * The code is designed to produce the same output as metastat -c does for a
49734Smw145384  * given diskset--with a couple exceptions.
50734Smw145384  * The primary differences between the output for the metastat -c command and
51734Smw145384  * metastat output for metaimport -v are:
52734Smw145384  *  - the set name is not printed next to each metadevice
53734Smw145384  *  - top-level state information is not printed for some metadevices
54734Smw145384  *  - the percent that a disk has completed resyncing is not listed
55734Smw145384  * in metaimport -v.
56734Smw145384  *
57734Smw145384  *
58734Smw145384  * The general layout of this file is as follows:
59734Smw145384  *
60734Smw145384  *  - report_metastat_info()
61734Smw145384  *	This is the primary entry point for the functions in this file, with
62734Smw145384  *	the exception of several functions that are also called from
63734Smw145384  *	cmd/io/lvm/util/metastat.c
64734Smw145384  *	report_metastat_info() calls functions to read in all the the
65734Smw145384  *	Directory blocks and Record blocks and then process the information
66734Smw145384  *	needed to print out the metadevice records in the same format as
67734Smw145384  *	metastat -c.
68734Smw145384  *
69734Smw145384  *  - read_all_mdrecords()
70734Smw145384  *	Reads in all the Directory blocks in the diskset and verifies their
71734Smw145384  *	validity.  For each Directly block, it loops through all Directory
72734Smw145384  *	Entries and for each one that contains a metadevice record calls
73734Smw145384  *	read_md_record().  Because the output is designed to imitate the
74734Smw145384  *	output of metastat -c, we ignore metadevice records for
75734Smw145384  *	optimized resync, changelog, and translog.
76734Smw145384  *
77734Smw145384  *  - read_md_record()
78734Smw145384  *	Reads in a Directory Entry and its associated Record block.  The
79734Smw145384  *	revision information for the Record block is checked and it is
80734Smw145384  *	determined whether or not it is a 64bit Record block or a 32bit record
81734Smw145384  *	block.  For each valid Record block, it allocates an md_im_rec_t
82734Smw145384  *	structure and calls extract_mduser_data().
83734Smw145384  *
84734Smw145384  *  - extract_mduser_data()
85734Smw145384  *	Populates the md_im_rec_t data structure with information about the
86734Smw145384  *	record's associated metadevice.  Also, the name of the metadevice is
87734Smw145384  *	either copied from the NM namespace(if it exists there) or is generated
88734Smw145384  *	from the record's un_self_id.
89734Smw145384  *
90734Smw145384  *  - process_toplevel_devices()
91734Smw145384  *	For a given metadevice type, searchs through the md_im_rec_t **mdimpp,
92734Smw145384  *	list of all metadevices in the set, to find all records of the
93734Smw145384  *	specified type that do not have a parent and puts them on a temp list.
94734Smw145384  *	The temp list is then iterated through and the associated processing
95734Smw145384  *	function is called.
96734Smw145384  *
97734Smw145384  *  - process_(trans, hotspare, hotspare_pool, soft_part, mirror, stripe, raid)
98734Smw145384  *	These functions are called by using the dfunc field in the mdimpp list.
99734Smw145384  *	Each process function only understands its own type of metadevice. Once
100734Smw145384  *	it processes the metadevice it was called for, it then loops through
101734Smw145384  *	all of the underlying metadevices.  After printing the name of the
102734Smw145384  *	underlying metadevice, it puts in on a list to be processed.  If the
103734Smw145384  *	underlying device is a physical device, then print_physical_device is
104734Smw145384  *	called.
105734Smw145384  *	Once all information about the original metadevice is processed, it
106734Smw145384  *	loops through the list of underlying metadevices and calls the
107734Smw145384  *	appropriate function to process them.
108734Smw145384  *
109734Smw145384  *  - process_toplevel_softparts()
110734Smw145384  *	To match the output for metastat -c, all top-level softpartions
111734Smw145384  *	are printed out in groups based on their underlying metadevice--so that
112734Smw145384  *	the underlying metadevice only needs to be processed once.
113734Smw145384  *
114734Smw145384  *  - meta_get_(sm_state, raid_col_state, stripe_state, hs_state)
115734Smw145384  *	These functions are used to retrieve the metadevice state information.
116734Smw145384  *	They are also used by the metastat concise routines in
117734Smw145384  *	cmd/lvm/util/metastat.c.
118734Smw145384  *
119734Smw145384  */
120734Smw145384 
121734Smw145384 
122734Smw145384 /*
123734Smw145384  * md_im_rec is a doubly linked list used to store the rb_data for each
124734Smw145384  * directory entry that corresponds to a metadevice.
125734Smw145384  * n_key: is set, if there is an associated entry in the NM namespace.
126734Smw145384  * dfunc: is set to point to the function that processes the particular
127734Smw145384  * metadevice associated with the record.
128734Smw145384  * hs_record_id: is only set, if the metadevice is a hotspare.
129734Smw145384  * un_self_id: is set for all other records. This is also used to generate
130734Smw145384  * the name of the metadevice if there is no entry for the metadevice in
131734Smw145384  * the NM namespace--n_key is not set.
132734Smw145384  */
133734Smw145384 typedef struct md_im_rec {
134734Smw145384 	mdkey_t			n_key; /* NM namespace key */
135734Smw145384 	struct md_im_rec 	*next;
136734Smw145384 	struct md_im_rec 	*prev;
137734Smw145384 	uint_t			md_type;
138734Smw145384 	uint_t			has_parent; /* either 0(no parent) or 1 */
139734Smw145384 	minor_t			un_self_id;
140734Smw145384 	mddb_recid_t		hs_record_id; /* hotspare recid */
141734Smw145384 	char 			*n_name;  /* name of metadevice */
142734Smw145384 	void 			(*dfunc) ();
143734Smw145384 	ushort_t		record_len;
144734Smw145384 	/* pointer to the unit structure for the metadevice, e.g. rb_data[0] */
145734Smw145384 	void			*record;
146734Smw145384 } md_im_rec_t;
147734Smw145384 
148734Smw145384 /*
149734Smw145384  * md_im_list is used to group toplevel metadevices by type and to group
150734Smw145384  * the underlying devices for a particular metadevice.
151734Smw145384  */
152734Smw145384 typedef struct md_im_list {
153734Smw145384 	struct md_im_list	*next;
154734Smw145384 	struct md_im_rec 	*mdrec;
155734Smw145384 } md_im_list_t;
156734Smw145384 
157734Smw145384 
158734Smw145384 /*
159734Smw145384  * MAXSIZEMDRECNAME is the value that has historically been used to allocate
160734Smw145384  * space for the metadevice name
161734Smw145384  */
162734Smw145384 #define	MAXSIZEMDRECNAME	20
163734Smw145384 #define	NAMEWIDTH		16
164734Smw145384 #define	offsetof(s, m)	((size_t)(&(((s *)0)->m)))
165734Smw145384 #define	NOT_PHYSICAL_DEV	0
166734Smw145384 #define	PHYSICAL_DEV		1
167734Smw145384 
168734Smw145384 
169734Smw145384 /*
170734Smw145384  * strip_blacks()
171734Smw145384  *
172734Smw145384  * Strip blanks from string.  Used for size field in concise output.
173734Smw145384  */
174734Smw145384 static char *
strip_blanks(char * s)175734Smw145384 strip_blanks(char *s)
176734Smw145384 {
177734Smw145384 	char *p;
178734Smw145384 
179734Smw145384 	for (p = s; *p; ) {
180734Smw145384 		if (*p == ' ') {
181734Smw145384 			char *t;
182734Smw145384 			for (t = p; *t; t++) {
183734Smw145384 				*t = *(t + 1);
184734Smw145384 			}
185734Smw145384 		} else {
186734Smw145384 			p++;
187734Smw145384 		}
188734Smw145384 	}
189734Smw145384 
190734Smw145384 	return (s);
191734Smw145384 }
192734Smw145384 
193734Smw145384 
194734Smw145384 /*
195734Smw145384  * print_concise_entry()
196734Smw145384  *
197734Smw145384  * Print properly indented metadevice name, type and size for concise output.
198734Smw145384  * This function is also called from: cmd/lvm/util/metastat.c.
199734Smw145384  */
200734Smw145384 void
print_concise_entry(int indent,char * name,diskaddr_t size,char mtype)201734Smw145384 print_concise_entry(int indent, char *name, diskaddr_t size, char mtype)
202734Smw145384 {
203734Smw145384 	int	i;
204734Smw145384 	int	width = NAMEWIDTH;	/* minumum field width for name */
205734Smw145384 	char	in[MAXPATHLEN];
206734Smw145384 	char	*sz;
207734Smw145384 
208734Smw145384 	in[0] = 0;
209734Smw145384 	for (i = 0; i < indent; i++)
210734Smw145384 		(void) strlcat(in, " ", sizeof (in));
211734Smw145384 
212734Smw145384 	/* set up minimum field width. negative for left justified */
213734Smw145384 	width -= indent;
214734Smw145384 	if (width < 0)
215734Smw145384 		width = 0;	/* overflowed; no minimum field needed */
216734Smw145384 	else
217734Smw145384 		width = 0 - width; /* negative for left justification */
218734Smw145384 
219734Smw145384 	if (size == 0) {
220734Smw145384 		sz = "-";
221734Smw145384 	} else {
222734Smw145384 		sz = strip_blanks(meta_number_to_string(size, DEV_BSIZE));
223734Smw145384 	}
224734Smw145384 
225734Smw145384 	(void) printf("%s%*s %c %6s", in, width, name, mtype, sz);
226734Smw145384 }
227734Smw145384 
228734Smw145384 
229734Smw145384 /*
230734Smw145384  * free_mdrec_list_entry()
231734Smw145384  *
232734Smw145384  * Removing entry from the list of metadevices in the diskset(mdimpp).
233734Smw145384  * This function will not remove the dummy entry at the head of the
234734Smw145384  * list, so we don't have to set mdrec equal to NULL.
235734Smw145384  */
236734Smw145384 static void
free_mdrec_list_entry(md_im_rec_t ** mdrec)237734Smw145384 free_mdrec_list_entry(md_im_rec_t  **mdrec)
238734Smw145384 {
239734Smw145384 	(*mdrec)->prev->next = (*mdrec)->next;
240734Smw145384 	if ((*mdrec)->next != NULL) {
241734Smw145384 		(*mdrec)->next->prev = (*mdrec)->prev;
242734Smw145384 	}
243734Smw145384 	Free((*mdrec)->record);
244734Smw145384 	Free((*mdrec)->n_name);
245734Smw145384 	Free(*mdrec);
246734Smw145384 }
247734Smw145384 
248734Smw145384 
249734Smw145384 /*
250734Smw145384  * ucomponent_append()
251734Smw145384  *
252734Smw145384  * Appending entry to the underlying component list.  The list
253734Smw145384  * is used to group all of the underlying devices before
254734Smw145384  * processing them.
255734Smw145384  */
256734Smw145384 static void
ucomponent_append(md_im_list_t ** ucomp_head,md_im_list_t ** ucomp_tail,md_im_list_t * ucomp)257734Smw145384 ucomponent_append(
258734Smw145384 	md_im_list_t	**ucomp_head,
259734Smw145384 	md_im_list_t	**ucomp_tail,
260734Smw145384 	md_im_list_t	*ucomp
261734Smw145384 )
262734Smw145384 {
263734Smw145384 	ucomp->next = NULL;
264734Smw145384 	if (*ucomp_head == NULL) {
265734Smw145384 		*ucomp_head = ucomp;
266734Smw145384 		*ucomp_tail = ucomp;
267734Smw145384 	} else {
268734Smw145384 		(*ucomp_tail)->next = ucomp;
269734Smw145384 		*ucomp_tail = (*ucomp_tail)->next;
270734Smw145384 	}
271734Smw145384 }
272734Smw145384 
273734Smw145384 
274734Smw145384 /*
275734Smw145384  * free_md_im_list_entries()
276734Smw145384  *
277734Smw145384  * Freeing entries on an md_im_list_t.  This list is used to group
278734Smw145384  * underlying components for processing and to group top-level metadevices
279734Smw145384  * by type.
280734Smw145384  */
281734Smw145384 static void
free_md_im_list_entries(md_im_list_t ** list_head)282734Smw145384 free_md_im_list_entries(md_im_list_t **list_head)
283734Smw145384 {
284734Smw145384 	md_im_list_t	*tmp_list_entry = *list_head;
285734Smw145384 	md_im_list_t	*rm_list_entry;
286734Smw145384 
287734Smw145384 	while (tmp_list_entry != NULL) {
288734Smw145384 		rm_list_entry = tmp_list_entry;
289734Smw145384 		tmp_list_entry = tmp_list_entry->next;
290734Smw145384 		Free(rm_list_entry);
291734Smw145384 	}
292734Smw145384 }
293734Smw145384 
294734Smw145384 
295734Smw145384 /*
296734Smw145384  * print_physical_device()
297734Smw145384  *
298734Smw145384  * If a metadevice has an underlying component that is a physical
299734Smw145384  * device, then this searches the pnm_rec_t list to match an entry's
300734Smw145384  * n_key to the key for the underlying component.  The ctd name of the
301734Smw145384  * physical device is printed on the same line as the metadevice.
302734Smw145384  */
303734Smw145384 static void
print_physical_device(pnm_rec_t * phys_nm,mdkey_t key)304734Smw145384 print_physical_device(
305734Smw145384 	pnm_rec_t	*phys_nm,
306734Smw145384 	mdkey_t		key
307734Smw145384 )
308734Smw145384 {
309734Smw145384 	pnm_rec_t	*tmpphys_nm;
310734Smw145384 
311734Smw145384 	for (tmpphys_nm = phys_nm; tmpphys_nm != NULL;
312734Smw145384 	    tmpphys_nm = tmpphys_nm->next) {
313734Smw145384 		if (tmpphys_nm->n_key == key) {
314734Smw145384 			(void) printf(" %s", tmpphys_nm->n_name);
315734Smw145384 			break;
316734Smw145384 		}
317734Smw145384 	}
318734Smw145384 }
319734Smw145384 
320734Smw145384 
321734Smw145384 /*
322734Smw145384  * get_stripe_req_size()
323734Smw145384  *
324734Smw145384  * Given a 64bit stripe unit, compute the size of the stripe unit.
325734Smw145384  * This function is a derivation of:
326734Smw145384  *	common/lvm/md_convert.c:get_big_stripe_req_size()
327734Smw145384  * and any changes made to either this function or get_big_stripe_req_size()
328734Smw145384  * should be reviewed to make sure the functionality in both places is correct.
329734Smw145384  *
330734Smw145384  * Returns:
331734Smw145384  *	total size of the 64bit stripe
332734Smw145384  */
333734Smw145384 size_t
get_stripe_req_size(ms_unit_t * un)334734Smw145384 get_stripe_req_size(ms_unit_t *un)
335734Smw145384 {
336734Smw145384 	struct ms_row *mdr;
337734Smw145384 	uint_t row;
338734Smw145384 	uint_t ncomps = 0;
339734Smw145384 	size_t mdsize = 0;
340734Smw145384 	size_t first_comp = 0;
341734Smw145384 
342734Smw145384 
343734Smw145384 	/* Compute the offset of the first component */
344734Smw145384 	first_comp = sizeof (ms_unit_t) +
345734Smw145384 	    sizeof (struct ms_row) * (un->un_nrows - 1);
346734Smw145384 	first_comp = roundup(first_comp, sizeof (long long));
347734Smw145384 
348734Smw145384 	/*
349734Smw145384 	 * Requestor wants to have the total size, add the sizes of
350734Smw145384 	 * all components
351734Smw145384 	 */
352734Smw145384 	mdr = &un->un_row[0];
353734Smw145384 	for (row = 0; (row < un->un_nrows); row++)
354734Smw145384 	    ncomps += mdr[row].un_ncomp;
355734Smw145384 	mdsize = first_comp + sizeof (ms_comp_t) * ncomps;
356734Smw145384 	return (mdsize);
357734Smw145384 }
358734Smw145384 
359734Smw145384 
360734Smw145384 /*
361734Smw145384  * meta_get_sm_state()
362734Smw145384  *
363734Smw145384  * Gets the state for the underlying components(submirrors) of a mirror.
364734Smw145384  * This function is also called from: cmd/lvm/util/metastat.c.
365734Smw145384  *
366734Smw145384  * Returns:
367734Smw145384  *	string for state of the sub-mirror
368734Smw145384  */
369734Smw145384 static char *
meta_get_sm_state(sm_state_t state)370734Smw145384 meta_get_sm_state(
371734Smw145384 	sm_state_t	state
372734Smw145384 )
373734Smw145384 {
374734Smw145384 	/* all is well */
375734Smw145384 	if (state & SMS_RUNNING) {
376734Smw145384 		return (NULL);
377734Smw145384 	}
378734Smw145384 
379734Smw145384 	/* resyncing, needs repair */
380734Smw145384 	if ((state & (SMS_COMP_RESYNC | SMS_ATTACHED_RESYNC |
381734Smw145384 	    SMS_OFFLINE_RESYNC))) {
382734Smw145384 		return (gettext("resyncing"));
383734Smw145384 	}
384734Smw145384 
385734Smw145384 	/* needs repair */
386734Smw145384 	if (state & (SMS_COMP_ERRED | SMS_ATTACHED | SMS_OFFLINE))
387734Smw145384 		return (gettext("maint"));
388734Smw145384 
389734Smw145384 	/* unknown */
390734Smw145384 	return (gettext("unknown"));
391734Smw145384 }
392734Smw145384 
393734Smw145384 
394734Smw145384 /*
395734Smw145384  * meta_get_raid_col_state()
396734Smw145384  *
397734Smw145384  * Gets the state for the underlying components(columns) of a raid.
398734Smw145384  * This function is also called from: cmd/lvm/util/metastat.c.
399734Smw145384  *
400734Smw145384  * Returns:
401734Smw145384  *	string for state of the raid column
402734Smw145384  *
403734Smw145384  */
404734Smw145384 char *
meta_get_raid_col_state(rcs_state_t state)405734Smw145384 meta_get_raid_col_state(
406734Smw145384 	rcs_state_t	state
407734Smw145384 )
408734Smw145384 {
409734Smw145384 	switch (state) {
410734Smw145384 		case RCS_INIT:
411734Smw145384 			return (gettext("initializing"));
412734Smw145384 		case RCS_OKAY:
413734Smw145384 			return (NULL);
414734Smw145384 		case RCS_INIT_ERRED:
415734Smw145384 			/*FALLTHROUGH*/
416734Smw145384 		case RCS_ERRED:
417734Smw145384 			return (gettext("maint"));
418734Smw145384 		case RCS_LAST_ERRED:
419734Smw145384 			return (gettext("last-erred"));
420734Smw145384 		case RCS_RESYNC:
421734Smw145384 			return (gettext("resyncing"));
422734Smw145384 		default:
423734Smw145384 			return (gettext("unknown"));
424734Smw145384 	}
425734Smw145384 }
426734Smw145384 
427734Smw145384 
428734Smw145384 /*
429734Smw145384  * meta_get_stripe_state()
430734Smw145384  *
431734Smw145384  * Gets the state for the underlying components of a stripe.
432734Smw145384  * This function is also called from: cmd/lvm/util/metastat.c.
433734Smw145384  *
434734Smw145384  * Returns:
435734Smw145384  *	string for state of the stripe
436734Smw145384  *
437734Smw145384  */
438734Smw145384 char *
meta_get_stripe_state(comp_state_t state)439734Smw145384 meta_get_stripe_state(
440734Smw145384 	comp_state_t	state
441734Smw145384 )
442734Smw145384 {
443734Smw145384 	switch (state) {
444734Smw145384 		case CS_OKAY:
445734Smw145384 			return (NULL);
446734Smw145384 		case CS_ERRED:
447734Smw145384 			return (gettext("maint"));
448734Smw145384 		case CS_LAST_ERRED:
449734Smw145384 			return (gettext("last-erred"));
450734Smw145384 		case CS_RESYNC:
451734Smw145384 			return (gettext("resyncing"));
452734Smw145384 		default:
453734Smw145384 			return (gettext("invalid"));
454734Smw145384 	}
455734Smw145384 }
456734Smw145384 
457734Smw145384 
458734Smw145384 /*
459734Smw145384  * meta_get_hs_state()
460734Smw145384  *
461734Smw145384  * Gets the state for the underlying components(hotspares) of a hotspare pool.
462734Smw145384  * This function is also called from: cmd/lvm/util/metastat.c.
463734Smw145384  *
464734Smw145384  * Returns:
465734Smw145384  *	string for state of the hotspare
466734Smw145384  *
467734Smw145384  */
468734Smw145384 char *
meta_get_hs_state(hotspare_states_t state)469734Smw145384 meta_get_hs_state(
470734Smw145384 	hotspare_states_t	state
471734Smw145384 )
472734Smw145384 {
473734Smw145384 	switch (state) {
474734Smw145384 		case HSS_AVAILABLE:
475734Smw145384 			return (NULL);
476734Smw145384 		case HSS_RESERVED:
477734Smw145384 			return (gettext("in-use"));
478734Smw145384 		case HSS_BROKEN:
479734Smw145384 			return (gettext("broken"));
480734Smw145384 		case HSS_UNUSED:
481734Smw145384 			/* FALLTHROUGH */
482734Smw145384 		default:
483734Smw145384 			return (gettext("invalid"));
484734Smw145384 	}
485734Smw145384 }
486734Smw145384 
487734Smw145384 
488734Smw145384 /*
489734Smw145384  * process_trans()
490734Smw145384  *
491734Smw145384  * Prints unit information for a trans metadevice and calls the respective
492734Smw145384  * functions to process the underlying metadevices.
493734Smw145384  *
494734Smw145384  */
495734Smw145384 static void
process_trans(md_im_rec_t ** mdimpp,int indent,pnm_rec_t * phys_nm,md_im_rec_t * mdrec)496734Smw145384 process_trans(
497734Smw145384 	md_im_rec_t	**mdimpp,
498734Smw145384 	int		indent,
499734Smw145384 	pnm_rec_t	*phys_nm,
500734Smw145384 	md_im_rec_t	*mdrec
501734Smw145384 )
502734Smw145384 {
503734Smw145384 	mt_unit_t	*mt;
504734Smw145384 	mdc_unit_t	uc;
505734Smw145384 	md_im_rec_t	*tmpmdrec;
506734Smw145384 	int		underlying_device = PHYSICAL_DEV;
507734Smw145384 
508734Smw145384 	mt = (mt_unit_t *)mdrec->record;
509734Smw145384 	uc = mt->c;
510734Smw145384 
511734Smw145384 	/* Printing name, size, and type of metadevice */
512734Smw145384 	print_concise_entry(indent, mdrec->n_name,
513734Smw145384 	    uc.un_total_blocks, 't');
514734Smw145384 
515734Smw145384 	/*
516734Smw145384 	 * Loops through md_im_rec_t **mdimpp list of all metadevices to find
517734Smw145384 	 * record that matches the underlying device.
518734Smw145384 	 * Trans devices can only have one underlying device, so once a
519734Smw145384 	 * match is found, we are done.
520734Smw145384 	 */
521734Smw145384 	for (tmpmdrec = *mdimpp; tmpmdrec != NULL;
522734Smw145384 	    tmpmdrec = tmpmdrec->next) {
523734Smw145384 		if (tmpmdrec->n_key == mt->un_m_key) {
524734Smw145384 			/* Printing name of the underlying metadevice */
525734Smw145384 			(void) printf(" %s", tmpmdrec->n_name);
526734Smw145384 			underlying_device = NOT_PHYSICAL_DEV;
527734Smw145384 			break;
528734Smw145384 		}
529734Smw145384 	}
530734Smw145384 
531734Smw145384 	/*
532734Smw145384 	 * If a metadevice was not found, then the underlying device must be a
533734Smw145384 	 * physical device.  Otherwise, call the functions to process the
534734Smw145384 	 * underlying devices.
535734Smw145384 	 */
536734Smw145384 	if (underlying_device == PHYSICAL_DEV) {
537734Smw145384 		print_physical_device(phys_nm, mt->un_m_key);
538734Smw145384 		(void) printf("\n");
539734Smw145384 	} else {
540734Smw145384 		/* process underlying component */
541734Smw145384 		(void) printf("\n");
542734Smw145384 		indent += META_INDENT;
543734Smw145384 		tmpmdrec->dfunc(mdimpp, indent, phys_nm, tmpmdrec);
544734Smw145384 	}
545734Smw145384 
546734Smw145384 	/*
547734Smw145384 	 * Removing the md_entry from the list
548734Smw145384 	 * of all metadevices
549734Smw145384 	 */
550734Smw145384 	free_mdrec_list_entry(&mdrec);
551734Smw145384 }
552734Smw145384 
553734Smw145384 
554734Smw145384 /*
555734Smw145384  * process_hotspare()
556734Smw145384  *
557734Smw145384  * Searches though list of physical devices to match hotspare record.
558734Smw145384  * Prints physical device name and state of a hotspare unit.
559734Smw145384  *
560734Smw145384  */
561734Smw145384 /*ARGSUSED*/
562734Smw145384 static void
process_hotspare(md_im_rec_t ** mdimpp,int indent,pnm_rec_t * phys_nm,md_im_rec_t * mdrec)563734Smw145384 process_hotspare(
564734Smw145384 	md_im_rec_t	**mdimpp,
565734Smw145384 	int		indent,
566734Smw145384 	pnm_rec_t	*phys_nm,
567734Smw145384 	md_im_rec_t	*mdrec
568734Smw145384 )
569734Smw145384 {
570734Smw145384 	hot_spare_t	*hs;
571734Smw145384 	pnm_rec_t	*tmpphys_nm;
572734Smw145384 	char 		*state = NULL;
573734Smw145384 
574734Smw145384 	hs =  (hot_spare_t *)mdrec->record;
575734Smw145384 
576734Smw145384 	/*
577734Smw145384 	 * Loops through physical namespace to find the device that matches
578734Smw145384 	 * the hotspare entry.
579734Smw145384 	 */
580734Smw145384 	for (tmpphys_nm = phys_nm; tmpphys_nm != NULL;
581734Smw145384 	    tmpphys_nm = tmpphys_nm->next) {
582734Smw145384 		if (tmpphys_nm->n_key ==
583734Smw145384 		    ((hot_spare_t *)hs)->hs_key) {
584734Smw145384 			/* Printing name of hotspare device */
585734Smw145384 			(void) printf(" %s", tmpphys_nm->n_name);
586734Smw145384 			break;
587734Smw145384 		}
588734Smw145384 	}
589734Smw145384 
590734Smw145384 	state = meta_get_hs_state(hs->hs_state);
591734Smw145384 	if (state != NULL)
592734Smw145384 		(void) printf(" (%s)", state);
593734Smw145384 
594734Smw145384 	/* Not removing entry, because it can be processed more than once. */
595734Smw145384 }
596734Smw145384 
597734Smw145384 
598734Smw145384 /*
599734Smw145384  * process_hotspare_pool()
600734Smw145384  *
601734Smw145384  * Prints concise unit information for a hotspare pool metadevice and calls a
602734Smw145384  * function to process each attached hotspare device.
603734Smw145384  *
604734Smw145384  */
605734Smw145384 static void
process_hotspare_pool(md_im_rec_t ** mdimpp,int indent,pnm_rec_t * phys_nm,md_im_rec_t * mdrec)606734Smw145384 process_hotspare_pool(
607734Smw145384 	md_im_rec_t	**mdimpp,
608734Smw145384 	int		indent,
609734Smw145384 	pnm_rec_t	*phys_nm,
610734Smw145384 	md_im_rec_t	*mdrec
611734Smw145384 )
612734Smw145384 {
613734Smw145384 	hot_spare_pool_ond_t	*hsp;
614734Smw145384 	int			i;
615734Smw145384 	md_im_rec_t		*tmpmdrec;
616734Smw145384 
617734Smw145384 	hsp =  (hot_spare_pool_ond_t *)mdrec->record;
618734Smw145384 
619734Smw145384 	/*
620734Smw145384 	 * Printing name, size, and type of metadevice. Setting size field to
621734Smw145384 	 * 0, so that output is the as metastat -c.
622734Smw145384 	 */
623734Smw145384 	print_concise_entry(indent, mdrec->n_name,
624734Smw145384 	    0, 'h');
625734Smw145384 
626734Smw145384 	/* Looping through list of attached hotspare devices. */
627734Smw145384 	for (i = 0; i < hsp->hsp_nhotspares; i++) {
628734Smw145384 		/* Looking for the matching record for the hotspare device. */
629734Smw145384 		for (tmpmdrec = *mdimpp; tmpmdrec != NULL;
630734Smw145384 		    tmpmdrec = tmpmdrec->next) {
631734Smw145384 			if (tmpmdrec->hs_record_id == hsp->hsp_hotspares[i]) {
632734Smw145384 				/* Calling function to print name of hotspare */
633734Smw145384 				tmpmdrec->dfunc(mdimpp, indent, phys_nm,
634734Smw145384 				    tmpmdrec);
635734Smw145384 			}
636734Smw145384 		}
637734Smw145384 	}
638734Smw145384 	(void) printf("\n");
639734Smw145384 
640734Smw145384 	/*
641734Smw145384 	 * Removing the md_entry from the list
642734Smw145384 	 * of all metadevices
643734Smw145384 	 */
644734Smw145384 	free_mdrec_list_entry(&mdrec);
645734Smw145384 }
646734Smw145384 
647734Smw145384 
648734Smw145384 /*
649734Smw145384  * process_raid()
650734Smw145384  *
651734Smw145384  * Prints concise unit information for a raid metadevice and calls the
652734Smw145384  * respective functions to process the underlying metadevices.
653734Smw145384  *
654734Smw145384  */
655734Smw145384 static void
process_raid(md_im_rec_t ** mdimpp,int indent,pnm_rec_t * phys_nm,md_im_rec_t * mdrec)656734Smw145384 process_raid(
657734Smw145384 	md_im_rec_t	**mdimpp,
658734Smw145384 	int		indent,
659734Smw145384 	pnm_rec_t	*phys_nm,
660734Smw145384 	md_im_rec_t	*mdrec
661734Smw145384 )
662734Smw145384 {
663734Smw145384 	mr_unit_t	*mr;
664734Smw145384 	mr_column_t	*mc;
665734Smw145384 	mdc_unit_t	uc;
666734Smw145384 	int		i;
667734Smw145384 	md_im_rec_t	*tmpmdrec;
668734Smw145384 	md_im_rec_t	*hstmpmdrec;
669734Smw145384 	md_im_list_t	*ucomp_head = NULL;
670734Smw145384 	md_im_list_t	*ucomp_tail = NULL;
671734Smw145384 	md_im_list_t	*ucomp = NULL;
672734Smw145384 	pnm_rec_t	*tmpphys_nm;
673734Smw145384 	int		underlying_device;
674734Smw145384 
675734Smw145384 	mr =  (mr_unit_t *)mdrec->record;
676734Smw145384 	uc = mr->c;
677734Smw145384 
678734Smw145384 	/* Printing name, size, and type of metadevice */
679734Smw145384 	print_concise_entry(indent, mdrec->n_name,
680734Smw145384 	    uc.un_total_blocks, 'r');
681734Smw145384 
682734Smw145384 	/* Loops through raid columns to find underlying metadevices */
683734Smw145384 	for (i = 0, mc = &mr->un_column[0];  i < mr->un_totalcolumncnt;
684734Smw145384 	    i++, mc++) {
685734Smw145384 		char	*state = NULL;
686734Smw145384 		char	*hsname = NULL;
687734Smw145384 
688734Smw145384 		/*
689734Smw145384 		 * Need to assume that underlying device is a physical device,
690734Smw145384 		 * unless we find a matching metadevice record.
691734Smw145384 		 */
692734Smw145384 		underlying_device = PHYSICAL_DEV;
693734Smw145384 
694734Smw145384 		/*
695734Smw145384 		 * Loops through list of metadevices to find record that matches
696734Smw145384 		 * the underlying device.
697734Smw145384 		 */
698734Smw145384 		for (tmpmdrec = *mdimpp; tmpmdrec != NULL;
699734Smw145384 		    tmpmdrec = tmpmdrec->next) {
700734Smw145384 			if (tmpmdrec->n_key == mc->un_orig_key) {
701734Smw145384 				/* check if hotspare device enabled */
702734Smw145384 				if (mc->un_hs_id !=  NULL) {
703734Smw145384 					/*
704734Smw145384 					 * Find matching metadevice record
705734Smw145384 					 * for the hotspare device.
706734Smw145384 					 */
707734Smw145384 					for (hstmpmdrec = *mdimpp;
708734Smw145384 					    hstmpmdrec != NULL;
709734Smw145384 					    hstmpmdrec = hstmpmdrec->next) {
710734Smw145384 						if (hstmpmdrec->hs_record_id ==
711734Smw145384 						    mc->un_hs_id) {
712734Smw145384 							/* print name of hs */
713734Smw145384 							hstmpmdrec->dfunc(
714734Smw145384 							    mdimpp, indent,
715734Smw145384 							    phys_nm,
716734Smw145384 							    hstmpmdrec);
717734Smw145384 							break;
718734Smw145384 						}
719734Smw145384 					}
720734Smw145384 				}
721734Smw145384 				/* print name of underlying metadevice */
722734Smw145384 				(void) printf(" %s", tmpmdrec->n_name);
723734Smw145384 				underlying_device = NOT_PHYSICAL_DEV;
724734Smw145384 				ucomp = Zalloc(sizeof (md_im_list_t));
725734Smw145384 				ucomp->mdrec = tmpmdrec;
726734Smw145384 				ucomponent_append(&ucomp_head, &ucomp_tail,
727734Smw145384 				    ucomp);
728734Smw145384 			}
729734Smw145384 		}
730734Smw145384 
731734Smw145384 		if (underlying_device == PHYSICAL_DEV) {
732734Smw145384 			print_physical_device(phys_nm, mc->un_orig_key);
733734Smw145384 		}
734734Smw145384 		state = meta_get_raid_col_state(mc->un_devstate);
735734Smw145384 
736734Smw145384 		/*
737734Smw145384 		 * An underlying hotspare must be a physical device.
738734Smw145384 		 * If support is ever added for soft-partitions under
739734Smw145384 		 * hotspare pools, then this code should be updated to
740734Smw145384 		 * include a search for underlying metadevices.
741734Smw145384 		 */
742734Smw145384 		if (mc->un_hs_id != 0) {
743734Smw145384 			for (tmpphys_nm = phys_nm; tmpphys_nm != NULL;
744734Smw145384 			    tmpphys_nm = tmpphys_nm->next) {
745734Smw145384 				if (tmpphys_nm->n_key == mc->un_hs_key) {
746734Smw145384 					hsname = tmpphys_nm->n_name;
747734Smw145384 					break;
748734Smw145384 				}
749734Smw145384 			}
750734Smw145384 		}
751734Smw145384 
752734Smw145384 		if (state != NULL) {
753734Smw145384 			if (hsname != NULL)
754734Smw145384 				(void) printf(" (%s-%s)", state,
755734Smw145384 				    hsname);
756734Smw145384 			else
757734Smw145384 				(void) printf(" (%s)", state);
758734Smw145384 		} else if (hsname != NULL) {
759734Smw145384 			(void) printf(gettext(" (spared-%s)"), hsname);
760734Smw145384 		}
761734Smw145384 	}
762734Smw145384 	(void) printf("\n");
763734Smw145384 
764734Smw145384 	/* process underlying components */
765734Smw145384 	indent += META_INDENT;
766734Smw145384 	for (ucomp = ucomp_head; ucomp != NULL;
767734Smw145384 	    ucomp = ucomp->next) {
768734Smw145384 		ucomp->mdrec->dfunc(mdimpp, indent, phys_nm,
769734Smw145384 		    ucomp->mdrec);
770734Smw145384 	}
771734Smw145384 	free_md_im_list_entries(&ucomp_head);
772734Smw145384 
773734Smw145384 	/*
774734Smw145384 	 * Removing the md_entry from the list
775734Smw145384 	 * of all metadevices
776734Smw145384 	 */
777734Smw145384 	free_mdrec_list_entry(&mdrec);
778734Smw145384 }
779734Smw145384 
780734Smw145384 
781734Smw145384 /*
782734Smw145384  * process_mirror()
783734Smw145384  *
784734Smw145384  * Prints concise unit information for a mirror metadevice and calls the
785734Smw145384  * respective functions to process the underlying metadevices.
786734Smw145384  *
787734Smw145384  */
788734Smw145384 static void
process_mirror(md_im_rec_t ** mdimpp,int indent,pnm_rec_t * phys_nm,md_im_rec_t * mdrec)789734Smw145384 process_mirror(
790734Smw145384 	md_im_rec_t	**mdimpp,
791734Smw145384 	int		indent,
792734Smw145384 	pnm_rec_t	*phys_nm,
793734Smw145384 	md_im_rec_t	*mdrec
794734Smw145384 )
795734Smw145384 {
796734Smw145384 	mm_unit_t	*mm;
797734Smw145384 	mm_submirror_t 	*sm;
798734Smw145384 	mdc_unit_t	uc;
799734Smw145384 	int		i;
800734Smw145384 	md_im_rec_t	*tmpmdrec;
801734Smw145384 	md_im_list_t	*ucomp_head = NULL;
802734Smw145384 	md_im_list_t	*ucomp_tail = NULL;
803734Smw145384 	md_im_list_t	*ucomp = NULL;
804734Smw145384 
805734Smw145384 	mm =  (mm_unit_t *)mdrec->record;
806734Smw145384 	uc = mm->c;
807734Smw145384 
808734Smw145384 	/* Printing name, size, and type of metadevice */
809734Smw145384 	print_concise_entry(indent, mdrec->n_name,
810734Smw145384 	    uc.un_total_blocks, 'm');
811734Smw145384 
812734Smw145384 	/* Looping through sub-mirrors to find underlying devices */
813734Smw145384 	for (i = 0, sm = &mm->un_sm[0]; i < mm->un_nsm; i++, sm++) {
814734Smw145384 		char 	*state = NULL;
815734Smw145384 
816734Smw145384 		for (tmpmdrec = *mdimpp; tmpmdrec != NULL;
817734Smw145384 		    tmpmdrec = tmpmdrec->next) {
818734Smw145384 			if (tmpmdrec->n_key == sm->sm_key) {
819734Smw145384 				(void) printf(" %s", tmpmdrec->n_name);
820734Smw145384 				ucomp = Zalloc(sizeof (md_im_list_t));
821734Smw145384 				ucomp->mdrec = tmpmdrec;
822734Smw145384 				ucomponent_append(&ucomp_head, &ucomp_tail,
823734Smw145384 				    ucomp);
824734Smw145384 			}
825734Smw145384 		}
826734Smw145384 
827734Smw145384 		/*
828734Smw145384 		 * It is not possible to have an underlying physical device
829734Smw145384 		 * for a submirror, so there is no need to search the phys_nm
830734Smw145384 		 * list.
831734Smw145384 		 */
832734Smw145384 
833734Smw145384 		/* Printing the state for the submirror */
834734Smw145384 		state = meta_get_sm_state(sm->sm_state);
835734Smw145384 		if (state != NULL) {
836734Smw145384 			(void) printf(" (%s)", state);
837734Smw145384 		}
838734Smw145384 	}
839734Smw145384 	(void) printf("\n");
840734Smw145384 
841734Smw145384 	/* process underlying components */
842734Smw145384 	indent += META_INDENT;
843734Smw145384 	for (ucomp = ucomp_head; ucomp != NULL;
844734Smw145384 	    ucomp = ucomp->next) {
845734Smw145384 		ucomp->mdrec->dfunc(mdimpp, indent, phys_nm,
846734Smw145384 		    ucomp->mdrec);
847734Smw145384 	}
848734Smw145384 	free_md_im_list_entries(&ucomp_head);
849734Smw145384 
850734Smw145384 	/*
851734Smw145384 	 * Removing the md_entry from the list
852734Smw145384 	 * of all metadevices
853734Smw145384 	 */
854734Smw145384 	free_mdrec_list_entry(&mdrec);
855734Smw145384 }
856734Smw145384 
857734Smw145384 
858734Smw145384 /*
859734Smw145384  * process_stripe()
860734Smw145384  *
861734Smw145384  * Prints concise unit information for a stripe metadevice and calls the
862734Smw145384  * respective functions to process the underlying metadevices.
863734Smw145384  *
864734Smw145384  */
865734Smw145384 static void
process_stripe(md_im_rec_t ** mdimpp,int indent,pnm_rec_t * phys_nm,md_im_rec_t * mdrec)866734Smw145384 process_stripe(
867734Smw145384 	md_im_rec_t	**mdimpp,
868734Smw145384 	int		indent,
869734Smw145384 	pnm_rec_t	*phys_nm,
870734Smw145384 	md_im_rec_t	*mdrec
871734Smw145384 )
872734Smw145384 {
873734Smw145384 	ms_unit_t	*ms;
874734Smw145384 	mdc_unit_t	uc;
875734Smw145384 	md_im_rec_t	*tmpmdrec;
876734Smw145384 	md_im_list_t	*ucomp_head = NULL;
877734Smw145384 	md_im_list_t	*ucomp_tail = NULL;
878734Smw145384 	md_im_list_t	*ucomp = NULL;
879734Smw145384 	pnm_rec_t	*tmpphys_nm;
880734Smw145384 	int		underlying_device;
881734Smw145384 	uint_t		row;
882734Smw145384 
883734Smw145384 	ms =  (ms_unit_t *)mdrec->record;
884734Smw145384 	uc = ms->c;
885734Smw145384 
886734Smw145384 	/* Printing name, size, and type of metadevice */
887734Smw145384 	print_concise_entry(indent, mdrec->n_name,
888734Smw145384 	    uc.un_total_blocks, 's');
889734Smw145384 
890734Smw145384 	/* Looping through stripe rows */
891734Smw145384 	for (row = 0; (row < ms->un_nrows); ++row) {
892734Smw145384 		struct ms_row	*mdr = &ms->un_row[row];
893734Smw145384 		ms_comp_t	*mdcomp = (void *)&((char *)ms)
894734Smw145384 		    [ms->un_ocomp];
895734Smw145384 		uint_t		comp, c;
896734Smw145384 
897734Smw145384 		/*
898734Smw145384 		 * Looping through the components in each row to find the
899734Smw145384 		 * underlying devices.
900734Smw145384 		 */
901734Smw145384 		for (comp = 0, c = mdr->un_icomp; (comp < mdr->un_ncomp);
902734Smw145384 		    ++comp, ++c) {
903734Smw145384 			char		*state = NULL;
904734Smw145384 			char		*hsname = NULL;
905734Smw145384 			ms_comp_t	*mdc = &mdcomp[c];
906734Smw145384 			md_m_shared_t 	*mdm = &mdc->un_mirror;
907734Smw145384 
908734Smw145384 			/*
909734Smw145384 			 * Need to assume that underlying device is a
910734Smw145384 			 * physical device, unless we find a matching
911734Smw145384 			 * metadevice record.
912734Smw145384 			 */
913734Smw145384 			underlying_device = PHYSICAL_DEV;
914734Smw145384 
915734Smw145384 			for (tmpmdrec = *mdimpp; tmpmdrec != NULL;
916734Smw145384 			    tmpmdrec = tmpmdrec->next) {
917734Smw145384 				if (tmpmdrec->n_key == mdc->un_key) {
918734Smw145384 					(void) printf(" %s", tmpmdrec->n_name);
919734Smw145384 					underlying_device = NOT_PHYSICAL_DEV;
920734Smw145384 					ucomp = Zalloc(sizeof (md_im_list_t));
921734Smw145384 					ucomp->mdrec = tmpmdrec;
922734Smw145384 					ucomponent_append(&ucomp_head,
923734Smw145384 					    &ucomp_tail, ucomp);
924734Smw145384 				}
925734Smw145384 			}
926734Smw145384 			/* if an underlying metadevice was not found */
927734Smw145384 			if (underlying_device == PHYSICAL_DEV) {
928734Smw145384 				print_physical_device(phys_nm, mdc->un_key);
929734Smw145384 			}
930734Smw145384 			state = meta_get_stripe_state(mdm->ms_state);
931734Smw145384 
932734Smw145384 			/*
933734Smw145384 			 * An underlying hotspare must be a physical device.
934734Smw145384 			 * If support is ever added for soft-partitions under
935734Smw145384 			 * hotspare pools, then this code should be updated to
936734Smw145384 			 * include a search for underlying metadevices.
937734Smw145384 			 */
938734Smw145384 			if (mdm->ms_hs_key != 0) {
939734Smw145384 				for (tmpphys_nm = phys_nm; tmpphys_nm != NULL;
940734Smw145384 				    tmpphys_nm = tmpphys_nm->next) {
941734Smw145384 					if (tmpphys_nm->n_key ==
942734Smw145384 					    mdm->ms_hs_key) {
943734Smw145384 						hsname = tmpphys_nm->n_name;
944734Smw145384 						break;
945734Smw145384 					}
946734Smw145384 				}
947734Smw145384 			}
948734Smw145384 			if (state != NULL) {
949734Smw145384 				if (hsname != NULL) {
950734Smw145384 					(void) printf(" (%s-%s)", state,
951734Smw145384 					    hsname);
952734Smw145384 				} else {
953734Smw145384 					(void) printf(" (%s)", state);
954734Smw145384 				}
955734Smw145384 			} else if (hsname != NULL) {
956734Smw145384 				(void) printf(gettext(" (spared-%s)"), hsname);
957734Smw145384 			}
958734Smw145384 		}
959734Smw145384 	}
960734Smw145384 	(void) printf("\n");
961734Smw145384 
962734Smw145384 	/* Process underlying metadevices */
963734Smw145384 	indent += META_INDENT;
964734Smw145384 	for (ucomp = ucomp_head; ucomp != NULL;
965734Smw145384 	    ucomp = ucomp->next) {
966734Smw145384 		ucomp->mdrec->dfunc(mdimpp, indent, phys_nm,
967734Smw145384 		    ucomp->mdrec);
968734Smw145384 	}
969734Smw145384 	free_md_im_list_entries(&ucomp_head);
970734Smw145384 
971734Smw145384 	/*
972734Smw145384 	 * Removing the md_entry from the list
973734Smw145384 	 * of all metadevices
974734Smw145384 	 */
975734Smw145384 	free_mdrec_list_entry(&mdrec);
976734Smw145384 }
977734Smw145384 
978734Smw145384 
979734Smw145384 /*
980734Smw145384  * process_softpart()
981734Smw145384  *
982734Smw145384  * Prints concise unit information for a softpart metadevice and calls the
983734Smw145384  * respective functions to process the underlying metadevices.
984734Smw145384  *
985734Smw145384  */
986734Smw145384 static void
process_softpart(md_im_rec_t ** mdimpp,int indent,pnm_rec_t * phys_nm,md_im_rec_t * mdrec)987734Smw145384 process_softpart(
988734Smw145384 	md_im_rec_t	**mdimpp,
989734Smw145384 	int		indent,
990734Smw145384 	pnm_rec_t	*phys_nm,
991734Smw145384 	md_im_rec_t	*mdrec
992734Smw145384 )
993734Smw145384 {
994734Smw145384 	mp_unit_t	*mp;
995734Smw145384 	mdc_unit_t	uc;
996734Smw145384 	md_im_rec_t	*tmpmdrec;
997734Smw145384 	int		underlying_device = PHYSICAL_DEV;
998734Smw145384 
999734Smw145384 	mp =  (mp_unit_t *)mdrec->record;
1000734Smw145384 	uc = mp->c;
1001734Smw145384 
1002734Smw145384 	/* Printing name, size, and type of metadevice */
1003734Smw145384 	print_concise_entry(indent, mdrec->n_name,
1004734Smw145384 	    uc.un_total_blocks, 'p');
1005734Smw145384 
1006734Smw145384 	/*
1007734Smw145384 	 * Loops through md_im_rec_t **mdimpp list of all metadevices to find
1008734Smw145384 	 * record that matches the underlying device.
1009734Smw145384 	 * Softpartitions can only have one underlying device, so once a
1010734Smw145384 	 * match is found, we are done.
1011734Smw145384 	 */
1012734Smw145384 	for (tmpmdrec = *mdimpp; tmpmdrec != NULL;
1013734Smw145384 	    tmpmdrec = tmpmdrec->next) {
1014734Smw145384 		if (tmpmdrec->n_key == mp->un_key) {
1015734Smw145384 			/* Printing name of the underlying metadevice */
1016734Smw145384 			(void) printf(" %s", tmpmdrec->n_name);
1017734Smw145384 			underlying_device = NOT_PHYSICAL_DEV;
1018734Smw145384 			break;
1019734Smw145384 		}
1020734Smw145384 	}
1021734Smw145384 
1022734Smw145384 	/* This is only executed if an underlying metadevice was not found */
1023734Smw145384 	if (underlying_device == PHYSICAL_DEV) {
1024734Smw145384 		print_physical_device(phys_nm, mp->un_key);
1025734Smw145384 		(void) printf("\n");
1026734Smw145384 	} else {
1027734Smw145384 		/* Process underlying metadevice */
1028734Smw145384 		(void) printf("\n");
1029734Smw145384 		indent += META_INDENT;
1030734Smw145384 		tmpmdrec->dfunc(mdimpp, indent, phys_nm,
1031734Smw145384 		    tmpmdrec);
1032734Smw145384 	}
1033734Smw145384 
1034734Smw145384 	/*
1035734Smw145384 	 * Removing the md_entry from the list
1036734Smw145384 	 * of all metadevices
1037734Smw145384 	 */
1038734Smw145384 	free_mdrec_list_entry(&mdrec);
1039734Smw145384 }
1040734Smw145384 
1041734Smw145384 
1042734Smw145384 /*
1043734Smw145384  * process_toplevel_softparts()
1044734Smw145384  *
1045734Smw145384  * Toplevel softpartions need to be grouped so that their underlying devices
1046734Smw145384  * can be printed just once.
1047734Smw145384  */
1048734Smw145384 static void
process_toplevel_softparts(md_im_rec_t ** mdimpp,int indent,pnm_rec_t * phys_nm)1049734Smw145384 process_toplevel_softparts(
1050734Smw145384 	md_im_rec_t	**mdimpp,
1051734Smw145384 	int		indent,
1052734Smw145384 	pnm_rec_t	*phys_nm
1053734Smw145384 )
1054734Smw145384 {
1055734Smw145384 	mp_unit_t	*mp;
1056734Smw145384 	mdc_unit_t	uc;
1057734Smw145384 	md_im_rec_t	*mdrec;
1058734Smw145384 	md_im_rec_t	*comp_mdrec; /* pntr to underlying component's record */
1059734Smw145384 	md_im_rec_t	*tmp_mdrec, *rm_mdrec;
1060734Smw145384 	mp_unit_t	*tmp_mp;
1061734Smw145384 	int		underlying_device;
1062734Smw145384 
1063734Smw145384 	/*
1064734Smw145384 	 * Loops through md_im_rec_t **mdimpp list of all metadevices to find
1065734Smw145384 	 * all softpartions that are toplevel softpartitions(softparts w/out
1066734Smw145384 	 * a parent). Groups output for these entries so that the function to
1067734Smw145384 	 * process the underlying metadevice is only called once.
1068734Smw145384 	 */
1069734Smw145384 	for (mdrec = *mdimpp; mdrec != NULL; mdrec = mdrec->next) {
1070734Smw145384 
1071734Smw145384 		underlying_device = PHYSICAL_DEV;
1072734Smw145384 		if ((mdrec->md_type == MDDB_F_SOFTPART) &&
1073734Smw145384 		    (mdrec->has_parent == 0)) {
1074734Smw145384 			mp =  (mp_unit_t *)mdrec->record;
1075734Smw145384 			uc = mp->c;
1076734Smw145384 			/* Printing name, size, and type of metadevice */
1077734Smw145384 			print_concise_entry(indent, mdrec->n_name,
1078734Smw145384 			    uc.un_total_blocks, 'p');
1079734Smw145384 			/*
1080734Smw145384 			 * Looking for record that matches underlying
1081734Smw145384 			 * component.
1082734Smw145384 			 */
1083734Smw145384 			for (comp_mdrec = *mdimpp; comp_mdrec != NULL;
1084734Smw145384 			    comp_mdrec = comp_mdrec->next) {
1085734Smw145384 				if (comp_mdrec->n_key == mp->un_key) {
1086734Smw145384 					/* Print name of underlying device */
1087734Smw145384 					(void) printf(" %s",
1088734Smw145384 					    comp_mdrec->n_name);
1089734Smw145384 					underlying_device = NOT_PHYSICAL_DEV;
1090734Smw145384 					break;
1091734Smw145384 				}
1092734Smw145384 			}
1093734Smw145384 			if (underlying_device == PHYSICAL_DEV) {
1094734Smw145384 				print_physical_device(phys_nm, mp->un_key);
1095734Smw145384 			}
1096734Smw145384 			(void) printf("\n");
1097734Smw145384 
1098734Smw145384 			/*
1099734Smw145384 			 * Looking for any other toplevel softpartitions with
1100734Smw145384 			 * same underlying device. We know that all other
1101734Smw145384 			 * matching metadevices, that share the same underlying
1102734Smw145384 			 * metadevice, are also soft-partitions.
1103734Smw145384 			 */
1104734Smw145384 			for (tmp_mdrec = mdrec->next; tmp_mdrec != NULL; ) {
1105734Smw145384 				tmp_mp = (mp_unit_t *)tmp_mdrec->record;
1106734Smw145384 				if ((tmp_mdrec->has_parent == 0) &&
1107734Smw145384 				    (tmp_mp->un_key == mp->un_key)) {
1108734Smw145384 					uc = tmp_mp->c;
1109734Smw145384 					print_concise_entry(indent,
1110734Smw145384 					    tmp_mdrec->n_name,
1111734Smw145384 					    uc.un_total_blocks, 'p');
1112734Smw145384 					if (underlying_device ==
1113734Smw145384 					    NOT_PHYSICAL_DEV) {
1114734Smw145384 						(void) printf(" %s",
1115734Smw145384 						    comp_mdrec->n_name);
1116734Smw145384 					} else {
1117734Smw145384 						print_physical_device(
1118734Smw145384 						    phys_nm, tmp_mp->un_key);
1119734Smw145384 					}
1120734Smw145384 					(void) printf("\n");
1121734Smw145384 					/*
1122734Smw145384 					 * Need to advance so that will not lose
1123734Smw145384 					 * position after removing processed
1124734Smw145384 					 * record.
1125734Smw145384 					 */
1126734Smw145384 					rm_mdrec = tmp_mdrec;
1127734Smw145384 					tmp_mdrec = tmp_mdrec->next;
1128734Smw145384 					/*
1129734Smw145384 					 * Removing the md_entry from the list
1130734Smw145384 					 * of all metadevices.
1131734Smw145384 					 */
1132734Smw145384 					free_mdrec_list_entry(&rm_mdrec);
1133734Smw145384 				} else {
1134734Smw145384 					tmp_mdrec = tmp_mdrec->next;
1135734Smw145384 				}
1136734Smw145384 			}
1137734Smw145384 			/* Process the underlying device */
1138734Smw145384 			if (underlying_device == NOT_PHYSICAL_DEV) {
1139734Smw145384 				indent += META_INDENT;
1140734Smw145384 				comp_mdrec->dfunc(mdimpp, indent, phys_nm,
1141734Smw145384 				    comp_mdrec);
1142734Smw145384 			}
1143734Smw145384 		}
1144734Smw145384 	}
1145734Smw145384 }
1146734Smw145384 
1147734Smw145384 
1148734Smw145384 /*
1149734Smw145384  * process_toplevel_devices()
1150734Smw145384  *
1151734Smw145384  * Search through list of metadevices for metadevices of md_type that do not
1152734Smw145384  * have a parent.
1153734Smw145384  *
1154734Smw145384  */
1155734Smw145384 static void
process_toplevel_devices(md_im_rec_t ** mdimpp,pnm_rec_t * pnm,uint_t md_type)1156734Smw145384 process_toplevel_devices(
1157734Smw145384 	md_im_rec_t	**mdimpp,
1158734Smw145384 	pnm_rec_t	*pnm,
1159734Smw145384 	uint_t		md_type
1160734Smw145384 )
1161734Smw145384 {
1162734Smw145384 	md_im_rec_t	*mdrec;
1163734Smw145384 	md_im_list_t	*mdrec_tl_tail = NULL;
1164734Smw145384 	md_im_list_t	*mdrec_tl_head = NULL;
1165734Smw145384 	md_im_list_t	*tmp_tl_list = NULL;
1166734Smw145384 	int		indent = 0;
1167734Smw145384 
1168734Smw145384 	indent += META_INDENT;
1169734Smw145384 
1170734Smw145384 	/*
1171734Smw145384 	 * Need to group soft partitions so that common underlying device
1172734Smw145384 	 * are only processed once.
1173734Smw145384 	 */
1174734Smw145384 	if (md_type == MDDB_F_SOFTPART) {
1175734Smw145384 		process_toplevel_softparts(mdimpp, indent, pnm);
1176734Smw145384 		return;
1177734Smw145384 	}
1178734Smw145384 
1179734Smw145384 	/*
1180734Smw145384 	 * Search the list of metadevices to find all metadevices that match
1181734Smw145384 	 * the type and don't have a parent.  Put them on a separate list
1182734Smw145384 	 * that will be processed.
1183734Smw145384 	 */
1184734Smw145384 	for (mdrec = *mdimpp; mdrec != NULL; mdrec = mdrec->next) {
1185734Smw145384 		if ((mdrec->md_type == md_type)&&(mdrec->has_parent == 0)) {
1186734Smw145384 			tmp_tl_list = Zalloc(sizeof (md_im_list_t));
1187734Smw145384 			tmp_tl_list->mdrec = mdrec;
1188734Smw145384 			tmp_tl_list->next = NULL;
1189734Smw145384 			if (mdrec_tl_tail == NULL) {
1190734Smw145384 				mdrec_tl_tail = tmp_tl_list;
1191734Smw145384 				mdrec_tl_head = mdrec_tl_tail;
1192734Smw145384 			} else {
1193734Smw145384 				mdrec_tl_tail->next = tmp_tl_list;
1194734Smw145384 				mdrec_tl_tail = mdrec_tl_tail->next;
1195734Smw145384 			}
1196734Smw145384 		}
1197734Smw145384 
1198734Smw145384 	}
1199734Smw145384 
1200734Smw145384 	/*
1201734Smw145384 	 * Loop through list and process all top-level metadevices of a
1202734Smw145384 	 * given type.
1203734Smw145384 	 */
1204734Smw145384 	for (tmp_tl_list = mdrec_tl_head; tmp_tl_list != NULL;
1205734Smw145384 	    tmp_tl_list = tmp_tl_list->next) {
1206734Smw145384 		tmp_tl_list->mdrec->dfunc(mdimpp, indent, pnm,
1207734Smw145384 		    tmp_tl_list->mdrec);
1208734Smw145384 	}
1209734Smw145384 
1210734Smw145384 	free_md_im_list_entries(&mdrec_tl_head);
1211734Smw145384 }
1212734Smw145384 
1213734Smw145384 
1214734Smw145384 /*
1215734Smw145384  * extract_mduser_data()
1216734Smw145384  *
1217734Smw145384  * Converts or copies the (mddb_rb_t->rb_data) metadevice record to a 64bit
1218734Smw145384  * record.
1219734Smw145384  * Sets the dfunc field to point to the appropriate function to process the
1220734Smw145384  * metadevice.
1221734Smw145384  * Sets the parent field for the metadevice.
1222734Smw145384  * Extracts the name from the NM namespace if it is available, otherwise
1223734Smw145384  * generates it from the metadevice's minor number.
1224734Smw145384  *
1225734Smw145384  * Returns:
1226734Smw145384  *	< 0 for failure
1227734Smw145384  *	  0 for success
1228734Smw145384  *
1229734Smw145384  */
1230734Smw145384 static int
extract_mduser_data(mddb_rb_t * nm,md_im_rec_t * mdrec,void * rbp,int is_32bit_record,md_error_t * ep)1231734Smw145384 extract_mduser_data(
1232734Smw145384 	mddb_rb_t		*nm,
1233734Smw145384 	md_im_rec_t		*mdrec,
1234734Smw145384 	void			*rbp,
1235734Smw145384 	int 			is_32bit_record,
1236734Smw145384 	md_error_t		*ep
1237734Smw145384 )
1238734Smw145384 {
1239734Smw145384 	mdc_unit_t		uc;
1240734Smw145384 	hot_spare_t 		*hs;
1241734Smw145384 	hot_spare_pool_ond_t 	*hsp;
1242734Smw145384 	size_t			newreqsize;
1243734Smw145384 	mddb_rb_t		*rbp_nm = nm;
1244734Smw145384 	struct nm_rec		*nm_record;
1245734Smw145384 	struct nm_name		*nmname;
1246734Smw145384 	char 			*uname = NULL;
1247734Smw145384 
1248734Smw145384 
1249734Smw145384 	/*LINTED*/
1250734Smw145384 	nm_record = (struct nm_rec *)((caddr_t)(&rbp_nm->rb_data));
1251734Smw145384 
1252734Smw145384 	/*
1253734Smw145384 	 * Setting the un_self_id or the hs_self_id, in the case of hotspare
1254734Smw145384 	 * records, for each metadevice entry. Also setting has_parent and
1255734Smw145384 	 * setting dfunc so that it points to the correct function to process
1256734Smw145384 	 * the record type.
1257734Smw145384 	 * If the record was stored ondisk in 32bit format, then it is
1258734Smw145384 	 * converted to the 64bits equivalent 64bit format and the memory
1259734Smw145384 	 * for the 32bit pointer is freed.
1260734Smw145384 	 */
1261734Smw145384 	switch (mdrec->md_type) {
1262734Smw145384 		case MDDB_F_SOFTPART:
1263734Smw145384 			if (is_32bit_record) {
1264734Smw145384 				mp_unit32_od_t	*small_un;
1265734Smw145384 				mp_unit_t	*big_un;
1266734Smw145384 
1267734Smw145384 				small_un = (mp_unit32_od_t *)((uintptr_t)rbp +
1268734Smw145384 				    (sizeof (mddb_rb_t) - sizeof (int)));
1269734Smw145384 				newreqsize = sizeof (mp_unit_t) +
1270734Smw145384 				    ((small_un->un_numexts - 1) *
1271734Smw145384 				    sizeof (struct mp_ext));
1272734Smw145384 				big_un = (void *)Zalloc(newreqsize);
1273734Smw145384 				softpart_convert((caddr_t)small_un,
1274734Smw145384 				    (caddr_t)big_un, SMALL_2_BIG);
1275734Smw145384 				mdrec->record = (void *)big_un;
1276734Smw145384 			} else {
1277734Smw145384 				mp_unit_t	*big_un;
1278734Smw145384 
1279734Smw145384 				big_un = (mp_unit_t *)((uintptr_t)rbp +
1280734Smw145384 				    (sizeof (mddb_rb_t) - sizeof (int)));
1281734Smw145384 				newreqsize = sizeof (mp_unit_t) +
1282734Smw145384 				    ((big_un->un_numexts - 1) *
1283734Smw145384 				    sizeof (struct mp_ext));
1284734Smw145384 				mdrec->record = (void *)Zalloc(newreqsize);
1285734Smw145384 				bcopy(big_un, mdrec->record, newreqsize);
1286734Smw145384 			}
1287734Smw145384 			uc = ((mp_unit_t *)mdrec->record)->c;
1288734Smw145384 			mdrec->dfunc = &process_softpart;
1289734Smw145384 			mdrec->un_self_id = uc.un_self_id;
1290734Smw145384 			mdrec->has_parent = MD_HAS_PARENT(
1291734Smw145384 			    uc.un_parent);
1292734Smw145384 			break;
1293734Smw145384 		case MDDB_F_STRIPE:
1294734Smw145384 			if (is_32bit_record) {
1295734Smw145384 				ms_unit32_od_t	*small_un;
1296734Smw145384 				ms_unit_t	*big_un;
1297734Smw145384 
1298734Smw145384 				small_un = (ms_unit32_od_t *)((uintptr_t)rbp +
1299734Smw145384 				    (sizeof (mddb_rb_t) - sizeof (int)));
1300734Smw145384 				newreqsize = get_big_stripe_req_size(
1301734Smw145384 				    small_un, COMPLETE_STRUCTURE);
1302734Smw145384 				    big_un = (void *)Zalloc(newreqsize);
1303734Smw145384 				stripe_convert((caddr_t)small_un,
1304734Smw145384 				    (caddr_t)big_un, SMALL_2_BIG);
1305734Smw145384 				mdrec->record = (void *)big_un;
1306734Smw145384 			} else {
1307734Smw145384 				ms_unit_t	*big_un;
1308734Smw145384 
1309734Smw145384 				big_un = (ms_unit_t *)((uintptr_t)rbp +
1310734Smw145384 				    (sizeof (mddb_rb_t) - sizeof (int)));
1311734Smw145384 				newreqsize = get_stripe_req_size(big_un);
1312734Smw145384 				mdrec->record = (void *)Zalloc(newreqsize);
1313734Smw145384 				bcopy(big_un, mdrec->record, newreqsize);
1314734Smw145384 			}
1315734Smw145384 			uc = ((ms_unit_t *)mdrec->record)->c;
1316734Smw145384 			mdrec->dfunc = &process_stripe;
1317734Smw145384 			mdrec->un_self_id = uc.un_self_id;
1318734Smw145384 			mdrec->has_parent = MD_HAS_PARENT(
1319734Smw145384 			    uc.un_parent);
1320734Smw145384 			break;
1321734Smw145384 		case MDDB_F_MIRROR:
1322734Smw145384 			if (is_32bit_record) {
1323734Smw145384 				mm_unit32_od_t	*small_un;
1324734Smw145384 				mm_unit_t	*big_un;
1325734Smw145384 
1326734Smw145384 				small_un = (mm_unit32_od_t *)((uintptr_t)rbp +
1327734Smw145384 				    (sizeof (mddb_rb_t) - sizeof (int)));
1328734Smw145384 				newreqsize = sizeof (mm_unit_t);
1329734Smw145384 				big_un = (void *)Zalloc(newreqsize);
1330734Smw145384 				mirror_convert((caddr_t)small_un,
1331734Smw145384 				    (caddr_t)big_un, SMALL_2_BIG);
1332734Smw145384 				mdrec->record = (void *)big_un;
1333734Smw145384 			} else {
1334734Smw145384 				mm_unit_t	*big_un;
1335734Smw145384 
1336734Smw145384 				big_un = (mm_unit_t *)((uintptr_t)rbp +
1337734Smw145384 				    (sizeof (mddb_rb_t) - sizeof (int)));
1338734Smw145384 				newreqsize = sizeof (mm_unit_t);
1339734Smw145384 				mdrec->record = (void *)Zalloc(newreqsize);
1340734Smw145384 				bcopy(big_un, mdrec->record, newreqsize);
1341734Smw145384 			}
1342734Smw145384 			uc = ((mm_unit_t *)mdrec->record)->c;
1343734Smw145384 			mdrec->dfunc = &process_mirror;
1344734Smw145384 			mdrec->un_self_id = uc.un_self_id;
1345734Smw145384 			mdrec->has_parent = MD_HAS_PARENT(
1346734Smw145384 			    uc.un_parent);
1347734Smw145384 			break;
1348734Smw145384 		case MDDB_F_RAID:
1349734Smw145384 			if (is_32bit_record) {
1350734Smw145384 				mr_unit32_od_t	*small_un;
1351734Smw145384 				mr_unit_t	*big_un;
1352734Smw145384 				uint_t		ncol;
1353734Smw145384 
1354734Smw145384 				small_un = (mr_unit32_od_t *)((uintptr_t)rbp +
1355734Smw145384 				    (sizeof (mddb_rb_t) - sizeof (int)));
1356734Smw145384 				ncol = small_un->un_totalcolumncnt;
1357734Smw145384 				newreqsize = sizeof (mr_unit_t) +
1358734Smw145384 				    ((ncol - 1) * sizeof (mr_column_t));
1359734Smw145384 				big_un = (void *)Zalloc(newreqsize);
1360734Smw145384 				raid_convert((caddr_t)small_un,
1361734Smw145384 				    (caddr_t)big_un, SMALL_2_BIG);
1362734Smw145384 				mdrec->record = (void *)big_un;
1363734Smw145384 			} else {
1364734Smw145384 				mr_unit_t	*big_un;
1365734Smw145384 				uint_t		ncol;
1366734Smw145384 
1367734Smw145384 				big_un = (mr_unit_t *)((uintptr_t)rbp +
1368734Smw145384 				    (sizeof (mddb_rb_t) - sizeof (int)));
1369734Smw145384 				ncol = big_un->un_totalcolumncnt;
1370734Smw145384 				newreqsize = sizeof (mr_unit_t) +
1371734Smw145384 				    ((ncol - 1) * sizeof (mr_column_t));
1372734Smw145384 				mdrec->record = (void *)Zalloc(newreqsize);
1373734Smw145384 				bcopy(big_un, mdrec->record, newreqsize);
1374734Smw145384 			}
1375734Smw145384 			uc = ((mr_unit_t *)mdrec->record)->c;
1376734Smw145384 			mdrec->dfunc = &process_raid;
1377734Smw145384 			mdrec->un_self_id = uc.un_self_id;
1378734Smw145384 			mdrec->has_parent = MD_HAS_PARENT(
1379734Smw145384 			    uc.un_parent);
1380734Smw145384 			break;
1381734Smw145384 		case MDDB_F_TRANS_MASTER:
1382734Smw145384 			if (is_32bit_record) {
1383734Smw145384 				mt_unit32_od_t	*small_un;
1384734Smw145384 				mt_unit_t	*big_un;
1385734Smw145384 
1386734Smw145384 				small_un = (mt_unit32_od_t *)((uintptr_t)rbp +
1387734Smw145384 				    (sizeof (mddb_rb_t) - sizeof (int)));
1388734Smw145384 				newreqsize = sizeof (mt_unit_t);
1389734Smw145384 				big_un = (void *)Zalloc(newreqsize);
1390734Smw145384 				trans_master_convert((caddr_t)small_un,
1391734Smw145384 				    (caddr_t)big_un, SMALL_2_BIG);
1392734Smw145384 				mdrec->record = (void *)big_un;
1393734Smw145384 			} else {
1394734Smw145384 				mt_unit_t	*big_un;
1395734Smw145384 
1396734Smw145384 				big_un = (mt_unit_t *)((uintptr_t)rbp +
1397734Smw145384 				    (sizeof (mddb_rb_t) - sizeof (int)));
1398734Smw145384 				newreqsize = sizeof (mt_unit_t);
1399734Smw145384 				mdrec->record = (void *)Zalloc(newreqsize);
1400734Smw145384 				bcopy(big_un, mdrec->record, newreqsize);
1401734Smw145384 			}
1402734Smw145384 			uc = ((mt_unit_t *)mdrec->record)->c;
1403734Smw145384 			mdrec->dfunc = &process_trans;
1404734Smw145384 			mdrec->un_self_id = uc.un_self_id;
1405734Smw145384 			mdrec->has_parent = MD_HAS_PARENT(
1406734Smw145384 			    uc.un_parent);
1407734Smw145384 			break;
1408734Smw145384 		case MDDB_F_HOTSPARE:
1409734Smw145384 			if (is_32bit_record) {
1410734Smw145384 				hot_spare32_od_t	*small_un;
1411734Smw145384 				hot_spare_t		*big_un;
1412734Smw145384 
1413734Smw145384 				small_un = (hot_spare32_od_t *)((uintptr_t)rbp +
1414734Smw145384 				    (sizeof (mddb_rb_t) - sizeof (int)));
1415734Smw145384 				newreqsize = sizeof (hot_spare_t);
1416734Smw145384 				big_un = (void *)Zalloc(newreqsize);
1417734Smw145384 				hs_convert((caddr_t)small_un,
1418734Smw145384 				    (caddr_t)big_un, SMALL_2_BIG);
1419734Smw145384 				mdrec->record = (void *)big_un;
1420734Smw145384 			} else {
1421734Smw145384 				hot_spare_t		*big_un;
1422734Smw145384 
1423734Smw145384 				big_un = (hot_spare_t *)((uintptr_t)rbp +
1424734Smw145384 				    (sizeof (mddb_rb_t) - sizeof (int)));
1425734Smw145384 				newreqsize = sizeof (hot_spare_t);
1426734Smw145384 				mdrec->record = (void *)Zalloc(newreqsize);
1427734Smw145384 				bcopy(big_un, mdrec->record, newreqsize);
1428734Smw145384 			}
1429734Smw145384 			hs = (hot_spare_t *)mdrec->record;
1430734Smw145384 			mdrec->dfunc = &process_hotspare;
1431734Smw145384 			mdrec->un_self_id = NULL;
1432734Smw145384 			mdrec->hs_record_id = hs->hs_record_id;
1433734Smw145384 			mdrec->has_parent = 1;
1434734Smw145384 			break;
1435734Smw145384 		case MDDB_F_HOTSPARE_POOL:
1436734Smw145384 			/*
1437734Smw145384 			 * Ondisk and incore records are always same size.
1438734Smw145384 			 */
1439734Smw145384 			hsp = (hot_spare_pool_ond_t *)((uintptr_t)rbp +
1440734Smw145384 			    (sizeof (mddb_rb_t) - sizeof (int)));
1441734Smw145384 			newreqsize = sizeof (hot_spare_pool_ond_t) +
1442734Smw145384 			    (sizeof (mddb_recid_t) * hsp->hsp_nhotspares);
1443734Smw145384 			mdrec->record = (void *)Zalloc(newreqsize);
1444734Smw145384 			bcopy(hsp, mdrec->record, newreqsize);
1445734Smw145384 			hsp = (hot_spare_pool_ond_t *)mdrec->record;
1446734Smw145384 			mdrec->dfunc = &process_hotspare_pool;
1447*1623Stw21770 			/*
1448*1623Stw21770 			 * If the hsp has descriptive name we'll get
1449*1623Stw21770 			 * the un_self_id
1450*1623Stw21770 			 */
1451*1623Stw21770 			if (HSP_ID_IS_FN(hsp->hsp_self_id))
1452*1623Stw21770 				mdrec->un_self_id = hsp->hsp_self_id;
1453*1623Stw21770 			else
1454*1623Stw21770 				mdrec->un_self_id = NULL;
1455734Smw145384 			mdrec->has_parent = 0;
1456734Smw145384 			break;
1457734Smw145384 		/* All valid cases have been dealt with */
1458734Smw145384 		default:
1459734Smw145384 			(void) mdmddberror(ep, MDE_DB_NODB, 0, 0, 0, NULL);
1460734Smw145384 			return (-1);
1461734Smw145384 	}
1462734Smw145384 
1463734Smw145384 	/*
1464734Smw145384 	 * If metadevice record has an entry in the NM namespace
1465734Smw145384 	 * then it is copied into the mdrec->n_name field.
1466734Smw145384 	 */
1467734Smw145384 	if (mdrec->un_self_id != NULL) {
1468734Smw145384 		for (nmname = &nm_record->r_name[0]; nmname->n_key != 0;
1469734Smw145384 		/*LINTED*/
1470734Smw145384 		    nmname = (struct nm_name *)((char *)nmname +
1471734Smw145384 		    NAMSIZ(nmname))) {
1472734Smw145384 			/*
1473*1623Stw21770 			 * Extract the metadevice/hsp name if it is
1474*1623Stw21770 			 * in the namespace.
1475*1623Stw21770 			 *
1476*1623Stw21770 			 * If it is a hot spare pool we will find our
1477*1623Stw21770 			 * match by comparing the NM record's n_key
1478*1623Stw21770 			 * with the extracted key from the hsp_self_id
1479*1623Stw21770 			 * Else, match the un_self_id for the record
1480*1623Stw21770 			 * to the n_minor name in the NM record.
1481734Smw145384 			 */
1482*1623Stw21770 			    if (mdrec->md_type == MDDB_F_HOTSPARE_POOL) {
1483*1623Stw21770 				if (nmname->n_key ==
1484*1623Stw21770 				    HSP_ID_TO_KEY(hsp->hsp_self_id)) {
1485*1623Stw21770 					mdrec->n_key = nmname->n_key;
1486*1623Stw21770 					uname = Strdup(nmname->n_name);
1487*1623Stw21770 					mdrec->n_name = uname;
1488*1623Stw21770 					break;
1489*1623Stw21770 				}
1490*1623Stw21770 			    } else {
1491*1623Stw21770 				if ((nmname->n_minor) == (uc.un_self_id)) {
1492*1623Stw21770 					(*mdrec).n_key = nmname->n_key;
1493*1623Stw21770 					uname = Strdup(nmname->n_name);
1494*1623Stw21770 					mdrec->n_name = uname;
1495*1623Stw21770 					break;
1496*1623Stw21770 				}
1497*1623Stw21770 			    }
1498734Smw145384 		}
1499734Smw145384 	}
1500734Smw145384 
1501734Smw145384 	/*
1502734Smw145384 	 * If the metadevice name is not in the namespace, then
1503734Smw145384 	 * then we will generate the name from the minor number
1504734Smw145384 	 * for the metadevice.  In the case of records for a hotspare
1505734Smw145384 	 * pool we use hsp_self_id, otherwise we use un_self_id.
1506734Smw145384 	 */
1507734Smw145384 	if (uname == NULL) {
1508734Smw145384 		if (mdrec->md_type == MDDB_F_HOTSPARE_POOL) {
1509734Smw145384 			uname = Malloc(MAXSIZEMDRECNAME);
1510734Smw145384 			(void) sprintf(uname, "hsp%03u",
1511734Smw145384 			    HSP_ID(hsp->hsp_self_id));
1512734Smw145384 			mdrec->n_name = uname;
1513734Smw145384 		} else if (mdrec->md_type != MDDB_F_HOTSPARE) {
1514734Smw145384 			/*
1515734Smw145384 			 * Generate the metadevice name for all other records
1516734Smw145384 			 * (except for hotspares, because hotspares can only
1517734Smw145384 			 * be physical devices.)
1518734Smw145384 			 */
1519734Smw145384 			uname = Malloc(MAXSIZEMDRECNAME);
1520734Smw145384 			(void) sprintf(uname, "d%lu",
1521734Smw145384 			    MD_MIN2UNIT(mdrec->un_self_id));
1522734Smw145384 			mdrec->n_name = uname;
1523734Smw145384 		}
1524734Smw145384 	}
1525734Smw145384 
1526734Smw145384 	return (0);
1527734Smw145384 }
1528734Smw145384 
1529734Smw145384 
1530734Smw145384 /*
1531734Smw145384  * read_mdrecord()
1532734Smw145384  *
1533734Smw145384  * Reads the mddb_rb32_od_t or mddb_rb_t and the associated metadevice record
1534734Smw145384  * from the disk.  Runs magic, checksum, and revision checks on the record
1535734Smw145384  * block.
1536734Smw145384  *
1537734Smw145384  * Returns:
1538734Smw145384  *	< 0 for failure
1539734Smw145384  *	  0 for success
1540734Smw145384  *
1541734Smw145384  */
1542734Smw145384 static int
read_mdrecord(md_im_rec_t ** mdimpp,mddb_mb_t * mbp,mddb_rb_t * nm,mddb_de_t * dep,char * diskname,int fd,md_timeval32_t * lastaccess,md_error_t * ep)1543734Smw145384 read_mdrecord(
1544734Smw145384 	md_im_rec_t	**mdimpp,
1545734Smw145384 	mddb_mb_t	*mbp,
1546734Smw145384 	mddb_rb_t	*nm,
1547734Smw145384 	mddb_de_t	*dep,
1548734Smw145384 	char		*diskname,
1549734Smw145384 	int 		fd,
1550734Smw145384 	md_timeval32_t	*lastaccess,
1551734Smw145384 	md_error_t 	*ep
1552734Smw145384 )
1553734Smw145384 {
1554734Smw145384 	int		cnt, rval = 0;
1555734Smw145384 	daddr_t		pblk;
1556734Smw145384 	md_im_rec_t	*tmp_mdrec;
1557734Smw145384 	void 		*rbp = NULL;
1558734Smw145384 	char 		*rbp_tmp = NULL;
1559734Smw145384 	mddb_rb32_t	*rbp_32;
1560734Smw145384 	mddb_rb_t	*rbp_64;
1561734Smw145384 	crc_skip_t	*skip = NULL;
1562*1623Stw21770 	int		is_32bit_record;
1563734Smw145384 
1564734Smw145384 	tmp_mdrec = Zalloc(sizeof (md_im_rec_t));
1565734Smw145384 	rbp = (void *)Zalloc(dbtob(dep->de_blkcount));
1566734Smw145384 	rbp_tmp = (char *)rbp;
1567734Smw145384 
1568734Smw145384 	/* Read in the appropriate record and return configurations */
1569734Smw145384 	for (cnt = 0; cnt < dep->de_blkcount; cnt++) {
1570734Smw145384 		if ((pblk = getphysblk(dep->de_blks[cnt], mbp)) < 0) {
1571734Smw145384 			rval = mdmddberror(ep, MDE_DB_BLKRANGE,
1572734Smw145384 			    NODEV32, MD_LOCAL_SET,
1573734Smw145384 			    dep->de_blks[cnt], diskname);
1574734Smw145384 			return (rval);
1575734Smw145384 		}
1576734Smw145384 
1577734Smw145384 		if (lseek(fd, (off_t)dbtob(pblk), SEEK_SET) < 0) {
1578734Smw145384 			rval = mdsyserror(ep, errno, diskname);
1579734Smw145384 			return (rval);
1580734Smw145384 		}
1581734Smw145384 
1582734Smw145384 		if (read(fd, rbp_tmp, DEV_BSIZE) != DEV_BSIZE) {
1583734Smw145384 			rval = mdsyserror(ep, errno, diskname);
1584734Smw145384 			return (rval);
1585734Smw145384 		}
1586734Smw145384 
1587734Smw145384 		rbp_tmp += DEV_BSIZE;
1588734Smw145384 	}
1589734Smw145384 	tmp_mdrec->md_type = dep->de_flags;
1590734Smw145384 
1591734Smw145384 	/*
1592734Smw145384 	 * The only place to discover whether or not the record is a
1593734Smw145384 	 * 32bit or 64bit record is from the record's rb_revision field.
1594734Smw145384 	 * The mddb_rb_t and mddb_rb32_t structures are identical for the
1595734Smw145384 	 * following fields:
1596734Smw145384 	 *	rb_magic, rb_revision, rb_checksum, and rb_checksum_fiddle.
1597734Smw145384 	 * So we can assume that the record is a 32bit structure when we
1598734Smw145384 	 * check the record's magic number and revision and when we calculate
1599734Smw145384 	 * the records checksum.
1600734Smw145384 	 */
1601734Smw145384 	rbp_32 = (mddb_rb32_t *)rbp;
1602734Smw145384 
1603734Smw145384 	/*
1604734Smw145384 	 * Checking the magic number for the record block.
1605734Smw145384 	 */
1606734Smw145384 	if (rbp_32->rb_magic != MDDB_MAGIC_RB) {
1607734Smw145384 		rval = -1;
1608734Smw145384 		(void) mdmddberror(ep, MDE_DB_NODB, 0, 0, 0, NULL);
1609734Smw145384 		goto out;
1610734Smw145384 	}
1611734Smw145384 
1612734Smw145384 	/*
1613734Smw145384 	 * Checking the revision for the record block. Must match either
1614734Smw145384 	 * revision for the current 64bit or 32bit record block.  Also,
1615734Smw145384 	 * setting the flag for whether or not it is a 32bit record.
1616734Smw145384 	 */
1617*1623Stw21770 	is_32bit_record = 0;
1618*1623Stw21770 	switch (rbp_32->rb_revision) {
1619*1623Stw21770 	case MDDB_REV_RB:
1620*1623Stw21770 	case MDDB_REV_RBFN:
1621734Smw145384 		is_32bit_record = 1;
1622*1623Stw21770 		break;
1623*1623Stw21770 	case MDDB_REV_RB64:
1624*1623Stw21770 	case MDDB_REV_RB64FN:
1625*1623Stw21770 		break;
1626*1623Stw21770 	default:
1627734Smw145384 		rval = -1;
1628734Smw145384 		(void) mdmddberror(ep, MDE_DB_NODB, 0, 0, 0, NULL);
1629734Smw145384 		goto out;
1630734Smw145384 	}
1631734Smw145384 
1632734Smw145384 	/*
1633734Smw145384 	 * Calculating the checksum for this record block. Need
1634734Smw145384 	 * to skip the rb's checksum fiddle.
1635734Smw145384 	 */
1636734Smw145384 	skip = (crc_skip_t *)Malloc(sizeof (crc_skip_t));
1637734Smw145384 	skip->skip_next = NULL;
1638734Smw145384 	skip->skip_offset = offsetof(mddb_rb_t, rb_checksum_fiddle);
1639734Smw145384 	skip->skip_size = 3 * sizeof (uint_t);
1640734Smw145384 	if (crcchk(rbp_32, &rbp_32->rb_checksum, dep->de_recsize, skip)) {
1641734Smw145384 		rval = -1;
1642734Smw145384 		(void) mdmddberror(ep, MDE_DB_NODB, 0, 0, 0, NULL);
1643734Smw145384 		goto out;
1644734Smw145384 	}
1645734Smw145384 
1646734Smw145384 	/* mddb_rb_t and mddb_rb32_t differ before the rb_timestamp field */
1647734Smw145384 	if (!is_32bit_record) {
1648734Smw145384 		if ((*lastaccess).tv_sec < rbp_32->rb_timestamp.tv_sec) {
1649734Smw145384 		    *lastaccess = rbp_32->rb_timestamp;
1650734Smw145384 		} else if ((*lastaccess).tv_sec ==
1651734Smw145384 		    rbp_32->rb_timestamp.tv_sec) {
1652734Smw145384 			if ((*lastaccess).tv_usec <
1653734Smw145384 			    rbp_32->rb_timestamp.tv_usec)
1654734Smw145384 				*lastaccess = rbp_32->rb_timestamp;
1655734Smw145384 		}
1656734Smw145384 	} else {
1657734Smw145384 		rbp_64 = (mddb_rb_t *)rbp;
1658734Smw145384 		if ((*lastaccess).tv_sec < rbp_64->rb_timestamp.tv_sec) {
1659734Smw145384 		    *lastaccess = rbp_64->rb_timestamp;
1660734Smw145384 		} else if ((*lastaccess).tv_sec ==
1661734Smw145384 		    rbp_64->rb_timestamp.tv_sec) {
1662734Smw145384 			if ((*lastaccess).tv_usec <
1663734Smw145384 			    rbp_64->rb_timestamp.tv_usec)
1664734Smw145384 				*lastaccess = rbp_64->rb_timestamp;
1665734Smw145384 		}
1666734Smw145384 	}
1667734Smw145384 
1668734Smw145384 	/* Populates the fields in md_im_rec_t *tmp_mdrec. */
1669734Smw145384 	rval = extract_mduser_data(nm, tmp_mdrec, rbp, is_32bit_record, ep);
1670734Smw145384 	if (rval < 0)
1671734Smw145384 		goto out;
1672734Smw145384 
1673734Smw145384 	/* Adding record to the head of the list of all metadevices. */
1674734Smw145384 	tmp_mdrec->prev = NULL;
1675734Smw145384 	if (*mdimpp == NULL) {
1676734Smw145384 		tmp_mdrec->next = NULL;
1677734Smw145384 		*mdimpp = tmp_mdrec;
1678734Smw145384 	} else {
1679734Smw145384 		(*mdimpp)->prev = tmp_mdrec;
1680734Smw145384 		tmp_mdrec->next = *mdimpp;
1681734Smw145384 		*mdimpp = tmp_mdrec;
1682734Smw145384 	}
1683734Smw145384 
1684734Smw145384 out:
1685734Smw145384 	/* Free the skip list */
1686734Smw145384 	while (skip) {
1687734Smw145384 		crc_skip_t	*skip_rm = skip;
1688734Smw145384 
1689734Smw145384 		skip = skip->skip_next;
1690734Smw145384 		Free(skip_rm);
1691734Smw145384 	}
1692734Smw145384 
1693734Smw145384 	if (rbp)
1694734Smw145384 		Free(rbp);
1695734Smw145384 
1696734Smw145384 	return (rval);
1697734Smw145384 }
1698734Smw145384 
1699734Smw145384 
1700734Smw145384 /*
1701734Smw145384  * read_all_mdrecords()
1702734Smw145384  *
1703734Smw145384  * Reads the directory block and directory entries.
1704734Smw145384  * Runs magic, checksum, and revision checks on the directory block.
1705734Smw145384  *
1706734Smw145384  * Returns:
1707734Smw145384  *	< 0 for failure
1708734Smw145384  *	  0 for success
1709734Smw145384  */
1710734Smw145384 static int
read_all_mdrecords(md_im_rec_t ** mdimpp,mddb_mb_t * mbp,mddb_lb_t * lbp,mddb_rb_t * nm,mdname_t * rsp,int fd,md_timeval32_t * lastaccess,md_error_t * ep)1711734Smw145384 read_all_mdrecords(
1712734Smw145384 	md_im_rec_t	**mdimpp,
1713734Smw145384 	mddb_mb_t	*mbp,
1714734Smw145384 	mddb_lb_t	*lbp,
1715734Smw145384 	mddb_rb_t	*nm,
1716734Smw145384 	mdname_t	*rsp,
1717734Smw145384 	int 		fd,
1718734Smw145384 	md_timeval32_t	*lastaccess,
1719734Smw145384 	md_error_t 	*ep
1720734Smw145384 )
1721734Smw145384 {
1722734Smw145384 	int		dbblk, rval = 0;
1723734Smw145384 	char		db[DEV_BSIZE];
1724734Smw145384 	mddb_de_t	*dep;
1725734Smw145384 	int		desize;
1726734Smw145384 	/*LINTED*/
1727734Smw145384 	mddb_db_t	*dbp = (mddb_db_t *)&db;
1728734Smw145384 
1729734Smw145384 	/* Read in all directory blocks */
1730734Smw145384 	for (dbblk = lbp->lb_dbfirstblk;
1731734Smw145384 	    dbblk != 0;
1732734Smw145384 	    dbblk = dbp->db_nextblk) {
1733734Smw145384 
1734734Smw145384 		if ((rval = read_database_block(ep, fd, mbp, dbblk,
1735734Smw145384 		    dbp, sizeof (db))) <= 0)
1736734Smw145384 			goto out;
1737734Smw145384 
1738734Smw145384 		/*
1739734Smw145384 		 * Set ep with error code for MDE_DB_NODB.  This is the
1740734Smw145384 		 * error code used in the kernel when there is a problem
1741734Smw145384 		 * with reading records in.  Checks the magic number, the
1742734Smw145384 		 * revision, and the checksum for each directory block.
1743734Smw145384 		 */
1744734Smw145384 		if (dbp->db_magic != MDDB_MAGIC_DB) {
1745734Smw145384 			rval = -1;
1746734Smw145384 			(void) mdmddberror(ep, MDE_DB_NODB, 0, 0, 0, NULL);
1747734Smw145384 			goto out;
1748734Smw145384 		}
1749734Smw145384 
1750734Smw145384 		if (revchk(MDDB_REV_DB, dbp->db_revision)) {
1751734Smw145384 			rval = -1;
1752734Smw145384 			(void) mdmddberror(ep, MDE_DB_NODB, 0, 0, 0, NULL);
1753734Smw145384 			goto out;
1754734Smw145384 		}
1755734Smw145384 
1756734Smw145384 		if (crcchk(dbp, &dbp->db_checksum, MDDB_BSIZE, NULL)) {
1757734Smw145384 			rval = -1;
1758734Smw145384 			(void) mdmddberror(ep, MDE_DB_NODB, 0, 0, 0, NULL);
1759734Smw145384 			goto out;
1760734Smw145384 		}
1761734Smw145384 
1762734Smw145384 		/*
1763734Smw145384 		 * If db timestamp is more recent than the previously recorded
1764734Smw145384 		 * last modified timestamp, then update last modified.
1765734Smw145384 		 */
1766734Smw145384 		if ((*lastaccess).tv_sec < dbp->db_timestamp.tv_sec) {
1767734Smw145384 			*lastaccess = dbp->db_timestamp;
1768734Smw145384 		} else if ((*lastaccess).tv_sec == dbp->db_timestamp.tv_sec) {
1769734Smw145384 			if ((*lastaccess).tv_usec < dbp->db_timestamp.tv_usec)
1770734Smw145384 				*lastaccess = dbp->db_timestamp;
1771734Smw145384 		}
1772734Smw145384 
1773734Smw145384 		/* Creates dep list of all directory entries in the db */
1774734Smw145384 		if (dbp->db_firstentry != NULL) {
1775734Smw145384 			/* LINTED */
1776734Smw145384 			dep = (mddb_de_t *)((caddr_t)(&dbp->db_firstentry)
1777734Smw145384 			    + sizeof (dbp->db_firstentry));
1778734Smw145384 			dbp->db_firstentry = dep;
1779734Smw145384 			while (dep && dep->de_next) {
1780734Smw145384 				desize = sizeof (*dep) -
1781734Smw145384 				    sizeof (dep->de_blks) +
1782734Smw145384 				    sizeof (daddr_t) * dep->de_blkcount;
1783734Smw145384 				/* LINTED */
1784734Smw145384 				dep->de_next = (mddb_de_t *)
1785734Smw145384 				    ((caddr_t)dep + desize);
1786734Smw145384 				dep = dep->de_next;
1787734Smw145384 			}
1788734Smw145384 		}
1789734Smw145384 
1790734Smw145384 		/*
1791734Smw145384 		 * Process all directory entries in the directory block.
1792734Smw145384 		 * For each directory entry, read_mdrec is called to read
1793734Smw145384 		 * in the record data.
1794734Smw145384 		 */
1795734Smw145384 		for (dep = dbp->db_firstentry; dep != NULL;
1796734Smw145384 		    dep = dep->de_next) {
1797734Smw145384 
1798734Smw145384 			/*
1799734Smw145384 			 * de_flags is set to the type of metadevice.
1800734Smw145384 			 * If directory entry does not correspond to a
1801734Smw145384 			 * specific metadevice then it is set to zero.
1802734Smw145384 			 * All namespace records(NM, SHR_NM, DID_SHR_NM) have a
1803734Smw145384 			 * value of zero in their de_flags field.
1804734Smw145384 			 */
1805734Smw145384 			if ((dep->de_flags != 0)&&
1806734Smw145384 			    (dep->de_flags != MDDB_F_OPT) &&
1807734Smw145384 			    (dep->de_flags != MDDB_F_TRANS_LOG) &&
1808734Smw145384 			    (dep->de_flags != MDDB_F_CHANGELOG)) {
1809734Smw145384 				rval = read_mdrecord(mdimpp, mbp, nm, dep,
1810734Smw145384 				    rsp->cname, fd, lastaccess, ep);
1811734Smw145384 				if (rval < 0)
1812734Smw145384 					goto out;
1813734Smw145384 			}
1814734Smw145384 		}
1815734Smw145384 	}
1816734Smw145384 
1817734Smw145384 out:
1818734Smw145384 	return (rval);
1819734Smw145384 }
1820734Smw145384 
1821734Smw145384 
1822734Smw145384 /*
1823734Smw145384  * report_metastat_info()
1824734Smw145384  *
1825734Smw145384  * Generates the metastat -c output.  Also, updates the global variable
1826734Smw145384  * for a last accessed timestamp.
1827734Smw145384  *
1828734Smw145384  * Returns:
1829734Smw145384  *	< 0 for failure
1830734Smw145384  *	  0 for success
1831734Smw145384  *
1832734Smw145384  */
1833734Smw145384 int
report_metastat_info(mddb_mb_t * mb,mddb_lb_t * lbp,mddb_rb_t * nm,pnm_rec_t ** pnm,mdname_t * rsp,int fd,md_timeval32_t * lastaccess,md_error_t * ep)1834734Smw145384 report_metastat_info(
1835734Smw145384 	mddb_mb_t		*mb,
1836734Smw145384 	mddb_lb_t		*lbp,
1837734Smw145384 	mddb_rb_t		*nm,
1838734Smw145384 	pnm_rec_t		**pnm,
1839734Smw145384 	mdname_t		*rsp,
1840734Smw145384 	int			fd,
1841734Smw145384 	md_timeval32_t		*lastaccess,
1842734Smw145384 	md_error_t		*ep
1843734Smw145384 )
1844734Smw145384 {
1845734Smw145384 	int rval = 0;
1846734Smw145384 	/* list of all metadevices in diskset */
1847734Smw145384 	md_im_rec_t	*mdimp = NULL;
1848734Smw145384 	md_im_rec_t	*tmp_mdrec, *rm_mdrec;
1849734Smw145384 
1850734Smw145384 	/* Read in metadevice records and add entries to mdimp list. */
1851734Smw145384 	rval = read_all_mdrecords(&mdimp, mb, lbp, nm, rsp, fd, lastaccess,
1852734Smw145384 	    ep);
1853734Smw145384 	if (rval < 0)
1854734Smw145384 		goto out;
1855734Smw145384 
1856734Smw145384 	/* Adding a fake record to the head of the list of all metadevices. */
1857734Smw145384 	if (mdimp != NULL) {
1858734Smw145384 		tmp_mdrec = Zalloc(sizeof (md_im_rec_t));
1859734Smw145384 		tmp_mdrec->prev = NULL;
1860734Smw145384 		mdimp->prev = tmp_mdrec;
1861734Smw145384 		tmp_mdrec->next = mdimp;
1862734Smw145384 		mdimp = tmp_mdrec;
1863734Smw145384 	}
1864734Smw145384 
1865734Smw145384 	/* Calling functions to process all metadevices on mdimp list */
1866734Smw145384 	process_toplevel_devices(&mdimp, *pnm, MDDB_F_SOFTPART);
1867734Smw145384 	process_toplevel_devices(&mdimp, *pnm, MDDB_F_TRANS_MASTER);
1868734Smw145384 	process_toplevel_devices(&mdimp, *pnm, MDDB_F_MIRROR);
1869734Smw145384 	process_toplevel_devices(&mdimp, *pnm, MDDB_F_RAID);
1870734Smw145384 	process_toplevel_devices(&mdimp, *pnm, MDDB_F_STRIPE);
1871734Smw145384 	process_toplevel_devices(&mdimp, *pnm, MDDB_F_HOTSPARE_POOL);
1872734Smw145384 	(void) printf("\n");
1873734Smw145384 
1874734Smw145384 out:
1875734Smw145384 	/*
1876734Smw145384 	 * If mdreclist is not null, then this will walk through all
1877734Smw145384 	 * elements and free them.
1878734Smw145384 	 */
1879734Smw145384 	tmp_mdrec = mdimp;
1880734Smw145384 	while (tmp_mdrec != NULL) {
1881734Smw145384 		rm_mdrec = tmp_mdrec;
1882734Smw145384 		tmp_mdrec = tmp_mdrec->next;
1883734Smw145384 		if (rm_mdrec->record != NULL)
1884734Smw145384 			Free(rm_mdrec->record);
1885734Smw145384 		if (rm_mdrec->n_name != NULL)
1886734Smw145384 			Free(rm_mdrec->n_name);
1887734Smw145384 		Free(rm_mdrec);
1888734Smw145384 	}
1889734Smw145384 
1890734Smw145384 	free_pnm_rec_list(pnm);
1891734Smw145384 	return (rval);
1892734Smw145384 }
1893