17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5d7cd8252Stw21770 * Common Development and Distribution License (the "License").
6d7cd8252Stw21770 * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
21bf85a12bSJohn Wren Kennedy
227c478bd9Sstevel@tonic-gate /*
23*704030f4SJames Hall * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
247c478bd9Sstevel@tonic-gate */
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate /*
277c478bd9Sstevel@tonic-gate * Just in case we're not in a build environment, make sure that
287c478bd9Sstevel@tonic-gate * TEXT_DOMAIN gets set to something.
297c478bd9Sstevel@tonic-gate */
307c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)
317c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST"
327c478bd9Sstevel@tonic-gate #endif
337c478bd9Sstevel@tonic-gate
347c478bd9Sstevel@tonic-gate /*
357c478bd9Sstevel@tonic-gate * soft partition operations
367c478bd9Sstevel@tonic-gate *
377c478bd9Sstevel@tonic-gate * Soft Partitions provide a virtual disk mechanism which is used to
387c478bd9Sstevel@tonic-gate * divide a large volume into many small pieces, each appearing as a
397c478bd9Sstevel@tonic-gate * separate device. A soft partition consists of a series of extents,
407c478bd9Sstevel@tonic-gate * each having an offset and a length. The extents are logically
417c478bd9Sstevel@tonic-gate * contiguous, so where the first extent leaves off the second extent
427c478bd9Sstevel@tonic-gate * picks up. Which extent a given "virtual offset" belongs to is
437c478bd9Sstevel@tonic-gate * dependent on the size of all the previous extents in the soft
447c478bd9Sstevel@tonic-gate * partition.
457c478bd9Sstevel@tonic-gate *
467c478bd9Sstevel@tonic-gate * Soft partitions are represented in memory by an extent node
477c478bd9Sstevel@tonic-gate * (sp_ext_node_t) which contains all of the information necessary to
487c478bd9Sstevel@tonic-gate * create a unit structure and update the on-disk format, called
497c478bd9Sstevel@tonic-gate * "watermarks". These extent nodes are typically kept in a doubly
507c478bd9Sstevel@tonic-gate * linked list and are manipulated by list manipulation routines. A
517c478bd9Sstevel@tonic-gate * list of extents may represent all of the soft partitions on a volume,
527c478bd9Sstevel@tonic-gate * a single soft partition, or perhaps just a set of extents that need
537c478bd9Sstevel@tonic-gate * to be updated. Extent lists may be sorted by extent or by name/seq#,
547c478bd9Sstevel@tonic-gate * depending on which compare function is used. Most of the routines
557c478bd9Sstevel@tonic-gate * require the list be sorted by offset to work, and that's the typical
567c478bd9Sstevel@tonic-gate * configuration.
577c478bd9Sstevel@tonic-gate *
587c478bd9Sstevel@tonic-gate * In order to do an allocation, knowledge of all soft partitions on the
597c478bd9Sstevel@tonic-gate * volume is required. Then free space is determined from the space
607c478bd9Sstevel@tonic-gate * that is not allocated, and new allocations can be made from the free
617c478bd9Sstevel@tonic-gate * space. Once the new allocations are made, a unit structure is created
627c478bd9Sstevel@tonic-gate * and the watermarks are updated. The status is then changed to "okay"
637c478bd9Sstevel@tonic-gate * on the unit structure to commit the transaction. If updating the
647c478bd9Sstevel@tonic-gate * watermarks fails, the unit structure is in an intermediate state and
657c478bd9Sstevel@tonic-gate * the driver will not allow access to the device.
667c478bd9Sstevel@tonic-gate *
677c478bd9Sstevel@tonic-gate * A typical sequence of events is:
687c478bd9Sstevel@tonic-gate * 1. Fetch the list of names for all soft partitions on a volume
697c478bd9Sstevel@tonic-gate * meta_sp_get_by_component()
707c478bd9Sstevel@tonic-gate * 2. Construct an extent list from the name list
717c478bd9Sstevel@tonic-gate * meta_sp_extlist_from_namelist()
727c478bd9Sstevel@tonic-gate * 3. Fill the gaps in the extent list with free extents
737c478bd9Sstevel@tonic-gate * meta_sp_list_freefill()
747c478bd9Sstevel@tonic-gate * 4. Allocate from the free extents
757c478bd9Sstevel@tonic-gate * meta_sp_alloc_by_len()
767c478bd9Sstevel@tonic-gate * meta_sp_alloc_by_list()
777c478bd9Sstevel@tonic-gate * 5. Create the unit structure from the extent list
787c478bd9Sstevel@tonic-gate * meta_sp_createunit()
797c478bd9Sstevel@tonic-gate * meta_sp_updateunit()
807c478bd9Sstevel@tonic-gate * 6. Write out the watermarks
817c478bd9Sstevel@tonic-gate * meta_sp_update_wm()
827c478bd9Sstevel@tonic-gate * 7. Set the status to "Okay"
837c478bd9Sstevel@tonic-gate * meta_sp_setstatus()
847c478bd9Sstevel@tonic-gate *
857c478bd9Sstevel@tonic-gate */
867c478bd9Sstevel@tonic-gate
877c478bd9Sstevel@tonic-gate #include <stdio.h>
887c478bd9Sstevel@tonic-gate #include <meta.h>
897c478bd9Sstevel@tonic-gate #include "meta_repartition.h"
907c478bd9Sstevel@tonic-gate #include <sys/lvm/md_sp.h>
917c478bd9Sstevel@tonic-gate #include <sys/lvm/md_crc.h>
927c478bd9Sstevel@tonic-gate #include <strings.h>
937c478bd9Sstevel@tonic-gate #include <sys/lvm/md_mirror.h>
947c478bd9Sstevel@tonic-gate #include <sys/bitmap.h>
957c478bd9Sstevel@tonic-gate
967c478bd9Sstevel@tonic-gate extern int md_in_daemon;
977c478bd9Sstevel@tonic-gate
987c478bd9Sstevel@tonic-gate typedef struct sp_ext_node {
997c478bd9Sstevel@tonic-gate struct sp_ext_node *ext_next; /* next element */
1007c478bd9Sstevel@tonic-gate struct sp_ext_node *ext_prev; /* previous element */
1017c478bd9Sstevel@tonic-gate sp_ext_type_t ext_type; /* type of extent */
1027c478bd9Sstevel@tonic-gate sp_ext_offset_t ext_offset; /* starting offset */
1037c478bd9Sstevel@tonic-gate sp_ext_length_t ext_length; /* length of this node */
1047c478bd9Sstevel@tonic-gate uint_t ext_flags; /* extent flags */
1057c478bd9Sstevel@tonic-gate uint32_t ext_seq; /* watermark seq no */
1067c478bd9Sstevel@tonic-gate mdname_t *ext_namep; /* name pointer */
1077c478bd9Sstevel@tonic-gate mdsetname_t *ext_setp; /* set pointer */
1087c478bd9Sstevel@tonic-gate } sp_ext_node_t;
1097c478bd9Sstevel@tonic-gate
1107c478bd9Sstevel@tonic-gate /* extent flags */
1117c478bd9Sstevel@tonic-gate #define EXTFLG_UPDATE (1)
1127c478bd9Sstevel@tonic-gate
1137c478bd9Sstevel@tonic-gate /* Extent node compare function for list sorting */
1147c478bd9Sstevel@tonic-gate typedef int (*ext_cmpfunc_t)(sp_ext_node_t *, sp_ext_node_t *);
1157c478bd9Sstevel@tonic-gate
1167c478bd9Sstevel@tonic-gate
1177c478bd9Sstevel@tonic-gate /* Function Prototypes */
1187c478bd9Sstevel@tonic-gate
1197c478bd9Sstevel@tonic-gate /* Debugging Functions */
1207c478bd9Sstevel@tonic-gate static void meta_sp_debug(char *format, ...);
1217c478bd9Sstevel@tonic-gate static void meta_sp_printunit(mp_unit_t *mp);
1227c478bd9Sstevel@tonic-gate
1237c478bd9Sstevel@tonic-gate /* Misc Support Functions */
1247c478bd9Sstevel@tonic-gate int meta_sp_parsesize(char *s, sp_ext_length_t *szp);
1257c478bd9Sstevel@tonic-gate static int meta_sp_parsesizestring(char *s, sp_ext_length_t *szp);
1267c478bd9Sstevel@tonic-gate static int meta_sp_setgeom(mdname_t *np, mdname_t *compnp, mp_unit_t *mp,
1277c478bd9Sstevel@tonic-gate md_error_t *ep);
1287c478bd9Sstevel@tonic-gate static int meta_sp_get_by_component(mdsetname_t *sp, mdname_t *compnp,
1297c478bd9Sstevel@tonic-gate mdnamelist_t **nlpp, int force, md_error_t *ep);
1307c478bd9Sstevel@tonic-gate static sp_ext_length_t meta_sp_get_default_alignment(mdsetname_t *sp,
1317c478bd9Sstevel@tonic-gate mdname_t *compnp, md_error_t *ep);
1327c478bd9Sstevel@tonic-gate
1337c478bd9Sstevel@tonic-gate /* Extent List Manipulation Functions */
1347c478bd9Sstevel@tonic-gate static int meta_sp_cmp_by_nameseq(sp_ext_node_t *e1, sp_ext_node_t *e2);
1357c478bd9Sstevel@tonic-gate static int meta_sp_cmp_by_offset(sp_ext_node_t *e1, sp_ext_node_t *e2);
1367c478bd9Sstevel@tonic-gate static void meta_sp_list_insert(mdsetname_t *sp, mdname_t *np,
1377c478bd9Sstevel@tonic-gate sp_ext_node_t **head, sp_ext_offset_t offset, sp_ext_length_t length,
1387c478bd9Sstevel@tonic-gate sp_ext_type_t type, uint_t seq, uint_t flags, ext_cmpfunc_t compare);
1397c478bd9Sstevel@tonic-gate static void meta_sp_list_free(sp_ext_node_t **head);
1407c478bd9Sstevel@tonic-gate static void meta_sp_list_remove(sp_ext_node_t **head, sp_ext_node_t *ext);
1417c478bd9Sstevel@tonic-gate static sp_ext_length_t meta_sp_list_size(sp_ext_node_t *head,
1427c478bd9Sstevel@tonic-gate sp_ext_type_t exttype, int exclude_wm);
1437c478bd9Sstevel@tonic-gate static sp_ext_node_t *meta_sp_list_find(sp_ext_node_t *head,
1447c478bd9Sstevel@tonic-gate sp_ext_offset_t offset);
1457c478bd9Sstevel@tonic-gate static void meta_sp_list_freefill(sp_ext_node_t **extlist,
1467c478bd9Sstevel@tonic-gate sp_ext_length_t size);
1477c478bd9Sstevel@tonic-gate static void meta_sp_list_dump(sp_ext_node_t *head);
1487c478bd9Sstevel@tonic-gate static int meta_sp_list_overlaps(sp_ext_node_t *head);
1497c478bd9Sstevel@tonic-gate
1507c478bd9Sstevel@tonic-gate /* Extent List Query Functions */
1517c478bd9Sstevel@tonic-gate static boolean_t meta_sp_enough_space(int desired_number_of_sps,
1527c478bd9Sstevel@tonic-gate blkcnt_t desired_sp_size, sp_ext_node_t **extent_listpp,
1537c478bd9Sstevel@tonic-gate sp_ext_length_t alignment);
1547c478bd9Sstevel@tonic-gate static boolean_t meta_sp_get_extent_list(mdsetname_t *mdsetnamep,
1557c478bd9Sstevel@tonic-gate mdname_t *device_mdnamep, sp_ext_node_t **extent_listpp,
1567c478bd9Sstevel@tonic-gate md_error_t *ep);
1577c478bd9Sstevel@tonic-gate static boolean_t meta_sp_get_extent_list_for_drive(mdsetname_t *mdsetnamep,
1587c478bd9Sstevel@tonic-gate mddrivename_t *mddrivenamep, sp_ext_node_t **extent_listpp);
1597c478bd9Sstevel@tonic-gate
1607c478bd9Sstevel@tonic-gate
1617c478bd9Sstevel@tonic-gate /* Extent Allocation Functions */
1627c478bd9Sstevel@tonic-gate static void meta_sp_alloc_by_ext(mdsetname_t *sp, mdname_t *np,
1637c478bd9Sstevel@tonic-gate sp_ext_node_t **extlist, sp_ext_node_t *free_ext,
1647c478bd9Sstevel@tonic-gate sp_ext_offset_t alloc_offset, sp_ext_length_t alloc_length, uint_t seq);
1657c478bd9Sstevel@tonic-gate static int meta_sp_alloc_by_len(mdsetname_t *sp, mdname_t *np,
1667c478bd9Sstevel@tonic-gate sp_ext_node_t **extlist, sp_ext_length_t *lp,
1677c478bd9Sstevel@tonic-gate sp_ext_offset_t last_off, sp_ext_length_t alignment);
1687c478bd9Sstevel@tonic-gate static int meta_sp_alloc_by_list(mdsetname_t *sp, mdname_t *np,
1697c478bd9Sstevel@tonic-gate sp_ext_node_t **extlist, sp_ext_node_t *oblist);
1707c478bd9Sstevel@tonic-gate
1717c478bd9Sstevel@tonic-gate /* Extent List Population Functions */
1727c478bd9Sstevel@tonic-gate static int meta_sp_extlist_from_namelist(mdsetname_t *sp, mdnamelist_t *spnlp,
1737c478bd9Sstevel@tonic-gate sp_ext_node_t **extlist, md_error_t *ep);
1747c478bd9Sstevel@tonic-gate static int meta_sp_extlist_from_wm(mdsetname_t *sp, mdname_t *compnp,
1757c478bd9Sstevel@tonic-gate sp_ext_node_t **extlist, ext_cmpfunc_t compare, md_error_t *ep);
1767c478bd9Sstevel@tonic-gate
1777c478bd9Sstevel@tonic-gate /* Print (metastat) Functions */
1787c478bd9Sstevel@tonic-gate static int meta_sp_short_print(md_sp_t *msp, char *fname, FILE *fp,
1797c478bd9Sstevel@tonic-gate mdprtopts_t options, md_error_t *ep);
1807c478bd9Sstevel@tonic-gate static char *meta_sp_status_to_name(xsp_status_t xsp_status, uint_t tstate);
1817c478bd9Sstevel@tonic-gate static int meta_sp_report(mdsetname_t *sp, md_sp_t *msp, mdnamelist_t **nlpp,
1827c478bd9Sstevel@tonic-gate char *fname, FILE *fp, mdprtopts_t options, md_error_t *ep);
1837c478bd9Sstevel@tonic-gate
1847c478bd9Sstevel@tonic-gate /* Watermark Manipulation Functions */
1857c478bd9Sstevel@tonic-gate static int meta_sp_update_wm(mdsetname_t *sp, md_sp_t *msp,
1867c478bd9Sstevel@tonic-gate sp_ext_node_t *extlist, md_error_t *ep);
1877c478bd9Sstevel@tonic-gate static int meta_sp_clear_wm(mdsetname_t *sp, md_sp_t *msp, md_error_t *ep);
1887c478bd9Sstevel@tonic-gate static int meta_sp_read_wm(mdsetname_t *sp, mdname_t *compnp,
1897c478bd9Sstevel@tonic-gate mp_watermark_t *wm, sp_ext_offset_t offset, md_error_t *ep);
1907c478bd9Sstevel@tonic-gate static diskaddr_t meta_sp_get_start(mdsetname_t *sp, mdname_t *compnp,
1917c478bd9Sstevel@tonic-gate md_error_t *ep);
1927c478bd9Sstevel@tonic-gate
1937c478bd9Sstevel@tonic-gate /* Unit Structure Manipulation Functions */
1947c478bd9Sstevel@tonic-gate static void meta_sp_fillextarray(mp_unit_t *mp, sp_ext_node_t *extlist);
1957c478bd9Sstevel@tonic-gate static mp_unit_t *meta_sp_createunit(mdname_t *np, mdname_t *compnp,
1967c478bd9Sstevel@tonic-gate sp_ext_node_t *extlist, int numexts, sp_ext_length_t len,
1977c478bd9Sstevel@tonic-gate sp_status_t status, md_error_t *ep);
1987c478bd9Sstevel@tonic-gate static mp_unit_t *meta_sp_updateunit(mdname_t *np, mp_unit_t *old_un,
1997c478bd9Sstevel@tonic-gate sp_ext_node_t *extlist, sp_ext_length_t grow_len, int numexts,
2007c478bd9Sstevel@tonic-gate md_error_t *ep);
2017c478bd9Sstevel@tonic-gate static int meta_create_sp(mdsetname_t *sp, md_sp_t *msp, sp_ext_node_t *oblist,
2027c478bd9Sstevel@tonic-gate mdcmdopts_t options, sp_ext_length_t alignment, md_error_t *ep);
2037c478bd9Sstevel@tonic-gate static int meta_check_sp(mdsetname_t *sp, md_sp_t *msp, mdcmdopts_t options,
2047c478bd9Sstevel@tonic-gate int *repart_options, md_error_t *ep);
2057c478bd9Sstevel@tonic-gate
2067c478bd9Sstevel@tonic-gate /* Reset (metaclear) Functions */
2077c478bd9Sstevel@tonic-gate static int meta_sp_reset_common(mdsetname_t *sp, mdname_t *np, md_sp_t *msp,
2087c478bd9Sstevel@tonic-gate md_sp_reset_t reset_params, mdcmdopts_t options, md_error_t *ep);
2097c478bd9Sstevel@tonic-gate
2107c478bd9Sstevel@tonic-gate /* Recovery (metarecover) Functions */
2117c478bd9Sstevel@tonic-gate static void meta_sp_display_exthdr(void);
2127c478bd9Sstevel@tonic-gate static void meta_sp_display_ext(sp_ext_node_t *ext);
2137c478bd9Sstevel@tonic-gate static int meta_sp_checkseq(sp_ext_node_t *extlist);
2147c478bd9Sstevel@tonic-gate static int meta_sp_resolve_name_conflict(mdsetname_t *, mdname_t *,
2157c478bd9Sstevel@tonic-gate mdname_t **, md_error_t *);
2167c478bd9Sstevel@tonic-gate static int meta_sp_validate_wm(mdsetname_t *sp, mdname_t *np,
2177c478bd9Sstevel@tonic-gate mdcmdopts_t options, md_error_t *ep);
2187c478bd9Sstevel@tonic-gate static int meta_sp_validate_unit(mdsetname_t *sp, mdname_t *compnp,
2197c478bd9Sstevel@tonic-gate mdcmdopts_t options, md_error_t *ep);
2207c478bd9Sstevel@tonic-gate static int meta_sp_validate_wm_and_unit(mdsetname_t *sp, mdname_t *np,
2217c478bd9Sstevel@tonic-gate mdcmdopts_t options, md_error_t *ep);
2227c478bd9Sstevel@tonic-gate static int meta_sp_validate_exts(mdname_t *np, sp_ext_node_t *wmext,
2237c478bd9Sstevel@tonic-gate sp_ext_node_t *unitext, md_error_t *ep);
2247c478bd9Sstevel@tonic-gate static int meta_sp_recover_from_wm(mdsetname_t *sp, mdname_t *compnp,
2257c478bd9Sstevel@tonic-gate mdcmdopts_t options, md_error_t *ep);
2267c478bd9Sstevel@tonic-gate static int meta_sp_recover_from_unit(mdsetname_t *sp, mdname_t *np,
2277c478bd9Sstevel@tonic-gate mdcmdopts_t options, md_error_t *ep);
2287c478bd9Sstevel@tonic-gate
2297c478bd9Sstevel@tonic-gate /*
2307c478bd9Sstevel@tonic-gate * Private Constants
2317c478bd9Sstevel@tonic-gate */
2327c478bd9Sstevel@tonic-gate
2337c478bd9Sstevel@tonic-gate static const int FORCE_RELOAD_CACHE = 1;
2347c478bd9Sstevel@tonic-gate static const uint_t NO_FLAGS = 0;
2357c478bd9Sstevel@tonic-gate static const sp_ext_offset_t NO_OFFSET = 0ULL;
2367c478bd9Sstevel@tonic-gate static const uint_t NO_SEQUENCE_NUMBER = 0;
2377c478bd9Sstevel@tonic-gate static const int ONE_SOFT_PARTITION = 1;
2387c478bd9Sstevel@tonic-gate
2392b637af7SJohn Harres static unsigned long *sp_parent_printed[MD_MAXSETS];
2407c478bd9Sstevel@tonic-gate
2417c478bd9Sstevel@tonic-gate #define TEST_SOFT_PARTITION_NAMEP NULL
2427c478bd9Sstevel@tonic-gate #define TEST_SETNAMEP NULL
2437c478bd9Sstevel@tonic-gate
2447c478bd9Sstevel@tonic-gate #define EXCLUDE_WM (1)
2457c478bd9Sstevel@tonic-gate #define INCLUDE_WM (0)
2467c478bd9Sstevel@tonic-gate
2477c478bd9Sstevel@tonic-gate #define SP_UNALIGNED (0LL)
2487c478bd9Sstevel@tonic-gate
2497c478bd9Sstevel@tonic-gate /*
2507c478bd9Sstevel@tonic-gate * **************************************************************************
2517c478bd9Sstevel@tonic-gate * Debugging Functions *
2527c478bd9Sstevel@tonic-gate * **************************************************************************
2537c478bd9Sstevel@tonic-gate */
2547c478bd9Sstevel@tonic-gate
2557c478bd9Sstevel@tonic-gate /*PRINTFLIKE1*/
2567c478bd9Sstevel@tonic-gate static void
meta_sp_debug(char * format,...)2577c478bd9Sstevel@tonic-gate meta_sp_debug(char *format, ...)
2587c478bd9Sstevel@tonic-gate {
2597c478bd9Sstevel@tonic-gate static int debug;
2607c478bd9Sstevel@tonic-gate static int debug_set = 0;
2617c478bd9Sstevel@tonic-gate va_list ap;
2627c478bd9Sstevel@tonic-gate
2637c478bd9Sstevel@tonic-gate if (!debug_set) {
2647c478bd9Sstevel@tonic-gate debug = getenv(META_SP_DEBUG) ? 1 : 0;
2657c478bd9Sstevel@tonic-gate debug_set = 1;
2667c478bd9Sstevel@tonic-gate }
2677c478bd9Sstevel@tonic-gate
2687c478bd9Sstevel@tonic-gate if (debug) {
2697c478bd9Sstevel@tonic-gate va_start(ap, format);
2707c478bd9Sstevel@tonic-gate (void) vfprintf(stderr, format, ap);
2717c478bd9Sstevel@tonic-gate va_end(ap);
2727c478bd9Sstevel@tonic-gate }
2737c478bd9Sstevel@tonic-gate }
2747c478bd9Sstevel@tonic-gate
2757c478bd9Sstevel@tonic-gate static void
meta_sp_printunit(mp_unit_t * mp)2767c478bd9Sstevel@tonic-gate meta_sp_printunit(mp_unit_t *mp)
2777c478bd9Sstevel@tonic-gate {
2787c478bd9Sstevel@tonic-gate int i;
2797c478bd9Sstevel@tonic-gate
2807c478bd9Sstevel@tonic-gate if (mp == NULL)
2817c478bd9Sstevel@tonic-gate return;
2827c478bd9Sstevel@tonic-gate
2837c478bd9Sstevel@tonic-gate /* print the common fields we know about */
2847c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\tmp->c.un_type: %d\n", mp->c.un_type);
2857c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\tmp->c.un_size: %u\n", mp->c.un_size);
2867c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\tmp->c.un_self_id: %lu\n", MD_SID(mp));
2877c478bd9Sstevel@tonic-gate
2887c478bd9Sstevel@tonic-gate /* sp-specific fields */
2897c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\tmp->un_status: %u\n", mp->un_status);
2907c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\tmp->un_numexts: %u\n", mp->un_numexts);
2917c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\tmp->un_length: %llu\n", mp->un_length);
2927c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\tmp->un_dev(32): 0x%llx\n", mp->un_dev);
2937c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\tmp->un_dev(64): 0x%llx\n", mp->un_dev);
2947c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\tmp->un_key: %d\n", mp->un_key);
2957c478bd9Sstevel@tonic-gate
2967c478bd9Sstevel@tonic-gate /* print extent information */
2977c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\tExt#\tvoff\t\tpoff\t\tLen\n");
2987c478bd9Sstevel@tonic-gate for (i = 0; i < mp->un_numexts; i++) {
2997c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\t%d\t%llu\t\t%llu\t\t%llu\n", i,
3007c478bd9Sstevel@tonic-gate mp->un_ext[i].un_voff, mp->un_ext[i].un_poff,
3017c478bd9Sstevel@tonic-gate mp->un_ext[i].un_len);
3027c478bd9Sstevel@tonic-gate }
3037c478bd9Sstevel@tonic-gate }
3047c478bd9Sstevel@tonic-gate
3057c478bd9Sstevel@tonic-gate /*
3067c478bd9Sstevel@tonic-gate * FUNCTION: meta_sp_parsesize()
3077c478bd9Sstevel@tonic-gate * INPUT: s - the string to parse
3087c478bd9Sstevel@tonic-gate * OUTPUT: *szp - disk block count (0 for "all")
3097c478bd9Sstevel@tonic-gate * RETURNS: -1 for error, 0 for success
3107c478bd9Sstevel@tonic-gate * PURPOSE: parses the command line parameter that specifies the
3117c478bd9Sstevel@tonic-gate * requested size of a soft partition. The input string
3127c478bd9Sstevel@tonic-gate * is either the literal "all" or a numeric value
3137c478bd9Sstevel@tonic-gate * followed by a single character, b for disk blocks, k
3147c478bd9Sstevel@tonic-gate * for kilobytes, m for megabytes, g for gigabytes, or t
3157c478bd9Sstevel@tonic-gate * for terabytes. p for petabytes and e for exabytes
3167c478bd9Sstevel@tonic-gate * have been added as undocumented features for future
3177c478bd9Sstevel@tonic-gate * expansion. For example, 100m is 100 megabytes, while
3187c478bd9Sstevel@tonic-gate * 50g is 50 gigabytes. All values are rounded up to the
3197c478bd9Sstevel@tonic-gate * nearest block size.
3207c478bd9Sstevel@tonic-gate */
3217c478bd9Sstevel@tonic-gate int
meta_sp_parsesize(char * s,sp_ext_length_t * szp)3227c478bd9Sstevel@tonic-gate meta_sp_parsesize(char *s, sp_ext_length_t *szp)
3237c478bd9Sstevel@tonic-gate {
3247c478bd9Sstevel@tonic-gate if (s == NULL || szp == NULL) {
3257c478bd9Sstevel@tonic-gate return (-1);
3267c478bd9Sstevel@tonic-gate }
3277c478bd9Sstevel@tonic-gate
3287c478bd9Sstevel@tonic-gate /* Check for literal "all" */
3297c478bd9Sstevel@tonic-gate if (strcasecmp(s, "all") == 0) {
3307c478bd9Sstevel@tonic-gate *szp = 0;
3317c478bd9Sstevel@tonic-gate return (0);
3327c478bd9Sstevel@tonic-gate }
3337c478bd9Sstevel@tonic-gate
3347c478bd9Sstevel@tonic-gate return (meta_sp_parsesizestring(s, szp));
3357c478bd9Sstevel@tonic-gate }
3367c478bd9Sstevel@tonic-gate
3377c478bd9Sstevel@tonic-gate /*
3387c478bd9Sstevel@tonic-gate * FUNCTION: meta_sp_parsesizestring()
3397c478bd9Sstevel@tonic-gate * INPUT: s - the string to parse
3407c478bd9Sstevel@tonic-gate * OUTPUT: *szp - disk block count
3417c478bd9Sstevel@tonic-gate * RETURNS: -1 for error, 0 for success
3427c478bd9Sstevel@tonic-gate * PURPOSE: parses a string that specifies size. The input string is a
3437c478bd9Sstevel@tonic-gate * numeric value followed by a single character, b for disk blocks,
3447c478bd9Sstevel@tonic-gate * k for kilobytes, m for megabytes, g for gigabytes, or t for
3457c478bd9Sstevel@tonic-gate * terabytes. p for petabytes and e for exabytes have been added
3467c478bd9Sstevel@tonic-gate * as undocumented features for future expansion. For example,
3477c478bd9Sstevel@tonic-gate * 100m is 100 megabytes, while 50g is 50 gigabytes. All values
3487c478bd9Sstevel@tonic-gate * are rounded up to the nearest block size.
3497c478bd9Sstevel@tonic-gate */
3507c478bd9Sstevel@tonic-gate static int
meta_sp_parsesizestring(char * s,sp_ext_length_t * szp)3517c478bd9Sstevel@tonic-gate meta_sp_parsesizestring(char *s, sp_ext_length_t *szp)
3527c478bd9Sstevel@tonic-gate {
3537c478bd9Sstevel@tonic-gate sp_ext_length_t len = 0;
3547c478bd9Sstevel@tonic-gate char len_type[2];
3557c478bd9Sstevel@tonic-gate
3567c478bd9Sstevel@tonic-gate if (s == NULL || szp == NULL) {
3577c478bd9Sstevel@tonic-gate return (-1);
3587c478bd9Sstevel@tonic-gate }
3597c478bd9Sstevel@tonic-gate
3607c478bd9Sstevel@tonic-gate /*
3617c478bd9Sstevel@tonic-gate * make sure block offset does not overflow 2^64 bytes.
3627c478bd9Sstevel@tonic-gate */
3637c478bd9Sstevel@tonic-gate if ((sscanf(s, "%llu%1[BbKkMmGgTt]", &len, len_type) != 2) ||
3647c478bd9Sstevel@tonic-gate (len == 0LL) ||
3657c478bd9Sstevel@tonic-gate (len > (1LL << (64 - DEV_BSHIFT))))
3667c478bd9Sstevel@tonic-gate return (-1);
3677c478bd9Sstevel@tonic-gate
3687c478bd9Sstevel@tonic-gate switch (len_type[0]) {
3697c478bd9Sstevel@tonic-gate case 'B':
3707c478bd9Sstevel@tonic-gate case 'b':
3717c478bd9Sstevel@tonic-gate len = lbtodb(roundup(len * DEV_BSIZE, DEV_BSIZE));
3727c478bd9Sstevel@tonic-gate break;
3737c478bd9Sstevel@tonic-gate case 'K':
3747c478bd9Sstevel@tonic-gate case 'k':
3757c478bd9Sstevel@tonic-gate len = lbtodb(roundup(len * 1024ULL, DEV_BSIZE));
3767c478bd9Sstevel@tonic-gate break;
3777c478bd9Sstevel@tonic-gate case 'M':
3787c478bd9Sstevel@tonic-gate case 'm':
3797c478bd9Sstevel@tonic-gate len = lbtodb(roundup(len * 1024ULL*1024ULL, DEV_BSIZE));
3807c478bd9Sstevel@tonic-gate break;
3817c478bd9Sstevel@tonic-gate case 'g':
3827c478bd9Sstevel@tonic-gate case 'G':
3837c478bd9Sstevel@tonic-gate len = lbtodb(roundup(len * 1024ULL*1024ULL*1024ULL, DEV_BSIZE));
3847c478bd9Sstevel@tonic-gate break;
3857c478bd9Sstevel@tonic-gate case 't':
3867c478bd9Sstevel@tonic-gate case 'T':
3877c478bd9Sstevel@tonic-gate len = lbtodb(roundup(len * 1024ULL*1024ULL*1024ULL*1024ULL,
3887c478bd9Sstevel@tonic-gate DEV_BSIZE));
3897c478bd9Sstevel@tonic-gate break;
3907c478bd9Sstevel@tonic-gate case 'p':
3917c478bd9Sstevel@tonic-gate case 'P':
3927c478bd9Sstevel@tonic-gate len = lbtodb(roundup(
3937c478bd9Sstevel@tonic-gate len * 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL,
3947c478bd9Sstevel@tonic-gate DEV_BSIZE));
3957c478bd9Sstevel@tonic-gate break;
3967c478bd9Sstevel@tonic-gate case 'e':
3977c478bd9Sstevel@tonic-gate case 'E':
3987c478bd9Sstevel@tonic-gate len = lbtodb(roundup(
3997c478bd9Sstevel@tonic-gate len * 1024ULL*1024ULL*1024ULL*1024ULL*1024ULL*1024ULL,
4007c478bd9Sstevel@tonic-gate DEV_BSIZE));
4017c478bd9Sstevel@tonic-gate break;
4027c478bd9Sstevel@tonic-gate default:
4037c478bd9Sstevel@tonic-gate /* error */
4047c478bd9Sstevel@tonic-gate return (-1);
4057c478bd9Sstevel@tonic-gate }
4067c478bd9Sstevel@tonic-gate
4077c478bd9Sstevel@tonic-gate *szp = len;
4087c478bd9Sstevel@tonic-gate return (0);
4097c478bd9Sstevel@tonic-gate }
4107c478bd9Sstevel@tonic-gate
4117c478bd9Sstevel@tonic-gate /*
4127c478bd9Sstevel@tonic-gate * FUNCTION: meta_sp_setgeom()
4137c478bd9Sstevel@tonic-gate * INPUT: np - the underlying device to setup geometry for
4147c478bd9Sstevel@tonic-gate * compnp - the underlying device to setup geometry for
4157c478bd9Sstevel@tonic-gate * mp - the unit structure to set the geometry for
4167c478bd9Sstevel@tonic-gate * OUTPUT: ep - return error pointer
4177c478bd9Sstevel@tonic-gate * RETURNS: int - -1 if error, 0 otherwise
4187c478bd9Sstevel@tonic-gate * PURPOSE: establishes geometry information for a device
4197c478bd9Sstevel@tonic-gate */
4207c478bd9Sstevel@tonic-gate static int
meta_sp_setgeom(mdname_t * np,mdname_t * compnp,mp_unit_t * mp,md_error_t * ep)4217c478bd9Sstevel@tonic-gate meta_sp_setgeom(
4227c478bd9Sstevel@tonic-gate mdname_t *np,
4237c478bd9Sstevel@tonic-gate mdname_t *compnp,
4247c478bd9Sstevel@tonic-gate mp_unit_t *mp,
4257c478bd9Sstevel@tonic-gate md_error_t *ep
4267c478bd9Sstevel@tonic-gate )
4277c478bd9Sstevel@tonic-gate {
4287c478bd9Sstevel@tonic-gate mdgeom_t *geomp;
4297c478bd9Sstevel@tonic-gate uint_t round_cyl = 0;
4307c478bd9Sstevel@tonic-gate
4317c478bd9Sstevel@tonic-gate if ((geomp = metagetgeom(compnp, ep)) == NULL)
4327c478bd9Sstevel@tonic-gate return (-1);
4337c478bd9Sstevel@tonic-gate if (meta_setup_geom((md_unit_t *)mp, np, geomp, geomp->write_reinstruct,
4347c478bd9Sstevel@tonic-gate geomp->read_reinstruct, round_cyl, ep) != 0)
4357c478bd9Sstevel@tonic-gate return (-1);
4367c478bd9Sstevel@tonic-gate
4377c478bd9Sstevel@tonic-gate return (0);
4387c478bd9Sstevel@tonic-gate }
4397c478bd9Sstevel@tonic-gate
4407c478bd9Sstevel@tonic-gate /*
4417c478bd9Sstevel@tonic-gate * FUNCTION: meta_sp_setstatus()
4427c478bd9Sstevel@tonic-gate * INPUT: sp - the set name for the devices to set the status on
4437c478bd9Sstevel@tonic-gate * minors - an array of minor numbers of devices to set status on
4447c478bd9Sstevel@tonic-gate * num_units - number of entries in the array
4457c478bd9Sstevel@tonic-gate * status - status value to set all units to
4467c478bd9Sstevel@tonic-gate * OUTPUT: ep - return error pointer
4477c478bd9Sstevel@tonic-gate * RETURNS: int - -1 if error, 0 success
4487c478bd9Sstevel@tonic-gate * PURPOSE: sets the status of one or more soft partitions to the
4497c478bd9Sstevel@tonic-gate * requested value
4507c478bd9Sstevel@tonic-gate */
4517c478bd9Sstevel@tonic-gate int
meta_sp_setstatus(mdsetname_t * sp,minor_t * minors,int num_units,sp_status_t status,md_error_t * ep)4527c478bd9Sstevel@tonic-gate meta_sp_setstatus(
4537c478bd9Sstevel@tonic-gate mdsetname_t *sp,
4547c478bd9Sstevel@tonic-gate minor_t *minors,
4557c478bd9Sstevel@tonic-gate int num_units,
4567c478bd9Sstevel@tonic-gate sp_status_t status,
4577c478bd9Sstevel@tonic-gate md_error_t *ep
4587c478bd9Sstevel@tonic-gate )
4597c478bd9Sstevel@tonic-gate {
4607c478bd9Sstevel@tonic-gate md_sp_statusset_t status_params;
4617c478bd9Sstevel@tonic-gate
4627c478bd9Sstevel@tonic-gate assert(minors != NULL);
4637c478bd9Sstevel@tonic-gate
4647c478bd9Sstevel@tonic-gate /* update status of all soft partitions to the status passed in */
4657c478bd9Sstevel@tonic-gate (void) memset(&status_params, 0, sizeof (status_params));
4667c478bd9Sstevel@tonic-gate status_params.num_units = num_units;
4677c478bd9Sstevel@tonic-gate status_params.new_status = status;
4687c478bd9Sstevel@tonic-gate status_params.size = num_units * sizeof (minor_t);
4697c478bd9Sstevel@tonic-gate status_params.minors = (uintptr_t)minors;
4707c478bd9Sstevel@tonic-gate MD_SETDRIVERNAME(&status_params, MD_SP, sp->setno);
4717c478bd9Sstevel@tonic-gate if (metaioctl(MD_IOC_SPSTATUS, &status_params, &status_params.mde,
4727c478bd9Sstevel@tonic-gate NULL) != 0) {
4737c478bd9Sstevel@tonic-gate (void) mdstealerror(ep, &status_params.mde);
4747c478bd9Sstevel@tonic-gate return (-1);
4757c478bd9Sstevel@tonic-gate }
4767c478bd9Sstevel@tonic-gate return (0);
4777c478bd9Sstevel@tonic-gate }
4787c478bd9Sstevel@tonic-gate
4797c478bd9Sstevel@tonic-gate /*
4807c478bd9Sstevel@tonic-gate * FUNCTION: meta_get_sp_names()
4817c478bd9Sstevel@tonic-gate * INPUT: sp - the set name to get soft partitions from
4827c478bd9Sstevel@tonic-gate * options - options from the command line
4837c478bd9Sstevel@tonic-gate * OUTPUT: nlpp - list of all soft partition names
4847c478bd9Sstevel@tonic-gate * ep - return error pointer
4857c478bd9Sstevel@tonic-gate * RETURNS: int - -1 if error, 0 success
4867c478bd9Sstevel@tonic-gate * PURPOSE: returns a list of all soft partitions in the metadb
4877c478bd9Sstevel@tonic-gate * for all devices in the specified set
4887c478bd9Sstevel@tonic-gate */
4897c478bd9Sstevel@tonic-gate int
meta_get_sp_names(mdsetname_t * sp,mdnamelist_t ** nlpp,int options,md_error_t * ep)4907c478bd9Sstevel@tonic-gate meta_get_sp_names(
4917c478bd9Sstevel@tonic-gate mdsetname_t *sp,
4927c478bd9Sstevel@tonic-gate mdnamelist_t **nlpp,
4937c478bd9Sstevel@tonic-gate int options,
4947c478bd9Sstevel@tonic-gate md_error_t *ep
4957c478bd9Sstevel@tonic-gate )
4967c478bd9Sstevel@tonic-gate {
4977c478bd9Sstevel@tonic-gate return (meta_get_names(MD_SP, sp, nlpp, options, ep));
4987c478bd9Sstevel@tonic-gate }
4997c478bd9Sstevel@tonic-gate
5007c478bd9Sstevel@tonic-gate /*
5017c478bd9Sstevel@tonic-gate * FUNCTION: meta_get_by_component()
5027c478bd9Sstevel@tonic-gate * INPUT: sp - the set name to get soft partitions from
5037c478bd9Sstevel@tonic-gate * compnp - the name of the device containing the soft
5047c478bd9Sstevel@tonic-gate * partitions that will be returned
5057c478bd9Sstevel@tonic-gate * force - 0 - reads cached namelist if available,
5067c478bd9Sstevel@tonic-gate * 1 - reloads cached namelist, frees old namelist
5077c478bd9Sstevel@tonic-gate * OUTPUT: nlpp - list of all soft partition names
5087c478bd9Sstevel@tonic-gate * ep - return error pointer
5097c478bd9Sstevel@tonic-gate * RETURNS: int - -1 error, otherwise the number of soft partitions
5107c478bd9Sstevel@tonic-gate * found on the component (0 = none found).
5117c478bd9Sstevel@tonic-gate * PURPOSE: returns a list of all soft partitions on a given device
5127c478bd9Sstevel@tonic-gate * from the metadb information
5137c478bd9Sstevel@tonic-gate */
5147c478bd9Sstevel@tonic-gate static int
meta_sp_get_by_component(mdsetname_t * sp,mdname_t * compnp,mdnamelist_t ** nlpp,int force,md_error_t * ep)5157c478bd9Sstevel@tonic-gate meta_sp_get_by_component(
5167c478bd9Sstevel@tonic-gate mdsetname_t *sp,
5177c478bd9Sstevel@tonic-gate mdname_t *compnp,
5187c478bd9Sstevel@tonic-gate mdnamelist_t **nlpp,
5197c478bd9Sstevel@tonic-gate int force,
5207c478bd9Sstevel@tonic-gate md_error_t *ep
5217c478bd9Sstevel@tonic-gate )
5227c478bd9Sstevel@tonic-gate {
5237c478bd9Sstevel@tonic-gate static mdnamelist_t *cached_list = NULL; /* cached namelist */
5247c478bd9Sstevel@tonic-gate static int cached_count = 0; /* cached count */
5257c478bd9Sstevel@tonic-gate mdnamelist_t *spnlp = NULL; /* all sp names */
5267c478bd9Sstevel@tonic-gate mdnamelist_t *namep; /* list iterator */
5277c478bd9Sstevel@tonic-gate mdnamelist_t **tailpp = nlpp; /* namelist tail */
5287c478bd9Sstevel@tonic-gate mdnamelist_t **cachetailpp; /* cache tail */
5297c478bd9Sstevel@tonic-gate md_sp_t *msp; /* unit structure */
5307c478bd9Sstevel@tonic-gate int count = 0; /* count of sp's */
5317c478bd9Sstevel@tonic-gate int err;
5327c478bd9Sstevel@tonic-gate mdname_t *curnp;
5337c478bd9Sstevel@tonic-gate
5347c478bd9Sstevel@tonic-gate if ((cached_list != NULL) && (!force)) {
5357c478bd9Sstevel@tonic-gate /* return a copy of the cached list */
5367c478bd9Sstevel@tonic-gate for (namep = cached_list; namep != NULL; namep = namep->next)
5377c478bd9Sstevel@tonic-gate tailpp = meta_namelist_append_wrapper(tailpp,
5387c478bd9Sstevel@tonic-gate namep->namep);
5397c478bd9Sstevel@tonic-gate return (cached_count);
5407c478bd9Sstevel@tonic-gate }
5417c478bd9Sstevel@tonic-gate
5427c478bd9Sstevel@tonic-gate /* free the cache and reset values to zeros to prepare for a new list */
5437c478bd9Sstevel@tonic-gate metafreenamelist(cached_list);
5447c478bd9Sstevel@tonic-gate cached_count = 0;
5457c478bd9Sstevel@tonic-gate cached_list = NULL;
5467c478bd9Sstevel@tonic-gate cachetailpp = &cached_list;
5477c478bd9Sstevel@tonic-gate *nlpp = NULL;
5487c478bd9Sstevel@tonic-gate
5497c478bd9Sstevel@tonic-gate /* get all the softpartitions first of all */
5507c478bd9Sstevel@tonic-gate if (meta_get_sp_names(sp, &spnlp, 0, ep) < 0)
5517c478bd9Sstevel@tonic-gate return (-1);
5527c478bd9Sstevel@tonic-gate
5537c478bd9Sstevel@tonic-gate /*
5547c478bd9Sstevel@tonic-gate * Now for each sp, see if it resides on the component we
5557c478bd9Sstevel@tonic-gate * are interested in, if so then add it to our list
5567c478bd9Sstevel@tonic-gate */
5577c478bd9Sstevel@tonic-gate for (namep = spnlp; namep != NULL; namep = namep->next) {
5587c478bd9Sstevel@tonic-gate curnp = namep->namep;
5597c478bd9Sstevel@tonic-gate
5607c478bd9Sstevel@tonic-gate /* get the unit structure */
5617c478bd9Sstevel@tonic-gate if ((msp = meta_get_sp_common(sp, curnp, 0, ep)) == NULL)
5627c478bd9Sstevel@tonic-gate continue;
5637c478bd9Sstevel@tonic-gate
5647c478bd9Sstevel@tonic-gate /*
5657c478bd9Sstevel@tonic-gate * If the current soft partition is not on the same
5667c478bd9Sstevel@tonic-gate * component, continue the search. If it is on the same
5677c478bd9Sstevel@tonic-gate * component, add it to our namelist.
5687c478bd9Sstevel@tonic-gate */
5697c478bd9Sstevel@tonic-gate err = meta_check_samedrive(compnp, msp->compnamep, ep);
5707c478bd9Sstevel@tonic-gate if (err <= 0) {
5717c478bd9Sstevel@tonic-gate /* not on the same device, check the next one */
5727c478bd9Sstevel@tonic-gate continue;
5737c478bd9Sstevel@tonic-gate }
5747c478bd9Sstevel@tonic-gate
5757c478bd9Sstevel@tonic-gate /* it's on the same drive */
5767c478bd9Sstevel@tonic-gate
5777c478bd9Sstevel@tonic-gate /*
5787c478bd9Sstevel@tonic-gate * Check for overlapping partitions if the component is not
5797c478bd9Sstevel@tonic-gate * a metadevice.
5807c478bd9Sstevel@tonic-gate */
5817c478bd9Sstevel@tonic-gate if (!metaismeta(msp->compnamep)) {
5827c478bd9Sstevel@tonic-gate /*
5837c478bd9Sstevel@tonic-gate * if they're on the same drive, neither
5847c478bd9Sstevel@tonic-gate * should be a metadevice if one isn't
5857c478bd9Sstevel@tonic-gate */
5867c478bd9Sstevel@tonic-gate assert(!metaismeta(compnp));
5877c478bd9Sstevel@tonic-gate
5887c478bd9Sstevel@tonic-gate if (meta_check_overlap(msp->compnamep->cname,
5897c478bd9Sstevel@tonic-gate compnp, 0, -1, msp->compnamep, 0, -1, ep) == 0)
5907c478bd9Sstevel@tonic-gate continue;
5917c478bd9Sstevel@tonic-gate
5927c478bd9Sstevel@tonic-gate /* in this case it's not an error for them to overlap */
5937c478bd9Sstevel@tonic-gate mdclrerror(ep);
5947c478bd9Sstevel@tonic-gate }
5957c478bd9Sstevel@tonic-gate
5967c478bd9Sstevel@tonic-gate /* Component is on the same device, add to the used list */
5977c478bd9Sstevel@tonic-gate tailpp = meta_namelist_append_wrapper(tailpp, curnp);
5987c478bd9Sstevel@tonic-gate cachetailpp = meta_namelist_append_wrapper(cachetailpp,
5997c478bd9Sstevel@tonic-gate curnp);
6007c478bd9Sstevel@tonic-gate
6017c478bd9Sstevel@tonic-gate ++count;
6027c478bd9Sstevel@tonic-gate ++cached_count;
6037c478bd9Sstevel@tonic-gate }
6047c478bd9Sstevel@tonic-gate
6057c478bd9Sstevel@tonic-gate assert(count == cached_count);
6067c478bd9Sstevel@tonic-gate return (count);
6077c478bd9Sstevel@tonic-gate
6087c478bd9Sstevel@tonic-gate out:
6097c478bd9Sstevel@tonic-gate metafreenamelist(*nlpp);
6107c478bd9Sstevel@tonic-gate *nlpp = NULL;
6117c478bd9Sstevel@tonic-gate return (-1);
6127c478bd9Sstevel@tonic-gate }
6137c478bd9Sstevel@tonic-gate
6147c478bd9Sstevel@tonic-gate /*
6157c478bd9Sstevel@tonic-gate * FUNCTION: meta_sp_get_default_alignment()
6167c478bd9Sstevel@tonic-gate * INPUT: sp - the pertinent set name
6177c478bd9Sstevel@tonic-gate * compnp - the name of the underlying component
6187c478bd9Sstevel@tonic-gate * OUTPUT: ep - return error pointer
6197c478bd9Sstevel@tonic-gate * RETURNS: sp_ext_length_t =0: no default alignment
6207c478bd9Sstevel@tonic-gate * >0: default alignment
6217c478bd9Sstevel@tonic-gate * PURPOSE: returns the default alignment for soft partitions to
6227c478bd9Sstevel@tonic-gate * be built on top of the specified component or
6237c478bd9Sstevel@tonic-gate * metadevice
6247c478bd9Sstevel@tonic-gate */
6257c478bd9Sstevel@tonic-gate static sp_ext_length_t
meta_sp_get_default_alignment(mdsetname_t * sp,mdname_t * compnp,md_error_t * ep)6267c478bd9Sstevel@tonic-gate meta_sp_get_default_alignment(
6277c478bd9Sstevel@tonic-gate mdsetname_t *sp,
6287c478bd9Sstevel@tonic-gate mdname_t *compnp,
6297c478bd9Sstevel@tonic-gate md_error_t *ep
6307c478bd9Sstevel@tonic-gate )
6317c478bd9Sstevel@tonic-gate {
6327c478bd9Sstevel@tonic-gate sp_ext_length_t a = SP_UNALIGNED;
6337c478bd9Sstevel@tonic-gate char *mname;
6347c478bd9Sstevel@tonic-gate
6357c478bd9Sstevel@tonic-gate assert(compnp != NULL);
6367c478bd9Sstevel@tonic-gate
6377c478bd9Sstevel@tonic-gate /*
6387c478bd9Sstevel@tonic-gate * We treat raw devices as opaque, and assume nothing about
6397c478bd9Sstevel@tonic-gate * their alignment requirements.
6407c478bd9Sstevel@tonic-gate */
6417c478bd9Sstevel@tonic-gate if (!metaismeta(compnp))
6427c478bd9Sstevel@tonic-gate return (SP_UNALIGNED);
6437c478bd9Sstevel@tonic-gate
6447c478bd9Sstevel@tonic-gate /*
6457c478bd9Sstevel@tonic-gate * We already know it's a metadevice from the previous test;
6467c478bd9Sstevel@tonic-gate * metagetmiscname() will tell us which metadevice type we
6477c478bd9Sstevel@tonic-gate * have
6487c478bd9Sstevel@tonic-gate */
6497c478bd9Sstevel@tonic-gate mname = metagetmiscname(compnp, ep);
6507c478bd9Sstevel@tonic-gate if (mname == NULL)
6517c478bd9Sstevel@tonic-gate goto out;
6527c478bd9Sstevel@tonic-gate
6537c478bd9Sstevel@tonic-gate /*
6547c478bd9Sstevel@tonic-gate * For a mirror, we want to deal with the stripe that is the
6557c478bd9Sstevel@tonic-gate * primary side. If it happens to be asymmetrically
6567c478bd9Sstevel@tonic-gate * configured, there is no simple way to fake a universal
6577c478bd9Sstevel@tonic-gate * alignment. There's a chance that the least common
6587c478bd9Sstevel@tonic-gate * denominator of the set of interlaces from all stripes of
6597c478bd9Sstevel@tonic-gate * all submirrors would do it, but nobody that really cared
6607c478bd9Sstevel@tonic-gate * that much about this issue would create an asymmetric
6617c478bd9Sstevel@tonic-gate * config to start with.
6627c478bd9Sstevel@tonic-gate *
6637c478bd9Sstevel@tonic-gate * If the component underlying the soft partition is a mirror,
6647c478bd9Sstevel@tonic-gate * then at the exit of this loop, compnp will have been
6657c478bd9Sstevel@tonic-gate * updated to describe the first active submirror.
6667c478bd9Sstevel@tonic-gate */
6677c478bd9Sstevel@tonic-gate if (strcmp(mname, MD_MIRROR) == 0) {
6687c478bd9Sstevel@tonic-gate md_mirror_t *mp;
6697c478bd9Sstevel@tonic-gate int smi;
6707c478bd9Sstevel@tonic-gate md_submirror_t *smp;
6717c478bd9Sstevel@tonic-gate
6727c478bd9Sstevel@tonic-gate mp = meta_get_mirror(sp, compnp, ep);
6737c478bd9Sstevel@tonic-gate if (mp == NULL)
6747c478bd9Sstevel@tonic-gate goto out;
6757c478bd9Sstevel@tonic-gate
6767c478bd9Sstevel@tonic-gate for (smi = 0; smi < NMIRROR; smi++) {
6777c478bd9Sstevel@tonic-gate
6787c478bd9Sstevel@tonic-gate smp = &mp->submirrors[smi];
6797c478bd9Sstevel@tonic-gate if (smp->state == SMS_UNUSED)
6807c478bd9Sstevel@tonic-gate continue;
6817c478bd9Sstevel@tonic-gate
6827c478bd9Sstevel@tonic-gate compnp = smp->submirnamep;
6837c478bd9Sstevel@tonic-gate assert(compnp != NULL);
6847c478bd9Sstevel@tonic-gate
6857c478bd9Sstevel@tonic-gate mname = metagetmiscname(compnp, ep);
6867c478bd9Sstevel@tonic-gate if (mname == NULL)
6877c478bd9Sstevel@tonic-gate goto out;
6887c478bd9Sstevel@tonic-gate
6897c478bd9Sstevel@tonic-gate break;
6907c478bd9Sstevel@tonic-gate }
6917c478bd9Sstevel@tonic-gate
6927c478bd9Sstevel@tonic-gate if (smi == NMIRROR)
6937c478bd9Sstevel@tonic-gate goto out;
6947c478bd9Sstevel@tonic-gate }
6957c478bd9Sstevel@tonic-gate
6967c478bd9Sstevel@tonic-gate /*
6977c478bd9Sstevel@tonic-gate * Handle stripes and submirrors identically; just return the
6987c478bd9Sstevel@tonic-gate * interlace of the first row.
6997c478bd9Sstevel@tonic-gate */
7007c478bd9Sstevel@tonic-gate if (strcmp(mname, MD_STRIPE) == 0) {
7017c478bd9Sstevel@tonic-gate md_stripe_t *stp;
7027c478bd9Sstevel@tonic-gate
7037c478bd9Sstevel@tonic-gate stp = meta_get_stripe(sp, compnp, ep);
7047c478bd9Sstevel@tonic-gate if (stp == NULL)
7057c478bd9Sstevel@tonic-gate goto out;
7067c478bd9Sstevel@tonic-gate
7077c478bd9Sstevel@tonic-gate a = stp->rows.rows_val[0].interlace;
7087c478bd9Sstevel@tonic-gate goto out;
7097c478bd9Sstevel@tonic-gate }
7107c478bd9Sstevel@tonic-gate
7117c478bd9Sstevel@tonic-gate /*
7127c478bd9Sstevel@tonic-gate * Raid is even more straightforward; the interlace applies to
7137c478bd9Sstevel@tonic-gate * the entire device.
7147c478bd9Sstevel@tonic-gate */
7157c478bd9Sstevel@tonic-gate if (strcmp(mname, MD_RAID) == 0) {
7167c478bd9Sstevel@tonic-gate md_raid_t *rp;
7177c478bd9Sstevel@tonic-gate
7187c478bd9Sstevel@tonic-gate rp = meta_get_raid(sp, compnp, ep);
7197c478bd9Sstevel@tonic-gate if (rp == NULL)
7207c478bd9Sstevel@tonic-gate goto out;
7217c478bd9Sstevel@tonic-gate
7227c478bd9Sstevel@tonic-gate a = rp->interlace;
7237c478bd9Sstevel@tonic-gate goto out;
7247c478bd9Sstevel@tonic-gate }
7257c478bd9Sstevel@tonic-gate
7267c478bd9Sstevel@tonic-gate /*
7277c478bd9Sstevel@tonic-gate * If we have arrived here with the alignment still not set,
7287c478bd9Sstevel@tonic-gate * then we expect the error to have been set by one of the
7297c478bd9Sstevel@tonic-gate * routines we called. If neither is the case, something has
7307c478bd9Sstevel@tonic-gate * really gone wrong above. (Probably the submirror walk
7317c478bd9Sstevel@tonic-gate * failed to produce a valid submirror, but that would be
7327c478bd9Sstevel@tonic-gate * really bad...)
7337c478bd9Sstevel@tonic-gate */
7347c478bd9Sstevel@tonic-gate out:
7357c478bd9Sstevel@tonic-gate meta_sp_debug("meta_sp_get_default_alignment: miscname %s, "
7367c478bd9Sstevel@tonic-gate "alignment %lld\n", (mname == NULL) ? "NULL" : mname, a);
7377c478bd9Sstevel@tonic-gate
7387c478bd9Sstevel@tonic-gate if (getenv(META_SP_DEBUG) && !mdisok(ep)) {
7397c478bd9Sstevel@tonic-gate mde_perror(ep, NULL);
7407c478bd9Sstevel@tonic-gate }
7417c478bd9Sstevel@tonic-gate
7427c478bd9Sstevel@tonic-gate assert((a > 0) || (!mdisok(ep)));
7437c478bd9Sstevel@tonic-gate
7447c478bd9Sstevel@tonic-gate return (a);
7457c478bd9Sstevel@tonic-gate }
7467c478bd9Sstevel@tonic-gate
7477c478bd9Sstevel@tonic-gate
7487c478bd9Sstevel@tonic-gate
7497c478bd9Sstevel@tonic-gate /*
7507c478bd9Sstevel@tonic-gate * FUNCTION: meta_check_insp()
7517c478bd9Sstevel@tonic-gate * INPUT: sp - the set name for the device to check
7527c478bd9Sstevel@tonic-gate * np - the name of the device to check
7537c478bd9Sstevel@tonic-gate * slblk - the starting offset of the device to check
7547c478bd9Sstevel@tonic-gate * nblks - the number of blocks in the device to check
7557c478bd9Sstevel@tonic-gate * OUTPUT: ep - return error pointer
7567c478bd9Sstevel@tonic-gate * RETURNS: int - 0 - device contains soft partitions
7577c478bd9Sstevel@tonic-gate * -1 - device does not contain soft partitions
7587c478bd9Sstevel@tonic-gate * PURPOSE: determines whether a device contains any soft partitions
7597c478bd9Sstevel@tonic-gate */
7607c478bd9Sstevel@tonic-gate /* ARGSUSED */
7617c478bd9Sstevel@tonic-gate int
meta_check_insp(mdsetname_t * sp,mdname_t * np,diskaddr_t slblk,diskaddr_t nblks,md_error_t * ep)7627c478bd9Sstevel@tonic-gate meta_check_insp(
7637c478bd9Sstevel@tonic-gate mdsetname_t *sp,
7647c478bd9Sstevel@tonic-gate mdname_t *np,
7657c478bd9Sstevel@tonic-gate diskaddr_t slblk,
7667c478bd9Sstevel@tonic-gate diskaddr_t nblks,
7677c478bd9Sstevel@tonic-gate md_error_t *ep
7687c478bd9Sstevel@tonic-gate )
7697c478bd9Sstevel@tonic-gate {
7707c478bd9Sstevel@tonic-gate mdnamelist_t *spnlp = NULL; /* soft partition name list */
7717c478bd9Sstevel@tonic-gate int count;
7727c478bd9Sstevel@tonic-gate int rval;
7737c478bd9Sstevel@tonic-gate
7747c478bd9Sstevel@tonic-gate /* check set pointer */
7757c478bd9Sstevel@tonic-gate assert(sp != NULL);
7767c478bd9Sstevel@tonic-gate
777d7cd8252Stw21770 /*
778d7cd8252Stw21770 * Get a list of the soft partitions that currently reside on
779d7cd8252Stw21770 * the component. We should ALWAYS force reload the cache,
780d7cd8252Stw21770 * because if we're using the md.tab, we must rebuild
781d7cd8252Stw21770 * the list because it won't contain the previous (if any)
782d7cd8252Stw21770 * soft partition.
783d7cd8252Stw21770 */
7847c478bd9Sstevel@tonic-gate /* find all soft partitions on the component */
785d7cd8252Stw21770 count = meta_sp_get_by_component(sp, np, &spnlp, 1, ep);
7867c478bd9Sstevel@tonic-gate
7877c478bd9Sstevel@tonic-gate if (count == -1) {
7887c478bd9Sstevel@tonic-gate rval = -1;
7897c478bd9Sstevel@tonic-gate } else if (count > 0) {
7907c478bd9Sstevel@tonic-gate rval = mduseerror(ep, MDE_ALREADY, np->dev,
7917c478bd9Sstevel@tonic-gate spnlp->namep->cname, np->cname);
7927c478bd9Sstevel@tonic-gate } else {
7937c478bd9Sstevel@tonic-gate rval = 0;
7947c478bd9Sstevel@tonic-gate }
7957c478bd9Sstevel@tonic-gate
7967c478bd9Sstevel@tonic-gate metafreenamelist(spnlp);
7977c478bd9Sstevel@tonic-gate return (rval);
7987c478bd9Sstevel@tonic-gate }
7997c478bd9Sstevel@tonic-gate
8007c478bd9Sstevel@tonic-gate /*
8017c478bd9Sstevel@tonic-gate * **************************************************************************
8027c478bd9Sstevel@tonic-gate * Extent List Manipulation Functions *
8037c478bd9Sstevel@tonic-gate * **************************************************************************
8047c478bd9Sstevel@tonic-gate */
8057c478bd9Sstevel@tonic-gate
8067c478bd9Sstevel@tonic-gate /*
8077c478bd9Sstevel@tonic-gate * FUNCTION: meta_sp_cmp_by_nameseq()
8087c478bd9Sstevel@tonic-gate * INPUT: e1 - first node to compare
8097c478bd9Sstevel@tonic-gate * e2 - second node to compare
8107c478bd9Sstevel@tonic-gate * OUTPUT: none
8117c478bd9Sstevel@tonic-gate * RETURNS: int - =0 - nodes are equal
8127c478bd9Sstevel@tonic-gate * <0 - e1 should go before e2
8137c478bd9Sstevel@tonic-gate * >0 - e1 should go after e2
8147c478bd9Sstevel@tonic-gate * PURPOSE: used for sorted list inserts to build a list sorted by
8157c478bd9Sstevel@tonic-gate * name first and sequence number second.
8167c478bd9Sstevel@tonic-gate */
8177c478bd9Sstevel@tonic-gate static int
meta_sp_cmp_by_nameseq(sp_ext_node_t * e1,sp_ext_node_t * e2)8187c478bd9Sstevel@tonic-gate meta_sp_cmp_by_nameseq(sp_ext_node_t *e1, sp_ext_node_t *e2)
8197c478bd9Sstevel@tonic-gate {
8207c478bd9Sstevel@tonic-gate int rval;
8217c478bd9Sstevel@tonic-gate
8227c478bd9Sstevel@tonic-gate if (e1->ext_namep == NULL)
8237c478bd9Sstevel@tonic-gate return (1);
8247c478bd9Sstevel@tonic-gate if (e2->ext_namep == NULL)
8257c478bd9Sstevel@tonic-gate return (-1);
8267c478bd9Sstevel@tonic-gate if ((rval = strcmp(e1->ext_namep->cname, e2->ext_namep->cname)) != 0)
8277c478bd9Sstevel@tonic-gate return (rval);
8287c478bd9Sstevel@tonic-gate
8297c478bd9Sstevel@tonic-gate /* the names are equal, compare sequence numbers */
8307c478bd9Sstevel@tonic-gate if (e1->ext_seq > e2->ext_seq)
8317c478bd9Sstevel@tonic-gate return (1);
8327c478bd9Sstevel@tonic-gate if (e1->ext_seq < e2->ext_seq)
8337c478bd9Sstevel@tonic-gate return (-1);
8347c478bd9Sstevel@tonic-gate /* sequence numbers are also equal */
8357c478bd9Sstevel@tonic-gate return (0);
8367c478bd9Sstevel@tonic-gate }
8377c478bd9Sstevel@tonic-gate
8387c478bd9Sstevel@tonic-gate /*
8397c478bd9Sstevel@tonic-gate * FUNCTION: meta_sp_cmp_by_offset()
8407c478bd9Sstevel@tonic-gate * INPUT: e1 - first node to compare
8417c478bd9Sstevel@tonic-gate * e2 - second node to compare
8427c478bd9Sstevel@tonic-gate * OUTPUT: none
8437c478bd9Sstevel@tonic-gate * RETURNS: int - =0 - nodes are equal
8447c478bd9Sstevel@tonic-gate * <0 - e1 should go before e2
8457c478bd9Sstevel@tonic-gate * >0 - e1 should go after e2
8467c478bd9Sstevel@tonic-gate * PURPOSE: used for sorted list inserts to build a list sorted by offset
8477c478bd9Sstevel@tonic-gate */
8487c478bd9Sstevel@tonic-gate static int
meta_sp_cmp_by_offset(sp_ext_node_t * e1,sp_ext_node_t * e2)8497c478bd9Sstevel@tonic-gate meta_sp_cmp_by_offset(sp_ext_node_t *e1, sp_ext_node_t *e2)
8507c478bd9Sstevel@tonic-gate {
8517c478bd9Sstevel@tonic-gate if (e1->ext_offset > e2->ext_offset)
8527c478bd9Sstevel@tonic-gate return (1);
8537c478bd9Sstevel@tonic-gate if (e1->ext_offset < e2->ext_offset)
8547c478bd9Sstevel@tonic-gate return (-1);
8557c478bd9Sstevel@tonic-gate /* offsets are equal */
8567c478bd9Sstevel@tonic-gate return (0);
8577c478bd9Sstevel@tonic-gate }
8587c478bd9Sstevel@tonic-gate
8597c478bd9Sstevel@tonic-gate /*
8607c478bd9Sstevel@tonic-gate * FUNCTION: meta_sp_list_insert()
8617c478bd9Sstevel@tonic-gate * INPUT: sp - the set name for the device the node belongs to
8627c478bd9Sstevel@tonic-gate * np - the name of the device the node belongs to
8637c478bd9Sstevel@tonic-gate * head - the head of the list, must be NULL for empty list
8647c478bd9Sstevel@tonic-gate * offset - the physical offset of this extent in sectors
8657c478bd9Sstevel@tonic-gate * length - the length of this extent in sectors
8667c478bd9Sstevel@tonic-gate * type - the type of the extent being inserted
8677c478bd9Sstevel@tonic-gate * seq - the sequence number of the extent being inserted
8687c478bd9Sstevel@tonic-gate * flags - extent flags (eg. whether it needs to be updated)
8697c478bd9Sstevel@tonic-gate * compare - the compare function to use
8707c478bd9Sstevel@tonic-gate * OUTPUT: head - points to the new head if a node was inserted
8717c478bd9Sstevel@tonic-gate * at the beginning
8727c478bd9Sstevel@tonic-gate * RETURNS: void
8737c478bd9Sstevel@tonic-gate * PURPOSE: inserts an extent node into a sorted doubly linked list.
8747c478bd9Sstevel@tonic-gate * The sort order is determined by the compare function.
8757c478bd9Sstevel@tonic-gate * Memory is allocated for the node in this function and it
8767c478bd9Sstevel@tonic-gate * is up to the caller to free it, possibly using
8777c478bd9Sstevel@tonic-gate * meta_sp_list_free(). If a node is inserted at the
8787c478bd9Sstevel@tonic-gate * beginning of the list, the head pointer is updated to
8797c478bd9Sstevel@tonic-gate * point to the new first node.
8807c478bd9Sstevel@tonic-gate */
8817c478bd9Sstevel@tonic-gate static void
meta_sp_list_insert(mdsetname_t * sp,mdname_t * np,sp_ext_node_t ** head,sp_ext_offset_t offset,sp_ext_length_t length,sp_ext_type_t type,uint_t seq,uint_t flags,ext_cmpfunc_t compare)8827c478bd9Sstevel@tonic-gate meta_sp_list_insert(
8837c478bd9Sstevel@tonic-gate mdsetname_t *sp,
8847c478bd9Sstevel@tonic-gate mdname_t *np,
8857c478bd9Sstevel@tonic-gate sp_ext_node_t **head,
8867c478bd9Sstevel@tonic-gate sp_ext_offset_t offset,
8877c478bd9Sstevel@tonic-gate sp_ext_length_t length,
8887c478bd9Sstevel@tonic-gate sp_ext_type_t type,
8897c478bd9Sstevel@tonic-gate uint_t seq,
8907c478bd9Sstevel@tonic-gate uint_t flags,
8917c478bd9Sstevel@tonic-gate ext_cmpfunc_t compare
8927c478bd9Sstevel@tonic-gate )
8937c478bd9Sstevel@tonic-gate {
8947c478bd9Sstevel@tonic-gate sp_ext_node_t *newext;
8957c478bd9Sstevel@tonic-gate sp_ext_node_t *curext;
8967c478bd9Sstevel@tonic-gate
8977c478bd9Sstevel@tonic-gate assert(head != NULL);
8987c478bd9Sstevel@tonic-gate
8997c478bd9Sstevel@tonic-gate /* Don't bother adding zero length nodes */
9007c478bd9Sstevel@tonic-gate if (length == 0ULL)
9017c478bd9Sstevel@tonic-gate return;
9027c478bd9Sstevel@tonic-gate
9037c478bd9Sstevel@tonic-gate /* allocate and fill in new ext_node */
9047c478bd9Sstevel@tonic-gate newext = Zalloc(sizeof (sp_ext_node_t));
9057c478bd9Sstevel@tonic-gate
9067c478bd9Sstevel@tonic-gate newext->ext_offset = offset;
9077c478bd9Sstevel@tonic-gate newext->ext_length = length;
9087c478bd9Sstevel@tonic-gate newext->ext_flags = flags;
9097c478bd9Sstevel@tonic-gate newext->ext_type = type;
9107c478bd9Sstevel@tonic-gate newext->ext_seq = seq;
9117c478bd9Sstevel@tonic-gate newext->ext_setp = sp;
9127c478bd9Sstevel@tonic-gate newext->ext_namep = np;
9137c478bd9Sstevel@tonic-gate
9147c478bd9Sstevel@tonic-gate /* first node in the list */
9157c478bd9Sstevel@tonic-gate if (*head == NULL) {
9167c478bd9Sstevel@tonic-gate newext->ext_next = newext->ext_prev = NULL;
9177c478bd9Sstevel@tonic-gate *head = newext;
9187c478bd9Sstevel@tonic-gate } else if ((*compare)(*head, newext) >= 0) {
9197c478bd9Sstevel@tonic-gate /* the first node has a bigger offset, so insert before it */
9207c478bd9Sstevel@tonic-gate assert((*head)->ext_prev == NULL);
9217c478bd9Sstevel@tonic-gate
9227c478bd9Sstevel@tonic-gate newext->ext_prev = NULL;
9237c478bd9Sstevel@tonic-gate newext->ext_next = *head;
9247c478bd9Sstevel@tonic-gate (*head)->ext_prev = newext;
9257c478bd9Sstevel@tonic-gate *head = newext;
9267c478bd9Sstevel@tonic-gate } else {
9277c478bd9Sstevel@tonic-gate /*
9287c478bd9Sstevel@tonic-gate * find the next node whose offset is greater than
9297c478bd9Sstevel@tonic-gate * the one we want to insert, or the end of the list.
9307c478bd9Sstevel@tonic-gate */
9317c478bd9Sstevel@tonic-gate for (curext = *head;
9327c478bd9Sstevel@tonic-gate (curext->ext_next != NULL) &&
9337c478bd9Sstevel@tonic-gate ((*compare)(curext->ext_next, newext) < 0);
9347c478bd9Sstevel@tonic-gate (curext = curext->ext_next))
9357c478bd9Sstevel@tonic-gate ;
9367c478bd9Sstevel@tonic-gate
9377c478bd9Sstevel@tonic-gate /* link the new node in after the current node */
9387c478bd9Sstevel@tonic-gate newext->ext_next = curext->ext_next;
9397c478bd9Sstevel@tonic-gate newext->ext_prev = curext;
9407c478bd9Sstevel@tonic-gate
9417c478bd9Sstevel@tonic-gate if (curext->ext_next != NULL)
9427c478bd9Sstevel@tonic-gate curext->ext_next->ext_prev = newext;
9437c478bd9Sstevel@tonic-gate
9447c478bd9Sstevel@tonic-gate curext->ext_next = newext;
9457c478bd9Sstevel@tonic-gate }
9467c478bd9Sstevel@tonic-gate }
9477c478bd9Sstevel@tonic-gate
9487c478bd9Sstevel@tonic-gate /*
9497c478bd9Sstevel@tonic-gate * FUNCTION: meta_sp_list_free()
9507c478bd9Sstevel@tonic-gate * INPUT: head - the head of the list, must be NULL for empty list
9517c478bd9Sstevel@tonic-gate * OUTPUT: head - points to NULL on return
9527c478bd9Sstevel@tonic-gate * RETURNS: void
9537c478bd9Sstevel@tonic-gate * PURPOSE: walks a double linked extent list and frees each node
9547c478bd9Sstevel@tonic-gate */
9557c478bd9Sstevel@tonic-gate static void
meta_sp_list_free(sp_ext_node_t ** head)9567c478bd9Sstevel@tonic-gate meta_sp_list_free(sp_ext_node_t **head)
9577c478bd9Sstevel@tonic-gate {
9587c478bd9Sstevel@tonic-gate sp_ext_node_t *ext;
9597c478bd9Sstevel@tonic-gate sp_ext_node_t *next;
9607c478bd9Sstevel@tonic-gate
9617c478bd9Sstevel@tonic-gate assert(head != NULL);
9627c478bd9Sstevel@tonic-gate
9637c478bd9Sstevel@tonic-gate ext = *head;
9647c478bd9Sstevel@tonic-gate while (ext) {
9657c478bd9Sstevel@tonic-gate next = ext->ext_next;
9667c478bd9Sstevel@tonic-gate Free(ext);
9677c478bd9Sstevel@tonic-gate ext = next;
9687c478bd9Sstevel@tonic-gate }
9697c478bd9Sstevel@tonic-gate *head = NULL;
9707c478bd9Sstevel@tonic-gate }
9717c478bd9Sstevel@tonic-gate
9727c478bd9Sstevel@tonic-gate /*
9737c478bd9Sstevel@tonic-gate * FUNCTION: meta_sp_list_remove()
9747c478bd9Sstevel@tonic-gate * INPUT: head - the head of the list, must be NULL for empty list
9757c478bd9Sstevel@tonic-gate * ext - the extent to remove, must be a member of the list
9767c478bd9Sstevel@tonic-gate * OUTPUT: head - points to the new head of the list
9777c478bd9Sstevel@tonic-gate * RETURNS: void
9787c478bd9Sstevel@tonic-gate * PURPOSE: unlinks the node specified by ext from the list and
9797c478bd9Sstevel@tonic-gate * frees it, possibly moving the head pointer forward if
9807c478bd9Sstevel@tonic-gate * the head is the node being removed.
9817c478bd9Sstevel@tonic-gate */
9827c478bd9Sstevel@tonic-gate static void
meta_sp_list_remove(sp_ext_node_t ** head,sp_ext_node_t * ext)9837c478bd9Sstevel@tonic-gate meta_sp_list_remove(sp_ext_node_t **head, sp_ext_node_t *ext)
9847c478bd9Sstevel@tonic-gate {
9857c478bd9Sstevel@tonic-gate assert(head != NULL);
9867c478bd9Sstevel@tonic-gate assert(*head != NULL);
9877c478bd9Sstevel@tonic-gate
9887c478bd9Sstevel@tonic-gate if (*head == ext)
9897c478bd9Sstevel@tonic-gate *head = ext->ext_next;
9907c478bd9Sstevel@tonic-gate
9917c478bd9Sstevel@tonic-gate if (ext->ext_prev != NULL)
9927c478bd9Sstevel@tonic-gate ext->ext_prev->ext_next = ext->ext_next;
9937c478bd9Sstevel@tonic-gate if (ext->ext_next != NULL)
9947c478bd9Sstevel@tonic-gate ext->ext_next->ext_prev = ext->ext_prev;
9957c478bd9Sstevel@tonic-gate Free(ext);
9967c478bd9Sstevel@tonic-gate }
9977c478bd9Sstevel@tonic-gate
9987c478bd9Sstevel@tonic-gate /*
9997c478bd9Sstevel@tonic-gate * FUNCTION: meta_sp_list_size()
10007c478bd9Sstevel@tonic-gate * INPUT: head - the head of the list, must be NULL for empty list
10017c478bd9Sstevel@tonic-gate * exttype - the type of the extents to sum
10027c478bd9Sstevel@tonic-gate * exclude_wm - subtract space for extent headers from total
10037c478bd9Sstevel@tonic-gate * OUTPUT: none
10047c478bd9Sstevel@tonic-gate * RETURNS: sp_ext_length_t - the sum of all of the lengths
10057c478bd9Sstevel@tonic-gate * PURPOSE: sums the lengths of all extents in the list matching the
10067c478bd9Sstevel@tonic-gate * specified type. This could be used for computing the
10077c478bd9Sstevel@tonic-gate * amount of free or used space, for example.
10087c478bd9Sstevel@tonic-gate */
10097c478bd9Sstevel@tonic-gate static sp_ext_length_t
meta_sp_list_size(sp_ext_node_t * head,sp_ext_type_t exttype,int exclude_wm)10107c478bd9Sstevel@tonic-gate meta_sp_list_size(sp_ext_node_t *head, sp_ext_type_t exttype, int exclude_wm)
10117c478bd9Sstevel@tonic-gate {
10127c478bd9Sstevel@tonic-gate sp_ext_node_t *ext;
10137c478bd9Sstevel@tonic-gate sp_ext_length_t size = 0LL;
10147c478bd9Sstevel@tonic-gate
10157c478bd9Sstevel@tonic-gate for (ext = head; ext != NULL; ext = ext->ext_next)
10167c478bd9Sstevel@tonic-gate if (ext->ext_type == exttype)
10177c478bd9Sstevel@tonic-gate size += ext->ext_length -
10187c478bd9Sstevel@tonic-gate ((exclude_wm) ? MD_SP_WMSIZE : 0);
10197c478bd9Sstevel@tonic-gate
10207c478bd9Sstevel@tonic-gate return (size);
10217c478bd9Sstevel@tonic-gate }
10227c478bd9Sstevel@tonic-gate
10237c478bd9Sstevel@tonic-gate /*
10247c478bd9Sstevel@tonic-gate * FUNCTION: meta_sp_list_find()
10257c478bd9Sstevel@tonic-gate * INPUT: head - the head of the list, must be NULL for empty list
10267c478bd9Sstevel@tonic-gate * offset - the offset contained by the node to find
10277c478bd9Sstevel@tonic-gate * OUTPUT: none
10287c478bd9Sstevel@tonic-gate * RETURNS: sp_ext_node_t * - the node containing the requested offset
10297c478bd9Sstevel@tonic-gate * or NULL if no such nodes were found.
10307c478bd9Sstevel@tonic-gate * PURPOSE: finds a node in a list containing the requested offset
10317c478bd9Sstevel@tonic-gate * (inclusive). If multiple nodes contain this offset then
10327c478bd9Sstevel@tonic-gate * only the first will be returned, though typically these
10337c478bd9Sstevel@tonic-gate * lists are managed with non-overlapping nodes.
10347c478bd9Sstevel@tonic-gate *
10357c478bd9Sstevel@tonic-gate * *The list MUST be sorted by offset for this function to work.*
10367c478bd9Sstevel@tonic-gate */
10377c478bd9Sstevel@tonic-gate static sp_ext_node_t *
meta_sp_list_find(sp_ext_node_t * head,sp_ext_offset_t offset)10387c478bd9Sstevel@tonic-gate meta_sp_list_find(
10397c478bd9Sstevel@tonic-gate sp_ext_node_t *head,
10407c478bd9Sstevel@tonic-gate sp_ext_offset_t offset
10417c478bd9Sstevel@tonic-gate )
10427c478bd9Sstevel@tonic-gate {
10437c478bd9Sstevel@tonic-gate sp_ext_node_t *ext;
10447c478bd9Sstevel@tonic-gate
10457c478bd9Sstevel@tonic-gate for (ext = head; ext != NULL; ext = ext->ext_next) {
10467c478bd9Sstevel@tonic-gate /* check if the offset lies within this extent */
10477c478bd9Sstevel@tonic-gate if ((offset >= ext->ext_offset) &&
10487c478bd9Sstevel@tonic-gate (offset < ext->ext_offset + ext->ext_length)) {
10497c478bd9Sstevel@tonic-gate /*
10507c478bd9Sstevel@tonic-gate * the requested extent should always be a
10517c478bd9Sstevel@tonic-gate * subset of an extent in the list.
10527c478bd9Sstevel@tonic-gate */
10537c478bd9Sstevel@tonic-gate return (ext);
10547c478bd9Sstevel@tonic-gate }
10557c478bd9Sstevel@tonic-gate }
10567c478bd9Sstevel@tonic-gate return (NULL);
10577c478bd9Sstevel@tonic-gate }
10587c478bd9Sstevel@tonic-gate
10597c478bd9Sstevel@tonic-gate /*
10607c478bd9Sstevel@tonic-gate * FUNCTION: meta_sp_list_freefill()
10617c478bd9Sstevel@tonic-gate * INPUT: head - the head of the list, must be NULL for empty list
10627c478bd9Sstevel@tonic-gate * size - the size of the volume this extent list is
10637c478bd9Sstevel@tonic-gate * representing
10647c478bd9Sstevel@tonic-gate * OUTPUT: head - the new head of the list
10657c478bd9Sstevel@tonic-gate * RETURNS: void
10667c478bd9Sstevel@tonic-gate * PURPOSE: finds gaps in the extent list and fills them with a free
10677c478bd9Sstevel@tonic-gate * node. If there is a gap at the beginning the head
10687c478bd9Sstevel@tonic-gate * pointer will be changed to point to the new free node.
10697c478bd9Sstevel@tonic-gate * If there is free space at the end, the last free extent
10707c478bd9Sstevel@tonic-gate * will extend all the way out to the size specified.
10717c478bd9Sstevel@tonic-gate *
10727c478bd9Sstevel@tonic-gate * *The list MUST be sorted by offset for this function to work.*
10737c478bd9Sstevel@tonic-gate */
10747c478bd9Sstevel@tonic-gate static void
meta_sp_list_freefill(sp_ext_node_t ** head,sp_ext_length_t size)10757c478bd9Sstevel@tonic-gate meta_sp_list_freefill(
10767c478bd9Sstevel@tonic-gate sp_ext_node_t **head,
10777c478bd9Sstevel@tonic-gate sp_ext_length_t size
10787c478bd9Sstevel@tonic-gate )
10797c478bd9Sstevel@tonic-gate {
10807c478bd9Sstevel@tonic-gate sp_ext_node_t *ext;
10817c478bd9Sstevel@tonic-gate sp_ext_offset_t curoff = 0LL;
10827c478bd9Sstevel@tonic-gate
10837c478bd9Sstevel@tonic-gate for (ext = *head; ext != NULL; ext = ext->ext_next) {
10847c478bd9Sstevel@tonic-gate if (curoff < ext->ext_offset)
10857c478bd9Sstevel@tonic-gate meta_sp_list_insert(NULL, NULL, head,
10867c478bd9Sstevel@tonic-gate curoff, ext->ext_offset - curoff,
10877c478bd9Sstevel@tonic-gate EXTTYP_FREE, 0, 0, meta_sp_cmp_by_offset);
10887c478bd9Sstevel@tonic-gate curoff = ext->ext_offset + ext->ext_length;
10897c478bd9Sstevel@tonic-gate }
10907c478bd9Sstevel@tonic-gate
10917c478bd9Sstevel@tonic-gate /* pad inverse list out to the end */
10927c478bd9Sstevel@tonic-gate if (curoff < size)
10937c478bd9Sstevel@tonic-gate meta_sp_list_insert(NULL, NULL, head, curoff, size - curoff,
10947c478bd9Sstevel@tonic-gate EXTTYP_FREE, 0, 0, meta_sp_cmp_by_offset);
10957c478bd9Sstevel@tonic-gate
10967c478bd9Sstevel@tonic-gate if (getenv(META_SP_DEBUG)) {
10977c478bd9Sstevel@tonic-gate meta_sp_debug("meta_sp_list_freefill: Extent list with "
10987c478bd9Sstevel@tonic-gate "holes freefilled:\n");
10997c478bd9Sstevel@tonic-gate meta_sp_list_dump(*head);
11007c478bd9Sstevel@tonic-gate }
11017c478bd9Sstevel@tonic-gate }
11027c478bd9Sstevel@tonic-gate
11037c478bd9Sstevel@tonic-gate /*
11047c478bd9Sstevel@tonic-gate * FUNCTION: meta_sp_list_dump()
11057c478bd9Sstevel@tonic-gate * INPUT: head - the head of the list, must be NULL for empty list
11067c478bd9Sstevel@tonic-gate * OUTPUT: none
11077c478bd9Sstevel@tonic-gate * RETURNS: void
11087c478bd9Sstevel@tonic-gate * PURPOSE: dumps the entire extent list to stdout for easy debugging
11097c478bd9Sstevel@tonic-gate */
11107c478bd9Sstevel@tonic-gate static void
meta_sp_list_dump(sp_ext_node_t * head)11117c478bd9Sstevel@tonic-gate meta_sp_list_dump(sp_ext_node_t *head)
11127c478bd9Sstevel@tonic-gate {
11137c478bd9Sstevel@tonic-gate sp_ext_node_t *ext;
11147c478bd9Sstevel@tonic-gate
11157c478bd9Sstevel@tonic-gate meta_sp_debug("meta_sp_list_dump: dumping extent list:\n");
11167c478bd9Sstevel@tonic-gate meta_sp_debug("%5s %10s %5s %7s %10s %10s %5s %10s %10s\n", "Name",
11177c478bd9Sstevel@tonic-gate "Addr", "Seq#", "Type", "Offset", "Length", "Flags", "Prev",
11187c478bd9Sstevel@tonic-gate "Next");
11197c478bd9Sstevel@tonic-gate for (ext = head; ext != NULL; ext = ext->ext_next) {
11207c478bd9Sstevel@tonic-gate if (ext->ext_namep != NULL)
11217c478bd9Sstevel@tonic-gate meta_sp_debug("%5s", ext->ext_namep->cname);
11227c478bd9Sstevel@tonic-gate else
11237c478bd9Sstevel@tonic-gate meta_sp_debug("%5s", "NONE");
11247c478bd9Sstevel@tonic-gate
11257c478bd9Sstevel@tonic-gate meta_sp_debug("%10p %5u ", (void *) ext, ext->ext_seq);
11267c478bd9Sstevel@tonic-gate switch (ext->ext_type) {
11277c478bd9Sstevel@tonic-gate case EXTTYP_ALLOC:
11287c478bd9Sstevel@tonic-gate meta_sp_debug("%7s ", "ALLOC");
11297c478bd9Sstevel@tonic-gate break;
11307c478bd9Sstevel@tonic-gate case EXTTYP_FREE:
11317c478bd9Sstevel@tonic-gate meta_sp_debug("%7s ", "FREE");
11327c478bd9Sstevel@tonic-gate break;
11337c478bd9Sstevel@tonic-gate case EXTTYP_END:
11347c478bd9Sstevel@tonic-gate meta_sp_debug("%7s ", "END");
11357c478bd9Sstevel@tonic-gate break;
11367c478bd9Sstevel@tonic-gate case EXTTYP_RESERVED:
11377c478bd9Sstevel@tonic-gate meta_sp_debug("%7s ", "RESV");
11387c478bd9Sstevel@tonic-gate break;
11397c478bd9Sstevel@tonic-gate default:
11407c478bd9Sstevel@tonic-gate meta_sp_debug("%7s ", "INVLD");
11417c478bd9Sstevel@tonic-gate break;
11427c478bd9Sstevel@tonic-gate }
11437c478bd9Sstevel@tonic-gate
11447c478bd9Sstevel@tonic-gate meta_sp_debug("%10llu %10llu %5u %10p %10p\n",
11457c478bd9Sstevel@tonic-gate ext->ext_offset, ext->ext_length,
11467c478bd9Sstevel@tonic-gate ext->ext_flags, (void *) ext->ext_prev,
11477c478bd9Sstevel@tonic-gate (void *) ext->ext_next);
11487c478bd9Sstevel@tonic-gate }
11497c478bd9Sstevel@tonic-gate meta_sp_debug("\n");
11507c478bd9Sstevel@tonic-gate }
11517c478bd9Sstevel@tonic-gate
11527c478bd9Sstevel@tonic-gate /*
11537c478bd9Sstevel@tonic-gate * FUNCTION: meta_sp_list_overlaps()
11547c478bd9Sstevel@tonic-gate * INPUT: head - the head of the list, must be NULL for empty list
11557c478bd9Sstevel@tonic-gate * OUTPUT: none
11567c478bd9Sstevel@tonic-gate * RETURNS: int - 1 if extents overlap, 0 if ok
11577c478bd9Sstevel@tonic-gate * PURPOSE: checks a list for overlaps. The list MUST be sorted by
11587c478bd9Sstevel@tonic-gate * offset for this function to work properly.
11597c478bd9Sstevel@tonic-gate */
11607c478bd9Sstevel@tonic-gate static int
meta_sp_list_overlaps(sp_ext_node_t * head)11617c478bd9Sstevel@tonic-gate meta_sp_list_overlaps(sp_ext_node_t *head)
11627c478bd9Sstevel@tonic-gate {
11637c478bd9Sstevel@tonic-gate sp_ext_node_t *ext;
11647c478bd9Sstevel@tonic-gate
11657c478bd9Sstevel@tonic-gate for (ext = head; ext->ext_next != NULL; ext = ext->ext_next) {
11667c478bd9Sstevel@tonic-gate if (ext->ext_offset + ext->ext_length >
11677c478bd9Sstevel@tonic-gate ext->ext_next->ext_offset)
11687c478bd9Sstevel@tonic-gate return (1);
11697c478bd9Sstevel@tonic-gate }
11707c478bd9Sstevel@tonic-gate return (0);
11717c478bd9Sstevel@tonic-gate }
11727c478bd9Sstevel@tonic-gate
11737c478bd9Sstevel@tonic-gate /*
11747c478bd9Sstevel@tonic-gate * **************************************************************************
11757c478bd9Sstevel@tonic-gate * Extent Allocation Functions *
11767c478bd9Sstevel@tonic-gate * **************************************************************************
11777c478bd9Sstevel@tonic-gate */
11787c478bd9Sstevel@tonic-gate
11797c478bd9Sstevel@tonic-gate /*
11807c478bd9Sstevel@tonic-gate * FUNCTION: meta_sp_alloc_by_ext()
11817c478bd9Sstevel@tonic-gate * INPUT: sp - the set name for the device the node belongs to
11827c478bd9Sstevel@tonic-gate * np - the name of the device the node belongs to
11837c478bd9Sstevel@tonic-gate * head - the head of the list, must be NULL for empty list
11847c478bd9Sstevel@tonic-gate * free_ext - the free extent being allocated from
11857c478bd9Sstevel@tonic-gate * alloc_offset - the offset of the allocation
11867c478bd9Sstevel@tonic-gate * alloc_len - the length of the allocation
11877c478bd9Sstevel@tonic-gate * seq - the sequence number of the allocation
11887c478bd9Sstevel@tonic-gate * OUTPUT: head - the new head pointer
11897c478bd9Sstevel@tonic-gate * RETURNS: void
11907c478bd9Sstevel@tonic-gate * PURPOSE: allocates a portion of the free extent free_ext. The
11917c478bd9Sstevel@tonic-gate * allocated portion starts at alloc_offset and is
11927c478bd9Sstevel@tonic-gate * alloc_length long. Both (alloc_offset) and (alloc_offset +
11937c478bd9Sstevel@tonic-gate * alloc_length) must be contained within the free extent.
11947c478bd9Sstevel@tonic-gate *
11957c478bd9Sstevel@tonic-gate * The free extent is split into as many as 3 pieces - a
11967c478bd9Sstevel@tonic-gate * free extent containing [ free_offset .. alloc_offset ), an
11977c478bd9Sstevel@tonic-gate * allocated extent containing the range [ alloc_offset ..
11987c478bd9Sstevel@tonic-gate * alloc_end ], and another free extent containing the
11997c478bd9Sstevel@tonic-gate * range ( alloc_end .. free_end ]. If either of the two
12007c478bd9Sstevel@tonic-gate * new free extents would be zero length, they are not created.
12017c478bd9Sstevel@tonic-gate *
12027c478bd9Sstevel@tonic-gate * Finally, the original free extent is removed. All newly
12037c478bd9Sstevel@tonic-gate * created extents have the EXTFLG_UPDATE flag set.
12047c478bd9Sstevel@tonic-gate */
12057c478bd9Sstevel@tonic-gate static void
meta_sp_alloc_by_ext(mdsetname_t * sp,mdname_t * np,sp_ext_node_t ** head,sp_ext_node_t * free_ext,sp_ext_offset_t alloc_offset,sp_ext_length_t alloc_length,uint_t seq)12067c478bd9Sstevel@tonic-gate meta_sp_alloc_by_ext(
12077c478bd9Sstevel@tonic-gate mdsetname_t *sp,
12087c478bd9Sstevel@tonic-gate mdname_t *np,
12097c478bd9Sstevel@tonic-gate sp_ext_node_t **head,
12107c478bd9Sstevel@tonic-gate sp_ext_node_t *free_ext,
12117c478bd9Sstevel@tonic-gate sp_ext_offset_t alloc_offset,
12127c478bd9Sstevel@tonic-gate sp_ext_length_t alloc_length,
12137c478bd9Sstevel@tonic-gate uint_t seq
12147c478bd9Sstevel@tonic-gate )
12157c478bd9Sstevel@tonic-gate {
12167c478bd9Sstevel@tonic-gate sp_ext_offset_t free_offset = free_ext->ext_offset;
12177c478bd9Sstevel@tonic-gate sp_ext_length_t free_length = free_ext->ext_length;
12187c478bd9Sstevel@tonic-gate
12197c478bd9Sstevel@tonic-gate sp_ext_offset_t alloc_end = alloc_offset + alloc_length;
12207c478bd9Sstevel@tonic-gate sp_ext_offset_t free_end = free_offset + free_length;
12217c478bd9Sstevel@tonic-gate
12227c478bd9Sstevel@tonic-gate /* allocated extent must be a subset of the free extent */
12237c478bd9Sstevel@tonic-gate assert(free_offset <= alloc_offset);
12247c478bd9Sstevel@tonic-gate assert(free_end >= alloc_end);
12257c478bd9Sstevel@tonic-gate
12267c478bd9Sstevel@tonic-gate meta_sp_list_remove(head, free_ext);
12277c478bd9Sstevel@tonic-gate
12287c478bd9Sstevel@tonic-gate if (free_offset < alloc_offset) {
12297c478bd9Sstevel@tonic-gate meta_sp_list_insert(NULL, NULL, head, free_offset,
12307c478bd9Sstevel@tonic-gate (alloc_offset - free_offset), EXTTYP_FREE, 0,
12317c478bd9Sstevel@tonic-gate EXTFLG_UPDATE, meta_sp_cmp_by_offset);
12327c478bd9Sstevel@tonic-gate }
12337c478bd9Sstevel@tonic-gate
12347c478bd9Sstevel@tonic-gate if (free_end > alloc_end) {
12357c478bd9Sstevel@tonic-gate meta_sp_list_insert(NULL, NULL, head, alloc_end,
12367c478bd9Sstevel@tonic-gate (free_end - alloc_end), EXTTYP_FREE, 0, EXTFLG_UPDATE,
12377c478bd9Sstevel@tonic-gate meta_sp_cmp_by_offset);
12387c478bd9Sstevel@tonic-gate }
12397c478bd9Sstevel@tonic-gate
12407c478bd9Sstevel@tonic-gate meta_sp_list_insert(sp, np, head, alloc_offset, alloc_length,
12417c478bd9Sstevel@tonic-gate EXTTYP_ALLOC, seq, EXTFLG_UPDATE, meta_sp_cmp_by_offset);
12427c478bd9Sstevel@tonic-gate
12437c478bd9Sstevel@tonic-gate if (getenv(META_SP_DEBUG)) {
12447c478bd9Sstevel@tonic-gate meta_sp_debug("meta_sp_alloc_by_ext: extent list:\n");
12457c478bd9Sstevel@tonic-gate meta_sp_list_dump(*head);
12467c478bd9Sstevel@tonic-gate }
12477c478bd9Sstevel@tonic-gate }
12487c478bd9Sstevel@tonic-gate
12497c478bd9Sstevel@tonic-gate /*
12507c478bd9Sstevel@tonic-gate * FUNCTION: meta_sp_alloc_by_len()
12517c478bd9Sstevel@tonic-gate * INPUT: sp - the set name for the device the node belongs to
12527c478bd9Sstevel@tonic-gate * np - the name of the device the node belongs to
12537c478bd9Sstevel@tonic-gate * head - the head of the list, must be NULL for empty list
12547c478bd9Sstevel@tonic-gate * *lp - the requested length to allocate
12557c478bd9Sstevel@tonic-gate * last_off - the last offset already allocated.
12567c478bd9Sstevel@tonic-gate * alignment - the desired extent alignmeent
12577c478bd9Sstevel@tonic-gate * OUTPUT: head - the new head pointer
12587c478bd9Sstevel@tonic-gate * *lp - the length allocated
12597c478bd9Sstevel@tonic-gate * RETURNS: int - -1 if error, the number of new extents on success
12607c478bd9Sstevel@tonic-gate * PURPOSE: allocates extents from free space to satisfy the requested
12617c478bd9Sstevel@tonic-gate * length. If requested length is zero, allocates all
12627c478bd9Sstevel@tonic-gate * remaining free space. This function provides the meat
12637c478bd9Sstevel@tonic-gate * of the extent allocation algorithm. Allocation is a
12647c478bd9Sstevel@tonic-gate * three tier process:
12657c478bd9Sstevel@tonic-gate *
12667c478bd9Sstevel@tonic-gate * 1. If last_off is nonzero and there is free space following
12677c478bd9Sstevel@tonic-gate * that node, then it is extended to allocate as much of that
12687c478bd9Sstevel@tonic-gate * free space as possible. This is useful for metattach.
12697c478bd9Sstevel@tonic-gate * 2. If a free extent can be found to satisfy the remaining
12707c478bd9Sstevel@tonic-gate * requested space, then satisfy the rest of the request
12717c478bd9Sstevel@tonic-gate * from that extent.
12727c478bd9Sstevel@tonic-gate * 3. Start allocating space from any remaining free extents until
12737c478bd9Sstevel@tonic-gate * the remainder of the request is satisified.
12747c478bd9Sstevel@tonic-gate *
12757c478bd9Sstevel@tonic-gate * If alignment is non-zero, then every extent modified
12767c478bd9Sstevel@tonic-gate * or newly allocated will be aligned modulo alignment,
12777c478bd9Sstevel@tonic-gate * with a length that is an integer multiple of
12787c478bd9Sstevel@tonic-gate * alignment.
12797c478bd9Sstevel@tonic-gate *
12807c478bd9Sstevel@tonic-gate * The EXTFLG_UPDATE flag is set for all nodes (free and
12817c478bd9Sstevel@tonic-gate * allocated) that require updated watermarks.
12827c478bd9Sstevel@tonic-gate *
12837c478bd9Sstevel@tonic-gate * This algorithm may have a negative impact on fragmentation
12847c478bd9Sstevel@tonic-gate * in pathological cases and may be improved if it turns out
12857c478bd9Sstevel@tonic-gate * to be a problem. This may be exacerbated by particularly
12867c478bd9Sstevel@tonic-gate * large alignments.
12877c478bd9Sstevel@tonic-gate *
12887c478bd9Sstevel@tonic-gate * NOTE: It's confusing, so it demands an explanation:
12897c478bd9Sstevel@tonic-gate * - len is used to represent requested data space; it
12907c478bd9Sstevel@tonic-gate * does not include room for a watermark. On each full
12917c478bd9Sstevel@tonic-gate * or partial allocation, len will be decremented by
12927c478bd9Sstevel@tonic-gate * alloc_len (see next paragraph) until it reaches
12937c478bd9Sstevel@tonic-gate * zero.
12947c478bd9Sstevel@tonic-gate * - alloc_len is used to represent data space allocated
12957c478bd9Sstevel@tonic-gate * from a particular extent; it does not include space
12967c478bd9Sstevel@tonic-gate * for a watermark. In the rare event that a_length
12977c478bd9Sstevel@tonic-gate * (see next paragraph) is equal to MD_SP_WMSIZE,
12987c478bd9Sstevel@tonic-gate * alloc_len will be zero and the resulting MD_SP_WMSIZE
12997c478bd9Sstevel@tonic-gate * fragment of space will be utterly unusable.
13007c478bd9Sstevel@tonic-gate * - a_length is used to represent all space to be
13017c478bd9Sstevel@tonic-gate * allocated from a particular extent; it DOES include
13027c478bd9Sstevel@tonic-gate * space for a watermark.
13037c478bd9Sstevel@tonic-gate */
13047c478bd9Sstevel@tonic-gate static int
meta_sp_alloc_by_len(mdsetname_t * sp,mdname_t * np,sp_ext_node_t ** head,sp_ext_length_t * lp,sp_ext_offset_t last_off,sp_ext_offset_t alignment)13057c478bd9Sstevel@tonic-gate meta_sp_alloc_by_len(
13067c478bd9Sstevel@tonic-gate mdsetname_t *sp,
13077c478bd9Sstevel@tonic-gate mdname_t *np,
13087c478bd9Sstevel@tonic-gate sp_ext_node_t **head,
13097c478bd9Sstevel@tonic-gate sp_ext_length_t *lp,
13107c478bd9Sstevel@tonic-gate sp_ext_offset_t last_off,
13117c478bd9Sstevel@tonic-gate sp_ext_offset_t alignment
13127c478bd9Sstevel@tonic-gate )
13137c478bd9Sstevel@tonic-gate {
13147c478bd9Sstevel@tonic-gate sp_ext_node_t *free_ext;
13157c478bd9Sstevel@tonic-gate sp_ext_node_t *alloc_ext;
13167c478bd9Sstevel@tonic-gate uint_t last_seq = 0;
13177c478bd9Sstevel@tonic-gate uint_t numexts = 0;
13187c478bd9Sstevel@tonic-gate sp_ext_length_t freespace;
13197c478bd9Sstevel@tonic-gate sp_ext_length_t alloc_len;
13207c478bd9Sstevel@tonic-gate sp_ext_length_t len;
13217c478bd9Sstevel@tonic-gate
13227c478bd9Sstevel@tonic-gate /* We're DOA if we can't read *lp */
13237c478bd9Sstevel@tonic-gate assert(lp != NULL);
13247c478bd9Sstevel@tonic-gate len = *lp;
13257c478bd9Sstevel@tonic-gate
13267c478bd9Sstevel@tonic-gate /*
13277c478bd9Sstevel@tonic-gate * Process the nominal case first: we've been given an actual
13287c478bd9Sstevel@tonic-gate * size argument, rather than the literal "all"
13297c478bd9Sstevel@tonic-gate */
13307c478bd9Sstevel@tonic-gate
13317c478bd9Sstevel@tonic-gate if (len != 0) {
13327c478bd9Sstevel@tonic-gate
13337c478bd9Sstevel@tonic-gate /*
13347c478bd9Sstevel@tonic-gate * Short circuit the check for free space. This may
13357c478bd9Sstevel@tonic-gate * tell us we have enough space when we really don't
13367c478bd9Sstevel@tonic-gate * because each extent loses space to a watermark, but
13377c478bd9Sstevel@tonic-gate * it will always tell us there isn't enough space
13387c478bd9Sstevel@tonic-gate * correctly. Worst case we do some extra work.
13397c478bd9Sstevel@tonic-gate */
13407c478bd9Sstevel@tonic-gate freespace = meta_sp_list_size(*head, EXTTYP_FREE,
13417c478bd9Sstevel@tonic-gate INCLUDE_WM);
13427c478bd9Sstevel@tonic-gate
13437c478bd9Sstevel@tonic-gate if (freespace < len)
13447c478bd9Sstevel@tonic-gate return (-1);
13457c478bd9Sstevel@tonic-gate
13467c478bd9Sstevel@tonic-gate /*
13477c478bd9Sstevel@tonic-gate * First see if we can extend the last extent for an
13487c478bd9Sstevel@tonic-gate * attach.
13497c478bd9Sstevel@tonic-gate */
13507c478bd9Sstevel@tonic-gate if (last_off != 0LL) {
13517c478bd9Sstevel@tonic-gate int align = 0;
13527c478bd9Sstevel@tonic-gate
13537c478bd9Sstevel@tonic-gate alloc_ext =
13547c478bd9Sstevel@tonic-gate meta_sp_list_find(*head, last_off);
13557c478bd9Sstevel@tonic-gate assert(alloc_ext != NULL);
13567c478bd9Sstevel@tonic-gate
13577c478bd9Sstevel@tonic-gate /*
13587c478bd9Sstevel@tonic-gate * The offset test reflects the
13597c478bd9Sstevel@tonic-gate * inclusion of the watermark in the extent
13607c478bd9Sstevel@tonic-gate */
13617c478bd9Sstevel@tonic-gate align = (alignment > 0) &&
13627c478bd9Sstevel@tonic-gate (((alloc_ext->ext_offset + MD_SP_WMSIZE) %
13637c478bd9Sstevel@tonic-gate alignment) == 0);
13647c478bd9Sstevel@tonic-gate
13657c478bd9Sstevel@tonic-gate /*
13667c478bd9Sstevel@tonic-gate * If we decided not to align here, we should
13677c478bd9Sstevel@tonic-gate * also reset "alignment" so we don't bother
13687c478bd9Sstevel@tonic-gate * later, either.
13697c478bd9Sstevel@tonic-gate */
13707c478bd9Sstevel@tonic-gate if (!align) {
13717c478bd9Sstevel@tonic-gate alignment = 0;
13727c478bd9Sstevel@tonic-gate }
13737c478bd9Sstevel@tonic-gate
13747c478bd9Sstevel@tonic-gate last_seq = alloc_ext->ext_seq;
13757c478bd9Sstevel@tonic-gate
13767c478bd9Sstevel@tonic-gate free_ext = meta_sp_list_find(*head,
13777c478bd9Sstevel@tonic-gate alloc_ext->ext_offset +
13787c478bd9Sstevel@tonic-gate alloc_ext->ext_length);
13797c478bd9Sstevel@tonic-gate
13807c478bd9Sstevel@tonic-gate /*
13817c478bd9Sstevel@tonic-gate * If a free extent follows our last allocated
13827c478bd9Sstevel@tonic-gate * extent, then remove the last allocated
13837c478bd9Sstevel@tonic-gate * extent and increase the size of the free
13847c478bd9Sstevel@tonic-gate * extent to overlap it, then allocate the
13857c478bd9Sstevel@tonic-gate * total space from the new free extent.
13867c478bd9Sstevel@tonic-gate */
13877c478bd9Sstevel@tonic-gate if (free_ext != NULL &&
13887c478bd9Sstevel@tonic-gate free_ext->ext_type == EXTTYP_FREE) {
13897c478bd9Sstevel@tonic-gate assert(free_ext->ext_offset ==
13907c478bd9Sstevel@tonic-gate alloc_ext->ext_offset +
13917c478bd9Sstevel@tonic-gate alloc_ext->ext_length);
13927c478bd9Sstevel@tonic-gate
13937c478bd9Sstevel@tonic-gate alloc_len =
13947c478bd9Sstevel@tonic-gate MIN(len, free_ext->ext_length);
13957c478bd9Sstevel@tonic-gate
13967c478bd9Sstevel@tonic-gate if (align && (alloc_len < len)) {
13977c478bd9Sstevel@tonic-gate /* No watermark space needed */
13987c478bd9Sstevel@tonic-gate alloc_len -= alloc_len % alignment;
13997c478bd9Sstevel@tonic-gate }
14007c478bd9Sstevel@tonic-gate
14017c478bd9Sstevel@tonic-gate if (alloc_len > 0) {
14027c478bd9Sstevel@tonic-gate free_ext->ext_offset -=
14037c478bd9Sstevel@tonic-gate alloc_ext->ext_length;
14047c478bd9Sstevel@tonic-gate free_ext->ext_length +=
14057c478bd9Sstevel@tonic-gate alloc_ext->ext_length;
14067c478bd9Sstevel@tonic-gate
14077c478bd9Sstevel@tonic-gate meta_sp_alloc_by_ext(sp, np, head,
14087c478bd9Sstevel@tonic-gate free_ext, free_ext->ext_offset,
14097c478bd9Sstevel@tonic-gate alloc_ext->ext_length + alloc_len,
14107c478bd9Sstevel@tonic-gate last_seq);
14117c478bd9Sstevel@tonic-gate
14127c478bd9Sstevel@tonic-gate /*
14137c478bd9Sstevel@tonic-gate * now remove the original allocated
14147c478bd9Sstevel@tonic-gate * node. We may have overlapping
14157c478bd9Sstevel@tonic-gate * extents for a short time before
14167c478bd9Sstevel@tonic-gate * this node is removed.
14177c478bd9Sstevel@tonic-gate */
14187c478bd9Sstevel@tonic-gate meta_sp_list_remove(head, alloc_ext);
14197c478bd9Sstevel@tonic-gate len -= alloc_len;
14207c478bd9Sstevel@tonic-gate }
14217c478bd9Sstevel@tonic-gate }
14227c478bd9Sstevel@tonic-gate last_seq++;
14237c478bd9Sstevel@tonic-gate }
14247c478bd9Sstevel@tonic-gate
14257c478bd9Sstevel@tonic-gate if (len == 0LL)
14267c478bd9Sstevel@tonic-gate goto out;
14277c478bd9Sstevel@tonic-gate
14287c478bd9Sstevel@tonic-gate /*
14297c478bd9Sstevel@tonic-gate * Next, see if we can find a single allocation for
14307c478bd9Sstevel@tonic-gate * the remainder. This may make fragmentation worse
14317c478bd9Sstevel@tonic-gate * in some cases, but there's no good way to allocate
14327c478bd9Sstevel@tonic-gate * that doesn't have a highly fragmented corner case.
14337c478bd9Sstevel@tonic-gate */
14347c478bd9Sstevel@tonic-gate for (free_ext = *head; free_ext != NULL;
14357c478bd9Sstevel@tonic-gate free_ext = free_ext->ext_next) {
14367c478bd9Sstevel@tonic-gate sp_ext_offset_t a_offset;
14377c478bd9Sstevel@tonic-gate sp_ext_offset_t a_length;
14387c478bd9Sstevel@tonic-gate
14397c478bd9Sstevel@tonic-gate if (free_ext->ext_type != EXTTYP_FREE)
14407c478bd9Sstevel@tonic-gate continue;
14417c478bd9Sstevel@tonic-gate
14427c478bd9Sstevel@tonic-gate /*
14437c478bd9Sstevel@tonic-gate * The length test should include space for
14447c478bd9Sstevel@tonic-gate * the watermark
14457c478bd9Sstevel@tonic-gate */
14467c478bd9Sstevel@tonic-gate
14477c478bd9Sstevel@tonic-gate a_offset = free_ext->ext_offset;
14487c478bd9Sstevel@tonic-gate a_length = free_ext->ext_length;
14497c478bd9Sstevel@tonic-gate
14507c478bd9Sstevel@tonic-gate if (alignment > 0) {
14517c478bd9Sstevel@tonic-gate
14527c478bd9Sstevel@tonic-gate /*
14537c478bd9Sstevel@tonic-gate * Shortcut for extents that have been
14547c478bd9Sstevel@tonic-gate * previously added to pad out the
14557c478bd9Sstevel@tonic-gate * data space
14567c478bd9Sstevel@tonic-gate */
14577c478bd9Sstevel@tonic-gate if (a_length < alignment) {
14587c478bd9Sstevel@tonic-gate continue;
14597c478bd9Sstevel@tonic-gate }
14607c478bd9Sstevel@tonic-gate
14617c478bd9Sstevel@tonic-gate /*
14627c478bd9Sstevel@tonic-gate * Round up so the data space begins
14637c478bd9Sstevel@tonic-gate * on a properly aligned boundary.
14647c478bd9Sstevel@tonic-gate */
14657c478bd9Sstevel@tonic-gate a_offset += alignment -
14667c478bd9Sstevel@tonic-gate (a_offset % alignment) - MD_SP_WMSIZE;
14677c478bd9Sstevel@tonic-gate
14687c478bd9Sstevel@tonic-gate /*
14697c478bd9Sstevel@tonic-gate * This is only necessary in case the
14707c478bd9Sstevel@tonic-gate * watermark size is ever greater than
14717c478bd9Sstevel@tonic-gate * one. It'll never happen, of
14727c478bd9Sstevel@tonic-gate * course; we'll get rid of watermarks
14737c478bd9Sstevel@tonic-gate * before we make 'em bigger.
14747c478bd9Sstevel@tonic-gate */
14757c478bd9Sstevel@tonic-gate if (a_offset < free_ext->ext_offset) {
14767c478bd9Sstevel@tonic-gate a_offset += alignment;
14777c478bd9Sstevel@tonic-gate }
14787c478bd9Sstevel@tonic-gate
14797c478bd9Sstevel@tonic-gate /*
14807c478bd9Sstevel@tonic-gate * Adjust the length to account for
14817c478bd9Sstevel@tonic-gate * the space lost above (if any)
14827c478bd9Sstevel@tonic-gate */
14837c478bd9Sstevel@tonic-gate a_length -=
14847c478bd9Sstevel@tonic-gate (a_offset - free_ext->ext_offset);
14857c478bd9Sstevel@tonic-gate }
14867c478bd9Sstevel@tonic-gate
14877c478bd9Sstevel@tonic-gate if (a_length >= len + MD_SP_WMSIZE) {
14887c478bd9Sstevel@tonic-gate meta_sp_alloc_by_ext(sp, np, head,
14897c478bd9Sstevel@tonic-gate free_ext, a_offset,
14907c478bd9Sstevel@tonic-gate len + MD_SP_WMSIZE, last_seq);
14917c478bd9Sstevel@tonic-gate
14927c478bd9Sstevel@tonic-gate len = 0LL;
14937c478bd9Sstevel@tonic-gate numexts++;
14947c478bd9Sstevel@tonic-gate break;
14957c478bd9Sstevel@tonic-gate }
14967c478bd9Sstevel@tonic-gate }
14977c478bd9Sstevel@tonic-gate
14987c478bd9Sstevel@tonic-gate if (len == 0LL)
14997c478bd9Sstevel@tonic-gate goto out;
15007c478bd9Sstevel@tonic-gate
15017c478bd9Sstevel@tonic-gate
15027c478bd9Sstevel@tonic-gate /*
15037c478bd9Sstevel@tonic-gate * If the request could not be satisfied by extending
15047c478bd9Sstevel@tonic-gate * the last extent or by a single extent, then put
15057c478bd9Sstevel@tonic-gate * multiple smaller extents together until the request
15067c478bd9Sstevel@tonic-gate * is satisfied.
15077c478bd9Sstevel@tonic-gate */
15087c478bd9Sstevel@tonic-gate for (free_ext = *head; (free_ext != NULL) && (len > 0);
15097c478bd9Sstevel@tonic-gate free_ext = free_ext->ext_next) {
15107c478bd9Sstevel@tonic-gate sp_ext_offset_t a_offset;
15117c478bd9Sstevel@tonic-gate sp_ext_length_t a_length;
15127c478bd9Sstevel@tonic-gate
15137c478bd9Sstevel@tonic-gate if (free_ext->ext_type != EXTTYP_FREE)
15147c478bd9Sstevel@tonic-gate continue;
15157c478bd9Sstevel@tonic-gate
15167c478bd9Sstevel@tonic-gate a_offset = free_ext->ext_offset;
15177c478bd9Sstevel@tonic-gate a_length = free_ext->ext_length;
15187c478bd9Sstevel@tonic-gate
15197c478bd9Sstevel@tonic-gate if (alignment > 0) {
15207c478bd9Sstevel@tonic-gate
15217c478bd9Sstevel@tonic-gate /*
15227c478bd9Sstevel@tonic-gate * Shortcut for extents that have been
15237c478bd9Sstevel@tonic-gate * previously added to pad out the
15247c478bd9Sstevel@tonic-gate * data space
15257c478bd9Sstevel@tonic-gate */
15267c478bd9Sstevel@tonic-gate if (a_length < alignment) {
15277c478bd9Sstevel@tonic-gate continue;
15287c478bd9Sstevel@tonic-gate }
15297c478bd9Sstevel@tonic-gate
15307c478bd9Sstevel@tonic-gate /*
15317c478bd9Sstevel@tonic-gate * Round up so the data space begins
15327c478bd9Sstevel@tonic-gate * on a properly aligned boundary.
15337c478bd9Sstevel@tonic-gate */
15347c478bd9Sstevel@tonic-gate a_offset += alignment -
15357c478bd9Sstevel@tonic-gate (a_offset % alignment) - MD_SP_WMSIZE;
15367c478bd9Sstevel@tonic-gate
15377c478bd9Sstevel@tonic-gate /*
15387c478bd9Sstevel@tonic-gate * This is only necessary in case the
15397c478bd9Sstevel@tonic-gate * watermark size is ever greater than
15407c478bd9Sstevel@tonic-gate * one. It'll never happen, of
15417c478bd9Sstevel@tonic-gate * course; we'll get rid of watermarks
15427c478bd9Sstevel@tonic-gate * before we make 'em bigger.
15437c478bd9Sstevel@tonic-gate */
15447c478bd9Sstevel@tonic-gate if (a_offset < free_ext->ext_offset) {
15457c478bd9Sstevel@tonic-gate a_offset += alignment;
15467c478bd9Sstevel@tonic-gate }
15477c478bd9Sstevel@tonic-gate
15487c478bd9Sstevel@tonic-gate /*
15497c478bd9Sstevel@tonic-gate * Adjust the length to account for
15507c478bd9Sstevel@tonic-gate * the space lost above (if any)
15517c478bd9Sstevel@tonic-gate */
15527c478bd9Sstevel@tonic-gate a_length -=
15537c478bd9Sstevel@tonic-gate (a_offset - free_ext->ext_offset);
15547c478bd9Sstevel@tonic-gate
15557c478bd9Sstevel@tonic-gate /*
15567c478bd9Sstevel@tonic-gate * Adjust the length to be properly
15577c478bd9Sstevel@tonic-gate * aligned if it is NOT to be the
15587c478bd9Sstevel@tonic-gate * last extent in the soft partition.
15597c478bd9Sstevel@tonic-gate */
15607c478bd9Sstevel@tonic-gate if ((a_length - MD_SP_WMSIZE) < len)
15617c478bd9Sstevel@tonic-gate a_length -=
15627c478bd9Sstevel@tonic-gate (a_length - MD_SP_WMSIZE)
15637c478bd9Sstevel@tonic-gate % alignment;
15647c478bd9Sstevel@tonic-gate }
15657c478bd9Sstevel@tonic-gate
15667c478bd9Sstevel@tonic-gate alloc_len = MIN(len, a_length - MD_SP_WMSIZE);
15677c478bd9Sstevel@tonic-gate if (alloc_len == 0)
15687c478bd9Sstevel@tonic-gate continue;
15697c478bd9Sstevel@tonic-gate
15707c478bd9Sstevel@tonic-gate /*
15717c478bd9Sstevel@tonic-gate * meta_sp_alloc_by_ext() expects the
15727c478bd9Sstevel@tonic-gate * allocation length to include the watermark
15737c478bd9Sstevel@tonic-gate * size, which is why we don't simply pass in
15747c478bd9Sstevel@tonic-gate * alloc_len here.
15757c478bd9Sstevel@tonic-gate */
15767c478bd9Sstevel@tonic-gate meta_sp_alloc_by_ext(sp, np, head, free_ext,
15777c478bd9Sstevel@tonic-gate a_offset, MIN(len + MD_SP_WMSIZE, a_length),
15787c478bd9Sstevel@tonic-gate last_seq);
15797c478bd9Sstevel@tonic-gate
15807c478bd9Sstevel@tonic-gate len -= alloc_len;
15817c478bd9Sstevel@tonic-gate numexts++;
15827c478bd9Sstevel@tonic-gate last_seq++;
15837c478bd9Sstevel@tonic-gate }
15847c478bd9Sstevel@tonic-gate
15857c478bd9Sstevel@tonic-gate
15867c478bd9Sstevel@tonic-gate /*
15877c478bd9Sstevel@tonic-gate * If there was not enough space we can throw it all
15887c478bd9Sstevel@tonic-gate * away since no real work has been done yet.
15897c478bd9Sstevel@tonic-gate */
15907c478bd9Sstevel@tonic-gate if (len != 0) {
15917c478bd9Sstevel@tonic-gate meta_sp_list_free(head);
15927c478bd9Sstevel@tonic-gate return (-1);
15937c478bd9Sstevel@tonic-gate }
15947c478bd9Sstevel@tonic-gate }
15957c478bd9Sstevel@tonic-gate
15967c478bd9Sstevel@tonic-gate /*
15977c478bd9Sstevel@tonic-gate * Otherwise, the literal "all" was specified: allocate all
15987c478bd9Sstevel@tonic-gate * available free space. Don't bother with alignment.
15997c478bd9Sstevel@tonic-gate */
16007c478bd9Sstevel@tonic-gate else {
16017c478bd9Sstevel@tonic-gate /* First, extend the last extent if this is a grow */
16027c478bd9Sstevel@tonic-gate if (last_off != 0LL) {
16037c478bd9Sstevel@tonic-gate alloc_ext =
16047c478bd9Sstevel@tonic-gate meta_sp_list_find(*head, last_off);
16057c478bd9Sstevel@tonic-gate assert(alloc_ext != NULL);
16067c478bd9Sstevel@tonic-gate
16077c478bd9Sstevel@tonic-gate last_seq = alloc_ext->ext_seq;
16087c478bd9Sstevel@tonic-gate
16097c478bd9Sstevel@tonic-gate free_ext = meta_sp_list_find(*head,
16107c478bd9Sstevel@tonic-gate alloc_ext->ext_offset +
16117c478bd9Sstevel@tonic-gate alloc_ext->ext_length);
16127c478bd9Sstevel@tonic-gate
16137c478bd9Sstevel@tonic-gate /*
16147c478bd9Sstevel@tonic-gate * If a free extent follows our last allocated
16157c478bd9Sstevel@tonic-gate * extent, then remove the last allocated
16167c478bd9Sstevel@tonic-gate * extent and increase the size of the free
16177c478bd9Sstevel@tonic-gate * extent to overlap it, then allocate the
16187c478bd9Sstevel@tonic-gate * total space from the new free extent.
16197c478bd9Sstevel@tonic-gate */
16207c478bd9Sstevel@tonic-gate if (free_ext != NULL &&
16217c478bd9Sstevel@tonic-gate free_ext->ext_type == EXTTYP_FREE) {
16227c478bd9Sstevel@tonic-gate assert(free_ext->ext_offset ==
16237c478bd9Sstevel@tonic-gate alloc_ext->ext_offset +
16247c478bd9Sstevel@tonic-gate alloc_ext->ext_length);
16257c478bd9Sstevel@tonic-gate
16267c478bd9Sstevel@tonic-gate len = alloc_len =
16277c478bd9Sstevel@tonic-gate free_ext->ext_length;
16287c478bd9Sstevel@tonic-gate
16297c478bd9Sstevel@tonic-gate free_ext->ext_offset -=
16307c478bd9Sstevel@tonic-gate alloc_ext->ext_length;
16317c478bd9Sstevel@tonic-gate free_ext->ext_length +=
16327c478bd9Sstevel@tonic-gate alloc_ext->ext_length;
16337c478bd9Sstevel@tonic-gate
16347c478bd9Sstevel@tonic-gate meta_sp_alloc_by_ext(sp, np, head,
16357c478bd9Sstevel@tonic-gate free_ext, free_ext->ext_offset,
16367c478bd9Sstevel@tonic-gate alloc_ext->ext_length + alloc_len,
16377c478bd9Sstevel@tonic-gate last_seq);
16387c478bd9Sstevel@tonic-gate
16397c478bd9Sstevel@tonic-gate /*
16407c478bd9Sstevel@tonic-gate * now remove the original allocated
16417c478bd9Sstevel@tonic-gate * node. We may have overlapping
16427c478bd9Sstevel@tonic-gate * extents for a short time before
16437c478bd9Sstevel@tonic-gate * this node is removed.
16447c478bd9Sstevel@tonic-gate */
16457c478bd9Sstevel@tonic-gate meta_sp_list_remove(head, alloc_ext);
16467c478bd9Sstevel@tonic-gate }
16477c478bd9Sstevel@tonic-gate
16487c478bd9Sstevel@tonic-gate last_seq++;
16497c478bd9Sstevel@tonic-gate }
16507c478bd9Sstevel@tonic-gate
16517c478bd9Sstevel@tonic-gate /* Next, grab all remaining free space */
16527c478bd9Sstevel@tonic-gate for (free_ext = *head; free_ext != NULL;
16537c478bd9Sstevel@tonic-gate free_ext = free_ext->ext_next) {
16547c478bd9Sstevel@tonic-gate
16557c478bd9Sstevel@tonic-gate if (free_ext->ext_type == EXTTYP_FREE) {
16567c478bd9Sstevel@tonic-gate alloc_len =
16577c478bd9Sstevel@tonic-gate free_ext->ext_length - MD_SP_WMSIZE;
16587c478bd9Sstevel@tonic-gate if (alloc_len == 0)
16597c478bd9Sstevel@tonic-gate continue;
16607c478bd9Sstevel@tonic-gate
16617c478bd9Sstevel@tonic-gate /*
16627c478bd9Sstevel@tonic-gate * meta_sp_alloc_by_ext() expects the
16637c478bd9Sstevel@tonic-gate * allocation length to include the
16647c478bd9Sstevel@tonic-gate * watermark size, which is why we
16657c478bd9Sstevel@tonic-gate * don't simply pass in alloc_len
16667c478bd9Sstevel@tonic-gate * here.
16677c478bd9Sstevel@tonic-gate */
16687c478bd9Sstevel@tonic-gate meta_sp_alloc_by_ext(sp, np, head,
16697c478bd9Sstevel@tonic-gate free_ext, free_ext->ext_offset,
16707c478bd9Sstevel@tonic-gate free_ext->ext_length,
16717c478bd9Sstevel@tonic-gate last_seq);
16727c478bd9Sstevel@tonic-gate
16737c478bd9Sstevel@tonic-gate len += alloc_len;
16747c478bd9Sstevel@tonic-gate numexts++;
16757c478bd9Sstevel@tonic-gate last_seq++;
16767c478bd9Sstevel@tonic-gate }
16777c478bd9Sstevel@tonic-gate }
16787c478bd9Sstevel@tonic-gate }
16797c478bd9Sstevel@tonic-gate
16807c478bd9Sstevel@tonic-gate out:
16817c478bd9Sstevel@tonic-gate if (getenv(META_SP_DEBUG)) {
16827c478bd9Sstevel@tonic-gate meta_sp_debug("meta_sp_alloc_by_len: Extent list after "
16837c478bd9Sstevel@tonic-gate "allocation:\n");
16847c478bd9Sstevel@tonic-gate meta_sp_list_dump(*head);
16857c478bd9Sstevel@tonic-gate }
16867c478bd9Sstevel@tonic-gate
16877c478bd9Sstevel@tonic-gate if (*lp == 0) {
16887c478bd9Sstevel@tonic-gate *lp = len;
16897c478bd9Sstevel@tonic-gate
16907c478bd9Sstevel@tonic-gate /*
16917c478bd9Sstevel@tonic-gate * Make sure the callers hit a no space error if we
16927c478bd9Sstevel@tonic-gate * didn't actually find anything.
16937c478bd9Sstevel@tonic-gate */
16947c478bd9Sstevel@tonic-gate if (len == 0) {
16957c478bd9Sstevel@tonic-gate return (-1);
16967c478bd9Sstevel@tonic-gate }
16977c478bd9Sstevel@tonic-gate }
16987c478bd9Sstevel@tonic-gate
16997c478bd9Sstevel@tonic-gate return (numexts);
17007c478bd9Sstevel@tonic-gate }
17017c478bd9Sstevel@tonic-gate
17027c478bd9Sstevel@tonic-gate /*
17037c478bd9Sstevel@tonic-gate * FUNCTION: meta_sp_alloc_by_list()
17047c478bd9Sstevel@tonic-gate * INPUT: sp - the set name for the device the node belongs to
17057c478bd9Sstevel@tonic-gate * np - the name of the device the node belongs to
17067c478bd9Sstevel@tonic-gate * head - the head of the list, must be NULL for empty list
17077c478bd9Sstevel@tonic-gate * oblist - an extent list containing requested nodes to allocate
17087c478bd9Sstevel@tonic-gate * OUTPUT: head - the new head pointer
17097c478bd9Sstevel@tonic-gate * RETURNS: int - -1 if error, the number of new extents on success
17107c478bd9Sstevel@tonic-gate * PURPOSE: allocates extents from free space to satisfy the requested
17117c478bd9Sstevel@tonic-gate * extent list. This is primarily used for the -o/-b options
17127c478bd9Sstevel@tonic-gate * where the user may specifically request extents to allocate.
17137c478bd9Sstevel@tonic-gate * Each extent in the oblist must be a subset (inclusive) of a
17147c478bd9Sstevel@tonic-gate * free extent and may not overlap each other. This
17157c478bd9Sstevel@tonic-gate * function sets the EXTFLG_UPDATE flag for each node that
17167c478bd9Sstevel@tonic-gate * requires a watermark update after allocating.
17177c478bd9Sstevel@tonic-gate */
17187c478bd9Sstevel@tonic-gate static int
meta_sp_alloc_by_list(mdsetname_t * sp,mdname_t * np,sp_ext_node_t ** head,sp_ext_node_t * oblist)17197c478bd9Sstevel@tonic-gate meta_sp_alloc_by_list(
17207c478bd9Sstevel@tonic-gate mdsetname_t *sp,
17217c478bd9Sstevel@tonic-gate mdname_t *np,
17227c478bd9Sstevel@tonic-gate sp_ext_node_t **head,
17237c478bd9Sstevel@tonic-gate sp_ext_node_t *oblist
17247c478bd9Sstevel@tonic-gate )
17257c478bd9Sstevel@tonic-gate {
17267c478bd9Sstevel@tonic-gate sp_ext_node_t *ext;
17277c478bd9Sstevel@tonic-gate sp_ext_node_t *free_ext;
17287c478bd9Sstevel@tonic-gate uint_t numexts = 0;
17297c478bd9Sstevel@tonic-gate
17307c478bd9Sstevel@tonic-gate for (ext = oblist; ext != NULL; ext = ext->ext_next) {
17317c478bd9Sstevel@tonic-gate
17327c478bd9Sstevel@tonic-gate free_ext = meta_sp_list_find(*head,
17337c478bd9Sstevel@tonic-gate ext->ext_offset - MD_SP_WMSIZE);
17347c478bd9Sstevel@tonic-gate
17357c478bd9Sstevel@tonic-gate /* Make sure the allocation is within the free extent */
17367c478bd9Sstevel@tonic-gate if ((free_ext == NULL) ||
17377c478bd9Sstevel@tonic-gate (ext->ext_offset + ext->ext_length >
17387c478bd9Sstevel@tonic-gate free_ext->ext_offset + free_ext->ext_length) ||
17397c478bd9Sstevel@tonic-gate (free_ext->ext_type != EXTTYP_FREE))
17407c478bd9Sstevel@tonic-gate return (-1);
17417c478bd9Sstevel@tonic-gate
17427c478bd9Sstevel@tonic-gate meta_sp_alloc_by_ext(sp, np, head, free_ext,
17437c478bd9Sstevel@tonic-gate ext->ext_offset - MD_SP_WMSIZE,
17447c478bd9Sstevel@tonic-gate ext->ext_length + MD_SP_WMSIZE, ext->ext_seq);
17457c478bd9Sstevel@tonic-gate
17467c478bd9Sstevel@tonic-gate numexts++;
17477c478bd9Sstevel@tonic-gate }
17487c478bd9Sstevel@tonic-gate
17497c478bd9Sstevel@tonic-gate assert(meta_sp_list_overlaps(*head) == 0);
17507c478bd9Sstevel@tonic-gate
17517c478bd9Sstevel@tonic-gate if (getenv(META_SP_DEBUG)) {
17527c478bd9Sstevel@tonic-gate meta_sp_debug("meta_sp_alloc_by_list: Extent list after "
17537c478bd9Sstevel@tonic-gate "allocation:\n");
17547c478bd9Sstevel@tonic-gate meta_sp_list_dump(*head);
17557c478bd9Sstevel@tonic-gate }
17567c478bd9Sstevel@tonic-gate
17577c478bd9Sstevel@tonic-gate return (numexts);
17587c478bd9Sstevel@tonic-gate }
17597c478bd9Sstevel@tonic-gate
17607c478bd9Sstevel@tonic-gate /*
17617c478bd9Sstevel@tonic-gate * **************************************************************************
17627c478bd9Sstevel@tonic-gate * Extent List Population Functions *
17637c478bd9Sstevel@tonic-gate * **************************************************************************
17647c478bd9Sstevel@tonic-gate */
17657c478bd9Sstevel@tonic-gate
17667c478bd9Sstevel@tonic-gate /*
17677c478bd9Sstevel@tonic-gate * FUNCTION: meta_sp_extlist_from_namelist()
17687c478bd9Sstevel@tonic-gate * INPUT: sp - the set name for the device the node belongs to
17697c478bd9Sstevel@tonic-gate * spnplp - the namelist of soft partitions to build a list from
17707c478bd9Sstevel@tonic-gate * OUTPUT: extlist - the extent list built from the SPs in the namelist
17717c478bd9Sstevel@tonic-gate * ep - return error pointer
17727c478bd9Sstevel@tonic-gate * RETURNS: int - -1 if error, 0 on success
17737c478bd9Sstevel@tonic-gate * PURPOSE: builds an extent list representing the soft partitions
17747c478bd9Sstevel@tonic-gate * specified in the namelist. Each extent in each soft
17757c478bd9Sstevel@tonic-gate * partition is added to the list with the type EXTTYP_ALLOC.
17767c478bd9Sstevel@tonic-gate * The EXTFLG_UPDATE flag is not set on any nodes. Each
17777c478bd9Sstevel@tonic-gate * extent in the list includes the space occupied by the
17787c478bd9Sstevel@tonic-gate * watermark, which is not included in the unit structures.
17797c478bd9Sstevel@tonic-gate */
17807c478bd9Sstevel@tonic-gate static int
meta_sp_extlist_from_namelist(mdsetname_t * sp,mdnamelist_t * spnlp,sp_ext_node_t ** extlist,md_error_t * ep)17817c478bd9Sstevel@tonic-gate meta_sp_extlist_from_namelist(
17827c478bd9Sstevel@tonic-gate mdsetname_t *sp,
17837c478bd9Sstevel@tonic-gate mdnamelist_t *spnlp,
17847c478bd9Sstevel@tonic-gate sp_ext_node_t **extlist,
17857c478bd9Sstevel@tonic-gate md_error_t *ep
17867c478bd9Sstevel@tonic-gate )
17877c478bd9Sstevel@tonic-gate {
17887c478bd9Sstevel@tonic-gate int extn;
17897c478bd9Sstevel@tonic-gate md_sp_t *msp; /* unit structure of the sp's */
17907c478bd9Sstevel@tonic-gate mdnamelist_t *namep;
17917c478bd9Sstevel@tonic-gate
17927c478bd9Sstevel@tonic-gate assert(sp != NULL);
17937c478bd9Sstevel@tonic-gate
17947c478bd9Sstevel@tonic-gate /*
17957c478bd9Sstevel@tonic-gate * Now go through the soft partitions and add a node to the used
17967c478bd9Sstevel@tonic-gate * list for each allocated extent.
17977c478bd9Sstevel@tonic-gate */
17987c478bd9Sstevel@tonic-gate for (namep = spnlp; namep != NULL; namep = namep->next) {
17997c478bd9Sstevel@tonic-gate mdname_t *curnp = namep->namep;
18007c478bd9Sstevel@tonic-gate
18017c478bd9Sstevel@tonic-gate /* get the unit structure */
18027c478bd9Sstevel@tonic-gate if ((msp = meta_get_sp_common(sp, curnp, 0, ep)) == NULL)
18037c478bd9Sstevel@tonic-gate return (-1);
18047c478bd9Sstevel@tonic-gate
18057c478bd9Sstevel@tonic-gate for (extn = 0; (extn < msp->ext.ext_len); extn++) {
18067c478bd9Sstevel@tonic-gate md_sp_ext_t *extp = &msp->ext.ext_val[extn];
18077c478bd9Sstevel@tonic-gate
18087c478bd9Sstevel@tonic-gate /*
18097c478bd9Sstevel@tonic-gate * subtract from offset and add to the length
18107c478bd9Sstevel@tonic-gate * to account for the watermark, which is not
18117c478bd9Sstevel@tonic-gate * contained in the extents in the unit structure.
18127c478bd9Sstevel@tonic-gate */
18137c478bd9Sstevel@tonic-gate meta_sp_list_insert(sp, curnp, extlist,
18147c478bd9Sstevel@tonic-gate extp->poff - MD_SP_WMSIZE, extp->len + MD_SP_WMSIZE,
18157c478bd9Sstevel@tonic-gate EXTTYP_ALLOC, extn, 0, meta_sp_cmp_by_offset);
18167c478bd9Sstevel@tonic-gate }
18177c478bd9Sstevel@tonic-gate }
18187c478bd9Sstevel@tonic-gate return (0);
18197c478bd9Sstevel@tonic-gate }
18207c478bd9Sstevel@tonic-gate
18217c478bd9Sstevel@tonic-gate /*
18227c478bd9Sstevel@tonic-gate * FUNCTION: meta_sp_extlist_from_wm()
18237c478bd9Sstevel@tonic-gate * INPUT: sp - the set name for the device the node belongs to
18247c478bd9Sstevel@tonic-gate * compnp - the name of the device to scan watermarks on
18257c478bd9Sstevel@tonic-gate * OUTPUT: extlist - the extent list built from the SPs in the namelist
18267c478bd9Sstevel@tonic-gate * ep - return error pointer
18277c478bd9Sstevel@tonic-gate * RETURNS: int - -1 if error, 0 on success
18287c478bd9Sstevel@tonic-gate * PURPOSE: builds an extent list representing the soft partitions
18297c478bd9Sstevel@tonic-gate * specified in the namelist. Each extent in each soft
18307c478bd9Sstevel@tonic-gate * partition is added to the list with the type EXTTYP_ALLOC.
18317c478bd9Sstevel@tonic-gate * The EXTFLG_UPDATE flag is not set on any nodes. Each
18327c478bd9Sstevel@tonic-gate * extent in the list includes the space occupied by the
18337c478bd9Sstevel@tonic-gate * watermark, which is not included in the unit structures.
18347c478bd9Sstevel@tonic-gate */
18357c478bd9Sstevel@tonic-gate static int
meta_sp_extlist_from_wm(mdsetname_t * sp,mdname_t * compnp,sp_ext_node_t ** extlist,ext_cmpfunc_t compare,md_error_t * ep)18367c478bd9Sstevel@tonic-gate meta_sp_extlist_from_wm(
18377c478bd9Sstevel@tonic-gate mdsetname_t *sp,
18387c478bd9Sstevel@tonic-gate mdname_t *compnp,
18397c478bd9Sstevel@tonic-gate sp_ext_node_t **extlist,
18407c478bd9Sstevel@tonic-gate ext_cmpfunc_t compare,
18417c478bd9Sstevel@tonic-gate md_error_t *ep
18427c478bd9Sstevel@tonic-gate )
18437c478bd9Sstevel@tonic-gate {
18447c478bd9Sstevel@tonic-gate mp_watermark_t wm;
18457c478bd9Sstevel@tonic-gate mdname_t *np = NULL;
18467c478bd9Sstevel@tonic-gate mdsetname_t *spsetp = NULL;
18477c478bd9Sstevel@tonic-gate sp_ext_offset_t cur_off;
1848d7cd8252Stw21770 md_set_desc *sd;
1849d7cd8252Stw21770 int init = 0;
1850d7cd8252Stw21770 mdkey_t key;
1851d7cd8252Stw21770 minor_t mnum;
1852d7cd8252Stw21770
1853d7cd8252Stw21770 if (!metaislocalset(sp)) {
1854d7cd8252Stw21770 if ((sd = metaget_setdesc(sp, ep)) == NULL)
1855d7cd8252Stw21770 return (-1);
1856d7cd8252Stw21770 }
18577c478bd9Sstevel@tonic-gate
18587c478bd9Sstevel@tonic-gate if ((cur_off = meta_sp_get_start(sp, compnp, ep)) == MD_DISKADDR_ERROR)
18597c478bd9Sstevel@tonic-gate return (-1);
18607c478bd9Sstevel@tonic-gate
18617c478bd9Sstevel@tonic-gate for (;;) {
18627c478bd9Sstevel@tonic-gate if (meta_sp_read_wm(sp, compnp, &wm, cur_off, ep) != 0) {
18637c478bd9Sstevel@tonic-gate return (-1);
18647c478bd9Sstevel@tonic-gate }
18657c478bd9Sstevel@tonic-gate
18667c478bd9Sstevel@tonic-gate /* get the set and name pointers */
18677c478bd9Sstevel@tonic-gate if (strcmp(wm.wm_setname, MD_SP_LOCALSETNAME) != 0) {
18687c478bd9Sstevel@tonic-gate if ((spsetp = metasetname(wm.wm_setname, ep)) == NULL) {
18697c478bd9Sstevel@tonic-gate return (-1);
18707c478bd9Sstevel@tonic-gate }
18717c478bd9Sstevel@tonic-gate }
18727c478bd9Sstevel@tonic-gate
1873d7cd8252Stw21770 /*
1874d7cd8252Stw21770 * For the MN set, meta_init_make_device needs to
1875d7cd8252Stw21770 * be run on all the nodes so the entries for the
1876d7cd8252Stw21770 * softpart device name and its comp can be created
1877d7cd8252Stw21770 * in the same order in the replica namespace. If
1878d7cd8252Stw21770 * we have it run on mdmn_do_iocset then the mddbs
1879d7cd8252Stw21770 * will be out of sync between master node and slave
1880d7cd8252Stw21770 * nodes.
1881d7cd8252Stw21770 */
18827c478bd9Sstevel@tonic-gate if (strcmp(wm.wm_mdname, MD_SP_FREEWMNAME) != 0) {
1883d7cd8252Stw21770
1884d7cd8252Stw21770 if (!metaislocalset(sp) && MD_MNSET_DESC(sd)) {
1885d7cd8252Stw21770 md_mn_msg_addmdname_t *send_params;
1886d7cd8252Stw21770 int result;
1887d7cd8252Stw21770 md_mn_result_t *resp = NULL;
1888d7cd8252Stw21770 int message_size;
1889d7cd8252Stw21770
1890d7cd8252Stw21770 message_size = sizeof (*send_params) +
1891d7cd8252Stw21770 strlen(wm.wm_mdname) + 1;
1892d7cd8252Stw21770 send_params = Zalloc(message_size);
1893d7cd8252Stw21770 send_params->addmdname_setno = sp->setno;
1894d7cd8252Stw21770 (void) strcpy(&send_params->addmdname_name[0],
1895d7cd8252Stw21770 wm.wm_mdname);
1896d7cd8252Stw21770 result = mdmn_send_message(sp->setno,
1897d7cd8252Stw21770 MD_MN_MSG_ADDMDNAME,
1898bf85a12bSJohn Wren Kennedy MD_MSGF_PANIC_WHEN_INCONSISTENT, 0,
1899d7cd8252Stw21770 (char *)send_params, message_size, &resp,
1900d7cd8252Stw21770 ep);
1901d7cd8252Stw21770 Free(send_params);
1902d7cd8252Stw21770 if (resp != NULL) {
1903d7cd8252Stw21770 if (resp->mmr_exitval != 0) {
1904d7cd8252Stw21770 free_result(resp);
19057c478bd9Sstevel@tonic-gate return (-1);
1906d7cd8252Stw21770 }
1907d7cd8252Stw21770 free_result(resp);
1908d7cd8252Stw21770 }
1909d7cd8252Stw21770 if (result != 0)
1910d7cd8252Stw21770 return (-1);
1911d7cd8252Stw21770 } else {
1912d7cd8252Stw21770
1913d7cd8252Stw21770 if (!is_existing_meta_hsp(sp, wm.wm_mdname)) {
1914d7cd8252Stw21770 if ((key = meta_init_make_device(&sp,
1915d7cd8252Stw21770 wm.wm_mdname, ep)) <= 0) {
1916d7cd8252Stw21770 return (-1);
1917d7cd8252Stw21770 }
1918d7cd8252Stw21770 init = 1;
1919d7cd8252Stw21770 }
1920d7cd8252Stw21770 }
1921d7cd8252Stw21770
1922d7cd8252Stw21770 np = metaname(&spsetp, wm.wm_mdname, META_DEVICE, ep);
19237c478bd9Sstevel@tonic-gate if (np == NULL) {
1924d7cd8252Stw21770 if (init) {
19251cd3f00bSsk102515 if (meta_getnmentbykey(sp->setno,
19261cd3f00bSsk102515 MD_SIDEWILD, key, NULL, &mnum,
19271cd3f00bSsk102515 NULL, ep) != NULL) {
19281cd3f00bSsk102515 (void) metaioctl(MD_IOCREM_DEV,
19291cd3f00bSsk102515 &mnum, ep, NULL);
1930d7cd8252Stw21770 }
1931d7cd8252Stw21770 (void) del_self_name(sp, key, ep);
1932d7cd8252Stw21770 }
19337c478bd9Sstevel@tonic-gate return (-1);
19347c478bd9Sstevel@tonic-gate }
19357c478bd9Sstevel@tonic-gate }
19367c478bd9Sstevel@tonic-gate
19377c478bd9Sstevel@tonic-gate /* insert watermark into extent list */
19387c478bd9Sstevel@tonic-gate meta_sp_list_insert(spsetp, np, extlist, cur_off,
19397c478bd9Sstevel@tonic-gate wm.wm_length + MD_SP_WMSIZE, wm.wm_type, wm.wm_seq,
19407c478bd9Sstevel@tonic-gate EXTFLG_UPDATE, compare);
19417c478bd9Sstevel@tonic-gate
19427c478bd9Sstevel@tonic-gate /* if we see the end watermark, we're done */
19437c478bd9Sstevel@tonic-gate if (wm.wm_type == EXTTYP_END)
19447c478bd9Sstevel@tonic-gate break;
19457c478bd9Sstevel@tonic-gate
19467c478bd9Sstevel@tonic-gate cur_off += wm.wm_length + 1;
19477c478bd9Sstevel@tonic-gate
19487c478bd9Sstevel@tonic-gate /* clear out set and name pointers for next iteration */
19497c478bd9Sstevel@tonic-gate np = NULL;
19507c478bd9Sstevel@tonic-gate spsetp = NULL;
19517c478bd9Sstevel@tonic-gate }
19527c478bd9Sstevel@tonic-gate
19537c478bd9Sstevel@tonic-gate return (0);
19547c478bd9Sstevel@tonic-gate }
19557c478bd9Sstevel@tonic-gate
19567c478bd9Sstevel@tonic-gate /*
19577c478bd9Sstevel@tonic-gate * **************************************************************************
19587c478bd9Sstevel@tonic-gate * Print (metastat) Functions *
19597c478bd9Sstevel@tonic-gate * **************************************************************************
19607c478bd9Sstevel@tonic-gate */
19617c478bd9Sstevel@tonic-gate
19627c478bd9Sstevel@tonic-gate /*
19637c478bd9Sstevel@tonic-gate * FUNCTION: meta_sp_short_print()
19647c478bd9Sstevel@tonic-gate * INPUT: msp - the unit structure to display
19657c478bd9Sstevel@tonic-gate * fp - the file pointer to send output to
19667c478bd9Sstevel@tonic-gate * options - print options from the command line processor
19677c478bd9Sstevel@tonic-gate * OUTPUT: ep - return error pointer
19687c478bd9Sstevel@tonic-gate * RETURNS: int - -1 if error, 0 on success
19697c478bd9Sstevel@tonic-gate * PURPOSE: display a short report of the soft partition in md.tab
19707c478bd9Sstevel@tonic-gate * form, primarily used for metastat -p.
19717c478bd9Sstevel@tonic-gate */
19727c478bd9Sstevel@tonic-gate static int
meta_sp_short_print(md_sp_t * msp,char * fname,FILE * fp,mdprtopts_t options,md_error_t * ep)19737c478bd9Sstevel@tonic-gate meta_sp_short_print(
19747c478bd9Sstevel@tonic-gate md_sp_t *msp,
19757c478bd9Sstevel@tonic-gate char *fname,
19767c478bd9Sstevel@tonic-gate FILE *fp,
19777c478bd9Sstevel@tonic-gate mdprtopts_t options,
19787c478bd9Sstevel@tonic-gate md_error_t *ep
19797c478bd9Sstevel@tonic-gate )
19807c478bd9Sstevel@tonic-gate {
19817c478bd9Sstevel@tonic-gate int extn;
19827c478bd9Sstevel@tonic-gate
19837c478bd9Sstevel@tonic-gate if (options & PRINT_LARGEDEVICES) {
1984d7cd8252Stw21770 if ((msp->common.revision & MD_64BIT_META_DEV) == 0)
1985d7cd8252Stw21770 return (0);
1986d7cd8252Stw21770 }
1987d7cd8252Stw21770
1988d7cd8252Stw21770 if (options & PRINT_FN) {
1989d7cd8252Stw21770 if ((msp->common.revision & MD_FN_META_DEV) == 0)
19907c478bd9Sstevel@tonic-gate return (0);
19917c478bd9Sstevel@tonic-gate }
19927c478bd9Sstevel@tonic-gate
19937c478bd9Sstevel@tonic-gate /* print name and -p */
19947c478bd9Sstevel@tonic-gate if (fprintf(fp, "%s -p", msp->common.namep->cname) == EOF)
19957c478bd9Sstevel@tonic-gate return (mdsyserror(ep, errno, fname));
19967c478bd9Sstevel@tonic-gate
19977c478bd9Sstevel@tonic-gate /* print the component */
19987c478bd9Sstevel@tonic-gate /*
1999d7cd8252Stw21770 * Always print the full path name
20007c478bd9Sstevel@tonic-gate */
20017c478bd9Sstevel@tonic-gate if (fprintf(fp, " %s", msp->compnamep->rname) == EOF)
20027c478bd9Sstevel@tonic-gate return (mdsyserror(ep, errno, fname));
20037c478bd9Sstevel@tonic-gate
20047c478bd9Sstevel@tonic-gate /* print out each extent */
20057c478bd9Sstevel@tonic-gate for (extn = 0; (extn < msp->ext.ext_len); extn++) {
20067c478bd9Sstevel@tonic-gate md_sp_ext_t *extp = &msp->ext.ext_val[extn];
20077c478bd9Sstevel@tonic-gate if (fprintf(fp, " -o %llu -b %llu ", extp->poff,
20087c478bd9Sstevel@tonic-gate extp->len) == EOF)
20097c478bd9Sstevel@tonic-gate return (mdsyserror(ep, errno, fname));
20107c478bd9Sstevel@tonic-gate }
20117c478bd9Sstevel@tonic-gate
20127c478bd9Sstevel@tonic-gate if (fprintf(fp, "\n") == EOF)
20137c478bd9Sstevel@tonic-gate return (mdsyserror(ep, errno, fname));
20147c478bd9Sstevel@tonic-gate
20157c478bd9Sstevel@tonic-gate /* success */
20167c478bd9Sstevel@tonic-gate return (0);
20177c478bd9Sstevel@tonic-gate }
20187c478bd9Sstevel@tonic-gate
20197c478bd9Sstevel@tonic-gate /*
20207c478bd9Sstevel@tonic-gate * FUNCTION: meta_sp_status_to_name()
20217c478bd9Sstevel@tonic-gate * INPUT: xsp_status - the status value to convert to a string
20227c478bd9Sstevel@tonic-gate * tstate - transient errored device state. If set the
20237c478bd9Sstevel@tonic-gate * device is Unavailable
20247c478bd9Sstevel@tonic-gate * OUTPUT: none
20257c478bd9Sstevel@tonic-gate * RETURNS: char * - a pointer to the string representing the status value
20267c478bd9Sstevel@tonic-gate * PURPOSE: return an internationalized string representing the
20277c478bd9Sstevel@tonic-gate * status value for a soft partition. The strings are
20287c478bd9Sstevel@tonic-gate * strdup'd and must be freed by the caller.
20297c478bd9Sstevel@tonic-gate */
20307c478bd9Sstevel@tonic-gate static char *
meta_sp_status_to_name(xsp_status_t xsp_status,uint_t tstate)20317c478bd9Sstevel@tonic-gate meta_sp_status_to_name(
20327c478bd9Sstevel@tonic-gate xsp_status_t xsp_status,
20337c478bd9Sstevel@tonic-gate uint_t tstate
20347c478bd9Sstevel@tonic-gate )
20357c478bd9Sstevel@tonic-gate {
20367c478bd9Sstevel@tonic-gate char *rval = NULL;
20377c478bd9Sstevel@tonic-gate
20387c478bd9Sstevel@tonic-gate /*
20397c478bd9Sstevel@tonic-gate * Check to see if we have MD_INACCESSIBLE set. This is the only valid
20407c478bd9Sstevel@tonic-gate * value for an 'Unavailable' return. tstate can be set because of
20417c478bd9Sstevel@tonic-gate * other multi-node reasons (e.g. ABR being set)
20427c478bd9Sstevel@tonic-gate */
20437c478bd9Sstevel@tonic-gate if (tstate & MD_INACCESSIBLE) {
20447c478bd9Sstevel@tonic-gate return (Strdup(dgettext(TEXT_DOMAIN, "Unavailable")));
20457c478bd9Sstevel@tonic-gate }
20467c478bd9Sstevel@tonic-gate
20477c478bd9Sstevel@tonic-gate switch (xsp_status) {
20487c478bd9Sstevel@tonic-gate case MD_SP_CREATEPEND:
20497c478bd9Sstevel@tonic-gate rval = Strdup(dgettext(TEXT_DOMAIN, "Creating"));
20507c478bd9Sstevel@tonic-gate break;
20517c478bd9Sstevel@tonic-gate case MD_SP_GROWPEND:
20527c478bd9Sstevel@tonic-gate rval = Strdup(dgettext(TEXT_DOMAIN, "Growing"));
20537c478bd9Sstevel@tonic-gate break;
20547c478bd9Sstevel@tonic-gate case MD_SP_DELPEND:
20557c478bd9Sstevel@tonic-gate rval = Strdup(dgettext(TEXT_DOMAIN, "Deleting"));
20567c478bd9Sstevel@tonic-gate break;
20577c478bd9Sstevel@tonic-gate case MD_SP_OK:
20587c478bd9Sstevel@tonic-gate rval = Strdup(dgettext(TEXT_DOMAIN, "Okay"));
20597c478bd9Sstevel@tonic-gate break;
20607c478bd9Sstevel@tonic-gate case MD_SP_ERR:
20617c478bd9Sstevel@tonic-gate rval = Strdup(dgettext(TEXT_DOMAIN, "Errored"));
20627c478bd9Sstevel@tonic-gate break;
20637c478bd9Sstevel@tonic-gate case MD_SP_RECOVER:
20647c478bd9Sstevel@tonic-gate rval = Strdup(dgettext(TEXT_DOMAIN, "Recovering"));
20657c478bd9Sstevel@tonic-gate break;
20667c478bd9Sstevel@tonic-gate }
20677c478bd9Sstevel@tonic-gate
20687c478bd9Sstevel@tonic-gate if (rval == NULL)
20697c478bd9Sstevel@tonic-gate rval = Strdup(dgettext(TEXT_DOMAIN, "Invalid"));
20707c478bd9Sstevel@tonic-gate
20717c478bd9Sstevel@tonic-gate return (rval);
20727c478bd9Sstevel@tonic-gate }
20737c478bd9Sstevel@tonic-gate
20747c478bd9Sstevel@tonic-gate /*
20757c478bd9Sstevel@tonic-gate * FUNCTION: meta_sp_report()
20767c478bd9Sstevel@tonic-gate * INPUT: sp - the set name for the unit being displayed
20777c478bd9Sstevel@tonic-gate * msp - the unit structure to display
20787c478bd9Sstevel@tonic-gate * nlpp - pass back the large devs
20797c478bd9Sstevel@tonic-gate * fp - the file pointer to send output to
20807c478bd9Sstevel@tonic-gate * options - print options from the command line processor
20817c478bd9Sstevel@tonic-gate * OUTPUT: ep - return error pointer
20827c478bd9Sstevel@tonic-gate * RETURNS: int - -1 if error, 0 on success
20837c478bd9Sstevel@tonic-gate * PURPOSE: print a full report of the device specified
20847c478bd9Sstevel@tonic-gate */
20857c478bd9Sstevel@tonic-gate static int
meta_sp_report(mdsetname_t * sp,md_sp_t * msp,mdnamelist_t ** nlpp,char * fname,FILE * fp,mdprtopts_t options,md_error_t * ep)20867c478bd9Sstevel@tonic-gate meta_sp_report(
20877c478bd9Sstevel@tonic-gate mdsetname_t *sp,
20887c478bd9Sstevel@tonic-gate md_sp_t *msp,
20897c478bd9Sstevel@tonic-gate mdnamelist_t **nlpp,
20907c478bd9Sstevel@tonic-gate char *fname,
20917c478bd9Sstevel@tonic-gate FILE *fp,
20927c478bd9Sstevel@tonic-gate mdprtopts_t options,
20937c478bd9Sstevel@tonic-gate md_error_t *ep
20947c478bd9Sstevel@tonic-gate )
20957c478bd9Sstevel@tonic-gate {
20967c478bd9Sstevel@tonic-gate uint_t extn;
20977c478bd9Sstevel@tonic-gate char *status;
20987c478bd9Sstevel@tonic-gate char *devid = "";
20997c478bd9Sstevel@tonic-gate mdname_t *didnp = NULL;
21007c478bd9Sstevel@tonic-gate ddi_devid_t dtp;
21017c478bd9Sstevel@tonic-gate int len;
21027c478bd9Sstevel@tonic-gate uint_t tstate = 0;
21037c478bd9Sstevel@tonic-gate
21047c478bd9Sstevel@tonic-gate if (options & PRINT_LARGEDEVICES) {
2105d7cd8252Stw21770 if ((msp->common.revision & MD_64BIT_META_DEV) == 0) {
2106d7cd8252Stw21770 return (0);
2107d7cd8252Stw21770 } else {
2108d7cd8252Stw21770 if (meta_getdevs(sp, msp->common.namep, nlpp, ep) != 0)
2109d7cd8252Stw21770 return (-1);
2110d7cd8252Stw21770 }
2111d7cd8252Stw21770 }
2112d7cd8252Stw21770
2113d7cd8252Stw21770 if (options & PRINT_FN) {
2114d7cd8252Stw21770 if ((msp->common.revision & MD_FN_META_DEV) == 0) {
21157c478bd9Sstevel@tonic-gate return (0);
21167c478bd9Sstevel@tonic-gate } else {
21177c478bd9Sstevel@tonic-gate if (meta_getdevs(sp, msp->common.namep, nlpp, ep) != 0)
21187c478bd9Sstevel@tonic-gate return (-1);
21197c478bd9Sstevel@tonic-gate }
21207c478bd9Sstevel@tonic-gate }
21217c478bd9Sstevel@tonic-gate
21227c478bd9Sstevel@tonic-gate if (options & PRINT_HEADER) {
21237c478bd9Sstevel@tonic-gate if (fprintf(fp, dgettext(TEXT_DOMAIN, "%s: Soft Partition\n"),
21247c478bd9Sstevel@tonic-gate msp->common.namep->cname) == EOF)
21257c478bd9Sstevel@tonic-gate return (mdsyserror(ep, errno, fname));
21267c478bd9Sstevel@tonic-gate }
21277c478bd9Sstevel@tonic-gate
21287c478bd9Sstevel@tonic-gate if (fprintf(fp, dgettext(TEXT_DOMAIN, " Device: %s\n"),
21297c478bd9Sstevel@tonic-gate msp->compnamep->cname) == EOF)
21307c478bd9Sstevel@tonic-gate return (mdsyserror(ep, errno, fname));
21317c478bd9Sstevel@tonic-gate
21327c478bd9Sstevel@tonic-gate /* Determine if device is available before displaying status */
21337c478bd9Sstevel@tonic-gate if (metaismeta(msp->common.namep)) {
21347c478bd9Sstevel@tonic-gate if (meta_get_tstate(msp->common.namep->dev, &tstate, ep) != 0)
21357c478bd9Sstevel@tonic-gate return (-1);
21367c478bd9Sstevel@tonic-gate }
21377c478bd9Sstevel@tonic-gate status = meta_sp_status_to_name(msp->status, tstate & MD_DEV_ERRORED);
21387c478bd9Sstevel@tonic-gate
21397c478bd9Sstevel@tonic-gate /* print out "State" to be consistent with other metadevices */
21407c478bd9Sstevel@tonic-gate if (tstate & MD_ABR_CAP) {
21417c478bd9Sstevel@tonic-gate if (fprintf(fp, dgettext(TEXT_DOMAIN,
21427c478bd9Sstevel@tonic-gate " State: %s - Application Based Recovery (ABR)\n"),
21437c478bd9Sstevel@tonic-gate status) == EOF) {
21447c478bd9Sstevel@tonic-gate Free(status);
21457c478bd9Sstevel@tonic-gate return (mdsyserror(ep, errno, fname));
21467c478bd9Sstevel@tonic-gate }
21477c478bd9Sstevel@tonic-gate } else {
21487c478bd9Sstevel@tonic-gate if (fprintf(fp, dgettext(TEXT_DOMAIN,
21497c478bd9Sstevel@tonic-gate " State: %s\n"), status) == EOF) {
21507c478bd9Sstevel@tonic-gate Free(status);
21517c478bd9Sstevel@tonic-gate return (mdsyserror(ep, errno, fname));
21527c478bd9Sstevel@tonic-gate }
21537c478bd9Sstevel@tonic-gate }
21547c478bd9Sstevel@tonic-gate free(status);
21557c478bd9Sstevel@tonic-gate
21567c478bd9Sstevel@tonic-gate if (fprintf(fp, dgettext(TEXT_DOMAIN, " Size: %llu blocks (%s)\n"),
21577c478bd9Sstevel@tonic-gate msp->common.size,
21587c478bd9Sstevel@tonic-gate meta_number_to_string(msp->common.size, DEV_BSIZE)) == EOF)
21597c478bd9Sstevel@tonic-gate return (mdsyserror(ep, errno, fname));
21607c478bd9Sstevel@tonic-gate
21617c478bd9Sstevel@tonic-gate /* print component details */
21627c478bd9Sstevel@tonic-gate if (! metaismeta(msp->compnamep)) {
21637c478bd9Sstevel@tonic-gate diskaddr_t start_blk;
21647c478bd9Sstevel@tonic-gate int has_mddb;
21657c478bd9Sstevel@tonic-gate char *has_mddb_str;
21667c478bd9Sstevel@tonic-gate
21677c478bd9Sstevel@tonic-gate /* print header */
21687c478bd9Sstevel@tonic-gate /*
21697c478bd9Sstevel@tonic-gate * Building a format string on the fly that will
21707c478bd9Sstevel@tonic-gate * be used in (f)printf. This allows the length
21717c478bd9Sstevel@tonic-gate * of the ctd to vary from small to large without
21727c478bd9Sstevel@tonic-gate * looking horrible.
21737c478bd9Sstevel@tonic-gate */
21747c478bd9Sstevel@tonic-gate len = strlen(msp->compnamep->cname);
21757c478bd9Sstevel@tonic-gate len = max(len, strlen(dgettext(TEXT_DOMAIN, "Device")));
21767c478bd9Sstevel@tonic-gate len += 2;
21777c478bd9Sstevel@tonic-gate if (fprintf(fp,
21787c478bd9Sstevel@tonic-gate "\t%-*.*s %-12.12s %-5.5s %s\n",
21797c478bd9Sstevel@tonic-gate len, len,
21807c478bd9Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Device"),
21817c478bd9Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Start Block"),
21827c478bd9Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Dbase"),
21837c478bd9Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Reloc")) == EOF) {
21847c478bd9Sstevel@tonic-gate return (mdsyserror(ep, errno, fname));
21857c478bd9Sstevel@tonic-gate }
21867c478bd9Sstevel@tonic-gate
21877c478bd9Sstevel@tonic-gate
21887c478bd9Sstevel@tonic-gate /* get info */
21897c478bd9Sstevel@tonic-gate if ((start_blk = meta_sp_get_start(sp, msp->compnamep, ep)) ==
21907c478bd9Sstevel@tonic-gate MD_DISKADDR_ERROR)
21917c478bd9Sstevel@tonic-gate return (-1);
21927c478bd9Sstevel@tonic-gate
21937c478bd9Sstevel@tonic-gate if ((has_mddb = metahasmddb(sp, msp->compnamep, ep)) < 0)
21947c478bd9Sstevel@tonic-gate return (-1);
21957c478bd9Sstevel@tonic-gate
21967c478bd9Sstevel@tonic-gate if (has_mddb)
21977c478bd9Sstevel@tonic-gate has_mddb_str = dgettext(TEXT_DOMAIN, "Yes");
21987c478bd9Sstevel@tonic-gate else
21997c478bd9Sstevel@tonic-gate has_mddb_str = dgettext(TEXT_DOMAIN, "No");
22007c478bd9Sstevel@tonic-gate
22017c478bd9Sstevel@tonic-gate /* populate the key in the name_p structure */
22027c478bd9Sstevel@tonic-gate didnp = metadevname(&sp, msp->compnamep->dev, ep);
22037c478bd9Sstevel@tonic-gate if (didnp == NULL) {
22047c478bd9Sstevel@tonic-gate return (-1);
22057c478bd9Sstevel@tonic-gate }
22067c478bd9Sstevel@tonic-gate
22077c478bd9Sstevel@tonic-gate /* determine if devid does NOT exist */
22087c478bd9Sstevel@tonic-gate if (options & PRINT_DEVID) {
22091cd3f00bSsk102515 if ((dtp = meta_getdidbykey(sp->setno,
22101cd3f00bSsk102515 getmyside(sp, ep), didnp->key, ep)) == NULL)
22117c478bd9Sstevel@tonic-gate devid = dgettext(TEXT_DOMAIN, "No ");
22127c478bd9Sstevel@tonic-gate else {
22137c478bd9Sstevel@tonic-gate devid = dgettext(TEXT_DOMAIN, "Yes");
22147c478bd9Sstevel@tonic-gate free(dtp);
22157c478bd9Sstevel@tonic-gate }
22167c478bd9Sstevel@tonic-gate }
22177c478bd9Sstevel@tonic-gate
22187c478bd9Sstevel@tonic-gate /* print info */
22197c478bd9Sstevel@tonic-gate /*
22207c478bd9Sstevel@tonic-gate * This allows the length
22217c478bd9Sstevel@tonic-gate * of the ctd to vary from small to large without
22227c478bd9Sstevel@tonic-gate * looking horrible.
22237c478bd9Sstevel@tonic-gate */
22247c478bd9Sstevel@tonic-gate if (fprintf(fp, "\t%-*s %8lld %-5.5s %s\n",
22257c478bd9Sstevel@tonic-gate len, msp->compnamep->cname,
22267c478bd9Sstevel@tonic-gate start_blk, has_mddb_str, devid) == EOF) {
22277c478bd9Sstevel@tonic-gate return (mdsyserror(ep, errno, fname));
22287c478bd9Sstevel@tonic-gate }
22297c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\n");
22307c478bd9Sstevel@tonic-gate }
22317c478bd9Sstevel@tonic-gate
22327c478bd9Sstevel@tonic-gate
22337c478bd9Sstevel@tonic-gate /* print the headers */
22347c478bd9Sstevel@tonic-gate if (fprintf(fp, "\t%6.6s %24.24s %24.24s\n",
22357c478bd9Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Extent"),
22367c478bd9Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Start Block"),
22377c478bd9Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Block count")) == EOF)
22387c478bd9Sstevel@tonic-gate return (mdsyserror(ep, errno, fname));
22397c478bd9Sstevel@tonic-gate
22407c478bd9Sstevel@tonic-gate /* print out each extent */
22417c478bd9Sstevel@tonic-gate for (extn = 0; (extn < msp->ext.ext_len); extn++) {
22427c478bd9Sstevel@tonic-gate md_sp_ext_t *extp = &msp->ext.ext_val[extn];
22437c478bd9Sstevel@tonic-gate
22447c478bd9Sstevel@tonic-gate /* If PRINT_TIMES option is ever supported, add output here */
22457c478bd9Sstevel@tonic-gate if (fprintf(fp, "\t%6u %24llu %24llu\n",
22467c478bd9Sstevel@tonic-gate extn, extp->poff, extp->len) == EOF)
22477c478bd9Sstevel@tonic-gate return (mdsyserror(ep, errno, fname));
22487c478bd9Sstevel@tonic-gate }
22497c478bd9Sstevel@tonic-gate
22507c478bd9Sstevel@tonic-gate /* separate records with a newline */
22517c478bd9Sstevel@tonic-gate (void) fprintf(fp, "\n");
22527c478bd9Sstevel@tonic-gate return (0);
22537c478bd9Sstevel@tonic-gate }
22547c478bd9Sstevel@tonic-gate
22557c478bd9Sstevel@tonic-gate /*
22567c478bd9Sstevel@tonic-gate * FUNCTION: meta_sp_print()
22577c478bd9Sstevel@tonic-gate * INPUT: sp - the set name for the unit being displayed
22587c478bd9Sstevel@tonic-gate * np - the name of the device to print
22597c478bd9Sstevel@tonic-gate * fname - ??? not used
22607c478bd9Sstevel@tonic-gate * fp - the file pointer to send output to
22617c478bd9Sstevel@tonic-gate * options - print options from the command line processor
22627c478bd9Sstevel@tonic-gate * OUTPUT: ep - return error pointer
22637c478bd9Sstevel@tonic-gate * RETURNS: int - -1 if error, 0 on success
22647c478bd9Sstevel@tonic-gate * PURPOSE: print a full report of the device specified by metastat.
22657c478bd9Sstevel@tonic-gate * This is the main entry point for printing.
22667c478bd9Sstevel@tonic-gate */
22677c478bd9Sstevel@tonic-gate int
meta_sp_print(mdsetname_t * sp,mdname_t * np,mdnamelist_t ** nlpp,char * fname,FILE * fp,mdprtopts_t options,md_error_t * ep)22687c478bd9Sstevel@tonic-gate meta_sp_print(
22697c478bd9Sstevel@tonic-gate mdsetname_t *sp,
22707c478bd9Sstevel@tonic-gate mdname_t *np,
22717c478bd9Sstevel@tonic-gate mdnamelist_t **nlpp,
22727c478bd9Sstevel@tonic-gate char *fname,
22737c478bd9Sstevel@tonic-gate FILE *fp,
22747c478bd9Sstevel@tonic-gate mdprtopts_t options,
22757c478bd9Sstevel@tonic-gate md_error_t *ep
22767c478bd9Sstevel@tonic-gate )
22777c478bd9Sstevel@tonic-gate {
22787c478bd9Sstevel@tonic-gate md_sp_t *msp;
22797c478bd9Sstevel@tonic-gate md_unit_t *mdp;
22807c478bd9Sstevel@tonic-gate int rval = 0;
22812b637af7SJohn Harres set_t setno;
22822b637af7SJohn Harres minor_t unit;
22837c478bd9Sstevel@tonic-gate
22847c478bd9Sstevel@tonic-gate /* should always have the same set */
22857c478bd9Sstevel@tonic-gate assert(sp != NULL);
22867c478bd9Sstevel@tonic-gate
22877c478bd9Sstevel@tonic-gate /* print all the soft partitions */
22887c478bd9Sstevel@tonic-gate if (np == NULL) {
22897c478bd9Sstevel@tonic-gate mdnamelist_t *nlp = NULL;
22907c478bd9Sstevel@tonic-gate mdnamelist_t *p;
22917c478bd9Sstevel@tonic-gate int cnt;
22927c478bd9Sstevel@tonic-gate
22937c478bd9Sstevel@tonic-gate if ((cnt = meta_get_sp_names(sp, &nlp, options, ep)) < 0)
22947c478bd9Sstevel@tonic-gate return (-1);
22957c478bd9Sstevel@tonic-gate else if (cnt == 0)
22967c478bd9Sstevel@tonic-gate return (0);
22977c478bd9Sstevel@tonic-gate
22987c478bd9Sstevel@tonic-gate /* recusively print them out */
22997c478bd9Sstevel@tonic-gate for (p = nlp; (p != NULL); p = p->next) {
23007c478bd9Sstevel@tonic-gate mdname_t *curnp = p->namep;
23017c478bd9Sstevel@tonic-gate
23027c478bd9Sstevel@tonic-gate /*
23037c478bd9Sstevel@tonic-gate * one problem with the rval of -1 here is that
23047c478bd9Sstevel@tonic-gate * the error gets "lost" when the next device is
23057c478bd9Sstevel@tonic-gate * printed, but we want to print them all anyway.
23067c478bd9Sstevel@tonic-gate */
23077c478bd9Sstevel@tonic-gate rval = meta_sp_print(sp, curnp, nlpp, fname, fp,
23087c478bd9Sstevel@tonic-gate options, ep);
23097c478bd9Sstevel@tonic-gate }
23107c478bd9Sstevel@tonic-gate
23117c478bd9Sstevel@tonic-gate /* clean up, return success */
23127c478bd9Sstevel@tonic-gate metafreenamelist(nlp);
23137c478bd9Sstevel@tonic-gate return (rval);
23147c478bd9Sstevel@tonic-gate }
23157c478bd9Sstevel@tonic-gate
23167c478bd9Sstevel@tonic-gate /* get the unit structure */
23177c478bd9Sstevel@tonic-gate if ((msp = meta_get_sp_common(sp, np,
23187c478bd9Sstevel@tonic-gate ((options & PRINT_FAST) ? 1 : 0), ep)) == NULL)
23197c478bd9Sstevel@tonic-gate return (-1);
23207c478bd9Sstevel@tonic-gate
23217c478bd9Sstevel@tonic-gate /* check for parented */
23227c478bd9Sstevel@tonic-gate if ((! (options & PRINT_SUBDEVS)) &&
23237c478bd9Sstevel@tonic-gate (MD_HAS_PARENT(msp->common.parent))) {
23247c478bd9Sstevel@tonic-gate return (0);
23257c478bd9Sstevel@tonic-gate }
23267c478bd9Sstevel@tonic-gate
23277c478bd9Sstevel@tonic-gate /* print appropriate detail */
23287c478bd9Sstevel@tonic-gate if (options & PRINT_SHORT) {
23297c478bd9Sstevel@tonic-gate if (meta_sp_short_print(msp, fname, fp, options, ep) != 0)
23307c478bd9Sstevel@tonic-gate return (-1);
23317c478bd9Sstevel@tonic-gate } else {
23327c478bd9Sstevel@tonic-gate if (meta_sp_report(sp, msp, nlpp, fname, fp, options, ep) != 0)
23337c478bd9Sstevel@tonic-gate return (-1);
23347c478bd9Sstevel@tonic-gate }
23357c478bd9Sstevel@tonic-gate
23367c478bd9Sstevel@tonic-gate /*
23377c478bd9Sstevel@tonic-gate * Print underlying metadevices if they are parented to us and
23387c478bd9Sstevel@tonic-gate * if the info for the underlying metadevice has not been printed.
23397c478bd9Sstevel@tonic-gate */
23407c478bd9Sstevel@tonic-gate if (metaismeta(msp->compnamep)) {
23417c478bd9Sstevel@tonic-gate /* get the unit structure for the subdevice */
23427c478bd9Sstevel@tonic-gate if ((mdp = meta_get_mdunit(sp, msp->compnamep, ep)) == NULL)
23437c478bd9Sstevel@tonic-gate return (-1);
23447c478bd9Sstevel@tonic-gate
23452b637af7SJohn Harres setno = MD_MIN2SET(MD_SID(mdp));
23462b637af7SJohn Harres unit = MD_MIN2UNIT(MD_SID(mdp));
23472b637af7SJohn Harres
23487c478bd9Sstevel@tonic-gate /* If info not already printed, recurse */
23492b637af7SJohn Harres if (sp_parent_printed[setno] == NULL ||
23502b637af7SJohn Harres !BT_TEST(sp_parent_printed[setno], unit)) {
23517c478bd9Sstevel@tonic-gate if (meta_print_name(sp, msp->compnamep, nlpp, fname, fp,
23527c478bd9Sstevel@tonic-gate (options | PRINT_HEADER | PRINT_SUBDEVS),
23537c478bd9Sstevel@tonic-gate NULL, ep) != 0) {
23547c478bd9Sstevel@tonic-gate return (-1);
23557c478bd9Sstevel@tonic-gate }
23562b637af7SJohn Harres if (sp_parent_printed[setno] == NULL)
23572b637af7SJohn Harres sp_parent_printed[setno] =
2358*704030f4SJames Hall Zalloc(BT_SIZEOFMAP(MD_MAXUNITS));
23592b637af7SJohn Harres BT_SET(sp_parent_printed[setno], unit);
23607c478bd9Sstevel@tonic-gate }
23617c478bd9Sstevel@tonic-gate }
23627c478bd9Sstevel@tonic-gate return (0);
23637c478bd9Sstevel@tonic-gate }
23647c478bd9Sstevel@tonic-gate
23657c478bd9Sstevel@tonic-gate /*
23667c478bd9Sstevel@tonic-gate * **************************************************************************
23677c478bd9Sstevel@tonic-gate * Watermark Manipulation Functions *
23687c478bd9Sstevel@tonic-gate * **************************************************************************
23697c478bd9Sstevel@tonic-gate */
23707c478bd9Sstevel@tonic-gate
23717c478bd9Sstevel@tonic-gate /*
23727c478bd9Sstevel@tonic-gate * FUNCTION: meta_sp_get_start()
23737c478bd9Sstevel@tonic-gate * INPUT: sp - the operating set
23747c478bd9Sstevel@tonic-gate * np - device upon which the sp is being built
23757c478bd9Sstevel@tonic-gate * OUTPUT: ep - return error pointer
23767c478bd9Sstevel@tonic-gate * RETURNS: daddr_t - -1 if error, otherwise the start block
23777c478bd9Sstevel@tonic-gate * PURPOSE: Encapsulate the determination of the start block of the
23787c478bd9Sstevel@tonic-gate * device upon which the sp is built or being built.
23797c478bd9Sstevel@tonic-gate */
23807c478bd9Sstevel@tonic-gate static diskaddr_t
meta_sp_get_start(mdsetname_t * sp,mdname_t * np,md_error_t * ep)23817c478bd9Sstevel@tonic-gate meta_sp_get_start(
23827c478bd9Sstevel@tonic-gate mdsetname_t *sp,
23837c478bd9Sstevel@tonic-gate mdname_t *np,
23847c478bd9Sstevel@tonic-gate md_error_t *ep
23857c478bd9Sstevel@tonic-gate )
23867c478bd9Sstevel@tonic-gate {
23877c478bd9Sstevel@tonic-gate daddr_t start_block;
23887c478bd9Sstevel@tonic-gate
23890f5425cbSjkennedy if ((start_block = metagetstart(sp, np, ep)) != MD_DISKADDR_ERROR)
23907c478bd9Sstevel@tonic-gate start_block += MD_SP_START;
23917c478bd9Sstevel@tonic-gate
23927c478bd9Sstevel@tonic-gate return (start_block);
23937c478bd9Sstevel@tonic-gate }
23947c478bd9Sstevel@tonic-gate
23957c478bd9Sstevel@tonic-gate /*
2396bf85a12bSJohn Wren Kennedy * FUNCTION: meta_sp_update_wm_common()
23977c478bd9Sstevel@tonic-gate * INPUT: sp - the operating set
23987c478bd9Sstevel@tonic-gate * msp - a pointer to the XDR unit structure
23997c478bd9Sstevel@tonic-gate * extlist - the extent list specifying watermarks to update
2400bf85a12bSJohn Wren Kennedy * iocval - either MD_IOC_SPUPDATEWM or MD_MN_IOC_SPUPDATEWM
24017c478bd9Sstevel@tonic-gate * OUTPUT: ep - return error pointer
24027c478bd9Sstevel@tonic-gate * RETURNS: int - -1 if error, 0 on success
24037c478bd9Sstevel@tonic-gate * PURPOSE: steps backwards through the extent list updating
24047c478bd9Sstevel@tonic-gate * watermarks for all extents with the EXTFLG_UPDATE flag
24057c478bd9Sstevel@tonic-gate * set. Writing the watermarks guarantees consistency when
24067c478bd9Sstevel@tonic-gate * extents must be broken into pieces since the original
24077c478bd9Sstevel@tonic-gate * watermark will be the last to be updated, and will be
24087c478bd9Sstevel@tonic-gate * changed to point to a new watermark that is already
24097c478bd9Sstevel@tonic-gate * known to be consistent. If one of the writes fails, the
24107c478bd9Sstevel@tonic-gate * original watermark stays intact and none of the changes
24117c478bd9Sstevel@tonic-gate * are realized.
24127c478bd9Sstevel@tonic-gate */
24137c478bd9Sstevel@tonic-gate static int
meta_sp_update_wm_common(mdsetname_t * sp,md_sp_t * msp,sp_ext_node_t * extlist,int iocval,md_error_t * ep)2414bf85a12bSJohn Wren Kennedy meta_sp_update_wm_common(
24157c478bd9Sstevel@tonic-gate mdsetname_t *sp,
24167c478bd9Sstevel@tonic-gate md_sp_t *msp,
24177c478bd9Sstevel@tonic-gate sp_ext_node_t *extlist,
2418bf85a12bSJohn Wren Kennedy int iocval,
24197c478bd9Sstevel@tonic-gate md_error_t *ep
24207c478bd9Sstevel@tonic-gate )
24217c478bd9Sstevel@tonic-gate {
24227c478bd9Sstevel@tonic-gate sp_ext_node_t *ext;
24237c478bd9Sstevel@tonic-gate sp_ext_node_t *tail;
24247c478bd9Sstevel@tonic-gate mp_watermark_t *wmp, *watermarks;
24257c478bd9Sstevel@tonic-gate xsp_offset_t *osp, *offsets;
24267c478bd9Sstevel@tonic-gate int update_count = 0;
24277c478bd9Sstevel@tonic-gate int rval = 0;
24287c478bd9Sstevel@tonic-gate md_unit_t *mdp;
24297c478bd9Sstevel@tonic-gate md_sp_update_wm_t update_params;
24307c478bd9Sstevel@tonic-gate
24317c478bd9Sstevel@tonic-gate if (getenv(META_SP_DEBUG)) {
24327c478bd9Sstevel@tonic-gate meta_sp_debug("meta_sp_update_wm: Updating watermarks:\n");
24337c478bd9Sstevel@tonic-gate meta_sp_list_dump(extlist);
24347c478bd9Sstevel@tonic-gate }
24357c478bd9Sstevel@tonic-gate
24367c478bd9Sstevel@tonic-gate /*
24377c478bd9Sstevel@tonic-gate * find the last node so we can write the watermarks backwards
24387c478bd9Sstevel@tonic-gate * and count watermarks to update so we can allocate space
24397c478bd9Sstevel@tonic-gate */
24407c478bd9Sstevel@tonic-gate for (ext = extlist; ext != NULL; ext = ext->ext_next) {
24417c478bd9Sstevel@tonic-gate if ((ext->ext_flags & EXTFLG_UPDATE) != 0) {
24427c478bd9Sstevel@tonic-gate update_count++;
24437c478bd9Sstevel@tonic-gate }
24447c478bd9Sstevel@tonic-gate
24457c478bd9Sstevel@tonic-gate if (ext->ext_next == NULL) {
24467c478bd9Sstevel@tonic-gate tail = ext;
24477c478bd9Sstevel@tonic-gate }
24487c478bd9Sstevel@tonic-gate }
24497c478bd9Sstevel@tonic-gate ext = tail;
24507c478bd9Sstevel@tonic-gate
24517c478bd9Sstevel@tonic-gate wmp = watermarks =
24527c478bd9Sstevel@tonic-gate Zalloc(update_count * sizeof (mp_watermark_t));
24537c478bd9Sstevel@tonic-gate osp = offsets =
24547c478bd9Sstevel@tonic-gate Zalloc(update_count * sizeof (sp_ext_offset_t));
24557c478bd9Sstevel@tonic-gate
24567c478bd9Sstevel@tonic-gate while (ext != NULL) {
24577c478bd9Sstevel@tonic-gate if ((ext->ext_flags & EXTFLG_UPDATE) != 0) {
24587c478bd9Sstevel@tonic-gate /* update watermark */
24597c478bd9Sstevel@tonic-gate wmp->wm_magic = MD_SP_MAGIC;
24607c478bd9Sstevel@tonic-gate wmp->wm_version = MD_SP_VERSION;
24617c478bd9Sstevel@tonic-gate wmp->wm_type = ext->ext_type;
24627c478bd9Sstevel@tonic-gate wmp->wm_seq = ext->ext_seq;
24637c478bd9Sstevel@tonic-gate wmp->wm_length = ext->ext_length - MD_SP_WMSIZE;
24647c478bd9Sstevel@tonic-gate
24657c478bd9Sstevel@tonic-gate /* fill in the volume name and set name */
24667c478bd9Sstevel@tonic-gate if (ext->ext_namep != NULL)
24677c478bd9Sstevel@tonic-gate (void) strcpy(wmp->wm_mdname,
24687c478bd9Sstevel@tonic-gate ext->ext_namep->cname);
24697c478bd9Sstevel@tonic-gate else
24707c478bd9Sstevel@tonic-gate (void) strcpy(wmp->wm_mdname, MD_SP_FREEWMNAME);
24717c478bd9Sstevel@tonic-gate if (ext->ext_setp != NULL &&
24727c478bd9Sstevel@tonic-gate ext->ext_setp->setno != MD_LOCAL_SET)
24737c478bd9Sstevel@tonic-gate (void) strcpy(wmp->wm_setname,
24747c478bd9Sstevel@tonic-gate ext->ext_setp->setname);
24757c478bd9Sstevel@tonic-gate else
24767c478bd9Sstevel@tonic-gate (void) strcpy(wmp->wm_setname,
24777c478bd9Sstevel@tonic-gate MD_SP_LOCALSETNAME);
24787c478bd9Sstevel@tonic-gate
24797c478bd9Sstevel@tonic-gate /* Generate the checksum */
24807c478bd9Sstevel@tonic-gate wmp->wm_checksum = 0;
24817c478bd9Sstevel@tonic-gate crcgen((uchar_t *)wmp, (uint_t *)&wmp->wm_checksum,
24827c478bd9Sstevel@tonic-gate sizeof (*wmp), NULL);
24837c478bd9Sstevel@tonic-gate
24847c478bd9Sstevel@tonic-gate /* record the extent offset */
24857c478bd9Sstevel@tonic-gate *osp = ext->ext_offset;
24867c478bd9Sstevel@tonic-gate
24877c478bd9Sstevel@tonic-gate /* Advance the placeholders */
24887c478bd9Sstevel@tonic-gate osp++; wmp++;
24897c478bd9Sstevel@tonic-gate }
24907c478bd9Sstevel@tonic-gate ext = ext->ext_prev;
24917c478bd9Sstevel@tonic-gate }
24927c478bd9Sstevel@tonic-gate
24937c478bd9Sstevel@tonic-gate mdp = meta_get_mdunit(sp, msp->common.namep, ep);
24947c478bd9Sstevel@tonic-gate if (mdp == NULL) {
24957c478bd9Sstevel@tonic-gate rval = -1;
24967c478bd9Sstevel@tonic-gate goto out;
24977c478bd9Sstevel@tonic-gate }
24987c478bd9Sstevel@tonic-gate
24997c478bd9Sstevel@tonic-gate (void) memset(&update_params, 0, sizeof (update_params));
25007c478bd9Sstevel@tonic-gate update_params.mnum = MD_SID(mdp);
25017c478bd9Sstevel@tonic-gate update_params.count = update_count;
25027c478bd9Sstevel@tonic-gate update_params.wmp = (uintptr_t)watermarks;
25037c478bd9Sstevel@tonic-gate update_params.osp = (uintptr_t)offsets;
25047c478bd9Sstevel@tonic-gate MD_SETDRIVERNAME(&update_params, MD_SP,
25057c478bd9Sstevel@tonic-gate MD_MIN2SET(update_params.mnum));
25067c478bd9Sstevel@tonic-gate
2507bf85a12bSJohn Wren Kennedy if (metaioctl(iocval, &update_params, &update_params.mde,
2508bf85a12bSJohn Wren Kennedy msp->common.namep->cname) != 0) {
25097c478bd9Sstevel@tonic-gate (void) mdstealerror(ep, &update_params.mde);
25107c478bd9Sstevel@tonic-gate rval = -1;
25117c478bd9Sstevel@tonic-gate goto out;
25127c478bd9Sstevel@tonic-gate }
25137c478bd9Sstevel@tonic-gate
25147c478bd9Sstevel@tonic-gate out:
25157c478bd9Sstevel@tonic-gate Free(watermarks);
25167c478bd9Sstevel@tonic-gate Free(offsets);
25177c478bd9Sstevel@tonic-gate
25187c478bd9Sstevel@tonic-gate return (rval);
25197c478bd9Sstevel@tonic-gate }
25207c478bd9Sstevel@tonic-gate
2521bf85a12bSJohn Wren Kennedy static int
meta_sp_update_wm(mdsetname_t * sp,md_sp_t * msp,sp_ext_node_t * extlist,md_error_t * ep)2522bf85a12bSJohn Wren Kennedy meta_sp_update_wm(
2523bf85a12bSJohn Wren Kennedy mdsetname_t *sp,
2524bf85a12bSJohn Wren Kennedy md_sp_t *msp,
2525bf85a12bSJohn Wren Kennedy sp_ext_node_t *extlist,
2526bf85a12bSJohn Wren Kennedy md_error_t *ep
2527bf85a12bSJohn Wren Kennedy )
2528bf85a12bSJohn Wren Kennedy {
2529bf85a12bSJohn Wren Kennedy return (meta_sp_update_wm_common(sp, msp, extlist, MD_IOC_SPUPDATEWM,
2530bf85a12bSJohn Wren Kennedy ep));
2531bf85a12bSJohn Wren Kennedy }
2532bf85a12bSJohn Wren Kennedy
2533bf85a12bSJohn Wren Kennedy static int
meta_mn_sp_update_wm(mdsetname_t * sp,md_sp_t * msp,sp_ext_node_t * extlist,md_error_t * ep)2534bf85a12bSJohn Wren Kennedy meta_mn_sp_update_wm(
2535bf85a12bSJohn Wren Kennedy mdsetname_t *sp,
2536bf85a12bSJohn Wren Kennedy md_sp_t *msp,
2537bf85a12bSJohn Wren Kennedy sp_ext_node_t *extlist,
2538bf85a12bSJohn Wren Kennedy md_error_t *ep
2539bf85a12bSJohn Wren Kennedy )
2540bf85a12bSJohn Wren Kennedy {
2541bf85a12bSJohn Wren Kennedy return (meta_sp_update_wm_common(sp, msp, extlist, MD_MN_IOC_SPUPDATEWM,
2542bf85a12bSJohn Wren Kennedy ep));
2543bf85a12bSJohn Wren Kennedy }
2544bf85a12bSJohn Wren Kennedy
25457c478bd9Sstevel@tonic-gate /*
25467c478bd9Sstevel@tonic-gate * FUNCTION: meta_sp_clear_wm()
25477c478bd9Sstevel@tonic-gate * INPUT: sp - the operating set
25487c478bd9Sstevel@tonic-gate * msp - the unit structure for the soft partition to clear
25497c478bd9Sstevel@tonic-gate * OUTPUT: ep - return error pointer
25507c478bd9Sstevel@tonic-gate * RETURNS: int - -1 if error, 0 on success
25517c478bd9Sstevel@tonic-gate * PURPOSE: steps through the extents for a soft partition unit and
25527c478bd9Sstevel@tonic-gate * creates an extent list designed to mark all of the
25537c478bd9Sstevel@tonic-gate * watermarks for those extents as free. The extent list
25547c478bd9Sstevel@tonic-gate * is then passed to meta_sp_update_wm() to actually write
25557c478bd9Sstevel@tonic-gate * the watermarks out.
25567c478bd9Sstevel@tonic-gate */
25577c478bd9Sstevel@tonic-gate static int
meta_sp_clear_wm(mdsetname_t * sp,md_sp_t * msp,md_error_t * ep)25587c478bd9Sstevel@tonic-gate meta_sp_clear_wm(
25597c478bd9Sstevel@tonic-gate mdsetname_t *sp,
25607c478bd9Sstevel@tonic-gate md_sp_t *msp,
25617c478bd9Sstevel@tonic-gate md_error_t *ep
25627c478bd9Sstevel@tonic-gate )
25637c478bd9Sstevel@tonic-gate {
25647c478bd9Sstevel@tonic-gate sp_ext_node_t *extlist = NULL;
25657c478bd9Sstevel@tonic-gate int numexts = msp->ext.ext_len;
25667c478bd9Sstevel@tonic-gate uint_t i;
25677c478bd9Sstevel@tonic-gate int rval = 0;
25687c478bd9Sstevel@tonic-gate
25697c478bd9Sstevel@tonic-gate /* for each watermark must set the flag to SP_FREE */
25707c478bd9Sstevel@tonic-gate for (i = 0; i < numexts; i++) {
25717c478bd9Sstevel@tonic-gate md_sp_ext_t *extp = &msp->ext.ext_val[i];
25727c478bd9Sstevel@tonic-gate
25737c478bd9Sstevel@tonic-gate meta_sp_list_insert(NULL, NULL, &extlist,
25747c478bd9Sstevel@tonic-gate extp->poff - MD_SP_WMSIZE, extp->len + MD_SP_WMSIZE,
25757c478bd9Sstevel@tonic-gate EXTTYP_FREE, 0, EXTFLG_UPDATE, meta_sp_cmp_by_offset);
25767c478bd9Sstevel@tonic-gate }
25777c478bd9Sstevel@tonic-gate
25787c478bd9Sstevel@tonic-gate /* update watermarks */
25797c478bd9Sstevel@tonic-gate rval = meta_sp_update_wm(sp, msp, extlist, ep);
25807c478bd9Sstevel@tonic-gate
25817c478bd9Sstevel@tonic-gate meta_sp_list_free(&extlist);
25827c478bd9Sstevel@tonic-gate return (rval);
25837c478bd9Sstevel@tonic-gate }
25847c478bd9Sstevel@tonic-gate
25857c478bd9Sstevel@tonic-gate /*
25867c478bd9Sstevel@tonic-gate * FUNCTION: meta_sp_read_wm()
25877c478bd9Sstevel@tonic-gate * INPUT: sp - setname for component
25887c478bd9Sstevel@tonic-gate * compnp - mdname_t for component
25897c478bd9Sstevel@tonic-gate * offset - the offset of the watermark to read (sectors)
25907c478bd9Sstevel@tonic-gate * OUTPUT: wm - the watermark structure to read into
25917c478bd9Sstevel@tonic-gate * ep - return error pointer
25927c478bd9Sstevel@tonic-gate * RETURNS: int - -1 if error, 0 on success
25937c478bd9Sstevel@tonic-gate * PURPOSE: seeks out to the requested offset and reads a watermark.
25947c478bd9Sstevel@tonic-gate * It then verifies that the magic number is correct and
25957c478bd9Sstevel@tonic-gate * that the checksum is valid, returning an error if either
25967c478bd9Sstevel@tonic-gate * is wrong.
25977c478bd9Sstevel@tonic-gate */
25987c478bd9Sstevel@tonic-gate static int
meta_sp_read_wm(mdsetname_t * sp,mdname_t * compnp,mp_watermark_t * wm,sp_ext_offset_t offset,md_error_t * ep)25997c478bd9Sstevel@tonic-gate meta_sp_read_wm(
26007c478bd9Sstevel@tonic-gate mdsetname_t *sp,
26017c478bd9Sstevel@tonic-gate mdname_t *compnp,
26027c478bd9Sstevel@tonic-gate mp_watermark_t *wm,
26037c478bd9Sstevel@tonic-gate sp_ext_offset_t offset,
26047c478bd9Sstevel@tonic-gate md_error_t *ep
26057c478bd9Sstevel@tonic-gate )
26067c478bd9Sstevel@tonic-gate {
26077c478bd9Sstevel@tonic-gate md_sp_read_wm_t read_params;
26087c478bd9Sstevel@tonic-gate
26097c478bd9Sstevel@tonic-gate /*
26107c478bd9Sstevel@tonic-gate * make sure block offset does not overflow 2^64 bytes and it's a
26117c478bd9Sstevel@tonic-gate * multiple of the block size.
26127c478bd9Sstevel@tonic-gate */
26137c478bd9Sstevel@tonic-gate assert(offset <= (1LL << (64 - DEV_BSHIFT)));
26147c478bd9Sstevel@tonic-gate /* LINTED */
26157c478bd9Sstevel@tonic-gate assert((sizeof (*wm) % DEV_BSIZE) == 0);
26167c478bd9Sstevel@tonic-gate
26177c478bd9Sstevel@tonic-gate (void) memset(wm, 0, sizeof (*wm));
26187c478bd9Sstevel@tonic-gate
26197c478bd9Sstevel@tonic-gate (void) memset(&read_params, 0, sizeof (read_params));
26207c478bd9Sstevel@tonic-gate read_params.rdev = compnp->dev;
26217c478bd9Sstevel@tonic-gate read_params.wmp = (uintptr_t)wm;
26227c478bd9Sstevel@tonic-gate read_params.offset = offset;
26237c478bd9Sstevel@tonic-gate MD_SETDRIVERNAME(&read_params, MD_SP, sp->setno);
26247c478bd9Sstevel@tonic-gate
26257c478bd9Sstevel@tonic-gate if (metaioctl(MD_IOC_SPREADWM, &read_params,
26267c478bd9Sstevel@tonic-gate &read_params.mde, compnp->cname) != 0) {
26277c478bd9Sstevel@tonic-gate
26287c478bd9Sstevel@tonic-gate (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
26297c478bd9Sstevel@tonic-gate "Extent header read failed, block %llu.\n"), offset);
26307c478bd9Sstevel@tonic-gate return (mdstealerror(ep, &read_params.mde));
26317c478bd9Sstevel@tonic-gate }
26327c478bd9Sstevel@tonic-gate
26337c478bd9Sstevel@tonic-gate /* make sure magic number is correct */
26347c478bd9Sstevel@tonic-gate if (wm->wm_magic != MD_SP_MAGIC) {
26357c478bd9Sstevel@tonic-gate (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
26367c478bd9Sstevel@tonic-gate "found incorrect magic number %x, expected %x.\n"),
26377c478bd9Sstevel@tonic-gate wm->wm_magic, MD_SP_MAGIC);
26387c478bd9Sstevel@tonic-gate /*
26397c478bd9Sstevel@tonic-gate * Pass NULL for the device name as we don't have
26407c478bd9Sstevel@tonic-gate * valid watermark contents.
26417c478bd9Sstevel@tonic-gate */
26427c478bd9Sstevel@tonic-gate return (mdmderror(ep, MDE_SP_BADWMMAGIC, 0, NULL));
26437c478bd9Sstevel@tonic-gate }
26447c478bd9Sstevel@tonic-gate
26457c478bd9Sstevel@tonic-gate if (crcchk((uchar_t *)wm, (uint_t *)&wm->wm_checksum,
26467c478bd9Sstevel@tonic-gate sizeof (*wm), NULL)) {
26477c478bd9Sstevel@tonic-gate (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
26487c478bd9Sstevel@tonic-gate "found incorrect checksum %x.\n"),
26497c478bd9Sstevel@tonic-gate wm->wm_checksum);
26507c478bd9Sstevel@tonic-gate return (mdmderror(ep, MDE_SP_BADWMCRC, 0, wm->wm_mdname));
26517c478bd9Sstevel@tonic-gate }
26527c478bd9Sstevel@tonic-gate
26537c478bd9Sstevel@tonic-gate return (0);
26547c478bd9Sstevel@tonic-gate }
26557c478bd9Sstevel@tonic-gate
26567c478bd9Sstevel@tonic-gate /*
26577c478bd9Sstevel@tonic-gate * **************************************************************************
26587c478bd9Sstevel@tonic-gate * Query Functions
26597c478bd9Sstevel@tonic-gate * **************************************************************************
26607c478bd9Sstevel@tonic-gate */
26617c478bd9Sstevel@tonic-gate
26627c478bd9Sstevel@tonic-gate /*
26637c478bd9Sstevel@tonic-gate * IMPORTANT NOTE: This is a static function that assumes that
26647c478bd9Sstevel@tonic-gate * its input parameters have been checked and
26657c478bd9Sstevel@tonic-gate * have valid values that lie within acceptable
26667c478bd9Sstevel@tonic-gate * ranges.
26677c478bd9Sstevel@tonic-gate *
26687c478bd9Sstevel@tonic-gate * FUNCTION: meta_sp_enough_space()
26697c478bd9Sstevel@tonic-gate * INPUT: desired_number_of_sps - the number of soft partitions desired;
26707c478bd9Sstevel@tonic-gate * must be > 0
26717c478bd9Sstevel@tonic-gate * desired_sp_size - the desired soft partition size in blocks;
26727c478bd9Sstevel@tonic-gate * must be > 0
26737c478bd9Sstevel@tonic-gate * extent_listpp - a reference to a reference to an extent
26747c478bd9Sstevel@tonic-gate * list that lists the extents on a device;
26757c478bd9Sstevel@tonic-gate * must be a reference to a reference to a
26767c478bd9Sstevel@tonic-gate * valid extent list
26777c478bd9Sstevel@tonic-gate * alignment - the desired data space alignment for the sp's
26787c478bd9Sstevel@tonic-gate * OUTPUT: boolean_t return value
26797c478bd9Sstevel@tonic-gate * RETURNS: boolean_t - B_TRUE if there's enough space in the extent
26807c478bd9Sstevel@tonic-gate * list to create the desired soft partitions,
26817c478bd9Sstevel@tonic-gate * B_FALSE if there's not enough space
26827c478bd9Sstevel@tonic-gate * PURPOSE: determines whether there's enough free space in an extent
26837c478bd9Sstevel@tonic-gate * list to allow creation of a set of soft partitions
26847c478bd9Sstevel@tonic-gate */
26857c478bd9Sstevel@tonic-gate static boolean_t
meta_sp_enough_space(int desired_number_of_sps,blkcnt_t desired_sp_size,sp_ext_node_t ** extent_listpp,sp_ext_length_t alignment)26867c478bd9Sstevel@tonic-gate meta_sp_enough_space(
26877c478bd9Sstevel@tonic-gate int desired_number_of_sps,
26887c478bd9Sstevel@tonic-gate blkcnt_t desired_sp_size,
26897c478bd9Sstevel@tonic-gate sp_ext_node_t **extent_listpp,
26907c478bd9Sstevel@tonic-gate sp_ext_length_t alignment
26917c478bd9Sstevel@tonic-gate )
26927c478bd9Sstevel@tonic-gate {
26937c478bd9Sstevel@tonic-gate boolean_t enough_space;
26947c478bd9Sstevel@tonic-gate int number_of_sps;
26957c478bd9Sstevel@tonic-gate int number_of_extents_used;
26967c478bd9Sstevel@tonic-gate sp_ext_length_t desired_ext_length = desired_sp_size;
26977c478bd9Sstevel@tonic-gate
26987c478bd9Sstevel@tonic-gate enough_space = B_TRUE;
26997c478bd9Sstevel@tonic-gate number_of_sps = 0;
27007c478bd9Sstevel@tonic-gate while ((enough_space == B_TRUE) &&
27017c478bd9Sstevel@tonic-gate (number_of_sps < desired_number_of_sps)) {
27027c478bd9Sstevel@tonic-gate /*
27037c478bd9Sstevel@tonic-gate * Use the extent allocation algorithm implemented by
27047c478bd9Sstevel@tonic-gate * meta_sp_alloc_by_len() to test whether the free
27057c478bd9Sstevel@tonic-gate * extents in the extent list referenced by *extent_listpp
27067c478bd9Sstevel@tonic-gate * contain enough space to accomodate a soft partition
27077c478bd9Sstevel@tonic-gate * of size desired_ext_length.
27087c478bd9Sstevel@tonic-gate *
27097c478bd9Sstevel@tonic-gate * Repeat the test <desired_number_of_sps> times
27107c478bd9Sstevel@tonic-gate * or until it fails, whichever comes first,
27117c478bd9Sstevel@tonic-gate * each time allocating the extents required to
27127c478bd9Sstevel@tonic-gate * create the soft partition without actually
27137c478bd9Sstevel@tonic-gate * creating the soft partition.
27147c478bd9Sstevel@tonic-gate */
27157c478bd9Sstevel@tonic-gate number_of_extents_used = meta_sp_alloc_by_len(
27161cd3f00bSsk102515 TEST_SETNAMEP, TEST_SOFT_PARTITION_NAMEP,
27171cd3f00bSsk102515 extent_listpp, &desired_ext_length,
27181cd3f00bSsk102515 NO_OFFSET, alignment);
27197c478bd9Sstevel@tonic-gate if (number_of_extents_used == -1) {
27207c478bd9Sstevel@tonic-gate enough_space = B_FALSE;
27217c478bd9Sstevel@tonic-gate } else {
27227c478bd9Sstevel@tonic-gate number_of_sps++;
27237c478bd9Sstevel@tonic-gate }
27247c478bd9Sstevel@tonic-gate }
27257c478bd9Sstevel@tonic-gate return (enough_space);
27267c478bd9Sstevel@tonic-gate }
27277c478bd9Sstevel@tonic-gate
27287c478bd9Sstevel@tonic-gate /*
27297c478bd9Sstevel@tonic-gate * IMPORTANT NOTE: This is a static function that calls other functions
27307c478bd9Sstevel@tonic-gate * that check its mdsetnamep and device_mdnamep
27317c478bd9Sstevel@tonic-gate * input parameters, but expects extent_listpp to
27327c478bd9Sstevel@tonic-gate * be a initialized to a valid address to which
27337c478bd9Sstevel@tonic-gate * it can write a reference to the extent list that
27347c478bd9Sstevel@tonic-gate * it creates.
27357c478bd9Sstevel@tonic-gate *
27367c478bd9Sstevel@tonic-gate * FUNCTION: meta_sp_get_extent_list()
27377c478bd9Sstevel@tonic-gate * INPUT: mdsetnamep - a reference to the mdsetname_t structure
27387c478bd9Sstevel@tonic-gate * for the set containing the device for
27397c478bd9Sstevel@tonic-gate * which the extents are to be listed
27407c478bd9Sstevel@tonic-gate * device_mdnamep - a reference to the mdname_t structure
27417c478bd9Sstevel@tonic-gate * for the device for which the extents
27427c478bd9Sstevel@tonic-gate * are to be listed
27437c478bd9Sstevel@tonic-gate * OUTPUT: *extent_listpp - a reference to the extent list for
27447c478bd9Sstevel@tonic-gate * the device; NULL if the function fails
27457c478bd9Sstevel@tonic-gate * *ep - the libmeta error encountered, if any
27467c478bd9Sstevel@tonic-gate * RETURNS: boolean_t - B_TRUE if the function call was successful,
27477c478bd9Sstevel@tonic-gate * B_FALSE if not
27487c478bd9Sstevel@tonic-gate * PURPOSE: gets the extent list for a device
27497c478bd9Sstevel@tonic-gate */
27507c478bd9Sstevel@tonic-gate static boolean_t
meta_sp_get_extent_list(mdsetname_t * mdsetnamep,mdname_t * device_mdnamep,sp_ext_node_t ** extent_listpp,md_error_t * ep)27517c478bd9Sstevel@tonic-gate meta_sp_get_extent_list(
27527c478bd9Sstevel@tonic-gate mdsetname_t *mdsetnamep,
27537c478bd9Sstevel@tonic-gate mdname_t *device_mdnamep,
27547c478bd9Sstevel@tonic-gate sp_ext_node_t **extent_listpp,
27557c478bd9Sstevel@tonic-gate md_error_t *ep
27567c478bd9Sstevel@tonic-gate )
27577c478bd9Sstevel@tonic-gate {
27587c478bd9Sstevel@tonic-gate diskaddr_t device_size_in_blocks;
27597c478bd9Sstevel@tonic-gate mdnamelist_t *sp_name_listp;
27607c478bd9Sstevel@tonic-gate diskaddr_t start_block_address_in_blocks;
27617c478bd9Sstevel@tonic-gate
27627c478bd9Sstevel@tonic-gate *extent_listpp = NULL;
27637c478bd9Sstevel@tonic-gate sp_name_listp = NULL;
27647c478bd9Sstevel@tonic-gate
27657c478bd9Sstevel@tonic-gate start_block_address_in_blocks = meta_sp_get_start(mdsetnamep,
27661cd3f00bSsk102515 device_mdnamep, ep);
27677c478bd9Sstevel@tonic-gate if (start_block_address_in_blocks == MD_DISKADDR_ERROR) {
27687c478bd9Sstevel@tonic-gate if (getenv(META_SP_DEBUG)) {
27691cd3f00bSsk102515 mde_perror(ep,
27701cd3f00bSsk102515 "meta_sp_get_extent_list:meta_sp_get_start");
27717c478bd9Sstevel@tonic-gate }
27727c478bd9Sstevel@tonic-gate return (B_FALSE);
27737c478bd9Sstevel@tonic-gate }
27747c478bd9Sstevel@tonic-gate
27757c478bd9Sstevel@tonic-gate device_size_in_blocks = metagetsize(device_mdnamep, ep);
27767c478bd9Sstevel@tonic-gate if (device_size_in_blocks == MD_DISKADDR_ERROR) {
27777c478bd9Sstevel@tonic-gate if (getenv(META_SP_DEBUG)) {
27787c478bd9Sstevel@tonic-gate mde_perror(ep,
27797c478bd9Sstevel@tonic-gate "meta_sp_get_extent_list:metagetsize");
27807c478bd9Sstevel@tonic-gate }
27817c478bd9Sstevel@tonic-gate return (B_FALSE);
27827c478bd9Sstevel@tonic-gate }
27837c478bd9Sstevel@tonic-gate
27847c478bd9Sstevel@tonic-gate /*
27857c478bd9Sstevel@tonic-gate * Sanity check: the start block will have skipped an integer
27867c478bd9Sstevel@tonic-gate * number of cylinders, C. C will usually be zero. If (C > 0),
27877c478bd9Sstevel@tonic-gate * and the disk slice happens to only be C cylinders in total
27887c478bd9Sstevel@tonic-gate * size, we'll fail this check.
27897c478bd9Sstevel@tonic-gate */
27907c478bd9Sstevel@tonic-gate if (device_size_in_blocks <=
27917c478bd9Sstevel@tonic-gate (start_block_address_in_blocks + MD_SP_WMSIZE)) {
27927c478bd9Sstevel@tonic-gate (void) mdmderror(ep, MDE_SP_NOSPACE, 0, device_mdnamep->cname);
27937c478bd9Sstevel@tonic-gate return (B_FALSE);
27947c478bd9Sstevel@tonic-gate }
27957c478bd9Sstevel@tonic-gate
27967c478bd9Sstevel@tonic-gate /*
27977c478bd9Sstevel@tonic-gate * After this point, we will have allocated resources, so any
27987c478bd9Sstevel@tonic-gate * failure returns must be through the supplied "fail" label
27997c478bd9Sstevel@tonic-gate * to properly deallocate things.
28007c478bd9Sstevel@tonic-gate */
28017c478bd9Sstevel@tonic-gate
28027c478bd9Sstevel@tonic-gate /*
28037c478bd9Sstevel@tonic-gate * Create an empty extent list that starts one watermark past
28047c478bd9Sstevel@tonic-gate * the start block of the device and ends one watermark before
28057c478bd9Sstevel@tonic-gate * the end of the device.
28067c478bd9Sstevel@tonic-gate */
28071cd3f00bSsk102515 meta_sp_list_insert(TEST_SETNAMEP, TEST_SOFT_PARTITION_NAMEP,
28081cd3f00bSsk102515 extent_listpp, NO_OFFSET,
28097c478bd9Sstevel@tonic-gate (sp_ext_length_t)start_block_address_in_blocks,
28101cd3f00bSsk102515 EXTTYP_RESERVED, NO_SEQUENCE_NUMBER, NO_FLAGS,
28117c478bd9Sstevel@tonic-gate meta_sp_cmp_by_offset);
28121cd3f00bSsk102515 meta_sp_list_insert(TEST_SETNAMEP, TEST_SOFT_PARTITION_NAMEP,
28131cd3f00bSsk102515 extent_listpp, (sp_ext_offset_t)(device_size_in_blocks -
28141cd3f00bSsk102515 MD_SP_WMSIZE), MD_SP_WMSIZE, EXTTYP_END, NO_SEQUENCE_NUMBER,
28151cd3f00bSsk102515 NO_FLAGS, meta_sp_cmp_by_offset);
28167c478bd9Sstevel@tonic-gate
28177c478bd9Sstevel@tonic-gate /*
28187c478bd9Sstevel@tonic-gate * Get the list of soft partitions that are already on the
28197c478bd9Sstevel@tonic-gate * device.
28207c478bd9Sstevel@tonic-gate */
28217c478bd9Sstevel@tonic-gate if (meta_sp_get_by_component(mdsetnamep, device_mdnamep,
28227c478bd9Sstevel@tonic-gate &sp_name_listp, FORCE_RELOAD_CACHE, ep) < 1) {
28237c478bd9Sstevel@tonic-gate if (getenv(META_SP_DEBUG)) {
28247c478bd9Sstevel@tonic-gate mde_perror(ep,
28257c478bd9Sstevel@tonic-gate "meta_sp_get_extent_list:meta_sp_get_by_component");
28267c478bd9Sstevel@tonic-gate }
28277c478bd9Sstevel@tonic-gate goto fail;
28287c478bd9Sstevel@tonic-gate }
28297c478bd9Sstevel@tonic-gate
28307c478bd9Sstevel@tonic-gate if (sp_name_listp != NULL) {
28317c478bd9Sstevel@tonic-gate /*
28327c478bd9Sstevel@tonic-gate * If there are soft partitions on the device, add the
28337c478bd9Sstevel@tonic-gate * extents used in them to the extent list.
28347c478bd9Sstevel@tonic-gate */
28357c478bd9Sstevel@tonic-gate if (meta_sp_extlist_from_namelist(mdsetnamep, sp_name_listp,
28367c478bd9Sstevel@tonic-gate extent_listpp, ep) == -1) {
28377c478bd9Sstevel@tonic-gate if (getenv(META_SP_DEBUG)) {
28387c478bd9Sstevel@tonic-gate mde_perror(ep, "meta_sp_get_extent_list:"
28397c478bd9Sstevel@tonic-gate "meta_sp_extlist_from_namelist");
28407c478bd9Sstevel@tonic-gate }
28417c478bd9Sstevel@tonic-gate goto fail;
28427c478bd9Sstevel@tonic-gate }
28437c478bd9Sstevel@tonic-gate metafreenamelist(sp_name_listp);
28447c478bd9Sstevel@tonic-gate }
28457c478bd9Sstevel@tonic-gate
28467c478bd9Sstevel@tonic-gate /*
28477c478bd9Sstevel@tonic-gate * Add free extents to the extent list to represent
28487c478bd9Sstevel@tonic-gate * the remaining regions of free space on the
28497c478bd9Sstevel@tonic-gate * device.
28507c478bd9Sstevel@tonic-gate */
28517c478bd9Sstevel@tonic-gate meta_sp_list_freefill(extent_listpp, device_size_in_blocks);
28527c478bd9Sstevel@tonic-gate return (B_TRUE);
28537c478bd9Sstevel@tonic-gate
28547c478bd9Sstevel@tonic-gate fail:
28557c478bd9Sstevel@tonic-gate if (sp_name_listp != NULL) {
28567c478bd9Sstevel@tonic-gate metafreenamelist(sp_name_listp);
28577c478bd9Sstevel@tonic-gate }
28587c478bd9Sstevel@tonic-gate
28597c478bd9Sstevel@tonic-gate if (*extent_listpp != NULL) {
28607c478bd9Sstevel@tonic-gate /*
28617c478bd9Sstevel@tonic-gate * meta_sp_list_free sets *extent_listpp to NULL.
28627c478bd9Sstevel@tonic-gate */
28637c478bd9Sstevel@tonic-gate meta_sp_list_free(extent_listpp);
28647c478bd9Sstevel@tonic-gate }
28657c478bd9Sstevel@tonic-gate return (B_FALSE);
28667c478bd9Sstevel@tonic-gate }
28677c478bd9Sstevel@tonic-gate
28687c478bd9Sstevel@tonic-gate /*
28697c478bd9Sstevel@tonic-gate * IMPORTANT NOTE: This is a static function that calls other functions
28707c478bd9Sstevel@tonic-gate * that check its mdsetnamep and mddrivenamep
28717c478bd9Sstevel@tonic-gate * input parameters, but expects extent_listpp to
28727c478bd9Sstevel@tonic-gate * be a initialized to a valid address to which
28737c478bd9Sstevel@tonic-gate * it can write a reference to the extent list that
28747c478bd9Sstevel@tonic-gate * it creates.
28757c478bd9Sstevel@tonic-gate *
28767c478bd9Sstevel@tonic-gate * FUNCTION: meta_sp_get_extent_list_for_drive()
28777c478bd9Sstevel@tonic-gate * INPUT: mdsetnamep - a reference to the mdsetname_t structure
28787c478bd9Sstevel@tonic-gate * for the set containing the drive for
28797c478bd9Sstevel@tonic-gate * which the extents are to be listed
28807c478bd9Sstevel@tonic-gate * mddrivenamep - a reference to the mddrivename_t structure
28817c478bd9Sstevel@tonic-gate * for the drive for which the extents
28827c478bd9Sstevel@tonic-gate * are to be listed
28837c478bd9Sstevel@tonic-gate * OUTPUT: *extent_listpp - a reference to the extent list for
28847c478bd9Sstevel@tonic-gate * the drive; NULL if the function fails
28857c478bd9Sstevel@tonic-gate * RETURNS: boolean_t - B_TRUE if the function call was successful,
28867c478bd9Sstevel@tonic-gate * B_FALSE if not
28877c478bd9Sstevel@tonic-gate * PURPOSE: gets the extent list for a drive when the entire drive
28887c478bd9Sstevel@tonic-gate * is to be soft partitioned
28897c478bd9Sstevel@tonic-gate */
28907c478bd9Sstevel@tonic-gate static boolean_t
meta_sp_get_extent_list_for_drive(mdsetname_t * mdsetnamep,mddrivename_t * mddrivenamep,sp_ext_node_t ** extent_listpp)28917c478bd9Sstevel@tonic-gate meta_sp_get_extent_list_for_drive(
28927c478bd9Sstevel@tonic-gate mdsetname_t *mdsetnamep,
28937c478bd9Sstevel@tonic-gate mddrivename_t *mddrivenamep,
28947c478bd9Sstevel@tonic-gate sp_ext_node_t **extent_listpp
28957c478bd9Sstevel@tonic-gate )
28967c478bd9Sstevel@tonic-gate {
28977c478bd9Sstevel@tonic-gate boolean_t can_use;
28987c478bd9Sstevel@tonic-gate diskaddr_t free_space;
28997c478bd9Sstevel@tonic-gate md_error_t mderror;
29007c478bd9Sstevel@tonic-gate mdvtoc_t proposed_vtoc;
29017c478bd9Sstevel@tonic-gate int repartition_options;
29027c478bd9Sstevel@tonic-gate int return_value;
29037c478bd9Sstevel@tonic-gate md_sp_t test_sp_struct;
29047c478bd9Sstevel@tonic-gate
29057c478bd9Sstevel@tonic-gate can_use = B_TRUE;
29067c478bd9Sstevel@tonic-gate *extent_listpp = NULL;
29077c478bd9Sstevel@tonic-gate mderror = mdnullerror;
29087c478bd9Sstevel@tonic-gate test_sp_struct.compnamep = metaslicename(mddrivenamep, MD_SLICE0,
29097c478bd9Sstevel@tonic-gate &mderror);
29107c478bd9Sstevel@tonic-gate if (test_sp_struct.compnamep == NULL) {
29117c478bd9Sstevel@tonic-gate can_use = B_FALSE;
29127c478bd9Sstevel@tonic-gate }
29137c478bd9Sstevel@tonic-gate
29147c478bd9Sstevel@tonic-gate if (can_use == B_TRUE) {
29157c478bd9Sstevel@tonic-gate mderror = mdnullerror;
29167c478bd9Sstevel@tonic-gate repartition_options = 0;
29177c478bd9Sstevel@tonic-gate return_value = meta_check_sp(mdsetnamep, &test_sp_struct,
29181cd3f00bSsk102515 MDCMD_USE_WHOLE_DISK, &repartition_options, &mderror);
29197c478bd9Sstevel@tonic-gate if (return_value != 0) {
29207c478bd9Sstevel@tonic-gate can_use = B_FALSE;
29217c478bd9Sstevel@tonic-gate }
29227c478bd9Sstevel@tonic-gate }
29237c478bd9Sstevel@tonic-gate
29247c478bd9Sstevel@tonic-gate if (can_use == B_TRUE) {
29257c478bd9Sstevel@tonic-gate mderror = mdnullerror;
29267c478bd9Sstevel@tonic-gate repartition_options = repartition_options |
29277c478bd9Sstevel@tonic-gate (MD_REPART_FORCE | MD_REPART_DONT_LABEL);
29287c478bd9Sstevel@tonic-gate return_value = meta_repartition_drive(mdsetnamep, mddrivenamep,
29297c478bd9Sstevel@tonic-gate repartition_options, &proposed_vtoc, &mderror);
29307c478bd9Sstevel@tonic-gate if (return_value != 0) {
29317c478bd9Sstevel@tonic-gate can_use = B_FALSE;
29327c478bd9Sstevel@tonic-gate }
29337c478bd9Sstevel@tonic-gate }
29347c478bd9Sstevel@tonic-gate
29357c478bd9Sstevel@tonic-gate if (can_use == B_TRUE) {
29367c478bd9Sstevel@tonic-gate free_space = proposed_vtoc.parts[MD_SLICE0].size;
29377c478bd9Sstevel@tonic-gate if (free_space <= (MD_SP_START + MD_SP_WMSIZE)) {
29387c478bd9Sstevel@tonic-gate can_use = B_FALSE;
29397c478bd9Sstevel@tonic-gate }
29407c478bd9Sstevel@tonic-gate }
29417c478bd9Sstevel@tonic-gate
29427c478bd9Sstevel@tonic-gate if (can_use == B_TRUE) {
29437c478bd9Sstevel@tonic-gate /*
29447c478bd9Sstevel@tonic-gate * Create an extent list that starts with
29457c478bd9Sstevel@tonic-gate * a reserved extent that ends at the start
29467c478bd9Sstevel@tonic-gate * of the usable space on slice zero of the
29477c478bd9Sstevel@tonic-gate * proposed VTOC, ends with an extent that
29487c478bd9Sstevel@tonic-gate * reserves space for a watermark at the end
29497c478bd9Sstevel@tonic-gate * of slice zero, and contains a single free
29507c478bd9Sstevel@tonic-gate * extent that occupies the rest of the space
29517c478bd9Sstevel@tonic-gate * on the slice.
29527c478bd9Sstevel@tonic-gate *
29537c478bd9Sstevel@tonic-gate * NOTE:
29547c478bd9Sstevel@tonic-gate *
29557c478bd9Sstevel@tonic-gate * Don't use metagetstart() or metagetsize() to
29567c478bd9Sstevel@tonic-gate * find the usable space. They query the mdname_t
29577c478bd9Sstevel@tonic-gate * structure that represents an actual device to
29587c478bd9Sstevel@tonic-gate * determine the amount of space on the device that
29597c478bd9Sstevel@tonic-gate * contains metadata and the total amount of space
29607c478bd9Sstevel@tonic-gate * on the device. Since this function creates a
29617c478bd9Sstevel@tonic-gate * proposed extent list that doesn't reflect the
29627c478bd9Sstevel@tonic-gate * state of an actual device, there's no mdname_t
29637c478bd9Sstevel@tonic-gate * structure to be queried.
29647c478bd9Sstevel@tonic-gate *
29657c478bd9Sstevel@tonic-gate * When a drive is reformatted to prepare for
29667c478bd9Sstevel@tonic-gate * soft partitioning, all of slice seven is
29677c478bd9Sstevel@tonic-gate * reserved for metadata, all of slice zero is
29687c478bd9Sstevel@tonic-gate * available for soft partitioning, and all other
29697c478bd9Sstevel@tonic-gate * slices on the drive are empty. The proposed
29707c478bd9Sstevel@tonic-gate * extent list for the drive therefore contains
29717c478bd9Sstevel@tonic-gate * only three extents: a reserved extent that ends
29727c478bd9Sstevel@tonic-gate * at the start of the usable space on slice zero,
29737c478bd9Sstevel@tonic-gate * a single free extent that occupies all the usable
29747c478bd9Sstevel@tonic-gate * space on slice zero, and an ending extent that
29757c478bd9Sstevel@tonic-gate * reserves space for a watermark at the end of
29767c478bd9Sstevel@tonic-gate * slice zero.
29777c478bd9Sstevel@tonic-gate */
29781cd3f00bSsk102515 meta_sp_list_insert(TEST_SETNAMEP, TEST_SOFT_PARTITION_NAMEP,
29791cd3f00bSsk102515 extent_listpp, NO_OFFSET, (sp_ext_length_t)(MD_SP_START),
29801cd3f00bSsk102515 EXTTYP_RESERVED, NO_SEQUENCE_NUMBER, NO_FLAGS,
29817c478bd9Sstevel@tonic-gate meta_sp_cmp_by_offset);
29821cd3f00bSsk102515 meta_sp_list_insert(TEST_SETNAMEP, TEST_SOFT_PARTITION_NAMEP,
29831cd3f00bSsk102515 extent_listpp, (sp_ext_offset_t)(free_space - MD_SP_WMSIZE),
29841cd3f00bSsk102515 MD_SP_WMSIZE, EXTTYP_END, NO_SEQUENCE_NUMBER, NO_FLAGS,
29857c478bd9Sstevel@tonic-gate meta_sp_cmp_by_offset);
29867c478bd9Sstevel@tonic-gate meta_sp_list_freefill(extent_listpp, free_space);
29877c478bd9Sstevel@tonic-gate }
29887c478bd9Sstevel@tonic-gate return (can_use);
29897c478bd9Sstevel@tonic-gate }
29907c478bd9Sstevel@tonic-gate
29917c478bd9Sstevel@tonic-gate /*
29927c478bd9Sstevel@tonic-gate * FUNCTION: meta_sp_can_create_sps()
29937c478bd9Sstevel@tonic-gate * INPUT: mdsetnamep - a reference to the mdsetname_t structure
29947c478bd9Sstevel@tonic-gate * for the set containing the device for
29957c478bd9Sstevel@tonic-gate * which the extents are to be listed
29967c478bd9Sstevel@tonic-gate * mdnamep - a reference to the mdname_t of the device
29977c478bd9Sstevel@tonic-gate * on which the soft parititions are to be created
29987c478bd9Sstevel@tonic-gate * number_of_sps - the desired number of soft partitions
29997c478bd9Sstevel@tonic-gate * sp_size - the desired soft partition size
30007c478bd9Sstevel@tonic-gate * OUTPUT: boolean_t return value
30017c478bd9Sstevel@tonic-gate * RETURNS: boolean_t - B_TRUE if the soft partitionns can be created,
30027c478bd9Sstevel@tonic-gate * B_FALSE if not
30037c478bd9Sstevel@tonic-gate * PURPOSE: determines whether a set of soft partitions can be created
30047c478bd9Sstevel@tonic-gate * on a device
30057c478bd9Sstevel@tonic-gate */
30067c478bd9Sstevel@tonic-gate boolean_t
meta_sp_can_create_sps(mdsetname_t * mdsetnamep,mdname_t * mdnamep,int number_of_sps,blkcnt_t sp_size)30077c478bd9Sstevel@tonic-gate meta_sp_can_create_sps(
30087c478bd9Sstevel@tonic-gate mdsetname_t *mdsetnamep,
30097c478bd9Sstevel@tonic-gate mdname_t *mdnamep,
30107c478bd9Sstevel@tonic-gate int number_of_sps,
30117c478bd9Sstevel@tonic-gate blkcnt_t sp_size
30127c478bd9Sstevel@tonic-gate )
30137c478bd9Sstevel@tonic-gate {
30147c478bd9Sstevel@tonic-gate sp_ext_node_t *extent_listp;
30157c478bd9Sstevel@tonic-gate boolean_t succeeded;
30167c478bd9Sstevel@tonic-gate md_error_t mde;
30177c478bd9Sstevel@tonic-gate
30187c478bd9Sstevel@tonic-gate if ((number_of_sps > 0) && (sp_size > 0)) {
30197c478bd9Sstevel@tonic-gate succeeded = meta_sp_get_extent_list(mdsetnamep, mdnamep,
30207c478bd9Sstevel@tonic-gate &extent_listp, &mde);
30217c478bd9Sstevel@tonic-gate } else {
30227c478bd9Sstevel@tonic-gate succeeded = B_FALSE;
30237c478bd9Sstevel@tonic-gate }
30247c478bd9Sstevel@tonic-gate
30257c478bd9Sstevel@tonic-gate /*
30267c478bd9Sstevel@tonic-gate * We don't really care about an error return from the
30277c478bd9Sstevel@tonic-gate * alignment call; that will just result in passing zero,
30287c478bd9Sstevel@tonic-gate * which will be interpreted as no alignment.
30297c478bd9Sstevel@tonic-gate */
30307c478bd9Sstevel@tonic-gate
30317c478bd9Sstevel@tonic-gate if (succeeded == B_TRUE) {
30327c478bd9Sstevel@tonic-gate succeeded = meta_sp_enough_space(number_of_sps,
30337c478bd9Sstevel@tonic-gate sp_size, &extent_listp,
30347c478bd9Sstevel@tonic-gate meta_sp_get_default_alignment(mdsetnamep, mdnamep, &mde));
30357c478bd9Sstevel@tonic-gate meta_sp_list_free(&extent_listp);
30367c478bd9Sstevel@tonic-gate }
30377c478bd9Sstevel@tonic-gate return (succeeded);
30387c478bd9Sstevel@tonic-gate }
30397c478bd9Sstevel@tonic-gate
30407c478bd9Sstevel@tonic-gate /*
30417c478bd9Sstevel@tonic-gate * FUNCTION: meta_sp_can_create_sps_on_drive()
30427c478bd9Sstevel@tonic-gate * INPUT: mdsetnamep - a reference to the mdsetname_t structure
30437c478bd9Sstevel@tonic-gate * for the set containing the drive for
30447c478bd9Sstevel@tonic-gate * which the extents are to be listed
30457c478bd9Sstevel@tonic-gate * mddrivenamep - a reference to the mddrivename_t of the drive
30467c478bd9Sstevel@tonic-gate * on which the soft parititions are to be created
30477c478bd9Sstevel@tonic-gate * number_of_sps - the desired number of soft partitions
30487c478bd9Sstevel@tonic-gate * sp_size - the desired soft partition size
30497c478bd9Sstevel@tonic-gate * OUTPUT: boolean_t return value
30507c478bd9Sstevel@tonic-gate * RETURNS: boolean_t - B_TRUE if the soft partitionns can be created,
30517c478bd9Sstevel@tonic-gate * B_FALSE if not
30527c478bd9Sstevel@tonic-gate * PURPOSE: determines whether a set of soft partitions can be created
30537c478bd9Sstevel@tonic-gate * on a drive if the entire drive is soft partitioned
30547c478bd9Sstevel@tonic-gate */
30557c478bd9Sstevel@tonic-gate boolean_t
meta_sp_can_create_sps_on_drive(mdsetname_t * mdsetnamep,mddrivename_t * mddrivenamep,int number_of_sps,blkcnt_t sp_size)30567c478bd9Sstevel@tonic-gate meta_sp_can_create_sps_on_drive(
30577c478bd9Sstevel@tonic-gate mdsetname_t *mdsetnamep,
30587c478bd9Sstevel@tonic-gate mddrivename_t *mddrivenamep,
30597c478bd9Sstevel@tonic-gate int number_of_sps,
30607c478bd9Sstevel@tonic-gate blkcnt_t sp_size
30617c478bd9Sstevel@tonic-gate )
30627c478bd9Sstevel@tonic-gate {
30637c478bd9Sstevel@tonic-gate sp_ext_node_t *extent_listp;
30647c478bd9Sstevel@tonic-gate boolean_t succeeded;
30657c478bd9Sstevel@tonic-gate
30667c478bd9Sstevel@tonic-gate if ((number_of_sps > 0) && (sp_size > 0)) {
30677c478bd9Sstevel@tonic-gate succeeded = meta_sp_get_extent_list_for_drive(mdsetnamep,
30681cd3f00bSsk102515 mddrivenamep, &extent_listp);
30697c478bd9Sstevel@tonic-gate } else {
30707c478bd9Sstevel@tonic-gate succeeded = B_FALSE;
30717c478bd9Sstevel@tonic-gate }
30727c478bd9Sstevel@tonic-gate
30737c478bd9Sstevel@tonic-gate /*
30747c478bd9Sstevel@tonic-gate * We don't care about alignment on the space call because
30757c478bd9Sstevel@tonic-gate * we're specifically dealing with a drive, which will have no
30767c478bd9Sstevel@tonic-gate * inherent alignment.
30777c478bd9Sstevel@tonic-gate */
30787c478bd9Sstevel@tonic-gate
30797c478bd9Sstevel@tonic-gate if (succeeded == B_TRUE) {
30807c478bd9Sstevel@tonic-gate succeeded = meta_sp_enough_space(number_of_sps, sp_size,
30817c478bd9Sstevel@tonic-gate &extent_listp, SP_UNALIGNED);
30827c478bd9Sstevel@tonic-gate meta_sp_list_free(&extent_listp);
30837c478bd9Sstevel@tonic-gate }
30847c478bd9Sstevel@tonic-gate return (succeeded);
30857c478bd9Sstevel@tonic-gate }
30867c478bd9Sstevel@tonic-gate
30877c478bd9Sstevel@tonic-gate /*
30887c478bd9Sstevel@tonic-gate * FUNCTION: meta_sp_get_free_space()
30897c478bd9Sstevel@tonic-gate * INPUT: mdsetnamep - a reference to the mdsetname_t structure
30907c478bd9Sstevel@tonic-gate * for the set containing the device for
30917c478bd9Sstevel@tonic-gate * which the free space is to be returned
30927c478bd9Sstevel@tonic-gate * mdnamep - a reference to the mdname_t of the device
30937c478bd9Sstevel@tonic-gate * for which the free space is to be returned
30947c478bd9Sstevel@tonic-gate * OUTPUT: blkcnt_t return value
30957c478bd9Sstevel@tonic-gate * RETURNS: blkcnt_t - the number of blocks of free space on the device
30967c478bd9Sstevel@tonic-gate * PURPOSE: returns the number of blocks of free space on a device
30977c478bd9Sstevel@tonic-gate */
30987c478bd9Sstevel@tonic-gate blkcnt_t
meta_sp_get_free_space(mdsetname_t * mdsetnamep,mdname_t * mdnamep)30997c478bd9Sstevel@tonic-gate meta_sp_get_free_space(
31007c478bd9Sstevel@tonic-gate mdsetname_t *mdsetnamep,
31017c478bd9Sstevel@tonic-gate mdname_t *mdnamep
31027c478bd9Sstevel@tonic-gate )
31037c478bd9Sstevel@tonic-gate {
31047c478bd9Sstevel@tonic-gate sp_ext_node_t *extent_listp;
31057c478bd9Sstevel@tonic-gate sp_ext_length_t free_blocks;
31067c478bd9Sstevel@tonic-gate boolean_t succeeded;
31077c478bd9Sstevel@tonic-gate md_error_t mde;
31087c478bd9Sstevel@tonic-gate
31097c478bd9Sstevel@tonic-gate extent_listp = NULL;
31107c478bd9Sstevel@tonic-gate free_blocks = 0;
31117c478bd9Sstevel@tonic-gate succeeded = meta_sp_get_extent_list(mdsetnamep, mdnamep,
31127c478bd9Sstevel@tonic-gate &extent_listp, &mde);
31137c478bd9Sstevel@tonic-gate if (succeeded == B_TRUE) {
31147c478bd9Sstevel@tonic-gate free_blocks = meta_sp_list_size(extent_listp,
31157c478bd9Sstevel@tonic-gate EXTTYP_FREE, INCLUDE_WM);
31167c478bd9Sstevel@tonic-gate meta_sp_list_free(&extent_listp);
31177c478bd9Sstevel@tonic-gate if (free_blocks > (10 * MD_SP_WMSIZE)) {
31187c478bd9Sstevel@tonic-gate /*
31197c478bd9Sstevel@tonic-gate * Subtract a safety margin for watermarks when
31207c478bd9Sstevel@tonic-gate * computing the number of blocks available for
31217c478bd9Sstevel@tonic-gate * use. The actual number of watermarks can't
31227c478bd9Sstevel@tonic-gate * be calculated without knowing the exact numbers
31237c478bd9Sstevel@tonic-gate * and sizes of both the free extents and the soft
31247c478bd9Sstevel@tonic-gate * partitions to be created. The calculation is
31257c478bd9Sstevel@tonic-gate * highly complex and error-prone even if those
31267c478bd9Sstevel@tonic-gate * quantities are known. The approximate value
31277c478bd9Sstevel@tonic-gate * 10 * MD_SP_WMSIZE is within a few blocks of the
31287c478bd9Sstevel@tonic-gate * correct value in all practical cases.
31297c478bd9Sstevel@tonic-gate */
31307c478bd9Sstevel@tonic-gate free_blocks = free_blocks - (10 * MD_SP_WMSIZE);
31317c478bd9Sstevel@tonic-gate } else {
31327c478bd9Sstevel@tonic-gate free_blocks = 0;
31337c478bd9Sstevel@tonic-gate }
31347c478bd9Sstevel@tonic-gate } else {
31357c478bd9Sstevel@tonic-gate mdclrerror(&mde);
31367c478bd9Sstevel@tonic-gate }
31377c478bd9Sstevel@tonic-gate
31387c478bd9Sstevel@tonic-gate return (free_blocks);
31397c478bd9Sstevel@tonic-gate }
31407c478bd9Sstevel@tonic-gate
31417c478bd9Sstevel@tonic-gate /*
31427c478bd9Sstevel@tonic-gate * FUNCTION: meta_sp_get_free_space_on_drive()
31437c478bd9Sstevel@tonic-gate * INPUT: mdsetnamep - a reference to the mdsetname_t structure
31447c478bd9Sstevel@tonic-gate * for the set containing the drive for
31457c478bd9Sstevel@tonic-gate * which the free space is to be returned
31467c478bd9Sstevel@tonic-gate * mddrivenamep - a reference to the mddrivename_t of the drive
31477c478bd9Sstevel@tonic-gate * for which the free space is to be returned
31487c478bd9Sstevel@tonic-gate * OUTPUT: blkcnt_t return value
31497c478bd9Sstevel@tonic-gate * RETURNS: blkcnt_t - the number of blocks of free space on the drive
31507c478bd9Sstevel@tonic-gate * PURPOSE: returns the number of blocks of space usable for soft
31517c478bd9Sstevel@tonic-gate * partitions on an entire drive, if the entire drive is
31527c478bd9Sstevel@tonic-gate * soft partitioned
31537c478bd9Sstevel@tonic-gate */
31547c478bd9Sstevel@tonic-gate blkcnt_t
meta_sp_get_free_space_on_drive(mdsetname_t * mdsetnamep,mddrivename_t * mddrivenamep)31557c478bd9Sstevel@tonic-gate meta_sp_get_free_space_on_drive(
31567c478bd9Sstevel@tonic-gate mdsetname_t *mdsetnamep,
31577c478bd9Sstevel@tonic-gate mddrivename_t *mddrivenamep
31587c478bd9Sstevel@tonic-gate )
31597c478bd9Sstevel@tonic-gate {
31607c478bd9Sstevel@tonic-gate sp_ext_node_t *extent_listp;
31617c478bd9Sstevel@tonic-gate sp_ext_length_t free_blocks;
31627c478bd9Sstevel@tonic-gate boolean_t succeeded;
31637c478bd9Sstevel@tonic-gate
31647c478bd9Sstevel@tonic-gate extent_listp = NULL;
31657c478bd9Sstevel@tonic-gate free_blocks = 0;
31667c478bd9Sstevel@tonic-gate succeeded = meta_sp_get_extent_list_for_drive(mdsetnamep,
31677c478bd9Sstevel@tonic-gate mddrivenamep, &extent_listp);
31687c478bd9Sstevel@tonic-gate if (succeeded == B_TRUE) {
31697c478bd9Sstevel@tonic-gate free_blocks = meta_sp_list_size(extent_listp,
31707c478bd9Sstevel@tonic-gate EXTTYP_FREE, INCLUDE_WM);
31717c478bd9Sstevel@tonic-gate meta_sp_list_free(&extent_listp);
31727c478bd9Sstevel@tonic-gate if (free_blocks > (10 * MD_SP_WMSIZE)) {
31737c478bd9Sstevel@tonic-gate /*
31747c478bd9Sstevel@tonic-gate * Subtract a safety margin for watermarks when
31757c478bd9Sstevel@tonic-gate * computing the number of blocks available for
31767c478bd9Sstevel@tonic-gate * use. The actual number of watermarks can't
31777c478bd9Sstevel@tonic-gate * be calculated without knowing the exact numbers
31787c478bd9Sstevel@tonic-gate * and sizes of both the free extents and the soft
31797c478bd9Sstevel@tonic-gate * partitions to be created. The calculation is
31807c478bd9Sstevel@tonic-gate * highly complex and error-prone even if those
31817c478bd9Sstevel@tonic-gate * quantities are known. The approximate value
31827c478bd9Sstevel@tonic-gate * 10 * MD_SP_WMSIZE is within a few blocks of the
31837c478bd9Sstevel@tonic-gate * correct value in all practical cases.
31847c478bd9Sstevel@tonic-gate */
31857c478bd9Sstevel@tonic-gate free_blocks = free_blocks - (10 * MD_SP_WMSIZE);
31867c478bd9Sstevel@tonic-gate } else {
31877c478bd9Sstevel@tonic-gate free_blocks = 0;
31887c478bd9Sstevel@tonic-gate }
31897c478bd9Sstevel@tonic-gate }
31907c478bd9Sstevel@tonic-gate return (free_blocks);
31917c478bd9Sstevel@tonic-gate }
31927c478bd9Sstevel@tonic-gate
31937c478bd9Sstevel@tonic-gate /*
31947c478bd9Sstevel@tonic-gate * FUNCTION: meta_sp_get_number_of_possible_sps()
31957c478bd9Sstevel@tonic-gate * INPUT: mdsetnamep - a reference to the mdsetname_t structure
31967c478bd9Sstevel@tonic-gate * for the set containing the device for
31977c478bd9Sstevel@tonic-gate * which the number of possible soft partitions
31987c478bd9Sstevel@tonic-gate * is to be returned
31997c478bd9Sstevel@tonic-gate * mdnamep - a reference to the mdname_t of the device
32007c478bd9Sstevel@tonic-gate * for which the number of possible soft partitions
32017c478bd9Sstevel@tonic-gate * is to be returned
32027c478bd9Sstevel@tonic-gate * OUTPUT: int return value
32037c478bd9Sstevel@tonic-gate * RETURNS: int - the number of soft partitions of the desired size
32047c478bd9Sstevel@tonic-gate * that can be created on the device
32057c478bd9Sstevel@tonic-gate * PURPOSE: returns the number of soft partitions of a given size
32067c478bd9Sstevel@tonic-gate * that can be created on a device
32077c478bd9Sstevel@tonic-gate */
32087c478bd9Sstevel@tonic-gate int
meta_sp_get_number_of_possible_sps(mdsetname_t * mdsetnamep,mdname_t * mdnamep,blkcnt_t sp_size)32097c478bd9Sstevel@tonic-gate meta_sp_get_number_of_possible_sps(
32107c478bd9Sstevel@tonic-gate mdsetname_t *mdsetnamep,
32117c478bd9Sstevel@tonic-gate mdname_t *mdnamep,
32127c478bd9Sstevel@tonic-gate blkcnt_t sp_size
32137c478bd9Sstevel@tonic-gate )
32147c478bd9Sstevel@tonic-gate {
32157c478bd9Sstevel@tonic-gate sp_ext_node_t *extent_listp;
32167c478bd9Sstevel@tonic-gate int number_of_possible_sps;
32177c478bd9Sstevel@tonic-gate boolean_t succeeded;
32187c478bd9Sstevel@tonic-gate md_error_t mde;
32197c478bd9Sstevel@tonic-gate sp_ext_length_t alignment;
32207c478bd9Sstevel@tonic-gate
32217c478bd9Sstevel@tonic-gate extent_listp = NULL;
32227c478bd9Sstevel@tonic-gate number_of_possible_sps = 0;
32237c478bd9Sstevel@tonic-gate if (sp_size > 0) {
32247c478bd9Sstevel@tonic-gate if ((succeeded = meta_sp_get_extent_list(mdsetnamep,
32257c478bd9Sstevel@tonic-gate mdnamep, &extent_listp, &mde)) == B_FALSE)
32267c478bd9Sstevel@tonic-gate mdclrerror(&mde);
32277c478bd9Sstevel@tonic-gate } else {
32287c478bd9Sstevel@tonic-gate succeeded = B_FALSE;
32297c478bd9Sstevel@tonic-gate }
32307c478bd9Sstevel@tonic-gate
32317c478bd9Sstevel@tonic-gate if (succeeded == B_TRUE) {
32327c478bd9Sstevel@tonic-gate alignment = meta_sp_get_default_alignment(mdsetnamep,
32337c478bd9Sstevel@tonic-gate mdnamep, &mde);
32347c478bd9Sstevel@tonic-gate }
32357c478bd9Sstevel@tonic-gate
32367c478bd9Sstevel@tonic-gate while (succeeded == B_TRUE) {
32377c478bd9Sstevel@tonic-gate /*
32387c478bd9Sstevel@tonic-gate * Keep allocating space from the extent list
32397c478bd9Sstevel@tonic-gate * for soft partitions of the desired size until
32407c478bd9Sstevel@tonic-gate * there's not enough free space left in the list
32417c478bd9Sstevel@tonic-gate * for another soft partiition of that size.
32427c478bd9Sstevel@tonic-gate * Add one to the number of possible soft partitions
32437c478bd9Sstevel@tonic-gate * for each soft partition for which there is
32447c478bd9Sstevel@tonic-gate * enough free space left.
32457c478bd9Sstevel@tonic-gate */
32467c478bd9Sstevel@tonic-gate succeeded = meta_sp_enough_space(ONE_SOFT_PARTITION,
32477c478bd9Sstevel@tonic-gate sp_size, &extent_listp, alignment);
32487c478bd9Sstevel@tonic-gate if (succeeded == B_TRUE) {
32497c478bd9Sstevel@tonic-gate number_of_possible_sps++;
32507c478bd9Sstevel@tonic-gate }
32517c478bd9Sstevel@tonic-gate }
32527c478bd9Sstevel@tonic-gate if (extent_listp != NULL) {
32537c478bd9Sstevel@tonic-gate meta_sp_list_free(&extent_listp);
32547c478bd9Sstevel@tonic-gate }
32557c478bd9Sstevel@tonic-gate return (number_of_possible_sps);
32567c478bd9Sstevel@tonic-gate }
32577c478bd9Sstevel@tonic-gate
32587c478bd9Sstevel@tonic-gate /*
32597c478bd9Sstevel@tonic-gate * FUNCTION: meta_sp_get_number_of_possible_sps_on_drive()
32607c478bd9Sstevel@tonic-gate * INPUT: mdsetnamep - a reference to the mdsetname_t structure
32617c478bd9Sstevel@tonic-gate * for the set containing the drive for
32627c478bd9Sstevel@tonic-gate * which the number of possible soft partitions
32637c478bd9Sstevel@tonic-gate * is to be returned
32647c478bd9Sstevel@tonic-gate * mddrivenamep - a reference to the mddrivename_t of the drive
32657c478bd9Sstevel@tonic-gate * for which the number of possible soft partitions
32667c478bd9Sstevel@tonic-gate * is to be returned
32677c478bd9Sstevel@tonic-gate * sp_size - the size in blocks of the proposed soft partitions
32687c478bd9Sstevel@tonic-gate * OUTPUT: int return value
32697c478bd9Sstevel@tonic-gate * RETURNS: int - the number of soft partitions of the desired size
32707c478bd9Sstevel@tonic-gate * that can be created on the drive
32717c478bd9Sstevel@tonic-gate * PURPOSE: returns the number of soft partitions of a given size
32727c478bd9Sstevel@tonic-gate * that can be created on a drive, if the entire drive is
32737c478bd9Sstevel@tonic-gate * soft partitioned
32747c478bd9Sstevel@tonic-gate */
32757c478bd9Sstevel@tonic-gate int
meta_sp_get_number_of_possible_sps_on_drive(mdsetname_t * mdsetnamep,mddrivename_t * mddrivenamep,blkcnt_t sp_size)32767c478bd9Sstevel@tonic-gate meta_sp_get_number_of_possible_sps_on_drive(
32777c478bd9Sstevel@tonic-gate mdsetname_t *mdsetnamep,
32787c478bd9Sstevel@tonic-gate mddrivename_t *mddrivenamep,
32797c478bd9Sstevel@tonic-gate blkcnt_t sp_size
32807c478bd9Sstevel@tonic-gate )
32817c478bd9Sstevel@tonic-gate {
32827c478bd9Sstevel@tonic-gate sp_ext_node_t *extent_listp;
32837c478bd9Sstevel@tonic-gate int number_of_possible_sps;
32847c478bd9Sstevel@tonic-gate boolean_t succeeded;
32857c478bd9Sstevel@tonic-gate
32867c478bd9Sstevel@tonic-gate extent_listp = NULL;
32877c478bd9Sstevel@tonic-gate number_of_possible_sps = 0;
32887c478bd9Sstevel@tonic-gate if (sp_size > 0) {
32897c478bd9Sstevel@tonic-gate succeeded = meta_sp_get_extent_list_for_drive(mdsetnamep,
32907c478bd9Sstevel@tonic-gate mddrivenamep, &extent_listp);
32917c478bd9Sstevel@tonic-gate } else {
32927c478bd9Sstevel@tonic-gate succeeded = B_FALSE;
32937c478bd9Sstevel@tonic-gate }
32947c478bd9Sstevel@tonic-gate while (succeeded == B_TRUE) {
32957c478bd9Sstevel@tonic-gate /*
32967c478bd9Sstevel@tonic-gate * Keep allocating space from the extent list
32977c478bd9Sstevel@tonic-gate * for soft partitions of the desired size until
32987c478bd9Sstevel@tonic-gate * there's not enough free space left in the list
32997c478bd9Sstevel@tonic-gate * for another soft partition of that size.
33007c478bd9Sstevel@tonic-gate * Add one to the number of possible soft partitions
33017c478bd9Sstevel@tonic-gate * for each soft partition for which there is
33027c478bd9Sstevel@tonic-gate * enough free space left.
33037c478bd9Sstevel@tonic-gate *
33047c478bd9Sstevel@tonic-gate * Since it's a drive, not a metadevice, make no
33057c478bd9Sstevel@tonic-gate * assumptions about alignment.
33067c478bd9Sstevel@tonic-gate */
33077c478bd9Sstevel@tonic-gate succeeded = meta_sp_enough_space(ONE_SOFT_PARTITION,
33087c478bd9Sstevel@tonic-gate sp_size, &extent_listp, SP_UNALIGNED);
33097c478bd9Sstevel@tonic-gate if (succeeded == B_TRUE) {
33107c478bd9Sstevel@tonic-gate number_of_possible_sps++;
33117c478bd9Sstevel@tonic-gate }
33127c478bd9Sstevel@tonic-gate }
33137c478bd9Sstevel@tonic-gate if (extent_listp != NULL) {
33147c478bd9Sstevel@tonic-gate meta_sp_list_free(&extent_listp);
33157c478bd9Sstevel@tonic-gate }
33167c478bd9Sstevel@tonic-gate return (number_of_possible_sps);
33177c478bd9Sstevel@tonic-gate }
33187c478bd9Sstevel@tonic-gate
33197c478bd9Sstevel@tonic-gate /*
33207c478bd9Sstevel@tonic-gate * FUNCTION: meta_sp_get_possible_sp_size()
33217c478bd9Sstevel@tonic-gate * INPUT: mdsetnamep - a reference to the mdsetname_t structure
33227c478bd9Sstevel@tonic-gate * for the set containing the device for
33237c478bd9Sstevel@tonic-gate * which the possible soft partition size
33247c478bd9Sstevel@tonic-gate * is to be returned
33257c478bd9Sstevel@tonic-gate * mdnamep - a reference to the mdname_t of the device
33267c478bd9Sstevel@tonic-gate * for which the possible soft partition size
33277c478bd9Sstevel@tonic-gate * is to be returned
33287c478bd9Sstevel@tonic-gate * number_of_sps - the desired number of soft partitions
33297c478bd9Sstevel@tonic-gate * OUTPUT: blkcnt_t return value
33307c478bd9Sstevel@tonic-gate * RETURNS: blkcnt_t - the possible soft partition size in blocks
33317c478bd9Sstevel@tonic-gate * PURPOSE: returns the maximum possible size of each of a given number of
33327c478bd9Sstevel@tonic-gate * soft partitions of equal size that can be created on a device
33337c478bd9Sstevel@tonic-gate */
33347c478bd9Sstevel@tonic-gate blkcnt_t
meta_sp_get_possible_sp_size(mdsetname_t * mdsetnamep,mdname_t * mdnamep,int number_of_sps)33357c478bd9Sstevel@tonic-gate meta_sp_get_possible_sp_size(
33367c478bd9Sstevel@tonic-gate mdsetname_t *mdsetnamep,
33377c478bd9Sstevel@tonic-gate mdname_t *mdnamep,
33387c478bd9Sstevel@tonic-gate int number_of_sps
33397c478bd9Sstevel@tonic-gate )
33407c478bd9Sstevel@tonic-gate {
33417c478bd9Sstevel@tonic-gate blkcnt_t free_blocks;
33427c478bd9Sstevel@tonic-gate blkcnt_t sp_size;
33437c478bd9Sstevel@tonic-gate boolean_t succeeded;
33447c478bd9Sstevel@tonic-gate
33457c478bd9Sstevel@tonic-gate sp_size = 0;
33467c478bd9Sstevel@tonic-gate if (number_of_sps > 0) {
33477c478bd9Sstevel@tonic-gate free_blocks = meta_sp_get_free_space(mdsetnamep, mdnamep);
33487c478bd9Sstevel@tonic-gate sp_size = free_blocks / number_of_sps;
33497c478bd9Sstevel@tonic-gate succeeded = meta_sp_can_create_sps(mdsetnamep, mdnamep,
33507c478bd9Sstevel@tonic-gate number_of_sps, sp_size);
33517c478bd9Sstevel@tonic-gate while ((succeeded == B_FALSE) && (sp_size > 0)) {
33527c478bd9Sstevel@tonic-gate /*
33537c478bd9Sstevel@tonic-gate * To compensate for space that may have been
33547c478bd9Sstevel@tonic-gate * occupied by watermarks, reduce sp_size by a
33557c478bd9Sstevel@tonic-gate * number of blocks equal to the number of soft
33567c478bd9Sstevel@tonic-gate * partitions desired, and test again to see
33577c478bd9Sstevel@tonic-gate * whether the desired number of soft partitions
33587c478bd9Sstevel@tonic-gate * can be created.
33597c478bd9Sstevel@tonic-gate */
33607c478bd9Sstevel@tonic-gate sp_size = sp_size - ((blkcnt_t)number_of_sps);
33617c478bd9Sstevel@tonic-gate succeeded = meta_sp_can_create_sps(mdsetnamep, mdnamep,
33627c478bd9Sstevel@tonic-gate number_of_sps, sp_size);
33637c478bd9Sstevel@tonic-gate }
33647c478bd9Sstevel@tonic-gate if (sp_size < 0) {
33657c478bd9Sstevel@tonic-gate sp_size = 0;
33667c478bd9Sstevel@tonic-gate }
33677c478bd9Sstevel@tonic-gate }
33687c478bd9Sstevel@tonic-gate return (sp_size);
33697c478bd9Sstevel@tonic-gate }
33707c478bd9Sstevel@tonic-gate
33717c478bd9Sstevel@tonic-gate /*
33727c478bd9Sstevel@tonic-gate * FUNCTION: meta_sp_get_possible_sp_size_on_drive()
33737c478bd9Sstevel@tonic-gate * INPUT: mdsetnamep - a reference to the mdsetname_t structure
33747c478bd9Sstevel@tonic-gate * for the set containing the drive for
33757c478bd9Sstevel@tonic-gate * which the possible soft partition size
33767c478bd9Sstevel@tonic-gate * is to be returned
33777c478bd9Sstevel@tonic-gate * mddrivenamep - a reference to the mddrivename_t of the drive
33787c478bd9Sstevel@tonic-gate * for which the possible soft partition size
33797c478bd9Sstevel@tonic-gate * is to be returned
33807c478bd9Sstevel@tonic-gate * number_of_sps - the desired number of soft partitions
33817c478bd9Sstevel@tonic-gate * OUTPUT: blkcnt_t return value
33827c478bd9Sstevel@tonic-gate * RETURNS: blkcnt_t - the possible soft partition size in blocks
33837c478bd9Sstevel@tonic-gate * PURPOSE: returns the maximum possible size of each of a given number of
33847c478bd9Sstevel@tonic-gate * soft partitions of equal size that can be created on a drive
33857c478bd9Sstevel@tonic-gate * if the entire drive is soft partitioned
33867c478bd9Sstevel@tonic-gate */
33877c478bd9Sstevel@tonic-gate blkcnt_t
meta_sp_get_possible_sp_size_on_drive(mdsetname_t * mdsetnamep,mddrivename_t * mddrivenamep,int number_of_sps)33887c478bd9Sstevel@tonic-gate meta_sp_get_possible_sp_size_on_drive(
33897c478bd9Sstevel@tonic-gate mdsetname_t *mdsetnamep,
33907c478bd9Sstevel@tonic-gate mddrivename_t *mddrivenamep,
33917c478bd9Sstevel@tonic-gate int number_of_sps
33927c478bd9Sstevel@tonic-gate )
33937c478bd9Sstevel@tonic-gate {
33947c478bd9Sstevel@tonic-gate blkcnt_t free_blocks;
33957c478bd9Sstevel@tonic-gate blkcnt_t sp_size;
33967c478bd9Sstevel@tonic-gate boolean_t succeeded;
33977c478bd9Sstevel@tonic-gate
33987c478bd9Sstevel@tonic-gate sp_size = 0;
33997c478bd9Sstevel@tonic-gate if (number_of_sps > 0) {
34007c478bd9Sstevel@tonic-gate free_blocks = meta_sp_get_free_space_on_drive(mdsetnamep,
34017c478bd9Sstevel@tonic-gate mddrivenamep);
34027c478bd9Sstevel@tonic-gate sp_size = free_blocks / number_of_sps;
34037c478bd9Sstevel@tonic-gate succeeded = meta_sp_can_create_sps_on_drive(mdsetnamep,
34041cd3f00bSsk102515 mddrivenamep, number_of_sps, sp_size);
34057c478bd9Sstevel@tonic-gate while ((succeeded == B_FALSE) && (sp_size > 0)) {
34067c478bd9Sstevel@tonic-gate /*
34077c478bd9Sstevel@tonic-gate * To compensate for space that may have been
34087c478bd9Sstevel@tonic-gate * occupied by watermarks, reduce sp_size by a
34097c478bd9Sstevel@tonic-gate * number of blocks equal to the number of soft
34107c478bd9Sstevel@tonic-gate * partitions desired, and test again to see
34117c478bd9Sstevel@tonic-gate * whether the desired number of soft partitions
34127c478bd9Sstevel@tonic-gate * can be created.
34137c478bd9Sstevel@tonic-gate */
34147c478bd9Sstevel@tonic-gate sp_size = sp_size - ((blkcnt_t)number_of_sps);
34157c478bd9Sstevel@tonic-gate succeeded = meta_sp_can_create_sps_on_drive(mdsetnamep,
34161cd3f00bSsk102515 mddrivenamep, number_of_sps, sp_size);
34177c478bd9Sstevel@tonic-gate }
34187c478bd9Sstevel@tonic-gate if (sp_size < 0) {
34197c478bd9Sstevel@tonic-gate sp_size = 0;
34207c478bd9Sstevel@tonic-gate }
34217c478bd9Sstevel@tonic-gate }
34227c478bd9Sstevel@tonic-gate return (sp_size);
34237c478bd9Sstevel@tonic-gate }
34247c478bd9Sstevel@tonic-gate
34257c478bd9Sstevel@tonic-gate /*
34267c478bd9Sstevel@tonic-gate * **************************************************************************
34277c478bd9Sstevel@tonic-gate * Unit Structure Manipulation Functions *
34287c478bd9Sstevel@tonic-gate * **************************************************************************
34297c478bd9Sstevel@tonic-gate */
34307c478bd9Sstevel@tonic-gate
34317c478bd9Sstevel@tonic-gate /*
34327c478bd9Sstevel@tonic-gate * FUNCTION: meta_sp_fillextarray()
34337c478bd9Sstevel@tonic-gate * INPUT: mp - the unit structure to fill
34347c478bd9Sstevel@tonic-gate * extlist - the list of extents to fill with
34357c478bd9Sstevel@tonic-gate * OUTPUT: none
34367c478bd9Sstevel@tonic-gate * RETURNS: void
34377c478bd9Sstevel@tonic-gate * PURPOSE: fills in the unit structure extent list with the extents
34387c478bd9Sstevel@tonic-gate * specified by extlist. Only extents in extlist with the
34397c478bd9Sstevel@tonic-gate * EXTFLG_UPDATE flag are changed in the unit structure,
34407c478bd9Sstevel@tonic-gate * and the index into the unit structure is the sequence
34417c478bd9Sstevel@tonic-gate * number in the extent list. After all of the nodes have
34427c478bd9Sstevel@tonic-gate * been updated the virtual offsets in the unit structure
34437c478bd9Sstevel@tonic-gate * are updated to reflect the new lengths.
34447c478bd9Sstevel@tonic-gate */
34457c478bd9Sstevel@tonic-gate static void
meta_sp_fillextarray(mp_unit_t * mp,sp_ext_node_t * extlist)34467c478bd9Sstevel@tonic-gate meta_sp_fillextarray(
34477c478bd9Sstevel@tonic-gate mp_unit_t *mp,
34487c478bd9Sstevel@tonic-gate sp_ext_node_t *extlist
34497c478bd9Sstevel@tonic-gate )
34507c478bd9Sstevel@tonic-gate {
34517c478bd9Sstevel@tonic-gate int i;
34527c478bd9Sstevel@tonic-gate sp_ext_node_t *ext;
34537c478bd9Sstevel@tonic-gate sp_ext_offset_t curvoff = 0LL;
34547c478bd9Sstevel@tonic-gate
34557c478bd9Sstevel@tonic-gate assert(mp != NULL);
34567c478bd9Sstevel@tonic-gate
34577c478bd9Sstevel@tonic-gate /* go through the allocation list and fill in our unit structure */
34587c478bd9Sstevel@tonic-gate for (ext = extlist; ext != NULL; ext = ext->ext_next) {
34597c478bd9Sstevel@tonic-gate if ((ext->ext_type == EXTTYP_ALLOC) &&
34607c478bd9Sstevel@tonic-gate (ext->ext_flags & EXTFLG_UPDATE) != 0) {
34617c478bd9Sstevel@tonic-gate mp->un_ext[ext->ext_seq].un_poff =
34627c478bd9Sstevel@tonic-gate ext->ext_offset + MD_SP_WMSIZE;
34637c478bd9Sstevel@tonic-gate mp->un_ext[ext->ext_seq].un_len =
34647c478bd9Sstevel@tonic-gate ext->ext_length - MD_SP_WMSIZE;
34657c478bd9Sstevel@tonic-gate }
34667c478bd9Sstevel@tonic-gate }
34677c478bd9Sstevel@tonic-gate
34687c478bd9Sstevel@tonic-gate for (i = 0; i < mp->un_numexts; i++) {
34697c478bd9Sstevel@tonic-gate assert(mp->un_ext[i].un_poff != 0);
34707c478bd9Sstevel@tonic-gate assert(mp->un_ext[i].un_len != 0);
34717c478bd9Sstevel@tonic-gate mp->un_ext[i].un_voff = curvoff;
34727c478bd9Sstevel@tonic-gate curvoff += mp->un_ext[i].un_len;
34737c478bd9Sstevel@tonic-gate }
34747c478bd9Sstevel@tonic-gate }
34757c478bd9Sstevel@tonic-gate
34767c478bd9Sstevel@tonic-gate /*
34777c478bd9Sstevel@tonic-gate * FUNCTION: meta_sp_createunit()
34787c478bd9Sstevel@tonic-gate * INPUT: np - the name of the device to create a unit structure for
34797c478bd9Sstevel@tonic-gate * compnp - the name of the device the soft partition is on
34807c478bd9Sstevel@tonic-gate * extlist - the extent list to populate the new unit with
34817c478bd9Sstevel@tonic-gate * numexts - the number of extents in the extent list
34827c478bd9Sstevel@tonic-gate * len - the total size of the soft partition (sectors)
34837c478bd9Sstevel@tonic-gate * status - the initial status of the unit structure
34847c478bd9Sstevel@tonic-gate * OUTPUT: ep - return error pointer
34857c478bd9Sstevel@tonic-gate * RETURNS: mp_unit_t * - the new unit structure.
34867c478bd9Sstevel@tonic-gate * PURPOSE: allocates and fills in a new soft partition unit
34877c478bd9Sstevel@tonic-gate * structure to be passed to the soft partitioning driver
34887c478bd9Sstevel@tonic-gate * for creation.
34897c478bd9Sstevel@tonic-gate */
34907c478bd9Sstevel@tonic-gate static mp_unit_t *
meta_sp_createunit(mdname_t * np,mdname_t * compnp,sp_ext_node_t * extlist,int numexts,sp_ext_length_t len,sp_status_t status,md_error_t * ep)34917c478bd9Sstevel@tonic-gate meta_sp_createunit(
34927c478bd9Sstevel@tonic-gate mdname_t *np,
34937c478bd9Sstevel@tonic-gate mdname_t *compnp,
34947c478bd9Sstevel@tonic-gate sp_ext_node_t *extlist,
34957c478bd9Sstevel@tonic-gate int numexts,
34967c478bd9Sstevel@tonic-gate sp_ext_length_t len,
34977c478bd9Sstevel@tonic-gate sp_status_t status,
34987c478bd9Sstevel@tonic-gate md_error_t *ep
34997c478bd9Sstevel@tonic-gate )
35007c478bd9Sstevel@tonic-gate {
35017c478bd9Sstevel@tonic-gate mp_unit_t *mp;
35027c478bd9Sstevel@tonic-gate uint_t ms_size;
35037c478bd9Sstevel@tonic-gate
35047c478bd9Sstevel@tonic-gate ms_size = (sizeof (*mp) - sizeof (mp->un_ext[0])) +
35057c478bd9Sstevel@tonic-gate (numexts * sizeof (mp->un_ext[0]));
35067c478bd9Sstevel@tonic-gate
35077c478bd9Sstevel@tonic-gate mp = Zalloc(ms_size);
35087c478bd9Sstevel@tonic-gate
35097c478bd9Sstevel@tonic-gate /* fill in fields in common unit structure */
35107c478bd9Sstevel@tonic-gate mp->c.un_type = MD_METASP;
35117c478bd9Sstevel@tonic-gate mp->c.un_size = ms_size;
35127c478bd9Sstevel@tonic-gate MD_SID(mp) = meta_getminor(np->dev);
35137c478bd9Sstevel@tonic-gate mp->c.un_total_blocks = len;
35147c478bd9Sstevel@tonic-gate mp->c.un_actual_tb = len;
35157c478bd9Sstevel@tonic-gate
35167c478bd9Sstevel@tonic-gate /* set up geometry */
35177c478bd9Sstevel@tonic-gate (void) meta_sp_setgeom(np, compnp, mp, ep);
35187c478bd9Sstevel@tonic-gate
35197c478bd9Sstevel@tonic-gate /* if we're building on metadevice we can't parent */
35207c478bd9Sstevel@tonic-gate if (metaismeta(compnp))
35217c478bd9Sstevel@tonic-gate MD_CAPAB(mp) = MD_CANT_PARENT;
35227c478bd9Sstevel@tonic-gate else
35237c478bd9Sstevel@tonic-gate MD_CAPAB(mp) = MD_CAN_PARENT;
35247c478bd9Sstevel@tonic-gate
35257c478bd9Sstevel@tonic-gate /* fill soft partition-specific fields */
35267c478bd9Sstevel@tonic-gate mp->un_dev = compnp->dev;
35277c478bd9Sstevel@tonic-gate mp->un_key = compnp->key;
35287c478bd9Sstevel@tonic-gate
35297c478bd9Sstevel@tonic-gate /* mdname_t start_blk field is not 64-bit! */
35307c478bd9Sstevel@tonic-gate mp->un_start_blk = (sp_ext_offset_t)compnp->start_blk;
35317c478bd9Sstevel@tonic-gate mp->un_status = status;
35327c478bd9Sstevel@tonic-gate mp->un_numexts = numexts;
35337c478bd9Sstevel@tonic-gate mp->un_length = len;
35347c478bd9Sstevel@tonic-gate
35357c478bd9Sstevel@tonic-gate /* fill in the extent array */
35367c478bd9Sstevel@tonic-gate meta_sp_fillextarray(mp, extlist);
35377c478bd9Sstevel@tonic-gate
35387c478bd9Sstevel@tonic-gate return (mp);
35397c478bd9Sstevel@tonic-gate }
35407c478bd9Sstevel@tonic-gate
35417c478bd9Sstevel@tonic-gate /*
35427c478bd9Sstevel@tonic-gate * FUNCTION: meta_sp_updateunit()
35437c478bd9Sstevel@tonic-gate * INPUT: np - name structure for the metadevice being updated
35447c478bd9Sstevel@tonic-gate * old_un - the original unit structure that is being updated
35457c478bd9Sstevel@tonic-gate * extlist - the extent list to populate the new unit with
35467c478bd9Sstevel@tonic-gate * grow_len - the amount by which the partition is being grown
35477c478bd9Sstevel@tonic-gate * numexts - the number of extents in the extent list
35487c478bd9Sstevel@tonic-gate * ep - return error pointer
35497c478bd9Sstevel@tonic-gate * OUTPUT: none
35507c478bd9Sstevel@tonic-gate * RETURNS: mp_unit_t * - the updated unit structure
35517c478bd9Sstevel@tonic-gate * PURPOSE: allocates and fills in a new soft partition unit structure to
35527c478bd9Sstevel@tonic-gate * be passed to the soft partitioning driver for creation. The
35537c478bd9Sstevel@tonic-gate * old unit structure is first copied in, and then the updated
35547c478bd9Sstevel@tonic-gate * extents are changed in the new unit structure. This is
35557c478bd9Sstevel@tonic-gate * typically used when the size of an existing unit is changed.
35567c478bd9Sstevel@tonic-gate */
35577c478bd9Sstevel@tonic-gate static mp_unit_t *
meta_sp_updateunit(mdname_t * np,mp_unit_t * old_un,sp_ext_node_t * extlist,sp_ext_length_t grow_len,int numexts,md_error_t * ep)35587c478bd9Sstevel@tonic-gate meta_sp_updateunit(
35597c478bd9Sstevel@tonic-gate mdname_t *np,
35607c478bd9Sstevel@tonic-gate mp_unit_t *old_un,
35617c478bd9Sstevel@tonic-gate sp_ext_node_t *extlist,
35627c478bd9Sstevel@tonic-gate sp_ext_length_t grow_len,
35637c478bd9Sstevel@tonic-gate int numexts,
35647c478bd9Sstevel@tonic-gate md_error_t *ep
35657c478bd9Sstevel@tonic-gate )
35667c478bd9Sstevel@tonic-gate {
35677c478bd9Sstevel@tonic-gate mp_unit_t *new_un;
35687c478bd9Sstevel@tonic-gate sp_ext_length_t new_len;
35697c478bd9Sstevel@tonic-gate uint_t new_size;
35707c478bd9Sstevel@tonic-gate
35717c478bd9Sstevel@tonic-gate assert(old_un != NULL);
35727c478bd9Sstevel@tonic-gate assert(extlist != NULL);
35737c478bd9Sstevel@tonic-gate
35747c478bd9Sstevel@tonic-gate /* allocate new unit structure and copy in old unit */
35757c478bd9Sstevel@tonic-gate new_size = (sizeof (*old_un) - sizeof (old_un->un_ext[0])) +
35767c478bd9Sstevel@tonic-gate ((old_un->un_numexts + numexts) * sizeof (old_un->un_ext[0]));
35777c478bd9Sstevel@tonic-gate new_len = old_un->un_length + grow_len;
35787c478bd9Sstevel@tonic-gate new_un = Zalloc(new_size);
35797c478bd9Sstevel@tonic-gate bcopy(old_un, new_un, old_un->c.un_size);
35807c478bd9Sstevel@tonic-gate
35817c478bd9Sstevel@tonic-gate /* update size and geometry information */
35827c478bd9Sstevel@tonic-gate new_un->c.un_size = new_size;
35837c478bd9Sstevel@tonic-gate new_un->un_length = new_len;
35847c478bd9Sstevel@tonic-gate new_un->c.un_total_blocks = new_len;
35857c478bd9Sstevel@tonic-gate new_un->c.un_actual_tb = new_len;
35867c478bd9Sstevel@tonic-gate if (meta_adjust_geom((md_unit_t *)new_un, np,
35877c478bd9Sstevel@tonic-gate old_un->c.un_wr_reinstruct, old_un->c.un_rd_reinstruct,
35887c478bd9Sstevel@tonic-gate 0, ep) != 0) {
35897c478bd9Sstevel@tonic-gate Free(new_un);
35907c478bd9Sstevel@tonic-gate return (NULL);
35917c478bd9Sstevel@tonic-gate }
35927c478bd9Sstevel@tonic-gate
35937c478bd9Sstevel@tonic-gate /* update extent information */
35947c478bd9Sstevel@tonic-gate new_un->un_numexts += numexts;
35957c478bd9Sstevel@tonic-gate
35967c478bd9Sstevel@tonic-gate meta_sp_fillextarray(new_un, extlist);
35977c478bd9Sstevel@tonic-gate
35987c478bd9Sstevel@tonic-gate return (new_un);
35997c478bd9Sstevel@tonic-gate }
36007c478bd9Sstevel@tonic-gate
36017c478bd9Sstevel@tonic-gate /*
36027c478bd9Sstevel@tonic-gate * FUNCTION: meta_get_sp()
36037c478bd9Sstevel@tonic-gate * INPUT: sp - the set name for the device to get
36047c478bd9Sstevel@tonic-gate * np - the name of the device to get
36057c478bd9Sstevel@tonic-gate * OUTPUT: ep - return error pointer
36067c478bd9Sstevel@tonic-gate * RETURNS: md_sp_t * - the XDR unit structure for the soft partition
36077c478bd9Sstevel@tonic-gate * PURPOSE: interface to the rest of libmeta for fetching a unit structure
36087c478bd9Sstevel@tonic-gate * for the named device. Just a wrapper for meta_get_sp_common().
36097c478bd9Sstevel@tonic-gate */
36107c478bd9Sstevel@tonic-gate md_sp_t *
meta_get_sp(mdsetname_t * sp,mdname_t * np,md_error_t * ep)36117c478bd9Sstevel@tonic-gate meta_get_sp(
36127c478bd9Sstevel@tonic-gate mdsetname_t *sp,
36137c478bd9Sstevel@tonic-gate mdname_t *np,
36147c478bd9Sstevel@tonic-gate md_error_t *ep
36157c478bd9Sstevel@tonic-gate )
36167c478bd9Sstevel@tonic-gate {
36177c478bd9Sstevel@tonic-gate return (meta_get_sp_common(sp, np, 0, ep));
36187c478bd9Sstevel@tonic-gate }
36197c478bd9Sstevel@tonic-gate
36207c478bd9Sstevel@tonic-gate /*
36217c478bd9Sstevel@tonic-gate * FUNCTION: meta_get_sp_common()
36227c478bd9Sstevel@tonic-gate * INPUT: sp - the set name for the device to get
36237c478bd9Sstevel@tonic-gate * np - the name of the device to get
36247c478bd9Sstevel@tonic-gate * fast - whether to use the cache or not (NOT IMPLEMENTED!)
36257c478bd9Sstevel@tonic-gate * OUTPUT: ep - return error pointer
36267c478bd9Sstevel@tonic-gate * RETURNS: md_sp_t * - the XDR unit structure for the soft partition,
36277c478bd9Sstevel@tonic-gate * NULL if np is not a soft partition
36287c478bd9Sstevel@tonic-gate * PURPOSE: common routine for fetching a soft partition unit structure
36297c478bd9Sstevel@tonic-gate */
36307c478bd9Sstevel@tonic-gate md_sp_t *
meta_get_sp_common(mdsetname_t * sp,mdname_t * np,int fast,md_error_t * ep)36317c478bd9Sstevel@tonic-gate meta_get_sp_common(
36327c478bd9Sstevel@tonic-gate mdsetname_t *sp,
36337c478bd9Sstevel@tonic-gate mdname_t *np,
36347c478bd9Sstevel@tonic-gate int fast,
36357c478bd9Sstevel@tonic-gate md_error_t *ep
36367c478bd9Sstevel@tonic-gate )
36377c478bd9Sstevel@tonic-gate {
36387c478bd9Sstevel@tonic-gate mddrivename_t *dnp = np->drivenamep;
36397c478bd9Sstevel@tonic-gate char *miscname;
36407c478bd9Sstevel@tonic-gate mp_unit_t *mp;
36417c478bd9Sstevel@tonic-gate md_sp_t *msp;
36427c478bd9Sstevel@tonic-gate int i;
36437c478bd9Sstevel@tonic-gate
36447c478bd9Sstevel@tonic-gate /* must have set */
36457c478bd9Sstevel@tonic-gate assert(sp != NULL);
36467c478bd9Sstevel@tonic-gate
36477c478bd9Sstevel@tonic-gate /* short circuit */
36487c478bd9Sstevel@tonic-gate if (dnp->unitp != NULL) {
36497c478bd9Sstevel@tonic-gate if (dnp->unitp->type != MD_METASP)
36507c478bd9Sstevel@tonic-gate return (NULL);
36517c478bd9Sstevel@tonic-gate return ((md_sp_t *)dnp->unitp);
36527c478bd9Sstevel@tonic-gate }
36537c478bd9Sstevel@tonic-gate /* get miscname and unit */
36547c478bd9Sstevel@tonic-gate if ((miscname = metagetmiscname(np, ep)) == NULL)
36557c478bd9Sstevel@tonic-gate return (NULL);
36567c478bd9Sstevel@tonic-gate
36577c478bd9Sstevel@tonic-gate if (strcmp(miscname, MD_SP) != 0) {
36587c478bd9Sstevel@tonic-gate (void) mdmderror(ep, MDE_NOT_SP, 0, np->cname);
36597c478bd9Sstevel@tonic-gate return (NULL);
36607c478bd9Sstevel@tonic-gate }
36617c478bd9Sstevel@tonic-gate
36627c478bd9Sstevel@tonic-gate if ((mp = (mp_unit_t *)meta_get_mdunit(sp, np, ep)) == NULL)
36637c478bd9Sstevel@tonic-gate return (NULL);
36647c478bd9Sstevel@tonic-gate
36657c478bd9Sstevel@tonic-gate assert(mp->c.un_type == MD_METASP);
36667c478bd9Sstevel@tonic-gate
36677c478bd9Sstevel@tonic-gate /* allocate soft partition */
36687c478bd9Sstevel@tonic-gate msp = Zalloc(sizeof (*msp));
36697c478bd9Sstevel@tonic-gate
36707c478bd9Sstevel@tonic-gate /* get the common information */
36717c478bd9Sstevel@tonic-gate msp->common.namep = np;
36727c478bd9Sstevel@tonic-gate msp->common.type = mp->c.un_type;
36737c478bd9Sstevel@tonic-gate msp->common.state = mp->c.un_status;
36747c478bd9Sstevel@tonic-gate msp->common.capabilities = mp->c.un_capabilities;
36757c478bd9Sstevel@tonic-gate msp->common.parent = mp->c.un_parent;
36767c478bd9Sstevel@tonic-gate msp->common.size = mp->c.un_total_blocks;
36777c478bd9Sstevel@tonic-gate msp->common.user_flags = mp->c.un_user_flags;
36787c478bd9Sstevel@tonic-gate msp->common.revision = mp->c.un_revision;
36797c478bd9Sstevel@tonic-gate
36807c478bd9Sstevel@tonic-gate /* get soft partition information */
36817c478bd9Sstevel@tonic-gate if ((msp->compnamep = metakeyname(&sp, mp->un_key, fast, ep)) == NULL)
36827c478bd9Sstevel@tonic-gate goto out;
36837c478bd9Sstevel@tonic-gate
36847c478bd9Sstevel@tonic-gate /*
36857c478bd9Sstevel@tonic-gate * Fill in the key and the start block. Note that the start
36867c478bd9Sstevel@tonic-gate * block in the unit structure is 64 bits but the name pointer
36877c478bd9Sstevel@tonic-gate * only supports 32 bits.
36887c478bd9Sstevel@tonic-gate */
36897c478bd9Sstevel@tonic-gate msp->compnamep->key = mp->un_key;
36907c478bd9Sstevel@tonic-gate msp->compnamep->start_blk = mp->un_start_blk;
36917c478bd9Sstevel@tonic-gate
36927c478bd9Sstevel@tonic-gate /* fill in status field */
36937c478bd9Sstevel@tonic-gate msp->status = mp->un_status;
36947c478bd9Sstevel@tonic-gate
36957c478bd9Sstevel@tonic-gate /* allocate the extents */
36967c478bd9Sstevel@tonic-gate msp->ext.ext_val = Zalloc(mp->un_numexts * sizeof (*msp->ext.ext_val));
36977c478bd9Sstevel@tonic-gate msp->ext.ext_len = mp->un_numexts;
36987c478bd9Sstevel@tonic-gate
36997c478bd9Sstevel@tonic-gate /* do the extents for this soft partition */
37007c478bd9Sstevel@tonic-gate for (i = 0; i < mp->un_numexts; i++) {
37017c478bd9Sstevel@tonic-gate struct mp_ext *mde = &mp->un_ext[i];
37027c478bd9Sstevel@tonic-gate md_sp_ext_t *extp = &msp->ext.ext_val[i];
37037c478bd9Sstevel@tonic-gate
37047c478bd9Sstevel@tonic-gate extp->voff = mde->un_voff;
37057c478bd9Sstevel@tonic-gate extp->poff = mde->un_poff;
37067c478bd9Sstevel@tonic-gate extp->len = mde->un_len;
37077c478bd9Sstevel@tonic-gate }
37087c478bd9Sstevel@tonic-gate
37097c478bd9Sstevel@tonic-gate /* cleanup, return success */
37107c478bd9Sstevel@tonic-gate Free(mp);
37117c478bd9Sstevel@tonic-gate dnp->unitp = (md_common_t *)msp;
37127c478bd9Sstevel@tonic-gate return (msp);
37137c478bd9Sstevel@tonic-gate
37147c478bd9Sstevel@tonic-gate out:
37157c478bd9Sstevel@tonic-gate /* clean up and return error */
37167c478bd9Sstevel@tonic-gate Free(mp);
37177c478bd9Sstevel@tonic-gate Free(msp);
37187c478bd9Sstevel@tonic-gate return (NULL);
37197c478bd9Sstevel@tonic-gate }
37207c478bd9Sstevel@tonic-gate
37217c478bd9Sstevel@tonic-gate
37227c478bd9Sstevel@tonic-gate /*
37237c478bd9Sstevel@tonic-gate * FUNCTION: meta_init_sp()
37247c478bd9Sstevel@tonic-gate * INPUT: spp - the set name for the new device
37257c478bd9Sstevel@tonic-gate * argc - the remaining argument count for the metainit cmdline
37267c478bd9Sstevel@tonic-gate * argv - the remainder of the unparsed command line
37277c478bd9Sstevel@tonic-gate * options - global options parsed by metainit
37287c478bd9Sstevel@tonic-gate * OUTPUT: ep - return error pointer
37297c478bd9Sstevel@tonic-gate * RETURNS: int - -1 failure, 0 success
37307c478bd9Sstevel@tonic-gate * PURPOSE: provides the command line parsing and name management overhead
37317c478bd9Sstevel@tonic-gate * for creating a new soft partition. Ultimately this calls
37327c478bd9Sstevel@tonic-gate * meta_create_sp() which does the real work of allocating space
37337c478bd9Sstevel@tonic-gate * for the new soft partition.
37347c478bd9Sstevel@tonic-gate */
37357c478bd9Sstevel@tonic-gate int
meta_init_sp(mdsetname_t ** spp,int argc,char * argv[],mdcmdopts_t options,md_error_t * ep)37367c478bd9Sstevel@tonic-gate meta_init_sp(
37377c478bd9Sstevel@tonic-gate mdsetname_t **spp,
37387c478bd9Sstevel@tonic-gate int argc,
37397c478bd9Sstevel@tonic-gate char *argv[],
37407c478bd9Sstevel@tonic-gate mdcmdopts_t options,
37417c478bd9Sstevel@tonic-gate md_error_t *ep
37427c478bd9Sstevel@tonic-gate )
37437c478bd9Sstevel@tonic-gate {
37447c478bd9Sstevel@tonic-gate char *compname = NULL;
37457c478bd9Sstevel@tonic-gate mdname_t *spcompnp = NULL; /* name of component volume */
37467c478bd9Sstevel@tonic-gate char *devname = argv[0]; /* unit name */
37477c478bd9Sstevel@tonic-gate mdname_t *np = NULL; /* name of soft partition */
37487c478bd9Sstevel@tonic-gate md_sp_t *msp = NULL;
37497c478bd9Sstevel@tonic-gate int c;
37507c478bd9Sstevel@tonic-gate int old_optind;
37517c478bd9Sstevel@tonic-gate sp_ext_length_t len = 0LL;
37527c478bd9Sstevel@tonic-gate int rval = -1;
37537c478bd9Sstevel@tonic-gate uint_t seq;
37547c478bd9Sstevel@tonic-gate int oflag;
37557c478bd9Sstevel@tonic-gate int failed;
37567c478bd9Sstevel@tonic-gate mddrivename_t *dnp = NULL;
37577c478bd9Sstevel@tonic-gate sp_ext_length_t alignment = 0LL;
37587c478bd9Sstevel@tonic-gate sp_ext_node_t *extlist = NULL;
37597c478bd9Sstevel@tonic-gate
37607c478bd9Sstevel@tonic-gate assert(argc > 0);
37617c478bd9Sstevel@tonic-gate
37627c478bd9Sstevel@tonic-gate /* expect sp name, -p, optional -e, compname, and size parameters */
37637c478bd9Sstevel@tonic-gate /* grab soft partition name */
3764d7cd8252Stw21770 if ((np = metaname(spp, devname, META_DEVICE, ep)) == NULL)
37657c478bd9Sstevel@tonic-gate goto out;
37667c478bd9Sstevel@tonic-gate
37677c478bd9Sstevel@tonic-gate /* see if it exists already */
37687c478bd9Sstevel@tonic-gate if (metagetmiscname(np, ep) != NULL) {
37697c478bd9Sstevel@tonic-gate (void) mdmderror(ep, MDE_UNIT_ALREADY_SETUP,
37707c478bd9Sstevel@tonic-gate meta_getminor(np->dev), devname);
37717c478bd9Sstevel@tonic-gate goto out;
37727c478bd9Sstevel@tonic-gate } else if (! mdismderror(ep, MDE_UNIT_NOT_SETUP)) {
37737c478bd9Sstevel@tonic-gate goto out;
37747c478bd9Sstevel@tonic-gate } else {
37757c478bd9Sstevel@tonic-gate mdclrerror(ep);
37767c478bd9Sstevel@tonic-gate }
37777c478bd9Sstevel@tonic-gate --argc, ++argv;
37787c478bd9Sstevel@tonic-gate
37797c478bd9Sstevel@tonic-gate if (argc == 0)
37807c478bd9Sstevel@tonic-gate goto syntax;
37817c478bd9Sstevel@tonic-gate
37827c478bd9Sstevel@tonic-gate /* grab -p */
37837c478bd9Sstevel@tonic-gate if (strcmp(argv[0], "-p") != 0)
37847c478bd9Sstevel@tonic-gate goto syntax;
37857c478bd9Sstevel@tonic-gate --argc, ++argv;
37867c478bd9Sstevel@tonic-gate
37877c478bd9Sstevel@tonic-gate if (argc == 0)
37887c478bd9Sstevel@tonic-gate goto syntax;
37897c478bd9Sstevel@tonic-gate
37907c478bd9Sstevel@tonic-gate /* see if -e is there */
37917c478bd9Sstevel@tonic-gate if (strcmp(argv[0], "-e") == 0) {
37927c478bd9Sstevel@tonic-gate /* use the whole disk */
37937c478bd9Sstevel@tonic-gate options |= MDCMD_USE_WHOLE_DISK;
37947c478bd9Sstevel@tonic-gate --argc, ++argv;
37957c478bd9Sstevel@tonic-gate }
37967c478bd9Sstevel@tonic-gate
37977c478bd9Sstevel@tonic-gate if (argc == 0)
37987c478bd9Sstevel@tonic-gate goto syntax;
37997c478bd9Sstevel@tonic-gate
38007c478bd9Sstevel@tonic-gate /* get component name */
38017c478bd9Sstevel@tonic-gate compname = Strdup(argv[0]);
38027c478bd9Sstevel@tonic-gate
38037c478bd9Sstevel@tonic-gate if (options & MDCMD_USE_WHOLE_DISK) {
38047c478bd9Sstevel@tonic-gate if ((dnp = metadrivename(spp, compname, ep)) == NULL) {
38057c478bd9Sstevel@tonic-gate goto out;
38067c478bd9Sstevel@tonic-gate }
38077c478bd9Sstevel@tonic-gate if ((spcompnp = metaslicename(dnp, 0, ep)) == NULL) {
38087c478bd9Sstevel@tonic-gate goto out;
38097c478bd9Sstevel@tonic-gate }
3810d7cd8252Stw21770 } else if ((spcompnp = metaname(spp, compname, UNKNOWN, ep)) == NULL) {
38117c478bd9Sstevel@tonic-gate goto out;
38127c478bd9Sstevel@tonic-gate }
38137c478bd9Sstevel@tonic-gate assert(*spp != NULL);
38147c478bd9Sstevel@tonic-gate
38157c478bd9Sstevel@tonic-gate if (!(options & MDCMD_NOLOCK)) {
38167c478bd9Sstevel@tonic-gate /* grab set lock */
38177c478bd9Sstevel@tonic-gate if (meta_lock(*spp, TRUE, ep))
38187c478bd9Sstevel@tonic-gate goto out;
38197c478bd9Sstevel@tonic-gate
38207c478bd9Sstevel@tonic-gate if (meta_check_ownership(*spp, ep) != 0)
38217c478bd9Sstevel@tonic-gate goto out;
38227c478bd9Sstevel@tonic-gate }
38237c478bd9Sstevel@tonic-gate
38247c478bd9Sstevel@tonic-gate /* allocate the soft partition */
38257c478bd9Sstevel@tonic-gate msp = Zalloc(sizeof (*msp));
38267c478bd9Sstevel@tonic-gate
38277c478bd9Sstevel@tonic-gate /* setup common */
38287c478bd9Sstevel@tonic-gate msp->common.namep = np;
38297c478bd9Sstevel@tonic-gate msp->common.type = MD_METASP;
38307c478bd9Sstevel@tonic-gate
38317c478bd9Sstevel@tonic-gate compname = spcompnp->cname;
38327c478bd9Sstevel@tonic-gate
38337c478bd9Sstevel@tonic-gate assert(spcompnp->rname != NULL);
38347c478bd9Sstevel@tonic-gate --argc, ++argv;
38357c478bd9Sstevel@tonic-gate
38367c478bd9Sstevel@tonic-gate if (argc == 0) {
38377c478bd9Sstevel@tonic-gate goto syntax;
38387c478bd9Sstevel@tonic-gate }
38397c478bd9Sstevel@tonic-gate
38407c478bd9Sstevel@tonic-gate if (*argv[0] == '-') {
38417c478bd9Sstevel@tonic-gate /*
38427c478bd9Sstevel@tonic-gate * parse any other command line options, this includes
38437c478bd9Sstevel@tonic-gate * the recovery options -o and -b. The special thing
38447c478bd9Sstevel@tonic-gate * with these options is that the len needs to be
38457c478bd9Sstevel@tonic-gate * kept track of otherwise when the geometry of the
38467c478bd9Sstevel@tonic-gate * "device" is built it will create an invalid geometry
38477c478bd9Sstevel@tonic-gate */
38487c478bd9Sstevel@tonic-gate old_optind = optind = 0;
38497c478bd9Sstevel@tonic-gate opterr = 0;
38507c478bd9Sstevel@tonic-gate oflag = 0;
38517c478bd9Sstevel@tonic-gate seq = 0;
38527c478bd9Sstevel@tonic-gate failed = 0;
38537c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv, "A:o:b:")) != -1) {
38547c478bd9Sstevel@tonic-gate sp_ext_offset_t offset;
38557c478bd9Sstevel@tonic-gate sp_ext_length_t length;
38567c478bd9Sstevel@tonic-gate longlong_t tmp_size;
38577c478bd9Sstevel@tonic-gate
38587c478bd9Sstevel@tonic-gate switch (c) {
38597c478bd9Sstevel@tonic-gate case 'A': /* data alignment */
38607c478bd9Sstevel@tonic-gate if (meta_sp_parsesizestring(optarg,
38617c478bd9Sstevel@tonic-gate &alignment) == -1) {
38627c478bd9Sstevel@tonic-gate failed = 1;
38637c478bd9Sstevel@tonic-gate }
38647c478bd9Sstevel@tonic-gate break;
38657c478bd9Sstevel@tonic-gate case 'o': /* offset in the partition */
38667c478bd9Sstevel@tonic-gate if (oflag == 1) {
38677c478bd9Sstevel@tonic-gate failed = 1;
38687c478bd9Sstevel@tonic-gate } else {
38697c478bd9Sstevel@tonic-gate tmp_size = atoll(optarg);
38707c478bd9Sstevel@tonic-gate if (tmp_size <= 0) {
38717c478bd9Sstevel@tonic-gate failed = 1;
38727c478bd9Sstevel@tonic-gate } else {
38737c478bd9Sstevel@tonic-gate oflag = 1;
38747c478bd9Sstevel@tonic-gate options |= MDCMD_DIRECT;
38757c478bd9Sstevel@tonic-gate
38767c478bd9Sstevel@tonic-gate offset = tmp_size;
38777c478bd9Sstevel@tonic-gate }
38787c478bd9Sstevel@tonic-gate }
38797c478bd9Sstevel@tonic-gate
38807c478bd9Sstevel@tonic-gate break;
38817c478bd9Sstevel@tonic-gate case 'b': /* number of blocks */
38827c478bd9Sstevel@tonic-gate if (oflag == 0) {
38837c478bd9Sstevel@tonic-gate failed = 1;
38847c478bd9Sstevel@tonic-gate } else {
38857c478bd9Sstevel@tonic-gate tmp_size = atoll(optarg);
38867c478bd9Sstevel@tonic-gate if (tmp_size <= 0) {
38877c478bd9Sstevel@tonic-gate failed = 1;
38887c478bd9Sstevel@tonic-gate } else {
38897c478bd9Sstevel@tonic-gate oflag = 0;
38907c478bd9Sstevel@tonic-gate
38917c478bd9Sstevel@tonic-gate length = tmp_size;
38927c478bd9Sstevel@tonic-gate
38937c478bd9Sstevel@tonic-gate /* we have a pair of values */
38947c478bd9Sstevel@tonic-gate meta_sp_list_insert(*spp, np,
38951cd3f00bSsk102515 &extlist, offset, length,
38961cd3f00bSsk102515 EXTTYP_ALLOC, seq++,
38971cd3f00bSsk102515 EXTFLG_UPDATE,
38987c478bd9Sstevel@tonic-gate meta_sp_cmp_by_offset);
38997c478bd9Sstevel@tonic-gate len += length;
39007c478bd9Sstevel@tonic-gate }
39017c478bd9Sstevel@tonic-gate }
39027c478bd9Sstevel@tonic-gate
39037c478bd9Sstevel@tonic-gate break;
39047c478bd9Sstevel@tonic-gate default:
39057c478bd9Sstevel@tonic-gate argc -= old_optind;
39067c478bd9Sstevel@tonic-gate argv += old_optind;
39077c478bd9Sstevel@tonic-gate goto options;
39087c478bd9Sstevel@tonic-gate }
39097c478bd9Sstevel@tonic-gate
39107c478bd9Sstevel@tonic-gate if (failed) {
39117c478bd9Sstevel@tonic-gate argc -= old_optind;
39127c478bd9Sstevel@tonic-gate argv += old_optind;
39137c478bd9Sstevel@tonic-gate goto syntax;
39147c478bd9Sstevel@tonic-gate }
39157c478bd9Sstevel@tonic-gate
39167c478bd9Sstevel@tonic-gate old_optind = optind;
39177c478bd9Sstevel@tonic-gate }
39187c478bd9Sstevel@tonic-gate argc -= optind;
39197c478bd9Sstevel@tonic-gate argv += optind;
39207c478bd9Sstevel@tonic-gate
39217c478bd9Sstevel@tonic-gate /*
39227c478bd9Sstevel@tonic-gate * Must have matching pairs of -o and -b flags
39237c478bd9Sstevel@tonic-gate */
39247c478bd9Sstevel@tonic-gate if (oflag != 0)
39257c478bd9Sstevel@tonic-gate goto syntax;
39267c478bd9Sstevel@tonic-gate
39277c478bd9Sstevel@tonic-gate /*
39287c478bd9Sstevel@tonic-gate * Can't specify both layout (indicated indirectly by
39297c478bd9Sstevel@tonic-gate * len being set by thye -o/-b cases above) AND
39307c478bd9Sstevel@tonic-gate * alignment
39317c478bd9Sstevel@tonic-gate */
39327c478bd9Sstevel@tonic-gate if ((len > 0LL) && (alignment > 0LL))
39337c478bd9Sstevel@tonic-gate goto syntax;
39347c478bd9Sstevel@tonic-gate
39357c478bd9Sstevel@tonic-gate /*
39367c478bd9Sstevel@tonic-gate * sanity check the allocation list
39377c478bd9Sstevel@tonic-gate */
39387c478bd9Sstevel@tonic-gate if ((extlist != NULL) && meta_sp_list_overlaps(extlist))
39397c478bd9Sstevel@tonic-gate goto syntax;
39407c478bd9Sstevel@tonic-gate }
39417c478bd9Sstevel@tonic-gate
39427c478bd9Sstevel@tonic-gate if (len == 0LL) {
39437c478bd9Sstevel@tonic-gate if (argc == 0)
39447c478bd9Sstevel@tonic-gate goto syntax;
39457c478bd9Sstevel@tonic-gate if (meta_sp_parsesize(argv[0], &len) == -1)
39467c478bd9Sstevel@tonic-gate goto syntax;
39477c478bd9Sstevel@tonic-gate --argc, ++argv;
39487c478bd9Sstevel@tonic-gate }
39497c478bd9Sstevel@tonic-gate
39507c478bd9Sstevel@tonic-gate msp->ext.ext_val = Zalloc(sizeof (*msp->ext.ext_val));
39517c478bd9Sstevel@tonic-gate msp->ext.ext_val->len = len;
39527c478bd9Sstevel@tonic-gate msp->compnamep = spcompnp;
39537c478bd9Sstevel@tonic-gate
39547c478bd9Sstevel@tonic-gate /* we should be at the end */
39557c478bd9Sstevel@tonic-gate if (argc != 0)
39567c478bd9Sstevel@tonic-gate goto syntax;
39577c478bd9Sstevel@tonic-gate
39587c478bd9Sstevel@tonic-gate /* create soft partition */
39597c478bd9Sstevel@tonic-gate if (meta_create_sp(*spp, msp, extlist, options, alignment, ep) != 0)
39607c478bd9Sstevel@tonic-gate goto out;
39617c478bd9Sstevel@tonic-gate rval = 0;
39627c478bd9Sstevel@tonic-gate
39637c478bd9Sstevel@tonic-gate /* let em know */
39647c478bd9Sstevel@tonic-gate if (options & MDCMD_PRINT) {
39657c478bd9Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN,
39667c478bd9Sstevel@tonic-gate "%s: Soft Partition is setup\n"),
39677c478bd9Sstevel@tonic-gate devname);
39687c478bd9Sstevel@tonic-gate (void) fflush(stdout);
39697c478bd9Sstevel@tonic-gate }
39707c478bd9Sstevel@tonic-gate goto out;
39717c478bd9Sstevel@tonic-gate
39727c478bd9Sstevel@tonic-gate syntax:
39737c478bd9Sstevel@tonic-gate /* syntax error */
39747c478bd9Sstevel@tonic-gate rval = meta_cook_syntax(ep, MDE_SYNTAX, compname, argc, argv);
39757c478bd9Sstevel@tonic-gate goto out;
39767c478bd9Sstevel@tonic-gate
39777c478bd9Sstevel@tonic-gate options:
39787c478bd9Sstevel@tonic-gate /* options error */
39797c478bd9Sstevel@tonic-gate rval = meta_cook_syntax(ep, MDE_OPTION, compname, argc, argv);
39807c478bd9Sstevel@tonic-gate goto out;
39817c478bd9Sstevel@tonic-gate
39827c478bd9Sstevel@tonic-gate out:
39837c478bd9Sstevel@tonic-gate if (msp != NULL) {
39847c478bd9Sstevel@tonic-gate if (msp->ext.ext_val != NULL) {
39857c478bd9Sstevel@tonic-gate Free(msp->ext.ext_val);
39867c478bd9Sstevel@tonic-gate }
39877c478bd9Sstevel@tonic-gate Free(msp);
39887c478bd9Sstevel@tonic-gate }
39897c478bd9Sstevel@tonic-gate
39907c478bd9Sstevel@tonic-gate return (rval);
39917c478bd9Sstevel@tonic-gate }
39927c478bd9Sstevel@tonic-gate
39937c478bd9Sstevel@tonic-gate /*
39947c478bd9Sstevel@tonic-gate * FUNCTION: meta_free_sp()
39957c478bd9Sstevel@tonic-gate * INPUT: msp - the soft partition unit to free
39967c478bd9Sstevel@tonic-gate * OUTPUT: none
39977c478bd9Sstevel@tonic-gate * RETURNS: void
39987c478bd9Sstevel@tonic-gate * PURPOSE: provides an interface from the rest of libmeta for freeing a
39997c478bd9Sstevel@tonic-gate * soft partition unit
40007c478bd9Sstevel@tonic-gate */
40017c478bd9Sstevel@tonic-gate void
meta_free_sp(md_sp_t * msp)40027c478bd9Sstevel@tonic-gate meta_free_sp(md_sp_t *msp)
40037c478bd9Sstevel@tonic-gate {
40047c478bd9Sstevel@tonic-gate Free(msp);
40057c478bd9Sstevel@tonic-gate }
40067c478bd9Sstevel@tonic-gate
40077c478bd9Sstevel@tonic-gate /*
40087c478bd9Sstevel@tonic-gate * FUNCTION: meta_sp_issp()
40097c478bd9Sstevel@tonic-gate * INPUT: sp - the set name to check
40107c478bd9Sstevel@tonic-gate * np - the name to check
40117c478bd9Sstevel@tonic-gate * OUTPUT: ep - return error pointer
40127c478bd9Sstevel@tonic-gate * RETURNS: int - 0 means sp,np is a soft partition
40137c478bd9Sstevel@tonic-gate * 1 means sp,np is not a soft partition
40147c478bd9Sstevel@tonic-gate * PURPOSE: determines whether the given device is a soft partition
40157c478bd9Sstevel@tonic-gate * device. This is called by other metadevice check routines.
40167c478bd9Sstevel@tonic-gate */
40177c478bd9Sstevel@tonic-gate int
meta_sp_issp(mdsetname_t * sp,mdname_t * np,md_error_t * ep)40187c478bd9Sstevel@tonic-gate meta_sp_issp(
40197c478bd9Sstevel@tonic-gate mdsetname_t *sp,
40207c478bd9Sstevel@tonic-gate mdname_t *np,
40217c478bd9Sstevel@tonic-gate md_error_t *ep
40227c478bd9Sstevel@tonic-gate )
40237c478bd9Sstevel@tonic-gate {
40247c478bd9Sstevel@tonic-gate if (meta_get_sp_common(sp, np, 0, ep) == NULL)
40257c478bd9Sstevel@tonic-gate return (1);
40267c478bd9Sstevel@tonic-gate
40277c478bd9Sstevel@tonic-gate return (0);
40287c478bd9Sstevel@tonic-gate }
40297c478bd9Sstevel@tonic-gate
40307c478bd9Sstevel@tonic-gate /*
40317c478bd9Sstevel@tonic-gate * FUNCTION: meta_check_sp()
40327c478bd9Sstevel@tonic-gate * INPUT: sp - the set name to check
40337c478bd9Sstevel@tonic-gate * msp - the unit structure to check
40347c478bd9Sstevel@tonic-gate * options - creation options
40357c478bd9Sstevel@tonic-gate * OUTPUT: repart_options - options to be passed to
40367c478bd9Sstevel@tonic-gate * meta_repartition_drive()
40377c478bd9Sstevel@tonic-gate * ep - return error pointer
40387c478bd9Sstevel@tonic-gate * RETURNS: int - 0 ok to create on this component
40397c478bd9Sstevel@tonic-gate * -1 error or not ok to create on this component
40407c478bd9Sstevel@tonic-gate * PURPOSE: Checks to determine whether the rules for creation of
40417c478bd9Sstevel@tonic-gate * soft partitions allow creation of a soft partition on
40427c478bd9Sstevel@tonic-gate * the device described by the mdname_t structure referred
40437c478bd9Sstevel@tonic-gate * to by msp->compnamep.
40447c478bd9Sstevel@tonic-gate *
40457c478bd9Sstevel@tonic-gate * NOTE: Does NOT check to determine whether the extents
40467c478bd9Sstevel@tonic-gate * described in the md_sp_t structure referred to by
40477c478bd9Sstevel@tonic-gate * msp will fit on the device described by the mdname_t
40487c478bd9Sstevel@tonic-gate * structure located at msp->compnamep.
40497c478bd9Sstevel@tonic-gate */
40507c478bd9Sstevel@tonic-gate static int
meta_check_sp(mdsetname_t * sp,md_sp_t * msp,mdcmdopts_t options,int * repart_options,md_error_t * ep)40517c478bd9Sstevel@tonic-gate meta_check_sp(
40527c478bd9Sstevel@tonic-gate mdsetname_t *sp,
40537c478bd9Sstevel@tonic-gate md_sp_t *msp,
40547c478bd9Sstevel@tonic-gate mdcmdopts_t options,
40557c478bd9Sstevel@tonic-gate int *repart_options,
40567c478bd9Sstevel@tonic-gate md_error_t *ep
40577c478bd9Sstevel@tonic-gate )
40587c478bd9Sstevel@tonic-gate {
40597c478bd9Sstevel@tonic-gate md_common_t *mdp;
40607c478bd9Sstevel@tonic-gate mdname_t *compnp = msp->compnamep;
40617c478bd9Sstevel@tonic-gate uint_t slice;
40627c478bd9Sstevel@tonic-gate mddrivename_t *dnp;
40637c478bd9Sstevel@tonic-gate mdname_t *slicenp;
40647c478bd9Sstevel@tonic-gate mdvtoc_t *vtocp;
40657c478bd9Sstevel@tonic-gate
40667c478bd9Sstevel@tonic-gate /* make sure it is in the set */
40677c478bd9Sstevel@tonic-gate if (meta_check_inset(sp, compnp, ep) != 0)
40687c478bd9Sstevel@tonic-gate return (-1);
40697c478bd9Sstevel@tonic-gate
40707c478bd9Sstevel@tonic-gate if ((options & MDCMD_USE_WHOLE_DISK) != 0) {
40717c478bd9Sstevel@tonic-gate uint_t rep_slice;
40727c478bd9Sstevel@tonic-gate
40737c478bd9Sstevel@tonic-gate /*
40747c478bd9Sstevel@tonic-gate * check to make sure we can partition this drive.
40757c478bd9Sstevel@tonic-gate * we cannot continue if any of the following are
40767c478bd9Sstevel@tonic-gate * true:
40777c478bd9Sstevel@tonic-gate * The drive is a metadevice.
40787c478bd9Sstevel@tonic-gate * The drive contains a mounted slice.
40797c478bd9Sstevel@tonic-gate * The drive contains a slice being swapped to.
40807c478bd9Sstevel@tonic-gate * The drive contains slices which are part of other
40817c478bd9Sstevel@tonic-gate * metadevices.
40827c478bd9Sstevel@tonic-gate * The drive contains a metadb.
40837c478bd9Sstevel@tonic-gate */
40847c478bd9Sstevel@tonic-gate if (metaismeta(compnp))
40857c478bd9Sstevel@tonic-gate return (mddeverror(ep, MDE_IS_META, compnp->dev,
40867c478bd9Sstevel@tonic-gate compnp->cname));
40877c478bd9Sstevel@tonic-gate
40887c478bd9Sstevel@tonic-gate assert(compnp->drivenamep != NULL);
40897c478bd9Sstevel@tonic-gate
40907c478bd9Sstevel@tonic-gate /*
40917c478bd9Sstevel@tonic-gate * ensure that we have slice 0 since the disk will be
40927c478bd9Sstevel@tonic-gate * repartitioned in the USE_WHOLE_DISK case. this check
40937c478bd9Sstevel@tonic-gate * is redundant unless the user incorrectly specifies a
40947c478bd9Sstevel@tonic-gate * a fully qualified drive AND slice name (i.e.,
40957c478bd9Sstevel@tonic-gate * /dev/dsk/cXtXdXsX), which will be incorrectly
40967c478bd9Sstevel@tonic-gate * recognized as a drive name by the metaname code.
40977c478bd9Sstevel@tonic-gate */
40987c478bd9Sstevel@tonic-gate
40997c478bd9Sstevel@tonic-gate if ((vtocp = metagetvtoc(compnp, FALSE, &slice, ep)) == NULL)
41007c478bd9Sstevel@tonic-gate return (-1);
41017c478bd9Sstevel@tonic-gate if (slice != MD_SLICE0)
41027c478bd9Sstevel@tonic-gate return (mderror(ep, MDE_NOT_DRIVENAME, compnp->cname));
41037c478bd9Sstevel@tonic-gate
41047c478bd9Sstevel@tonic-gate dnp = compnp->drivenamep;
41057c478bd9Sstevel@tonic-gate if (meta_replicaslice(dnp, &rep_slice, ep) != 0)
41067c478bd9Sstevel@tonic-gate return (-1);
41077c478bd9Sstevel@tonic-gate
41087c478bd9Sstevel@tonic-gate for (slice = 0; slice < vtocp->nparts; slice++) {
41097c478bd9Sstevel@tonic-gate
41107c478bd9Sstevel@tonic-gate /* only check if the slice really exists */
41117c478bd9Sstevel@tonic-gate if (vtocp->parts[slice].size == 0)
41127c478bd9Sstevel@tonic-gate continue;
41137c478bd9Sstevel@tonic-gate
41147c478bd9Sstevel@tonic-gate slicenp = metaslicename(dnp, slice, ep);
41157c478bd9Sstevel@tonic-gate if (slicenp == NULL)
41167c478bd9Sstevel@tonic-gate return (-1);
41177c478bd9Sstevel@tonic-gate
41187c478bd9Sstevel@tonic-gate /* check to ensure that it is not already in use */
41197c478bd9Sstevel@tonic-gate if (meta_check_inuse(sp,
41207c478bd9Sstevel@tonic-gate slicenp, MDCHK_INUSE, ep) != 0) {
41217c478bd9Sstevel@tonic-gate return (-1);
41227c478bd9Sstevel@tonic-gate }
41237c478bd9Sstevel@tonic-gate
41247c478bd9Sstevel@tonic-gate /*
41257c478bd9Sstevel@tonic-gate * Up to this point, tests are applied to all
41267c478bd9Sstevel@tonic-gate * slices uniformly.
41277c478bd9Sstevel@tonic-gate */
41287c478bd9Sstevel@tonic-gate
41297c478bd9Sstevel@tonic-gate if (slice == rep_slice) {
41307c478bd9Sstevel@tonic-gate /*
41317c478bd9Sstevel@tonic-gate * Tests inside the body of this
41327c478bd9Sstevel@tonic-gate * conditional are applied only to
41337c478bd9Sstevel@tonic-gate * slice seven.
41347c478bd9Sstevel@tonic-gate */
41357c478bd9Sstevel@tonic-gate if (meta_check_inmeta(sp, slicenp,
41367c478bd9Sstevel@tonic-gate options | MDCHK_ALLOW_MDDB |
41377c478bd9Sstevel@tonic-gate MDCHK_ALLOW_REPSLICE, 0, -1, ep) != 0)
41387c478bd9Sstevel@tonic-gate return (-1);
41397c478bd9Sstevel@tonic-gate
41407c478bd9Sstevel@tonic-gate /*
41417c478bd9Sstevel@tonic-gate * For slice seven, a metadb is NOT an
41427c478bd9Sstevel@tonic-gate * automatic failure. It merely means
41437c478bd9Sstevel@tonic-gate * that we're not allowed to muck
41447c478bd9Sstevel@tonic-gate * about with the partitioning of that
41457c478bd9Sstevel@tonic-gate * slice. We indicate this by masking
41467c478bd9Sstevel@tonic-gate * in the MD_REPART_LEAVE_REP flag.
41477c478bd9Sstevel@tonic-gate */
41487c478bd9Sstevel@tonic-gate if (metahasmddb(sp, slicenp, ep)) {
41497c478bd9Sstevel@tonic-gate assert(repart_options !=
41507c478bd9Sstevel@tonic-gate NULL);
41517c478bd9Sstevel@tonic-gate *repart_options |=
41527c478bd9Sstevel@tonic-gate MD_REPART_LEAVE_REP;
41537c478bd9Sstevel@tonic-gate }
41547c478bd9Sstevel@tonic-gate
41557c478bd9Sstevel@tonic-gate /*
41567c478bd9Sstevel@tonic-gate * Skip the remaining tests for slice
41577c478bd9Sstevel@tonic-gate * seven
41587c478bd9Sstevel@tonic-gate */
41597c478bd9Sstevel@tonic-gate continue;
41607c478bd9Sstevel@tonic-gate }
41617c478bd9Sstevel@tonic-gate
41627c478bd9Sstevel@tonic-gate /*
41637c478bd9Sstevel@tonic-gate * Tests below this point will be applied to
41647c478bd9Sstevel@tonic-gate * all slices EXCEPT for the replica slice.
41657c478bd9Sstevel@tonic-gate */
41667c478bd9Sstevel@tonic-gate
41677c478bd9Sstevel@tonic-gate
41687c478bd9Sstevel@tonic-gate /* check if component is in a metadevice */
41697c478bd9Sstevel@tonic-gate if (meta_check_inmeta(sp, slicenp, options, 0,
41707c478bd9Sstevel@tonic-gate -1, ep) != 0)
41717c478bd9Sstevel@tonic-gate return (-1);
41727c478bd9Sstevel@tonic-gate
41737c478bd9Sstevel@tonic-gate /* check to see if component has a metadb */
41747c478bd9Sstevel@tonic-gate if (metahasmddb(sp, slicenp, ep))
41757c478bd9Sstevel@tonic-gate return (mddeverror(ep, MDE_HAS_MDDB,
41767c478bd9Sstevel@tonic-gate slicenp->dev, slicenp->cname));
41777c478bd9Sstevel@tonic-gate }
41787c478bd9Sstevel@tonic-gate /*
41797c478bd9Sstevel@tonic-gate * This should be all of the testing necessary when
41807c478bd9Sstevel@tonic-gate * the MDCMD_USE_WHOLE_DISK flag is set; the rest of
41817c478bd9Sstevel@tonic-gate * meta_check_sp() is oriented towards component
41827c478bd9Sstevel@tonic-gate * arguments instead of disks.
41837c478bd9Sstevel@tonic-gate */
41847c478bd9Sstevel@tonic-gate goto meta_check_sp_ok;
41857c478bd9Sstevel@tonic-gate
41867c478bd9Sstevel@tonic-gate }
41877c478bd9Sstevel@tonic-gate
41887c478bd9Sstevel@tonic-gate /* check to ensure that it is not already in use */
41897c478bd9Sstevel@tonic-gate if (meta_check_inuse(sp, compnp, MDCHK_INUSE, ep) != 0) {
41907c478bd9Sstevel@tonic-gate return (-1);
41917c478bd9Sstevel@tonic-gate }
41927c478bd9Sstevel@tonic-gate
41937c478bd9Sstevel@tonic-gate if (!metaismeta(compnp)) { /* handle non-metadevices */
41947c478bd9Sstevel@tonic-gate
41957c478bd9Sstevel@tonic-gate /*
41967c478bd9Sstevel@tonic-gate * The component can have one or more soft partitions on it
41977c478bd9Sstevel@tonic-gate * already, but can't be part of any other type of metadevice,
41987c478bd9Sstevel@tonic-gate * so if it is used for a metadevice, but the metadevice
41997c478bd9Sstevel@tonic-gate * isn't a soft partition, return failure.
42007c478bd9Sstevel@tonic-gate */
42017c478bd9Sstevel@tonic-gate
42027c478bd9Sstevel@tonic-gate if (meta_check_inmeta(sp, compnp, options, 0, -1, ep) != 0 &&
42037c478bd9Sstevel@tonic-gate meta_check_insp(sp, compnp, 0, -1, ep) == 0) {
42047c478bd9Sstevel@tonic-gate return (-1);
42057c478bd9Sstevel@tonic-gate }
42067c478bd9Sstevel@tonic-gate } else { /* handle metadevices */
42077c478bd9Sstevel@tonic-gate /* get underlying unit & check capabilities */
42087c478bd9Sstevel@tonic-gate if ((mdp = meta_get_unit(sp, compnp, ep)) == NULL)
42097c478bd9Sstevel@tonic-gate return (-1);
42107c478bd9Sstevel@tonic-gate
42117c478bd9Sstevel@tonic-gate if ((! (mdp->capabilities & MD_CAN_PARENT)) ||
42127c478bd9Sstevel@tonic-gate (! (mdp->capabilities & MD_CAN_SP)))
42137c478bd9Sstevel@tonic-gate return (mdmderror(ep, MDE_INVAL_UNIT,
42147c478bd9Sstevel@tonic-gate meta_getminor(compnp->dev), compnp->cname));
42157c478bd9Sstevel@tonic-gate }
42167c478bd9Sstevel@tonic-gate
42177c478bd9Sstevel@tonic-gate meta_check_sp_ok:
42187c478bd9Sstevel@tonic-gate mdclrerror(ep);
42197c478bd9Sstevel@tonic-gate return (0);
42207c478bd9Sstevel@tonic-gate }
42217c478bd9Sstevel@tonic-gate
42227c478bd9Sstevel@tonic-gate /*
42237c478bd9Sstevel@tonic-gate * FUNCTION: meta_create_sp()
42247c478bd9Sstevel@tonic-gate * INPUT: sp - the set name to create in
42257c478bd9Sstevel@tonic-gate * msp - the unit structure to create
42267c478bd9Sstevel@tonic-gate * oblist - an optional list of requested extents (-o/-b options)
42277c478bd9Sstevel@tonic-gate * options - creation options
42287c478bd9Sstevel@tonic-gate * alignment - data alignment
42297c478bd9Sstevel@tonic-gate * OUTPUT: ep - return error pointer
42307c478bd9Sstevel@tonic-gate * RETURNS: int - 0 success, -1 error
42317c478bd9Sstevel@tonic-gate * PURPOSE: does most of the work for creating a soft partition. If
42327c478bd9Sstevel@tonic-gate * metainit -p -e was used, first partition the drive. Then
42337c478bd9Sstevel@tonic-gate * create an extent list based on the existing soft partitions
42347c478bd9Sstevel@tonic-gate * and assume all space not used by them is free. Storage for
42357c478bd9Sstevel@tonic-gate * the new soft partition is allocated from the free extents
42367c478bd9Sstevel@tonic-gate * based on the length specified on the command line or the
42377c478bd9Sstevel@tonic-gate * oblist passed in. The unit structure is then committed and
42387c478bd9Sstevel@tonic-gate * the watermarks are updated. Finally, the status is changed to
42397c478bd9Sstevel@tonic-gate * Okay and the process is complete.
42407c478bd9Sstevel@tonic-gate */
42417c478bd9Sstevel@tonic-gate static int
meta_create_sp(mdsetname_t * sp,md_sp_t * msp,sp_ext_node_t * oblist,mdcmdopts_t options,sp_ext_length_t alignment,md_error_t * ep)42427c478bd9Sstevel@tonic-gate meta_create_sp(
42437c478bd9Sstevel@tonic-gate mdsetname_t *sp,
42447c478bd9Sstevel@tonic-gate md_sp_t *msp,
42457c478bd9Sstevel@tonic-gate sp_ext_node_t *oblist,
42467c478bd9Sstevel@tonic-gate mdcmdopts_t options,
42477c478bd9Sstevel@tonic-gate sp_ext_length_t alignment,
42487c478bd9Sstevel@tonic-gate md_error_t *ep
42497c478bd9Sstevel@tonic-gate )
42507c478bd9Sstevel@tonic-gate {
42517c478bd9Sstevel@tonic-gate mdname_t *np = msp->common.namep;
42527c478bd9Sstevel@tonic-gate mdname_t *compnp = msp->compnamep;
42537c478bd9Sstevel@tonic-gate mp_unit_t *mp = NULL;
42547c478bd9Sstevel@tonic-gate mdnamelist_t *keynlp = NULL, *spnlp = NULL;
42557c478bd9Sstevel@tonic-gate md_set_params_t set_params;
42567c478bd9Sstevel@tonic-gate int rval = -1;
42577c478bd9Sstevel@tonic-gate diskaddr_t comp_size;
42587c478bd9Sstevel@tonic-gate diskaddr_t sp_start;
42597c478bd9Sstevel@tonic-gate sp_ext_node_t *extlist = NULL;
42607c478bd9Sstevel@tonic-gate int numexts = 0; /* number of extents */
42617c478bd9Sstevel@tonic-gate int count = 0;
42627c478bd9Sstevel@tonic-gate int committed = 0;
42637c478bd9Sstevel@tonic-gate int repart_options = MD_REPART_FORCE;
42647c478bd9Sstevel@tonic-gate int create_flag = MD_CRO_32BIT;
4265bf85a12bSJohn Wren Kennedy int mn_set_master = 0;
42667c478bd9Sstevel@tonic-gate
42677c478bd9Sstevel@tonic-gate md_set_desc *sd;
42687c478bd9Sstevel@tonic-gate md_set_mmown_params_t *ownpar = NULL;
42697c478bd9Sstevel@tonic-gate int comp_is_mirror = 0;
42707c478bd9Sstevel@tonic-gate
42717c478bd9Sstevel@tonic-gate /* validate soft partition */
42727c478bd9Sstevel@tonic-gate if (meta_check_sp(sp, msp, options, &repart_options, ep) != 0)
42737c478bd9Sstevel@tonic-gate return (-1);
42747c478bd9Sstevel@tonic-gate
42757c478bd9Sstevel@tonic-gate if ((options & MDCMD_USE_WHOLE_DISK) != 0) {
42767c478bd9Sstevel@tonic-gate if ((options & MDCMD_DOIT) != 0) {
42777c478bd9Sstevel@tonic-gate if (meta_repartition_drive(sp,
42787c478bd9Sstevel@tonic-gate compnp->drivenamep,
42797c478bd9Sstevel@tonic-gate repart_options,
42807c478bd9Sstevel@tonic-gate NULL, /* Don't return the VTOC */
42817c478bd9Sstevel@tonic-gate ep) != 0)
42827c478bd9Sstevel@tonic-gate
42837c478bd9Sstevel@tonic-gate return (-1);
42847c478bd9Sstevel@tonic-gate } else {
42857c478bd9Sstevel@tonic-gate /*
42867c478bd9Sstevel@tonic-gate * If -n and -e are both specified, it doesn't make
42877c478bd9Sstevel@tonic-gate * sense to continue without actually partitioning
42887c478bd9Sstevel@tonic-gate * the drive.
42897c478bd9Sstevel@tonic-gate */
42907c478bd9Sstevel@tonic-gate return (0);
42917c478bd9Sstevel@tonic-gate }
42927c478bd9Sstevel@tonic-gate }
42937c478bd9Sstevel@tonic-gate
42947c478bd9Sstevel@tonic-gate /* populate the start_blk field of the component name */
42957c478bd9Sstevel@tonic-gate if ((sp_start = meta_sp_get_start(sp, compnp, ep)) ==
42967c478bd9Sstevel@tonic-gate MD_DISKADDR_ERROR) {
42977c478bd9Sstevel@tonic-gate rval = -1;
42987c478bd9Sstevel@tonic-gate goto out;
42997c478bd9Sstevel@tonic-gate }
43007c478bd9Sstevel@tonic-gate
43017c478bd9Sstevel@tonic-gate if (options & MDCMD_DOIT) {
43027c478bd9Sstevel@tonic-gate /* store name in namespace */
43037c478bd9Sstevel@tonic-gate if (add_key_name(sp, compnp, &keynlp, ep) != 0) {
43047c478bd9Sstevel@tonic-gate rval = -1;
43057c478bd9Sstevel@tonic-gate goto out;
43067c478bd9Sstevel@tonic-gate }
43077c478bd9Sstevel@tonic-gate }
43087c478bd9Sstevel@tonic-gate
43097c478bd9Sstevel@tonic-gate /*
43107c478bd9Sstevel@tonic-gate * Get a list of the soft partitions that currently reside on
43117c478bd9Sstevel@tonic-gate * the component. We should ALWAYS force reload the cache,
43127c478bd9Sstevel@tonic-gate * because if this is a single creation, there will not BE a
43137c478bd9Sstevel@tonic-gate * cached list, and if we're using the md.tab, we must rebuild
43147c478bd9Sstevel@tonic-gate * the list because it won't contain the previous (if any)
43157c478bd9Sstevel@tonic-gate * soft partition.
43167c478bd9Sstevel@tonic-gate */
43177c478bd9Sstevel@tonic-gate count = meta_sp_get_by_component(sp, compnp, &spnlp, 1, ep);
43187c478bd9Sstevel@tonic-gate if (count < 0) {
43197c478bd9Sstevel@tonic-gate /* error occured */
43207c478bd9Sstevel@tonic-gate rval = -1;
43217c478bd9Sstevel@tonic-gate goto out;
43227c478bd9Sstevel@tonic-gate }
43237c478bd9Sstevel@tonic-gate
43247c478bd9Sstevel@tonic-gate /*
43257c478bd9Sstevel@tonic-gate * get the size of the underlying device. if the size is smaller
43267c478bd9Sstevel@tonic-gate * than or equal to the watermark size, we know there isn't
43277c478bd9Sstevel@tonic-gate * enough space.
43287c478bd9Sstevel@tonic-gate */
43297c478bd9Sstevel@tonic-gate if ((comp_size = metagetsize(compnp, ep)) == MD_DISKADDR_ERROR) {
43307c478bd9Sstevel@tonic-gate rval = -1;
43317c478bd9Sstevel@tonic-gate goto out;
43327c478bd9Sstevel@tonic-gate } else if (comp_size <= MD_SP_WMSIZE) {
43337c478bd9Sstevel@tonic-gate (void) mdmderror(ep, MDE_SP_NOSPACE, 0, compnp->cname);
43347c478bd9Sstevel@tonic-gate rval = -1;
43357c478bd9Sstevel@tonic-gate goto out;
43367c478bd9Sstevel@tonic-gate }
43377c478bd9Sstevel@tonic-gate /*
43387c478bd9Sstevel@tonic-gate * seed extlist with reserved space at the beginning of the volume and
43397c478bd9Sstevel@tonic-gate * enough space for the end watermark. The end watermark always gets
43407c478bd9Sstevel@tonic-gate * updated, but if the underlying device changes size it may not be
43417c478bd9Sstevel@tonic-gate * pointed to until the extent before it is updated. Since the
43427c478bd9Sstevel@tonic-gate * end of the reserved space is where the first watermark starts,
43437c478bd9Sstevel@tonic-gate * the reserved extent should never be marked for updating.
43447c478bd9Sstevel@tonic-gate */
43457c478bd9Sstevel@tonic-gate
43467c478bd9Sstevel@tonic-gate meta_sp_list_insert(NULL, NULL, &extlist,
43477c478bd9Sstevel@tonic-gate 0ULL, sp_start, EXTTYP_RESERVED, 0, 0, meta_sp_cmp_by_offset);
43487c478bd9Sstevel@tonic-gate meta_sp_list_insert(NULL, NULL, &extlist,
43497c478bd9Sstevel@tonic-gate (sp_ext_offset_t)(comp_size - MD_SP_WMSIZE), MD_SP_WMSIZE,
43507c478bd9Sstevel@tonic-gate EXTTYP_END, 0, EXTFLG_UPDATE, meta_sp_cmp_by_offset);
43517c478bd9Sstevel@tonic-gate
43527c478bd9Sstevel@tonic-gate if (meta_sp_extlist_from_namelist(sp, spnlp, &extlist, ep) == -1) {
43537c478bd9Sstevel@tonic-gate rval = -1;
43547c478bd9Sstevel@tonic-gate goto out;
43557c478bd9Sstevel@tonic-gate }
43567c478bd9Sstevel@tonic-gate
43577c478bd9Sstevel@tonic-gate metafreenamelist(spnlp);
43587c478bd9Sstevel@tonic-gate
43597c478bd9Sstevel@tonic-gate if (getenv(META_SP_DEBUG)) {
43607c478bd9Sstevel@tonic-gate meta_sp_debug("meta_create_sp: list of used extents:\n");
43617c478bd9Sstevel@tonic-gate meta_sp_list_dump(extlist);
43627c478bd9Sstevel@tonic-gate }
43637c478bd9Sstevel@tonic-gate
43647c478bd9Sstevel@tonic-gate meta_sp_list_freefill(&extlist, metagetsize(compnp, ep));
43657c478bd9Sstevel@tonic-gate
43667c478bd9Sstevel@tonic-gate /* get extent list from -o/-b options or from free space */
43677c478bd9Sstevel@tonic-gate if (options & MDCMD_DIRECT) {
43687c478bd9Sstevel@tonic-gate if (getenv(META_SP_DEBUG)) {
43697c478bd9Sstevel@tonic-gate meta_sp_debug("meta_create_sp: Dumping -o/-b list:\n");
43707c478bd9Sstevel@tonic-gate meta_sp_list_dump(oblist);
43717c478bd9Sstevel@tonic-gate }
43727c478bd9Sstevel@tonic-gate
43737c478bd9Sstevel@tonic-gate numexts = meta_sp_alloc_by_list(sp, np, &extlist, oblist);
43747c478bd9Sstevel@tonic-gate if (numexts == -1) {
43757c478bd9Sstevel@tonic-gate (void) mdmderror(ep, MDE_SP_OVERLAP, 0, np->cname);
43767c478bd9Sstevel@tonic-gate rval = -1;
43777c478bd9Sstevel@tonic-gate goto out;
43787c478bd9Sstevel@tonic-gate }
43797c478bd9Sstevel@tonic-gate } else {
43807c478bd9Sstevel@tonic-gate numexts = meta_sp_alloc_by_len(sp, np, &extlist,
43817c478bd9Sstevel@tonic-gate &msp->ext.ext_val->len, 0LL, (alignment > 0) ? alignment :
43827c478bd9Sstevel@tonic-gate meta_sp_get_default_alignment(sp, compnp, ep));
43837c478bd9Sstevel@tonic-gate if (numexts == -1) {
43847c478bd9Sstevel@tonic-gate (void) mdmderror(ep, MDE_SP_NOSPACE, 0, np->cname);
43857c478bd9Sstevel@tonic-gate rval = -1;
43867c478bd9Sstevel@tonic-gate goto out;
43877c478bd9Sstevel@tonic-gate }
43887c478bd9Sstevel@tonic-gate }
43897c478bd9Sstevel@tonic-gate
43907c478bd9Sstevel@tonic-gate assert(extlist != NULL);
43917c478bd9Sstevel@tonic-gate
43927c478bd9Sstevel@tonic-gate /* create soft partition */
43937c478bd9Sstevel@tonic-gate mp = meta_sp_createunit(msp->common.namep, msp->compnamep,
43947c478bd9Sstevel@tonic-gate extlist, numexts, msp->ext.ext_val->len, MD_SP_CREATEPEND, ep);
43957c478bd9Sstevel@tonic-gate
43967c478bd9Sstevel@tonic-gate create_flag = meta_check_devicesize(mp->c.un_total_blocks);
43977c478bd9Sstevel@tonic-gate
43987c478bd9Sstevel@tonic-gate /* if we're not doing anything (metainit -n), return success */
43997c478bd9Sstevel@tonic-gate if (! (options & MDCMD_DOIT)) {
44007c478bd9Sstevel@tonic-gate rval = 0; /* success */
44017c478bd9Sstevel@tonic-gate goto out;
44027c478bd9Sstevel@tonic-gate }
44037c478bd9Sstevel@tonic-gate
44047c478bd9Sstevel@tonic-gate (void) memset(&set_params, 0, sizeof (set_params));
44057c478bd9Sstevel@tonic-gate
44067c478bd9Sstevel@tonic-gate if (create_flag == MD_CRO_64BIT) {
4407d7cd8252Stw21770 mp->c.un_revision |= MD_64BIT_META_DEV;
44087c478bd9Sstevel@tonic-gate set_params.options = MD_CRO_64BIT;
44097c478bd9Sstevel@tonic-gate } else {
4410d7cd8252Stw21770 mp->c.un_revision &= ~MD_64BIT_META_DEV;
44117c478bd9Sstevel@tonic-gate set_params.options = MD_CRO_32BIT;
44127c478bd9Sstevel@tonic-gate }
44137c478bd9Sstevel@tonic-gate
44147c478bd9Sstevel@tonic-gate if (getenv(META_SP_DEBUG)) {
44157c478bd9Sstevel@tonic-gate meta_sp_debug("meta_create_sp: printing unit structure\n");
44167c478bd9Sstevel@tonic-gate meta_sp_printunit(mp);
44177c478bd9Sstevel@tonic-gate }
44187c478bd9Sstevel@tonic-gate
44197c478bd9Sstevel@tonic-gate /*
44207c478bd9Sstevel@tonic-gate * Check to see if we're trying to create a partition on a mirror. If so
44217c478bd9Sstevel@tonic-gate * we may have to enforce an ownership change before writing the
44227c478bd9Sstevel@tonic-gate * watermark out.
44237c478bd9Sstevel@tonic-gate */
44247c478bd9Sstevel@tonic-gate if (metaismeta(compnp)) {
44257c478bd9Sstevel@tonic-gate char *miscname;
44267c478bd9Sstevel@tonic-gate
44277c478bd9Sstevel@tonic-gate miscname = metagetmiscname(compnp, ep);
44287c478bd9Sstevel@tonic-gate if (miscname != NULL)
44297c478bd9Sstevel@tonic-gate comp_is_mirror = (strcmp(miscname, MD_MIRROR) == 0);
44307c478bd9Sstevel@tonic-gate else
44317c478bd9Sstevel@tonic-gate comp_is_mirror = 0;
44327c478bd9Sstevel@tonic-gate } else {
44337c478bd9Sstevel@tonic-gate comp_is_mirror = 0;
44347c478bd9Sstevel@tonic-gate }
44357c478bd9Sstevel@tonic-gate
44367c478bd9Sstevel@tonic-gate /*
44377c478bd9Sstevel@tonic-gate * For a multi-node environment we have to ensure that the master
44387c478bd9Sstevel@tonic-gate * node owns an underlying mirror before we issue the MD_IOCSET ioctl.
44397c478bd9Sstevel@tonic-gate * If the master does not own the device we will deadlock as the
44407c478bd9Sstevel@tonic-gate * implicit write of the watermarks (in sp_ioctl.c) will cause an
44417c478bd9Sstevel@tonic-gate * ownership change that will block as the MD_IOCSET is still in
44427c478bd9Sstevel@tonic-gate * progress. To close this window we force an owner change to occur
44437c478bd9Sstevel@tonic-gate * before issuing the MD_IOCSET. We cannot simply open the device and
44447c478bd9Sstevel@tonic-gate * write to it as this will only work for the first soft-partition
44457c478bd9Sstevel@tonic-gate * creation.
44467c478bd9Sstevel@tonic-gate */
44477c478bd9Sstevel@tonic-gate
44487c478bd9Sstevel@tonic-gate if (comp_is_mirror && !metaislocalset(sp)) {
44497c478bd9Sstevel@tonic-gate
44507c478bd9Sstevel@tonic-gate if ((sd = metaget_setdesc(sp, ep)) == NULL) {
44517c478bd9Sstevel@tonic-gate rval = -1;
44527c478bd9Sstevel@tonic-gate goto out;
44537c478bd9Sstevel@tonic-gate }
44547c478bd9Sstevel@tonic-gate if (MD_MNSET_DESC(sd) && sd->sd_mn_am_i_master) {
4455bf85a12bSJohn Wren Kennedy mn_set_master = 1;
44567c478bd9Sstevel@tonic-gate }
44577c478bd9Sstevel@tonic-gate }
44587c478bd9Sstevel@tonic-gate
44597c478bd9Sstevel@tonic-gate set_params.mnum = MD_SID(mp);
44607c478bd9Sstevel@tonic-gate set_params.size = mp->c.un_size;
44617c478bd9Sstevel@tonic-gate set_params.mdp = (uintptr_t)mp;
44627c478bd9Sstevel@tonic-gate MD_SETDRIVERNAME(&set_params, MD_SP, MD_MIN2SET(set_params.mnum));
44637c478bd9Sstevel@tonic-gate
44647c478bd9Sstevel@tonic-gate /* first phase of commit. */
44657c478bd9Sstevel@tonic-gate if (metaioctl(MD_IOCSET, &set_params, &set_params.mde,
44667c478bd9Sstevel@tonic-gate np->cname) != 0) {
44677c478bd9Sstevel@tonic-gate (void) mdstealerror(ep, &set_params.mde);
44687c478bd9Sstevel@tonic-gate rval = -1;
44697c478bd9Sstevel@tonic-gate goto out;
44707c478bd9Sstevel@tonic-gate }
44717c478bd9Sstevel@tonic-gate
44727c478bd9Sstevel@tonic-gate /* we've successfully committed the record */
44737c478bd9Sstevel@tonic-gate committed = 1;
44747c478bd9Sstevel@tonic-gate
44757c478bd9Sstevel@tonic-gate /* write watermarks */
4476bf85a12bSJohn Wren Kennedy /*
4477bf85a12bSJohn Wren Kennedy * Special-case for Multi-node sets. As we now have a distributed DRL
4478bf85a12bSJohn Wren Kennedy * update mechanism, we _will_ hit the ioctl-within-ioctl deadlock case
4479bf85a12bSJohn Wren Kennedy * unless we use a 'special' MN-capable ioctl to stage the watermark
4480bf85a12bSJohn Wren Kennedy * update. This only affects the master-node in an MN set.
4481bf85a12bSJohn Wren Kennedy */
4482bf85a12bSJohn Wren Kennedy if (mn_set_master) {
4483bf85a12bSJohn Wren Kennedy if (meta_mn_sp_update_wm(sp, msp, extlist, ep) < 0) {
4484bf85a12bSJohn Wren Kennedy rval = -1;
4485bf85a12bSJohn Wren Kennedy goto out;
4486bf85a12bSJohn Wren Kennedy }
4487bf85a12bSJohn Wren Kennedy } else {
44887c478bd9Sstevel@tonic-gate if (meta_sp_update_wm(sp, msp, extlist, ep) < 0) {
44897c478bd9Sstevel@tonic-gate rval = -1;
44907c478bd9Sstevel@tonic-gate goto out;
44917c478bd9Sstevel@tonic-gate }
44927c478bd9Sstevel@tonic-gate }
44937c478bd9Sstevel@tonic-gate
44947c478bd9Sstevel@tonic-gate /* second phase of commit, set status to MD_SP_OK */
44957c478bd9Sstevel@tonic-gate if (meta_sp_setstatus(sp, &(MD_SID(mp)), 1, MD_SP_OK, ep) < 0) {
44967c478bd9Sstevel@tonic-gate rval = -1;
44977c478bd9Sstevel@tonic-gate goto out;
44987c478bd9Sstevel@tonic-gate }
44997c478bd9Sstevel@tonic-gate rval = 0;
45007c478bd9Sstevel@tonic-gate out:
45017c478bd9Sstevel@tonic-gate Free(mp);
45027c478bd9Sstevel@tonic-gate if (ownpar)
45037c478bd9Sstevel@tonic-gate Free(ownpar);
45047c478bd9Sstevel@tonic-gate
45057c478bd9Sstevel@tonic-gate if (extlist != NULL)
45067c478bd9Sstevel@tonic-gate meta_sp_list_free(&extlist);
45077c478bd9Sstevel@tonic-gate
45087c478bd9Sstevel@tonic-gate if (rval != 0 && keynlp != NULL && committed != 1)
45097c478bd9Sstevel@tonic-gate (void) del_key_names(sp, keynlp, NULL);
45107c478bd9Sstevel@tonic-gate
45117c478bd9Sstevel@tonic-gate metafreenamelist(keynlp);
45127c478bd9Sstevel@tonic-gate
45137c478bd9Sstevel@tonic-gate return (rval);
45147c478bd9Sstevel@tonic-gate }
45157c478bd9Sstevel@tonic-gate
45167c478bd9Sstevel@tonic-gate /*
45177c478bd9Sstevel@tonic-gate * **************************************************************************
45187c478bd9Sstevel@tonic-gate * Reset (metaclear) Functions *
45197c478bd9Sstevel@tonic-gate * **************************************************************************
45207c478bd9Sstevel@tonic-gate */
45217c478bd9Sstevel@tonic-gate
45227c478bd9Sstevel@tonic-gate /*
45237c478bd9Sstevel@tonic-gate * FUNCTION: meta_sp_reset_common()
45247c478bd9Sstevel@tonic-gate * INPUT: sp - the set name of the device to reset
45257c478bd9Sstevel@tonic-gate * np - the name of the device to reset
45267c478bd9Sstevel@tonic-gate * msp - the unit structure to reset
45277c478bd9Sstevel@tonic-gate * options - metaclear options
45287c478bd9Sstevel@tonic-gate * OUTPUT: ep - return error pointer
45297c478bd9Sstevel@tonic-gate * RETURNS: int - 0 success, -1 error
45307c478bd9Sstevel@tonic-gate * PURPOSE: "resets", or more accurately deletes, the soft partition
45317c478bd9Sstevel@tonic-gate * specified. First the state is set to "deleting" and then the
45327c478bd9Sstevel@tonic-gate * watermarks are all cleared out. Once the watermarks have been
45337c478bd9Sstevel@tonic-gate * updated, the unit structure is deleted from the metadb.
45347c478bd9Sstevel@tonic-gate */
45357c478bd9Sstevel@tonic-gate static int
meta_sp_reset_common(mdsetname_t * sp,mdname_t * np,md_sp_t * msp,md_sp_reset_t reset_params,mdcmdopts_t options,md_error_t * ep)45367c478bd9Sstevel@tonic-gate meta_sp_reset_common(
45377c478bd9Sstevel@tonic-gate mdsetname_t *sp,
45387c478bd9Sstevel@tonic-gate mdname_t *np,
45397c478bd9Sstevel@tonic-gate md_sp_t *msp,
45407c478bd9Sstevel@tonic-gate md_sp_reset_t reset_params,
45417c478bd9Sstevel@tonic-gate mdcmdopts_t options,
45427c478bd9Sstevel@tonic-gate md_error_t *ep
45437c478bd9Sstevel@tonic-gate )
45447c478bd9Sstevel@tonic-gate {
45457c478bd9Sstevel@tonic-gate char *miscname;
45467c478bd9Sstevel@tonic-gate int rval = -1;
45477c478bd9Sstevel@tonic-gate int is_open = 0;
45487c478bd9Sstevel@tonic-gate
45497c478bd9Sstevel@tonic-gate /* make sure that nobody owns us */
45507c478bd9Sstevel@tonic-gate if (MD_HAS_PARENT(msp->common.parent))
45517c478bd9Sstevel@tonic-gate return (mdmderror(ep, MDE_IN_USE, meta_getminor(np->dev),
45527c478bd9Sstevel@tonic-gate np->cname));
45537c478bd9Sstevel@tonic-gate
45547c478bd9Sstevel@tonic-gate /* make sure that the soft partition isn't open */
45557c478bd9Sstevel@tonic-gate if ((is_open = meta_isopen(sp, np, ep, options)) < 0)
45567c478bd9Sstevel@tonic-gate return (-1);
45577c478bd9Sstevel@tonic-gate else if (is_open)
45587c478bd9Sstevel@tonic-gate return (mdmderror(ep, MDE_IS_OPEN, meta_getminor(np->dev),
45597c478bd9Sstevel@tonic-gate np->cname));
45607c478bd9Sstevel@tonic-gate
45617c478bd9Sstevel@tonic-gate /* get miscname */
45627c478bd9Sstevel@tonic-gate if ((miscname = metagetmiscname(np, ep)) == NULL)
45637c478bd9Sstevel@tonic-gate return (-1);
45647c478bd9Sstevel@tonic-gate
45657c478bd9Sstevel@tonic-gate /* fill in reset params */
45667c478bd9Sstevel@tonic-gate MD_SETDRIVERNAME(&reset_params, miscname, sp->setno);
45677c478bd9Sstevel@tonic-gate reset_params.mnum = meta_getminor(np->dev);
45687c478bd9Sstevel@tonic-gate reset_params.force = (options & MDCMD_FORCE) ? 1 : 0;
45697c478bd9Sstevel@tonic-gate
45707c478bd9Sstevel@tonic-gate /*
45717c478bd9Sstevel@tonic-gate * clear soft partition - phase one.
45727c478bd9Sstevel@tonic-gate * place the soft partition into the "delete pending" state.
45737c478bd9Sstevel@tonic-gate */
45747c478bd9Sstevel@tonic-gate if (meta_sp_setstatus(sp, &reset_params.mnum, 1, MD_SP_DELPEND, ep) < 0)
45757c478bd9Sstevel@tonic-gate return (-1);
45767c478bd9Sstevel@tonic-gate
45777c478bd9Sstevel@tonic-gate /*
45787c478bd9Sstevel@tonic-gate * Now clear the watermarks. If the force flag is specified,
45797c478bd9Sstevel@tonic-gate * ignore any errors writing the watermarks and delete the unit
45807c478bd9Sstevel@tonic-gate * structure anyway. An error may leave the on-disk format in a
45817c478bd9Sstevel@tonic-gate * corrupt state. If force is not specified and we fail here,
45827c478bd9Sstevel@tonic-gate * the soft partition will remain in the "delete pending" state.
45837c478bd9Sstevel@tonic-gate */
45847c478bd9Sstevel@tonic-gate if ((meta_sp_clear_wm(sp, msp, ep) < 0) &&
45857c478bd9Sstevel@tonic-gate ((options & MDCMD_FORCE) == 0))
45867c478bd9Sstevel@tonic-gate goto out;
45877c478bd9Sstevel@tonic-gate
45887c478bd9Sstevel@tonic-gate /*
45897c478bd9Sstevel@tonic-gate * clear soft partition - phase two.
45907c478bd9Sstevel@tonic-gate * the driver removes the soft partition from the metadb and
45917c478bd9Sstevel@tonic-gate * zeros out incore version.
45927c478bd9Sstevel@tonic-gate */
45937c478bd9Sstevel@tonic-gate if (metaioctl(MD_IOCRESET, &reset_params,
45947c478bd9Sstevel@tonic-gate &reset_params.mde, np->cname) != 0) {
45957c478bd9Sstevel@tonic-gate (void) mdstealerror(ep, &reset_params.mde);
45967c478bd9Sstevel@tonic-gate goto out;
45977c478bd9Sstevel@tonic-gate }
4598c113cb38Stn143363
4599c113cb38Stn143363 /*
4600c113cb38Stn143363 * Wait for the /dev to be cleaned up. Ignore the return
4601c113cb38Stn143363 * value since there's not much we can do.
4602c113cb38Stn143363 */
4603c113cb38Stn143363 (void) meta_update_devtree(meta_getminor(np->dev));
4604c113cb38Stn143363
46057c478bd9Sstevel@tonic-gate rval = 0; /* success */
46067c478bd9Sstevel@tonic-gate
46077c478bd9Sstevel@tonic-gate if (options & MDCMD_PRINT) {
46087c478bd9Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN,
46097c478bd9Sstevel@tonic-gate "%s: Soft Partition is cleared\n"),
46107c478bd9Sstevel@tonic-gate np->cname);
46117c478bd9Sstevel@tonic-gate (void) fflush(stdout);
46127c478bd9Sstevel@tonic-gate }
46137c478bd9Sstevel@tonic-gate
46147c478bd9Sstevel@tonic-gate /*
46157c478bd9Sstevel@tonic-gate * if told to recurse and on a metadevice, then attempt to
46167c478bd9Sstevel@tonic-gate * clear the subdevices. Indicate failure if the clear fails.
46177c478bd9Sstevel@tonic-gate */
46187c478bd9Sstevel@tonic-gate if ((options & MDCMD_RECURSE) &&
46197c478bd9Sstevel@tonic-gate (metaismeta(msp->compnamep)) &&
46207c478bd9Sstevel@tonic-gate (meta_reset_by_name(sp, msp->compnamep, options, ep) != 0))
46217c478bd9Sstevel@tonic-gate rval = -1;
46227c478bd9Sstevel@tonic-gate
46237c478bd9Sstevel@tonic-gate out:
46247c478bd9Sstevel@tonic-gate meta_invalidate_name(np);
46257c478bd9Sstevel@tonic-gate return (rval);
46267c478bd9Sstevel@tonic-gate }
46277c478bd9Sstevel@tonic-gate
46287c478bd9Sstevel@tonic-gate /*
46297c478bd9Sstevel@tonic-gate * FUNCTION: meta_sp_reset()
46307c478bd9Sstevel@tonic-gate * INPUT: sp - the set name of the device to reset
46317c478bd9Sstevel@tonic-gate * np - the name of the device to reset
46327c478bd9Sstevel@tonic-gate * options - metaclear options
46337c478bd9Sstevel@tonic-gate * OUTPUT: ep - return error pointer
46347c478bd9Sstevel@tonic-gate * RETURNS: int - 0 success, -1 error
46357c478bd9Sstevel@tonic-gate * PURPOSE: provides the entry point to the rest of libmeta for deleting a
46367c478bd9Sstevel@tonic-gate * soft partition. If np is NULL, then soft partitions are
46377c478bd9Sstevel@tonic-gate * all deleted at the current level and then recursively deleted.
46387c478bd9Sstevel@tonic-gate * Otherwise, if a name is specified either directly or as a
46397c478bd9Sstevel@tonic-gate * result of a recursive operation, it deletes only that name.
46407c478bd9Sstevel@tonic-gate * Since something sitting under a soft partition may be parented
46417c478bd9Sstevel@tonic-gate * to it, we have to reparent that other device to another soft
46427c478bd9Sstevel@tonic-gate * partition on the same component if we're deleting the one it's
46437c478bd9Sstevel@tonic-gate * parented to.
46447c478bd9Sstevel@tonic-gate */
46457c478bd9Sstevel@tonic-gate int
meta_sp_reset(mdsetname_t * sp,mdname_t * np,mdcmdopts_t options,md_error_t * ep)46467c478bd9Sstevel@tonic-gate meta_sp_reset(
46477c478bd9Sstevel@tonic-gate mdsetname_t *sp,
46487c478bd9Sstevel@tonic-gate mdname_t *np,
46497c478bd9Sstevel@tonic-gate mdcmdopts_t options,
46507c478bd9Sstevel@tonic-gate md_error_t *ep
46517c478bd9Sstevel@tonic-gate )
46527c478bd9Sstevel@tonic-gate {
46537c478bd9Sstevel@tonic-gate md_sp_t *msp;
46547c478bd9Sstevel@tonic-gate int rval = -1;
46557c478bd9Sstevel@tonic-gate mdnamelist_t *spnlp = NULL, *nlp = NULL;
46567c478bd9Sstevel@tonic-gate md_sp_reset_t reset_params;
46577c478bd9Sstevel@tonic-gate int num_sp;
46587c478bd9Sstevel@tonic-gate
46597c478bd9Sstevel@tonic-gate assert(sp != NULL);
46607c478bd9Sstevel@tonic-gate
46617c478bd9Sstevel@tonic-gate /* reset/delete all soft paritions */
46627c478bd9Sstevel@tonic-gate if (np == NULL) {
46637c478bd9Sstevel@tonic-gate /*
46647c478bd9Sstevel@tonic-gate * meta_reset_all sets MDCMD_RECURSE, but this behavior
46657c478bd9Sstevel@tonic-gate * is incorrect for soft partitions. We want to clear
46667c478bd9Sstevel@tonic-gate * all soft partitions at a particular level in the
46677c478bd9Sstevel@tonic-gate * metadevice stack before moving to the next level.
46687c478bd9Sstevel@tonic-gate * Thus, we clear MDCMD_RECURSE from the options.
46697c478bd9Sstevel@tonic-gate */
46707c478bd9Sstevel@tonic-gate options &= ~MDCMD_RECURSE;
46717c478bd9Sstevel@tonic-gate
46727c478bd9Sstevel@tonic-gate /* for each soft partition */
46737c478bd9Sstevel@tonic-gate rval = 0;
46747c478bd9Sstevel@tonic-gate if (meta_get_sp_names(sp, &spnlp, 0, ep) < 0)
46757c478bd9Sstevel@tonic-gate rval = -1;
46767c478bd9Sstevel@tonic-gate
46777c478bd9Sstevel@tonic-gate for (nlp = spnlp; (nlp != NULL); nlp = nlp->next) {
46787c478bd9Sstevel@tonic-gate np = nlp->namep;
46797c478bd9Sstevel@tonic-gate if ((msp = meta_get_sp(sp, np, ep)) == NULL) {
46807c478bd9Sstevel@tonic-gate rval = -1;
46817c478bd9Sstevel@tonic-gate break;
46827c478bd9Sstevel@tonic-gate }
46837c478bd9Sstevel@tonic-gate /*
46847c478bd9Sstevel@tonic-gate * meta_reset_all calls us twice to get soft
46857c478bd9Sstevel@tonic-gate * partitions at the top and bottom of the stack.
46867c478bd9Sstevel@tonic-gate * thus, if we have a parent, we'll get deleted
46877c478bd9Sstevel@tonic-gate * on the next call.
46887c478bd9Sstevel@tonic-gate */
46897c478bd9Sstevel@tonic-gate if (MD_HAS_PARENT(msp->common.parent))
46907c478bd9Sstevel@tonic-gate continue;
46917c478bd9Sstevel@tonic-gate /*
46927c478bd9Sstevel@tonic-gate * If this is a multi-node set, we send a series
46937c478bd9Sstevel@tonic-gate * of individual metaclear commands.
46947c478bd9Sstevel@tonic-gate */
46957c478bd9Sstevel@tonic-gate if (meta_is_mn_set(sp, ep)) {
46967c478bd9Sstevel@tonic-gate if (meta_mn_send_metaclear_command(sp,
46977c478bd9Sstevel@tonic-gate np->cname, options, 0, ep) != 0) {
46987c478bd9Sstevel@tonic-gate rval = -1;
46997c478bd9Sstevel@tonic-gate break;
47007c478bd9Sstevel@tonic-gate }
47017c478bd9Sstevel@tonic-gate } else {
47027c478bd9Sstevel@tonic-gate if (meta_sp_reset(sp, np, options, ep) != 0) {
47037c478bd9Sstevel@tonic-gate rval = -1;
47047c478bd9Sstevel@tonic-gate break;
47057c478bd9Sstevel@tonic-gate }
47067c478bd9Sstevel@tonic-gate }
47077c478bd9Sstevel@tonic-gate }
47087c478bd9Sstevel@tonic-gate /* cleanup return status */
47097c478bd9Sstevel@tonic-gate metafreenamelist(spnlp);
47107c478bd9Sstevel@tonic-gate return (rval);
47117c478bd9Sstevel@tonic-gate }
47127c478bd9Sstevel@tonic-gate
47137c478bd9Sstevel@tonic-gate /* check the name */
47147c478bd9Sstevel@tonic-gate if (metachkmeta(np, ep) != 0)
47157c478bd9Sstevel@tonic-gate return (-1);
47167c478bd9Sstevel@tonic-gate
47177c478bd9Sstevel@tonic-gate /* get the unit structure */
47187c478bd9Sstevel@tonic-gate if ((msp = meta_get_sp(sp, np, ep)) == NULL)
47197c478bd9Sstevel@tonic-gate return (-1);
47207c478bd9Sstevel@tonic-gate
47217c478bd9Sstevel@tonic-gate /* clear out reset parameters */
47227c478bd9Sstevel@tonic-gate (void) memset(&reset_params, 0, sizeof (reset_params));
47237c478bd9Sstevel@tonic-gate
47247c478bd9Sstevel@tonic-gate /* if our child is a metadevice, we need to deparent/reparent it */
47257c478bd9Sstevel@tonic-gate if (metaismeta(msp->compnamep)) {
47267c478bd9Sstevel@tonic-gate /* get sp's on this component */
47277c478bd9Sstevel@tonic-gate if ((num_sp = meta_sp_get_by_component(sp, msp->compnamep,
47287c478bd9Sstevel@tonic-gate &spnlp, 1, ep)) <= 0)
47297c478bd9Sstevel@tonic-gate /* no sp's on this device. error! */
47307c478bd9Sstevel@tonic-gate return (-1);
47317c478bd9Sstevel@tonic-gate else if (num_sp == 1)
47327c478bd9Sstevel@tonic-gate /* last sp on this device, so we deparent */
47337c478bd9Sstevel@tonic-gate reset_params.new_parent = MD_NO_PARENT;
47347c478bd9Sstevel@tonic-gate else {
47357c478bd9Sstevel@tonic-gate /* have to reparent this metadevice */
47367c478bd9Sstevel@tonic-gate for (nlp = spnlp; nlp != NULL; nlp = nlp->next) {
47377c478bd9Sstevel@tonic-gate if (meta_getminor(nlp->namep->dev) ==
47387c478bd9Sstevel@tonic-gate meta_getminor(np->dev))
47397c478bd9Sstevel@tonic-gate continue;
47407c478bd9Sstevel@tonic-gate /*
47417c478bd9Sstevel@tonic-gate * this isn't the softpart we are deleting,
47427c478bd9Sstevel@tonic-gate * so use this device as the new parent.
47437c478bd9Sstevel@tonic-gate */
47447c478bd9Sstevel@tonic-gate reset_params.new_parent =
47457c478bd9Sstevel@tonic-gate meta_getminor(nlp->namep->dev);
47467c478bd9Sstevel@tonic-gate break;
47477c478bd9Sstevel@tonic-gate }
47487c478bd9Sstevel@tonic-gate }
47497c478bd9Sstevel@tonic-gate metafreenamelist(spnlp);
47507c478bd9Sstevel@tonic-gate }
47517c478bd9Sstevel@tonic-gate
47527c478bd9Sstevel@tonic-gate if (meta_sp_reset_common(sp, np, msp, reset_params, options, ep) != 0)
47537c478bd9Sstevel@tonic-gate return (-1);
47547c478bd9Sstevel@tonic-gate
47557c478bd9Sstevel@tonic-gate return (0);
47567c478bd9Sstevel@tonic-gate }
47577c478bd9Sstevel@tonic-gate
47587c478bd9Sstevel@tonic-gate /*
47597c478bd9Sstevel@tonic-gate * FUNCTION: meta_sp_reset_component()
47607c478bd9Sstevel@tonic-gate * INPUT: sp - the set name of the device to reset
47617c478bd9Sstevel@tonic-gate * name - the string name of the device to reset
47627c478bd9Sstevel@tonic-gate * options - metaclear options
47637c478bd9Sstevel@tonic-gate * OUTPUT: ep - return error pointer
47647c478bd9Sstevel@tonic-gate * RETURNS: int - 0 success, -1 error
47657c478bd9Sstevel@tonic-gate * PURPOSE: provides the ability to delete all soft partitions on a
47667c478bd9Sstevel@tonic-gate * specified device (metaclear -p). It first gets all of the
47677c478bd9Sstevel@tonic-gate * soft partitions on the component and then deletes each one
47687c478bd9Sstevel@tonic-gate * individually.
47697c478bd9Sstevel@tonic-gate */
47707c478bd9Sstevel@tonic-gate int
meta_sp_reset_component(mdsetname_t * sp,char * name,mdcmdopts_t options,md_error_t * ep)47717c478bd9Sstevel@tonic-gate meta_sp_reset_component(
47727c478bd9Sstevel@tonic-gate mdsetname_t *sp,
47737c478bd9Sstevel@tonic-gate char *name,
47747c478bd9Sstevel@tonic-gate mdcmdopts_t options,
47757c478bd9Sstevel@tonic-gate md_error_t *ep
47767c478bd9Sstevel@tonic-gate )
47777c478bd9Sstevel@tonic-gate {
47787c478bd9Sstevel@tonic-gate mdname_t *compnp, *np;
47797c478bd9Sstevel@tonic-gate mdnamelist_t *spnlp = NULL;
47807c478bd9Sstevel@tonic-gate mdnamelist_t *nlp = NULL;
47817c478bd9Sstevel@tonic-gate md_sp_t *msp;
47827c478bd9Sstevel@tonic-gate int count;
47837c478bd9Sstevel@tonic-gate md_sp_reset_t reset_params;
47847c478bd9Sstevel@tonic-gate
4785d7cd8252Stw21770 if ((compnp = metaname(&sp, name, UNKNOWN, ep)) == NULL)
47867c478bd9Sstevel@tonic-gate return (-1);
47877c478bd9Sstevel@tonic-gate
47887c478bd9Sstevel@tonic-gate /* If we're starting out with no soft partitions, it's an error */
47897c478bd9Sstevel@tonic-gate count = meta_sp_get_by_component(sp, compnp, &spnlp, 1, ep);
47907c478bd9Sstevel@tonic-gate if (count == 0)
47917c478bd9Sstevel@tonic-gate return (mdmderror(ep, MDE_SP_NOSP, 0, compnp->cname));
47927c478bd9Sstevel@tonic-gate else if (count < 0)
47937c478bd9Sstevel@tonic-gate return (-1);
47947c478bd9Sstevel@tonic-gate
47957c478bd9Sstevel@tonic-gate /*
47967c478bd9Sstevel@tonic-gate * clear all soft partitions on this component.
47977c478bd9Sstevel@tonic-gate * NOTE: we reparent underlying metadevices as we go so that
47987c478bd9Sstevel@tonic-gate * things stay sane. Also, if we encounter an error, we stop
47997c478bd9Sstevel@tonic-gate * and go no further in case recovery might be needed.
48007c478bd9Sstevel@tonic-gate */
48017c478bd9Sstevel@tonic-gate for (nlp = spnlp; nlp != NULL; nlp = nlp->next) {
48027c478bd9Sstevel@tonic-gate /* clear out reset parameters */
48037c478bd9Sstevel@tonic-gate (void) memset(&reset_params, 0, sizeof (reset_params));
48047c478bd9Sstevel@tonic-gate
48057c478bd9Sstevel@tonic-gate /* check the name */
48067c478bd9Sstevel@tonic-gate np = nlp->namep;
48077c478bd9Sstevel@tonic-gate
48087c478bd9Sstevel@tonic-gate if (metachkmeta(np, ep) != 0) {
48097c478bd9Sstevel@tonic-gate metafreenamelist(spnlp);
48107c478bd9Sstevel@tonic-gate return (-1);
48117c478bd9Sstevel@tonic-gate }
48127c478bd9Sstevel@tonic-gate
48137c478bd9Sstevel@tonic-gate /* get the unit structure */
48147c478bd9Sstevel@tonic-gate if ((msp = meta_get_sp(sp, np, ep)) == NULL) {
48157c478bd9Sstevel@tonic-gate metafreenamelist(spnlp);
48167c478bd9Sstevel@tonic-gate return (-1);
48177c478bd9Sstevel@tonic-gate }
48187c478bd9Sstevel@tonic-gate
48197c478bd9Sstevel@tonic-gate /* have to deparent/reparent metadevices */
48207c478bd9Sstevel@tonic-gate if (metaismeta(compnp)) {
48217c478bd9Sstevel@tonic-gate if (nlp->next == NULL)
48227c478bd9Sstevel@tonic-gate reset_params.new_parent = MD_NO_PARENT;
48237c478bd9Sstevel@tonic-gate else
48247c478bd9Sstevel@tonic-gate reset_params.new_parent =
48257c478bd9Sstevel@tonic-gate meta_getminor(spnlp->next->namep->dev);
48267c478bd9Sstevel@tonic-gate }
48277c478bd9Sstevel@tonic-gate
48287c478bd9Sstevel@tonic-gate /* clear soft partition */
48297c478bd9Sstevel@tonic-gate if (meta_sp_reset_common(sp, np, msp, reset_params,
48307c478bd9Sstevel@tonic-gate options, ep) < 0) {
48317c478bd9Sstevel@tonic-gate metafreenamelist(spnlp);
48327c478bd9Sstevel@tonic-gate return (-1);
48337c478bd9Sstevel@tonic-gate }
48347c478bd9Sstevel@tonic-gate }
48357c478bd9Sstevel@tonic-gate metafreenamelist(spnlp);
48367c478bd9Sstevel@tonic-gate return (0);
48377c478bd9Sstevel@tonic-gate }
48387c478bd9Sstevel@tonic-gate
48397c478bd9Sstevel@tonic-gate /*
48407c478bd9Sstevel@tonic-gate * **************************************************************************
48417c478bd9Sstevel@tonic-gate * Grow (metattach) Functions *
48427c478bd9Sstevel@tonic-gate * **************************************************************************
48437c478bd9Sstevel@tonic-gate */
48447c478bd9Sstevel@tonic-gate
48457c478bd9Sstevel@tonic-gate /*
48467c478bd9Sstevel@tonic-gate * FUNCTION: meta_sp_attach()
48477c478bd9Sstevel@tonic-gate * INPUT: sp - the set name of the device to attach to
48487c478bd9Sstevel@tonic-gate * np - the name of the device to attach to
48497c478bd9Sstevel@tonic-gate * addsize - the unparsed string holding the amount of space to add
48507c478bd9Sstevel@tonic-gate * options - metattach options
48517c478bd9Sstevel@tonic-gate * alignment - data alignment
48527c478bd9Sstevel@tonic-gate * OUTPUT: ep - return error pointer
48537c478bd9Sstevel@tonic-gate * RETURNS: int - 0 success, -1 error
48547c478bd9Sstevel@tonic-gate * PURPOSE: grows a soft partition by reading in the existing unit
48557c478bd9Sstevel@tonic-gate * structure and setting its state to Growing, allocating more
48567c478bd9Sstevel@tonic-gate * space (similar to meta_create_sp()), updating the watermarks,
48577c478bd9Sstevel@tonic-gate * and then writing out the new unit structure in the Okay state.
48587c478bd9Sstevel@tonic-gate */
48597c478bd9Sstevel@tonic-gate int
meta_sp_attach(mdsetname_t * sp,mdname_t * np,char * addsize,mdcmdopts_t options,sp_ext_length_t alignment,md_error_t * ep)48607c478bd9Sstevel@tonic-gate meta_sp_attach(
48617c478bd9Sstevel@tonic-gate mdsetname_t *sp,
48627c478bd9Sstevel@tonic-gate mdname_t *np,
48637c478bd9Sstevel@tonic-gate char *addsize,
48647c478bd9Sstevel@tonic-gate mdcmdopts_t options,
48657c478bd9Sstevel@tonic-gate sp_ext_length_t alignment,
48667c478bd9Sstevel@tonic-gate md_error_t *ep
48677c478bd9Sstevel@tonic-gate )
48687c478bd9Sstevel@tonic-gate {
48697c478bd9Sstevel@tonic-gate md_grow_params_t grow_params;
48707c478bd9Sstevel@tonic-gate sp_ext_length_t grow_len; /* amount to grow */
48717c478bd9Sstevel@tonic-gate mp_unit_t *mp, *new_un;
48727c478bd9Sstevel@tonic-gate mdname_t *compnp = NULL;
48737c478bd9Sstevel@tonic-gate
48747c478bd9Sstevel@tonic-gate sp_ext_node_t *extlist = NULL;
48757c478bd9Sstevel@tonic-gate int numexts;
48767c478bd9Sstevel@tonic-gate mdnamelist_t *spnlp = NULL;
48777c478bd9Sstevel@tonic-gate int count;
48787c478bd9Sstevel@tonic-gate md_sp_t *msp;
48797c478bd9Sstevel@tonic-gate daddr_t start_block;
48807c478bd9Sstevel@tonic-gate
48817c478bd9Sstevel@tonic-gate /* should have the same set */
48827c478bd9Sstevel@tonic-gate assert(sp != NULL);
48837c478bd9Sstevel@tonic-gate assert(sp->setno == MD_MIN2SET(meta_getminor(np->dev)));
48847c478bd9Sstevel@tonic-gate
48857c478bd9Sstevel@tonic-gate /* check name */
48867c478bd9Sstevel@tonic-gate if (metachkmeta(np, ep) != 0)
48877c478bd9Sstevel@tonic-gate return (-1);
48887c478bd9Sstevel@tonic-gate
48897c478bd9Sstevel@tonic-gate if (meta_sp_parsesize(addsize, &grow_len) == -1) {
48907c478bd9Sstevel@tonic-gate return (mdmderror(ep, MDE_SP_BAD_LENGTH, 0, np->cname));
48917c478bd9Sstevel@tonic-gate }
48927c478bd9Sstevel@tonic-gate
48937c478bd9Sstevel@tonic-gate if ((mp = (mp_unit_t *)meta_get_mdunit(sp, np, ep)) == NULL)
48947c478bd9Sstevel@tonic-gate return (-1);
48957c478bd9Sstevel@tonic-gate
48967c478bd9Sstevel@tonic-gate /* make sure we don't have a parent */
48977c478bd9Sstevel@tonic-gate if (MD_HAS_PARENT(mp->c.un_parent)) {
48987c478bd9Sstevel@tonic-gate Free(mp);
48997c478bd9Sstevel@tonic-gate return (mdmderror(ep, MDE_INVAL_UNIT, 0, np->cname));
49007c478bd9Sstevel@tonic-gate }
49017c478bd9Sstevel@tonic-gate
49027c478bd9Sstevel@tonic-gate if (getenv(META_SP_DEBUG)) {
49037c478bd9Sstevel@tonic-gate meta_sp_debug("meta_sp_attach: Unit structure before new "
49047c478bd9Sstevel@tonic-gate "space:\n");
49057c478bd9Sstevel@tonic-gate meta_sp_printunit(mp);
49067c478bd9Sstevel@tonic-gate }
49077c478bd9Sstevel@tonic-gate
49087c478bd9Sstevel@tonic-gate /*
49097c478bd9Sstevel@tonic-gate * NOTE: the fast option to metakeyname is 0 as opposed to 1
49107c478bd9Sstevel@tonic-gate * If this was not the case we would suffer the following
49117c478bd9Sstevel@tonic-gate * assertion failure:
49127c478bd9Sstevel@tonic-gate * Assertion failed: type1 != MDT_FAST_META && type1 != MDT_FAST_COMP
49137c478bd9Sstevel@tonic-gate * file meta_check.x, line 315
49147c478bd9Sstevel@tonic-gate * I guess this is because we have not "seen" this drive before
49157c478bd9Sstevel@tonic-gate * and hence hit the failure - this is of course the attach routine
49167c478bd9Sstevel@tonic-gate */
49177c478bd9Sstevel@tonic-gate if ((compnp = metakeyname(&sp, mp->un_key, 0, ep)) == NULL) {
49187c478bd9Sstevel@tonic-gate Free(mp);
49197c478bd9Sstevel@tonic-gate return (-1);
49207c478bd9Sstevel@tonic-gate }
49217c478bd9Sstevel@tonic-gate
49227c478bd9Sstevel@tonic-gate /* metakeyname does not fill in the key. */
49237c478bd9Sstevel@tonic-gate compnp->key = mp->un_key;
49247c478bd9Sstevel@tonic-gate
49257c478bd9Sstevel@tonic-gate /* work out the space on the component that we are dealing with */
49267c478bd9Sstevel@tonic-gate count = meta_sp_get_by_component(sp, compnp, &spnlp, 0, ep);
49277c478bd9Sstevel@tonic-gate
49287c478bd9Sstevel@tonic-gate /*
49297c478bd9Sstevel@tonic-gate * see if the component has been soft partitioned yet, or if an
49307c478bd9Sstevel@tonic-gate * error occurred.
49317c478bd9Sstevel@tonic-gate */
49327c478bd9Sstevel@tonic-gate if (count == 0) {
49337c478bd9Sstevel@tonic-gate Free(mp);
49347c478bd9Sstevel@tonic-gate return (mdmderror(ep, MDE_NOT_SP, 0, np->cname));
49357c478bd9Sstevel@tonic-gate } else if (count < 0) {
49367c478bd9Sstevel@tonic-gate Free(mp);
49377c478bd9Sstevel@tonic-gate return (-1);
49387c478bd9Sstevel@tonic-gate }
49397c478bd9Sstevel@tonic-gate
49407c478bd9Sstevel@tonic-gate /*
49417c478bd9Sstevel@tonic-gate * seed extlist with reserved space at the beginning of the volume and
49427c478bd9Sstevel@tonic-gate * enough space for the end watermark. The end watermark always gets
49437c478bd9Sstevel@tonic-gate * updated, but if the underlying device changes size it may not be
49447c478bd9Sstevel@tonic-gate * pointed to until the extent before it is updated. Since the
49457c478bd9Sstevel@tonic-gate * end of the reserved space is where the first watermark starts,
49467c478bd9Sstevel@tonic-gate * the reserved extent should never be marked for updating.
49477c478bd9Sstevel@tonic-gate */
49487c478bd9Sstevel@tonic-gate if ((start_block = meta_sp_get_start(sp, compnp, ep)) ==
49497c478bd9Sstevel@tonic-gate MD_DISKADDR_ERROR) {
49507c478bd9Sstevel@tonic-gate Free(mp);
49517c478bd9Sstevel@tonic-gate return (-1);
49527c478bd9Sstevel@tonic-gate }
49537c478bd9Sstevel@tonic-gate
49547c478bd9Sstevel@tonic-gate meta_sp_list_insert(NULL, NULL, &extlist, 0ULL, start_block,
49557c478bd9Sstevel@tonic-gate EXTTYP_RESERVED, 0, 0, meta_sp_cmp_by_offset);
49567c478bd9Sstevel@tonic-gate meta_sp_list_insert(NULL, NULL, &extlist,
49577c478bd9Sstevel@tonic-gate metagetsize(compnp, ep) - MD_SP_WMSIZE, MD_SP_WMSIZE,
49587c478bd9Sstevel@tonic-gate EXTTYP_END, 0, EXTFLG_UPDATE, meta_sp_cmp_by_offset);
49597c478bd9Sstevel@tonic-gate
49607c478bd9Sstevel@tonic-gate if (meta_sp_extlist_from_namelist(sp, spnlp, &extlist, ep) == -1) {
49617c478bd9Sstevel@tonic-gate Free(mp);
49627c478bd9Sstevel@tonic-gate return (-1);
49637c478bd9Sstevel@tonic-gate }
49647c478bd9Sstevel@tonic-gate
49657c478bd9Sstevel@tonic-gate metafreenamelist(spnlp);
49667c478bd9Sstevel@tonic-gate
49677c478bd9Sstevel@tonic-gate if (getenv(META_SP_DEBUG)) {
49687c478bd9Sstevel@tonic-gate meta_sp_debug("meta_sp_attach: list of used extents:\n");
49697c478bd9Sstevel@tonic-gate meta_sp_list_dump(extlist);
49707c478bd9Sstevel@tonic-gate }
49717c478bd9Sstevel@tonic-gate
49727c478bd9Sstevel@tonic-gate meta_sp_list_freefill(&extlist, metagetsize(compnp, ep));
49737c478bd9Sstevel@tonic-gate
49747c478bd9Sstevel@tonic-gate assert(mp->un_numexts >= 1);
49757c478bd9Sstevel@tonic-gate numexts = meta_sp_alloc_by_len(sp, np, &extlist, &grow_len,
49767c478bd9Sstevel@tonic-gate mp->un_ext[mp->un_numexts - 1].un_poff,
49777c478bd9Sstevel@tonic-gate (alignment > 0) ? alignment :
49787c478bd9Sstevel@tonic-gate meta_sp_get_default_alignment(sp, compnp, ep));
49797c478bd9Sstevel@tonic-gate
49807c478bd9Sstevel@tonic-gate if (numexts == -1) {
49817c478bd9Sstevel@tonic-gate Free(mp);
49827c478bd9Sstevel@tonic-gate return (mdmderror(ep, MDE_SP_NOSPACE, 0, np->cname));
49837c478bd9Sstevel@tonic-gate }
49847c478bd9Sstevel@tonic-gate
49857c478bd9Sstevel@tonic-gate /* allocate new unit structure and copy in old unit */
49867c478bd9Sstevel@tonic-gate if ((new_un = meta_sp_updateunit(np, mp, extlist,
49877c478bd9Sstevel@tonic-gate grow_len, numexts, ep)) == NULL) {
49887c478bd9Sstevel@tonic-gate Free(mp);
49897c478bd9Sstevel@tonic-gate return (-1);
49907c478bd9Sstevel@tonic-gate }
49917c478bd9Sstevel@tonic-gate Free(mp);
49927c478bd9Sstevel@tonic-gate
49937c478bd9Sstevel@tonic-gate /* If running in dryrun mode (-n option), we're done here */
49947c478bd9Sstevel@tonic-gate if ((options & MDCMD_DOIT) == 0) {
49957c478bd9Sstevel@tonic-gate if (options & MDCMD_PRINT) {
49967c478bd9Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN,
49977c478bd9Sstevel@tonic-gate "%s: Soft Partition would grow\n"),
49987c478bd9Sstevel@tonic-gate np->cname);
49997c478bd9Sstevel@tonic-gate (void) fflush(stdout);
50007c478bd9Sstevel@tonic-gate }
50017c478bd9Sstevel@tonic-gate return (0);
50027c478bd9Sstevel@tonic-gate }
50037c478bd9Sstevel@tonic-gate
50047c478bd9Sstevel@tonic-gate if (getenv(META_SP_DEBUG)) {
50057c478bd9Sstevel@tonic-gate meta_sp_debug("meta_sp_attach: updated unit structure:\n");
50067c478bd9Sstevel@tonic-gate meta_sp_printunit(new_un);
50077c478bd9Sstevel@tonic-gate }
50087c478bd9Sstevel@tonic-gate
50097c478bd9Sstevel@tonic-gate assert(new_un != NULL);
50107c478bd9Sstevel@tonic-gate
50117c478bd9Sstevel@tonic-gate (void) memset(&grow_params, 0, sizeof (grow_params));
50127c478bd9Sstevel@tonic-gate if (new_un->c.un_total_blocks > MD_MAX_BLKS_FOR_SMALL_DEVS) {
50137c478bd9Sstevel@tonic-gate grow_params.options = MD_CRO_64BIT;
5014d7cd8252Stw21770 new_un->c.un_revision |= MD_64BIT_META_DEV;
50157c478bd9Sstevel@tonic-gate } else {
50167c478bd9Sstevel@tonic-gate grow_params.options = MD_CRO_32BIT;
5017d7cd8252Stw21770 new_un->c.un_revision &= ~MD_64BIT_META_DEV;
50187c478bd9Sstevel@tonic-gate }
50197c478bd9Sstevel@tonic-gate grow_params.mnum = MD_SID(new_un);
50207c478bd9Sstevel@tonic-gate grow_params.size = new_un->c.un_size;
50217c478bd9Sstevel@tonic-gate grow_params.mdp = (uintptr_t)new_un;
50227c478bd9Sstevel@tonic-gate MD_SETDRIVERNAME(&grow_params, MD_SP, MD_MIN2SET(grow_params.mnum));
50237c478bd9Sstevel@tonic-gate
50247c478bd9Sstevel@tonic-gate if (metaioctl(MD_IOCGROW, &grow_params, &grow_params.mde,
50257c478bd9Sstevel@tonic-gate np->cname) != 0) {
50267c478bd9Sstevel@tonic-gate (void) mdstealerror(ep, &grow_params.mde);
50277c478bd9Sstevel@tonic-gate return (-1);
50287c478bd9Sstevel@tonic-gate }
50297c478bd9Sstevel@tonic-gate
50307c478bd9Sstevel@tonic-gate /* update all watermarks */
50317c478bd9Sstevel@tonic-gate
50327c478bd9Sstevel@tonic-gate if ((msp = meta_get_sp(sp, np, ep)) == NULL)
50337c478bd9Sstevel@tonic-gate return (-1);
50347c478bd9Sstevel@tonic-gate if (meta_sp_update_wm(sp, msp, extlist, ep) < 0)
50357c478bd9Sstevel@tonic-gate return (-1);
50367c478bd9Sstevel@tonic-gate
50377c478bd9Sstevel@tonic-gate
50387c478bd9Sstevel@tonic-gate /* second phase of commit, set status to MD_SP_OK */
50397c478bd9Sstevel@tonic-gate if (meta_sp_setstatus(sp, &(MD_SID(new_un)), 1, MD_SP_OK, ep) < 0)
50407c478bd9Sstevel@tonic-gate return (-1);
50417c478bd9Sstevel@tonic-gate
50427c478bd9Sstevel@tonic-gate meta_invalidate_name(np);
50437c478bd9Sstevel@tonic-gate
50447c478bd9Sstevel@tonic-gate if (options & MDCMD_PRINT) {
50457c478bd9Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN,
50467c478bd9Sstevel@tonic-gate "%s: Soft Partition has been grown\n"),
50477c478bd9Sstevel@tonic-gate np->cname);
50487c478bd9Sstevel@tonic-gate (void) fflush(stdout);
50497c478bd9Sstevel@tonic-gate }
50507c478bd9Sstevel@tonic-gate
50517c478bd9Sstevel@tonic-gate return (0);
50527c478bd9Sstevel@tonic-gate }
50537c478bd9Sstevel@tonic-gate
50547c478bd9Sstevel@tonic-gate /*
50557c478bd9Sstevel@tonic-gate * **************************************************************************
50567c478bd9Sstevel@tonic-gate * Recovery (metarecover) Functions *
50577c478bd9Sstevel@tonic-gate * **************************************************************************
50587c478bd9Sstevel@tonic-gate */
50597c478bd9Sstevel@tonic-gate
50607c478bd9Sstevel@tonic-gate /*
50617c478bd9Sstevel@tonic-gate * FUNCTION: meta_recover_sp()
50627c478bd9Sstevel@tonic-gate * INPUT: sp - the name of the set we are recovering on
50637c478bd9Sstevel@tonic-gate * compnp - name pointer for device we are recovering on
50647c478bd9Sstevel@tonic-gate * argc - argument count
50657c478bd9Sstevel@tonic-gate * argv - left over arguments not parsed by metarecover command
50667c478bd9Sstevel@tonic-gate * options - metarecover options
50677c478bd9Sstevel@tonic-gate * OUTPUT: ep - return error pointer
50687c478bd9Sstevel@tonic-gate * RETURNS: int - 0 - success, -1 - error
50697c478bd9Sstevel@tonic-gate * PURPOSE: parse soft partitioning-specific metarecover options and
50707c478bd9Sstevel@tonic-gate * dispatch to the appropriate function to handle recovery.
50717c478bd9Sstevel@tonic-gate */
50727c478bd9Sstevel@tonic-gate int
meta_recover_sp(mdsetname_t * sp,mdname_t * compnp,int argc,char * argv[],mdcmdopts_t options,md_error_t * ep)50737c478bd9Sstevel@tonic-gate meta_recover_sp(
50747c478bd9Sstevel@tonic-gate mdsetname_t *sp,
50757c478bd9Sstevel@tonic-gate mdname_t *compnp,
50767c478bd9Sstevel@tonic-gate int argc,
50777c478bd9Sstevel@tonic-gate char *argv[],
50787c478bd9Sstevel@tonic-gate mdcmdopts_t options,
50797c478bd9Sstevel@tonic-gate md_error_t *ep
50807c478bd9Sstevel@tonic-gate )
50817c478bd9Sstevel@tonic-gate {
50827c478bd9Sstevel@tonic-gate md_set_desc *sd;
50837c478bd9Sstevel@tonic-gate
50847c478bd9Sstevel@tonic-gate if (argc > 1) {
50857c478bd9Sstevel@tonic-gate (void) meta_cook_syntax(ep, MDE_SYNTAX, compnp->cname,
50867c478bd9Sstevel@tonic-gate argc, argv);
50877c478bd9Sstevel@tonic-gate return (-1);
50887c478bd9Sstevel@tonic-gate }
50897c478bd9Sstevel@tonic-gate
50907c478bd9Sstevel@tonic-gate /*
50917c478bd9Sstevel@tonic-gate * For a MN set, this operation must be performed on the master
50927c478bd9Sstevel@tonic-gate * as it is responsible for maintaining the watermarks
50937c478bd9Sstevel@tonic-gate */
50947c478bd9Sstevel@tonic-gate if (!metaislocalset(sp)) {
50957c478bd9Sstevel@tonic-gate if ((sd = metaget_setdesc(sp, ep)) == NULL)
50967c478bd9Sstevel@tonic-gate return (-1);
50977c478bd9Sstevel@tonic-gate if (MD_MNSET_DESC(sd) && !sd->sd_mn_am_i_master) {
50987c478bd9Sstevel@tonic-gate (void) mddserror(ep, MDE_DS_MASTER_ONLY, sp->setno,
50997c478bd9Sstevel@tonic-gate sd->sd_mn_master_nodenm, NULL, NULL);
51007c478bd9Sstevel@tonic-gate return (-1);
51017c478bd9Sstevel@tonic-gate }
51027c478bd9Sstevel@tonic-gate }
51037c478bd9Sstevel@tonic-gate if (argc == 0) {
51047c478bd9Sstevel@tonic-gate /*
51057c478bd9Sstevel@tonic-gate * if no additional arguments are passed, metarecover should
51067c478bd9Sstevel@tonic-gate * validate both on-disk and metadb structures as well as
51077c478bd9Sstevel@tonic-gate * checking that both are consistent with each other
51087c478bd9Sstevel@tonic-gate */
51097c478bd9Sstevel@tonic-gate if (meta_sp_validate_wm(sp, compnp, options, ep) < 0)
51107c478bd9Sstevel@tonic-gate return (-1);
51117c478bd9Sstevel@tonic-gate if (meta_sp_validate_unit(sp, compnp, options, ep) < 0)
51127c478bd9Sstevel@tonic-gate return (-1);
51137c478bd9Sstevel@tonic-gate if (meta_sp_validate_wm_and_unit(sp, compnp, options, ep) < 0)
51147c478bd9Sstevel@tonic-gate return (-1);
51157c478bd9Sstevel@tonic-gate } else if (strcmp(argv[0], "-d") == 0) {
51167c478bd9Sstevel@tonic-gate /*
51177c478bd9Sstevel@tonic-gate * Ensure that there is no existing valid record for this
51187c478bd9Sstevel@tonic-gate * soft-partition. If there is we have nothing to do.
51197c478bd9Sstevel@tonic-gate */
51207c478bd9Sstevel@tonic-gate if (meta_sp_validate_unit(sp, compnp, options, ep) == 0)
51217c478bd9Sstevel@tonic-gate return (-1);
51227c478bd9Sstevel@tonic-gate /* validate and recover from on-disk structures */
51237c478bd9Sstevel@tonic-gate if (meta_sp_validate_wm(sp, compnp, options, ep) < 0)
51247c478bd9Sstevel@tonic-gate return (-1);
51257c478bd9Sstevel@tonic-gate if (meta_sp_recover_from_wm(sp, compnp, options, ep) < 0)
51267c478bd9Sstevel@tonic-gate return (-1);
51277c478bd9Sstevel@tonic-gate } else if (strcmp(argv[0], "-m") == 0) {
51287c478bd9Sstevel@tonic-gate /* validate and recover from metadb structures */
51297c478bd9Sstevel@tonic-gate if (meta_sp_validate_unit(sp, compnp, options, ep) < 0)
51307c478bd9Sstevel@tonic-gate return (-1);
51317c478bd9Sstevel@tonic-gate if (meta_sp_recover_from_unit(sp, compnp, options, ep) < 0)
51327c478bd9Sstevel@tonic-gate return (-1);
51337c478bd9Sstevel@tonic-gate } else {
51347c478bd9Sstevel@tonic-gate /* syntax error */
51357c478bd9Sstevel@tonic-gate (void) meta_cook_syntax(ep, MDE_SYNTAX, compnp->cname,
51367c478bd9Sstevel@tonic-gate argc, argv);
51377c478bd9Sstevel@tonic-gate return (-1);
51387c478bd9Sstevel@tonic-gate }
51397c478bd9Sstevel@tonic-gate
51407c478bd9Sstevel@tonic-gate return (0);
51417c478bd9Sstevel@tonic-gate }
51427c478bd9Sstevel@tonic-gate
51437c478bd9Sstevel@tonic-gate /*
51447c478bd9Sstevel@tonic-gate * FUNCTION: meta_sp_display_exthdr()
51457c478bd9Sstevel@tonic-gate * INPUT: none
51467c478bd9Sstevel@tonic-gate * OUTPUT: none
51477c478bd9Sstevel@tonic-gate * RETURNS: void
51487c478bd9Sstevel@tonic-gate * PURPOSE: print header line for sp_ext_node_t information. to be used
51497c478bd9Sstevel@tonic-gate * in conjunction with meta_sp_display_ext().
51507c478bd9Sstevel@tonic-gate */
51517c478bd9Sstevel@tonic-gate static void
meta_sp_display_exthdr(void)51527c478bd9Sstevel@tonic-gate meta_sp_display_exthdr(void)
51537c478bd9Sstevel@tonic-gate {
51547c478bd9Sstevel@tonic-gate (void) printf("%20s %5s %7s %20s %20s\n",
51557c478bd9Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Name"),
51567c478bd9Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Seq#"),
51577c478bd9Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Type"),
51587c478bd9Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Offset"),
51597c478bd9Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Length"));
51607c478bd9Sstevel@tonic-gate }
51617c478bd9Sstevel@tonic-gate
51627c478bd9Sstevel@tonic-gate
51637c478bd9Sstevel@tonic-gate /*
51647c478bd9Sstevel@tonic-gate * FUNCTION: meta_sp_display_ext()
51657c478bd9Sstevel@tonic-gate * INPUT: ext - extent to display
51667c478bd9Sstevel@tonic-gate * OUTPUT: none
51677c478bd9Sstevel@tonic-gate * RETURNS: void
51687c478bd9Sstevel@tonic-gate * PURPOSE: print selected fields from sp_ext_node_t.
51697c478bd9Sstevel@tonic-gate */
51707c478bd9Sstevel@tonic-gate static void
meta_sp_display_ext(sp_ext_node_t * ext)51717c478bd9Sstevel@tonic-gate meta_sp_display_ext(sp_ext_node_t *ext)
51727c478bd9Sstevel@tonic-gate {
51737c478bd9Sstevel@tonic-gate /* print extent information */
51747c478bd9Sstevel@tonic-gate if (ext->ext_namep != NULL)
51757c478bd9Sstevel@tonic-gate (void) printf("%20s ", ext->ext_namep->cname);
51767c478bd9Sstevel@tonic-gate else
51777c478bd9Sstevel@tonic-gate (void) printf("%20s ", "NONE");
51787c478bd9Sstevel@tonic-gate
51797c478bd9Sstevel@tonic-gate (void) printf("%5u ", ext->ext_seq);
51807c478bd9Sstevel@tonic-gate
51817c478bd9Sstevel@tonic-gate switch (ext->ext_type) {
51827c478bd9Sstevel@tonic-gate case EXTTYP_ALLOC:
51837c478bd9Sstevel@tonic-gate (void) printf("%7s ", "ALLOC");
51847c478bd9Sstevel@tonic-gate break;
51857c478bd9Sstevel@tonic-gate case EXTTYP_FREE:
51867c478bd9Sstevel@tonic-gate (void) printf("%7s ", "FREE");
51877c478bd9Sstevel@tonic-gate break;
51887c478bd9Sstevel@tonic-gate case EXTTYP_RESERVED:
51897c478bd9Sstevel@tonic-gate (void) printf("%7s ", "RESV");
51907c478bd9Sstevel@tonic-gate break;
51917c478bd9Sstevel@tonic-gate case EXTTYP_END:
51927c478bd9Sstevel@tonic-gate (void) printf("%7s ", "END");
51937c478bd9Sstevel@tonic-gate break;
51947c478bd9Sstevel@tonic-gate default:
51957c478bd9Sstevel@tonic-gate (void) printf("%7s ", "INVLD");
51967c478bd9Sstevel@tonic-gate break;
51977c478bd9Sstevel@tonic-gate }
51987c478bd9Sstevel@tonic-gate
51997c478bd9Sstevel@tonic-gate (void) printf("%20llu %20llu\n", ext->ext_offset, ext->ext_length);
52007c478bd9Sstevel@tonic-gate }
52017c478bd9Sstevel@tonic-gate
52027c478bd9Sstevel@tonic-gate
52037c478bd9Sstevel@tonic-gate /*
52047c478bd9Sstevel@tonic-gate * FUNCTION: meta_sp_checkseq()
52057c478bd9Sstevel@tonic-gate * INPUT: extlist - list of extents to be checked
52067c478bd9Sstevel@tonic-gate * OUTPUT: none
52077c478bd9Sstevel@tonic-gate * RETURNS: int - 0 - success, -1 - error
52087c478bd9Sstevel@tonic-gate * PURPOSE: check soft partition sequence numbers. this function assumes
52097c478bd9Sstevel@tonic-gate * that a list of extents representing 1 or more soft partitions
52107c478bd9Sstevel@tonic-gate * is passed in sorted in sequence number order. within a
52117c478bd9Sstevel@tonic-gate * single soft partition, there may not be any missing or
52127c478bd9Sstevel@tonic-gate * duplicate sequence numbers.
52137c478bd9Sstevel@tonic-gate */
52147c478bd9Sstevel@tonic-gate static int
meta_sp_checkseq(sp_ext_node_t * extlist)52157c478bd9Sstevel@tonic-gate meta_sp_checkseq(sp_ext_node_t *extlist)
52167c478bd9Sstevel@tonic-gate {
52177c478bd9Sstevel@tonic-gate sp_ext_node_t *ext;
52187c478bd9Sstevel@tonic-gate
52197c478bd9Sstevel@tonic-gate assert(extlist != NULL);
52207c478bd9Sstevel@tonic-gate
52217c478bd9Sstevel@tonic-gate for (ext = extlist;
52227c478bd9Sstevel@tonic-gate ext->ext_next != NULL && ext->ext_next->ext_type == EXTTYP_ALLOC;
52237c478bd9Sstevel@tonic-gate ext = ext->ext_next) {
52247c478bd9Sstevel@tonic-gate if (ext->ext_next->ext_namep != NULL &&
52257c478bd9Sstevel@tonic-gate strcmp(ext->ext_next->ext_namep->cname,
52267c478bd9Sstevel@tonic-gate ext->ext_namep->cname) != 0)
52277c478bd9Sstevel@tonic-gate continue;
52287c478bd9Sstevel@tonic-gate
52297c478bd9Sstevel@tonic-gate if (ext->ext_next->ext_seq != ext->ext_seq + 1) {
52307c478bd9Sstevel@tonic-gate (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
52317c478bd9Sstevel@tonic-gate "%s: sequence numbers are "
52327c478bd9Sstevel@tonic-gate "incorrect: %d should be %d\n"),
52337c478bd9Sstevel@tonic-gate ext->ext_next->ext_namep->cname,
52347c478bd9Sstevel@tonic-gate ext->ext_next->ext_seq, ext->ext_seq + 1);
52357c478bd9Sstevel@tonic-gate return (-1);
52367c478bd9Sstevel@tonic-gate }
52377c478bd9Sstevel@tonic-gate }
52387c478bd9Sstevel@tonic-gate return (0);
52397c478bd9Sstevel@tonic-gate }
52407c478bd9Sstevel@tonic-gate
52417c478bd9Sstevel@tonic-gate
52427c478bd9Sstevel@tonic-gate /*
52437c478bd9Sstevel@tonic-gate * FUNCTION: meta_sp_resolve_name_conflict()
52447c478bd9Sstevel@tonic-gate * INPUT: sp - name of set we're are recovering in.
52457c478bd9Sstevel@tonic-gate * old_np - name pointer of soft partition we found on disk.
52467c478bd9Sstevel@tonic-gate * OUTPUT: new_np - name pointer for new soft partition name.
52477c478bd9Sstevel@tonic-gate * ep - error pointer returned.
52487c478bd9Sstevel@tonic-gate * RETURNS: int - 0 - name not replace, 1 - name replaced, -1 - error
52497c478bd9Sstevel@tonic-gate * PURPOSE: Check to see if the name of one of the soft partitions we found
52507c478bd9Sstevel@tonic-gate * on disk already exists in the metadb. If so, prompt for a new
52517c478bd9Sstevel@tonic-gate * name. In addition, we keep a static array of names that
52527c478bd9Sstevel@tonic-gate * will be recovered from this device since these names don't
52537c478bd9Sstevel@tonic-gate * exist in the configuration at this point but cannot be
52547c478bd9Sstevel@tonic-gate * recovered more than once.
52557c478bd9Sstevel@tonic-gate */
52567c478bd9Sstevel@tonic-gate static int
meta_sp_resolve_name_conflict(mdsetname_t * sp,mdname_t * old_np,mdname_t ** new_np,md_error_t * ep)52577c478bd9Sstevel@tonic-gate meta_sp_resolve_name_conflict(
52587c478bd9Sstevel@tonic-gate mdsetname_t *sp,
52597c478bd9Sstevel@tonic-gate mdname_t *old_np,
52607c478bd9Sstevel@tonic-gate mdname_t **new_np,
52617c478bd9Sstevel@tonic-gate md_error_t *ep
52627c478bd9Sstevel@tonic-gate )
52637c478bd9Sstevel@tonic-gate {
52647c478bd9Sstevel@tonic-gate char yesno[255];
52657c478bd9Sstevel@tonic-gate char *yes;
52667c478bd9Sstevel@tonic-gate char newname[MD_SP_MAX_DEVNAME_PLUS_1];
52677c478bd9Sstevel@tonic-gate int nunits;
52687c478bd9Sstevel@tonic-gate static int *used_names = NULL;
52697c478bd9Sstevel@tonic-gate
52707c478bd9Sstevel@tonic-gate assert(old_np != NULL);
52717c478bd9Sstevel@tonic-gate
52727c478bd9Sstevel@tonic-gate if (used_names == NULL) {
52737c478bd9Sstevel@tonic-gate if ((nunits = meta_get_nunits(ep)) < 0)
52747c478bd9Sstevel@tonic-gate return (-1);
52757c478bd9Sstevel@tonic-gate used_names = Zalloc(nunits * sizeof (int));
52767c478bd9Sstevel@tonic-gate }
52777c478bd9Sstevel@tonic-gate
52787c478bd9Sstevel@tonic-gate /* see if it exists already */
52797c478bd9Sstevel@tonic-gate if (used_names[MD_MIN2UNIT(meta_getminor(old_np->dev))] == 0 &&
52807c478bd9Sstevel@tonic-gate metagetmiscname(old_np, ep) == NULL) {
52817c478bd9Sstevel@tonic-gate if (! mdismderror(ep, MDE_UNIT_NOT_SETUP))
52827c478bd9Sstevel@tonic-gate return (-1);
52837c478bd9Sstevel@tonic-gate else {
52847c478bd9Sstevel@tonic-gate used_names[MD_MIN2UNIT(meta_getminor(old_np->dev))] = 1;
52857c478bd9Sstevel@tonic-gate mdclrerror(ep);
52867c478bd9Sstevel@tonic-gate return (0);
52877c478bd9Sstevel@tonic-gate }
52887c478bd9Sstevel@tonic-gate }
52897c478bd9Sstevel@tonic-gate
52907c478bd9Sstevel@tonic-gate /* name exists, ask the user for a new one */
52917c478bd9Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN,
52927c478bd9Sstevel@tonic-gate "WARNING: A soft partition named %s was found in the extent\n"
52937c478bd9Sstevel@tonic-gate "headers, but this name already exists in the metadb "
52947c478bd9Sstevel@tonic-gate "configuration.\n"
52957c478bd9Sstevel@tonic-gate "In order to continue recovery you must supply\n"
52967c478bd9Sstevel@tonic-gate "a new name for this soft partition.\n"), old_np->cname);
52977c478bd9Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN,
52987c478bd9Sstevel@tonic-gate "Would you like to continue and supply a new name? (yes/no) "));
52997c478bd9Sstevel@tonic-gate
53007c478bd9Sstevel@tonic-gate (void) fflush(stdout);
53017c478bd9Sstevel@tonic-gate if ((fgets(yesno, sizeof (yesno), stdin) == NULL) ||
53027c478bd9Sstevel@tonic-gate (strlen(yesno) == 1))
53037c478bd9Sstevel@tonic-gate (void) snprintf(yesno, sizeof (yesno), "%s\n",
53047c478bd9Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "no"));
53057c478bd9Sstevel@tonic-gate yes = dgettext(TEXT_DOMAIN, "yes");
53067c478bd9Sstevel@tonic-gate if (strncasecmp(yesno, yes, strlen(yesno) - 1) != 0) {
53077c478bd9Sstevel@tonic-gate return (-1);
53087c478bd9Sstevel@tonic-gate }
53097c478bd9Sstevel@tonic-gate
53107c478bd9Sstevel@tonic-gate (void) fflush(stdin);
53117c478bd9Sstevel@tonic-gate
53127c478bd9Sstevel@tonic-gate /* get the new name */
53137c478bd9Sstevel@tonic-gate for (;;) {
53147c478bd9Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN, "Please enter a new name "
53157c478bd9Sstevel@tonic-gate "for this soft partition (dXXXX) "));
53167c478bd9Sstevel@tonic-gate (void) fflush(stdout);
53177c478bd9Sstevel@tonic-gate if (fgets(newname, MD_SP_MAX_DEVNAME_PLUS_1, stdin) == NULL)
53187c478bd9Sstevel@tonic-gate (void) strcpy(newname, "");
53197c478bd9Sstevel@tonic-gate
53207c478bd9Sstevel@tonic-gate /* remove newline character */
53217c478bd9Sstevel@tonic-gate if (newname[strlen(newname) - 1] == '\n')
53227c478bd9Sstevel@tonic-gate newname[strlen(newname) - 1] = '\0';
53237c478bd9Sstevel@tonic-gate
53247c478bd9Sstevel@tonic-gate if (!(is_metaname(newname)) ||
5325d7cd8252Stw21770 (meta_init_make_device(&sp, newname, ep) <= 0)) {
53267c478bd9Sstevel@tonic-gate (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
53277c478bd9Sstevel@tonic-gate "Invalid metadevice name\n"));
53287c478bd9Sstevel@tonic-gate (void) fflush(stderr);
53297c478bd9Sstevel@tonic-gate continue;
53307c478bd9Sstevel@tonic-gate }
53317c478bd9Sstevel@tonic-gate
5332d7cd8252Stw21770 if ((*new_np = metaname(&sp, newname,
5333d7cd8252Stw21770 META_DEVICE, ep)) == NULL) {
53347c478bd9Sstevel@tonic-gate (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
53357c478bd9Sstevel@tonic-gate "Invalid metadevice name\n"));
53367c478bd9Sstevel@tonic-gate (void) fflush(stderr);
53377c478bd9Sstevel@tonic-gate continue;
53387c478bd9Sstevel@tonic-gate }
53397c478bd9Sstevel@tonic-gate
53407c478bd9Sstevel@tonic-gate assert(MD_MIN2UNIT(meta_getminor((*new_np)->dev)) < nunits);
53417c478bd9Sstevel@tonic-gate /* make sure the name isn't already being used */
53427c478bd9Sstevel@tonic-gate if (used_names[MD_MIN2UNIT(meta_getminor((*new_np)->dev))] ||
53437c478bd9Sstevel@tonic-gate metagetmiscname(*new_np, ep) != NULL) {
53447c478bd9Sstevel@tonic-gate (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
53457c478bd9Sstevel@tonic-gate "That name already exists\n"));
53467c478bd9Sstevel@tonic-gate continue;
53477c478bd9Sstevel@tonic-gate } else if (! mdismderror(ep, MDE_UNIT_NOT_SETUP))
53487c478bd9Sstevel@tonic-gate return (-1);
53497c478bd9Sstevel@tonic-gate
53507c478bd9Sstevel@tonic-gate break;
53517c478bd9Sstevel@tonic-gate }
53527c478bd9Sstevel@tonic-gate
53537c478bd9Sstevel@tonic-gate /* got a new name, place in used array and return */
53547c478bd9Sstevel@tonic-gate used_names[MD_MIN2UNIT(meta_getminor((*new_np)->dev))] = 1;
53557c478bd9Sstevel@tonic-gate mdclrerror(ep);
53567c478bd9Sstevel@tonic-gate return (1);
53577c478bd9Sstevel@tonic-gate }
53587c478bd9Sstevel@tonic-gate
53597c478bd9Sstevel@tonic-gate /*
53607c478bd9Sstevel@tonic-gate * FUNCTION: meta_sp_validate_wm()
53617c478bd9Sstevel@tonic-gate * INPUT: sp - set name we are recovering in
53627c478bd9Sstevel@tonic-gate * compnp - name pointer for device we are recovering from
53637c478bd9Sstevel@tonic-gate * options - metarecover options
53647c478bd9Sstevel@tonic-gate * OUTPUT: ep - error pointer returned
53657c478bd9Sstevel@tonic-gate * RETURNS: int - 0 - success, -1 - error
53667c478bd9Sstevel@tonic-gate * PURPOSE: validate and display watermark configuration. walk the
53677c478bd9Sstevel@tonic-gate * on-disk watermark structures and validate the information
53687c478bd9Sstevel@tonic-gate * found within. since a watermark configuration is
53697c478bd9Sstevel@tonic-gate * "self-defining", the act of traversing the watermarks
53707c478bd9Sstevel@tonic-gate * is part of the validation process.
53717c478bd9Sstevel@tonic-gate */
53727c478bd9Sstevel@tonic-gate static int
meta_sp_validate_wm(mdsetname_t * sp,mdname_t * compnp,mdcmdopts_t options,md_error_t * ep)53737c478bd9Sstevel@tonic-gate meta_sp_validate_wm(
53747c478bd9Sstevel@tonic-gate mdsetname_t *sp,
53757c478bd9Sstevel@tonic-gate mdname_t *compnp,
53767c478bd9Sstevel@tonic-gate mdcmdopts_t options,
53777c478bd9Sstevel@tonic-gate md_error_t *ep
53787c478bd9Sstevel@tonic-gate )
53797c478bd9Sstevel@tonic-gate {
53807c478bd9Sstevel@tonic-gate sp_ext_node_t *extlist = NULL;
53817c478bd9Sstevel@tonic-gate sp_ext_node_t *ext;
53827c478bd9Sstevel@tonic-gate int num_sps = 0;
53837c478bd9Sstevel@tonic-gate int rval;
53847c478bd9Sstevel@tonic-gate
53857c478bd9Sstevel@tonic-gate if ((options & MDCMD_VERBOSE) != 0)
53867c478bd9Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN,
53877c478bd9Sstevel@tonic-gate "Verifying on-disk structures on %s.\n"),
53887c478bd9Sstevel@tonic-gate compnp->cname);
53897c478bd9Sstevel@tonic-gate
53907c478bd9Sstevel@tonic-gate /*
53917c478bd9Sstevel@tonic-gate * for each watermark, build an ext_node, place on list.
53927c478bd9Sstevel@tonic-gate */
53937c478bd9Sstevel@tonic-gate rval = meta_sp_extlist_from_wm(sp, compnp, &extlist,
53947c478bd9Sstevel@tonic-gate meta_sp_cmp_by_nameseq, ep);
53957c478bd9Sstevel@tonic-gate
53967c478bd9Sstevel@tonic-gate if ((options & MDCMD_VERBOSE) != 0) {
53977c478bd9Sstevel@tonic-gate /* print out what we found */
53987c478bd9Sstevel@tonic-gate if (extlist == NULL)
53997c478bd9Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN,
54007c478bd9Sstevel@tonic-gate "No extent headers found on %s.\n"),
54017c478bd9Sstevel@tonic-gate compnp->cname);
54027c478bd9Sstevel@tonic-gate else {
54037c478bd9Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN,
54047c478bd9Sstevel@tonic-gate "The following extent headers were found on %s.\n"),
54057c478bd9Sstevel@tonic-gate compnp->cname);
54067c478bd9Sstevel@tonic-gate meta_sp_display_exthdr();
54077c478bd9Sstevel@tonic-gate }
54087c478bd9Sstevel@tonic-gate for (ext = extlist; ext != NULL; ext = ext->ext_next)
54097c478bd9Sstevel@tonic-gate meta_sp_display_ext(ext);
54107c478bd9Sstevel@tonic-gate }
54117c478bd9Sstevel@tonic-gate
54127c478bd9Sstevel@tonic-gate if (rval < 0) {
54137c478bd9Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN,
54147c478bd9Sstevel@tonic-gate "%s: On-disk structures invalid or "
54157c478bd9Sstevel@tonic-gate "no soft partitions found.\n"),
54167c478bd9Sstevel@tonic-gate compnp->cname);
54177c478bd9Sstevel@tonic-gate return (-1);
54187c478bd9Sstevel@tonic-gate }
54197c478bd9Sstevel@tonic-gate
54207c478bd9Sstevel@tonic-gate assert(extlist != NULL);
54217c478bd9Sstevel@tonic-gate
54227c478bd9Sstevel@tonic-gate /* count number of soft partitions */
54237c478bd9Sstevel@tonic-gate for (ext = extlist;
54247c478bd9Sstevel@tonic-gate ext != NULL && ext->ext_type == EXTTYP_ALLOC;
54257c478bd9Sstevel@tonic-gate ext = ext->ext_next) {
54267c478bd9Sstevel@tonic-gate if (ext->ext_next != NULL &&
54277c478bd9Sstevel@tonic-gate ext->ext_next->ext_namep != NULL &&
54287c478bd9Sstevel@tonic-gate strcmp(ext->ext_next->ext_namep->cname,
54297c478bd9Sstevel@tonic-gate ext->ext_namep->cname) == 0)
54307c478bd9Sstevel@tonic-gate continue;
54317c478bd9Sstevel@tonic-gate num_sps++;
54327c478bd9Sstevel@tonic-gate }
54337c478bd9Sstevel@tonic-gate
54347c478bd9Sstevel@tonic-gate if ((options & MDCMD_VERBOSE) != 0)
54357c478bd9Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN,
54367c478bd9Sstevel@tonic-gate "Found %d soft partition(s) on %s.\n"), num_sps,
54377c478bd9Sstevel@tonic-gate compnp->cname);
54387c478bd9Sstevel@tonic-gate
54397c478bd9Sstevel@tonic-gate if (num_sps == 0) {
54407c478bd9Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN,
54417c478bd9Sstevel@tonic-gate "%s: No soft partitions.\n"), compnp->cname);
54427c478bd9Sstevel@tonic-gate return (mdmderror(ep, MDE_RECOVER_FAILED, 0, compnp->cname));
54437c478bd9Sstevel@tonic-gate }
54447c478bd9Sstevel@tonic-gate
54457c478bd9Sstevel@tonic-gate /* check sequence numbers */
54467c478bd9Sstevel@tonic-gate if ((options & MDCMD_VERBOSE) != 0)
54477c478bd9Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN,
54487c478bd9Sstevel@tonic-gate "Checking sequence numbers.\n"));
54497c478bd9Sstevel@tonic-gate
54507c478bd9Sstevel@tonic-gate if (meta_sp_checkseq(extlist) != 0)
54517c478bd9Sstevel@tonic-gate return (mdmderror(ep, MDE_RECOVER_FAILED, 0, compnp->cname));
54527c478bd9Sstevel@tonic-gate
54537c478bd9Sstevel@tonic-gate return (0);
54547c478bd9Sstevel@tonic-gate }
54557c478bd9Sstevel@tonic-gate
54567c478bd9Sstevel@tonic-gate /*
54577c478bd9Sstevel@tonic-gate * FUNCTION: meta_sp_validate_unit()
54587c478bd9Sstevel@tonic-gate * INPUT: sp - name of set we are recovering in
54597c478bd9Sstevel@tonic-gate * compnp - name of component we are recovering from
54607c478bd9Sstevel@tonic-gate * options - metarecover options
54617c478bd9Sstevel@tonic-gate * OUTPUT: ep - error pointer returned
54627c478bd9Sstevel@tonic-gate * RETURNS: int - 0 - success, -1 - error
54637c478bd9Sstevel@tonic-gate * PURPOSE: validate and display metadb configuration. begin by getting
54647c478bd9Sstevel@tonic-gate * all soft partitions built on the specified component. get
54657c478bd9Sstevel@tonic-gate * the unit structure for each one and validate the fields within.
54667c478bd9Sstevel@tonic-gate */
54677c478bd9Sstevel@tonic-gate static int
meta_sp_validate_unit(mdsetname_t * sp,mdname_t * compnp,mdcmdopts_t options,md_error_t * ep)54687c478bd9Sstevel@tonic-gate meta_sp_validate_unit(
54697c478bd9Sstevel@tonic-gate mdsetname_t *sp,
54707c478bd9Sstevel@tonic-gate mdname_t *compnp,
54717c478bd9Sstevel@tonic-gate mdcmdopts_t options,
54727c478bd9Sstevel@tonic-gate md_error_t *ep
54737c478bd9Sstevel@tonic-gate )
54747c478bd9Sstevel@tonic-gate {
54757c478bd9Sstevel@tonic-gate md_sp_t *msp;
54767c478bd9Sstevel@tonic-gate mdnamelist_t *spnlp = NULL;
54777c478bd9Sstevel@tonic-gate mdnamelist_t *namep = NULL;
54787c478bd9Sstevel@tonic-gate int count;
54797c478bd9Sstevel@tonic-gate uint_t extn;
54807c478bd9Sstevel@tonic-gate sp_ext_length_t size;
54817c478bd9Sstevel@tonic-gate
54827c478bd9Sstevel@tonic-gate if ((options & MDCMD_VERBOSE) != 0)
54837c478bd9Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN,
54847c478bd9Sstevel@tonic-gate "%s: Validating soft partition metadb entries.\n"),
54857c478bd9Sstevel@tonic-gate compnp->cname);
54867c478bd9Sstevel@tonic-gate
54877c478bd9Sstevel@tonic-gate if ((size = metagetsize(compnp, ep)) == MD_DISKADDR_ERROR)
54887c478bd9Sstevel@tonic-gate return (-1);
54897c478bd9Sstevel@tonic-gate
54907c478bd9Sstevel@tonic-gate /* get all soft partitions on component */
54917c478bd9Sstevel@tonic-gate count = meta_sp_get_by_component(sp, compnp, &spnlp, 0, ep);
54927c478bd9Sstevel@tonic-gate
54937c478bd9Sstevel@tonic-gate if (count == 0) {
54947c478bd9Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN,
54957c478bd9Sstevel@tonic-gate "%s: No soft partitions.\n"), compnp->cname);
54967c478bd9Sstevel@tonic-gate return (mdmderror(ep, MDE_RECOVER_FAILED, 0, compnp->cname));
54977c478bd9Sstevel@tonic-gate } else if (count < 0) {
54987c478bd9Sstevel@tonic-gate return (-1);
54997c478bd9Sstevel@tonic-gate }
55007c478bd9Sstevel@tonic-gate
55017c478bd9Sstevel@tonic-gate /* Now go through the soft partitions and check each one */
55027c478bd9Sstevel@tonic-gate for (namep = spnlp; namep != NULL; namep = namep->next) {
55037c478bd9Sstevel@tonic-gate mdname_t *curnp = namep->namep;
55047c478bd9Sstevel@tonic-gate sp_ext_offset_t curvoff;
55057c478bd9Sstevel@tonic-gate
55067c478bd9Sstevel@tonic-gate /* get the unit structure */
55077c478bd9Sstevel@tonic-gate if ((msp = meta_get_sp_common(sp, curnp, 0, ep)) == NULL)
55087c478bd9Sstevel@tonic-gate return (-1);
55097c478bd9Sstevel@tonic-gate
55107c478bd9Sstevel@tonic-gate /* verify generic unit structure parameters */
55117c478bd9Sstevel@tonic-gate if ((options & MDCMD_VERBOSE) != 0)
55127c478bd9Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN,
55137c478bd9Sstevel@tonic-gate "\nVerifying device %s.\n"),
55147c478bd9Sstevel@tonic-gate curnp->cname);
55157c478bd9Sstevel@tonic-gate
55167c478bd9Sstevel@tonic-gate /*
55177c478bd9Sstevel@tonic-gate * MD_SP_LAST is an invalid state and is always the
55187c478bd9Sstevel@tonic-gate * highest numbered.
55197c478bd9Sstevel@tonic-gate */
55207c478bd9Sstevel@tonic-gate if (msp->status >= MD_SP_LAST) {
55217c478bd9Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN,
55227c478bd9Sstevel@tonic-gate "%s: status value %u is out of range.\n"),
55237c478bd9Sstevel@tonic-gate curnp->cname, msp->status);
55247c478bd9Sstevel@tonic-gate return (mdmderror(ep, MDE_RECOVER_FAILED,
55257c478bd9Sstevel@tonic-gate 0, curnp->cname));
55267c478bd9Sstevel@tonic-gate } else if ((options & MDCMD_VERBOSE) != 0) {
55277c478bd9Sstevel@tonic-gate uint_t tstate = 0;
55287c478bd9Sstevel@tonic-gate
55297c478bd9Sstevel@tonic-gate if (metaismeta(msp->compnamep)) {
55307c478bd9Sstevel@tonic-gate if (meta_get_tstate(msp->common.namep->dev,
55317c478bd9Sstevel@tonic-gate &tstate, ep) != 0)
55327c478bd9Sstevel@tonic-gate return (-1);
55337c478bd9Sstevel@tonic-gate }
55347c478bd9Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN,
55357c478bd9Sstevel@tonic-gate "%s: Status \"%s\" is valid.\n"),
55367c478bd9Sstevel@tonic-gate curnp->cname, meta_sp_status_to_name(msp->status,
55377c478bd9Sstevel@tonic-gate tstate & MD_DEV_ERRORED));
55387c478bd9Sstevel@tonic-gate }
55397c478bd9Sstevel@tonic-gate
55407c478bd9Sstevel@tonic-gate /* Now verify each extent */
55417c478bd9Sstevel@tonic-gate if ((options & MDCMD_VERBOSE) != 0)
55427c478bd9Sstevel@tonic-gate (void) printf("%14s %21s %21s %21s\n",
55437c478bd9Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Extent Number"),
55447c478bd9Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Virtual Offset"),
55457c478bd9Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Physical Offset"),
55467c478bd9Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Length"));
55477c478bd9Sstevel@tonic-gate
55487c478bd9Sstevel@tonic-gate curvoff = 0ULL;
55497c478bd9Sstevel@tonic-gate for (extn = 0; extn < msp->ext.ext_len; extn++) {
55507c478bd9Sstevel@tonic-gate md_sp_ext_t *extp = &msp->ext.ext_val[extn];
55517c478bd9Sstevel@tonic-gate
55527c478bd9Sstevel@tonic-gate if ((options & MDCMD_VERBOSE) != 0)
55537c478bd9Sstevel@tonic-gate (void) printf("%14u %21llu %21llu %21llu\n",
55547c478bd9Sstevel@tonic-gate extn, extp->voff, extp->poff, extp->len);
55557c478bd9Sstevel@tonic-gate
55567c478bd9Sstevel@tonic-gate if (extp->voff != curvoff) {
55577c478bd9Sstevel@tonic-gate (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
55587c478bd9Sstevel@tonic-gate "%s: virtual offset for extent %u "
55597c478bd9Sstevel@tonic-gate "is inconsistent, expected %llu, "
55607c478bd9Sstevel@tonic-gate "got %llu.\n"), curnp->cname, extn,
55617c478bd9Sstevel@tonic-gate curvoff, extp->voff);
55627c478bd9Sstevel@tonic-gate return (mdmderror(ep, MDE_RECOVER_FAILED,
55637c478bd9Sstevel@tonic-gate 0, compnp->cname));
55647c478bd9Sstevel@tonic-gate }
55657c478bd9Sstevel@tonic-gate
55667c478bd9Sstevel@tonic-gate /* make sure extent does not drop off the end */
55677c478bd9Sstevel@tonic-gate if ((extp->poff + extp->len) == size) {
55687c478bd9Sstevel@tonic-gate (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
55697c478bd9Sstevel@tonic-gate "%s: extent %u at offset %llu, "
55707c478bd9Sstevel@tonic-gate "length %llu exceeds the size of the "
55717c478bd9Sstevel@tonic-gate "device, %llu.\n"), curnp->cname,
55727c478bd9Sstevel@tonic-gate extn, extp->poff, extp->len, size);
55737c478bd9Sstevel@tonic-gate return (mdmderror(ep, MDE_RECOVER_FAILED,
55747c478bd9Sstevel@tonic-gate 0, compnp->cname));
55757c478bd9Sstevel@tonic-gate }
55767c478bd9Sstevel@tonic-gate
55777c478bd9Sstevel@tonic-gate curvoff += extp->len;
55787c478bd9Sstevel@tonic-gate }
55797c478bd9Sstevel@tonic-gate }
55807c478bd9Sstevel@tonic-gate if (options & MDCMD_PRINT) {
55817c478bd9Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN,
55827c478bd9Sstevel@tonic-gate "%s: Soft Partition metadb configuration is valid\n"),
55837c478bd9Sstevel@tonic-gate compnp->cname);
55847c478bd9Sstevel@tonic-gate }
55857c478bd9Sstevel@tonic-gate return (0);
55867c478bd9Sstevel@tonic-gate }
55877c478bd9Sstevel@tonic-gate
55887c478bd9Sstevel@tonic-gate /*
55897c478bd9Sstevel@tonic-gate * FUNCTION: meta_sp_validate_wm_and_unit()
55907c478bd9Sstevel@tonic-gate * INPUT: sp - name of set we are recovering in
55917c478bd9Sstevel@tonic-gate * compnp - name of device we are recovering from
55927c478bd9Sstevel@tonic-gate * options - metarecover options
55937c478bd9Sstevel@tonic-gate * OUTPUT: ep - error pointer returned
55947c478bd9Sstevel@tonic-gate * RETURNS: int - 0 - success, -1 error
55957c478bd9Sstevel@tonic-gate * PURPOSE: cross-validate and display watermarks and metadb records.
55967c478bd9Sstevel@tonic-gate * get both the unit structures for the soft partitions built
55977c478bd9Sstevel@tonic-gate * on the specified component and the watermarks found on that
55987c478bd9Sstevel@tonic-gate * component and check to make sure they are consistent with
55997c478bd9Sstevel@tonic-gate * each other.
56007c478bd9Sstevel@tonic-gate */
56017c478bd9Sstevel@tonic-gate static int
meta_sp_validate_wm_and_unit(mdsetname_t * sp,mdname_t * np,mdcmdopts_t options,md_error_t * ep)56027c478bd9Sstevel@tonic-gate meta_sp_validate_wm_and_unit(
56037c478bd9Sstevel@tonic-gate mdsetname_t *sp,
56047c478bd9Sstevel@tonic-gate mdname_t *np,
56057c478bd9Sstevel@tonic-gate mdcmdopts_t options,
56067c478bd9Sstevel@tonic-gate md_error_t *ep
56077c478bd9Sstevel@tonic-gate )
56087c478bd9Sstevel@tonic-gate {
56097c478bd9Sstevel@tonic-gate sp_ext_node_t *wmlist = NULL;
56107c478bd9Sstevel@tonic-gate sp_ext_node_t *unitlist = NULL;
56117c478bd9Sstevel@tonic-gate sp_ext_node_t *unitext;
56127c478bd9Sstevel@tonic-gate sp_ext_node_t *wmext;
56137c478bd9Sstevel@tonic-gate sp_ext_offset_t tmpunitoff;
56147c478bd9Sstevel@tonic-gate mdnamelist_t *spnlp = NULL;
56157c478bd9Sstevel@tonic-gate int count;
56167c478bd9Sstevel@tonic-gate int rval = 0;
56177c478bd9Sstevel@tonic-gate int verbose = (options & MDCMD_VERBOSE);
56187c478bd9Sstevel@tonic-gate
56197c478bd9Sstevel@tonic-gate /* get unit structure list */
56207c478bd9Sstevel@tonic-gate count = meta_sp_get_by_component(sp, np, &spnlp, 0, ep);
56217c478bd9Sstevel@tonic-gate if (count <= 0)
56227c478bd9Sstevel@tonic-gate return (-1);
56237c478bd9Sstevel@tonic-gate
56247c478bd9Sstevel@tonic-gate meta_sp_list_insert(NULL, NULL, &unitlist,
56257c478bd9Sstevel@tonic-gate metagetsize(np, ep) - MD_SP_WMSIZE, MD_SP_WMSIZE,
56267c478bd9Sstevel@tonic-gate EXTTYP_END, 0, EXTFLG_UPDATE, meta_sp_cmp_by_offset);
56277c478bd9Sstevel@tonic-gate
56287c478bd9Sstevel@tonic-gate if (meta_sp_extlist_from_namelist(sp, spnlp, &unitlist, ep) == -1) {
56297c478bd9Sstevel@tonic-gate metafreenamelist(spnlp);
56307c478bd9Sstevel@tonic-gate return (-1);
56317c478bd9Sstevel@tonic-gate }
56327c478bd9Sstevel@tonic-gate
56337c478bd9Sstevel@tonic-gate metafreenamelist(spnlp);
56347c478bd9Sstevel@tonic-gate
56357c478bd9Sstevel@tonic-gate meta_sp_list_freefill(&unitlist, metagetsize(np, ep));
56367c478bd9Sstevel@tonic-gate
56377c478bd9Sstevel@tonic-gate if (meta_sp_extlist_from_wm(sp, np, &wmlist,
56387c478bd9Sstevel@tonic-gate meta_sp_cmp_by_offset, ep) < 0) {
56397c478bd9Sstevel@tonic-gate meta_sp_list_free(&unitlist);
56407c478bd9Sstevel@tonic-gate return (-1);
56417c478bd9Sstevel@tonic-gate }
56427c478bd9Sstevel@tonic-gate
56437c478bd9Sstevel@tonic-gate if (getenv(META_SP_DEBUG)) {
56447c478bd9Sstevel@tonic-gate meta_sp_debug("meta_sp_validate_wm_and_unit: unit list:\n");
56457c478bd9Sstevel@tonic-gate meta_sp_list_dump(unitlist);
56467c478bd9Sstevel@tonic-gate meta_sp_debug("meta_sp_validate_wm_and_unit: wm list:\n");
56477c478bd9Sstevel@tonic-gate meta_sp_list_dump(wmlist);
56487c478bd9Sstevel@tonic-gate }
56497c478bd9Sstevel@tonic-gate
56507c478bd9Sstevel@tonic-gate /*
56517c478bd9Sstevel@tonic-gate * step through both lists and compare allocated nodes. Free
56527c478bd9Sstevel@tonic-gate * nodes and end watermarks may differ between the two but
56537c478bd9Sstevel@tonic-gate * that's generally ok, and if they're wrong will typically
56547c478bd9Sstevel@tonic-gate * cause misplaced allocated extents.
56557c478bd9Sstevel@tonic-gate */
56567c478bd9Sstevel@tonic-gate if (verbose)
56577c478bd9Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN, "\n%s: Verifying metadb "
56587c478bd9Sstevel@tonic-gate "allocations match extent headers.\n"), np->cname);
56597c478bd9Sstevel@tonic-gate
56607c478bd9Sstevel@tonic-gate unitext = unitlist;
56617c478bd9Sstevel@tonic-gate wmext = wmlist;
56627c478bd9Sstevel@tonic-gate while ((wmext != NULL) && (unitext != NULL)) {
56637c478bd9Sstevel@tonic-gate /* find next allocated extents in each list */
56647c478bd9Sstevel@tonic-gate while (wmext != NULL && wmext->ext_type != EXTTYP_ALLOC)
56657c478bd9Sstevel@tonic-gate wmext = wmext->ext_next;
56667c478bd9Sstevel@tonic-gate
56677c478bd9Sstevel@tonic-gate while (unitext != NULL && unitext->ext_type != EXTTYP_ALLOC)
56687c478bd9Sstevel@tonic-gate unitext = unitext->ext_next;
56697c478bd9Sstevel@tonic-gate
56707c478bd9Sstevel@tonic-gate if (wmext == NULL || unitext == NULL)
56717c478bd9Sstevel@tonic-gate break;
56727c478bd9Sstevel@tonic-gate
56737c478bd9Sstevel@tonic-gate if (verbose) {
56747c478bd9Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN,
56757c478bd9Sstevel@tonic-gate "Metadb extent:\n"));
56767c478bd9Sstevel@tonic-gate meta_sp_display_exthdr();
56777c478bd9Sstevel@tonic-gate meta_sp_display_ext(unitext);
56787c478bd9Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN,
56797c478bd9Sstevel@tonic-gate "Extent header extent:\n"));
56807c478bd9Sstevel@tonic-gate meta_sp_display_exthdr();
56817c478bd9Sstevel@tonic-gate meta_sp_display_ext(wmext);
56827c478bd9Sstevel@tonic-gate (void) printf("\n");
56837c478bd9Sstevel@tonic-gate }
56847c478bd9Sstevel@tonic-gate
56857c478bd9Sstevel@tonic-gate if (meta_sp_validate_exts(np, wmext, unitext, ep) < 0)
56867c478bd9Sstevel@tonic-gate rval = -1;
56877c478bd9Sstevel@tonic-gate
56887c478bd9Sstevel@tonic-gate /*
56897c478bd9Sstevel@tonic-gate * if the offsets aren't equal, only increment the
56907c478bd9Sstevel@tonic-gate * lowest one in hopes of getting the lists back in sync.
56917c478bd9Sstevel@tonic-gate */
56927c478bd9Sstevel@tonic-gate tmpunitoff = unitext->ext_offset;
56937c478bd9Sstevel@tonic-gate if (unitext->ext_offset <= wmext->ext_offset)
56947c478bd9Sstevel@tonic-gate unitext = unitext->ext_next;
56957c478bd9Sstevel@tonic-gate if (wmext->ext_offset <= tmpunitoff)
56967c478bd9Sstevel@tonic-gate wmext = wmext->ext_next;
56977c478bd9Sstevel@tonic-gate }
56987c478bd9Sstevel@tonic-gate
56997c478bd9Sstevel@tonic-gate /*
57007c478bd9Sstevel@tonic-gate * if both lists aren't at the end then there are extra
57017c478bd9Sstevel@tonic-gate * allocated nodes in one of them.
57027c478bd9Sstevel@tonic-gate */
57037c478bd9Sstevel@tonic-gate if (wmext != NULL) {
57047c478bd9Sstevel@tonic-gate (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
57057c478bd9Sstevel@tonic-gate "%s: extent headers contain allocations not in "
57067c478bd9Sstevel@tonic-gate "the metadb\n\n"), np->cname);
57077c478bd9Sstevel@tonic-gate rval = -1;
57087c478bd9Sstevel@tonic-gate }
57097c478bd9Sstevel@tonic-gate
57107c478bd9Sstevel@tonic-gate if (unitext != NULL) {
57117c478bd9Sstevel@tonic-gate (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
57127c478bd9Sstevel@tonic-gate "%s: metadb contains allocations not in the extent "
57137c478bd9Sstevel@tonic-gate "headers\n\n"), np->cname);
57147c478bd9Sstevel@tonic-gate rval = -1;
57157c478bd9Sstevel@tonic-gate }
57167c478bd9Sstevel@tonic-gate
57177c478bd9Sstevel@tonic-gate if (options & MDCMD_PRINT) {
57187c478bd9Sstevel@tonic-gate if (rval == 0) {
57197c478bd9Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN,
57207c478bd9Sstevel@tonic-gate "%s: Soft Partition metadb matches extent "
57217c478bd9Sstevel@tonic-gate "header configuration\n"), np->cname);
57227c478bd9Sstevel@tonic-gate } else {
57237c478bd9Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN,
57247c478bd9Sstevel@tonic-gate "%s: Soft Partition metadb does not match extent "
57257c478bd9Sstevel@tonic-gate "header configuration\n"), np->cname);
57267c478bd9Sstevel@tonic-gate }
57277c478bd9Sstevel@tonic-gate }
57287c478bd9Sstevel@tonic-gate
57297c478bd9Sstevel@tonic-gate return (rval);
57307c478bd9Sstevel@tonic-gate }
57317c478bd9Sstevel@tonic-gate
57327c478bd9Sstevel@tonic-gate /*
57337c478bd9Sstevel@tonic-gate * FUNCTION: meta_sp_validate_exts()
57347c478bd9Sstevel@tonic-gate * INPUT: compnp - name pointer for device we are recovering from
57357c478bd9Sstevel@tonic-gate * wmext - extent node representing watermark
57367c478bd9Sstevel@tonic-gate * unitext - extent node from unit structure
57377c478bd9Sstevel@tonic-gate * OUTPUT: ep - return error pointer
57387c478bd9Sstevel@tonic-gate * RETURNS: int - 0 - succes, mdmderror return code - error
57397c478bd9Sstevel@tonic-gate * PURPOSE: Takes two extent nodes and checks them against each other.
57407c478bd9Sstevel@tonic-gate * offset, length, sequence number, set, and name are compared.
57417c478bd9Sstevel@tonic-gate */
57427c478bd9Sstevel@tonic-gate static int
meta_sp_validate_exts(mdname_t * compnp,sp_ext_node_t * wmext,sp_ext_node_t * unitext,md_error_t * ep)57437c478bd9Sstevel@tonic-gate meta_sp_validate_exts(
57447c478bd9Sstevel@tonic-gate mdname_t *compnp,
57457c478bd9Sstevel@tonic-gate sp_ext_node_t *wmext,
57467c478bd9Sstevel@tonic-gate sp_ext_node_t *unitext,
57477c478bd9Sstevel@tonic-gate md_error_t *ep
57487c478bd9Sstevel@tonic-gate )
57497c478bd9Sstevel@tonic-gate {
57507c478bd9Sstevel@tonic-gate if (wmext->ext_offset != unitext->ext_offset) {
57517c478bd9Sstevel@tonic-gate (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
57527c478bd9Sstevel@tonic-gate "%s: unit structure and extent header offsets differ.\n"),
57537c478bd9Sstevel@tonic-gate compnp->cname);
57547c478bd9Sstevel@tonic-gate return (mdmderror(ep, MDE_RECOVER_FAILED, 0, compnp->cname));
57557c478bd9Sstevel@tonic-gate }
57567c478bd9Sstevel@tonic-gate
57577c478bd9Sstevel@tonic-gate if (wmext->ext_length != unitext->ext_length) {
57587c478bd9Sstevel@tonic-gate (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
57597c478bd9Sstevel@tonic-gate "%s: unit structure and extent header lengths differ.\n"),
57607c478bd9Sstevel@tonic-gate compnp->cname);
57617c478bd9Sstevel@tonic-gate return (mdmderror(ep, MDE_RECOVER_FAILED, 0, compnp->cname));
57627c478bd9Sstevel@tonic-gate }
57637c478bd9Sstevel@tonic-gate
57647c478bd9Sstevel@tonic-gate if (wmext->ext_seq != unitext->ext_seq) {
57657c478bd9Sstevel@tonic-gate (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
57667c478bd9Sstevel@tonic-gate "%s: unit structure and extent header sequence numbers "
57677c478bd9Sstevel@tonic-gate "differ.\n"), compnp->cname);
57687c478bd9Sstevel@tonic-gate return (mdmderror(ep, MDE_RECOVER_FAILED, 0, compnp->cname));
57697c478bd9Sstevel@tonic-gate }
57707c478bd9Sstevel@tonic-gate
57717c478bd9Sstevel@tonic-gate if (wmext->ext_type != unitext->ext_type) {
57727c478bd9Sstevel@tonic-gate (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
57737c478bd9Sstevel@tonic-gate "%s: unit structure and extent header types differ.\n"),
57747c478bd9Sstevel@tonic-gate compnp->cname);
57757c478bd9Sstevel@tonic-gate return (mdmderror(ep, MDE_RECOVER_FAILED, 0, compnp->cname));
57767c478bd9Sstevel@tonic-gate }
57777c478bd9Sstevel@tonic-gate
57787c478bd9Sstevel@tonic-gate /*
57797c478bd9Sstevel@tonic-gate * If one has a set pointer and the other doesn't, error.
57807c478bd9Sstevel@tonic-gate * If both extents have setnames, then make sure they match
57817c478bd9Sstevel@tonic-gate * If both are NULL, it's ok, they match.
57827c478bd9Sstevel@tonic-gate */
57837c478bd9Sstevel@tonic-gate if ((unitext->ext_setp == NULL) ^ (wmext->ext_setp == NULL)) {
57847c478bd9Sstevel@tonic-gate (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
57857c478bd9Sstevel@tonic-gate "%s: unit structure and extent header set values "
57867c478bd9Sstevel@tonic-gate "differ.\n"), compnp->cname);
57877c478bd9Sstevel@tonic-gate return (mdmderror(ep, MDE_RECOVER_FAILED, 0, compnp->cname));
57887c478bd9Sstevel@tonic-gate }
57897c478bd9Sstevel@tonic-gate
57907c478bd9Sstevel@tonic-gate if (unitext->ext_setp != NULL) {
57917c478bd9Sstevel@tonic-gate if (strcmp(unitext->ext_setp->setname,
57927c478bd9Sstevel@tonic-gate wmext->ext_setp->setname) != 0) {
57937c478bd9Sstevel@tonic-gate (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
57947c478bd9Sstevel@tonic-gate "%s: unit structure and extent header set names "
57957c478bd9Sstevel@tonic-gate "differ.\n"), compnp->cname);
57967c478bd9Sstevel@tonic-gate return (mdmderror(ep, MDE_RECOVER_FAILED,
57977c478bd9Sstevel@tonic-gate 0, compnp->cname));
57987c478bd9Sstevel@tonic-gate }
57997c478bd9Sstevel@tonic-gate }
58007c478bd9Sstevel@tonic-gate
58017c478bd9Sstevel@tonic-gate /*
58027c478bd9Sstevel@tonic-gate * If one has a name pointer and the other doesn't, error.
58037c478bd9Sstevel@tonic-gate * If both extents have names, then make sure they match
58047c478bd9Sstevel@tonic-gate * If both are NULL, it's ok, they match.
58057c478bd9Sstevel@tonic-gate */
58067c478bd9Sstevel@tonic-gate if ((unitext->ext_namep == NULL) ^ (wmext->ext_namep == NULL)) {
58077c478bd9Sstevel@tonic-gate (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
58087c478bd9Sstevel@tonic-gate "%s: unit structure and extent header name values "
58097c478bd9Sstevel@tonic-gate "differ.\n"), compnp->cname);
58107c478bd9Sstevel@tonic-gate return (mdmderror(ep, MDE_RECOVER_FAILED, 0, compnp->cname));
58117c478bd9Sstevel@tonic-gate }
58127c478bd9Sstevel@tonic-gate
58137c478bd9Sstevel@tonic-gate if (unitext->ext_namep != NULL) {
58147c478bd9Sstevel@tonic-gate if (strcmp(wmext->ext_namep->cname,
58157c478bd9Sstevel@tonic-gate unitext->ext_namep->cname) != 0) {
58167c478bd9Sstevel@tonic-gate (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
58177c478bd9Sstevel@tonic-gate "%s: unit structure and extent header names "
58187c478bd9Sstevel@tonic-gate "differ.\n"), compnp->cname);
58197c478bd9Sstevel@tonic-gate return (mdmderror(ep, MDE_RECOVER_FAILED,
58207c478bd9Sstevel@tonic-gate 0, compnp->cname));
58217c478bd9Sstevel@tonic-gate }
58227c478bd9Sstevel@tonic-gate }
58237c478bd9Sstevel@tonic-gate
58247c478bd9Sstevel@tonic-gate return (0);
58257c478bd9Sstevel@tonic-gate }
58267c478bd9Sstevel@tonic-gate
58277c478bd9Sstevel@tonic-gate /*
58287c478bd9Sstevel@tonic-gate * FUNCTION: update_sp_status()
58297c478bd9Sstevel@tonic-gate * INPUT: sp - name of set we are recovering in
58307c478bd9Sstevel@tonic-gate * minors - pointer to an array of soft partition minor numbers
58317c478bd9Sstevel@tonic-gate * num_sps - number of minor numbers in array
58327c478bd9Sstevel@tonic-gate * status - new status to be applied to all soft parts in array
58337c478bd9Sstevel@tonic-gate * mn_set - set if current set is a multi-node set
58347c478bd9Sstevel@tonic-gate * OUTPUT: ep - return error pointer
58357c478bd9Sstevel@tonic-gate * RETURNS: int - 0 - success, -1 - error
58367c478bd9Sstevel@tonic-gate * PURPOSE: update status of soft partitions to new status. minors is an
58377c478bd9Sstevel@tonic-gate * array of minor numbers to apply the new status to.
58387c478bd9Sstevel@tonic-gate * If mn_set is set, a message is sent to all nodes in the
58397c478bd9Sstevel@tonic-gate * cluster to update the status locally.
58407c478bd9Sstevel@tonic-gate */
58417c478bd9Sstevel@tonic-gate static int
update_sp_status(mdsetname_t * sp,minor_t * minors,int num_sps,sp_status_t status,bool_t mn_set,md_error_t * ep)58427c478bd9Sstevel@tonic-gate update_sp_status(
58437c478bd9Sstevel@tonic-gate mdsetname_t *sp,
58447c478bd9Sstevel@tonic-gate minor_t *minors,
58457c478bd9Sstevel@tonic-gate int num_sps,
58467c478bd9Sstevel@tonic-gate sp_status_t status,
58477c478bd9Sstevel@tonic-gate bool_t mn_set,
58487c478bd9Sstevel@tonic-gate md_error_t *ep
58497c478bd9Sstevel@tonic-gate )
58507c478bd9Sstevel@tonic-gate {
58517c478bd9Sstevel@tonic-gate int i;
58527c478bd9Sstevel@tonic-gate int err = 0;
58537c478bd9Sstevel@tonic-gate
58547c478bd9Sstevel@tonic-gate if (mn_set) {
58557c478bd9Sstevel@tonic-gate md_mn_msg_sp_setstat_t sp_setstat_params;
58567c478bd9Sstevel@tonic-gate int result;
58577c478bd9Sstevel@tonic-gate md_mn_result_t *resp = NULL;
58587c478bd9Sstevel@tonic-gate
58597c478bd9Sstevel@tonic-gate for (i = 0; i < num_sps; i++) {
58607c478bd9Sstevel@tonic-gate sp_setstat_params.sp_setstat_mnum = minors[i];
58617c478bd9Sstevel@tonic-gate sp_setstat_params.sp_setstat_status = status;
58627c478bd9Sstevel@tonic-gate
58637c478bd9Sstevel@tonic-gate result = mdmn_send_message(sp->setno,
5864bf85a12bSJohn Wren Kennedy MD_MN_MSG_SP_SETSTAT, MD_MSGF_DEFAULT_FLAGS, 0,
58657c478bd9Sstevel@tonic-gate (char *)&sp_setstat_params,
58667c478bd9Sstevel@tonic-gate sizeof (sp_setstat_params),
58677c478bd9Sstevel@tonic-gate &resp, ep);
58687c478bd9Sstevel@tonic-gate if (resp != NULL) {
58697c478bd9Sstevel@tonic-gate if (resp->mmr_exitval != 0)
58707c478bd9Sstevel@tonic-gate err = -1;
58717c478bd9Sstevel@tonic-gate free_result(resp);
58727c478bd9Sstevel@tonic-gate }
58737c478bd9Sstevel@tonic-gate if (result != 0) {
58747c478bd9Sstevel@tonic-gate err = -1;
58757c478bd9Sstevel@tonic-gate }
58767c478bd9Sstevel@tonic-gate }
58777c478bd9Sstevel@tonic-gate } else {
58787c478bd9Sstevel@tonic-gate if (meta_sp_setstatus(sp, minors, num_sps, status, ep) < 0)
58797c478bd9Sstevel@tonic-gate err = -1;
58807c478bd9Sstevel@tonic-gate }
58817c478bd9Sstevel@tonic-gate if (err < 0) {
58827c478bd9Sstevel@tonic-gate (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
58837c478bd9Sstevel@tonic-gate "Error updating status on recovered soft "
58847c478bd9Sstevel@tonic-gate "partitions.\n"));
58857c478bd9Sstevel@tonic-gate }
58867c478bd9Sstevel@tonic-gate return (err);
58877c478bd9Sstevel@tonic-gate }
58887c478bd9Sstevel@tonic-gate
58897c478bd9Sstevel@tonic-gate /*
58907c478bd9Sstevel@tonic-gate * FUNCTION: meta_sp_recover_from_wm()
58917c478bd9Sstevel@tonic-gate * INPUT: sp - name of set we are recovering in
58927c478bd9Sstevel@tonic-gate * compnp - name pointer for component we are recovering from
58937c478bd9Sstevel@tonic-gate * options - metarecover options
58947c478bd9Sstevel@tonic-gate * OUTPUT: ep - return error pointer
58957c478bd9Sstevel@tonic-gate * RETURNS: int - 0 - success, -1 - error
58967c478bd9Sstevel@tonic-gate * PURPOSE: update metadb records to match watermarks. begin by getting
58977c478bd9Sstevel@tonic-gate * an extlist representing all soft partitions on the component.
58987c478bd9Sstevel@tonic-gate * then build a unit structure for each soft partition.
58997c478bd9Sstevel@tonic-gate * notify user of changes, then commit each soft partition to
59007c478bd9Sstevel@tonic-gate * the metadb one at a time in the "recovering" state. update
59017c478bd9Sstevel@tonic-gate * any watermarks that may need it (to reflect possible name
59027c478bd9Sstevel@tonic-gate * changes), and, finally, set the status of all recovered
59037c478bd9Sstevel@tonic-gate * partitions to the "OK" state at once.
59047c478bd9Sstevel@tonic-gate */
59057c478bd9Sstevel@tonic-gate static int
meta_sp_recover_from_wm(mdsetname_t * sp,mdname_t * compnp,mdcmdopts_t options,md_error_t * ep)59067c478bd9Sstevel@tonic-gate meta_sp_recover_from_wm(
59077c478bd9Sstevel@tonic-gate mdsetname_t *sp,
59087c478bd9Sstevel@tonic-gate mdname_t *compnp,
59097c478bd9Sstevel@tonic-gate mdcmdopts_t options,
59107c478bd9Sstevel@tonic-gate md_error_t *ep
59117c478bd9Sstevel@tonic-gate )
59127c478bd9Sstevel@tonic-gate {
59137c478bd9Sstevel@tonic-gate sp_ext_node_t *extlist = NULL;
59147c478bd9Sstevel@tonic-gate sp_ext_node_t *sp_list = NULL;
59157c478bd9Sstevel@tonic-gate sp_ext_node_t *update_list = NULL;
59167c478bd9Sstevel@tonic-gate sp_ext_node_t *ext;
59177c478bd9Sstevel@tonic-gate sp_ext_node_t *sp_ext;
59187c478bd9Sstevel@tonic-gate mp_unit_t *mp;
59197c478bd9Sstevel@tonic-gate mp_unit_t **un_array;
59207c478bd9Sstevel@tonic-gate int numexts = 0, num_sps = 0, i = 0;
59217c478bd9Sstevel@tonic-gate int err = 0;
59227c478bd9Sstevel@tonic-gate int not_recovered = 0;
59237c478bd9Sstevel@tonic-gate int committed = 0;
59247c478bd9Sstevel@tonic-gate sp_ext_length_t sp_length = 0LL;
59257c478bd9Sstevel@tonic-gate mdnamelist_t *keynlp = NULL;
59267c478bd9Sstevel@tonic-gate mdname_t *np;
59277c478bd9Sstevel@tonic-gate mdname_t *new_np;
59287c478bd9Sstevel@tonic-gate int new_name;
59297c478bd9Sstevel@tonic-gate md_set_params_t set_params;
59307c478bd9Sstevel@tonic-gate minor_t *minors = NULL;
59317c478bd9Sstevel@tonic-gate char yesno[255];
59327c478bd9Sstevel@tonic-gate char *yes;
59337c478bd9Sstevel@tonic-gate bool_t mn_set = 0;
59347c478bd9Sstevel@tonic-gate md_set_desc *sd;
59357c478bd9Sstevel@tonic-gate mm_unit_t *mm;
59367c478bd9Sstevel@tonic-gate md_set_mmown_params_t *ownpar = NULL;
59377c478bd9Sstevel@tonic-gate int comp_is_mirror = 0;
59387c478bd9Sstevel@tonic-gate
59397c478bd9Sstevel@tonic-gate /*
59407c478bd9Sstevel@tonic-gate * if this component appears in another metadevice already, do
59417c478bd9Sstevel@tonic-gate * NOT recover from it.
59427c478bd9Sstevel@tonic-gate */
59437c478bd9Sstevel@tonic-gate if (meta_check_inmeta(sp, compnp, options, 0, -1, ep) != 0)
59447c478bd9Sstevel@tonic-gate return (-1);
59457c478bd9Sstevel@tonic-gate
59467c478bd9Sstevel@tonic-gate /* set flag if dealing with a MN set */
59477c478bd9Sstevel@tonic-gate if (!metaislocalset(sp)) {
59487c478bd9Sstevel@tonic-gate if ((sd = metaget_setdesc(sp, ep)) == NULL) {
59497c478bd9Sstevel@tonic-gate return (-1);
59507c478bd9Sstevel@tonic-gate }
59517c478bd9Sstevel@tonic-gate if (MD_MNSET_DESC(sd))
59527c478bd9Sstevel@tonic-gate mn_set = 1;
59537c478bd9Sstevel@tonic-gate }
59547c478bd9Sstevel@tonic-gate /*
59557c478bd9Sstevel@tonic-gate * for each watermark, build an ext_node, place on list.
59567c478bd9Sstevel@tonic-gate */
59577c478bd9Sstevel@tonic-gate if (meta_sp_extlist_from_wm(sp, compnp, &extlist,
59587c478bd9Sstevel@tonic-gate meta_sp_cmp_by_nameseq, ep) < 0)
59597c478bd9Sstevel@tonic-gate return (mdmderror(ep, MDE_RECOVER_FAILED, 0, compnp->cname));
59607c478bd9Sstevel@tonic-gate
59617c478bd9Sstevel@tonic-gate assert(extlist != NULL);
59627c478bd9Sstevel@tonic-gate
59637c478bd9Sstevel@tonic-gate /* count number of soft partitions */
59647c478bd9Sstevel@tonic-gate for (ext = extlist;
59657c478bd9Sstevel@tonic-gate ext != NULL && ext->ext_type == EXTTYP_ALLOC;
59667c478bd9Sstevel@tonic-gate ext = ext->ext_next) {
59677c478bd9Sstevel@tonic-gate if (ext->ext_next != NULL &&
59687c478bd9Sstevel@tonic-gate ext->ext_next->ext_namep != NULL &&
59697c478bd9Sstevel@tonic-gate strcmp(ext->ext_next->ext_namep->cname,
59707c478bd9Sstevel@tonic-gate ext->ext_namep->cname) == 0)
59717c478bd9Sstevel@tonic-gate continue;
59727c478bd9Sstevel@tonic-gate num_sps++;
59737c478bd9Sstevel@tonic-gate }
59747c478bd9Sstevel@tonic-gate
59757c478bd9Sstevel@tonic-gate /* allocate array of unit structure pointers */
59767c478bd9Sstevel@tonic-gate un_array = Zalloc(num_sps * sizeof (mp_unit_t *));
59777c478bd9Sstevel@tonic-gate
59787c478bd9Sstevel@tonic-gate /*
59797c478bd9Sstevel@tonic-gate * build unit structures from list of ext_nodes.
59807c478bd9Sstevel@tonic-gate */
59817c478bd9Sstevel@tonic-gate for (ext = extlist;
59827c478bd9Sstevel@tonic-gate ext != NULL && ext->ext_type == EXTTYP_ALLOC;
59837c478bd9Sstevel@tonic-gate ext = ext->ext_next) {
59847c478bd9Sstevel@tonic-gate meta_sp_list_insert(ext->ext_setp, ext->ext_namep,
59857c478bd9Sstevel@tonic-gate &sp_list, ext->ext_offset, ext->ext_length,
59867c478bd9Sstevel@tonic-gate ext->ext_type, ext->ext_seq, ext->ext_flags,
59877c478bd9Sstevel@tonic-gate meta_sp_cmp_by_nameseq);
59887c478bd9Sstevel@tonic-gate
59897c478bd9Sstevel@tonic-gate numexts++;
59907c478bd9Sstevel@tonic-gate sp_length += ext->ext_length - MD_SP_WMSIZE;
59917c478bd9Sstevel@tonic-gate
59927c478bd9Sstevel@tonic-gate if (ext->ext_next != NULL &&
59937c478bd9Sstevel@tonic-gate ext->ext_next->ext_namep != NULL &&
59947c478bd9Sstevel@tonic-gate strcmp(ext->ext_next->ext_namep->cname,
59957c478bd9Sstevel@tonic-gate ext->ext_namep->cname) == 0)
59967c478bd9Sstevel@tonic-gate continue;
59977c478bd9Sstevel@tonic-gate
59987c478bd9Sstevel@tonic-gate /*
59997c478bd9Sstevel@tonic-gate * if we made it here, we are at a soft partition
60007c478bd9Sstevel@tonic-gate * boundary in the list.
60017c478bd9Sstevel@tonic-gate */
60027c478bd9Sstevel@tonic-gate if (getenv(META_SP_DEBUG)) {
60037c478bd9Sstevel@tonic-gate meta_sp_debug("meta_recover_from_wm: dumping wm "
60047c478bd9Sstevel@tonic-gate "list:\n");
60057c478bd9Sstevel@tonic-gate meta_sp_list_dump(sp_list);
60067c478bd9Sstevel@tonic-gate }
60077c478bd9Sstevel@tonic-gate
60087c478bd9Sstevel@tonic-gate assert(sp_list != NULL);
60097c478bd9Sstevel@tonic-gate assert(sp_list->ext_namep != NULL);
60107c478bd9Sstevel@tonic-gate
60117c478bd9Sstevel@tonic-gate if ((new_name = meta_sp_resolve_name_conflict(sp,
60127c478bd9Sstevel@tonic-gate sp_list->ext_namep, &new_np, ep)) < 0) {
60137c478bd9Sstevel@tonic-gate err = 1;
60147c478bd9Sstevel@tonic-gate goto out;
60157c478bd9Sstevel@tonic-gate } else if (new_name) {
60167c478bd9Sstevel@tonic-gate for (sp_ext = sp_list;
60177c478bd9Sstevel@tonic-gate sp_ext != NULL;
60187c478bd9Sstevel@tonic-gate sp_ext = sp_ext->ext_next) {
60197c478bd9Sstevel@tonic-gate /*
60207c478bd9Sstevel@tonic-gate * insert into the update list for
60217c478bd9Sstevel@tonic-gate * watermark update.
60227c478bd9Sstevel@tonic-gate */
60237c478bd9Sstevel@tonic-gate meta_sp_list_insert(sp_ext->ext_setp,
60247c478bd9Sstevel@tonic-gate new_np, &update_list, sp_ext->ext_offset,
60257c478bd9Sstevel@tonic-gate sp_ext->ext_length, sp_ext->ext_type,
60267c478bd9Sstevel@tonic-gate sp_ext->ext_seq, EXTFLG_UPDATE,
60277c478bd9Sstevel@tonic-gate meta_sp_cmp_by_offset);
60287c478bd9Sstevel@tonic-gate }
60297c478bd9Sstevel@tonic-gate
60307c478bd9Sstevel@tonic-gate }
60317c478bd9Sstevel@tonic-gate if (options & MDCMD_DOIT) {
60327c478bd9Sstevel@tonic-gate /* store name in namespace */
60337c478bd9Sstevel@tonic-gate if (mn_set) {
60347c478bd9Sstevel@tonic-gate /* send message to all nodes to return key */
60357c478bd9Sstevel@tonic-gate md_mn_msg_addkeyname_t *send_params;
60367c478bd9Sstevel@tonic-gate int result;
60377c478bd9Sstevel@tonic-gate md_mn_result_t *resp = NULL;
60387c478bd9Sstevel@tonic-gate int message_size;
60397c478bd9Sstevel@tonic-gate
60407c478bd9Sstevel@tonic-gate message_size = sizeof (*send_params) +
60417c478bd9Sstevel@tonic-gate strlen(compnp->cname) + 1;
60427c478bd9Sstevel@tonic-gate send_params = Zalloc(message_size);
60437c478bd9Sstevel@tonic-gate send_params->addkeyname_setno = sp->setno;
60447c478bd9Sstevel@tonic-gate (void) strcpy(&send_params->addkeyname_name[0],
60457c478bd9Sstevel@tonic-gate compnp->cname);
60467c478bd9Sstevel@tonic-gate result = mdmn_send_message(sp->setno,
60477c478bd9Sstevel@tonic-gate MD_MN_MSG_ADDKEYNAME, MD_MSGF_DEFAULT_FLAGS,
6048bf85a12bSJohn Wren Kennedy 0, (char *)send_params, message_size, &resp,
60497c478bd9Sstevel@tonic-gate ep);
60507c478bd9Sstevel@tonic-gate Free(send_params);
60517c478bd9Sstevel@tonic-gate if (resp != NULL) {
60527c478bd9Sstevel@tonic-gate if (resp->mmr_exitval >= 0) {
60537c478bd9Sstevel@tonic-gate compnp->key =
60547c478bd9Sstevel@tonic-gate (mdkey_t)resp->mmr_exitval;
60557c478bd9Sstevel@tonic-gate } else {
60567c478bd9Sstevel@tonic-gate err = 1;
60577c478bd9Sstevel@tonic-gate free_result(resp);
60587c478bd9Sstevel@tonic-gate goto out;
60597c478bd9Sstevel@tonic-gate }
60607c478bd9Sstevel@tonic-gate free_result(resp);
60617c478bd9Sstevel@tonic-gate }
60627c478bd9Sstevel@tonic-gate if (result != 0) {
60637c478bd9Sstevel@tonic-gate err = 1;
60647c478bd9Sstevel@tonic-gate goto out;
60657c478bd9Sstevel@tonic-gate }
60667c478bd9Sstevel@tonic-gate (void) metanamelist_append(&keynlp, compnp);
60677c478bd9Sstevel@tonic-gate } else {
60687c478bd9Sstevel@tonic-gate if (add_key_name(sp, compnp, &keynlp,
60697c478bd9Sstevel@tonic-gate ep) != 0) {
60707c478bd9Sstevel@tonic-gate err = 1;
60717c478bd9Sstevel@tonic-gate goto out;
60727c478bd9Sstevel@tonic-gate }
60737c478bd9Sstevel@tonic-gate }
60747c478bd9Sstevel@tonic-gate }
60757c478bd9Sstevel@tonic-gate
60767c478bd9Sstevel@tonic-gate /* create the unit structure */
60777c478bd9Sstevel@tonic-gate if ((mp = meta_sp_createunit(
60787c478bd9Sstevel@tonic-gate (new_name) ? new_np : sp_list->ext_namep, compnp,
60797c478bd9Sstevel@tonic-gate sp_list, numexts, sp_length, MD_SP_RECOVER, ep)) == NULL) {
60807c478bd9Sstevel@tonic-gate err = 1;
60817c478bd9Sstevel@tonic-gate goto out;
60827c478bd9Sstevel@tonic-gate }
60837c478bd9Sstevel@tonic-gate
60847c478bd9Sstevel@tonic-gate if (getenv(META_SP_DEBUG)) {
60857c478bd9Sstevel@tonic-gate meta_sp_debug("meta_sp_recover_from_wm: "
60867c478bd9Sstevel@tonic-gate "printing newly created unit structure");
60877c478bd9Sstevel@tonic-gate meta_sp_printunit(mp);
60887c478bd9Sstevel@tonic-gate }
60897c478bd9Sstevel@tonic-gate
60907c478bd9Sstevel@tonic-gate /* place in unit structure array */
60917c478bd9Sstevel@tonic-gate un_array[i++] = mp;
60927c478bd9Sstevel@tonic-gate
60937c478bd9Sstevel@tonic-gate /* free sp_list */
60947c478bd9Sstevel@tonic-gate meta_sp_list_free(&sp_list);
60957c478bd9Sstevel@tonic-gate sp_list = NULL;
60967c478bd9Sstevel@tonic-gate numexts = 0;
60977c478bd9Sstevel@tonic-gate sp_length = 0LL;
60987c478bd9Sstevel@tonic-gate }
60997c478bd9Sstevel@tonic-gate
61007c478bd9Sstevel@tonic-gate /* display configuration updates */
61017c478bd9Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN,
61027c478bd9Sstevel@tonic-gate "The following soft partitions were found and will be added to\n"
61037c478bd9Sstevel@tonic-gate "your metadevice configuration.\n"));
61047c478bd9Sstevel@tonic-gate (void) printf("%5s %15s %18s\n",
61057c478bd9Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Name"),
61067c478bd9Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "Size"),
61077c478bd9Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "No. of Extents"));
61087c478bd9Sstevel@tonic-gate for (i = 0; i < num_sps; i++) {
61097c478bd9Sstevel@tonic-gate (void) printf("%5s%lu %15llu %9d\n", "d",
61107c478bd9Sstevel@tonic-gate MD_MIN2UNIT(MD_SID(un_array[i])),
61117c478bd9Sstevel@tonic-gate un_array[i]->un_length, un_array[i]->un_numexts);
61127c478bd9Sstevel@tonic-gate }
61137c478bd9Sstevel@tonic-gate
61147c478bd9Sstevel@tonic-gate if (!(options & MDCMD_DOIT)) {
61157c478bd9Sstevel@tonic-gate not_recovered = 1;
61167c478bd9Sstevel@tonic-gate goto out;
61177c478bd9Sstevel@tonic-gate }
61187c478bd9Sstevel@tonic-gate
61197c478bd9Sstevel@tonic-gate /* ask user for confirmation */
61207c478bd9Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN,
61217c478bd9Sstevel@tonic-gate "WARNING: You are about to add one or more soft partition\n"
61227c478bd9Sstevel@tonic-gate "metadevices to your metadevice configuration. If there\n"
61237c478bd9Sstevel@tonic-gate "appears to be an error in the soft partition(s) displayed\n"
61247c478bd9Sstevel@tonic-gate "above, do NOT proceed with this recovery operation.\n"));
61257c478bd9Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN,
61267c478bd9Sstevel@tonic-gate "Are you sure you want to do this (yes/no)? "));
61277c478bd9Sstevel@tonic-gate
61287c478bd9Sstevel@tonic-gate (void) fflush(stdout);
61297c478bd9Sstevel@tonic-gate if ((fgets(yesno, sizeof (yesno), stdin) == NULL) ||
61307c478bd9Sstevel@tonic-gate (strlen(yesno) == 1))
61317c478bd9Sstevel@tonic-gate (void) snprintf(yesno, sizeof (yesno), "%s\n",
61327c478bd9Sstevel@tonic-gate dgettext(TEXT_DOMAIN, "no"));
61337c478bd9Sstevel@tonic-gate yes = dgettext(TEXT_DOMAIN, "yes");
61347c478bd9Sstevel@tonic-gate if (strncasecmp(yesno, yes, strlen(yesno) - 1) != 0) {
61357c478bd9Sstevel@tonic-gate not_recovered = 1;
61367c478bd9Sstevel@tonic-gate goto out;
61377c478bd9Sstevel@tonic-gate }
61387c478bd9Sstevel@tonic-gate
61397c478bd9Sstevel@tonic-gate /* commit records one at a time */
61407c478bd9Sstevel@tonic-gate for (i = 0; i < num_sps; i++) {
61417c478bd9Sstevel@tonic-gate (void) memset(&set_params, 0, sizeof (set_params));
61427c478bd9Sstevel@tonic-gate set_params.mnum = MD_SID(un_array[i]);
61437c478bd9Sstevel@tonic-gate set_params.size = (un_array[i])->c.un_size;
61447c478bd9Sstevel@tonic-gate set_params.mdp = (uintptr_t)(un_array[i]);
61457c478bd9Sstevel@tonic-gate set_params.options =
61467c478bd9Sstevel@tonic-gate meta_check_devicesize(un_array[i]->un_length);
61477c478bd9Sstevel@tonic-gate if (set_params.options == MD_CRO_64BIT) {
6148d7cd8252Stw21770 un_array[i]->c.un_revision |= MD_64BIT_META_DEV;
61497c478bd9Sstevel@tonic-gate } else {
6150d7cd8252Stw21770 un_array[i]->c.un_revision &= ~MD_64BIT_META_DEV;
61517c478bd9Sstevel@tonic-gate }
61527c478bd9Sstevel@tonic-gate MD_SETDRIVERNAME(&set_params, MD_SP,
61537c478bd9Sstevel@tonic-gate MD_MIN2SET(set_params.mnum));
61547c478bd9Sstevel@tonic-gate
61557c478bd9Sstevel@tonic-gate np = metamnumname(&sp, MD_SID(un_array[i]), 0, ep);
61567c478bd9Sstevel@tonic-gate
61577c478bd9Sstevel@tonic-gate /*
61587c478bd9Sstevel@tonic-gate * If this is an MN set, send the MD_IOCSET ioctl to all nodes
61597c478bd9Sstevel@tonic-gate */
61607c478bd9Sstevel@tonic-gate if (mn_set) {
61617c478bd9Sstevel@tonic-gate md_mn_msg_iocset_t send_params;
61627c478bd9Sstevel@tonic-gate int result;
61637c478bd9Sstevel@tonic-gate md_mn_result_t *resp = NULL;
61647c478bd9Sstevel@tonic-gate int mess_size;
61657c478bd9Sstevel@tonic-gate
61667c478bd9Sstevel@tonic-gate /*
61677c478bd9Sstevel@tonic-gate * Calculate message size. md_mn_msg_iocset_t only
61687c478bd9Sstevel@tonic-gate * contains one extent, so increment the size to
61697c478bd9Sstevel@tonic-gate * include all extents
61707c478bd9Sstevel@tonic-gate */
61717c478bd9Sstevel@tonic-gate mess_size = sizeof (send_params) -
61727c478bd9Sstevel@tonic-gate sizeof (mp_ext_t) +
61737c478bd9Sstevel@tonic-gate (un_array[i]->un_numexts * sizeof (mp_ext_t));
61747c478bd9Sstevel@tonic-gate
61757c478bd9Sstevel@tonic-gate send_params.iocset_params = set_params;
61767c478bd9Sstevel@tonic-gate (void) memcpy(&send_params.unit, un_array[i],
61777c478bd9Sstevel@tonic-gate sizeof (*un_array[i]) - sizeof (mp_ext_t) +
61787c478bd9Sstevel@tonic-gate (un_array[i]->un_numexts * sizeof (mp_ext_t)));
61797c478bd9Sstevel@tonic-gate result = mdmn_send_message(sp->setno,
6180bf85a12bSJohn Wren Kennedy MD_MN_MSG_IOCSET, MD_MSGF_DEFAULT_FLAGS, 0,
61817c478bd9Sstevel@tonic-gate (char *)&send_params, mess_size, &resp,
61827c478bd9Sstevel@tonic-gate ep);
61837c478bd9Sstevel@tonic-gate if (resp != NULL) {
61847c478bd9Sstevel@tonic-gate if (resp->mmr_exitval != 0)
61857c478bd9Sstevel@tonic-gate err = 1;
61867c478bd9Sstevel@tonic-gate free_result(resp);
61877c478bd9Sstevel@tonic-gate }
61887c478bd9Sstevel@tonic-gate if (result != 0) {
61897c478bd9Sstevel@tonic-gate err = 1;
61907c478bd9Sstevel@tonic-gate }
61917c478bd9Sstevel@tonic-gate } else {
61927c478bd9Sstevel@tonic-gate if (metaioctl(MD_IOCSET, &set_params, &set_params.mde,
61937c478bd9Sstevel@tonic-gate np->cname) != 0) {
61947c478bd9Sstevel@tonic-gate err = 1;
61957c478bd9Sstevel@tonic-gate }
61967c478bd9Sstevel@tonic-gate }
61977c478bd9Sstevel@tonic-gate
61987c478bd9Sstevel@tonic-gate if (err == 1) {
61997c478bd9Sstevel@tonic-gate (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
62007c478bd9Sstevel@tonic-gate "%s: Error committing record to metadb.\n"),
62017c478bd9Sstevel@tonic-gate np->cname);
62027c478bd9Sstevel@tonic-gate goto out;
62037c478bd9Sstevel@tonic-gate }
62047c478bd9Sstevel@tonic-gate
62057c478bd9Sstevel@tonic-gate /* note that we've committed a record */
62067c478bd9Sstevel@tonic-gate if (!committed)
62077c478bd9Sstevel@tonic-gate committed = 1;
62087c478bd9Sstevel@tonic-gate
62097c478bd9Sstevel@tonic-gate /* update any watermarks that need it */
62107c478bd9Sstevel@tonic-gate if (update_list != NULL) {
62117c478bd9Sstevel@tonic-gate md_sp_t *msp;
62127c478bd9Sstevel@tonic-gate
62137c478bd9Sstevel@tonic-gate /*
62147c478bd9Sstevel@tonic-gate * Check to see if we're trying to create a partition
62157c478bd9Sstevel@tonic-gate * on a mirror. If so we may have to enforce an
62167c478bd9Sstevel@tonic-gate * ownership change before writing the watermark out.
62177c478bd9Sstevel@tonic-gate */
62187c478bd9Sstevel@tonic-gate if (metaismeta(compnp)) {
62197c478bd9Sstevel@tonic-gate char *miscname;
62207c478bd9Sstevel@tonic-gate
62217c478bd9Sstevel@tonic-gate miscname = metagetmiscname(compnp, ep);
62227c478bd9Sstevel@tonic-gate if (miscname != NULL)
62237c478bd9Sstevel@tonic-gate comp_is_mirror = (strcmp(miscname,
62247c478bd9Sstevel@tonic-gate MD_MIRROR) == 0);
62257c478bd9Sstevel@tonic-gate else
62267c478bd9Sstevel@tonic-gate comp_is_mirror = 0;
62277c478bd9Sstevel@tonic-gate }
62287c478bd9Sstevel@tonic-gate /*
62297c478bd9Sstevel@tonic-gate * If this is a MN set and the component is a mirror,
62307c478bd9Sstevel@tonic-gate * change ownership to this node in order to write the
62317c478bd9Sstevel@tonic-gate * watermarks
62327c478bd9Sstevel@tonic-gate */
62337c478bd9Sstevel@tonic-gate if (mn_set && comp_is_mirror) {
62347c478bd9Sstevel@tonic-gate mm = (mm_unit_t *)meta_get_unit(sp, compnp, ep);
62357c478bd9Sstevel@tonic-gate if (mm == NULL) {
62367c478bd9Sstevel@tonic-gate err = 1;
62377c478bd9Sstevel@tonic-gate goto out;
62387c478bd9Sstevel@tonic-gate } else {
62397c478bd9Sstevel@tonic-gate err = meta_mn_change_owner(&ownpar,
62407c478bd9Sstevel@tonic-gate sp->setno,
62417c478bd9Sstevel@tonic-gate meta_getminor(compnp->dev),
62427c478bd9Sstevel@tonic-gate sd->sd_mn_mynode->nd_nodeid,
62437c478bd9Sstevel@tonic-gate MD_MN_MM_PREVENT_CHANGE |
62447c478bd9Sstevel@tonic-gate MD_MN_MM_SPAWN_THREAD);
62457c478bd9Sstevel@tonic-gate if (err != 0)
62467c478bd9Sstevel@tonic-gate goto out;
62477c478bd9Sstevel@tonic-gate }
62487c478bd9Sstevel@tonic-gate }
62497c478bd9Sstevel@tonic-gate
62507c478bd9Sstevel@tonic-gate if ((msp = meta_get_sp(sp, np, ep)) == NULL) {
62517c478bd9Sstevel@tonic-gate err = 1;
62527c478bd9Sstevel@tonic-gate (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
62537c478bd9Sstevel@tonic-gate "%s: Error updating extent headers.\n"),
62547c478bd9Sstevel@tonic-gate np->cname);
62557c478bd9Sstevel@tonic-gate goto out;
62567c478bd9Sstevel@tonic-gate }
62577c478bd9Sstevel@tonic-gate if (meta_sp_update_wm(sp, msp, update_list, ep) < 0) {
62587c478bd9Sstevel@tonic-gate err = 1;
62597c478bd9Sstevel@tonic-gate (void) fprintf(stderr, dgettext(TEXT_DOMAIN,
62607c478bd9Sstevel@tonic-gate "%s: Error updating extent headers "
62617c478bd9Sstevel@tonic-gate "on disk.\n"), np->cname);
62627c478bd9Sstevel@tonic-gate goto out;
62637c478bd9Sstevel@tonic-gate }
62647c478bd9Sstevel@tonic-gate }
62657c478bd9Sstevel@tonic-gate /*
62667c478bd9Sstevel@tonic-gate * If we have changed ownership earlier and prevented any
62677c478bd9Sstevel@tonic-gate * ownership changes, we can now allow ownership changes
62687c478bd9Sstevel@tonic-gate * again.
62697c478bd9Sstevel@tonic-gate */
62707c478bd9Sstevel@tonic-gate if (ownpar) {
62717c478bd9Sstevel@tonic-gate (void) meta_mn_change_owner(&ownpar, sp->setno,
62727c478bd9Sstevel@tonic-gate ownpar->d.mnum,
62737c478bd9Sstevel@tonic-gate ownpar->d.owner,
62747c478bd9Sstevel@tonic-gate MD_MN_MM_ALLOW_CHANGE | MD_MN_MM_SPAWN_THREAD);
62757c478bd9Sstevel@tonic-gate }
62767c478bd9Sstevel@tonic-gate }
62777c478bd9Sstevel@tonic-gate
62787c478bd9Sstevel@tonic-gate /* update status of all soft partitions to OK */
62797c478bd9Sstevel@tonic-gate minors = Zalloc(num_sps * sizeof (minor_t));
62807c478bd9Sstevel@tonic-gate for (i = 0; i < num_sps; i++)
62817c478bd9Sstevel@tonic-gate minors[i] = MD_SID(un_array[i]);
62827c478bd9Sstevel@tonic-gate
62837c478bd9Sstevel@tonic-gate err = update_sp_status(sp, minors, num_sps, MD_SP_OK, mn_set, ep);
62847c478bd9Sstevel@tonic-gate if (err != 0)
62857c478bd9Sstevel@tonic-gate goto out;
62867c478bd9Sstevel@tonic-gate
62877c478bd9Sstevel@tonic-gate if (options & MDCMD_PRINT)
62887c478bd9Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN, "%s: "
62897c478bd9Sstevel@tonic-gate "Soft Partitions recovered from device.\n"),
62907c478bd9Sstevel@tonic-gate compnp->cname);
62917c478bd9Sstevel@tonic-gate out:
62927c478bd9Sstevel@tonic-gate /* free memory */
62937c478bd9Sstevel@tonic-gate if (extlist != NULL)
62947c478bd9Sstevel@tonic-gate meta_sp_list_free(&extlist);
62957c478bd9Sstevel@tonic-gate if (sp_list != NULL)
62967c478bd9Sstevel@tonic-gate meta_sp_list_free(&sp_list);
62977c478bd9Sstevel@tonic-gate if (update_list != NULL)
62987c478bd9Sstevel@tonic-gate meta_sp_list_free(&update_list);
62997c478bd9Sstevel@tonic-gate if (un_array != NULL) {
63007c478bd9Sstevel@tonic-gate for (i = 0; i < num_sps; i++)
63017c478bd9Sstevel@tonic-gate Free(un_array[i]);
63027c478bd9Sstevel@tonic-gate Free(un_array);
63037c478bd9Sstevel@tonic-gate }
63047c478bd9Sstevel@tonic-gate if (minors != NULL)
63057c478bd9Sstevel@tonic-gate Free(minors);
63067c478bd9Sstevel@tonic-gate if (ownpar != NULL)
63077c478bd9Sstevel@tonic-gate Free(ownpar);
63087c478bd9Sstevel@tonic-gate (void) fflush(stdout);
63097c478bd9Sstevel@tonic-gate
63107c478bd9Sstevel@tonic-gate if ((keynlp != NULL) && (committed != 1)) {
63117c478bd9Sstevel@tonic-gate /*
63127c478bd9Sstevel@tonic-gate * if we haven't committed any softparts, either because of an
63137c478bd9Sstevel@tonic-gate * error or because the user decided not to proceed, delete
63147c478bd9Sstevel@tonic-gate * namelist key for the component
63157c478bd9Sstevel@tonic-gate */
63167c478bd9Sstevel@tonic-gate if (mn_set) {
63177c478bd9Sstevel@tonic-gate mdnamelist_t *p;
63187c478bd9Sstevel@tonic-gate
63197c478bd9Sstevel@tonic-gate for (p = keynlp; (p != NULL); p = p->next) {
63207c478bd9Sstevel@tonic-gate mdname_t *np = p->namep;
63217c478bd9Sstevel@tonic-gate md_mn_msg_delkeyname_t send_params;
63227c478bd9Sstevel@tonic-gate md_mn_result_t *resp = NULL;
63237c478bd9Sstevel@tonic-gate
63247c478bd9Sstevel@tonic-gate send_params.delkeyname_dev = np->dev;
63257c478bd9Sstevel@tonic-gate send_params.delkeyname_setno = sp->setno;
63267c478bd9Sstevel@tonic-gate send_params.delkeyname_key = np->key;
63277c478bd9Sstevel@tonic-gate (void) mdmn_send_message(sp->setno,
63287c478bd9Sstevel@tonic-gate MD_MN_MSG_DELKEYNAME, MD_MSGF_DEFAULT_FLAGS,
6329bf85a12bSJohn Wren Kennedy 0, (char *)&send_params,
6330bf85a12bSJohn Wren Kennedy sizeof (send_params),
63317c478bd9Sstevel@tonic-gate &resp, ep);
63327c478bd9Sstevel@tonic-gate if (resp != NULL) {
63337c478bd9Sstevel@tonic-gate free_result(resp);
63347c478bd9Sstevel@tonic-gate }
63357c478bd9Sstevel@tonic-gate }
63367c478bd9Sstevel@tonic-gate } else {
63377c478bd9Sstevel@tonic-gate (void) del_key_names(sp, keynlp, NULL);
63387c478bd9Sstevel@tonic-gate }
63397c478bd9Sstevel@tonic-gate }
63407c478bd9Sstevel@tonic-gate
63417c478bd9Sstevel@tonic-gate metafreenamelist(keynlp);
63427c478bd9Sstevel@tonic-gate
63437c478bd9Sstevel@tonic-gate if (err)
63447c478bd9Sstevel@tonic-gate return (mdmderror(ep, MDE_RECOVER_FAILED, 0, compnp->cname));
63457c478bd9Sstevel@tonic-gate
63467c478bd9Sstevel@tonic-gate if (not_recovered)
63477c478bd9Sstevel@tonic-gate if (options & MDCMD_PRINT)
63487c478bd9Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN, "%s: "
63497c478bd9Sstevel@tonic-gate "Soft Partitions NOT recovered from device.\n"),
63507c478bd9Sstevel@tonic-gate compnp->cname);
63517c478bd9Sstevel@tonic-gate return (0);
63527c478bd9Sstevel@tonic-gate }
63537c478bd9Sstevel@tonic-gate
63547c478bd9Sstevel@tonic-gate /*
63557c478bd9Sstevel@tonic-gate * FUNCTION: meta_sp_recover_from_unit()
63567c478bd9Sstevel@tonic-gate * INPUT: sp - name of set we are recovering in
63577c478bd9Sstevel@tonic-gate * compnp - name of component we are recovering from
63587c478bd9Sstevel@tonic-gate * options - metarecover options
63597c478bd9Sstevel@tonic-gate * OUTPUT: ep - return error pointer
63607c478bd9Sstevel@tonic-gate * RETURNS: int - 0 - success, -1 - error
63617c478bd9Sstevel@tonic-gate * PURPOSE: update watermarks to match metadb records. begin by getting
63627c478bd9Sstevel@tonic-gate * a namelist representing all soft partitions on the specified
63637c478bd9Sstevel@tonic-gate * component. then, build an extlist representing the soft
63647c478bd9Sstevel@tonic-gate * partitions, filling in the freespace extents. notify user
63657c478bd9Sstevel@tonic-gate * of changes, place all soft partitions into the "recovering"
63667c478bd9Sstevel@tonic-gate * state and update the watermarks. finally, return all soft
63677c478bd9Sstevel@tonic-gate * partitions to the "OK" state.
63687c478bd9Sstevel@tonic-gate */
63697c478bd9Sstevel@tonic-gate static int
meta_sp_recover_from_unit(mdsetname_t * sp,mdname_t * compnp,mdcmdopts_t options,md_error_t * ep)63707c478bd9Sstevel@tonic-gate meta_sp_recover_from_unit(
63717c478bd9Sstevel@tonic-gate mdsetname_t *sp,
63727c478bd9Sstevel@tonic-gate mdname_t *compnp,
63737c478bd9Sstevel@tonic-gate mdcmdopts_t options,
63747c478bd9Sstevel@tonic-gate md_error_t *ep
63757c478bd9Sstevel@tonic-gate )
63767c478bd9Sstevel@tonic-gate {
63777c478bd9Sstevel@tonic-gate mdnamelist_t *spnlp = NULL;
63787c478bd9Sstevel@tonic-gate mdnamelist_t *nlp = NULL;
63797c478bd9Sstevel@tonic-gate sp_ext_node_t *ext = NULL;
63807c478bd9Sstevel@tonic-gate sp_ext_node_t *extlist = NULL;
63817c478bd9Sstevel@tonic-gate int count;
63827c478bd9Sstevel@tonic-gate char yesno[255];
63837c478bd9Sstevel@tonic-gate char *yes;
63847c478bd9Sstevel@tonic-gate int rval = 0;
63857c478bd9Sstevel@tonic-gate minor_t *minors = NULL;
63867c478bd9Sstevel@tonic-gate int i;
63877c478bd9Sstevel@tonic-gate md_sp_t *msp;
63887c478bd9Sstevel@tonic-gate md_set_desc *sd;
63897c478bd9Sstevel@tonic-gate bool_t mn_set = 0;
63907c478bd9Sstevel@tonic-gate daddr_t start_block;
63917c478bd9Sstevel@tonic-gate
63927c478bd9Sstevel@tonic-gate count = meta_sp_get_by_component(sp, compnp, &spnlp, 0, ep);
63937c478bd9Sstevel@tonic-gate if (count <= 0)
63947c478bd9Sstevel@tonic-gate return (-1);
63957c478bd9Sstevel@tonic-gate
63967c478bd9Sstevel@tonic-gate /* set flag if dealing with a MN set */
63977c478bd9Sstevel@tonic-gate if (!metaislocalset(sp)) {
63987c478bd9Sstevel@tonic-gate if ((sd = metaget_setdesc(sp, ep)) == NULL) {
63997c478bd9Sstevel@tonic-gate return (-1);
64007c478bd9Sstevel@tonic-gate }
64017c478bd9Sstevel@tonic-gate if (MD_MNSET_DESC(sd))
64027c478bd9Sstevel@tonic-gate mn_set = 1;
64037c478bd9Sstevel@tonic-gate }
64047c478bd9Sstevel@tonic-gate /*
64057c478bd9Sstevel@tonic-gate * Save the XDR unit structure for one of the soft partitions;
64067c478bd9Sstevel@tonic-gate * we'll use this later to provide metadevice context to
64077c478bd9Sstevel@tonic-gate * update the watermarks so the device can be resolved by
64087c478bd9Sstevel@tonic-gate * devid instead of dev_t.
64097c478bd9Sstevel@tonic-gate */
64107c478bd9Sstevel@tonic-gate if ((msp = meta_get_sp(sp, spnlp->namep, ep)) == NULL) {
64117c478bd9Sstevel@tonic-gate metafreenamelist(spnlp);
64127c478bd9Sstevel@tonic-gate return (-1);
64137c478bd9Sstevel@tonic-gate }
64147c478bd9Sstevel@tonic-gate
64157c478bd9Sstevel@tonic-gate if ((start_block = meta_sp_get_start(sp, compnp, ep)) ==
64167c478bd9Sstevel@tonic-gate MD_DISKADDR_ERROR) {
64177c478bd9Sstevel@tonic-gate return (-1);
64187c478bd9Sstevel@tonic-gate }
64197c478bd9Sstevel@tonic-gate
64207c478bd9Sstevel@tonic-gate meta_sp_list_insert(NULL, NULL, &extlist, 0ULL, start_block,
64217c478bd9Sstevel@tonic-gate EXTTYP_RESERVED, 0, 0, meta_sp_cmp_by_offset);
64227c478bd9Sstevel@tonic-gate meta_sp_list_insert(NULL, NULL, &extlist,
64237c478bd9Sstevel@tonic-gate metagetsize(compnp, ep) - MD_SP_WMSIZE, MD_SP_WMSIZE,
64247c478bd9Sstevel@tonic-gate EXTTYP_END, 0, EXTFLG_UPDATE, meta_sp_cmp_by_offset);
64257c478bd9Sstevel@tonic-gate
64267c478bd9Sstevel@tonic-gate if (meta_sp_extlist_from_namelist(sp, spnlp, &extlist, ep) == -1) {
64277c478bd9Sstevel@tonic-gate metafreenamelist(spnlp);
64287c478bd9Sstevel@tonic-gate return (-1);
64297c478bd9Sstevel@tonic-gate }
64307c478bd9Sstevel@tonic-gate
64317c478bd9Sstevel@tonic-gate assert(extlist != NULL);
64327c478bd9Sstevel@tonic-gate if ((options & MDCMD_VERBOSE) != 0) {
64337c478bd9Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN,
64347c478bd9Sstevel@tonic-gate "Updating extent headers on device %s from metadb.\n\n"),
64357c478bd9Sstevel@tonic-gate compnp->cname);
64367c478bd9Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN,
64377c478bd9Sstevel@tonic-gate "The following extent headers will be written:\n"));
64387c478bd9Sstevel@tonic-gate meta_sp_display_exthdr();
64397c478bd9Sstevel@tonic-gate }
64407c478bd9Sstevel@tonic-gate
64417c478bd9Sstevel@tonic-gate meta_sp_list_freefill(&extlist, metagetsize(compnp, ep));
64427c478bd9Sstevel@tonic-gate
64437c478bd9Sstevel@tonic-gate for (ext = extlist; ext != NULL; ext = ext->ext_next) {
64447c478bd9Sstevel@tonic-gate
64457c478bd9Sstevel@tonic-gate /* mark every node for updating except the reserved space */
64467c478bd9Sstevel@tonic-gate if (ext->ext_type != EXTTYP_RESERVED) {
64477c478bd9Sstevel@tonic-gate ext->ext_flags |= EXTFLG_UPDATE;
64487c478bd9Sstevel@tonic-gate
64497c478bd9Sstevel@tonic-gate /* print extent information */
64507c478bd9Sstevel@tonic-gate if ((options & MDCMD_VERBOSE) != 0)
64517c478bd9Sstevel@tonic-gate meta_sp_display_ext(ext);
64527c478bd9Sstevel@tonic-gate }
64537c478bd9Sstevel@tonic-gate }
64547c478bd9Sstevel@tonic-gate
64557c478bd9Sstevel@tonic-gate /* request verification and then update all watermarks */
64567c478bd9Sstevel@tonic-gate if ((options & MDCMD_DOIT) != 0) {
64577c478bd9Sstevel@tonic-gate
64587c478bd9Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN,
64597c478bd9Sstevel@tonic-gate "\nWARNING: You are about to overwrite portions of %s\n"
64607c478bd9Sstevel@tonic-gate "with soft partition metadata. The extent headers will be\n"
64617c478bd9Sstevel@tonic-gate "written to match the existing metadb configuration. If\n"
64627c478bd9Sstevel@tonic-gate "the device was not previously setup with this\n"
64637c478bd9Sstevel@tonic-gate "configuration, data loss may result.\n\n"),
64647c478bd9Sstevel@tonic-gate compnp->cname);
64657c478bd9Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN,
64667c478bd9Sstevel@tonic-gate "Are you sure you want to do this (yes/no)? "));
64677c478bd9Sstevel@tonic-gate
64687c478bd9Sstevel@tonic-gate (void) fflush(stdout);
64697c478bd9Sstevel@tonic-gate if ((fgets(yesno, sizeof (yesno), stdin) == NULL) ||
64707c478bd9Sstevel@tonic-gate (strlen(yesno) == 1))
64717c478bd9Sstevel@tonic-gate (void) snprintf(yesno, sizeof (yesno),
64727c478bd9Sstevel@tonic-gate "%s\n", dgettext(TEXT_DOMAIN, "no"));
64737c478bd9Sstevel@tonic-gate yes = dgettext(TEXT_DOMAIN, "yes");
64747c478bd9Sstevel@tonic-gate if (strncasecmp(yesno, yes, strlen(yesno) - 1) == 0) {
64757c478bd9Sstevel@tonic-gate /* place soft partitions into recovering state */
64767c478bd9Sstevel@tonic-gate minors = Zalloc(count * sizeof (minor_t));
64777c478bd9Sstevel@tonic-gate for (nlp = spnlp, i = 0;
64787c478bd9Sstevel@tonic-gate nlp != NULL && i < count;
64797c478bd9Sstevel@tonic-gate nlp = nlp->next, i++) {
64807c478bd9Sstevel@tonic-gate assert(nlp->namep != NULL);
64817c478bd9Sstevel@tonic-gate minors[i] = meta_getminor(nlp->namep->dev);
64827c478bd9Sstevel@tonic-gate }
64837c478bd9Sstevel@tonic-gate if (update_sp_status(sp, minors, count,
64847c478bd9Sstevel@tonic-gate MD_SP_RECOVER, mn_set, ep) != 0) {
64857c478bd9Sstevel@tonic-gate rval = -1;
64867c478bd9Sstevel@tonic-gate goto out;
64877c478bd9Sstevel@tonic-gate }
64887c478bd9Sstevel@tonic-gate
64897c478bd9Sstevel@tonic-gate /* update the watermarks */
64907c478bd9Sstevel@tonic-gate if (meta_sp_update_wm(sp, msp, extlist, ep) < 0) {
64917c478bd9Sstevel@tonic-gate rval = -1;
64927c478bd9Sstevel@tonic-gate goto out;
64937c478bd9Sstevel@tonic-gate }
64947c478bd9Sstevel@tonic-gate
64957c478bd9Sstevel@tonic-gate if (options & MDCMD_PRINT) {
64967c478bd9Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN, "%s: "
64977c478bd9Sstevel@tonic-gate "Soft Partitions recovered from metadb\n"),
64987c478bd9Sstevel@tonic-gate compnp->cname);
64997c478bd9Sstevel@tonic-gate }
65007c478bd9Sstevel@tonic-gate
65017c478bd9Sstevel@tonic-gate /* return soft partitions to the OK state */
65027c478bd9Sstevel@tonic-gate if (update_sp_status(sp, minors, count,
65037c478bd9Sstevel@tonic-gate MD_SP_OK, mn_set, ep) != 0) {
65047c478bd9Sstevel@tonic-gate rval = -1;
65057c478bd9Sstevel@tonic-gate goto out;
65067c478bd9Sstevel@tonic-gate }
65077c478bd9Sstevel@tonic-gate
65087c478bd9Sstevel@tonic-gate rval = 0;
65097c478bd9Sstevel@tonic-gate goto out;
65107c478bd9Sstevel@tonic-gate }
65117c478bd9Sstevel@tonic-gate }
65127c478bd9Sstevel@tonic-gate
65137c478bd9Sstevel@tonic-gate if (options & MDCMD_PRINT) {
65147c478bd9Sstevel@tonic-gate (void) printf(dgettext(TEXT_DOMAIN,
65157c478bd9Sstevel@tonic-gate "%s: Soft Partitions NOT recovered from metadb\n"),
65167c478bd9Sstevel@tonic-gate compnp->cname);
65177c478bd9Sstevel@tonic-gate }
65187c478bd9Sstevel@tonic-gate
65197c478bd9Sstevel@tonic-gate out:
65207c478bd9Sstevel@tonic-gate if (minors != NULL)
65217c478bd9Sstevel@tonic-gate Free(minors);
65227c478bd9Sstevel@tonic-gate metafreenamelist(spnlp);
65237c478bd9Sstevel@tonic-gate meta_sp_list_free(&extlist);
65247c478bd9Sstevel@tonic-gate (void) fflush(stdout);
65257c478bd9Sstevel@tonic-gate return (rval);
65267c478bd9Sstevel@tonic-gate }
65277c478bd9Sstevel@tonic-gate
65287c478bd9Sstevel@tonic-gate
65297c478bd9Sstevel@tonic-gate /*
65307c478bd9Sstevel@tonic-gate * FUNCTION: meta_sp_update_abr()
65317c478bd9Sstevel@tonic-gate * INPUT: sp - name of set we are recovering in
65327c478bd9Sstevel@tonic-gate * OUTPUT: ep - return error pointer
65337c478bd9Sstevel@tonic-gate * RETURNS: int - 0 - success, -1 - error
65347c478bd9Sstevel@tonic-gate * PURPOSE: update the ABR state for all soft partitions in the set. This
65357c478bd9Sstevel@tonic-gate * is called when joining a set. It sends a message to the master
65367c478bd9Sstevel@tonic-gate * node for each soft partition to get the value of tstate and
65377c478bd9Sstevel@tonic-gate * then sets ABR ,if required, by opening the sp, setting ABR
65387c478bd9Sstevel@tonic-gate * and then closing the sp. This approach is taken rather that
65397c478bd9Sstevel@tonic-gate * just issuing the MD_MN_SET_CAP ioctl, in order to deal with
65407c478bd9Sstevel@tonic-gate * the case when we have another node simultaneously unsetting ABR.
65417c478bd9Sstevel@tonic-gate */
65427c478bd9Sstevel@tonic-gate int
meta_sp_update_abr(mdsetname_t * sp,md_error_t * ep)65437c478bd9Sstevel@tonic-gate meta_sp_update_abr(
65447c478bd9Sstevel@tonic-gate mdsetname_t *sp,
65457c478bd9Sstevel@tonic-gate md_error_t *ep
65467c478bd9Sstevel@tonic-gate )
65477c478bd9Sstevel@tonic-gate {
65487c478bd9Sstevel@tonic-gate mdnamelist_t *devnlp = NULL;
65497c478bd9Sstevel@tonic-gate mdnamelist_t *p;
65507c478bd9Sstevel@tonic-gate mdname_t *devnp = NULL;
65517c478bd9Sstevel@tonic-gate md_unit_t *un;
65527c478bd9Sstevel@tonic-gate char fname[MAXPATHLEN];
65537c478bd9Sstevel@tonic-gate int mnum, fd;
65547c478bd9Sstevel@tonic-gate volcap_t vc;
65557c478bd9Sstevel@tonic-gate uint_t tstate;
65567c478bd9Sstevel@tonic-gate
65577c478bd9Sstevel@tonic-gate
65587c478bd9Sstevel@tonic-gate if (meta_get_sp_names(sp, &devnlp, 0, ep) < 0) {
65597c478bd9Sstevel@tonic-gate return (-1);
65607c478bd9Sstevel@tonic-gate }
65617c478bd9Sstevel@tonic-gate
65627c478bd9Sstevel@tonic-gate /* Exit if no soft partitions in this set */
65637c478bd9Sstevel@tonic-gate if (devnlp == NULL)
65647c478bd9Sstevel@tonic-gate return (0);
65657c478bd9Sstevel@tonic-gate
65667c478bd9Sstevel@tonic-gate /* For each soft partition */
65677c478bd9Sstevel@tonic-gate for (p = devnlp; (p != NULL); p = p->next) {
65687c478bd9Sstevel@tonic-gate devnp = p->namep;
65697c478bd9Sstevel@tonic-gate
65707c478bd9Sstevel@tonic-gate /* check if this is a top level metadevice */
65717c478bd9Sstevel@tonic-gate if ((un = meta_get_mdunit(sp, devnp, ep)) == NULL)
65727c478bd9Sstevel@tonic-gate goto out;
65737c478bd9Sstevel@tonic-gate if (MD_HAS_PARENT(MD_PARENT(un))) {
65747c478bd9Sstevel@tonic-gate Free(un);
65757c478bd9Sstevel@tonic-gate continue;
65767c478bd9Sstevel@tonic-gate }
65777c478bd9Sstevel@tonic-gate Free(un);
65787c478bd9Sstevel@tonic-gate
65797c478bd9Sstevel@tonic-gate /* Get tstate from Master */
65807c478bd9Sstevel@tonic-gate if (meta_mn_send_get_tstate(devnp->dev, &tstate, ep) != 0) {
65817c478bd9Sstevel@tonic-gate mdname_t *np;
65827c478bd9Sstevel@tonic-gate np = metamnumname(&sp, meta_getminor(devnp->dev), 0,
65837c478bd9Sstevel@tonic-gate ep);
65847c478bd9Sstevel@tonic-gate if (np) {
65857c478bd9Sstevel@tonic-gate md_perror(dgettext(TEXT_DOMAIN,
65867c478bd9Sstevel@tonic-gate "Unable to get tstate for %s"), np->cname);
65877c478bd9Sstevel@tonic-gate }
65887c478bd9Sstevel@tonic-gate continue;
65897c478bd9Sstevel@tonic-gate }
65907c478bd9Sstevel@tonic-gate /* If not set on the master, nothing to do */
65917c478bd9Sstevel@tonic-gate if (!(tstate & MD_ABR_CAP))
65927c478bd9Sstevel@tonic-gate continue;
65937c478bd9Sstevel@tonic-gate
65947c478bd9Sstevel@tonic-gate mnum = meta_getminor(devnp->dev);
65957c478bd9Sstevel@tonic-gate (void) snprintf(fname, MAXPATHLEN, "/dev/md/%s/rdsk/d%u",
65967c478bd9Sstevel@tonic-gate sp->setname, (unsigned)MD_MIN2UNIT(mnum));
65977c478bd9Sstevel@tonic-gate if ((fd = open(fname, O_RDWR, 0)) < 0) {
65987c478bd9Sstevel@tonic-gate md_perror(dgettext(TEXT_DOMAIN,
65997c478bd9Sstevel@tonic-gate "Could not open device %s"), fname);
66007c478bd9Sstevel@tonic-gate continue;
66017c478bd9Sstevel@tonic-gate }
66027c478bd9Sstevel@tonic-gate
66037c478bd9Sstevel@tonic-gate /* Set ABR state */
66047c478bd9Sstevel@tonic-gate vc.vc_info = 0;
66057c478bd9Sstevel@tonic-gate vc.vc_set = 0;
66067c478bd9Sstevel@tonic-gate if (ioctl(fd, DKIOCGETVOLCAP, &vc) < 0) {
66077c478bd9Sstevel@tonic-gate (void) close(fd);
66087c478bd9Sstevel@tonic-gate continue;
66097c478bd9Sstevel@tonic-gate }
66107c478bd9Sstevel@tonic-gate
66117c478bd9Sstevel@tonic-gate vc.vc_set = DKV_ABR_CAP;
66127c478bd9Sstevel@tonic-gate if (ioctl(fd, DKIOCSETVOLCAP, &vc) < 0) {
66137c478bd9Sstevel@tonic-gate (void) close(fd);
66147c478bd9Sstevel@tonic-gate goto out;
66157c478bd9Sstevel@tonic-gate }
66167c478bd9Sstevel@tonic-gate
66177c478bd9Sstevel@tonic-gate (void) close(fd);
66187c478bd9Sstevel@tonic-gate }
66197c478bd9Sstevel@tonic-gate metafreenamelist(devnlp);
66207c478bd9Sstevel@tonic-gate return (0);
66217c478bd9Sstevel@tonic-gate out:
66227c478bd9Sstevel@tonic-gate metafreenamelist(devnlp);
66237c478bd9Sstevel@tonic-gate return (-1);
66247c478bd9Sstevel@tonic-gate }
66257c478bd9Sstevel@tonic-gate
66267c478bd9Sstevel@tonic-gate /*
66277c478bd9Sstevel@tonic-gate * FUNCTION: meta_mn_sp_update_abr()
66287c478bd9Sstevel@tonic-gate * INPUT: arg - Given set.
66297c478bd9Sstevel@tonic-gate * PURPOSE: update the ABR state for all soft partitions in the set by
66307c478bd9Sstevel@tonic-gate * forking a process to call meta_sp_update_abr()
66317c478bd9Sstevel@tonic-gate * This function is only called via rpc.metad when adding a node
66327c478bd9Sstevel@tonic-gate * to a set, ie this node is beong joined to the set by another
66337c478bd9Sstevel@tonic-gate * node.
66347c478bd9Sstevel@tonic-gate */
66357c478bd9Sstevel@tonic-gate void *
meta_mn_sp_update_abr(void * arg)66367c478bd9Sstevel@tonic-gate meta_mn_sp_update_abr(void *arg)
66377c478bd9Sstevel@tonic-gate {
66387c478bd9Sstevel@tonic-gate set_t setno = *((set_t *)arg);
66397c478bd9Sstevel@tonic-gate mdsetname_t *sp;
66407c478bd9Sstevel@tonic-gate md_error_t mde = mdnullerror;
66417c478bd9Sstevel@tonic-gate int fval;
66427c478bd9Sstevel@tonic-gate
66437c478bd9Sstevel@tonic-gate /* should have a set */
66447c478bd9Sstevel@tonic-gate assert(setno != NULL);
66457c478bd9Sstevel@tonic-gate
66467c478bd9Sstevel@tonic-gate if ((sp = metasetnosetname(setno, &mde)) == NULL) {
66477c478bd9Sstevel@tonic-gate mde_perror(&mde, "");
66487c478bd9Sstevel@tonic-gate return (NULL);
66497c478bd9Sstevel@tonic-gate }
66507c478bd9Sstevel@tonic-gate
66517c478bd9Sstevel@tonic-gate if (!(meta_is_mn_set(sp, &mde))) {
66527c478bd9Sstevel@tonic-gate mde_perror(&mde, "");
66537c478bd9Sstevel@tonic-gate return (NULL);
66547c478bd9Sstevel@tonic-gate }
66557c478bd9Sstevel@tonic-gate
66567c478bd9Sstevel@tonic-gate /* fork a process */
66577c478bd9Sstevel@tonic-gate if ((fval = md_daemonize(sp, &mde)) != 0) {
66587c478bd9Sstevel@tonic-gate /*
66597c478bd9Sstevel@tonic-gate * md_daemonize will fork off a process. The is the
66607c478bd9Sstevel@tonic-gate * parent or error.
66617c478bd9Sstevel@tonic-gate */
66627c478bd9Sstevel@tonic-gate if (fval > 0) {
66637c478bd9Sstevel@tonic-gate return (NULL);
66647c478bd9Sstevel@tonic-gate }
66657c478bd9Sstevel@tonic-gate mde_perror(&mde, "");
66667c478bd9Sstevel@tonic-gate return (NULL);
66677c478bd9Sstevel@tonic-gate }
66687c478bd9Sstevel@tonic-gate /*
66697c478bd9Sstevel@tonic-gate * Child process should never return back to rpc.metad, but
66707c478bd9Sstevel@tonic-gate * should exit.
66717c478bd9Sstevel@tonic-gate * Flush all internally cached data inherited from parent process
66727c478bd9Sstevel@tonic-gate * since cached data will be cleared when parent process RPC request
66737c478bd9Sstevel@tonic-gate * has completed (which is possibly before this child process
66747c478bd9Sstevel@tonic-gate * can complete).
66757c478bd9Sstevel@tonic-gate * Child process can retrieve and cache its own copy of data from
66767c478bd9Sstevel@tonic-gate * rpc.metad that won't be changed by the parent process.
66777c478bd9Sstevel@tonic-gate *
66787c478bd9Sstevel@tonic-gate * Reset md_in_daemon since this child will be a client of rpc.metad
66797c478bd9Sstevel@tonic-gate * not part of the rpc.metad daemon itself.
66807c478bd9Sstevel@tonic-gate * md_in_daemon is used by rpc.metad so that libmeta can tell if
66817c478bd9Sstevel@tonic-gate * this thread is rpc.metad or any other thread. (If this thread
66827c478bd9Sstevel@tonic-gate * was rpc.metad it could use some short circuit code to get data
66837c478bd9Sstevel@tonic-gate * directly from rpc.metad instead of doing an RPC call to rpc.metad).
66847c478bd9Sstevel@tonic-gate */
66857c478bd9Sstevel@tonic-gate md_in_daemon = 0;
66867c478bd9Sstevel@tonic-gate metaflushsetname(sp);
66877c478bd9Sstevel@tonic-gate sr_cache_flush_setno(setno);
66887c478bd9Sstevel@tonic-gate if ((sp = metasetnosetname(setno, &mde)) == NULL) {
66897c478bd9Sstevel@tonic-gate mde_perror(&mde, "");
66907c478bd9Sstevel@tonic-gate md_exit(sp, 1);
66917c478bd9Sstevel@tonic-gate }
66927c478bd9Sstevel@tonic-gate
66937c478bd9Sstevel@tonic-gate
66947c478bd9Sstevel@tonic-gate /*
66957c478bd9Sstevel@tonic-gate * Closing stdin/out/err here.
66967c478bd9Sstevel@tonic-gate */
66977c478bd9Sstevel@tonic-gate (void) close(0);
66987c478bd9Sstevel@tonic-gate (void) close(1);
66997c478bd9Sstevel@tonic-gate (void) close(2);
67007c478bd9Sstevel@tonic-gate assert(fval == 0);
67017c478bd9Sstevel@tonic-gate
67027c478bd9Sstevel@tonic-gate (void) meta_sp_update_abr(sp, &mde);
67037c478bd9Sstevel@tonic-gate
67047c478bd9Sstevel@tonic-gate md_exit(sp, 0);
67057c478bd9Sstevel@tonic-gate /*NOTREACHED*/
6706b6c8bd52Sjeanm return (NULL);
67077c478bd9Sstevel@tonic-gate }
67081cd3f00bSsk102515
67091cd3f00bSsk102515 int
meta_sp_check_component(mdsetname_t * sp,mdname_t * np,md_error_t * ep)67101cd3f00bSsk102515 meta_sp_check_component(
67111cd3f00bSsk102515 mdsetname_t *sp,
67121cd3f00bSsk102515 mdname_t *np,
67131cd3f00bSsk102515 md_error_t *ep
67141cd3f00bSsk102515 )
67151cd3f00bSsk102515 {
67161cd3f00bSsk102515 md_sp_t *msp;
67171cd3f00bSsk102515 minor_t mnum = 0;
67181cd3f00bSsk102515 md_dev64_t dev = 0;
67191cd3f00bSsk102515 mdnm_params_t nm;
67201cd3f00bSsk102515 md_getdevs_params_t mgd;
67211cd3f00bSsk102515 side_t sideno;
67221cd3f00bSsk102515 char *miscname;
67231cd3f00bSsk102515 md_dev64_t *mydev = NULL;
67242791f8b9SPeter Dennis - Sustaining Engineer char *pname = NULL, *t;
67252791f8b9SPeter Dennis - Sustaining Engineer char *ctd_name = NULL;
67262791f8b9SPeter Dennis - Sustaining Engineer char *devname = NULL;
67271cd3f00bSsk102515 int len;
67281cd3f00bSsk102515 int rval = -1;
67291cd3f00bSsk102515
67301cd3f00bSsk102515 (void) memset(&nm, '\0', sizeof (nm));
67311cd3f00bSsk102515 if ((msp = meta_get_sp_common(sp, np, 0, ep)) == NULL)
67321cd3f00bSsk102515 return (-1);
67331cd3f00bSsk102515
67341cd3f00bSsk102515 if ((miscname = metagetmiscname(np, ep)) == NULL)
67351cd3f00bSsk102515 return (-1);
67361cd3f00bSsk102515
67371cd3f00bSsk102515 sideno = getmyside(sp, ep);
67381cd3f00bSsk102515
67391cd3f00bSsk102515 meta_sp_debug("meta_sp_check_component: %s is on %s key: %d"
67401cd3f00bSsk102515 " dev: %llu\n",
67411cd3f00bSsk102515 np->cname, msp->compnamep->cname, msp->compnamep->key,
67421cd3f00bSsk102515 msp->compnamep->dev);
67431cd3f00bSsk102515
67441cd3f00bSsk102515 /*
67451cd3f00bSsk102515 * Now get the data from the unit structure. The compnamep stuff
67461cd3f00bSsk102515 * contains the data from the namespace and we need the un_dev
67471cd3f00bSsk102515 * from the unit structure.
67481cd3f00bSsk102515 */
67491cd3f00bSsk102515 (void) memset(&mgd, '\0', sizeof (mgd));
67501cd3f00bSsk102515 MD_SETDRIVERNAME(&mgd, miscname, sp->setno);
67511cd3f00bSsk102515 mgd.cnt = 1; /* sp's only have one subdevice */
67521cd3f00bSsk102515 mgd.mnum = meta_getminor(np->dev);
67531cd3f00bSsk102515
67541cd3f00bSsk102515 mydev = Zalloc(sizeof (*mydev));
67551cd3f00bSsk102515 mgd.devs = (uintptr_t)mydev;
67561cd3f00bSsk102515
67571cd3f00bSsk102515 if (metaioctl(MD_IOCGET_DEVS, &mgd, &mgd.mde, np->cname) != 0) {
67581cd3f00bSsk102515 meta_sp_debug("meta_sp_check_component: ioctl failed\n");
67591cd3f00bSsk102515 (void) mdstealerror(ep, &mgd.mde);
67601cd3f00bSsk102515 rval = 0;
67611cd3f00bSsk102515 goto out;
67621cd3f00bSsk102515 } else if (mgd.cnt <= 0) {
67631cd3f00bSsk102515 assert(mgd.cnt >= 0);
67641cd3f00bSsk102515 rval = 0;
67651cd3f00bSsk102515 goto out;
67661cd3f00bSsk102515 }
67671cd3f00bSsk102515
67681cd3f00bSsk102515 /* Get the devname from the name space. */
67691cd3f00bSsk102515 if ((devname = meta_getnmentbykey(sp->setno, sideno,
67701cd3f00bSsk102515 msp->compnamep->key, NULL, &mnum, &dev, ep)) == NULL) {
67711cd3f00bSsk102515 meta_sp_debug("meta_sp_check_component: key %d not"
67721cd3f00bSsk102515 "found\n", msp->compnamep->key);
67731cd3f00bSsk102515 goto out;
67741cd3f00bSsk102515 }
67751cd3f00bSsk102515
67761cd3f00bSsk102515 meta_sp_debug("dev %s from component: (%lu, %lu)\n",
67771cd3f00bSsk102515 devname,
67781cd3f00bSsk102515 meta_getmajor(*mydev),
67791cd3f00bSsk102515 meta_getminor(*mydev));
67801cd3f00bSsk102515 meta_sp_debug("minor from the namespace: %lu\n", mnum);
67811cd3f00bSsk102515
67821cd3f00bSsk102515 if (mnum != meta_getminor(*mydev)) {
67831cd3f00bSsk102515 /*
67841cd3f00bSsk102515 * The minor numbers are different. Update the namespace
67851cd3f00bSsk102515 * with the information from the component.
67861cd3f00bSsk102515 */
67871cd3f00bSsk102515
67881cd3f00bSsk102515 t = strrchr(devname, '/');
67891cd3f00bSsk102515 t++;
67901cd3f00bSsk102515 ctd_name = Strdup(t);
67911cd3f00bSsk102515
67921cd3f00bSsk102515 meta_sp_debug("meta_sp_check_component: ctd_name: %s\n",
67931cd3f00bSsk102515 ctd_name);
67941cd3f00bSsk102515
67951cd3f00bSsk102515 len = strlen(devname);
67961cd3f00bSsk102515 t = strrchr(devname, '/');
67971cd3f00bSsk102515 t++;
67981cd3f00bSsk102515 pname = Zalloc((len - strlen(t)) + 1);
67991cd3f00bSsk102515 (void) strncpy(pname, devname, (len - strlen(t)));
68001cd3f00bSsk102515 meta_sp_debug("pathname: %s\n", pname);
68011cd3f00bSsk102515
68021cd3f00bSsk102515 meta_sp_debug("updating the minor number to %lu\n", nm.mnum);
68031cd3f00bSsk102515
68041cd3f00bSsk102515 if (meta_update_namespace(sp->setno, sideno,
68051cd3f00bSsk102515 ctd_name, *mydev, msp->compnamep->key, pname,
68061cd3f00bSsk102515 ep) != 0) {
68071cd3f00bSsk102515 goto out;
68081cd3f00bSsk102515 }
68091cd3f00bSsk102515 }
68101cd3f00bSsk102515 out:
68111cd3f00bSsk102515 if (pname != NULL)
68121cd3f00bSsk102515 Free(pname);
68131cd3f00bSsk102515 if (ctd_name != NULL)
68141cd3f00bSsk102515 Free(ctd_name);
68151cd3f00bSsk102515 if (devname != NULL)
68161cd3f00bSsk102515 Free(devname);
68171cd3f00bSsk102515 if (mydev != NULL)
68181cd3f00bSsk102515 Free(mydev);
68191cd3f00bSsk102515 return (rval);
68201cd3f00bSsk102515 }
6821