10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
51945Sjeanm * Common Development and Distribution License (the "License").
61945Sjeanm * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
22*4901Sjr26306 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
230Sstevel@tonic-gate * Use is subject to license terms.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
270Sstevel@tonic-gate
280Sstevel@tonic-gate #include <assert.h>
290Sstevel@tonic-gate #include <ctype.h>
300Sstevel@tonic-gate #include <libdevinfo.h>
310Sstevel@tonic-gate #include <mdiox.h>
320Sstevel@tonic-gate #include <meta.h>
330Sstevel@tonic-gate #include "meta_repartition.h"
340Sstevel@tonic-gate #include "meta_set_prv.h"
350Sstevel@tonic-gate #include <stdio.h>
360Sstevel@tonic-gate #include <stdlib.h>
37734Smw145384 #include <strings.h>
380Sstevel@tonic-gate #include <sys/lvm/md_mddb.h>
390Sstevel@tonic-gate #include <sys/lvm/md_names.h>
400Sstevel@tonic-gate #include <sys/lvm/md_crc.h>
41734Smw145384 #include <sys/lvm/md_convert.h>
420Sstevel@tonic-gate
430Sstevel@tonic-gate typedef struct did_list {
440Sstevel@tonic-gate void *rdid; /* real did if replicated set */
450Sstevel@tonic-gate void *did; /* did stored in lb */
460Sstevel@tonic-gate char *devname;
470Sstevel@tonic-gate dev_t dev;
480Sstevel@tonic-gate uint_t did_index;
490Sstevel@tonic-gate char *minor_name;
501945Sjeanm char *driver_name;
511945Sjeanm int available;
520Sstevel@tonic-gate struct did_list *next;
530Sstevel@tonic-gate } did_list_t;
540Sstevel@tonic-gate
550Sstevel@tonic-gate typedef struct replicated_disk {
560Sstevel@tonic-gate void *old_devid;
570Sstevel@tonic-gate void *new_devid;
580Sstevel@tonic-gate struct replicated_disk *next;
590Sstevel@tonic-gate } replicated_disk_t;
600Sstevel@tonic-gate
610Sstevel@tonic-gate /*
620Sstevel@tonic-gate * The current implementation limits the max device id length to 256 bytes.
63734Smw145384 * Should the max device id length be increased, this definition would have to
640Sstevel@tonic-gate * be bumped up accordingly
650Sstevel@tonic-gate */
660Sstevel@tonic-gate #define MAX_DEVID_LEN 256
670Sstevel@tonic-gate
680Sstevel@tonic-gate /*
690Sstevel@tonic-gate * We store a global list of all the replicated disks in the system. In
700Sstevel@tonic-gate * order to prevent us from performing a linear search on this list, we
710Sstevel@tonic-gate * store the disks in a two dimensional sparse array. The disks are bucketed
720Sstevel@tonic-gate * based on the length of their device ids.
730Sstevel@tonic-gate */
740Sstevel@tonic-gate static replicated_disk_t *replicated_disk_list[MAX_DEVID_LEN + 1] = {NULL};
750Sstevel@tonic-gate
760Sstevel@tonic-gate /*
770Sstevel@tonic-gate * The list of replicated disks is built just once and this flag is set
780Sstevel@tonic-gate * once it's done
790Sstevel@tonic-gate */
801945Sjeanm int replicated_disk_list_built_pass1 = 0;
811945Sjeanm int replicated_disk_list_built_pass2 = 0;
821945Sjeanm int *replicated_disk_list_built;
831945Sjeanm
841945Sjeanm static void free_did_list(did_list_t *did_listp);
850Sstevel@tonic-gate
860Sstevel@tonic-gate /*
870Sstevel@tonic-gate * Map logical blk to physical
880Sstevel@tonic-gate *
890Sstevel@tonic-gate * This is based on the routine of the same name in the md kernel module (see
900Sstevel@tonic-gate * file md_mddb.c), with the following caveats:
910Sstevel@tonic-gate *
920Sstevel@tonic-gate * - The kernel routine works on in core master blocks, or mddb_mb_ic_t; this
930Sstevel@tonic-gate * routine works instead on the mddb_mb_t read directly from the disk
940Sstevel@tonic-gate */
95734Smw145384 daddr_t
getphysblk(mddb_block_t blk,mddb_mb_t * mbp)960Sstevel@tonic-gate getphysblk(
970Sstevel@tonic-gate mddb_block_t blk,
980Sstevel@tonic-gate mddb_mb_t *mbp
990Sstevel@tonic-gate )
1000Sstevel@tonic-gate {
1010Sstevel@tonic-gate /*
1020Sstevel@tonic-gate * Sanity check: is the block within range? If so, we then assume
1030Sstevel@tonic-gate * that the block range map in the master block is valid and
1040Sstevel@tonic-gate * consistent with the block count. Unfortunately, there is no
1050Sstevel@tonic-gate * reliable way to validate this assumption.
1060Sstevel@tonic-gate */
1070Sstevel@tonic-gate if (blk >= mbp->mb_blkcnt || blk >= mbp->mb_blkmap.m_consecutive)
1080Sstevel@tonic-gate return ((daddr_t)-1);
1090Sstevel@tonic-gate
1100Sstevel@tonic-gate return (mbp->mb_blkmap.m_firstblk + blk);
1110Sstevel@tonic-gate }
1120Sstevel@tonic-gate
1130Sstevel@tonic-gate
1140Sstevel@tonic-gate
1150Sstevel@tonic-gate /*
1160Sstevel@tonic-gate * drive_append()
1170Sstevel@tonic-gate *
1180Sstevel@tonic-gate * Append to tail of linked list of md_im_drive_info_t.
1190Sstevel@tonic-gate *
1200Sstevel@tonic-gate * Will allocate space for new node and copy args into new space.
1210Sstevel@tonic-gate *
1220Sstevel@tonic-gate * Returns pointer to new node.
1230Sstevel@tonic-gate */
1240Sstevel@tonic-gate static md_im_drive_info_t *
drive_append(md_im_drive_info_t ** midpp,mddrivename_t * dnp,did_list_t * nonrep_did_listp,minor_t mnum,md_timeval32_t timestamp,md_im_replica_info_t * mirp)1250Sstevel@tonic-gate drive_append(
1260Sstevel@tonic-gate md_im_drive_info_t **midpp,
1270Sstevel@tonic-gate mddrivename_t *dnp,
1281945Sjeanm did_list_t *nonrep_did_listp,
1291945Sjeanm minor_t mnum,
1300Sstevel@tonic-gate md_timeval32_t timestamp,
1310Sstevel@tonic-gate md_im_replica_info_t *mirp
1320Sstevel@tonic-gate )
1330Sstevel@tonic-gate {
1340Sstevel@tonic-gate md_im_drive_info_t *midp;
1350Sstevel@tonic-gate int o_devid_sz;
1361945Sjeanm int devid_sz;
1370Sstevel@tonic-gate
1380Sstevel@tonic-gate for (; (*midpp != NULL); midpp = &((*midpp)->mid_next))
1390Sstevel@tonic-gate ;
1400Sstevel@tonic-gate
1410Sstevel@tonic-gate midp = *midpp = Zalloc(sizeof (md_im_drive_info_t));
1420Sstevel@tonic-gate
1430Sstevel@tonic-gate midp->mid_dnp = dnp;
1440Sstevel@tonic-gate
1450Sstevel@tonic-gate /*
1461945Sjeanm * If rdid is not NULL then we know we are dealing with
1470Sstevel@tonic-gate * replicated diskset case. 'devid_sz' will always be the
1481945Sjeanm * size of a valid devid which can be 'did' or 'rdid'
1490Sstevel@tonic-gate */
1501945Sjeanm
1511945Sjeanm if (nonrep_did_listp->rdid) {
1521945Sjeanm devid_sz = devid_sizeof(nonrep_did_listp->rdid);
1531945Sjeanm midp->mid_devid = (void *)Malloc(devid_sz);
1541945Sjeanm (void) memcpy(midp->mid_devid, nonrep_did_listp->rdid,
1551945Sjeanm devid_sz);
1560Sstevel@tonic-gate /*
1570Sstevel@tonic-gate * Also need to store the 'other' devid
1580Sstevel@tonic-gate */
1591945Sjeanm o_devid_sz = devid_sizeof((ddi_devid_t)(nonrep_did_listp->did));
1600Sstevel@tonic-gate midp->mid_o_devid = (void *)Malloc(o_devid_sz);
1611945Sjeanm (void) memcpy(midp->mid_o_devid, nonrep_did_listp->did,
1621945Sjeanm o_devid_sz);
1630Sstevel@tonic-gate midp->mid_o_devid_sz = o_devid_sz;
1640Sstevel@tonic-gate } else {
1651945Sjeanm devid_sz = devid_sizeof(nonrep_did_listp->did);
1661945Sjeanm midp->mid_devid = (void *)Malloc(devid_sz);
1670Sstevel@tonic-gate /*
1680Sstevel@tonic-gate * In the case of regular diskset, midp->mid_o_devid
1690Sstevel@tonic-gate * will be a NULL pointer
1700Sstevel@tonic-gate */
1711945Sjeanm (void) memcpy(midp->mid_devid, nonrep_did_listp->did, devid_sz);
1720Sstevel@tonic-gate }
1730Sstevel@tonic-gate
1740Sstevel@tonic-gate midp->mid_devid_sz = devid_sz;
1750Sstevel@tonic-gate midp->mid_setcreatetimestamp = timestamp;
1761945Sjeanm midp->mid_available = nonrep_did_listp->available;
1771945Sjeanm if (nonrep_did_listp->minor_name) {
1781945Sjeanm (void) strlcpy(midp->mid_minor_name,
1791945Sjeanm nonrep_did_listp->minor_name, MDDB_MINOR_NAME_MAX);
1801945Sjeanm }
1811945Sjeanm midp->mid_mnum = mnum;
1821945Sjeanm if (nonrep_did_listp->driver_name)
1831945Sjeanm midp->mid_driver_name = Strdup(nonrep_did_listp->driver_name);
1840Sstevel@tonic-gate midp->mid_replicas = mirp;
1851945Sjeanm if (nonrep_did_listp->devname)
1861945Sjeanm midp->mid_devname = Strdup(nonrep_did_listp->devname);
1870Sstevel@tonic-gate return (midp);
1880Sstevel@tonic-gate }
1890Sstevel@tonic-gate
1900Sstevel@tonic-gate
1910Sstevel@tonic-gate
1920Sstevel@tonic-gate /*
1930Sstevel@tonic-gate * drive_append_wrapper()
1940Sstevel@tonic-gate *
1950Sstevel@tonic-gate * Constant time append wrapper; the append function will always walk the list,
1960Sstevel@tonic-gate * this will take a tail argument and use the append function on just the tail
1970Sstevel@tonic-gate * node, doing the appropriate old-tail-next-pointer bookkeeping.
1980Sstevel@tonic-gate */
1990Sstevel@tonic-gate static md_im_drive_info_t **
drive_append_wrapper(md_im_drive_info_t ** tailpp,mddrivename_t * dnp,did_list_t * nonrep_did_listp,minor_t mnum,md_timeval32_t timestamp,md_im_replica_info_t * mirp)2000Sstevel@tonic-gate drive_append_wrapper(
2010Sstevel@tonic-gate md_im_drive_info_t **tailpp,
2020Sstevel@tonic-gate mddrivename_t *dnp,
2031945Sjeanm did_list_t *nonrep_did_listp,
2041945Sjeanm minor_t mnum,
2050Sstevel@tonic-gate md_timeval32_t timestamp,
2060Sstevel@tonic-gate md_im_replica_info_t *mirp
2070Sstevel@tonic-gate )
2080Sstevel@tonic-gate {
2091945Sjeanm (void) drive_append(tailpp, dnp, nonrep_did_listp, mnum, timestamp,
2101945Sjeanm mirp);
2110Sstevel@tonic-gate
2120Sstevel@tonic-gate if ((*tailpp)->mid_next == NULL)
2130Sstevel@tonic-gate return (tailpp);
2140Sstevel@tonic-gate
2150Sstevel@tonic-gate return (&((*tailpp)->mid_next));
2160Sstevel@tonic-gate }
2170Sstevel@tonic-gate
2180Sstevel@tonic-gate
2190Sstevel@tonic-gate
2200Sstevel@tonic-gate /*
2210Sstevel@tonic-gate * replica_append()
2220Sstevel@tonic-gate *
2230Sstevel@tonic-gate * Append to tail of linked list of md_im_replica_info_t.
2240Sstevel@tonic-gate *
2250Sstevel@tonic-gate * Will allocate space for new node and copy args into new space.
2260Sstevel@tonic-gate *
2270Sstevel@tonic-gate * Returns pointer to new node.
2280Sstevel@tonic-gate */
2290Sstevel@tonic-gate static md_im_replica_info_t *
replica_append(md_im_replica_info_t ** mirpp,int flags,daddr32_t offset,daddr32_t length,md_timeval32_t timestamp)2300Sstevel@tonic-gate replica_append(
2310Sstevel@tonic-gate md_im_replica_info_t **mirpp,
2320Sstevel@tonic-gate int flags,
2330Sstevel@tonic-gate daddr32_t offset,
2340Sstevel@tonic-gate daddr32_t length,
2350Sstevel@tonic-gate md_timeval32_t timestamp
2360Sstevel@tonic-gate )
2370Sstevel@tonic-gate {
2380Sstevel@tonic-gate md_im_replica_info_t *mirp;
2390Sstevel@tonic-gate
2400Sstevel@tonic-gate for (; (*mirpp != NULL); mirpp = &((*mirpp)->mir_next))
2410Sstevel@tonic-gate ;
2420Sstevel@tonic-gate
2430Sstevel@tonic-gate mirp = *mirpp = Zalloc(sizeof (md_im_replica_info_t));
2440Sstevel@tonic-gate
2450Sstevel@tonic-gate mirp->mir_flags = flags;
2460Sstevel@tonic-gate mirp->mir_offset = offset;
2470Sstevel@tonic-gate mirp->mir_length = length;
2480Sstevel@tonic-gate mirp->mir_timestamp = timestamp;
2490Sstevel@tonic-gate
2500Sstevel@tonic-gate return (mirp);
2510Sstevel@tonic-gate
2520Sstevel@tonic-gate }
2530Sstevel@tonic-gate
2540Sstevel@tonic-gate
2550Sstevel@tonic-gate
2560Sstevel@tonic-gate /*
2570Sstevel@tonic-gate * replica_append_wrapper()
2580Sstevel@tonic-gate *
2590Sstevel@tonic-gate * Constant time append wrapper; the append function will always walk the list,
2600Sstevel@tonic-gate * this will take a tail argument and use the append function on just the tail
2610Sstevel@tonic-gate * node, doing the appropriate old-tail-next-pointer bookkeeping.
2620Sstevel@tonic-gate */
2630Sstevel@tonic-gate static md_im_replica_info_t **
replica_append_wrapper(md_im_replica_info_t ** tailpp,int flags,daddr32_t offset,daddr32_t length,md_timeval32_t timestamp)2640Sstevel@tonic-gate replica_append_wrapper(
2650Sstevel@tonic-gate md_im_replica_info_t **tailpp,
2660Sstevel@tonic-gate int flags,
2670Sstevel@tonic-gate daddr32_t offset,
2680Sstevel@tonic-gate daddr32_t length,
2690Sstevel@tonic-gate md_timeval32_t timestamp
2700Sstevel@tonic-gate )
2710Sstevel@tonic-gate {
2720Sstevel@tonic-gate (void) replica_append(tailpp, flags, offset, length, timestamp);
2730Sstevel@tonic-gate
2740Sstevel@tonic-gate if ((*tailpp)->mir_next == NULL)
2750Sstevel@tonic-gate return (tailpp);
2760Sstevel@tonic-gate
2770Sstevel@tonic-gate return (&(*tailpp)->mir_next);
2780Sstevel@tonic-gate }
2790Sstevel@tonic-gate
2800Sstevel@tonic-gate /*
2810Sstevel@tonic-gate * map_replica_disk()
2820Sstevel@tonic-gate *
2830Sstevel@tonic-gate * Searches the device id list for a specific
2840Sstevel@tonic-gate * disk based on the locator block device id array index.
2850Sstevel@tonic-gate *
2860Sstevel@tonic-gate * Returns a pointer to the did_list node if a match was
2870Sstevel@tonic-gate * found or NULL otherwise.
2880Sstevel@tonic-gate */
2890Sstevel@tonic-gate static did_list_t *
map_replica_disk(did_list_t * did_listp,int did_index)2900Sstevel@tonic-gate map_replica_disk(
2910Sstevel@tonic-gate did_list_t *did_listp,
2920Sstevel@tonic-gate int did_index
2930Sstevel@tonic-gate )
2940Sstevel@tonic-gate {
2950Sstevel@tonic-gate did_list_t *tailp = did_listp;
2960Sstevel@tonic-gate
2970Sstevel@tonic-gate while (tailp != NULL) {
2980Sstevel@tonic-gate if (tailp->did_index == did_index)
2990Sstevel@tonic-gate return (tailp);
3000Sstevel@tonic-gate tailp = tailp->next;
3010Sstevel@tonic-gate }
3020Sstevel@tonic-gate
3030Sstevel@tonic-gate /* not found, return failure */
3040Sstevel@tonic-gate return (NULL);
3050Sstevel@tonic-gate }
3060Sstevel@tonic-gate
3070Sstevel@tonic-gate /*
3080Sstevel@tonic-gate * replicated_list_lookup()
3090Sstevel@tonic-gate *
3100Sstevel@tonic-gate * looks up a replicated disk entry in the global replicated disk list
3110Sstevel@tonic-gate * based upon the length of that disk's device id. returns the new device id
3120Sstevel@tonic-gate * for the disk.
3130Sstevel@tonic-gate * If you store the returned devid you must create a local copy.
3140Sstevel@tonic-gate */
3151945Sjeanm void *
replicated_list_lookup(uint_t devid_len,void * old_devid)3160Sstevel@tonic-gate replicated_list_lookup(
3170Sstevel@tonic-gate uint_t devid_len,
3180Sstevel@tonic-gate void *old_devid
3190Sstevel@tonic-gate )
3200Sstevel@tonic-gate {
3210Sstevel@tonic-gate replicated_disk_t *head = NULL;
3220Sstevel@tonic-gate
3230Sstevel@tonic-gate assert(devid_len <= MAX_DEVID_LEN);
3240Sstevel@tonic-gate head = replicated_disk_list[devid_len];
3250Sstevel@tonic-gate
3260Sstevel@tonic-gate if (head == NULL)
3270Sstevel@tonic-gate return (NULL);
3280Sstevel@tonic-gate
3290Sstevel@tonic-gate do {
3300Sstevel@tonic-gate if (devid_compare((ddi_devid_t)old_devid,
3310Sstevel@tonic-gate (ddi_devid_t)head->old_devid) == 0)
3320Sstevel@tonic-gate return (head->new_devid);
3330Sstevel@tonic-gate head = head->next;
3340Sstevel@tonic-gate } while (head != NULL);
3350Sstevel@tonic-gate
3360Sstevel@tonic-gate return (NULL);
3370Sstevel@tonic-gate }
3380Sstevel@tonic-gate
3390Sstevel@tonic-gate /*
3400Sstevel@tonic-gate * replicated_list_insert()
3410Sstevel@tonic-gate *
3420Sstevel@tonic-gate * inserts a replicated disk entry into the global replicated disk list
3430Sstevel@tonic-gate */
3440Sstevel@tonic-gate static void
replicated_list_insert(size_t old_devid_len,void * old_devid,void * new_devid)3450Sstevel@tonic-gate replicated_list_insert(
3460Sstevel@tonic-gate size_t old_devid_len,
3470Sstevel@tonic-gate void *old_devid,
3480Sstevel@tonic-gate void *new_devid
3490Sstevel@tonic-gate )
3500Sstevel@tonic-gate {
3510Sstevel@tonic-gate replicated_disk_t *repl_disk, **first_entry;
3520Sstevel@tonic-gate void *repl_old_devid = NULL;
3530Sstevel@tonic-gate
3540Sstevel@tonic-gate assert(old_devid_len <= MAX_DEVID_LEN);
3550Sstevel@tonic-gate
3560Sstevel@tonic-gate repl_disk = Zalloc(sizeof (replicated_disk_t));
3570Sstevel@tonic-gate repl_old_devid = Zalloc(old_devid_len);
3580Sstevel@tonic-gate (void) memcpy(repl_old_devid, (void *)old_devid, old_devid_len);
3590Sstevel@tonic-gate
3600Sstevel@tonic-gate repl_disk->old_devid = repl_old_devid;
3610Sstevel@tonic-gate repl_disk->new_devid = new_devid;
3620Sstevel@tonic-gate
3630Sstevel@tonic-gate first_entry = &replicated_disk_list[old_devid_len];
3640Sstevel@tonic-gate
3650Sstevel@tonic-gate if (*first_entry == NULL) {
3660Sstevel@tonic-gate *first_entry = repl_disk;
3670Sstevel@tonic-gate return;
3680Sstevel@tonic-gate }
3690Sstevel@tonic-gate
3700Sstevel@tonic-gate repl_disk->next = *first_entry;
3710Sstevel@tonic-gate replicated_disk_list[old_devid_len] = repl_disk;
3720Sstevel@tonic-gate }
3730Sstevel@tonic-gate
3740Sstevel@tonic-gate /*
3750Sstevel@tonic-gate * get_replica_disks()
3760Sstevel@tonic-gate *
3770Sstevel@tonic-gate * Will step through the locator records in the supplied locator block, and add
3780Sstevel@tonic-gate * each one with an active replica to a supplied list of md_im_drive_info_t, and
3790Sstevel@tonic-gate * add the appropriate replicas to the md_im_replica_info_t contained therein.
3800Sstevel@tonic-gate */
3810Sstevel@tonic-gate static void
get_replica_disks(md_im_set_desc_t * misp,did_list_t * did_listp,mddb_mb_t * mb,mddb_lb_t * lbp,md_error_t * ep)3820Sstevel@tonic-gate get_replica_disks(
3830Sstevel@tonic-gate md_im_set_desc_t *misp,
3840Sstevel@tonic-gate did_list_t *did_listp,
3850Sstevel@tonic-gate mddb_mb_t *mb,
3860Sstevel@tonic-gate mddb_lb_t *lbp,
3871945Sjeanm md_error_t *ep
3880Sstevel@tonic-gate )
3890Sstevel@tonic-gate {
3900Sstevel@tonic-gate mddrivename_t *dnp;
3910Sstevel@tonic-gate int indx, on_list;
3920Sstevel@tonic-gate mdsetname_t *sp = metasetname(MD_LOCAL_NAME, ep);
3930Sstevel@tonic-gate int flags;
3940Sstevel@tonic-gate did_list_t *replica_disk;
3950Sstevel@tonic-gate daddr32_t offset;
3960Sstevel@tonic-gate daddr32_t length;
3970Sstevel@tonic-gate md_timeval32_t timestamp;
3980Sstevel@tonic-gate md_im_replica_info_t **mirpp = NULL;
3990Sstevel@tonic-gate md_im_drive_info_t **midpp = &misp->mis_drives;
4000Sstevel@tonic-gate md_im_drive_info_t *midp;
4010Sstevel@tonic-gate
4020Sstevel@tonic-gate for (indx = 0; indx < lbp->lb_loccnt; indx++) {
4030Sstevel@tonic-gate
4040Sstevel@tonic-gate on_list = 0;
4051945Sjeanm if ((lbp->lb_locators[indx].l_flags == 0) ||
4061945Sjeanm (lbp->lb_locators[indx].l_flags & MDDB_F_DELETED))
4071945Sjeanm continue;
4081945Sjeanm
4091945Sjeanm /*
4101945Sjeanm * search the device id list for a
4111945Sjeanm * specific ctds based on the locator
4121945Sjeanm * block device id array index.
4131945Sjeanm */
4141945Sjeanm replica_disk = map_replica_disk(did_listp, indx);
4151945Sjeanm
4161945Sjeanm assert(replica_disk != NULL);
4171945Sjeanm
4181945Sjeanm
4191945Sjeanm /*
4201945Sjeanm * metadrivename() can fail for a slice name
4211945Sjeanm * if there is not an existing mddrivename_t.
4221945Sjeanm * So we use metadiskname() to strip the slice
4231945Sjeanm * number.
4241945Sjeanm */
4251945Sjeanm dnp = metadrivename(&sp, metadiskname(replica_disk->devname),
4261945Sjeanm ep);
4271945Sjeanm
4281945Sjeanm for (midp = misp->mis_drives; midp != NULL;
4291945Sjeanm midp = midp->mid_next) {
4301945Sjeanm if (dnp == midp->mid_dnp) {
4311945Sjeanm /*
4321945Sjeanm * You could get a dnp match, but if 1 disk
4331945Sjeanm * is unavailable and the other isn't, they
4341945Sjeanm * will have the same dnp due
4351945Sjeanm * to the name being the same, but in fact
4361945Sjeanm * are different disks.
4371945Sjeanm */
4381945Sjeanm if (midp->mid_available ==
4391945Sjeanm replica_disk->available) {
4400Sstevel@tonic-gate on_list = 1;
4410Sstevel@tonic-gate mirpp = &midp->mid_replicas;
4420Sstevel@tonic-gate break;
4430Sstevel@tonic-gate }
4440Sstevel@tonic-gate }
4451945Sjeanm }
4461945Sjeanm
4471945Sjeanm /*
4481945Sjeanm * New on the list so add it
4491945Sjeanm */
4501945Sjeanm if (!on_list) {
4511945Sjeanm mddb_mb_t *mbp;
4521945Sjeanm uint_t sliceno;
4531945Sjeanm mdname_t *rsp;
4541945Sjeanm int fd = -1;
4551945Sjeanm
4561945Sjeanm mbp = Malloc(DEV_BSIZE);
4570Sstevel@tonic-gate
4580Sstevel@tonic-gate /*
4591945Sjeanm * If the disk isn't available, we don't
4601945Sjeanm * want to try to read from it.
4610Sstevel@tonic-gate */
4621945Sjeanm if (replica_disk->available == MD_IM_DISK_AVAILABLE) {
4630Sstevel@tonic-gate /* determine the replica slice */
4640Sstevel@tonic-gate if (meta_replicaslice(dnp, &sliceno,
4650Sstevel@tonic-gate ep) != 0) {
4660Sstevel@tonic-gate Free(mbp);
4670Sstevel@tonic-gate continue;
4680Sstevel@tonic-gate }
4690Sstevel@tonic-gate
4700Sstevel@tonic-gate /*
4710Sstevel@tonic-gate * if the replica slice size is zero,
4720Sstevel@tonic-gate * don't bother opening
4730Sstevel@tonic-gate */
4740Sstevel@tonic-gate if (dnp->vtoc.parts[sliceno].size == 0) {
4750Sstevel@tonic-gate Free(mbp);
4760Sstevel@tonic-gate continue;
4770Sstevel@tonic-gate }
4780Sstevel@tonic-gate
4790Sstevel@tonic-gate if ((rsp = metaslicename(dnp, sliceno,
4800Sstevel@tonic-gate ep)) == NULL) {
4810Sstevel@tonic-gate Free(mbp);
4820Sstevel@tonic-gate continue;
4830Sstevel@tonic-gate }
4840Sstevel@tonic-gate
4850Sstevel@tonic-gate if ((fd = open(rsp->rname,
4860Sstevel@tonic-gate O_RDONLY| O_NDELAY)) < 0) {
4870Sstevel@tonic-gate Free(mbp);
4880Sstevel@tonic-gate continue;
4890Sstevel@tonic-gate }
4900Sstevel@tonic-gate
4910Sstevel@tonic-gate /*
4920Sstevel@tonic-gate * a drive may not have a master block
4930Sstevel@tonic-gate */
4940Sstevel@tonic-gate if (read_master_block(ep, fd, mbp,
4950Sstevel@tonic-gate DEV_BSIZE) <= 0) {
4960Sstevel@tonic-gate mdclrerror(ep);
4970Sstevel@tonic-gate Free(mbp);
4980Sstevel@tonic-gate (void) close(fd);
4990Sstevel@tonic-gate continue;
5000Sstevel@tonic-gate }
5010Sstevel@tonic-gate
5020Sstevel@tonic-gate (void) close(fd);
5030Sstevel@tonic-gate }
5041945Sjeanm midpp = drive_append_wrapper(midpp, dnp,
5051945Sjeanm replica_disk,
5061945Sjeanm meta_getminor(replica_disk->dev),
5071945Sjeanm mbp->mb_setcreatetime, NULL);
5081945Sjeanm mirpp = &((*midpp)->mid_replicas);
5091945Sjeanm Free(mbp);
5101945Sjeanm }
5111945Sjeanm
5121945Sjeanm /*
5131945Sjeanm * For either of these assertions to fail, it implies
5141945Sjeanm * a NULL return from metadrivename() above. Since
5151945Sjeanm * the args came from a presumed valid locator block,
5161945Sjeanm * that's Bad.
5171945Sjeanm */
5181945Sjeanm assert(midpp != NULL);
5191945Sjeanm assert(mirpp != NULL);
5201945Sjeanm
5211945Sjeanm /*
5221945Sjeanm * Extract the parameters describing this replica.
5231945Sjeanm *
5241945Sjeanm * The magic "1" in the length calculation accounts
5251945Sjeanm * for the length of the master block, in addition to
5261945Sjeanm * the block count it describes. (The master block
5271945Sjeanm * will always take up one block on the disk, and
5281945Sjeanm * there will always only be one master block per
5291945Sjeanm * replica, even though much of the code is structured
5301945Sjeanm * to handle noncontiguous replicas.)
5311945Sjeanm */
5321945Sjeanm flags = lbp->lb_locators[indx].l_flags;
5331945Sjeanm offset = lbp->lb_locators[indx].l_blkno;
5341945Sjeanm length = mb->mb_blkcnt + 1;
5351945Sjeanm timestamp = mb->mb_setcreatetime;
5361945Sjeanm
5371945Sjeanm mirpp = replica_append_wrapper(mirpp, flags,
5381945Sjeanm offset, length, timestamp);
5391945Sjeanm
5401945Sjeanm /*
5411945Sjeanm * If we're here it means -
5421945Sjeanm *
5431945Sjeanm * we've added the disk to the list of
5441945Sjeanm * disks.
5451945Sjeanm */
5461945Sjeanm
5471945Sjeanm /*
5481945Sjeanm * We need to bump up the number of active
5491945Sjeanm * replica count for each such replica that is
5501945Sjeanm * active so that it can be used later for replica
5511945Sjeanm * quorum check.
5521945Sjeanm */
5531945Sjeanm if (flags & MDDB_F_ACTIVE) {
5540Sstevel@tonic-gate misp->mis_active_replicas++;
5550Sstevel@tonic-gate }
5560Sstevel@tonic-gate }
5570Sstevel@tonic-gate }
5580Sstevel@tonic-gate
5590Sstevel@tonic-gate
560734Smw145384 /*
561734Smw145384 * append_pnm_rec()
562734Smw145384 *
563734Smw145384 * Append pnm_rec_t entry to list of physical devices in the diskset. Entry
564734Smw145384 * contains a mapping of n_key in NM namespace(or min_key in DID_NM namespace)
565734Smw145384 * to name of the physical device. This list will be used to ensure that the
566734Smw145384 * correct names of the physical devices are printed in the metastat output--the
567734Smw145384 * NM namespace might have stale information about where the physical devices
568734Smw145384 * were previously located when the diskset was last active.
569734Smw145384 */
570734Smw145384 static void
append_pnm_rec(pnm_rec_t ** pnm,mdkey_t min_key,char * n_name)571734Smw145384 append_pnm_rec(
572734Smw145384 pnm_rec_t **pnm,
573734Smw145384 mdkey_t min_key,
574734Smw145384 char *n_name
575734Smw145384 )
576734Smw145384 {
577734Smw145384 pnm_rec_t *tmp_pnm;
578734Smw145384 char *p;
579734Smw145384 int len;
580734Smw145384
581734Smw145384 if ((p = strrchr(n_name, '/')) != NULL)
582734Smw145384 p++;
583734Smw145384
584734Smw145384 /*
585734Smw145384 * Allocates pnm_rec_t record for the physical
586734Smw145384 * device.
587734Smw145384 */
588734Smw145384 len = strlen(p) + 1; /* Length of name plus Null term */
589734Smw145384 tmp_pnm = Malloc(sizeof (pnm_rec_t) + len);
590734Smw145384 (void) strncpy(tmp_pnm->n_name, p, len);
591734Smw145384 tmp_pnm->n_key = min_key;
592734Smw145384
593734Smw145384 /*
594734Smw145384 * Adds new element to head of pnm_rec_t list.
595734Smw145384 */
596734Smw145384 if (*pnm == NULL) {
597734Smw145384 tmp_pnm->next = NULL;
598734Smw145384 *pnm = tmp_pnm;
599734Smw145384 } else {
600734Smw145384 tmp_pnm->next = *pnm;
601734Smw145384 *pnm = tmp_pnm;
602734Smw145384 }
603734Smw145384 }
6040Sstevel@tonic-gate
6050Sstevel@tonic-gate /*
606734Smw145384 * free_pnm_rec_list()
607734Smw145384 *
608734Smw145384 * Freeing all pnm_rec_t entries on the list of physical devices in the
609734Smw145384 * diskset.
610734Smw145384 */
611734Smw145384 void
free_pnm_rec_list(pnm_rec_t ** pnm)612734Smw145384 free_pnm_rec_list(pnm_rec_t **pnm)
613734Smw145384 {
614734Smw145384 pnm_rec_t *tmp_pnm, *rm_pnm;
615734Smw145384
616734Smw145384 for (tmp_pnm = *pnm; tmp_pnm != NULL; ) {
617734Smw145384 rm_pnm = tmp_pnm;
618734Smw145384 tmp_pnm = tmp_pnm->next;
619734Smw145384 Free(rm_pnm);
620734Smw145384 }
621734Smw145384
622734Smw145384 *pnm = NULL;
623734Smw145384 }
624734Smw145384
625734Smw145384
626734Smw145384 /*
627734Smw145384 * get_disks_from_didnamespace()
628734Smw145384 * This function was origionally called: get_nonreplica_disks()
6290Sstevel@tonic-gate *
6300Sstevel@tonic-gate * Extracts the disks without replicas from the locator name space and adds them
6310Sstevel@tonic-gate * to the supplied list of md_im_drive_info_t.
632734Smw145384 * If the print verbose option was given then this function will also
633734Smw145384 * correct the nm namespace so that the n_name is the right ctd name
6340Sstevel@tonic-gate */
6350Sstevel@tonic-gate static void
get_disks_from_didnamespace(md_im_set_desc_t * misp,pnm_rec_t ** pnm,mddb_rb_t * nm,mddb_rb_t * shrnm,mddb_rb_t * did_nm,mddb_rb_t * did_shrnm,uint_t imp_flags,int replicated,md_error_t * ep)636734Smw145384 get_disks_from_didnamespace(
6370Sstevel@tonic-gate md_im_set_desc_t *misp,
638734Smw145384 pnm_rec_t **pnm,
6391945Sjeanm mddb_rb_t *nm,
6401945Sjeanm mddb_rb_t *shrnm,
6410Sstevel@tonic-gate mddb_rb_t *did_nm,
6420Sstevel@tonic-gate mddb_rb_t *did_shrnm,
643734Smw145384 uint_t imp_flags,
644734Smw145384 int replicated,
645734Smw145384 md_error_t *ep
6460Sstevel@tonic-gate )
6470Sstevel@tonic-gate {
6480Sstevel@tonic-gate char *search_path = "/dev";
6490Sstevel@tonic-gate devid_nmlist_t *nmlist;
6500Sstevel@tonic-gate md_im_drive_info_t *midp, **midpp = &misp->mis_drives;
6510Sstevel@tonic-gate mddrivename_t *dnp;
6520Sstevel@tonic-gate mdsetname_t *sp = metasetname(MD_LOCAL_NAME, ep);
6530Sstevel@tonic-gate mddb_rb_t *rbp_did = did_nm;
6540Sstevel@tonic-gate mddb_rb_t *rbp_did_shr = did_shrnm;
6551945Sjeanm mddb_rb_t *rbp_nm = nm;
6561945Sjeanm mddb_rb_t *rbp_shr_nm = shrnm;
6570Sstevel@tonic-gate int on_list = 0;
6580Sstevel@tonic-gate struct devid_min_rec *did_rec;
6590Sstevel@tonic-gate struct devid_shr_rec *did_shr_rec;
6601945Sjeanm struct nm_rec *namesp_rec;
6611945Sjeanm struct nm_shr_rec *namesp_shr_rec;
6620Sstevel@tonic-gate struct did_shr_name *did;
6630Sstevel@tonic-gate struct did_min_name *min;
6640Sstevel@tonic-gate void *r_did; /* NULL if not a replicated diskset */
6650Sstevel@tonic-gate void *valid_did;
6661945Sjeanm int avail = 0;
6671945Sjeanm struct nm_name *nmp;
6681945Sjeanm struct nm_shared_name *snmp;
6691945Sjeanm mdkey_t drv_key, key, dev_key;
6701945Sjeanm minor_t mnum = 0;
6711945Sjeanm did_list_t *nonrep_did_listp;
6721945Sjeanm size_t used_size, offset;
6730Sstevel@tonic-gate
6740Sstevel@tonic-gate /*
6750Sstevel@tonic-gate * We got a pointer to an mddb record, which we expect to contain a
6760Sstevel@tonic-gate * name record; extract the pointer thereto.
6770Sstevel@tonic-gate */
6780Sstevel@tonic-gate /* LINTED */
6790Sstevel@tonic-gate did_rec = (struct devid_min_rec *)((caddr_t)(&rbp_did->rb_data));
6800Sstevel@tonic-gate /* LINTED */
6810Sstevel@tonic-gate did_shr_rec = (struct devid_shr_rec *)
6820Sstevel@tonic-gate ((caddr_t)(&rbp_did_shr->rb_data));
6831945Sjeanm /* LINTED */
6841945Sjeanm namesp_rec = (struct nm_rec *)((caddr_t)(&rbp_nm->rb_data));
6851945Sjeanm /* LINTED */
6861945Sjeanm namesp_shr_rec = (struct nm_shr_rec *)((caddr_t)(&rbp_shr_nm->rb_data));
6870Sstevel@tonic-gate
6880Sstevel@tonic-gate /*
6890Sstevel@tonic-gate * Skip the nm_rec_hdr and iterate on the array of struct minor_name
6900Sstevel@tonic-gate * at the end of the devid_min_rec
6910Sstevel@tonic-gate */
6920Sstevel@tonic-gate for (min = &did_rec->minor_name[0]; min->min_devid_key != 0;
6930Sstevel@tonic-gate /* LINTED */
6940Sstevel@tonic-gate min = (struct did_min_name *)((char *)min + DID_NAMSIZ(min))) {
6950Sstevel@tonic-gate
6960Sstevel@tonic-gate on_list = 0;
6970Sstevel@tonic-gate r_did = NULL;
6981945Sjeanm nonrep_did_listp = Zalloc(sizeof (struct did_list));
6990Sstevel@tonic-gate
7000Sstevel@tonic-gate /*
7011945Sjeanm * For a given DID_NM key, locate the corresponding device
7020Sstevel@tonic-gate * id from DID_NM_SHR
7030Sstevel@tonic-gate */
7040Sstevel@tonic-gate for (did = &did_shr_rec->device_id[0]; did->did_key != 0;
7050Sstevel@tonic-gate /* LINTED */
7060Sstevel@tonic-gate did = (struct did_shr_name *)
7070Sstevel@tonic-gate ((char *)did + DID_SHR_NAMSIZ(did))) {
7080Sstevel@tonic-gate /*
7090Sstevel@tonic-gate * We got a match, this is the device id we're
7100Sstevel@tonic-gate * looking for
7110Sstevel@tonic-gate */
7120Sstevel@tonic-gate if (min->min_devid_key == did->did_key)
7130Sstevel@tonic-gate break;
7140Sstevel@tonic-gate }
7150Sstevel@tonic-gate
7160Sstevel@tonic-gate if (did->did_key == 0) {
7170Sstevel@tonic-gate /* we didn't find a match */
7180Sstevel@tonic-gate assert(did->did_key != 0);
7190Sstevel@tonic-gate md_exit(NULL, 1);
7200Sstevel@tonic-gate }
7210Sstevel@tonic-gate
7220Sstevel@tonic-gate /*
7230Sstevel@tonic-gate * If replicated diskset
7240Sstevel@tonic-gate */
7250Sstevel@tonic-gate if (replicated) {
7261945Sjeanm size_t new_devid_len, old_devid_len;
7270Sstevel@tonic-gate char *temp;
7280Sstevel@tonic-gate /*
7290Sstevel@tonic-gate * In this case, did->did_devid will
7300Sstevel@tonic-gate * be invalid so lookup the real one
7310Sstevel@tonic-gate */
7320Sstevel@tonic-gate temp = replicated_list_lookup(did->did_size,
7330Sstevel@tonic-gate did->did_devid);
7341945Sjeanm if (temp == NULL) {
7351945Sjeanm /* we have a partial replicated set, fake it */
7361945Sjeanm new_devid_len = did->did_size;
7371945Sjeanm r_did = Zalloc(new_devid_len);
7381945Sjeanm (void) memcpy(r_did, did->did_devid,
7391945Sjeanm new_devid_len);
7401945Sjeanm } else {
7411945Sjeanm new_devid_len = devid_sizeof((ddi_devid_t)temp);
7421945Sjeanm r_did = Zalloc(new_devid_len);
7431945Sjeanm (void) memcpy(r_did, temp, new_devid_len);
7441945Sjeanm }
7450Sstevel@tonic-gate valid_did = r_did;
7461945Sjeanm nonrep_did_listp->rdid = Zalloc(new_devid_len);
7471945Sjeanm (void) memcpy(nonrep_did_listp->rdid, r_did,
7481945Sjeanm new_devid_len);
7491945Sjeanm old_devid_len =
7501945Sjeanm devid_sizeof((ddi_devid_t)did->did_devid);
7511945Sjeanm nonrep_did_listp->did = Zalloc(old_devid_len);
7521945Sjeanm (void) memcpy((void *)nonrep_did_listp->did,
7531945Sjeanm (void *)did->did_devid, old_devid_len);
7540Sstevel@tonic-gate } else {
7551945Sjeanm size_t new_devid_len;
7561945Sjeanm
7570Sstevel@tonic-gate valid_did = did->did_devid;
7581945Sjeanm new_devid_len =
7591945Sjeanm devid_sizeof((ddi_devid_t)did->did_devid);
7601945Sjeanm nonrep_did_listp->did = Zalloc(new_devid_len);
7611945Sjeanm (void) memcpy((void *)nonrep_did_listp->did,
7621945Sjeanm (void *)did->did_devid, new_devid_len);
7630Sstevel@tonic-gate }
7640Sstevel@tonic-gate
7651945Sjeanm /*
7661945Sjeanm * Get a ctds mapping for that device id.
7671945Sjeanm * Since disk is being imported into this system,
7681945Sjeanm * just use the first ctds in list.
7691945Sjeanm */
7700Sstevel@tonic-gate if (meta_deviceid_to_nmlist(search_path,
7710Sstevel@tonic-gate (ddi_devid_t)valid_did,
7720Sstevel@tonic-gate &min->min_name[0], &nmlist) == 0) {
7731945Sjeanm /*
7741945Sjeanm * We know the disk is available. Use the
7751945Sjeanm * device information in nmlist.
7761945Sjeanm */
7771945Sjeanm assert(nmlist[0].devname != NULL);
7781945Sjeanm nonrep_did_listp->devname = Strdup(nmlist[0].devname);
7791945Sjeanm nonrep_did_listp->available = MD_IM_DISK_AVAILABLE;
7801945Sjeanm avail = 0;
7811945Sjeanm mnum = meta_getminor(nmlist[0].dev);
7821945Sjeanm devid_free_nmlist(nmlist);
7831945Sjeanm } else {
784734Smw145384 /*
7851945Sjeanm * The disk is not available. That means we need to
7861945Sjeanm * use the (old) device information stored in the
7871945Sjeanm * namespace.
7881945Sjeanm */
7891945Sjeanm /* search in nm space for a match */
7901945Sjeanm offset = sizeof (struct nm_rec) -
7911945Sjeanm sizeof (struct nm_name);
7921945Sjeanm used_size = namesp_rec->r_rec_hdr.r_used_size - offset;
7931945Sjeanm for (nmp = &namesp_rec->r_name[0]; nmp->n_key != 0;
7941945Sjeanm /* LINTED */
7951945Sjeanm nmp = (struct nm_name *)((char *)nmp +
7961945Sjeanm NAMSIZ(nmp))) {
7971945Sjeanm if (nmp->n_key == min->min_key)
7981945Sjeanm break;
7991945Sjeanm used_size -= NAMSIZ(nmp);
8001945Sjeanm if ((int)used_size <= 0) {
8011945Sjeanm md_exit(NULL, 1);
8021945Sjeanm }
8031945Sjeanm }
8041945Sjeanm
8051945Sjeanm if (nmp->n_key == 0) {
8061945Sjeanm assert(nmp->n_key != 0);
8071945Sjeanm md_exit(NULL, 1);
8081945Sjeanm }
8091945Sjeanm dev_key = nmp->n_dir_key;
8101945Sjeanm snmp = &namesp_shr_rec->sr_name[0];
8111945Sjeanm key = snmp->sn_key;
8121945Sjeanm /*
8131945Sjeanm * Use the namespace n_dir_key to look in the
8141945Sjeanm * shared namespace. When we find the matching
8151945Sjeanm * key, that is the devname and minor number we
8161945Sjeanm * want.
817734Smw145384 */
8181945Sjeanm offset = sizeof (struct nm_shr_rec) -
8191945Sjeanm sizeof (struct nm_shared_name);
8201945Sjeanm used_size = namesp_shr_rec->sr_rec_hdr.r_used_size -
8211945Sjeanm offset;
8221945Sjeanm while (key != 0) {
8231945Sjeanm if (dev_key == key) {
8241945Sjeanm /*
8251945Sjeanm * This complicated looking series
8261945Sjeanm * of code creates a devname of the
8271945Sjeanm * form <sn_name>/<n_name> which
8281945Sjeanm * will look like /dev/dsk/c1t4d0s0.
8291945Sjeanm */
8301945Sjeanm nonrep_did_listp->devname =
8311945Sjeanm Zalloc(strlen(nmp->n_name) +
8321945Sjeanm strlen(snmp->sn_name) + 2);
8331945Sjeanm (void) strlcpy(
8341945Sjeanm nonrep_did_listp->devname,
8351945Sjeanm snmp->sn_name,
8361945Sjeanm strlen(snmp->sn_name));
8371945Sjeanm (void) strlcat(
8381945Sjeanm nonrep_did_listp->devname, "/",
8391945Sjeanm strlen(nmp->n_name) +
8401945Sjeanm strlen(snmp->sn_name) + 2);
8411945Sjeanm (void) strlcat(
8421945Sjeanm nonrep_did_listp->devname,
8431945Sjeanm nmp->n_name,
8441945Sjeanm strlen(nmp->n_name) +
8451945Sjeanm strlen(snmp->sn_name) + 2);
8461945Sjeanm mnum = nmp->n_minor;
8471945Sjeanm break;
8481945Sjeanm }
8491945Sjeanm /* LINTED */
8501945Sjeanm snmp = (struct nm_shared_name *)((char *)snmp +
8511945Sjeanm SHR_NAMSIZ(snmp));
8521945Sjeanm key = snmp->sn_key;
8531945Sjeanm used_size -= SHR_NAMSIZ(snmp);
8541945Sjeanm if ((int)used_size <= 0) {
8551945Sjeanm md_exit(NULL, 1);
8561945Sjeanm }
8571945Sjeanm }
8581945Sjeanm if (key == 0) {
8591945Sjeanm nonrep_did_listp->devname = NULL;
8601945Sjeanm mnum = 0;
861734Smw145384 }
862127Shshaw
8631945Sjeanm nonrep_did_listp->available = MD_IM_DISK_NOT_AVAILABLE;
8641945Sjeanm nonrep_did_listp->minor_name = Strdup(min->min_name);
8651945Sjeanm avail = 1;
8661945Sjeanm drv_key = nmp->n_drv_key;
8671945Sjeanm snmp = &namesp_shr_rec->sr_name[0];
8681945Sjeanm key = snmp->sn_key;
8691945Sjeanm /*
8701945Sjeanm * Use the namespace n_drv_key to look in the
8711945Sjeanm * shared namespace. When we find the matching
8721945Sjeanm * key, that is the driver name for the disk.
8731945Sjeanm */
8741945Sjeanm offset = sizeof (struct nm_shr_rec) -
8751945Sjeanm sizeof (struct nm_shared_name);
8761945Sjeanm used_size = namesp_shr_rec->sr_rec_hdr.r_used_size -
8771945Sjeanm offset;
8781945Sjeanm while (key != 0) {
8791945Sjeanm if (drv_key == key) {
8801945Sjeanm nonrep_did_listp->driver_name =
8811945Sjeanm Strdup(snmp->sn_name);
8821945Sjeanm break;
8831945Sjeanm }
8841945Sjeanm /* LINTED */
8851945Sjeanm snmp = (struct nm_shared_name *)((char *)snmp +
8861945Sjeanm SHR_NAMSIZ(snmp));
8871945Sjeanm key = snmp->sn_key;
8881945Sjeanm used_size -= SHR_NAMSIZ(snmp);
8891945Sjeanm if ((int)used_size <= 0) {
8901945Sjeanm md_exit(NULL, 1);
8911945Sjeanm }
8921945Sjeanm }
8931945Sjeanm if (key == 0)
8941945Sjeanm nonrep_did_listp->driver_name = NULL;
8951945Sjeanm }
8961945Sjeanm dnp = metadrivename(&sp,
8971945Sjeanm metadiskname(nonrep_did_listp->devname), ep);
8981945Sjeanm /*
8991945Sjeanm * Add drive to pnm_rec_t list of physical devices for
9001945Sjeanm * metastat output.
9011945Sjeanm */
9021945Sjeanm if (imp_flags & META_IMP_VERBOSE) {
9031945Sjeanm append_pnm_rec(pnm, min->min_key,
9041945Sjeanm nonrep_did_listp->devname);
9051945Sjeanm }
9061945Sjeanm
9071945Sjeanm assert(dnp != NULL);
9081945Sjeanm /* Is it already on the list? */
9091945Sjeanm for (midp = misp->mis_drives; midp != NULL;
9101945Sjeanm midp = midp->mid_next) {
9111945Sjeanm if (midp->mid_dnp == dnp) {
9121945Sjeanm if (midp->mid_available ==
9131945Sjeanm nonrep_did_listp->available) {
914127Shshaw on_list = 1;
915127Shshaw break;
916127Shshaw }
917127Shshaw }
9181945Sjeanm }
9191945Sjeanm
9201945Sjeanm if (!on_list) {
9211945Sjeanm mddb_mb_t *mbp;
9221945Sjeanm uint_t sliceno;
9231945Sjeanm mdname_t *rsp;
9241945Sjeanm int fd = -1;
9251945Sjeanm
9261945Sjeanm mbp = Malloc(DEV_BSIZE);
9271945Sjeanm
9281945Sjeanm if (!avail) {
929127Shshaw /* determine the replica slice */
930127Shshaw if (meta_replicaslice(dnp, &sliceno,
931127Shshaw ep) != 0) {
932127Shshaw Free(mbp);
9331945Sjeanm free_did_list(nonrep_did_listp);
934127Shshaw continue;
9350Sstevel@tonic-gate }
9360Sstevel@tonic-gate
937127Shshaw /*
938127Shshaw * if the replica slice size is zero,
939127Shshaw * don't bother opening
940127Shshaw */
941127Shshaw if (dnp->vtoc.parts[sliceno].size
942127Shshaw == 0) {
943127Shshaw Free(mbp);
9441945Sjeanm free_did_list(nonrep_did_listp);
945127Shshaw continue;
946127Shshaw }
9470Sstevel@tonic-gate
948127Shshaw if ((rsp = metaslicename(dnp, sliceno,
949127Shshaw ep)) == NULL) {
950127Shshaw Free(mbp);
9511945Sjeanm free_did_list(nonrep_did_listp);
952127Shshaw continue;
953127Shshaw }
9540Sstevel@tonic-gate
955127Shshaw if ((fd = open(rsp->rname,
956127Shshaw O_RDONLY| O_NDELAY)) < 0) {
957127Shshaw Free(mbp);
9581945Sjeanm free_did_list(nonrep_did_listp);
959127Shshaw continue;
960127Shshaw }
9610Sstevel@tonic-gate
962127Shshaw /*
963127Shshaw * a drive may not have a master block
964127Shshaw */
965127Shshaw if (read_master_block(ep, fd, mbp,
966127Shshaw DEV_BSIZE) <= 0) {
967127Shshaw mdclrerror(ep);
968127Shshaw Free(mbp);
9691945Sjeanm free_did_list(nonrep_did_listp);
9701945Sjeanm (void) close(fd);
9711945Sjeanm continue;
972127Shshaw }
9730Sstevel@tonic-gate
974127Shshaw (void) close(fd);
9750Sstevel@tonic-gate }
9761945Sjeanm /*
9771945Sjeanm * If it is replicated diskset,
9781945Sjeanm * r_did will be non-NULL.
9791945Sjeanm * Passing the devname as NULL because field
9801945Sjeanm * is not currently used for a non-replica disk.
9811945Sjeanm */
9821945Sjeanm midpp = drive_append_wrapper(midpp,
9831945Sjeanm dnp, nonrep_did_listp,
9841945Sjeanm mnum, mbp->mb_setcreatetime, NULL);
9851945Sjeanm Free(mbp);
9861945Sjeanm free_did_list(nonrep_did_listp);
9870Sstevel@tonic-gate }
9881945Sjeanm free_did_list(nonrep_did_listp);
9890Sstevel@tonic-gate }
9900Sstevel@tonic-gate }
9910Sstevel@tonic-gate
9920Sstevel@tonic-gate /*
9930Sstevel@tonic-gate * set_append()
9940Sstevel@tonic-gate *
9950Sstevel@tonic-gate * Append to tail of linked list of md_im_set_desc_t.
9960Sstevel@tonic-gate *
9970Sstevel@tonic-gate * Will allocate space for new node AND populate it by extracting disks with
9980Sstevel@tonic-gate * and without replicas from the locator blocks and locator namespace.
9990Sstevel@tonic-gate *
10000Sstevel@tonic-gate * Returns pointer to new node.
10010Sstevel@tonic-gate */
10020Sstevel@tonic-gate static md_im_set_desc_t *
set_append(md_im_set_desc_t ** mispp,did_list_t * did_listp,mddb_mb_t * mb,mddb_lb_t * lbp,mddb_rb_t * nm,mddb_rb_t * shrnm,pnm_rec_t ** pnm,mddb_rb_t * did_nm,mddb_rb_t * did_shrnm,uint_t imp_flags,md_error_t * ep)10030Sstevel@tonic-gate set_append(
10040Sstevel@tonic-gate md_im_set_desc_t **mispp,
10050Sstevel@tonic-gate did_list_t *did_listp,
10060Sstevel@tonic-gate mddb_mb_t *mb,
10070Sstevel@tonic-gate mddb_lb_t *lbp,
10080Sstevel@tonic-gate mddb_rb_t *nm,
10091945Sjeanm mddb_rb_t *shrnm,
1010734Smw145384 pnm_rec_t **pnm,
10110Sstevel@tonic-gate mddb_rb_t *did_nm,
10120Sstevel@tonic-gate mddb_rb_t *did_shrnm,
1013734Smw145384 uint_t imp_flags,
1014734Smw145384 md_error_t *ep
10150Sstevel@tonic-gate )
10160Sstevel@tonic-gate {
1017734Smw145384
10180Sstevel@tonic-gate md_im_set_desc_t *misp;
10190Sstevel@tonic-gate set_t setno = mb->mb_setno;
10201945Sjeanm int partial = imp_flags & MD_IM_PARTIAL_DISKSET;
10211945Sjeanm int replicated = imp_flags & MD_IM_SET_REPLICATED;
10220Sstevel@tonic-gate
10230Sstevel@tonic-gate /* run to end of list */
10240Sstevel@tonic-gate for (; (*mispp != NULL); mispp = &((*mispp)->mis_next))
10250Sstevel@tonic-gate ;
10260Sstevel@tonic-gate
10270Sstevel@tonic-gate /* allocate new list element */
10280Sstevel@tonic-gate misp = *mispp = Zalloc(sizeof (md_im_set_desc_t));
10290Sstevel@tonic-gate
10300Sstevel@tonic-gate if (replicated)
10310Sstevel@tonic-gate misp->mis_flags = MD_IM_SET_REPLICATED;
10320Sstevel@tonic-gate
10330Sstevel@tonic-gate misp->mis_oldsetno = setno;
10341945Sjeanm misp->mis_partial = partial;
10350Sstevel@tonic-gate
10360Sstevel@tonic-gate /* Get the disks with and without replicas */
10371945Sjeanm get_replica_disks(misp, did_listp, mb, lbp, ep);
10380Sstevel@tonic-gate
10390Sstevel@tonic-gate if (nm != NULL && did_nm != NULL && did_shrnm != NULL) {
10401945Sjeanm get_disks_from_didnamespace(misp, pnm, nm, shrnm, did_nm,
1041734Smw145384 did_shrnm, imp_flags, replicated, ep);
10420Sstevel@tonic-gate }
10430Sstevel@tonic-gate
10440Sstevel@tonic-gate /*
1045734Smw145384 * An error in this struct could come from either of
1046734Smw145384 * the above routines;
10470Sstevel@tonic-gate * in both cases, we want to pass it back on up.
10480Sstevel@tonic-gate */
1049734Smw145384
10500Sstevel@tonic-gate return (misp);
10510Sstevel@tonic-gate }
10520Sstevel@tonic-gate
10530Sstevel@tonic-gate
10540Sstevel@tonic-gate /*
10550Sstevel@tonic-gate * add_disk_names()
10560Sstevel@tonic-gate *
10570Sstevel@tonic-gate * Iterator to walk the minor node tree of the device snapshot, adding only the
10580Sstevel@tonic-gate * first non-block instance of each non-cdrom minor node to a list of disks.
10590Sstevel@tonic-gate */
10600Sstevel@tonic-gate static int
add_disk_names(di_node_t node,di_minor_t minor,void * args)10610Sstevel@tonic-gate add_disk_names(di_node_t node, di_minor_t minor, void *args)
10620Sstevel@tonic-gate {
10630Sstevel@tonic-gate char *search_path = "/dev";
10640Sstevel@tonic-gate ddi_devid_t devid = di_devid(node);
10650Sstevel@tonic-gate devid_nmlist_t *nm;
10660Sstevel@tonic-gate char *min = di_minor_name(minor);
10670Sstevel@tonic-gate md_im_names_t *cnames = (md_im_names_t *)args;
10680Sstevel@tonic-gate static di_node_t save_node = NULL;
10690Sstevel@tonic-gate
10700Sstevel@tonic-gate /*
10710Sstevel@tonic-gate * skip CD devices
10720Sstevel@tonic-gate * If a device does not have a device id, we can't
10730Sstevel@tonic-gate * do anything with it so just exclude it from our
10740Sstevel@tonic-gate * list.
10750Sstevel@tonic-gate *
10760Sstevel@tonic-gate * This would also encompass CD devices and floppy
10770Sstevel@tonic-gate * devices that don't have a device id.
10780Sstevel@tonic-gate */
10790Sstevel@tonic-gate if (devid == NULL) {
10800Sstevel@tonic-gate return (DI_WALK_CONTINUE);
10810Sstevel@tonic-gate }
10820Sstevel@tonic-gate
10830Sstevel@tonic-gate /* char disk devices (as opposed to block) */
10840Sstevel@tonic-gate if (di_minor_spectype(minor) == S_IFCHR) {
10850Sstevel@tonic-gate
10860Sstevel@tonic-gate /* only first occurrence (slice 0) of each instance */
10870Sstevel@tonic-gate if (save_node == NULL || node != save_node) {
10880Sstevel@tonic-gate save_node = node;
10890Sstevel@tonic-gate if (meta_deviceid_to_nmlist(search_path, devid,
10900Sstevel@tonic-gate min, &nm) == 0) {
10910Sstevel@tonic-gate int index = cnames->min_count++;
10920Sstevel@tonic-gate
10930Sstevel@tonic-gate assert(nm->devname != NULL);
10940Sstevel@tonic-gate cnames->min_names =
10950Sstevel@tonic-gate Realloc(cnames->min_names,
10960Sstevel@tonic-gate cnames->min_count *
10970Sstevel@tonic-gate sizeof (char *));
10980Sstevel@tonic-gate
10990Sstevel@tonic-gate assert(cnames->min_names != NULL);
11000Sstevel@tonic-gate cnames->min_names[index] =
11010Sstevel@tonic-gate metadiskname(nm->devname);
11020Sstevel@tonic-gate devid_free_nmlist(nm);
11030Sstevel@tonic-gate }
11040Sstevel@tonic-gate }
11050Sstevel@tonic-gate }
11060Sstevel@tonic-gate return (DI_WALK_CONTINUE);
11070Sstevel@tonic-gate }
11080Sstevel@tonic-gate
11090Sstevel@tonic-gate
11100Sstevel@tonic-gate
11110Sstevel@tonic-gate /*
11120Sstevel@tonic-gate * meta_list_disks()
11130Sstevel@tonic-gate *
11140Sstevel@tonic-gate * Snapshots the device tree and extracts disk devices from the snapshot.
11150Sstevel@tonic-gate */
11160Sstevel@tonic-gate int
meta_list_disks(md_error_t * ep,md_im_names_t * cnames)11170Sstevel@tonic-gate meta_list_disks(md_error_t *ep, md_im_names_t *cnames)
11180Sstevel@tonic-gate {
11190Sstevel@tonic-gate di_node_t root_node;
11200Sstevel@tonic-gate
11210Sstevel@tonic-gate assert(cnames != NULL);
11220Sstevel@tonic-gate cnames->min_count = 0;
11230Sstevel@tonic-gate cnames->min_names = NULL;
11240Sstevel@tonic-gate
11250Sstevel@tonic-gate if ((root_node = di_init("/", DINFOCPYALL|DINFOFORCE))
11260Sstevel@tonic-gate == DI_NODE_NIL) {
11270Sstevel@tonic-gate return (mdsyserror(ep, errno, NULL));
11280Sstevel@tonic-gate }
11290Sstevel@tonic-gate
11300Sstevel@tonic-gate (void) di_walk_minor(root_node, DDI_NT_BLOCK, 0, cnames,
11310Sstevel@tonic-gate add_disk_names);
11320Sstevel@tonic-gate
11330Sstevel@tonic-gate di_fini(root_node);
11340Sstevel@tonic-gate return (0);
11350Sstevel@tonic-gate }
11360Sstevel@tonic-gate
11370Sstevel@tonic-gate /*
11380Sstevel@tonic-gate * meta_imp_drvused
11390Sstevel@tonic-gate *
11400Sstevel@tonic-gate * Checks if given drive is mounted, swapped, part of disk configuration
11410Sstevel@tonic-gate * or in use by SVM. ep also has error code set up if drive is in use.
11420Sstevel@tonic-gate *
11430Sstevel@tonic-gate * Returns 1 if drive is in use.
11440Sstevel@tonic-gate * Returns 0 if drive is not in use.
11450Sstevel@tonic-gate */
11460Sstevel@tonic-gate int
meta_imp_drvused(mdsetname_t * sp,mddrivename_t * dnp,md_error_t * ep)11470Sstevel@tonic-gate meta_imp_drvused(
11480Sstevel@tonic-gate mdsetname_t *sp,
11490Sstevel@tonic-gate mddrivename_t *dnp,
11500Sstevel@tonic-gate md_error_t *ep
11510Sstevel@tonic-gate )
11520Sstevel@tonic-gate {
11530Sstevel@tonic-gate md_error_t status = mdnullerror;
11540Sstevel@tonic-gate md_error_t *db_ep = &status;
11550Sstevel@tonic-gate
11560Sstevel@tonic-gate /*
11570Sstevel@tonic-gate * We pass in db_ep to meta_setup_db_locations
11580Sstevel@tonic-gate * and never ever use the error contained therein
11590Sstevel@tonic-gate * because all we're interested in is a check to
11600Sstevel@tonic-gate * see whether any local metadbs are present.
11610Sstevel@tonic-gate */
11620Sstevel@tonic-gate if ((meta_check_drivemounted(sp, dnp, ep) != 0) ||
11630Sstevel@tonic-gate (meta_check_driveswapped(sp, dnp, ep) != 0) ||
11640Sstevel@tonic-gate (((meta_setup_db_locations(db_ep) == 0) &&
11650Sstevel@tonic-gate ((meta_check_drive_inuse(sp, dnp, 1, ep) != 0) ||
11660Sstevel@tonic-gate (meta_check_driveinset(sp, dnp, ep) != 0))))) {
11670Sstevel@tonic-gate return (1);
11680Sstevel@tonic-gate } else {
11690Sstevel@tonic-gate return (0);
11700Sstevel@tonic-gate }
11710Sstevel@tonic-gate }
11720Sstevel@tonic-gate
11730Sstevel@tonic-gate /*
11740Sstevel@tonic-gate * meta_prune_cnames()
11750Sstevel@tonic-gate *
11760Sstevel@tonic-gate * Removes in-use disks from the list prior to further processing.
11770Sstevel@tonic-gate *
11780Sstevel@tonic-gate * Return value depends on err_on_prune flag: if set, and one or more disks
11790Sstevel@tonic-gate * are pruned, the return list will be the pruned disks. If not set, or if no
11800Sstevel@tonic-gate * disks are pruned, the return list will be the unpruned disks.
11810Sstevel@tonic-gate */
11820Sstevel@tonic-gate mddrivenamelist_t *
meta_prune_cnames(md_error_t * ep,md_im_names_t * cnames,int err_on_prune)11830Sstevel@tonic-gate meta_prune_cnames(
11840Sstevel@tonic-gate md_error_t *ep,
11850Sstevel@tonic-gate md_im_names_t *cnames,
11860Sstevel@tonic-gate int err_on_prune
11870Sstevel@tonic-gate )
11880Sstevel@tonic-gate {
11890Sstevel@tonic-gate int d;
11900Sstevel@tonic-gate int fcount = 0;
11910Sstevel@tonic-gate mddrivenamelist_t *dnlp = NULL;
11920Sstevel@tonic-gate mddrivenamelist_t **dnlpp = &dnlp;
11930Sstevel@tonic-gate mddrivenamelist_t *fdnlp = NULL;
11940Sstevel@tonic-gate mddrivenamelist_t **fdnlpp = &fdnlp;
11950Sstevel@tonic-gate mdsetname_t *sp = metasetname(MD_LOCAL_NAME, ep);
11960Sstevel@tonic-gate
11970Sstevel@tonic-gate for (d = 0; d < cnames->min_count; ++d) {
11980Sstevel@tonic-gate mddrivename_t *dnp;
11990Sstevel@tonic-gate
12000Sstevel@tonic-gate dnp = metadrivename(&sp, cnames->min_names[d], ep);
12010Sstevel@tonic-gate if (dnp == NULL) {
12020Sstevel@tonic-gate /*
12030Sstevel@tonic-gate * Assuming we're interested in knowing about
12040Sstevel@tonic-gate * whatever error occurred, but not in stopping.
12050Sstevel@tonic-gate */
12060Sstevel@tonic-gate mde_perror(ep, cnames->min_names[d]);
12070Sstevel@tonic-gate mdclrerror(ep);
12080Sstevel@tonic-gate
12090Sstevel@tonic-gate continue;
12100Sstevel@tonic-gate }
12110Sstevel@tonic-gate
12120Sstevel@tonic-gate /*
12130Sstevel@tonic-gate * Check if the drive is inuse.
12140Sstevel@tonic-gate */
12150Sstevel@tonic-gate if (meta_imp_drvused(sp, dnp, ep)) {
12160Sstevel@tonic-gate fdnlpp = meta_drivenamelist_append_wrapper(fdnlpp, dnp);
12170Sstevel@tonic-gate fcount++;
12180Sstevel@tonic-gate mdclrerror(ep);
12190Sstevel@tonic-gate } else {
12200Sstevel@tonic-gate dnlpp = meta_drivenamelist_append_wrapper(dnlpp, dnp);
12210Sstevel@tonic-gate }
12220Sstevel@tonic-gate }
12230Sstevel@tonic-gate
12240Sstevel@tonic-gate if (fcount) {
12250Sstevel@tonic-gate if (err_on_prune) {
12260Sstevel@tonic-gate (void) mddserror(ep, MDE_DS_DRIVEINUSE, 0,
12270Sstevel@tonic-gate NULL, fdnlp->drivenamep->cname, NULL);
12280Sstevel@tonic-gate metafreedrivenamelist(dnlp);
12290Sstevel@tonic-gate return (fdnlp);
12300Sstevel@tonic-gate }
12310Sstevel@tonic-gate metafreedrivenamelist(fdnlp);
12320Sstevel@tonic-gate }
12330Sstevel@tonic-gate
12340Sstevel@tonic-gate return (dnlp);
12350Sstevel@tonic-gate }
12360Sstevel@tonic-gate
12370Sstevel@tonic-gate /*
12380Sstevel@tonic-gate * read_master_block()
12390Sstevel@tonic-gate *
12400Sstevel@tonic-gate * Returns:
12410Sstevel@tonic-gate * < 0 for failure
12420Sstevel@tonic-gate * 0 for no valid master block
12430Sstevel@tonic-gate * 1 for valid master block
12440Sstevel@tonic-gate *
12450Sstevel@tonic-gate * The supplied buffer will be filled in for EITHER 0 or 1.
12460Sstevel@tonic-gate */
12470Sstevel@tonic-gate int
read_master_block(md_error_t * ep,int fd,void * bp,int bsize)12480Sstevel@tonic-gate read_master_block(
12490Sstevel@tonic-gate md_error_t *ep,
12500Sstevel@tonic-gate int fd,
12510Sstevel@tonic-gate void *bp,
12520Sstevel@tonic-gate int bsize
12530Sstevel@tonic-gate )
12540Sstevel@tonic-gate {
12550Sstevel@tonic-gate mddb_mb_t *mbp = bp;
12560Sstevel@tonic-gate int rval = 1;
12570Sstevel@tonic-gate
12580Sstevel@tonic-gate assert(bp != NULL);
12590Sstevel@tonic-gate
12600Sstevel@tonic-gate if (lseek(fd, (off_t)dbtob(16), SEEK_SET) < 0)
12610Sstevel@tonic-gate return (mdsyserror(ep, errno, NULL));
12620Sstevel@tonic-gate
12630Sstevel@tonic-gate if (read(fd, bp, bsize) != bsize)
12640Sstevel@tonic-gate return (mdsyserror(ep, errno, NULL));
12650Sstevel@tonic-gate
12660Sstevel@tonic-gate /*
12670Sstevel@tonic-gate * The master block magic number can either be MDDB_MAGIC_MB in
12680Sstevel@tonic-gate * the case of a real master block, or, it can be MDDB_MAGIC_DU
12690Sstevel@tonic-gate * in the case of a dummy master block
12700Sstevel@tonic-gate */
12710Sstevel@tonic-gate if ((mbp->mb_magic != MDDB_MAGIC_MB) &&
12720Sstevel@tonic-gate (mbp->mb_magic != MDDB_MAGIC_DU)) {
12730Sstevel@tonic-gate rval = 0;
12740Sstevel@tonic-gate (void) mdmddberror(ep, MDE_DB_MASTER, 0, 0, 0, NULL);
12750Sstevel@tonic-gate }
12760Sstevel@tonic-gate
12770Sstevel@tonic-gate if (mbp->mb_revision != MDDB_REV_MB) {
12780Sstevel@tonic-gate rval = 0;
12790Sstevel@tonic-gate }
12800Sstevel@tonic-gate
12810Sstevel@tonic-gate return (rval);
12820Sstevel@tonic-gate }
12830Sstevel@tonic-gate
12840Sstevel@tonic-gate /*
12850Sstevel@tonic-gate * read_locator_block()
12860Sstevel@tonic-gate *
12870Sstevel@tonic-gate * Returns:
12880Sstevel@tonic-gate * < 0 for failure
12890Sstevel@tonic-gate * 0 for no valid locator block
12900Sstevel@tonic-gate * 1 for valid locator block
12910Sstevel@tonic-gate */
12920Sstevel@tonic-gate int
read_locator_block(md_error_t * ep,int fd,mddb_mb_t * mbp,void * bp,int bsize)12930Sstevel@tonic-gate read_locator_block(
12940Sstevel@tonic-gate md_error_t *ep,
12950Sstevel@tonic-gate int fd,
12960Sstevel@tonic-gate mddb_mb_t *mbp,
12970Sstevel@tonic-gate void *bp,
12980Sstevel@tonic-gate int bsize
12990Sstevel@tonic-gate )
13000Sstevel@tonic-gate {
13010Sstevel@tonic-gate mddb_lb_t *lbp = bp;
13020Sstevel@tonic-gate
13030Sstevel@tonic-gate assert(bp != NULL);
13040Sstevel@tonic-gate
13050Sstevel@tonic-gate if (lseek(fd, (off_t)dbtob(mbp->mb_blkmap.m_firstblk), SEEK_SET) < 0)
13060Sstevel@tonic-gate return (mdsyserror(ep, errno, NULL));
13070Sstevel@tonic-gate
13080Sstevel@tonic-gate if (read(fd, bp, bsize) != bsize)
13090Sstevel@tonic-gate return (mdsyserror(ep, errno, NULL));
13100Sstevel@tonic-gate
13110Sstevel@tonic-gate return ((lbp->lb_magic == MDDB_MAGIC_LB) ? 1 : 0);
13120Sstevel@tonic-gate }
13130Sstevel@tonic-gate
13140Sstevel@tonic-gate int
phys_read(md_error_t * ep,int fd,mddb_mb_t * mbp,daddr_t blk,void * bp,int bcount)13150Sstevel@tonic-gate phys_read(
13160Sstevel@tonic-gate md_error_t *ep,
13170Sstevel@tonic-gate int fd,
13180Sstevel@tonic-gate mddb_mb_t *mbp,
13190Sstevel@tonic-gate daddr_t blk,
13200Sstevel@tonic-gate void *bp,
13210Sstevel@tonic-gate int bcount
13220Sstevel@tonic-gate )
13230Sstevel@tonic-gate {
13240Sstevel@tonic-gate daddr_t pblk;
13250Sstevel@tonic-gate
13260Sstevel@tonic-gate if ((pblk = getphysblk(blk, mbp)) < 0)
13270Sstevel@tonic-gate return (mdmddberror(ep, MDE_DB_BLKRANGE, NODEV32,
13280Sstevel@tonic-gate MD_LOCAL_SET, blk, NULL));
13290Sstevel@tonic-gate
13300Sstevel@tonic-gate if (lseek(fd, (off_t)dbtob(pblk), SEEK_SET) < 0)
13310Sstevel@tonic-gate return (mdsyserror(ep, errno, NULL));
13320Sstevel@tonic-gate
13330Sstevel@tonic-gate if (read(fd, bp, bcount) != bcount)
13340Sstevel@tonic-gate return (mdsyserror(ep, errno, NULL));
13350Sstevel@tonic-gate
13360Sstevel@tonic-gate return (bcount);
13370Sstevel@tonic-gate }
13380Sstevel@tonic-gate
13390Sstevel@tonic-gate /*
13400Sstevel@tonic-gate * read_locator_block_did()
13410Sstevel@tonic-gate *
13420Sstevel@tonic-gate * Returns:
13430Sstevel@tonic-gate * < 0 for failure
13440Sstevel@tonic-gate * 0 for no valid locator name struct
13450Sstevel@tonic-gate * 1 for valid locator name struct
13460Sstevel@tonic-gate */
13470Sstevel@tonic-gate int
read_locator_block_did(md_error_t * ep,int fd,mddb_mb_t * mbp,mddb_lb_t * lbp,void * bp,int bsize)13480Sstevel@tonic-gate read_locator_block_did(
13490Sstevel@tonic-gate md_error_t *ep,
13500Sstevel@tonic-gate int fd,
13510Sstevel@tonic-gate mddb_mb_t *mbp,
13520Sstevel@tonic-gate mddb_lb_t *lbp,
13530Sstevel@tonic-gate void *bp,
13540Sstevel@tonic-gate int bsize
13550Sstevel@tonic-gate )
13560Sstevel@tonic-gate {
13570Sstevel@tonic-gate int lb_didfirstblk = lbp->lb_didfirstblk;
13580Sstevel@tonic-gate mddb_did_blk_t *lbdidp = bp;
13590Sstevel@tonic-gate int rval;
13600Sstevel@tonic-gate
13610Sstevel@tonic-gate assert(bp != NULL);
13620Sstevel@tonic-gate
13630Sstevel@tonic-gate if ((rval = phys_read(ep, fd, mbp, lb_didfirstblk, bp, bsize)) < 0)
13640Sstevel@tonic-gate return (rval);
13650Sstevel@tonic-gate
13660Sstevel@tonic-gate return ((lbdidp->blk_magic == MDDB_MAGIC_DI) ? 1 : 0);
13670Sstevel@tonic-gate }
13680Sstevel@tonic-gate
13690Sstevel@tonic-gate /*
13700Sstevel@tonic-gate * read_locator_names()
13710Sstevel@tonic-gate *
13720Sstevel@tonic-gate * Returns:
13730Sstevel@tonic-gate * < 0 for failure
13740Sstevel@tonic-gate * 0 for no valid locator name struct
13750Sstevel@tonic-gate * 1 for valid locator name struct
13760Sstevel@tonic-gate */
13770Sstevel@tonic-gate int
read_locator_names(md_error_t * ep,int fd,mddb_mb_t * mbp,mddb_lb_t * lbp,void * bp,int bsize)13780Sstevel@tonic-gate read_locator_names(
13790Sstevel@tonic-gate md_error_t *ep,
13800Sstevel@tonic-gate int fd,
13810Sstevel@tonic-gate mddb_mb_t *mbp,
13820Sstevel@tonic-gate mddb_lb_t *lbp,
13830Sstevel@tonic-gate void *bp,
13840Sstevel@tonic-gate int bsize
13850Sstevel@tonic-gate )
13860Sstevel@tonic-gate {
13870Sstevel@tonic-gate int lnfirstblk = lbp->lb_lnfirstblk;
13880Sstevel@tonic-gate mddb_ln_t *lnp = bp;
13890Sstevel@tonic-gate int rval;
13900Sstevel@tonic-gate
13910Sstevel@tonic-gate assert(bp != NULL);
13920Sstevel@tonic-gate
13930Sstevel@tonic-gate if ((rval = phys_read(ep, fd, mbp, lnfirstblk, bp, bsize)) < 0)
13940Sstevel@tonic-gate return (rval);
13950Sstevel@tonic-gate
13960Sstevel@tonic-gate return ((lnp->ln_magic == MDDB_MAGIC_LN) ? 1 : 0);
13970Sstevel@tonic-gate }
13980Sstevel@tonic-gate
13990Sstevel@tonic-gate
14000Sstevel@tonic-gate int
read_database_block(md_error_t * ep,int fd,mddb_mb_t * mbp,int dbblk,void * bp,int bsize)14010Sstevel@tonic-gate read_database_block(
14020Sstevel@tonic-gate md_error_t *ep,
14030Sstevel@tonic-gate int fd,
14040Sstevel@tonic-gate mddb_mb_t *mbp,
14050Sstevel@tonic-gate int dbblk,
14060Sstevel@tonic-gate void *bp,
14070Sstevel@tonic-gate int bsize
14080Sstevel@tonic-gate )
14090Sstevel@tonic-gate {
14100Sstevel@tonic-gate mddb_db_t *dbp = bp;
14110Sstevel@tonic-gate int rval;
14120Sstevel@tonic-gate
14130Sstevel@tonic-gate assert(bp != NULL);
14140Sstevel@tonic-gate
14150Sstevel@tonic-gate if ((rval = phys_read(ep, fd, mbp, dbblk, bp, bsize)) < 0)
14160Sstevel@tonic-gate return (rval);
14170Sstevel@tonic-gate
14180Sstevel@tonic-gate return ((dbp->db_magic == MDDB_MAGIC_DB) ? 1 : 0);
14190Sstevel@tonic-gate }
14200Sstevel@tonic-gate
14210Sstevel@tonic-gate int
read_loc_didblks(md_error_t * ep,int fd,mddb_mb_t * mbp,int didblk,void * bp,int bsize)14220Sstevel@tonic-gate read_loc_didblks(
14230Sstevel@tonic-gate md_error_t *ep,
14240Sstevel@tonic-gate int fd,
14250Sstevel@tonic-gate mddb_mb_t *mbp,
14260Sstevel@tonic-gate int didblk,
14270Sstevel@tonic-gate void *bp,
14280Sstevel@tonic-gate int bsize
14290Sstevel@tonic-gate )
14300Sstevel@tonic-gate {
14310Sstevel@tonic-gate mddb_did_blk_t *didbp = bp;
14320Sstevel@tonic-gate int rval;
14330Sstevel@tonic-gate
14340Sstevel@tonic-gate assert(bp != NULL);
14350Sstevel@tonic-gate
14360Sstevel@tonic-gate if ((rval = phys_read(ep, fd, mbp, didblk, bp, bsize)) < 0)
14370Sstevel@tonic-gate return (rval);
14380Sstevel@tonic-gate
14390Sstevel@tonic-gate return ((didbp->blk_magic == MDDB_MAGIC_DI) ? 1 : 0);
14400Sstevel@tonic-gate }
14410Sstevel@tonic-gate
14420Sstevel@tonic-gate
14430Sstevel@tonic-gate int
read_loc_didinfo(md_error_t * ep,int fd,mddb_mb_t * mbp,int infoblk,void * bp,int bsize)14440Sstevel@tonic-gate read_loc_didinfo(
14450Sstevel@tonic-gate md_error_t *ep,
14460Sstevel@tonic-gate int fd,
14470Sstevel@tonic-gate mddb_mb_t *mbp,
14480Sstevel@tonic-gate int infoblk,
14490Sstevel@tonic-gate void *bp,
14500Sstevel@tonic-gate int bsize
14510Sstevel@tonic-gate )
14520Sstevel@tonic-gate {
14530Sstevel@tonic-gate int rval = 1;
14540Sstevel@tonic-gate mddb_did_info_t *infop = bp;
14550Sstevel@tonic-gate
14560Sstevel@tonic-gate assert(bp != NULL);
14570Sstevel@tonic-gate
14580Sstevel@tonic-gate if ((rval = phys_read(ep, fd, mbp, infoblk, bp, bsize)) < 0)
14590Sstevel@tonic-gate return (rval);
14600Sstevel@tonic-gate
14610Sstevel@tonic-gate return ((infop->info_flags & MDDB_DID_EXISTS) ? 1 : 0);
14620Sstevel@tonic-gate }
14630Sstevel@tonic-gate
14640Sstevel@tonic-gate /*
14650Sstevel@tonic-gate * meta_nm_rec()
14660Sstevel@tonic-gate *
14670Sstevel@tonic-gate * Return the DE corresponding to the requested namespace record type.
14680Sstevel@tonic-gate * Modifies dbp to have a firstentry if one isn't there.
14690Sstevel@tonic-gate */
14700Sstevel@tonic-gate static mddb_de_t *
meta_nm_rec(mddb_db_t * dbp,mddb_type_t rectype)14710Sstevel@tonic-gate meta_nm_rec(mddb_db_t *dbp, mddb_type_t rectype)
14720Sstevel@tonic-gate {
14730Sstevel@tonic-gate mddb_de_t *dep;
14740Sstevel@tonic-gate int desize;
14750Sstevel@tonic-gate
14760Sstevel@tonic-gate if (dbp->db_firstentry != NULL) {
14770Sstevel@tonic-gate /* LINTED */
14780Sstevel@tonic-gate dep = (mddb_de_t *)((caddr_t)(&dbp->db_firstentry)
14790Sstevel@tonic-gate + sizeof (dbp->db_firstentry));
14800Sstevel@tonic-gate dbp->db_firstentry = dep;
14810Sstevel@tonic-gate while (dep && dep->de_next) {
14820Sstevel@tonic-gate desize = sizeof (*dep) - sizeof (dep->de_blks) +
14830Sstevel@tonic-gate sizeof (daddr_t) * dep->de_blkcount;
14840Sstevel@tonic-gate /* LINTED */
14850Sstevel@tonic-gate dep->de_next = (mddb_de_t *)
14860Sstevel@tonic-gate ((caddr_t)dep + desize);
14870Sstevel@tonic-gate dep = dep->de_next;
14880Sstevel@tonic-gate }
14890Sstevel@tonic-gate }
14900Sstevel@tonic-gate
14910Sstevel@tonic-gate for (dep = dbp->db_firstentry; dep != NULL; dep = dep->de_next) {
14920Sstevel@tonic-gate if (dep->de_type1 == rectype)
14930Sstevel@tonic-gate break;
14940Sstevel@tonic-gate }
14950Sstevel@tonic-gate return (dep);
14960Sstevel@tonic-gate }
14970Sstevel@tonic-gate
14980Sstevel@tonic-gate /*
14990Sstevel@tonic-gate * read_nm_rec()
15000Sstevel@tonic-gate *
15010Sstevel@tonic-gate * Reads the NM, NM_DID or NM_DID_SHR record in the mddb and stores the
15020Sstevel@tonic-gate * configuration data in the buffer 'nm'
15030Sstevel@tonic-gate *
15040Sstevel@tonic-gate * Returns:
15050Sstevel@tonic-gate * < 0 for failure
15060Sstevel@tonic-gate * 0 for no valid NM/DID_NM/DID_NM_SHR record
15070Sstevel@tonic-gate * 1 for valid NM/DID_NM/DID_NM_SHR record
15080Sstevel@tonic-gate *
15090Sstevel@tonic-gate */
15100Sstevel@tonic-gate static int
read_nm_rec(md_error_t * ep,int fd,mddb_mb_t * mbp,mddb_lb_t * lbp,char ** nm,mddb_type_t rectype,char * diskname)15110Sstevel@tonic-gate read_nm_rec(
15120Sstevel@tonic-gate md_error_t *ep,
15130Sstevel@tonic-gate int fd,
15140Sstevel@tonic-gate mddb_mb_t *mbp,
15150Sstevel@tonic-gate mddb_lb_t *lbp,
15160Sstevel@tonic-gate char **nm,
15170Sstevel@tonic-gate mddb_type_t rectype,
15180Sstevel@tonic-gate char *diskname
15190Sstevel@tonic-gate )
15200Sstevel@tonic-gate {
15210Sstevel@tonic-gate int cnt, dbblk, rval = 0;
15220Sstevel@tonic-gate char db[DEV_BSIZE];
15230Sstevel@tonic-gate mddb_de_t *dep;
15240Sstevel@tonic-gate /*LINTED*/
15250Sstevel@tonic-gate mddb_db_t *dbp = (mddb_db_t *)&db;
15260Sstevel@tonic-gate char *tmpnm = NULL;
15270Sstevel@tonic-gate daddr_t pblk;
15280Sstevel@tonic-gate
15290Sstevel@tonic-gate for (dbblk = lbp->lb_dbfirstblk;
15300Sstevel@tonic-gate dbblk != 0;
15310Sstevel@tonic-gate dbblk = dbp->db_nextblk) {
15320Sstevel@tonic-gate
15330Sstevel@tonic-gate if ((rval = read_database_block(ep, fd, mbp, dbblk, dbp,
15340Sstevel@tonic-gate sizeof (db))) <= 0)
15350Sstevel@tonic-gate return (rval);
15360Sstevel@tonic-gate
15370Sstevel@tonic-gate /*
15380Sstevel@tonic-gate * Locate NM/DID_NM/DID_NM_SHR record. Normally there is
15390Sstevel@tonic-gate * only one record per mddb. There is a rare case when we
15400Sstevel@tonic-gate * can't expand the record. If this is the case then we
15410Sstevel@tonic-gate * will have multiple NM/DID_NM/DID_NM_SHR records linked
15420Sstevel@tonic-gate * with r_next_recid.
15430Sstevel@tonic-gate *
15440Sstevel@tonic-gate * For now assume the normal case and handle the extended
15450Sstevel@tonic-gate * namespace in Phase 2.
15460Sstevel@tonic-gate */
15470Sstevel@tonic-gate if ((dep = meta_nm_rec(dbp, rectype)) != NULL)
15480Sstevel@tonic-gate break;
15490Sstevel@tonic-gate }
15500Sstevel@tonic-gate
15510Sstevel@tonic-gate /* If meta_nm_rec() never succeeded, bail out */
15520Sstevel@tonic-gate if (dep == NULL)
15530Sstevel@tonic-gate return (0);
15540Sstevel@tonic-gate
15550Sstevel@tonic-gate /* Read in the appropriate record and return configurations */
15560Sstevel@tonic-gate tmpnm = (char *)Zalloc(dbtob(dep->de_blkcount));
15570Sstevel@tonic-gate *nm = tmpnm;
15580Sstevel@tonic-gate
15590Sstevel@tonic-gate for (cnt = 0; cnt < dep->de_blkcount; cnt++) {
15600Sstevel@tonic-gate if ((pblk = getphysblk(dep->de_blks[cnt], mbp)) < 0) {
15610Sstevel@tonic-gate rval = mdmddberror(ep, MDE_DB_BLKRANGE,
15620Sstevel@tonic-gate NODEV32, MD_LOCAL_SET,
15630Sstevel@tonic-gate dep->de_blks[cnt], diskname);
15640Sstevel@tonic-gate return (rval);
15650Sstevel@tonic-gate }
15660Sstevel@tonic-gate
15670Sstevel@tonic-gate if (lseek(fd, (off_t)dbtob(pblk), SEEK_SET) < 0) {
15680Sstevel@tonic-gate rval = mdsyserror(ep, errno, diskname);
15690Sstevel@tonic-gate return (rval);
15700Sstevel@tonic-gate }
15710Sstevel@tonic-gate
15720Sstevel@tonic-gate if (read(fd, tmpnm, DEV_BSIZE) != DEV_BSIZE) {
15730Sstevel@tonic-gate rval = mdsyserror(ep, errno, diskname);
15740Sstevel@tonic-gate return (rval);
15750Sstevel@tonic-gate }
15760Sstevel@tonic-gate
15770Sstevel@tonic-gate tmpnm += DEV_BSIZE;
15780Sstevel@tonic-gate }
15790Sstevel@tonic-gate return (1);
15800Sstevel@tonic-gate }
15810Sstevel@tonic-gate
15820Sstevel@tonic-gate /*
15830Sstevel@tonic-gate * is_replicated
15840Sstevel@tonic-gate *
15850Sstevel@tonic-gate * Determines whether a disk has been replicated or not. It checks to see
15860Sstevel@tonic-gate * if the device id stored in the master block is the same as the device id
15870Sstevel@tonic-gate * registered for that disk on the current system. If the two device ids are
15880Sstevel@tonic-gate * different, then we know that the disk has been replicated.
15890Sstevel@tonic-gate *
15900Sstevel@tonic-gate * If need_devid is set and the disk is replicated, fill in the new_devid.
15910Sstevel@tonic-gate * Also, if need_devid is set, this routine allocates memory for the device
15920Sstevel@tonic-gate * ids; the caller of this routine is responsible for free'ing up the memory.
15930Sstevel@tonic-gate *
15940Sstevel@tonic-gate * Returns:
15951945Sjeanm * MD_IM_SET_REPLICATED if it's a replicated disk
15961945Sjeanm * 0 if it's not a replicated disk
15970Sstevel@tonic-gate */
15980Sstevel@tonic-gate static int
is_replicated(int fd,mddb_mb_t * mbp,int need_devid,void ** new_devid)15990Sstevel@tonic-gate is_replicated(
16000Sstevel@tonic-gate int fd,
16010Sstevel@tonic-gate mddb_mb_t *mbp,
16020Sstevel@tonic-gate int need_devid,
16030Sstevel@tonic-gate void **new_devid
16040Sstevel@tonic-gate )
16050Sstevel@tonic-gate {
16060Sstevel@tonic-gate ddi_devid_t current_devid;
16070Sstevel@tonic-gate int retval = 0;
16080Sstevel@tonic-gate size_t new_devid_len;
16090Sstevel@tonic-gate
16100Sstevel@tonic-gate if (mbp->mb_devid_magic != MDDB_MAGIC_DE)
16110Sstevel@tonic-gate return (retval);
16120Sstevel@tonic-gate
16130Sstevel@tonic-gate if (devid_get(fd, ¤t_devid) != 0)
16140Sstevel@tonic-gate return (retval);
16150Sstevel@tonic-gate
16160Sstevel@tonic-gate if (devid_compare((ddi_devid_t)mbp->mb_devid, current_devid) != 0)
16171945Sjeanm retval = MD_IM_SET_REPLICATED;
16180Sstevel@tonic-gate
16190Sstevel@tonic-gate if (retval && need_devid) {
16200Sstevel@tonic-gate new_devid_len = devid_sizeof(current_devid);
16210Sstevel@tonic-gate *new_devid = Zalloc(new_devid_len);
16220Sstevel@tonic-gate (void) memcpy(*new_devid, (void *)current_devid, new_devid_len);
16230Sstevel@tonic-gate }
16240Sstevel@tonic-gate
16250Sstevel@tonic-gate devid_free(current_devid);
16260Sstevel@tonic-gate return (retval);
16270Sstevel@tonic-gate }
16280Sstevel@tonic-gate
16290Sstevel@tonic-gate /*
16300Sstevel@tonic-gate * free_replicated_disks_list()
16310Sstevel@tonic-gate *
16320Sstevel@tonic-gate * this frees up all the memory allocated by build_replicated_disks_list
16330Sstevel@tonic-gate */
16340Sstevel@tonic-gate static void
free_replicated_disks_list()16350Sstevel@tonic-gate free_replicated_disks_list()
16360Sstevel@tonic-gate {
16370Sstevel@tonic-gate replicated_disk_t **repl_disk, *temp;
16380Sstevel@tonic-gate int index;
16390Sstevel@tonic-gate
16400Sstevel@tonic-gate for (index = 0; index <= MAX_DEVID_LEN; index++) {
16410Sstevel@tonic-gate repl_disk = &replicated_disk_list[index];
16420Sstevel@tonic-gate
16430Sstevel@tonic-gate while (*repl_disk != NULL) {
16440Sstevel@tonic-gate temp = *repl_disk;
16450Sstevel@tonic-gate *repl_disk = (*repl_disk)->next;
16460Sstevel@tonic-gate
16470Sstevel@tonic-gate Free(temp->old_devid);
16480Sstevel@tonic-gate Free(temp->new_devid);
16490Sstevel@tonic-gate Free(temp);
16500Sstevel@tonic-gate }
16510Sstevel@tonic-gate }
16520Sstevel@tonic-gate }
16530Sstevel@tonic-gate
16540Sstevel@tonic-gate /*
16550Sstevel@tonic-gate * build_replicated_disks_list()
16560Sstevel@tonic-gate *
16570Sstevel@tonic-gate * Builds a list of disks that have been replicated using either a
16580Sstevel@tonic-gate * remote replication or a point-in-time replication software. The
16590Sstevel@tonic-gate * list is stored as a two dimensional sparse array.
16600Sstevel@tonic-gate *
16610Sstevel@tonic-gate * Returns
16620Sstevel@tonic-gate * 1 on success
16630Sstevel@tonic-gate * 0 on failure
16640Sstevel@tonic-gate */
16651945Sjeanm int
build_replicated_disks_list(md_error_t * ep,mddrivenamelist_t * dnlp)16660Sstevel@tonic-gate build_replicated_disks_list(
16670Sstevel@tonic-gate md_error_t *ep,
16680Sstevel@tonic-gate mddrivenamelist_t *dnlp
16690Sstevel@tonic-gate )
16700Sstevel@tonic-gate {
16710Sstevel@tonic-gate uint_t sliceno;
16720Sstevel@tonic-gate int fd = -1;
16730Sstevel@tonic-gate mddrivenamelist_t *dp;
16740Sstevel@tonic-gate mdname_t *rsp;
16750Sstevel@tonic-gate mddb_mb_t *mbp;
16760Sstevel@tonic-gate
16770Sstevel@tonic-gate mbp = Malloc(DEV_BSIZE);
16780Sstevel@tonic-gate
16790Sstevel@tonic-gate for (dp = dnlp; dp != NULL; dp = dp->next) {
16800Sstevel@tonic-gate mddrivename_t *dnp;
16810Sstevel@tonic-gate void *new_devid;
16820Sstevel@tonic-gate
16830Sstevel@tonic-gate dnp = dp->drivenamep;
16840Sstevel@tonic-gate /* determine the replica slice */
16850Sstevel@tonic-gate if (meta_replicaslice(dnp, &sliceno, ep) != 0)
16860Sstevel@tonic-gate continue;
16870Sstevel@tonic-gate
16880Sstevel@tonic-gate /*
16890Sstevel@tonic-gate * if the replica slice size is zero, don't bother opening
16900Sstevel@tonic-gate */
16910Sstevel@tonic-gate if (dnp->vtoc.parts[sliceno].size == 0)
16920Sstevel@tonic-gate continue;
16930Sstevel@tonic-gate
16940Sstevel@tonic-gate if ((rsp = metaslicename(dnp, sliceno, ep)) == NULL)
16950Sstevel@tonic-gate continue;
16960Sstevel@tonic-gate
16970Sstevel@tonic-gate if ((fd = open(rsp->rname, O_RDONLY| O_NDELAY)) < 0)
16980Sstevel@tonic-gate return (mdsyserror(ep, errno, rsp->rname));
16990Sstevel@tonic-gate
17000Sstevel@tonic-gate /* a drive may not have a master block so we just continue */
17010Sstevel@tonic-gate if (read_master_block(ep, fd, mbp, DEV_BSIZE) <= 0) {
17020Sstevel@tonic-gate (void) close(fd);
17030Sstevel@tonic-gate mdclrerror(ep);
17040Sstevel@tonic-gate continue;
17050Sstevel@tonic-gate }
17060Sstevel@tonic-gate
17070Sstevel@tonic-gate if (is_replicated(fd, mbp, 1, &new_devid)) {
17080Sstevel@tonic-gate replicated_list_insert(mbp->mb_devid_len,
17090Sstevel@tonic-gate mbp->mb_devid, new_devid);
17100Sstevel@tonic-gate }
17110Sstevel@tonic-gate (void) close(fd);
17120Sstevel@tonic-gate }
17131945Sjeanm *replicated_disk_list_built = 1;
17140Sstevel@tonic-gate
17150Sstevel@tonic-gate Free(mbp);
17160Sstevel@tonic-gate return (1);
17170Sstevel@tonic-gate }
17180Sstevel@tonic-gate
17190Sstevel@tonic-gate /*
17200Sstevel@tonic-gate * free_did_list()
17210Sstevel@tonic-gate *
17220Sstevel@tonic-gate * Frees the did_list allocated as part of build_did_list
17230Sstevel@tonic-gate */
17240Sstevel@tonic-gate static void
free_did_list(did_list_t * did_listp)17250Sstevel@tonic-gate free_did_list(
17260Sstevel@tonic-gate did_list_t *did_listp
17270Sstevel@tonic-gate )
17280Sstevel@tonic-gate {
17290Sstevel@tonic-gate did_list_t *temp, *head;
17300Sstevel@tonic-gate
17310Sstevel@tonic-gate head = did_listp;
17320Sstevel@tonic-gate
17330Sstevel@tonic-gate while (head != NULL) {
17340Sstevel@tonic-gate temp = head;
17350Sstevel@tonic-gate head = head->next;
17360Sstevel@tonic-gate if (temp->rdid)
17370Sstevel@tonic-gate Free(temp->rdid);
17380Sstevel@tonic-gate if (temp->did)
17390Sstevel@tonic-gate Free(temp->did);
17400Sstevel@tonic-gate if (temp->devname)
17410Sstevel@tonic-gate Free(temp->devname);
17420Sstevel@tonic-gate if (temp->minor_name)
17430Sstevel@tonic-gate Free(temp->minor_name);
17441945Sjeanm if (temp->driver_name)
17451945Sjeanm Free(temp->driver_name);
17461945Sjeanm Free(temp);
17471945Sjeanm }
17481945Sjeanm }
17491945Sjeanm
17501945Sjeanm /*
17511945Sjeanm * meta_free_im_replica_info
17521945Sjeanm *
17531945Sjeanm * Frees the md_im_replica_info list
17541945Sjeanm */
17551945Sjeanm static void
meta_free_im_replica_info(md_im_replica_info_t * mirp)17561945Sjeanm meta_free_im_replica_info(
17571945Sjeanm md_im_replica_info_t *mirp
17581945Sjeanm )
17591945Sjeanm {
17601945Sjeanm md_im_replica_info_t *r, *temp;
17611945Sjeanm
17621945Sjeanm r = mirp;
17631945Sjeanm
17641945Sjeanm while (r != NULL) {
17651945Sjeanm temp = r;
17661945Sjeanm r = r->mir_next;
17671945Sjeanm
17681945Sjeanm Free(temp);
17691945Sjeanm }
17701945Sjeanm }
17711945Sjeanm
17721945Sjeanm /*
17731945Sjeanm * meta_free_im_drive_info
17741945Sjeanm *
17751945Sjeanm * Frees the md_im_drive_info list
17761945Sjeanm */
17771945Sjeanm static void
meta_free_im_drive_info(md_im_drive_info_t * midp)17781945Sjeanm meta_free_im_drive_info(
17791945Sjeanm md_im_drive_info_t *midp
17801945Sjeanm )
17811945Sjeanm {
17821945Sjeanm md_im_drive_info_t *d, *temp;
17831945Sjeanm
17841945Sjeanm d = midp;
17851945Sjeanm
17861945Sjeanm while (d != NULL) {
17871945Sjeanm temp = d;
17881945Sjeanm d = d->mid_next;
17891945Sjeanm
17901945Sjeanm if (temp->mid_available & MD_IM_DISK_NOT_AVAILABLE)
17911945Sjeanm /*
17921945Sjeanm * dnp is not on the drivenamelist and is a temp
17931945Sjeanm * dnp for metaimport if the disk is unavailable.
17941945Sjeanm * We need to specifically free it because of this.
17951945Sjeanm * If the disk is available, standard drivelist freeing
17961945Sjeanm * will kick in so we don't need to do it.
17971945Sjeanm */
17981945Sjeanm metafreedrivename(temp->mid_dnp);
17991945Sjeanm if (temp->mid_devid)
18001945Sjeanm Free(temp->mid_devid);
18011945Sjeanm if (temp->mid_o_devid)
18021945Sjeanm Free(temp->mid_o_devid);
18031945Sjeanm if (temp->mid_driver_name)
18041945Sjeanm Free(temp->mid_driver_name);
18051945Sjeanm if (temp->mid_devname)
18061945Sjeanm Free(temp->mid_devname);
18071945Sjeanm if (temp->mid_replicas) {
18081945Sjeanm meta_free_im_replica_info(temp->mid_replicas);
18091945Sjeanm temp->mid_replicas = NULL;
18101945Sjeanm }
18111945Sjeanm if (temp->overlap) {
18121945Sjeanm meta_free_im_drive_info(temp->overlap);
18131945Sjeanm temp->overlap = NULL;
18141945Sjeanm }
18151945Sjeanm Free(temp);
18161945Sjeanm }
18171945Sjeanm }
18181945Sjeanm
18191945Sjeanm /*
18201945Sjeanm * meta_free_im_set_desc
18211945Sjeanm *
18221945Sjeanm * Frees the md_im_set_desc_t list
18231945Sjeanm */
18241945Sjeanm void
meta_free_im_set_desc(md_im_set_desc_t * misp)18251945Sjeanm meta_free_im_set_desc(
18261945Sjeanm md_im_set_desc_t *misp
18271945Sjeanm )
18281945Sjeanm {
18291945Sjeanm md_im_set_desc_t *s, *temp;
18301945Sjeanm
18311945Sjeanm s = misp;
18321945Sjeanm
18331945Sjeanm while (s != NULL) {
18341945Sjeanm temp = s;
18351945Sjeanm s = s->mis_next;
18361945Sjeanm if (temp->mis_drives) {
18371945Sjeanm meta_free_im_drive_info(temp->mis_drives);
18381945Sjeanm temp->mis_drives = NULL;
18391945Sjeanm }
18400Sstevel@tonic-gate Free(temp);
18410Sstevel@tonic-gate }
18420Sstevel@tonic-gate }
18430Sstevel@tonic-gate
18440Sstevel@tonic-gate /*
18450Sstevel@tonic-gate * build_did_list()
18460Sstevel@tonic-gate *
18470Sstevel@tonic-gate * Build a list of device ids corresponding to disks in the locator block.
18480Sstevel@tonic-gate * Memory is allocated here for the nodes in the did_list. The callers of
18490Sstevel@tonic-gate * this routine must also call free_did_list to free up the memory after
18500Sstevel@tonic-gate * they're done.
18510Sstevel@tonic-gate *
18520Sstevel@tonic-gate * Returns:
18530Sstevel@tonic-gate * < 0 for failure
18540Sstevel@tonic-gate * 0 for no valid locator block device id array
18550Sstevel@tonic-gate * 1 for valid locator block device id array
18560Sstevel@tonic-gate * ENOTSUP partial diskset, not all disks in a diskset on the
18570Sstevel@tonic-gate * system where import is being executed
18580Sstevel@tonic-gate */
18590Sstevel@tonic-gate static int
build_did_list(md_error_t * ep,int fd,mddb_mb_t * mb,mddb_lb_t * lbp,mddb_did_blk_t * lbdidp,mddb_ln_t * lnp,did_list_t ** did_listp,int replicated)18600Sstevel@tonic-gate build_did_list(
18610Sstevel@tonic-gate md_error_t *ep,
18620Sstevel@tonic-gate int fd,
18630Sstevel@tonic-gate mddb_mb_t *mb,
18641945Sjeanm mddb_lb_t *lbp,
18650Sstevel@tonic-gate mddb_did_blk_t *lbdidp,
18661945Sjeanm mddb_ln_t *lnp,
18670Sstevel@tonic-gate did_list_t **did_listp,
18680Sstevel@tonic-gate int replicated
18690Sstevel@tonic-gate )
18700Sstevel@tonic-gate {
18710Sstevel@tonic-gate char *search_path = "/dev";
18720Sstevel@tonic-gate char *minor_name;
18730Sstevel@tonic-gate int rval, cnt;
18740Sstevel@tonic-gate devid_nmlist_t *nm;
18750Sstevel@tonic-gate uint_t did_info_length = 0;
18760Sstevel@tonic-gate uint_t did_info_firstblk = 0;
18770Sstevel@tonic-gate did_list_t *new, *head = NULL;
18780Sstevel@tonic-gate char *bp = NULL, *temp;
18790Sstevel@tonic-gate mddb_did_info_t *did_info = NULL;
18800Sstevel@tonic-gate void *did = NULL;
18810Sstevel@tonic-gate size_t new_devid_len;
18821945Sjeanm int partial = 0;
18831945Sjeanm int partial_replicated = 0;
18840Sstevel@tonic-gate
18850Sstevel@tonic-gate for (cnt = 0; cnt < MDDB_NLB; cnt++) {
18861945Sjeanm partial_replicated = 0;
18870Sstevel@tonic-gate did_info = &lbdidp->blk_info[cnt];
18880Sstevel@tonic-gate
18890Sstevel@tonic-gate if (!(did_info->info_flags & MDDB_DID_EXISTS))
18900Sstevel@tonic-gate continue;
18910Sstevel@tonic-gate
18920Sstevel@tonic-gate new = Zalloc(sizeof (did_list_t));
18930Sstevel@tonic-gate new->did = Zalloc(did_info->info_length);
18940Sstevel@tonic-gate
18950Sstevel@tonic-gate /*
18961945Sjeanm * If we can re-use the buffer that has already been
18970Sstevel@tonic-gate * read in then just use it. Otherwise free
18980Sstevel@tonic-gate * the previous one and alloc a new one
18990Sstevel@tonic-gate */
1900*4901Sjr26306 if (did_info->info_firstblk != did_info_firstblk) {
19010Sstevel@tonic-gate
19020Sstevel@tonic-gate did_info_length = dbtob(did_info->info_blkcnt);
19030Sstevel@tonic-gate did_info_firstblk = did_info->info_firstblk;
19040Sstevel@tonic-gate
19050Sstevel@tonic-gate if (bp)
19060Sstevel@tonic-gate Free(bp);
19070Sstevel@tonic-gate bp = temp = Zalloc(did_info_length);
19080Sstevel@tonic-gate
19090Sstevel@tonic-gate if ((rval = phys_read(ep, fd, mb, did_info_firstblk,
19100Sstevel@tonic-gate (void *)bp, did_info_length)) < 0)
19110Sstevel@tonic-gate return (rval);
19120Sstevel@tonic-gate } else {
19130Sstevel@tonic-gate temp = bp;
19140Sstevel@tonic-gate }
19150Sstevel@tonic-gate
19160Sstevel@tonic-gate temp += did_info->info_offset;
19170Sstevel@tonic-gate (void) memcpy(new->did, temp, did_info->info_length);
19180Sstevel@tonic-gate new->did_index = cnt;
19190Sstevel@tonic-gate minor_name = did_info->info_minor_name;
19200Sstevel@tonic-gate
19210Sstevel@tonic-gate /*
19220Sstevel@tonic-gate * If we are not able to find the ctd mapping corresponding
19230Sstevel@tonic-gate * to a given device id, it probably means the device id in
19240Sstevel@tonic-gate * question is not registered with the system.
19250Sstevel@tonic-gate *
19260Sstevel@tonic-gate * Highly likely that the only time this happens, we've hit
19270Sstevel@tonic-gate * a case where not all the disks that are a part of the
19280Sstevel@tonic-gate * diskset were moved before importing the diskset.
19290Sstevel@tonic-gate *
19300Sstevel@tonic-gate * If set is a replicated diskset, then the device id we get
19310Sstevel@tonic-gate * from 'lb' will be the 'other' did and we need to lookup
19320Sstevel@tonic-gate * the real one before we call this routine.
19330Sstevel@tonic-gate */
19340Sstevel@tonic-gate if (replicated) {
19350Sstevel@tonic-gate temp = replicated_list_lookup(did_info->info_length,
19360Sstevel@tonic-gate new->did);
19371945Sjeanm if (temp == NULL) {
19381945Sjeanm /* we have a partial replicated set, fake it */
19391945Sjeanm new_devid_len = devid_sizeof((ddi_devid_t)new->did);
19401945Sjeanm new->rdid = Zalloc(new_devid_len);
19411945Sjeanm (void) memcpy(new->rdid, new->did, new_devid_len);
19421945Sjeanm did = new->rdid;
19431945Sjeanm partial_replicated = 1;
19441945Sjeanm } else {
19451945Sjeanm new_devid_len = devid_sizeof((ddi_devid_t)temp);
19461945Sjeanm new->rdid = Zalloc(new_devid_len);
19471945Sjeanm (void) memcpy(new->rdid, temp, new_devid_len);
19481945Sjeanm did = new->rdid;
19491945Sjeanm }
19500Sstevel@tonic-gate } else {
19510Sstevel@tonic-gate did = new->did;
19520Sstevel@tonic-gate }
19530Sstevel@tonic-gate
19540Sstevel@tonic-gate if (devid_valid((ddi_devid_t)(did)) == 0) {
19550Sstevel@tonic-gate return (-1);
19560Sstevel@tonic-gate }
19570Sstevel@tonic-gate
19581945Sjeanm if (partial_replicated || meta_deviceid_to_nmlist(search_path,
19591945Sjeanm (ddi_devid_t)did, minor_name, &nm) != 0) {
19601945Sjeanm int len = 0;
19611945Sjeanm
19621945Sjeanm /*
19631945Sjeanm * Partial diskset case. We'll need to get the
19641945Sjeanm * device information from the metadb instead
19651945Sjeanm * of the output (nm) of meta_deviceid_to_nmlist.
19661945Sjeanm */
19671945Sjeanm len = strlen(lnp->ln_prefixes[0].pre_data) +
19681945Sjeanm strlen(lnp->ln_suffixes[0][cnt].suf_data) + 2;
19691945Sjeanm new->devname = Zalloc(len);
19701945Sjeanm (void) strlcpy(new->devname,
19711945Sjeanm lnp->ln_prefixes[0].pre_data,
19721945Sjeanm strlen(lnp->ln_prefixes[0].pre_data) + 1);
19731945Sjeanm (void) strlcat(new->devname, "/", len);
19741945Sjeanm (void) strlcat(new->devname,
19751945Sjeanm lnp->ln_suffixes[0][cnt].suf_data, len);
19761945Sjeanm new->minor_name = Strdup(minor_name);
19771945Sjeanm new->next = head;
19781945Sjeanm new->available = MD_IM_DISK_NOT_AVAILABLE;
19791945Sjeanm new->driver_name = Strdup(lbp->lb_drvnm[0].dn_data);
19801945Sjeanm new->dev = lbp->lb_locators[cnt].l_dev;
19811945Sjeanm head = new;
19821945Sjeanm partial = ENOTSUP;
19831945Sjeanm continue;
19840Sstevel@tonic-gate }
19850Sstevel@tonic-gate
19861945Sjeanm /*
19871945Sjeanm * Disk is there. Grab device information from nm structure.
19881945Sjeanm */
19890Sstevel@tonic-gate assert(nm->devname != NULL);
19900Sstevel@tonic-gate new->devname = Strdup(nm->devname);
19910Sstevel@tonic-gate new->dev = nm->dev;
19920Sstevel@tonic-gate new->minor_name = Strdup(minor_name);
19931945Sjeanm new->available = MD_IM_DISK_AVAILABLE;
19940Sstevel@tonic-gate
19950Sstevel@tonic-gate devid_free_nmlist(nm);
19960Sstevel@tonic-gate
19970Sstevel@tonic-gate new->next = head;
19980Sstevel@tonic-gate head = new;
19990Sstevel@tonic-gate }
20000Sstevel@tonic-gate
20010Sstevel@tonic-gate /* Free the last bp */
20020Sstevel@tonic-gate if (bp)
20030Sstevel@tonic-gate Free(bp);
20040Sstevel@tonic-gate *did_listp = head;
20051945Sjeanm if (partial)
20061945Sjeanm return (partial);
20070Sstevel@tonic-gate return (1);
20080Sstevel@tonic-gate }
200957Sjeanm /*
201057Sjeanm * check_nm_disks
201157Sjeanm * Checks the disks listed in the shared did namespace to see if they
201257Sjeanm * are accessable on the system. If not, return ENOTSUP error to
201357Sjeanm * indicate we have a partial diskset.
201457Sjeanm * Returns:
201557Sjeanm * < 0 for failure
201657Sjeanm * 0 success
201757Sjeanm * ENOTSUP partial diskset, not all disks in a diskset on the
201857Sjeanm * system where import is being executed
201957Sjeanm */
202057Sjeanm static int
check_nm_disks(struct devid_min_rec * did_nmp,struct devid_shr_rec * did_shrnmp)202157Sjeanm check_nm_disks(
202257Sjeanm struct devid_min_rec *did_nmp,
202357Sjeanm struct devid_shr_rec *did_shrnmp
202457Sjeanm )
202557Sjeanm {
202657Sjeanm char *search_path = "/dev";
202757Sjeanm char *minor_name = NULL;
202857Sjeanm uint_t used_size, min_used_size;
202957Sjeanm ddi_devid_t did;
203057Sjeanm devid_nmlist_t *nm;
203157Sjeanm void *did_min_namep;
203257Sjeanm void *did_shr_namep;
203357Sjeanm size_t did_nsize, did_shr_nsize;
203457Sjeanm
203557Sjeanm used_size = did_shrnmp->did_rec_hdr.r_used_size -
203657Sjeanm sizeof (struct nm_rec_hdr);
203757Sjeanm min_used_size = did_nmp->min_rec_hdr.r_used_size -
203857Sjeanm sizeof (struct nm_rec_hdr);
203957Sjeanm did_shr_namep = (void *)(&did_shrnmp->device_id[0]);
204057Sjeanm while (used_size > (int)sizeof (struct did_shr_name)) {
204157Sjeanm did_min_namep = (void *)(&did_nmp->minor_name[0]);
204257Sjeanm /* grab device id and minor name from the shared spaces */
204357Sjeanm did = (ddi_devid_t)(((struct did_shr_name *)
204457Sjeanm did_shr_namep)->did_devid);
204557Sjeanm if (devid_valid(did) == 0) {
204657Sjeanm return (-1);
204757Sjeanm }
204857Sjeanm
204957Sjeanm /*
205057Sjeanm * We need to check that the DID_NM and DID_SHR_NM are in
205157Sjeanm * sync. It is possible that we took a panic between writing
205257Sjeanm * the two areas to disk. This would be cleaned up on the
205357Sjeanm * next snarf but we don't know for sure that snarf has even
205457Sjeanm * happened since we're reading from disk.
205557Sjeanm */
205657Sjeanm while (((struct did_shr_name *)did_shr_namep)->did_key !=
205757Sjeanm ((struct did_min_name *)did_min_namep)->min_devid_key) {
205857Sjeanm did_nsize = DID_NAMSIZ((struct did_min_name *)
205957Sjeanm did_min_namep);
206057Sjeanm did_min_namep = ((void *)((char *)did_min_namep +
206157Sjeanm did_nsize));
206257Sjeanm min_used_size -= did_nsize;
206357Sjeanm if (min_used_size < (int)sizeof (struct did_min_name))
206457Sjeanm continue;
206557Sjeanm }
206657Sjeanm minor_name = ((struct did_min_name *)did_min_namep)->min_name;
206757Sjeanm
206857Sjeanm /*
206957Sjeanm * Try to find disk in the system. If we can't find the
207057Sjeanm * disk, we have a partial diskset.
207157Sjeanm */
207257Sjeanm if ((meta_deviceid_to_nmlist(search_path,
207357Sjeanm did, minor_name, &nm)) != 0) {
20741945Sjeanm /* Partial diskset detected */
207557Sjeanm return (ENOTSUP);
207657Sjeanm }
207757Sjeanm devid_free_nmlist(nm);
207857Sjeanm used_size -= DID_SHR_NAMSIZ((struct did_shr_name *)
207957Sjeanm did_shr_namep);
208057Sjeanm /* increment to next item in the shared spaces */
208157Sjeanm did_shr_nsize = DID_SHR_NAMSIZ((struct did_shr_name *)
208257Sjeanm did_shr_namep);
208357Sjeanm did_shr_namep = ((void *)((char *)did_shr_namep +
208457Sjeanm did_shr_nsize));
208557Sjeanm }
208657Sjeanm return (0);
208757Sjeanm }
20880Sstevel@tonic-gate
2089734Smw145384
20900Sstevel@tonic-gate /*
2091734Smw145384 * report_metadb_info()
2092734Smw145384 *
2093734Smw145384 * Generates metadb output for the diskset.
2094734Smw145384 *
2095734Smw145384 */
2096734Smw145384 static void
report_metadb_info(md_im_set_desc_t * misp,char * indent)2097734Smw145384 report_metadb_info(
2098734Smw145384 md_im_set_desc_t *misp,
2099734Smw145384 char *indent
2100734Smw145384 )
2101734Smw145384 {
2102734Smw145384 md_im_drive_info_t *d;
2103734Smw145384 md_im_replica_info_t *r;
2104734Smw145384 char *unk_str = "";
2105734Smw145384 int i;
2106734Smw145384
2107734Smw145384 (void) printf("%s\t%5.5s\t\t%9.9s\t%11.11s\n", indent, gettext("flags"),
2108734Smw145384 gettext("first blk"), gettext("block count"));
2109734Smw145384
2110734Smw145384 unk_str = gettext("unknown");
2111734Smw145384
2112734Smw145384 /*
2113734Smw145384 * Looping through all drives in the diskset to print
2114734Smw145384 * out information about the drive and if the verbose
2115734Smw145384 * option is set print out replica data.
2116734Smw145384 */
2117734Smw145384 for (d = misp->mis_drives; d != NULL; d = d->mid_next) {
2118734Smw145384
2119734Smw145384 if (d->mid_replicas != NULL) {
2120734Smw145384 for (r = d->mid_replicas; r != NULL;
2121734Smw145384 r = r->mir_next) {
2122734Smw145384 (void) printf("%s", indent);
2123734Smw145384 for (i = 0; i < MDDB_FLAGS_LEN; i++) {
2124734Smw145384 if (r->mir_flags & (1 << i)) {
2125734Smw145384 (void) putchar(
2126734Smw145384 MDDB_FLAGS_STRING[i]);
2127734Smw145384 } else {
2128734Smw145384 (void) putchar(' ');
2129734Smw145384 }
2130734Smw145384 }
2131734Smw145384 if ((r->mir_offset == -1) && (r->mir_length
2132734Smw145384 == -1)) {
2133734Smw145384 (void) printf("%7.7s\t\t%7.7s\t",
2134734Smw145384 unk_str, unk_str);
2135734Smw145384 } else if (r->mir_length == -1) {
2136734Smw145384 (void) printf("%i\t\t%7.7s\t",
2137734Smw145384 r->mir_offset, unk_str);
2138734Smw145384 } else {
2139734Smw145384 (void) printf("%i\t\t%i\t",
2140734Smw145384 r->mir_offset, r->mir_length);
2141734Smw145384 }
2142734Smw145384 (void) printf("\t%s\n",
2143734Smw145384 d->mid_devname);
2144734Smw145384 }
2145734Smw145384 }
2146734Smw145384 }
2147734Smw145384 (void) printf("\n");
2148734Smw145384 }
2149734Smw145384
21501945Sjeanm /*
21511945Sjeanm * meta_replica_quorum will determine if the disks in the set to be
21521945Sjeanm * imported have enough valid replicas to have quorum.
21531945Sjeanm *
21541945Sjeanm * RETURN:
21551945Sjeanm * -1 Set doesn't have quorum
21561945Sjeanm * 0 Set does have quorum
21571945Sjeanm */
21581945Sjeanm int
meta_replica_quorum(md_im_set_desc_t * misp)21591945Sjeanm meta_replica_quorum(
21601945Sjeanm md_im_set_desc_t *misp
21611945Sjeanm )
21621945Sjeanm {
21631945Sjeanm md_im_drive_info_t *midp;
21641945Sjeanm md_im_replica_info_t *midr;
21651945Sjeanm int replica_count = 0;
21661945Sjeanm
21671945Sjeanm for (midp = misp->mis_drives; midp != NULL;
21681945Sjeanm midp = midp->mid_next) {
21691945Sjeanm
21701945Sjeanm if (midp->mid_available == MD_IM_DISK_NOT_AVAILABLE)
21711945Sjeanm continue;
21721945Sjeanm
21731945Sjeanm /*
21741945Sjeanm * The drive is okay. Now count its replicas
21751945Sjeanm */
21761945Sjeanm for (midr = midp->mid_replicas; midr != NULL;
21771945Sjeanm midr = midr->mir_next) {
21781945Sjeanm replica_count++;
21791945Sjeanm }
21801945Sjeanm }
21811945Sjeanm
21821945Sjeanm if (misp->mis_active_replicas & 1) {
21831945Sjeanm /* odd number of replicas */
21841945Sjeanm if (replica_count < (misp->mis_active_replicas + 1)/2)
21851945Sjeanm return (-1);
21861945Sjeanm } else {
21871945Sjeanm /* even number of replicas */
21881945Sjeanm if (replica_count <= ((misp->mis_active_replicas + 1)/2))
21891945Sjeanm return (-1);
21901945Sjeanm }
21911945Sjeanm
21921945Sjeanm return (0);
21931945Sjeanm }
21941945Sjeanm
21951945Sjeanm
21961945Sjeanm /*
21971945Sjeanm * Choose the best drive to use for the metaimport command.
21981945Sjeanm */
21991945Sjeanm md_im_drive_info_t *
pick_good_disk(md_im_set_desc_t * misp)22001945Sjeanm pick_good_disk(md_im_set_desc_t *misp)
22011945Sjeanm {
22021945Sjeanm md_timeval32_t *setcrtime; /* set creation time */
22031945Sjeanm md_im_drive_info_t *good_disk = NULL;
22041945Sjeanm md_im_drive_info_t *midp = NULL;
22051945Sjeanm md_im_replica_info_t *mirp;
22061945Sjeanm
22071945Sjeanm setcrtime = &(misp->mis_drives->mid_replicas->mir_timestamp);
22081945Sjeanm for (midp = misp->mis_drives; (midp != NULL) && (good_disk == NULL);
22091945Sjeanm midp = midp->mid_next) {
22101945Sjeanm /* drive must be available */
22111945Sjeanm if (midp->mid_available == MD_IM_DISK_NOT_AVAILABLE) {
22121945Sjeanm continue;
22131945Sjeanm }
22141945Sjeanm for (mirp = midp->mid_replicas; mirp != NULL;
22151945Sjeanm mirp = mirp->mir_next) {
22161945Sjeanm /* replica must be active to be a good one */
22171945Sjeanm if (mirp->mir_flags & MDDB_F_ACTIVE) {
22181945Sjeanm if ((setcrtime->tv_sec ==
22191945Sjeanm midp-> mid_setcreatetimestamp.tv_sec) &&
22201945Sjeanm (setcrtime->tv_usec ==
22211945Sjeanm midp->mid_setcreatetimestamp.tv_usec)) {
22221945Sjeanm good_disk = midp;
22231945Sjeanm break;
22241945Sjeanm }
22251945Sjeanm }
22261945Sjeanm }
22271945Sjeanm }
22281945Sjeanm return (good_disk);
22291945Sjeanm }
2230734Smw145384
2231734Smw145384 /*
2232734Smw145384 * report_set_info()
2233734Smw145384 *
2234734Smw145384 * Returns:
2235734Smw145384 * < 0 for failure
2236734Smw145384 * 0 for success
2237734Smw145384 *
2238734Smw145384 */
2239734Smw145384 static int
report_set_info(md_im_set_desc_t * misp,mddb_mb_t * mb,mddb_lb_t * lbp,mddb_rb_t * nm,pnm_rec_t ** pnm,mdname_t * rsp,int fd,uint_t imp_flags,int set_count,int overlap,md_im_drive_info_t * overlap_disks,md_error_t * ep)2240734Smw145384 report_set_info(
2241734Smw145384 md_im_set_desc_t *misp,
2242734Smw145384 mddb_mb_t *mb,
2243734Smw145384 mddb_lb_t *lbp,
2244734Smw145384 mddb_rb_t *nm,
2245734Smw145384 pnm_rec_t **pnm,
2246734Smw145384 mdname_t *rsp,
2247734Smw145384 int fd,
2248734Smw145384 uint_t imp_flags,
2249734Smw145384 int set_count,
22501945Sjeanm int overlap,
22511945Sjeanm md_im_drive_info_t *overlap_disks,
2252734Smw145384 md_error_t *ep
2253734Smw145384 )
2254734Smw145384 {
2255734Smw145384 int rval = 0;
2256734Smw145384 md_im_drive_info_t *d;
2257734Smw145384 md_im_drive_info_t *good_disk = NULL;
2258734Smw145384 int i;
2259734Smw145384 int in = META_INDENT;
2260734Smw145384 char indent[MAXPATHLEN];
2261734Smw145384 md_timeval32_t lastaccess; /* stores last modified timestamp */
22621945Sjeanm int has_overlap = 0;
22631945Sjeanm int no_quorum = 0;
22641945Sjeanm int partial = 0;
2265734Smw145384
2266734Smw145384 /* Calculates the correct indentation. */
2267734Smw145384 indent[0] = 0;
2268734Smw145384 for (i = 0; i < in; i++)
2269734Smw145384 (void) strlcat(indent, " ", sizeof (indent));
2270734Smw145384
2271734Smw145384 /*
2272734Smw145384 * This will print before the information for the first diskset
2273734Smw145384 * if the verbose option was set.
2274734Smw145384 */
2275734Smw145384 if (set_count == 1) {
2276734Smw145384 if (imp_flags & META_IMP_REPORT) {
2277734Smw145384 (void) printf("\n%s:\n\n",
2278734Smw145384 gettext("Disksets eligible for import"));
2279734Smw145384 }
2280734Smw145384 }
2281734Smw145384
22821945Sjeanm partial = misp->mis_partial;
22831945Sjeanm good_disk = pick_good_disk(misp);
22841945Sjeanm if (good_disk == NULL) {
22851945Sjeanm return (rval);
22861945Sjeanm }
22871945Sjeanm
2288734Smw145384 /*
2289734Smw145384 * Make the distinction between a regular diskset and
22901945Sjeanm * a replicated diskset. Also make the distinction
22911945Sjeanm * between a partial vs. full diskset.
2292734Smw145384 */
22931945Sjeanm if (partial == MD_IM_PARTIAL_DISKSET) {
22941945Sjeanm if (misp->mis_flags & MD_IM_SET_REPLICATED) {
22951945Sjeanm if (imp_flags & META_IMP_REPORT) {
22961945Sjeanm (void) printf("%i) %s:\n", set_count, gettext(
22971945Sjeanm "Found partial replicated diskset "
22981945Sjeanm "containing disks"));
22991945Sjeanm } else {
23001945Sjeanm (void) printf("\n%s:\n", gettext(
23011945Sjeanm "Importing partial replicated diskset "
23021945Sjeanm "containing disks"));
23031945Sjeanm }
2304734Smw145384 } else {
23051945Sjeanm if (imp_flags & META_IMP_REPORT) {
23061945Sjeanm (void) printf("%i) %s:\n", set_count, gettext(
23071945Sjeanm "Found partial regular diskset containing "
23081945Sjeanm "disks"));
23091945Sjeanm } else {
23101945Sjeanm (void) printf("\n%s:\n", gettext(
23111945Sjeanm "Importing partial regular diskset "
23121945Sjeanm "containing disks"));
23131945Sjeanm }
2314734Smw145384 }
2315734Smw145384 } else {
23161945Sjeanm if (misp->mis_flags & MD_IM_SET_REPLICATED) {
23171945Sjeanm if (imp_flags & META_IMP_REPORT) {
23181945Sjeanm (void) printf("%i) %s:\n", set_count, gettext(
23191945Sjeanm "Found replicated diskset containing "
23201945Sjeanm "disks"));
23211945Sjeanm } else {
23221945Sjeanm (void) printf("\n%s:\n", gettext(
23231945Sjeanm "Importing replicated diskset containing "
23241945Sjeanm "disks"));
23251945Sjeanm }
2326734Smw145384 } else {
23271945Sjeanm if (imp_flags & META_IMP_REPORT) {
23281945Sjeanm (void) printf("%i) %s:\n", set_count, gettext(
23291945Sjeanm "Found regular diskset containing disks"));
23301945Sjeanm } else {
23311945Sjeanm (void) printf("\n%s:\n", gettext(
23321945Sjeanm "Importing regular diskset containing "
23331945Sjeanm "disks"));
23341945Sjeanm }
2335734Smw145384 }
2336734Smw145384 }
2337734Smw145384
2338734Smw145384 /*
23391945Sjeanm * Check each drive in the set. If it's unavailable or
23401945Sjeanm * an overlap tell the user.
2341734Smw145384 */
2342734Smw145384 for (d = misp->mis_drives; d != NULL; d = d->mid_next) {
23431945Sjeanm (void) fprintf(stdout, " %s", d->mid_dnp->cname);
23441945Sjeanm if (d->mid_available == MD_IM_DISK_NOT_AVAILABLE) {
23451945Sjeanm (void) fprintf(stdout, " (UNAVAIL)");
23461945Sjeanm }
23471945Sjeanm if (overlap) {
23481945Sjeanm md_im_drive_info_t **chain;
23491945Sjeanm /*
23501945Sjeanm * There is the potential for an overlap, see if
23511945Sjeanm * this disk is one of the overlapped disks.
23521945Sjeanm */
23531945Sjeanm for (chain = &overlap_disks; *chain != NULL;
23541945Sjeanm chain = &(*chain)->overlap) {
23551945Sjeanm if (strcmp(d->mid_dnp->cname,
23561945Sjeanm (*chain)->mid_dnp->cname) == 0) {
23571945Sjeanm (void) fprintf(stdout, " (CONFLICT)");
23581945Sjeanm has_overlap = 1;
2359734Smw145384 break;
2360734Smw145384 }
2361734Smw145384 }
2362734Smw145384 }
23631945Sjeanm (void) fprintf(stdout, "\n");
2364734Smw145384 }
2365734Smw145384
2366734Smw145384 /*
23671945Sjeanm * This note explains the (UNAVAIL) that appears next to the
23681945Sjeanm * disks in the diskset that are not available.
2369734Smw145384 */
23701945Sjeanm if (partial) {
23711945Sjeanm (void) printf("%s%s\n%s%s\n\n", indent,
23721945Sjeanm gettext("(UNAVAIL) WARNING: This disk is unavailable on"
23731945Sjeanm " this system."), indent, gettext("Import may corrupt "
23741945Sjeanm "data in the diskset."));
2375734Smw145384 }
2376734Smw145384
2377734Smw145384 /*
23781945Sjeanm * This note explains the (CONFLICT) that appears next to the
23791945Sjeanm * disks whose lb_inittime timestamp does not
2380734Smw145384 * match the rest of the diskset.
2381734Smw145384 */
23821945Sjeanm if (has_overlap) {
2383734Smw145384 (void) printf("%s%s\n%s%s\n\n", indent,
23841945Sjeanm gettext("(CONFLICT) WARNING: This disk has been reused in "
23851945Sjeanm "another diskset or system configuration."), indent,
23861945Sjeanm gettext("Import may corrupt data in the diskset."));
2387734Smw145384 }
2388734Smw145384
2389734Smw145384 /*
2390734Smw145384 * If the verbose flag was given on the command line,
2391734Smw145384 * we will print out the metastat -c information , the
2392734Smw145384 * creation time, and last modified time for the diskset.
2393734Smw145384 */
2394734Smw145384 if (imp_flags & META_IMP_VERBOSE) {
2395734Smw145384 (void) printf("%s%s\n", indent,
2396734Smw145384 gettext("Metadatabase information:"));
2397734Smw145384 report_metadb_info(misp, indent);
2398734Smw145384
2399734Smw145384 /*
2400734Smw145384 * Printing creation time and last modified time.
2401734Smw145384 * Last modified: uses the global variable "lastaccess",
2402734Smw145384 * which is set to the last updated timestamp from all of
2403734Smw145384 * the database blocks(db_timestamp) or record blocks
2404734Smw145384 * (rb_timestamp).
2405734Smw145384 * Creation time is the locator block init time
2406734Smw145384 * (lb_inittime).
2407734Smw145384 */
2408734Smw145384 lastaccess = good_disk->mid_replicas->mir_timestamp;
2409734Smw145384
2410734Smw145384 (void) printf("%s%s\n", indent,
2411734Smw145384 gettext("Metadevice information:"));
2412734Smw145384 rval = report_metastat_info(mb, lbp, nm, pnm, rsp, fd,
2413734Smw145384 &lastaccess, ep);
2414734Smw145384 if (rval < 0) {
2415734Smw145384 return (rval);
2416734Smw145384 }
2417734Smw145384
2418734Smw145384 (void) printf("%s%s:\t%s\n", indent,
2419734Smw145384 gettext("Creation time"),
2420734Smw145384 meta_print_time(&good_disk->mid_replicas->mir_timestamp));
2421734Smw145384 (void) printf("%s%s:\t%s\n", indent,
2422734Smw145384 gettext("Last modified time"),
2423734Smw145384 meta_print_time(&lastaccess));
2424734Smw145384 } else {
2425734Smw145384 /*
2426734Smw145384 * Even if the verbose option is not set, we will print the
2427734Smw145384 * creation time for the diskset.
2428734Smw145384 */
2429734Smw145384 (void) printf("%s%s:\t%s\n", indent, gettext("Creation time"),
2430734Smw145384 meta_print_time(&good_disk->mid_replicas->mir_timestamp));
2431734Smw145384 }
2432734Smw145384
2433734Smw145384
2434734Smw145384 /*
2435734Smw145384 * If the diskset is not actually being imported, then we
2436734Smw145384 * print out extra information about how to import it.
2437734Smw145384 * If the verbose flag was not set, then we will also
2438734Smw145384 * print out information about how to obtain verbose output.
2439734Smw145384 */
2440734Smw145384 if (imp_flags & META_IMP_REPORT) {
2441734Smw145384 /*
2442734Smw145384 * TRANSLATION_NOTE
2443734Smw145384 *
2444734Smw145384 * The translation of the phrase "For more information
2445734Smw145384 * about this set" will be followed by a ":" and a
2446734Smw145384 * suggested command (untranslatable) that the user
2447734Smw145384 * may use to request additional information.
2448734Smw145384 */
2449734Smw145384 if (!(imp_flags & META_IMP_VERBOSE)) {
2450734Smw145384 (void) printf("%s%s:\n%s %s -r -v %s\n", indent,
2451734Smw145384 gettext("For more information about this diskset"),
2452734Smw145384 indent, myname, good_disk->mid_dnp->cname);
2453734Smw145384 }
24541945Sjeanm
24551945Sjeanm if (meta_replica_quorum(misp) != 0)
24561945Sjeanm no_quorum = 1;
24571945Sjeanm
2458734Smw145384 /*
2459734Smw145384 * TRANSLATION_NOTE
2460734Smw145384 *
2461734Smw145384 * The translation of the phrase "To import this set"
2462734Smw145384 * will be followed by a ":" and a suggested command
2463734Smw145384 * (untranslatable) that the user may use to import
2464734Smw145384 * the specified diskset.
2465734Smw145384 */
24661945Sjeanm if (partial || has_overlap || no_quorum) {
24671945Sjeanm (void) printf("%s%s:\n%s %s -f -s <newsetname> %s\n",
24681945Sjeanm indent, gettext("To import this diskset"), indent,
24691945Sjeanm myname, good_disk->mid_dnp->cname);
24701945Sjeanm } else {
24711945Sjeanm (void) printf("%s%s:\n%s %s -s <newsetname> %s\n",
24721945Sjeanm indent, gettext("To import this diskset"), indent,
24731945Sjeanm myname, good_disk->mid_dnp->cname);
24741945Sjeanm }
2475734Smw145384 }
2476734Smw145384 (void) printf("\n\n");
2477734Smw145384
2478734Smw145384 return (rval);
2479734Smw145384 }
2480734Smw145384
2481734Smw145384
2482734Smw145384 /*
2483734Smw145384 * meta_get_and_report_set_info
24840Sstevel@tonic-gate *
24850Sstevel@tonic-gate * Scans a given drive for set specific information. If the given drive
24860Sstevel@tonic-gate * has a shared metadb, scans the shared metadb for information pertaining
24870Sstevel@tonic-gate * to the set.
24881945Sjeanm * If imp_flags has META_IMP_PASS1 set don't report.
24890Sstevel@tonic-gate *
24900Sstevel@tonic-gate * Returns:
24910Sstevel@tonic-gate * <0 for failure
24920Sstevel@tonic-gate * 0 success but no replicas were found
24930Sstevel@tonic-gate * 1 success and a replica was found
24940Sstevel@tonic-gate */
24950Sstevel@tonic-gate int
meta_get_and_report_set_info(mddrivenamelist_t * dp,md_im_set_desc_t ** mispp,int local_mb_ok,uint_t imp_flags,int * set_count,int overlap,md_im_drive_info_t * overlap_disks,md_error_t * ep)2496734Smw145384 meta_get_and_report_set_info(
2497734Smw145384 mddrivenamelist_t *dp,
2498734Smw145384 md_im_set_desc_t **mispp,
2499734Smw145384 int local_mb_ok,
2500734Smw145384 uint_t imp_flags,
2501734Smw145384 int *set_count,
25021945Sjeanm int overlap,
25031945Sjeanm md_im_drive_info_t *overlap_disks,
2504734Smw145384 md_error_t *ep
25050Sstevel@tonic-gate )
25060Sstevel@tonic-gate {
25070Sstevel@tonic-gate uint_t s;
25080Sstevel@tonic-gate mdname_t *rsp;
25090Sstevel@tonic-gate int fd;
25100Sstevel@tonic-gate char mb[DEV_BSIZE];
25110Sstevel@tonic-gate /*LINTED*/
25120Sstevel@tonic-gate mddb_mb_t *mbp = (mddb_mb_t *)mb;
25130Sstevel@tonic-gate char lb[dbtob(MDDB_LBCNT)];
25140Sstevel@tonic-gate /*LINTED*/
25150Sstevel@tonic-gate mddb_lb_t *lbp = (mddb_lb_t *)lb;
25160Sstevel@tonic-gate mddb_did_blk_t *lbdidp = NULL;
25170Sstevel@tonic-gate mddb_ln_t *lnp = NULL;
25180Sstevel@tonic-gate int lnsize, lbdid_size;
25190Sstevel@tonic-gate int rval = 0;
25200Sstevel@tonic-gate char db[DEV_BSIZE];
25210Sstevel@tonic-gate /*LINTED*/
25220Sstevel@tonic-gate mddb_db_t *dbp = (mddb_db_t *)db;
25230Sstevel@tonic-gate did_list_t *did_listp = NULL;
25240Sstevel@tonic-gate mddrivenamelist_t *dnlp;
25250Sstevel@tonic-gate mddrivename_t *dnp;
25260Sstevel@tonic-gate md_im_names_t cnames = { 0, NULL};
25271945Sjeanm char *nm = NULL, *shrnm = NULL;
25280Sstevel@tonic-gate char *did_nm = NULL, *did_shrnm = NULL;
25290Sstevel@tonic-gate struct nm_rec *nmp;
25301945Sjeanm struct nm_shr_rec *snmp;
25310Sstevel@tonic-gate struct devid_shr_rec *did_shrnmp;
25320Sstevel@tonic-gate struct devid_min_rec *did_nmp;
25330Sstevel@tonic-gate int extended_namespace = 0;
25340Sstevel@tonic-gate int replicated = 0;
25351945Sjeanm int partial = 0;
2536734Smw145384 pnm_rec_t *pnm = NULL; /* list of physical devs in set */
2537734Smw145384 md_im_set_desc_t *misp;
25380Sstevel@tonic-gate
25390Sstevel@tonic-gate dnp = dp->drivenamep;
25400Sstevel@tonic-gate
25410Sstevel@tonic-gate /*
25420Sstevel@tonic-gate * Determine and open the replica slice
25430Sstevel@tonic-gate */
25440Sstevel@tonic-gate if (meta_replicaslice(dnp, &s, ep) != 0) {
25450Sstevel@tonic-gate return (-1);
25460Sstevel@tonic-gate }
25470Sstevel@tonic-gate
25480Sstevel@tonic-gate /*
25490Sstevel@tonic-gate * Test for the size of replica slice in question. If
25500Sstevel@tonic-gate * the size is zero, we know that this is not a disk that was
25510Sstevel@tonic-gate * part of a set and it should be silently ignored for import.
25520Sstevel@tonic-gate */
25530Sstevel@tonic-gate if (dnp->vtoc.parts[s].size == 0)
25540Sstevel@tonic-gate return (0);
25550Sstevel@tonic-gate
25560Sstevel@tonic-gate if ((rsp = metaslicename(dnp, s, ep)) == NULL) {
25570Sstevel@tonic-gate return (-1);
25580Sstevel@tonic-gate }
25590Sstevel@tonic-gate
25600Sstevel@tonic-gate if ((fd = open(rsp->rname, O_RDONLY|O_NDELAY)) < 0)
25610Sstevel@tonic-gate return (mdsyserror(ep, errno, rsp->cname));
25620Sstevel@tonic-gate
25630Sstevel@tonic-gate /*
25640Sstevel@tonic-gate * After the open() succeeds, we should return via the "out"
25650Sstevel@tonic-gate * label to clean up after ourselves. (Up 'til now, we can
25660Sstevel@tonic-gate * just return directly, because there are no resources to
25670Sstevel@tonic-gate * give back.)
25680Sstevel@tonic-gate */
25690Sstevel@tonic-gate
25700Sstevel@tonic-gate if ((rval = read_master_block(ep, fd, mbp, sizeof (mb))) <= 0)
25710Sstevel@tonic-gate goto out;
25720Sstevel@tonic-gate
25730Sstevel@tonic-gate replicated = is_replicated(fd, mbp, 0, NULL);
25740Sstevel@tonic-gate
25750Sstevel@tonic-gate if (!local_mb_ok && mbp->mb_setno == 0) {
25760Sstevel@tonic-gate rval = 0;
25770Sstevel@tonic-gate goto out;
25780Sstevel@tonic-gate }
25790Sstevel@tonic-gate
25800Sstevel@tonic-gate if ((rval = read_locator_block(ep, fd, mbp, lbp, sizeof (lb))) <= 0)
25810Sstevel@tonic-gate goto out;
25820Sstevel@tonic-gate
25830Sstevel@tonic-gate /*
25840Sstevel@tonic-gate * Once the locator block has been read, we need to
25850Sstevel@tonic-gate * check if the locator block commit count is zero.
25860Sstevel@tonic-gate * If it is zero, we know that the replica we're dealing
25870Sstevel@tonic-gate * with is on a disk that was deleted from the disk set;
25880Sstevel@tonic-gate * and, it potentially has stale data. We need to quit
25890Sstevel@tonic-gate * in that case
25900Sstevel@tonic-gate */
25910Sstevel@tonic-gate if (lbp->lb_commitcnt == 0) {
25920Sstevel@tonic-gate rval = 0;
25930Sstevel@tonic-gate goto out;
25940Sstevel@tonic-gate }
25950Sstevel@tonic-gate
25960Sstevel@tonic-gate /*
25970Sstevel@tonic-gate * Make sure that the disk being imported has device id
25980Sstevel@tonic-gate * namespace present for disksets. If a disk doesn't have
25990Sstevel@tonic-gate * device id namespace, we skip reading the replica on that disk
26000Sstevel@tonic-gate */
26010Sstevel@tonic-gate if (!(lbp->lb_flags & MDDB_DEVID_STYLE)) {
26020Sstevel@tonic-gate rval = 0;
26030Sstevel@tonic-gate goto out;
26040Sstevel@tonic-gate }
26050Sstevel@tonic-gate
26060Sstevel@tonic-gate /*
26070Sstevel@tonic-gate * Grab the locator block device id array. Allocate memory for the
26080Sstevel@tonic-gate * array first.
26090Sstevel@tonic-gate */
26100Sstevel@tonic-gate lbdid_size = dbtob(lbp->lb_didblkcnt);
26110Sstevel@tonic-gate lbdidp = Zalloc(lbdid_size);
26120Sstevel@tonic-gate
26130Sstevel@tonic-gate if ((rval = read_locator_block_did(ep, fd, mbp, lbp, lbdidp,
26140Sstevel@tonic-gate lbdid_size)) <= 0)
26150Sstevel@tonic-gate goto out;
26160Sstevel@tonic-gate
26170Sstevel@tonic-gate /*
26180Sstevel@tonic-gate * For a disk that has not been replicated, extract the device ids
26190Sstevel@tonic-gate * stored in the locator block device id array and store them in
26200Sstevel@tonic-gate * a list.
26210Sstevel@tonic-gate *
26220Sstevel@tonic-gate * If the disk has been replicated using replication software such
26230Sstevel@tonic-gate * as HDS Truecopy/ShadowImage or EMC SRDF/BCV, the device ids in
26240Sstevel@tonic-gate * the locator block are invalid and we need to build a list of
26250Sstevel@tonic-gate * replicated disks.
26260Sstevel@tonic-gate */
26271945Sjeanm if (imp_flags & META_IMP_PASS1) {
26281945Sjeanm /*
26291945Sjeanm * We need to do this for both passes but
26301945Sjeanm * replicated_disk_list_built is global so we need some way
26311945Sjeanm * to determine which pass we're on. Set it to the appropriate
26321945Sjeanm * pass's flag.
26331945Sjeanm */
26341945Sjeanm replicated_disk_list_built = &replicated_disk_list_built_pass1;
26351945Sjeanm } else {
26361945Sjeanm replicated_disk_list_built = &replicated_disk_list_built_pass2;
26371945Sjeanm }
26381945Sjeanm if (replicated && !(*replicated_disk_list_built)) {
26390Sstevel@tonic-gate /*
26400Sstevel@tonic-gate * if there's a replicated diskset involved, we need to
26410Sstevel@tonic-gate * scan the system one more time and build a list of all
26420Sstevel@tonic-gate * candidate disks that might be part of that replicated set
26430Sstevel@tonic-gate */
26440Sstevel@tonic-gate if (meta_list_disks(ep, &cnames) != 0) {
26450Sstevel@tonic-gate rval = 0;
26460Sstevel@tonic-gate goto out;
26470Sstevel@tonic-gate }
26480Sstevel@tonic-gate dnlp = meta_prune_cnames(ep, &cnames, 0);
26490Sstevel@tonic-gate rval = build_replicated_disks_list(ep, dnlp);
26500Sstevel@tonic-gate if (rval == 0)
26510Sstevel@tonic-gate goto out;
26520Sstevel@tonic-gate }
26530Sstevel@tonic-gate
26540Sstevel@tonic-gate /*
26550Sstevel@tonic-gate * Until here, we've gotten away with fixed sizes for the
26560Sstevel@tonic-gate * master block and locator block. The locator names,
26570Sstevel@tonic-gate * however, are sized (and therefore allocated) dynamically
26580Sstevel@tonic-gate * according to information in the locator block.
26590Sstevel@tonic-gate */
26600Sstevel@tonic-gate lnsize = dbtob(lbp->lb_lnblkcnt);
26610Sstevel@tonic-gate lnp = Zalloc(lnsize);
26620Sstevel@tonic-gate
26630Sstevel@tonic-gate if ((rval = read_locator_names(ep, fd, mbp, lbp, lnp, lnsize)) <= 0)
26640Sstevel@tonic-gate goto out;
26650Sstevel@tonic-gate
26661945Sjeanm rval = build_did_list(ep, fd, mbp, lbp, lbdidp, lnp, &did_listp,
26671945Sjeanm replicated);
26681945Sjeanm
26691945Sjeanm /*
26701945Sjeanm * An rval of ENOTSUP means we have a partial diskset. We'll want
26711945Sjeanm * to set the partial variable so we can pass this information
26721945Sjeanm * set_append_wrapper later for placing on the misp list.
26731945Sjeanm */
26741945Sjeanm if (rval == ENOTSUP)
26751945Sjeanm partial = MD_IM_PARTIAL_DISKSET;
26761945Sjeanm
26771945Sjeanm if (rval < 0)
26781945Sjeanm goto out;
26791945Sjeanm
26800Sstevel@tonic-gate /*
26810Sstevel@tonic-gate * Read in the NM record
26820Sstevel@tonic-gate * If no NM record was found, it still is a valid configuration
26830Sstevel@tonic-gate * but it also means that we won't find any corresponding DID_NM
26840Sstevel@tonic-gate * or DID_SHR_NM.
26850Sstevel@tonic-gate */
26860Sstevel@tonic-gate if ((rval = read_nm_rec(ep, fd, mbp, lbp, &nm, MDDB_NM, rsp->cname))
26870Sstevel@tonic-gate < 0)
26880Sstevel@tonic-gate goto out;
26890Sstevel@tonic-gate else if (rval == 0)
26900Sstevel@tonic-gate goto append;
26910Sstevel@tonic-gate
26920Sstevel@tonic-gate /*
26930Sstevel@tonic-gate * At this point, we have read in all of the blocks that form
26940Sstevel@tonic-gate * the nm_rec. We should at least detect the corner case
26950Sstevel@tonic-gate * mentioned above, in which r_next_recid links to another
26960Sstevel@tonic-gate * nm_rec. Extended namespace handling is left for Phase 2.
26970Sstevel@tonic-gate *
26980Sstevel@tonic-gate * What this should really be is a loop, each iteration of
2699734Smw145384 * which reads in a nm_rec and calls the set_append().
27000Sstevel@tonic-gate */
27010Sstevel@tonic-gate /*LINTED*/
27020Sstevel@tonic-gate nmp = (struct nm_rec *)(nm + sizeof (mddb_rb_t));
27030Sstevel@tonic-gate if (nmp->r_rec_hdr.r_next_recid != (mddb_recid_t)0) {
27040Sstevel@tonic-gate extended_namespace = 1;
27050Sstevel@tonic-gate rval = 0;
27060Sstevel@tonic-gate goto out;
27070Sstevel@tonic-gate }
27080Sstevel@tonic-gate
27091945Sjeanm if ((rval = read_nm_rec(ep, fd, mbp, lbp, &shrnm, MDDB_SHR_NM,
27101945Sjeanm rsp->cname)) < 0)
27111945Sjeanm goto out;
27121945Sjeanm else if (rval == 0)
27131945Sjeanm goto append;
27141945Sjeanm
27151945Sjeanm /*LINTED*/
27161945Sjeanm snmp = (struct nm_shr_rec *)(shrnm + sizeof (mddb_rb_t));
27171945Sjeanm if (snmp->sr_rec_hdr.r_next_recid != (mddb_recid_t)0) {
27181945Sjeanm extended_namespace = 1;
27191945Sjeanm rval = 0;
27201945Sjeanm goto out;
27211945Sjeanm }
27221945Sjeanm
27230Sstevel@tonic-gate if ((rval = read_nm_rec(ep, fd, mbp, lbp, &did_nm,
27240Sstevel@tonic-gate MDDB_DID_NM, rsp->cname)) < 0)
27250Sstevel@tonic-gate goto out;
27260Sstevel@tonic-gate else if (rval == 0)
27270Sstevel@tonic-gate goto append;
27280Sstevel@tonic-gate
27290Sstevel@tonic-gate /*LINTED*/
273057Sjeanm did_nmp = (struct devid_min_rec *)(did_nm + sizeof (mddb_rb_t) -
273157Sjeanm sizeof (int));
27320Sstevel@tonic-gate if (did_nmp->min_rec_hdr.r_next_recid != (mddb_recid_t)0) {
27330Sstevel@tonic-gate extended_namespace = 1;
27340Sstevel@tonic-gate rval = 0;
27350Sstevel@tonic-gate goto out;
27360Sstevel@tonic-gate }
27370Sstevel@tonic-gate
27380Sstevel@tonic-gate if ((rval = read_nm_rec(ep, fd, mbp, lbp, &did_shrnm,
27390Sstevel@tonic-gate MDDB_DID_SHR_NM, rsp->cname)) < 0)
27400Sstevel@tonic-gate goto out;
27410Sstevel@tonic-gate else if (rval == 0)
27420Sstevel@tonic-gate goto append;
27430Sstevel@tonic-gate
27440Sstevel@tonic-gate /*LINTED*/
274557Sjeanm did_shrnmp = (struct devid_shr_rec *)(did_shrnm + sizeof (mddb_rb_t) -
274657Sjeanm sizeof (int));
27470Sstevel@tonic-gate if (did_shrnmp->did_rec_hdr.r_next_recid != (mddb_recid_t)0) {
27480Sstevel@tonic-gate extended_namespace = 1;
27490Sstevel@tonic-gate rval = 0;
27500Sstevel@tonic-gate goto out;
27510Sstevel@tonic-gate }
27520Sstevel@tonic-gate
275357Sjeanm /*
275457Sjeanm * We need to check if all of the disks listed in the namespace
275557Sjeanm * are actually available. If they aren't we'll return with
275657Sjeanm * an ENOTSUP error which indicates a partial diskset.
275757Sjeanm */
27581945Sjeanm rval = check_nm_disks(did_nmp, did_shrnmp);
27591945Sjeanm
27601945Sjeanm /*
27611945Sjeanm * An rval of ENOTSUP means we have a partial diskset. We'll want
27621945Sjeanm * to set the partial variable so we can pass this information
27631945Sjeanm * to set_append_wrapper later for placing on the misp list.
27641945Sjeanm */
27651945Sjeanm if (rval == ENOTSUP)
27661945Sjeanm partial = MD_IM_PARTIAL_DISKSET;
27671945Sjeanm
27681945Sjeanm if (rval < 0)
276957Sjeanm goto out;
277057Sjeanm
27710Sstevel@tonic-gate append:
27720Sstevel@tonic-gate /* Finally, we've got what we need to process this replica. */
2773734Smw145384 misp = set_append(mispp, did_listp, mbp, lbp,
27740Sstevel@tonic-gate /*LINTED*/
27751945Sjeanm (mddb_rb_t *)nm, (mddb_rb_t *)shrnm, &pnm, (mddb_rb_t *)did_nm,
27761945Sjeanm /*LINTED*/
27771945Sjeanm (mddb_rb_t *)did_shrnm, (imp_flags | partial | replicated), ep);
27781945Sjeanm
27791945Sjeanm if (!(imp_flags & META_IMP_PASS1)) {
27801945Sjeanm *set_count += 1;
27811945Sjeanm rval = report_set_info(misp, mbp, lbp,
27821945Sjeanm /*LINTED*/
27831945Sjeanm (mddb_rb_t *)nm, &pnm, rsp, fd, imp_flags, *set_count,
27841945Sjeanm overlap, overlap_disks, ep);
27851945Sjeanm if (rval < 0)
27861945Sjeanm goto out;
27871945Sjeanm }
27880Sstevel@tonic-gate
27890Sstevel@tonic-gate /* Return the fact that we found at least one set */
27900Sstevel@tonic-gate rval = 1;
27910Sstevel@tonic-gate
27920Sstevel@tonic-gate out:
27930Sstevel@tonic-gate if (fd >= 0)
27940Sstevel@tonic-gate (void) close(fd);
27950Sstevel@tonic-gate if (did_listp != NULL)
27960Sstevel@tonic-gate free_did_list(did_listp);
27970Sstevel@tonic-gate if (lnp != NULL)
27980Sstevel@tonic-gate Free(lnp);
27990Sstevel@tonic-gate if (nm != NULL)
28000Sstevel@tonic-gate Free(nm);
28010Sstevel@tonic-gate if (did_nm != NULL)
28020Sstevel@tonic-gate Free(did_nm);
28030Sstevel@tonic-gate if (did_shrnm != NULL)
28040Sstevel@tonic-gate Free(did_shrnm);
2805734Smw145384 if (pnm != NULL)
2806734Smw145384 free_pnm_rec_list(&pnm);
28070Sstevel@tonic-gate
28080Sstevel@tonic-gate /*
28090Sstevel@tonic-gate * If we are at the end of the list, we must free up
28100Sstevel@tonic-gate * the replicated list too
28110Sstevel@tonic-gate */
28120Sstevel@tonic-gate if (dp->next == NULL)
28130Sstevel@tonic-gate free_replicated_disks_list();
28140Sstevel@tonic-gate
28150Sstevel@tonic-gate if (extended_namespace)
28160Sstevel@tonic-gate return (mddserror(ep, MDE_DS_EXTENDEDNM, MD_SET_BAD,
28170Sstevel@tonic-gate mynode(), NULL, NULL));
28180Sstevel@tonic-gate
28190Sstevel@tonic-gate return (rval);
28200Sstevel@tonic-gate }
28210Sstevel@tonic-gate
28220Sstevel@tonic-gate /*
28230Sstevel@tonic-gate * Return the minor name associated with a given disk slice
28240Sstevel@tonic-gate */
28250Sstevel@tonic-gate static char *
meta_getminor_name(char * devname,md_error_t * ep)28260Sstevel@tonic-gate meta_getminor_name(
28270Sstevel@tonic-gate char *devname,
28280Sstevel@tonic-gate md_error_t *ep
28290Sstevel@tonic-gate )
28300Sstevel@tonic-gate {
28310Sstevel@tonic-gate int fd = -1;
28320Sstevel@tonic-gate char *minor_name = NULL;
28330Sstevel@tonic-gate char *ret_minor_name = NULL;
28340Sstevel@tonic-gate
28350Sstevel@tonic-gate if (devname == NULL)
28360Sstevel@tonic-gate return (NULL);
28370Sstevel@tonic-gate
28380Sstevel@tonic-gate if ((fd = open(devname, O_RDONLY|O_NDELAY, 0)) < 0) {
28390Sstevel@tonic-gate (void) mdsyserror(ep, errno, devname);
28400Sstevel@tonic-gate return (NULL);
28410Sstevel@tonic-gate }
28420Sstevel@tonic-gate
28430Sstevel@tonic-gate if (devid_get_minor_name(fd, &minor_name) == 0) {
28440Sstevel@tonic-gate ret_minor_name = Strdup(minor_name);
28450Sstevel@tonic-gate devid_str_free(minor_name);
28460Sstevel@tonic-gate }
28470Sstevel@tonic-gate
28480Sstevel@tonic-gate (void) close(fd);
28490Sstevel@tonic-gate return (ret_minor_name);
28500Sstevel@tonic-gate }
28510Sstevel@tonic-gate
28521945Sjeanm /*
28531945Sjeanm * meta_update_mb_did
28541945Sjeanm *
28551945Sjeanm * Update or create the master block with the new set number.
28561945Sjeanm * If a non-null devid pointer is given, the devid in the
28571945Sjeanm * master block will also be changed.
28581945Sjeanm *
28591945Sjeanm * This routine is called during the import of a diskset
28601945Sjeanm * (meta_imp_update_mb) and during the take of a diskset that has
28611945Sjeanm * some unresolved replicated drives (meta_unrslv_replicated_mb).
28621945Sjeanm *
28631945Sjeanm * Returns : nothing (void)
28641945Sjeanm */
28651945Sjeanm static void
meta_update_mb_did(mdsetname_t * sp,mddrivename_t * dnp,void * new_devid,int new_devid_len,void * old_devid,int replica_present,int offset,md_error_t * ep)28661945Sjeanm meta_update_mb_did(
28671945Sjeanm mdsetname_t *sp,
28681945Sjeanm mddrivename_t *dnp, /* raw name of drive with mb */
28691945Sjeanm void *new_devid, /* devid to be stored in mb */
28701945Sjeanm int new_devid_len,
28711945Sjeanm void *old_devid, /* old devid stored in mb */
28721945Sjeanm int replica_present, /* does replica follow mb? */
28731945Sjeanm int offset,
28741945Sjeanm md_error_t *ep
28750Sstevel@tonic-gate )
28760Sstevel@tonic-gate {
28771945Sjeanm int fd;
28781945Sjeanm struct mddb_mb *mbp;
28791945Sjeanm uint_t sliceno;
28801945Sjeanm mdname_t *rsp;
28811945Sjeanm
28821945Sjeanm /* determine the replica slice */
28831945Sjeanm if (meta_replicaslice(dnp, &sliceno, ep) != 0) {
28841945Sjeanm return;
28851945Sjeanm }
28861945Sjeanm
28871945Sjeanm /*
28881945Sjeanm * if the replica slice size is zero,
28891945Sjeanm * don't bother opening
28901945Sjeanm */
28911945Sjeanm if (dnp->vtoc.parts[sliceno].size == 0) {
28921945Sjeanm return;
28931945Sjeanm }
28941945Sjeanm
28951945Sjeanm if ((rsp = metaslicename(dnp, sliceno, ep)) == NULL) {
28961945Sjeanm return;
28971945Sjeanm }
28981945Sjeanm
28991945Sjeanm if ((fd = open(rsp->rname, O_RDWR | O_NDELAY)) < 0) {
29001945Sjeanm return;
29011945Sjeanm }
29021945Sjeanm
29031945Sjeanm if (lseek(fd, (off_t)dbtob(offset), SEEK_SET) < 0)
29041945Sjeanm return;
29051945Sjeanm
29061945Sjeanm mbp = Zalloc(DEV_BSIZE);
29071945Sjeanm if (read(fd, mbp, DEV_BSIZE) != DEV_BSIZE) {
29081945Sjeanm Free(mbp);
29091945Sjeanm return;
29101945Sjeanm }
29111945Sjeanm
29121945Sjeanm /* If no replica on disk, check for dummy mb */
29131945Sjeanm if (replica_present == NULL) {
29141945Sjeanm /*
29151945Sjeanm * Check to see if there is a dummy there. If not
29161945Sjeanm * create one. This would happen if the set was
29171945Sjeanm * created before the master block dummy code was
29181945Sjeanm * implemented.
29191945Sjeanm */
29201945Sjeanm if ((mbp->mb_magic != MDDB_MAGIC_DU) ||
29211945Sjeanm (mbp->mb_revision != MDDB_REV_MB)) {
29221945Sjeanm meta_mkdummymaster(sp, fd, offset);
29231945Sjeanm Free(mbp);
29241945Sjeanm return;
29251945Sjeanm }
29261945Sjeanm }
29271945Sjeanm
29281945Sjeanm mbp->mb_setno = sp->setno;
29291945Sjeanm if (meta_gettimeofday(&mbp->mb_timestamp) == -1) {
29301945Sjeanm Free(mbp);
29311945Sjeanm return;
29321945Sjeanm }
29331945Sjeanm
29341945Sjeanm /*
29351945Sjeanm * If a old_devid is non-NULL then we're are dealing with a
29361945Sjeanm * replicated diskset and the devid needs to be updated.
29371945Sjeanm */
29381945Sjeanm if (old_devid) {
29391945Sjeanm if (mbp->mb_devid_magic == MDDB_MAGIC_DE) {
29401945Sjeanm if (mbp->mb_devid_len)
29411945Sjeanm (void) memset(mbp->mb_devid, 0,
29421945Sjeanm mbp->mb_devid_len);
29431945Sjeanm (void) memcpy(mbp->mb_devid,
29441945Sjeanm (char *)new_devid, new_devid_len);
29451945Sjeanm mbp->mb_devid_len = new_devid_len;
29461945Sjeanm }
29471945Sjeanm }
29481945Sjeanm
29491945Sjeanm crcgen((uchar_t *)mbp, (uint_t *)&mbp->mb_checksum,
29501945Sjeanm (uint_t)DEV_BSIZE, (crc_skip_t *)NULL);
29511945Sjeanm
29521945Sjeanm /*
29531945Sjeanm * Now write out the changes to disk.
29541945Sjeanm * If an error occurs, just continue on.
29551945Sjeanm * Next take of set will register this drive as
29561945Sjeanm * an unresolved replicated drive and will attempt
29571945Sjeanm * to fix the master block again.
29581945Sjeanm */
29591945Sjeanm if (lseek(fd, (off_t)dbtob(offset), SEEK_SET) < 0) {
29601945Sjeanm Free(mbp);
29611945Sjeanm return;
29621945Sjeanm }
29631945Sjeanm if (write(fd, mbp, DEV_BSIZE) != DEV_BSIZE) {
29641945Sjeanm Free(mbp);
29651945Sjeanm return;
29661945Sjeanm }
29671945Sjeanm
29681945Sjeanm Free(mbp);
29691945Sjeanm (void) close(fd);
29701945Sjeanm }
29711945Sjeanm
29721945Sjeanm
29731945Sjeanm /*
29741945Sjeanm * meta_imp_update_mb
29751945Sjeanm *
29761945Sjeanm * Update the master block information during an import.
29771945Sjeanm * Takes an import set descriptor.
29781945Sjeanm *
29791945Sjeanm * Returns : nothing (void)
29801945Sjeanm */
29811945Sjeanm void
meta_imp_update_mb(mdsetname_t * sp,md_im_set_desc_t * misp,md_error_t * ep)29821945Sjeanm meta_imp_update_mb(mdsetname_t *sp, md_im_set_desc_t *misp, md_error_t *ep)
29831945Sjeanm {
29840Sstevel@tonic-gate md_im_drive_info_t *midp;
29850Sstevel@tonic-gate mddrivename_t *dnp;
29861945Sjeanm int offset = 16; /* default mb offset is 16 */
29871945Sjeanm
29881945Sjeanm for (midp = misp->mis_drives; midp != NULL; midp = midp->mid_next) {
29891945Sjeanm /*
29901945Sjeanm * If disk isn't available we can't update, so go to next
29911945Sjeanm */
29921945Sjeanm if (midp->mid_available == MD_IM_DISK_NOT_AVAILABLE) {
29931945Sjeanm continue;
29941945Sjeanm }
29950Sstevel@tonic-gate
29960Sstevel@tonic-gate dnp = midp->mid_dnp;
29970Sstevel@tonic-gate
29981945Sjeanm if (midp->mid_replicas) {
29991945Sjeanm md_im_replica_info_t *mirp;
30001945Sjeanm
30011945Sjeanm /*
30021945Sjeanm * If we have replicas on this disk we need to make
30031945Sjeanm * sure that we update the master block on every
30041945Sjeanm * replica on the disk.
30051945Sjeanm */
30061945Sjeanm for (mirp = midp->mid_replicas; mirp != NULL;
30071945Sjeanm mirp = mirp->mir_next) {
30081945Sjeanm offset = mirp->mir_offset;
30091945Sjeanm meta_update_mb_did(sp, dnp, midp->mid_devid,
30101945Sjeanm midp->mid_devid_sz, midp->mid_o_devid,
30111945Sjeanm 1, offset, ep);
30121945Sjeanm }
30131945Sjeanm } else {
30141945Sjeanm /* No replicas, just update the one dummy mb */
30151945Sjeanm meta_update_mb_did(sp, dnp, midp->mid_devid,
30161945Sjeanm midp->mid_devid_sz, midp->mid_o_devid,
30171945Sjeanm 0, offset, ep);
30181945Sjeanm }
30191945Sjeanm if (!mdisok(ep))
30201945Sjeanm return;
30211945Sjeanm }
30221945Sjeanm }
30231945Sjeanm
30241945Sjeanm /*
30251945Sjeanm * meta_unrslv_replicated_common
30261945Sjeanm *
30271945Sjeanm * Given a drive_desc and a drivenamelist pointer,
30281945Sjeanm * return the devidp associated with the drive_desc,
30291945Sjeanm * the replicated (new) devidp associated with the drive_desc
30301945Sjeanm * and the specific mddrivename in the drivenamelist that
30311945Sjeanm * matches the replicated (new) devidp.
30321945Sjeanm *
30331945Sjeanm * Typically the drivenamelist pointer would be setup by
30341945Sjeanm * the meta_prune_cnames function.
30351945Sjeanm *
30361945Sjeanm * Calling function must free devidp using devid_free.
30371945Sjeanm *
30381945Sjeanm * Returns 0 - success, found new_devidp and dnp_new.
30391945Sjeanm * Returns 1 - failure, didn't find new devid info
30401945Sjeanm */
30411945Sjeanm static int
meta_unrslv_replicated_common(int myside,md_drive_desc * dd,mddrivenamelist_t * dnlp,ddi_devid_t * devidp,ddi_devid_t * new_devidp,mddrivename_t ** dnp_new,md_error_t * ep)30421945Sjeanm meta_unrslv_replicated_common(
30431945Sjeanm int myside,
30441945Sjeanm md_drive_desc *dd, /* drive list for diskset */
30451945Sjeanm mddrivenamelist_t *dnlp, /* list of drives on current system */
30461945Sjeanm ddi_devid_t *devidp, /* old devid */
30471945Sjeanm ddi_devid_t *new_devidp, /* replicated (new) devid */
30481945Sjeanm mddrivename_t **dnp_new, /* replicated drive name */
30491945Sjeanm md_error_t *ep
30501945Sjeanm )
30511945Sjeanm {
30521945Sjeanm mddrivename_t *dnp; /* drive name of old drive */
30531945Sjeanm mdsidenames_t *sn = NULL;
30541945Sjeanm uint_t rep_slice;
30551945Sjeanm mdname_t *np;
30561945Sjeanm char *minor_name = NULL;
30571945Sjeanm char *devid_str = NULL;
30581945Sjeanm size_t len;
30591945Sjeanm int devid_sz;
30601945Sjeanm mddrivenamelist_t *dp;
30611945Sjeanm ddi_devid_t old_devid; /* devid of old drive */
30621945Sjeanm ddi_devid_t new_devid; /* devid of new replicated drive */
30631945Sjeanm ddi_devid_t dnp_new_devid; /* devid derived from drive */
30641945Sjeanm /* name of replicated drive */
30651945Sjeanm
30661945Sjeanm dnp = dd->dd_dnp;
30671945Sjeanm
30681945Sjeanm /* Get old devid from drive record */
30691945Sjeanm (void) devid_str_decode(dd->dd_dnp->devid,
30701945Sjeanm &old_devid, NULL);
30711945Sjeanm
30721945Sjeanm /* Look up replicated (new) devid */
30731945Sjeanm new_devid = replicated_list_lookup(
30741945Sjeanm devid_sizeof(old_devid), old_devid);
30751945Sjeanm
30761945Sjeanm devid_free(old_devid);
30771945Sjeanm
30781945Sjeanm if (new_devid == NULL)
30791945Sjeanm return (1);
30801945Sjeanm
30811945Sjeanm /*
30821945Sjeanm * Using new_devid, find a drivename entry with a matching devid.
30831945Sjeanm * Use the passed in dnlp since it has the new (replicated) disknames
30841945Sjeanm * in it.
30851945Sjeanm */
30861945Sjeanm for (dp = dnlp; dp != NULL; dp = dp->next) {
30871945Sjeanm (void) devid_str_decode(dp->drivenamep->devid,
30881945Sjeanm &dnp_new_devid, NULL);
30891945Sjeanm
30901945Sjeanm if (dnp_new_devid == NULL)
30911945Sjeanm continue;
30921945Sjeanm
30931945Sjeanm if (devid_compare(new_devid, dnp_new_devid) == 0) {
30941945Sjeanm devid_free(dnp_new_devid);
30951945Sjeanm break;
30961945Sjeanm }
30971945Sjeanm devid_free(dnp_new_devid);
30981945Sjeanm }
30991945Sjeanm
31001945Sjeanm /* If can't find new name for drive - nothing to update */
31011945Sjeanm if (dp == NULL)
31021945Sjeanm return (1);
31031945Sjeanm
31041945Sjeanm /*
31051945Sjeanm * Setup returned value to be the drivename structure associated
31061945Sjeanm * with new (replicated) drive.
31071945Sjeanm */
31081945Sjeanm *dnp_new = dp->drivenamep;
31091945Sjeanm
31101945Sjeanm /*
31111945Sjeanm * Need to return the new devid including the minor name.
31121945Sjeanm * Find the minor_name here using the sidename or by
31131945Sjeanm * looking in the namespace.
31141945Sjeanm */
31151945Sjeanm for (sn = dnp->side_names; sn != NULL; sn = sn->next) {
31161945Sjeanm if (sn->sideno == myside)
31171945Sjeanm break;
31181945Sjeanm }
31191945Sjeanm
31201945Sjeanm /*
31211945Sjeanm * The disk has no side name information
31221945Sjeanm */
31231945Sjeanm if (sn == NULL) {
31241945Sjeanm if ((meta_replicaslice(*dnp_new, &rep_slice, ep) != 0) ||
31251945Sjeanm ((np = metaslicename(*dnp_new, rep_slice, ep))
31260Sstevel@tonic-gate == NULL)) {
31270Sstevel@tonic-gate mdclrerror(ep);
31281945Sjeanm return (1);
31291945Sjeanm }
31301945Sjeanm
31311945Sjeanm if (np->dev == NODEV64)
31321945Sjeanm return (1);
31331945Sjeanm
31341945Sjeanm /*
31351945Sjeanm * minor_name will be NULL if dnp->devid == NULL
31361945Sjeanm * - see metagetvtoc()
31371945Sjeanm */
31381945Sjeanm if (np->minor_name == NULL)
31391945Sjeanm return (1);
31401945Sjeanm else
31411945Sjeanm minor_name = Strdup(np->minor_name);
31421945Sjeanm
31431945Sjeanm } else {
31441945Sjeanm minor_name = meta_getdidminorbykey(
31451945Sjeanm MD_LOCAL_SET, sn->sideno + SKEW,
31461945Sjeanm dnp->side_names_key, ep);
31471945Sjeanm if (!mdisok(ep))
31481945Sjeanm return (1);
31491945Sjeanm }
31501945Sjeanm /*
31511945Sjeanm * Now, use the old devid with minor name to lookup
31521945Sjeanm * the replicated (new) devid that will also contain
31531945Sjeanm * a minor name.
31541945Sjeanm */
31551945Sjeanm len = strlen(dnp->devid) + strlen(minor_name) + 2;
31561945Sjeanm devid_str = (char *)Malloc(len);
31571945Sjeanm (void) snprintf(devid_str, len, "%s/%s", dnp->devid,
31581945Sjeanm minor_name);
31591945Sjeanm (void) devid_str_decode(devid_str, devidp, NULL);
31601945Sjeanm Free(devid_str);
31611945Sjeanm devid_sz = devid_sizeof((ddi_devid_t)*devidp);
31621945Sjeanm *new_devidp = replicated_list_lookup(devid_sz, *devidp);
31631945Sjeanm return (0);
31641945Sjeanm }
31651945Sjeanm
31661945Sjeanm /*
31671945Sjeanm * meta_unrslv_replicated_mb
31681945Sjeanm *
31691945Sjeanm * Update the master block information during a take.
31701945Sjeanm * Takes an md_drive_desc descriptor.
31711945Sjeanm *
31721945Sjeanm * Returns : nothing (void)
31731945Sjeanm */
31741945Sjeanm void
meta_unrslv_replicated_mb(mdsetname_t * sp,md_drive_desc * dd,mddrivenamelist_t * dnlp,md_error_t * ep)31751945Sjeanm meta_unrslv_replicated_mb(
31761945Sjeanm mdsetname_t *sp,
31771945Sjeanm md_drive_desc *dd, /* drive list for diskset */
31781945Sjeanm mddrivenamelist_t *dnlp, /* list of drives on current system */
31791945Sjeanm md_error_t *ep
31801945Sjeanm )
31811945Sjeanm {
31821945Sjeanm md_drive_desc *d = NULL, *d_save;
31831945Sjeanm mddrivename_t *dnp; /* dnp of old drive */
31841945Sjeanm mddrivename_t *dnp_new; /* dnp of new (replicated) drive */
31851945Sjeanm mddrivename_t *dnp_save; /* saved copy needed to restore */
31861945Sjeanm ddi_devid_t devidp, new_devidp;
31871945Sjeanm int myside;
31881945Sjeanm
31891945Sjeanm if ((myside = getmyside(sp, ep)) == MD_SIDEWILD)
31901945Sjeanm return;
31911945Sjeanm
31921945Sjeanm for (d = dd; d != NULL; d = d->dd_next) {
31931945Sjeanm dnp = d->dd_dnp;
31941945Sjeanm if (dnp == NULL)
31951945Sjeanm continue;
31961945Sjeanm
31971945Sjeanm /* If don't need to update master block - skip it. */
31981945Sjeanm if (!(d->dd_flags & MD_DR_FIX_MB_DID))
31991945Sjeanm continue;
32001945Sjeanm
32011945Sjeanm /*
32021945Sjeanm * Get old and replicated (new) devids associated with this
32031945Sjeanm * drive. Also, get the new (replicated) drivename structure.
32041945Sjeanm */
32051945Sjeanm if (meta_unrslv_replicated_common(myside, d, dnlp, &devidp,
32061945Sjeanm &new_devidp, &dnp_new, ep) != 0) {
32071945Sjeanm mdclrerror(ep);
32080Sstevel@tonic-gate continue;
32090Sstevel@tonic-gate }
32100Sstevel@tonic-gate
32111945Sjeanm if (new_devidp) {
32121945Sjeanm int offset = 16; /* default mb offset is 16 */
32131945Sjeanm int dbcnt;
32141945Sjeanm
32151945Sjeanm if (d->dd_dbcnt) {
32161945Sjeanm /*
32171945Sjeanm * Update each master block on the disk
32181945Sjeanm */
32191945Sjeanm for (dbcnt = d->dd_dbcnt; dbcnt != 0; dbcnt--) {
32201945Sjeanm meta_update_mb_did(sp, dnp_new,
32211945Sjeanm new_devidp,
32221945Sjeanm devid_sizeof(new_devidp), devidp,
32231945Sjeanm 1, offset, ep);
32241945Sjeanm offset += d->dd_dbsize;
32251945Sjeanm }
32261945Sjeanm } else {
32271945Sjeanm /* update the one dummy mb */
32281945Sjeanm meta_update_mb_did(sp, dnp_new, new_devidp,
32291945Sjeanm devid_sizeof(new_devidp), devidp,
32301945Sjeanm 0, offset, ep);
32311945Sjeanm }
32321945Sjeanm if (!mdisok(ep)) {
32331945Sjeanm devid_free(devidp);
32341945Sjeanm return;
32351945Sjeanm }
32361945Sjeanm
32371945Sjeanm /* Set drive record flags to ok */
32381945Sjeanm /* Just update this one drive record. */
32391945Sjeanm d_save = d->dd_next;
32401945Sjeanm dnp_save = d->dd_dnp;
32411945Sjeanm d->dd_next = NULL;
32421945Sjeanm d->dd_dnp = dnp_new;
32431945Sjeanm /* Ignore failure since no bad effect. */
32441945Sjeanm (void) clnt_upd_dr_flags(mynode(), sp, d,
32451945Sjeanm MD_DR_OK, ep);
32461945Sjeanm d->dd_next = d_save;
32471945Sjeanm d->dd_dnp = dnp_save;
32481945Sjeanm }
32491945Sjeanm devid_free(devidp);
32501945Sjeanm }
32511945Sjeanm }
32521945Sjeanm
32531945Sjeanm /*
32541945Sjeanm * meta_update_nm_rr_did
32551945Sjeanm *
32561945Sjeanm * Change a devid stored in the diskset namespace and in the local set
32571945Sjeanm * namespace with the new devid.
32581945Sjeanm *
32591945Sjeanm * This routine is called during the import of a diskset
32601945Sjeanm * (meta_imp_update_nn) and during the take of a diskset that has
32611945Sjeanm * some unresolved replicated drives (meta_unrslv_replicated_nm).
32621945Sjeanm *
32631945Sjeanm * Returns : nothing (void)
32641945Sjeanm */
32651945Sjeanm static void
meta_update_nm_rr_did(mdsetname_t * sp,void * old_devid,int old_devid_sz,void * new_devid,int new_devid_sz,int import_flag,md_error_t * ep)32661945Sjeanm meta_update_nm_rr_did(
32671945Sjeanm mdsetname_t *sp,
32681945Sjeanm void *old_devid, /* old devid being replaced */
32691945Sjeanm int old_devid_sz,
32701945Sjeanm void *new_devid, /* devid to be stored in nm */
32711945Sjeanm int new_devid_sz,
32721945Sjeanm int import_flag, /* called during import? */
32731945Sjeanm md_error_t *ep
32741945Sjeanm )
32751945Sjeanm {
32761945Sjeanm struct mddb_config c;
32771945Sjeanm
32781945Sjeanm (void) memset(&c, 0, sizeof (c));
32791945Sjeanm c.c_setno = sp->setno;
32801945Sjeanm
32811945Sjeanm /* During import to NOT update the local namespace. */
32821945Sjeanm if (import_flag)
32831945Sjeanm c.c_flags = MDDB_C_IMPORT;
32841945Sjeanm
32851945Sjeanm c.c_locator.l_devid = (uintptr_t)Malloc(new_devid_sz);
32861945Sjeanm (void) memcpy((void *)(uintptr_t)c.c_locator.l_devid,
32871945Sjeanm new_devid, new_devid_sz);
32881945Sjeanm c.c_locator.l_devid_sz = new_devid_sz;
32891945Sjeanm c.c_locator.l_devid_flags =
32901945Sjeanm MDDB_DEVID_VALID | MDDB_DEVID_SPACE | MDDB_DEVID_SZ;
32911945Sjeanm c.c_locator.l_old_devid = (uint64_t)(uintptr_t)Malloc(old_devid_sz);
32921945Sjeanm (void) memcpy((void *)(uintptr_t)c.c_locator.l_old_devid,
32931945Sjeanm old_devid, old_devid_sz);
32941945Sjeanm c.c_locator.l_old_devid_sz = old_devid_sz;
32951945Sjeanm if (metaioctl(MD_IOCUPDATE_NM_RR_DID, &c, &c.c_mde, NULL) != 0) {
32961945Sjeanm (void) mdstealerror(ep, &c.c_mde);
32971945Sjeanm }
32981945Sjeanm Free((void *)(uintptr_t)c.c_locator.l_devid);
32991945Sjeanm Free((void *)(uintptr_t)c.c_locator.l_old_devid);
33001945Sjeanm }
33011945Sjeanm
33021945Sjeanm /*
33031945Sjeanm * meta_imp_update_nm
33041945Sjeanm *
33051945Sjeanm * Change a devid stored in the diskset namespace with the new devid.
33061945Sjeanm * This routine is called during the import of a remotely replicated diskset.
33071945Sjeanm *
33081945Sjeanm * Returns : nothing (void)
33091945Sjeanm */
33101945Sjeanm void
meta_imp_update_nm(mdsetname_t * sp,md_im_set_desc_t * misp,md_error_t * ep)33111945Sjeanm meta_imp_update_nm(mdsetname_t *sp, md_im_set_desc_t *misp, md_error_t *ep)
33121945Sjeanm {
33131945Sjeanm md_im_drive_info_t *midp;
33141945Sjeanm
33151945Sjeanm for (midp = misp->mis_drives; midp != NULL; midp = midp->mid_next) {
33161945Sjeanm /*
33171945Sjeanm * If disk isn't available we can't update, so go to next
33181945Sjeanm */
33191945Sjeanm if (midp->mid_available == MD_IM_DISK_NOT_AVAILABLE) {
33200Sstevel@tonic-gate continue;
33211945Sjeanm }
33221945Sjeanm
33231945Sjeanm meta_update_nm_rr_did(sp, midp->mid_o_devid,
33241945Sjeanm midp->mid_o_devid_sz, midp->mid_devid,
33251945Sjeanm midp->mid_devid_sz, 1, ep);
33261945Sjeanm if (!mdisok(ep))
33271945Sjeanm return;
33281945Sjeanm }
33291945Sjeanm }
33301945Sjeanm
33311945Sjeanm /*
33321945Sjeanm * meta_unrslv_replicated_nm
33331945Sjeanm *
33341945Sjeanm * Change a devid stored in the diskset namespace and in the local set
33351945Sjeanm * namespace with the new devid.
33361945Sjeanm *
33371945Sjeanm * This routine is called during the take of a diskset that has
33381945Sjeanm * some unresolved replicated drives.
33391945Sjeanm *
33401945Sjeanm * Returns : nothing (void)
33411945Sjeanm */
33421945Sjeanm void
meta_unrslv_replicated_nm(mdsetname_t * sp,md_drive_desc * dd,mddrivenamelist_t * dnlp,md_error_t * ep)33431945Sjeanm meta_unrslv_replicated_nm(
33441945Sjeanm mdsetname_t *sp,
33451945Sjeanm md_drive_desc *dd, /* drive list for diskset */
33461945Sjeanm mddrivenamelist_t *dnlp, /* list of drives on current system */
33471945Sjeanm md_error_t *ep
33481945Sjeanm )
33491945Sjeanm {
33501945Sjeanm md_drive_desc *d = NULL;
33511945Sjeanm mddrivename_t *dnp; /* drive name of old drive */
33521945Sjeanm mddrivename_t *dnp_new; /* drive name of new (repl) drive */
33531945Sjeanm ddi_devid_t devidp, new_devidp;
33541945Sjeanm ddi_devid_t old_devid;
33551945Sjeanm char *devid_old_save;
33561945Sjeanm mdsetname_t *local_sp = NULL;
33571945Sjeanm int myside;
33581945Sjeanm
33591945Sjeanm if ((myside = getmyside(sp, ep)) == MD_SIDEWILD)
33601945Sjeanm return;
33611945Sjeanm
33621945Sjeanm for (d = dd; d != NULL; d = d->dd_next) {
33631945Sjeanm dnp = d->dd_dnp;
33641945Sjeanm if (dnp == NULL)
33651945Sjeanm continue;
33661945Sjeanm
33671945Sjeanm /* If don't need to update namespace - skip it. */
33681945Sjeanm if (!(d->dd_flags & MD_DR_FIX_LB_NM_DID))
33691945Sjeanm continue;
33701945Sjeanm
33711945Sjeanm /* Get old devid from drive record */
33721945Sjeanm (void) devid_str_decode(d->dd_dnp->devid,
33731945Sjeanm &old_devid, NULL);
33740Sstevel@tonic-gate
33750Sstevel@tonic-gate /*
33761945Sjeanm * Get old and replicated (new) devids associated with this
33771945Sjeanm * drive. Also, get the new (replicated) drivename structure.
33780Sstevel@tonic-gate */
33791945Sjeanm if (meta_unrslv_replicated_common(myside, d, dnlp, &devidp,
33801945Sjeanm &new_devidp, &dnp_new, ep) != 0) {
33811945Sjeanm mdclrerror(ep);
33821945Sjeanm continue;
33830Sstevel@tonic-gate }
33841945Sjeanm
33851945Sjeanm if (new_devidp) {
33861945Sjeanm meta_update_nm_rr_did(sp, devidp,
33871945Sjeanm devid_sizeof(devidp), new_devidp,
33881945Sjeanm devid_sizeof(new_devidp), 0, ep);
33891945Sjeanm if (!mdisok(ep)) {
33901945Sjeanm devid_free(devidp);
33911945Sjeanm return;
33921945Sjeanm }
33931945Sjeanm }
33941945Sjeanm devid_free(devidp);
33951945Sjeanm
33961945Sjeanm /*
33971945Sjeanm * Using the new devid, fix up the name.
33981945Sjeanm * If meta_upd_ctdnames fails, the next take will re-resolve
33991945Sjeanm * the name from the new devid.
34001945Sjeanm */
34011945Sjeanm local_sp = metasetname(MD_LOCAL_NAME, ep);
34021945Sjeanm devid_old_save = dnp->devid;
34031945Sjeanm dnp->devid = dnp_new->devid;
34041945Sjeanm (void) meta_upd_ctdnames(&local_sp, 0, (myside + SKEW),
34051945Sjeanm dnp, NULL, ep);
34061945Sjeanm mdclrerror(ep);
34071945Sjeanm dnp->devid = devid_old_save;
34080Sstevel@tonic-gate }
34090Sstevel@tonic-gate }
34100Sstevel@tonic-gate
34110Sstevel@tonic-gate static set_t
meta_imp_setno(md_error_t * ep)34120Sstevel@tonic-gate meta_imp_setno(
34130Sstevel@tonic-gate md_error_t *ep
34140Sstevel@tonic-gate )
34150Sstevel@tonic-gate {
34160Sstevel@tonic-gate set_t max_sets, setno;
34170Sstevel@tonic-gate int bool;
34180Sstevel@tonic-gate
34190Sstevel@tonic-gate if ((max_sets = get_max_sets(ep)) == 0) {
34200Sstevel@tonic-gate return (MD_SET_BAD);
34210Sstevel@tonic-gate }
34220Sstevel@tonic-gate
34230Sstevel@tonic-gate /*
34240Sstevel@tonic-gate * This code needs to be expanded when we run in SunCluster
34250Sstevel@tonic-gate * environment SunCluster obtains setno internally
34260Sstevel@tonic-gate */
34270Sstevel@tonic-gate for (setno = 1; setno < max_sets; setno++) {
34280Sstevel@tonic-gate if (clnt_setnumbusy(mynode(), setno,
34290Sstevel@tonic-gate &bool, ep) == -1) {
34300Sstevel@tonic-gate setno = MD_SET_BAD;
34310Sstevel@tonic-gate break;
34320Sstevel@tonic-gate }
34330Sstevel@tonic-gate /*
34340Sstevel@tonic-gate * found one available
34350Sstevel@tonic-gate */
34360Sstevel@tonic-gate if (bool == FALSE)
34370Sstevel@tonic-gate break;
34380Sstevel@tonic-gate }
34390Sstevel@tonic-gate
34400Sstevel@tonic-gate if (setno == max_sets) {
34410Sstevel@tonic-gate setno = MD_SET_BAD;
34420Sstevel@tonic-gate }
34430Sstevel@tonic-gate
34440Sstevel@tonic-gate return (setno);
34450Sstevel@tonic-gate }
34460Sstevel@tonic-gate
34470Sstevel@tonic-gate int
meta_imp_set(md_im_set_desc_t * misp,char * setname,int force,bool_t dry_run,md_error_t * ep)34480Sstevel@tonic-gate meta_imp_set(
34490Sstevel@tonic-gate md_im_set_desc_t *misp,
34500Sstevel@tonic-gate char *setname,
34510Sstevel@tonic-gate int force,
34520Sstevel@tonic-gate bool_t dry_run,
34530Sstevel@tonic-gate md_error_t *ep
34540Sstevel@tonic-gate )
34550Sstevel@tonic-gate {
34560Sstevel@tonic-gate md_timeval32_t tp;
34570Sstevel@tonic-gate md_im_drive_info_t *midp;
34580Sstevel@tonic-gate uint_t rep_slice;
34590Sstevel@tonic-gate mddrivename_t *dnp;
34600Sstevel@tonic-gate struct mddb_config c;
34610Sstevel@tonic-gate mdname_t *np;
34620Sstevel@tonic-gate md_im_replica_info_t *mirp;
34631945Sjeanm set_t setno;
34641945Sjeanm mdcinfo_t *cinfo;
34651945Sjeanm mdsetname_t *sp;
34661945Sjeanm mddrivenamelist_t *dnlp = NULL;
34671945Sjeanm mddrivenamelist_t **dnlpp = &dnlp;
34680Sstevel@tonic-gate char *minor_name = NULL;
34691945Sjeanm int stale_flag = 0;
34701945Sjeanm md_set_desc *sd;
34711945Sjeanm int partial_replicated_flag = 0;
34721945Sjeanm md_error_t xep = mdnullerror;
34731945Sjeanm md_setkey_t *cl_sk;
34740Sstevel@tonic-gate
34750Sstevel@tonic-gate (void) memset(&c, 0, sizeof (c));
34760Sstevel@tonic-gate (void) strlcpy(c.c_setname, setname, sizeof (c.c_setname));
34770Sstevel@tonic-gate c.c_sideno = 0;
34780Sstevel@tonic-gate c.c_flags = MDDB_C_IMPORT;
34790Sstevel@tonic-gate
34800Sstevel@tonic-gate /*
34810Sstevel@tonic-gate * Check to see if the setname that the set is being imported into,
34820Sstevel@tonic-gate * already exists.
34830Sstevel@tonic-gate */
34840Sstevel@tonic-gate if (getsetbyname(c.c_setname, ep) != NULL) {
34850Sstevel@tonic-gate return (mddserror(ep, MDE_DS_SETNAMEBUSY, MD_SET_BAD,
34860Sstevel@tonic-gate mynode(), NULL, c.c_setname));
34870Sstevel@tonic-gate }
34880Sstevel@tonic-gate
34890Sstevel@tonic-gate /*
34900Sstevel@tonic-gate * Find the next available set number
34910Sstevel@tonic-gate */
34921945Sjeanm if ((setno = meta_imp_setno(ep)) == MD_SET_BAD) {
34930Sstevel@tonic-gate return (mddserror(ep, MDE_DS_SETNOTIMP, MD_SET_BAD,
34940Sstevel@tonic-gate mynode(), NULL, c.c_setname));
34950Sstevel@tonic-gate }
34960Sstevel@tonic-gate
34971945Sjeanm c.c_setno = setno;
34980Sstevel@tonic-gate if (meta_gettimeofday(&tp) == -1) {
34990Sstevel@tonic-gate return (mdsyserror(ep, errno, NULL));
35000Sstevel@tonic-gate }
35010Sstevel@tonic-gate c.c_timestamp = tp;
35020Sstevel@tonic-gate
35030Sstevel@tonic-gate /* Check to see if replica quorum requirement is fulfilled */
35041945Sjeanm if (meta_replica_quorum(misp) == -1) {
35051945Sjeanm if (!force) {
35061945Sjeanm return (mddserror(ep, MDE_DS_INSUFQUORUM, MD_SET_BAD,
35071945Sjeanm mynode(), NULL, c.c_setname));
35081945Sjeanm } else {
35091945Sjeanm stale_flag = MD_IMP_STALE_SET;
35101945Sjeanm /*
35111945Sjeanm * If we have a stale diskset, the kernel will
35121945Sjeanm * delete the replicas on the unavailable disks.
35131945Sjeanm * To be consistent, we'll zero out the mirp on those
35141945Sjeanm * disks here.
35151945Sjeanm */
35161945Sjeanm for (midp = misp->mis_drives; midp != NULL;
35171945Sjeanm midp = midp->mid_next) {
35181945Sjeanm if (midp->mid_available ==
35191945Sjeanm MD_IM_DISK_NOT_AVAILABLE) {
35201945Sjeanm midp->mid_replicas = NULL;
35211945Sjeanm }
35221945Sjeanm }
35231945Sjeanm }
35241945Sjeanm }
35250Sstevel@tonic-gate
35260Sstevel@tonic-gate for (midp = misp->mis_drives; midp != NULL;
35270Sstevel@tonic-gate midp = midp->mid_next) {
35281945Sjeanm
35291945Sjeanm if ((misp->mis_flags & MD_IM_SET_REPLICATED) &&
35301945Sjeanm (partial_replicated_flag == 0) &&
35311945Sjeanm (midp->mid_available == MD_IM_DISK_NOT_AVAILABLE))
35321945Sjeanm partial_replicated_flag = MD_SR_UNRSLV_REPLICATED;
35330Sstevel@tonic-gate
35340Sstevel@tonic-gate /*
35351945Sjeanm * We pass the list of the drives in the
35361945Sjeanm * set with replicas on them down to the kernel.
35370Sstevel@tonic-gate */
35380Sstevel@tonic-gate dnp = midp->mid_dnp;
35391945Sjeanm mirp = midp->mid_replicas;
35401945Sjeanm if (!mirp) {
35411945Sjeanm /*
35421945Sjeanm * No replicas on this disk, go to next disk.
35431945Sjeanm */
35440Sstevel@tonic-gate continue;
35450Sstevel@tonic-gate }
35460Sstevel@tonic-gate
35471945Sjeanm if (midp->mid_available == MD_IM_DISK_NOT_AVAILABLE) {
35481945Sjeanm /*
35491945Sjeanm * The disk isn't there. We'll need to get the
35501945Sjeanm * disk information from the midp list instead
35511945Sjeanm * of going and looking for it. This means it
35521945Sjeanm * will be information relative to the old
35531945Sjeanm * system.
35541945Sjeanm */
35551945Sjeanm minor_name = Strdup(midp->mid_minor_name);
35561945Sjeanm (void) strncpy(c.c_locator.l_driver,
35571945Sjeanm midp->mid_driver_name,
35581945Sjeanm sizeof (c.c_locator.l_driver));
35591945Sjeanm (void) strcpy(c.c_locator.l_devname, midp->mid_devname);
35601945Sjeanm c.c_locator.l_mnum = midp->mid_mnum;
35611945Sjeanm
35621945Sjeanm } else {
35631945Sjeanm if ((meta_replicaslice(dnp, &rep_slice, ep) != 0) ||
35641945Sjeanm ((np = metaslicename(dnp, rep_slice, ep))
35651945Sjeanm == NULL)) {
35661945Sjeanm mdclrerror(ep);
35671945Sjeanm continue;
35681945Sjeanm }
35691945Sjeanm (void) strcpy(c.c_locator.l_devname, np->bname);
35701945Sjeanm c.c_locator.l_dev = meta_cmpldev(np->dev);
35711945Sjeanm c.c_locator.l_mnum = meta_getminor(np->dev);
35721945Sjeanm minor_name = meta_getminor_name(np->bname, ep);
35731945Sjeanm if ((cinfo = metagetcinfo(np, ep)) == NULL) {
35741945Sjeanm mdclrerror(ep);
35751945Sjeanm continue;
35761945Sjeanm }
35771945Sjeanm
35781945Sjeanm if (cinfo->dname) {
35791945Sjeanm (void) strncpy(c.c_locator.l_driver,
35801945Sjeanm cinfo->dname,
35811945Sjeanm sizeof (c.c_locator.l_driver));
35821945Sjeanm }
35831945Sjeanm }
35841945Sjeanm
35850Sstevel@tonic-gate c.c_locator.l_devid = (uintptr_t)Malloc(midp->mid_devid_sz);
358662Sjeanm (void) memcpy((void *)(uintptr_t)c.c_locator.l_devid,
358762Sjeanm midp->mid_devid, midp->mid_devid_sz);
35880Sstevel@tonic-gate c.c_locator.l_devid_sz = midp->mid_devid_sz;
35890Sstevel@tonic-gate c.c_locator.l_devid_flags =
35900Sstevel@tonic-gate MDDB_DEVID_VALID | MDDB_DEVID_SPACE | MDDB_DEVID_SZ;
35910Sstevel@tonic-gate if (midp->mid_o_devid) {
35920Sstevel@tonic-gate c.c_locator.l_old_devid =
359362Sjeanm (uint64_t)(uintptr_t)Malloc(midp->mid_o_devid_sz);
359462Sjeanm (void) memcpy((void *)(uintptr_t)
359562Sjeanm c.c_locator.l_old_devid,
35960Sstevel@tonic-gate midp->mid_o_devid, midp->mid_o_devid_sz);
35970Sstevel@tonic-gate c.c_locator.l_old_devid_sz = midp->mid_o_devid_sz;
35980Sstevel@tonic-gate }
35991945Sjeanm if (minor_name) {
36001945Sjeanm (void) strncpy(c.c_locator.l_minor_name, minor_name,
36011945Sjeanm sizeof (c.c_locator.l_minor_name));
36020Sstevel@tonic-gate }
36030Sstevel@tonic-gate
36040Sstevel@tonic-gate do {
36051945Sjeanm c.c_locator.l_flags = 0;
36061945Sjeanm c.c_locator.l_blkno = mirp->mir_offset;
36070Sstevel@tonic-gate if (metaioctl(MD_DB_USEDEV, &c, &c.c_mde, NULL) != 0) {
360862Sjeanm Free((void *)(uintptr_t)c.c_locator.l_devid);
36090Sstevel@tonic-gate if (c.c_locator.l_old_devid)
361062Sjeanm Free((void *)(uintptr_t)
361162Sjeanm c.c_locator.l_old_devid);
36120Sstevel@tonic-gate return (mdstealerror(ep, &c.c_mde));
36130Sstevel@tonic-gate }
36141945Sjeanm mirp = mirp->mir_next;
36150Sstevel@tonic-gate } while (mirp != NULL);
36160Sstevel@tonic-gate }
36170Sstevel@tonic-gate
36180Sstevel@tonic-gate /*
36190Sstevel@tonic-gate * If the dry run option was specified, flag success
36200Sstevel@tonic-gate * and exit out
36210Sstevel@tonic-gate */
36220Sstevel@tonic-gate if (dry_run == 1) {
36230Sstevel@tonic-gate md_eprintf("%s\n", dgettext(TEXT_DOMAIN,
36240Sstevel@tonic-gate "import should be successful"));
362562Sjeanm Free((void *)(uintptr_t)c.c_locator.l_devid);
36260Sstevel@tonic-gate if (c.c_locator.l_old_devid)
362762Sjeanm Free((void *)(uintptr_t)c.c_locator.l_old_devid);
36280Sstevel@tonic-gate return (0);
36290Sstevel@tonic-gate }
36300Sstevel@tonic-gate
36310Sstevel@tonic-gate /*
36321945Sjeanm * Now the kernel should have all the information
36330Sstevel@tonic-gate * regarding the import diskset replica.
36341945Sjeanm * Tell the kernel to load them up and import the set
36350Sstevel@tonic-gate */
36361945Sjeanm (void) memset(&c, 0, sizeof (c));
36371945Sjeanm c.c_flags = stale_flag;
36381945Sjeanm c.c_setno = setno;
36391945Sjeanm if (metaioctl(MD_IOCIMP_LOAD, &c, &c.c_mde, NULL) != 0) {
364062Sjeanm Free((void *)(uintptr_t)c.c_locator.l_devid);
36410Sstevel@tonic-gate if (c.c_locator.l_old_devid)
364262Sjeanm Free((void *)(uintptr_t)c.c_locator.l_old_devid);
36430Sstevel@tonic-gate return (mdstealerror(ep, &c.c_mde));
36440Sstevel@tonic-gate }
36450Sstevel@tonic-gate
36462063Shshaw (void) meta_smf_enable(META_SMF_DISKSET, NULL);
36472063Shshaw
36481945Sjeanm /*
36491945Sjeanm * Create a set name for the set.
36501945Sjeanm */
36511945Sjeanm sp = Zalloc(sizeof (*sp));
36521945Sjeanm sp->setname = Strdup(setname);
36531945Sjeanm sp->lockfd = MD_NO_LOCK;
36541945Sjeanm sp->setno = setno;
36551945Sjeanm sd = Zalloc(sizeof (*sd));
36561945Sjeanm (void) strcpy(sd->sd_nodes[0], mynode());
36571945Sjeanm sd->sd_ctime = tp;
36581945Sjeanm sd->sd_genid = 0;
36591945Sjeanm
36601945Sjeanm if (misp->mis_flags & MD_IM_SET_REPLICATED) {
36611945Sjeanm /* Update the diskset namespace */
36621945Sjeanm meta_imp_update_nm(sp, misp, ep);
36631945Sjeanm
36641945Sjeanm /* Release the diskset - even if update_nm failed */
36651945Sjeanm (void) memset(&c, 0, sizeof (c));
36661945Sjeanm c.c_setno = setno;
36671945Sjeanm /* Don't need device id information from this ioctl */
36681945Sjeanm c.c_locator.l_devid = (uint64_t)0;
36691945Sjeanm c.c_locator.l_devid_flags = 0;
36701945Sjeanm if (metaioctl(MD_RELEASE_SET, &c, &c.c_mde, NULL) != 0) {
36711945Sjeanm if (mdisok(ep))
36721945Sjeanm (void) mdstealerror(ep, &c.c_mde);
36731945Sjeanm Free(sd);
36741945Sjeanm Free(sp);
36751945Sjeanm return (-1);
36761945Sjeanm }
36771945Sjeanm
36781945Sjeanm /* If update_nm failed, then fail the import. */
36791945Sjeanm if (!mdisok(ep)) {
36801945Sjeanm Free(sd);
36811945Sjeanm Free(sp);
36821945Sjeanm return (-1);
36831945Sjeanm }
36841945Sjeanm }
36851945Sjeanm
36861945Sjeanm /*
36871945Sjeanm * We'll need to update information in the master block due
36881945Sjeanm * to the set number changing and if the case of a replicated
36891945Sjeanm * diskset, the device id changing. May also need to create a
36901945Sjeanm * dummy master block if it's not there.
36911945Sjeanm */
36921945Sjeanm meta_imp_update_mb(sp, misp, ep);
36931945Sjeanm if (!mdisok(ep)) {
36941945Sjeanm Free(sd);
36951945Sjeanm Free(sp);
36961945Sjeanm return (-1);
36971945Sjeanm }
36980Sstevel@tonic-gate
36990Sstevel@tonic-gate /*
37001945Sjeanm * Create set record for diskset, but record is left in
37011945Sjeanm * MD_SR_ADD state until after drives are added to set.
37020Sstevel@tonic-gate */
37031945Sjeanm if (clnt_lock_set(mynode(), sp, ep)) {
37041945Sjeanm Free(sd);
37051945Sjeanm Free(sp);
37061945Sjeanm return (-1);
37071945Sjeanm }
37081945Sjeanm
37091945Sjeanm if (clnt_createset(mynode(), sp, sd->sd_nodes,
37101945Sjeanm sd->sd_ctime, sd->sd_genid, ep)) {
37111945Sjeanm cl_sk = cl_get_setkey(sp->setno, sp->setname);
37121945Sjeanm (void) clnt_unlock_set(mynode(), cl_sk, &xep);
37131945Sjeanm Free(sd);
37141945Sjeanm Free(sp);
37151945Sjeanm return (-1);
37160Sstevel@tonic-gate }
37170Sstevel@tonic-gate
37181945Sjeanm Free(sd);
37191945Sjeanm
37201945Sjeanm /*
37211945Sjeanm * Create drive records for the disks in the set.
37221945Sjeanm */
37231945Sjeanm for (midp = misp->mis_drives; midp != NULL; midp = midp->mid_next) {
37241945Sjeanm dnp = midp->mid_dnp;
37251945Sjeanm if (midp->mid_available & MD_IM_DISK_NOT_AVAILABLE) {
37261945Sjeanm /*
37271945Sjeanm * If the disk isn't available, the dnp->devid is
37281945Sjeanm * no good. It is either blank for the case where
37291945Sjeanm * there is no disk with that devname, or it
37301945Sjeanm * contains the devid for the real disk in the system
37311945Sjeanm * with that name. The problem is, if the disk is
37321945Sjeanm * unavailable, then the devid should be the devid
37331945Sjeanm * of the missing disk. So we're faking a dnp for
37341945Sjeanm * the import. This is needed for creating drive
37351945Sjeanm * records.
37361945Sjeanm */
37371945Sjeanm dnp = Zalloc(sizeof (mddrivename_t));
37381945Sjeanm dnp->side_names_key = midp->mid_dnp->side_names_key;
37391945Sjeanm dnp->type = midp->mid_dnp->type;
37401945Sjeanm dnp->cname = Strdup(midp->mid_dnp->cname);
37411945Sjeanm dnp->rname = Strdup(midp->mid_dnp->rname);
37421945Sjeanm dnp->devid = devid_str_encode(midp->mid_devid,
37431945Sjeanm NULL);
37441945Sjeanm midp->mid_dnp = dnp;
37451945Sjeanm }
37461945Sjeanm dnlpp = meta_drivenamelist_append_wrapper(dnlpp, dnp);
37471945Sjeanm }
37481945Sjeanm
37491945Sjeanm if (meta_imp_set_adddrives(sp, dnlp, misp, ep)) {
37501945Sjeanm Free(sp);
37511945Sjeanm return (mddserror(ep, MDE_DS_SETNOTIMP, MD_SET_BAD,
37521945Sjeanm mynode(), NULL, c.c_setname));
37531945Sjeanm }
37541945Sjeanm
37551945Sjeanm /* If drives were added without error, set set_record to OK */
37561945Sjeanm if (clnt_upd_sr_flags(mynode(), sp,
37571945Sjeanm (partial_replicated_flag | MD_SR_OK | MD_SR_MB_DEVID), ep)) {
37581945Sjeanm Free(sp);
37591945Sjeanm return (mddserror(ep, MDE_DS_SETNOTIMP, MD_SET_BAD,
37601945Sjeanm mynode(), NULL, c.c_setname));
37611945Sjeanm }
37621945Sjeanm
37631945Sjeanm Free(sp);
37641945Sjeanm
37651945Sjeanm cl_sk = cl_get_setkey(sp->setno, sp->setname);
37661945Sjeanm if (clnt_unlock_set(mynode(), cl_sk, ep)) {
37671945Sjeanm return (-1);
37681945Sjeanm }
37691945Sjeanm cl_set_setkey(NULL);
37700Sstevel@tonic-gate
377162Sjeanm Free((void *)(uintptr_t)c.c_locator.l_devid);
37720Sstevel@tonic-gate if (c.c_locator.l_old_devid)
377362Sjeanm Free((void *)(uintptr_t)c.c_locator.l_old_devid);
37740Sstevel@tonic-gate return (0);
37750Sstevel@tonic-gate }
3776