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
57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate * with the License.
87c478bd9Sstevel@tonic-gate *
97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate * and limitations under the License.
137c478bd9Sstevel@tonic-gate *
147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate *
207c478bd9Sstevel@tonic-gate * CDDL HEADER END
217c478bd9Sstevel@tonic-gate */
227c478bd9Sstevel@tonic-gate /*
23*b6c8bd52Sjeanm * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
247c478bd9Sstevel@tonic-gate * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate */
267c478bd9Sstevel@tonic-gate
277c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
287c478bd9Sstevel@tonic-gate
297c478bd9Sstevel@tonic-gate #include <assert.h>
307c478bd9Sstevel@tonic-gate #include <string.h>
317c478bd9Sstevel@tonic-gate #include <libintl.h>
327c478bd9Sstevel@tonic-gate
337c478bd9Sstevel@tonic-gate #include "volume_error.h"
347c478bd9Sstevel@tonic-gate #include "volume_defaults.h"
357c478bd9Sstevel@tonic-gate #include "volume_dlist.h"
367c478bd9Sstevel@tonic-gate #include "volume_output.h"
377c478bd9Sstevel@tonic-gate #include "volume_request.h"
387c478bd9Sstevel@tonic-gate
397c478bd9Sstevel@tonic-gate #include "layout_device_cache.h"
407c478bd9Sstevel@tonic-gate #include "layout_discovery.h"
417c478bd9Sstevel@tonic-gate #include "layout_dlist_util.h"
427c478bd9Sstevel@tonic-gate #include "layout_request.h"
437c478bd9Sstevel@tonic-gate #include "layout_slice.h"
447c478bd9Sstevel@tonic-gate #include "layout_validate.h"
457c478bd9Sstevel@tonic-gate
467c478bd9Sstevel@tonic-gate #define _LAYOUT_REQUEST_C
477c478bd9Sstevel@tonic-gate
487c478bd9Sstevel@tonic-gate static char *_request_diskset = NULL;
497c478bd9Sstevel@tonic-gate static devconfig_t *_toplevel_request = NULL;
507c478bd9Sstevel@tonic-gate static defaults_t *_defaults = NULL;
517c478bd9Sstevel@tonic-gate
527c478bd9Sstevel@tonic-gate /*
537c478bd9Sstevel@tonic-gate * This file contains code which handles various aspects of the
547c478bd9Sstevel@tonic-gate * request and defaults devconfig_t structs passed to the layout
557c478bd9Sstevel@tonic-gate * module.
567c478bd9Sstevel@tonic-gate *
577c478bd9Sstevel@tonic-gate * Functions are provided which determine what devices are available
587c478bd9Sstevel@tonic-gate * for use by the various volume layout mechanisms. These are based
597c478bd9Sstevel@tonic-gate * on the user specified available/unavailable devices included in
607c478bd9Sstevel@tonic-gate * a request or in the defaults associated with the destination diskset.
617c478bd9Sstevel@tonic-gate */
627c478bd9Sstevel@tonic-gate
637c478bd9Sstevel@tonic-gate /*
647c478bd9Sstevel@tonic-gate * A struct to hold device "specifications" extracted from a user
657c478bd9Sstevel@tonic-gate * specified device name. This struct is used to compare the user's
667c478bd9Sstevel@tonic-gate * available and unavailable device specifications against physical
677c478bd9Sstevel@tonic-gate * devices attached to the system.
687c478bd9Sstevel@tonic-gate *
697c478bd9Sstevel@tonic-gate * The spec struct holds one of two different specifications: if the
707c478bd9Sstevel@tonic-gate * user supplied device name is parsable as a CTD name, it is parsed
717c478bd9Sstevel@tonic-gate * into the component ids. Otherwise, it is stored as is.
727c478bd9Sstevel@tonic-gate *
737c478bd9Sstevel@tonic-gate * The CTD name space implies a device hierarchy and metassist
747c478bd9Sstevel@tonic-gate * supports an implied wildcarding scheme for the CTD name space.
757c478bd9Sstevel@tonic-gate * A CTD specification from the user is of the form cX, cXdX,
767c478bd9Sstevel@tonic-gate * cXdXsX, cXtX, cXtXdX, or cXtXdXsX, so it may or may nor
777c478bd9Sstevel@tonic-gate * correspond to an individual physical device depending on
787c478bd9Sstevel@tonic-gate * the context.
797c478bd9Sstevel@tonic-gate *
807c478bd9Sstevel@tonic-gate * For example, "c1" can mean the controller/HBA with the
817c478bd9Sstevel@tonic-gate * name "c1" or it can mean all devices attached to the
827c478bd9Sstevel@tonic-gate * controller named "c1".
837c478bd9Sstevel@tonic-gate *
847c478bd9Sstevel@tonic-gate * The ctd specs make matching physical devices against a
857c478bd9Sstevel@tonic-gate * user specification easier since the matching is based on
867c478bd9Sstevel@tonic-gate * the numeric values extracted from the cXtXdXsX string
877c478bd9Sstevel@tonic-gate * and not on the strings themselves. The strings are
887c478bd9Sstevel@tonic-gate * troublesome because of situations like "c1" being
897c478bd9Sstevel@tonic-gate * compared to "c11t1d0s0" and getting false matches.
907c478bd9Sstevel@tonic-gate *
917c478bd9Sstevel@tonic-gate * The ID_UNSPECIFIED value is used to flag components
927c478bd9Sstevel@tonic-gate * that were not in the CTD name:
937c478bd9Sstevel@tonic-gate *
947c478bd9Sstevel@tonic-gate * "c3" -> { ctrl=3, target=ID_UNSPECIFIED,
957c478bd9Sstevel@tonic-gate * lun=ID_UNSPECIFIED, slice=ID_UNSPECIFIED }
967c478bd9Sstevel@tonic-gate *
977c478bd9Sstevel@tonic-gate * "c3t2" -> { ctrl=3, target=2,
987c478bd9Sstevel@tonic-gate * lun=ID_UNSPECIFIED, slice=ID_UNSPECIFIED }
997c478bd9Sstevel@tonic-gate */
1007c478bd9Sstevel@tonic-gate
1017c478bd9Sstevel@tonic-gate #define ID_UNSPECIFIED -1
1027c478bd9Sstevel@tonic-gate typedef struct {
1037c478bd9Sstevel@tonic-gate int ctrl;
1047c478bd9Sstevel@tonic-gate int target;
1057c478bd9Sstevel@tonic-gate int lun;
1067c478bd9Sstevel@tonic-gate int slice;
1077c478bd9Sstevel@tonic-gate boolean_t is_ide;
1087c478bd9Sstevel@tonic-gate } ctd_spec_t;
1097c478bd9Sstevel@tonic-gate
1107c478bd9Sstevel@tonic-gate typedef enum {
1117c478bd9Sstevel@tonic-gate SPEC_TYPE_CTD = 0,
1127c478bd9Sstevel@tonic-gate SPEC_TYPE_RAW,
1137c478bd9Sstevel@tonic-gate SPEC_TYPE_OTHER
1147c478bd9Sstevel@tonic-gate } spec_type_t;
1157c478bd9Sstevel@tonic-gate
1167c478bd9Sstevel@tonic-gate typedef struct {
1177c478bd9Sstevel@tonic-gate spec_type_t type;
1187c478bd9Sstevel@tonic-gate union {
1197c478bd9Sstevel@tonic-gate ctd_spec_t *ctd;
1207c478bd9Sstevel@tonic-gate char *raw;
1217c478bd9Sstevel@tonic-gate } data;
1227c478bd9Sstevel@tonic-gate } device_spec_t;
1237c478bd9Sstevel@tonic-gate
1247c478bd9Sstevel@tonic-gate static int get_spec_for_name(
1257c478bd9Sstevel@tonic-gate char *name,
1267c478bd9Sstevel@tonic-gate device_spec_t **id);
1277c478bd9Sstevel@tonic-gate
1287c478bd9Sstevel@tonic-gate static int create_device_spec(
1297c478bd9Sstevel@tonic-gate char *name,
1307c478bd9Sstevel@tonic-gate device_spec_t **spec);
1317c478bd9Sstevel@tonic-gate
1327c478bd9Sstevel@tonic-gate static int create_device_ctd_spec(
1337c478bd9Sstevel@tonic-gate char *name,
1347c478bd9Sstevel@tonic-gate device_spec_t **spec);
1357c478bd9Sstevel@tonic-gate
1367c478bd9Sstevel@tonic-gate static int create_device_raw_spec(
1377c478bd9Sstevel@tonic-gate char *name,
1387c478bd9Sstevel@tonic-gate device_spec_t **spec);
1397c478bd9Sstevel@tonic-gate
1407c478bd9Sstevel@tonic-gate static void destroy_device_spec(
1417c478bd9Sstevel@tonic-gate device_spec_t *spec);
1427c478bd9Sstevel@tonic-gate
1437c478bd9Sstevel@tonic-gate static boolean_t ctd_spec_includes_device(
1447c478bd9Sstevel@tonic-gate device_spec_t *spec,
1457c478bd9Sstevel@tonic-gate device_spec_t *device);
1467c478bd9Sstevel@tonic-gate
1477c478bd9Sstevel@tonic-gate static boolean_t raw_spec_includes_device(
1487c478bd9Sstevel@tonic-gate device_spec_t *spec,
1497c478bd9Sstevel@tonic-gate device_spec_t *device);
1507c478bd9Sstevel@tonic-gate
1517c478bd9Sstevel@tonic-gate /*
1527c478bd9Sstevel@tonic-gate * get_spec_for_name builds up a cached mapping of device
1537c478bd9Sstevel@tonic-gate * names to the corresponding device_spec_t structs.
1547c478bd9Sstevel@tonic-gate *
1557c478bd9Sstevel@tonic-gate * This saves repeatedly converting the device names, which
1567c478bd9Sstevel@tonic-gate * could get expensive since devices are checked against the
1577c478bd9Sstevel@tonic-gate * user specified available/unavailable devices a lot.
1587c478bd9Sstevel@tonic-gate *
1597c478bd9Sstevel@tonic-gate * The cache is implemented as a list of these structs:
1607c478bd9Sstevel@tonic-gate */
1617c478bd9Sstevel@tonic-gate typedef struct {
1627c478bd9Sstevel@tonic-gate
1637c478bd9Sstevel@tonic-gate char *name;
1647c478bd9Sstevel@tonic-gate device_spec_t *device_spec;
1657c478bd9Sstevel@tonic-gate
1667c478bd9Sstevel@tonic-gate } spec_cache_t;
1677c478bd9Sstevel@tonic-gate
1687c478bd9Sstevel@tonic-gate static dlist_t *_spec_cache = NULL;
1697c478bd9Sstevel@tonic-gate
1707c478bd9Sstevel@tonic-gate static int destroy_spec_cache();
1717c478bd9Sstevel@tonic-gate static int compare_name_to_spec_cache_name(
1727c478bd9Sstevel@tonic-gate void *name, void *list_item);
1737c478bd9Sstevel@tonic-gate
1747c478bd9Sstevel@tonic-gate /*
1757c478bd9Sstevel@tonic-gate * The user specified available/unavailable devices are
1767c478bd9Sstevel@tonic-gate * accessed frequently during layout. To make this more
1777c478bd9Sstevel@tonic-gate * efficient, the char *arrays of available/unavailable
1787c478bd9Sstevel@tonic-gate * specifications for a request or defaults devconfig_t
1797c478bd9Sstevel@tonic-gate * object are converted to device_spec_ts the first time
1807c478bd9Sstevel@tonic-gate * they're accessed and then cached using this struct:
1817c478bd9Sstevel@tonic-gate */
1827c478bd9Sstevel@tonic-gate typedef struct {
1837c478bd9Sstevel@tonic-gate
1847c478bd9Sstevel@tonic-gate devconfig_t *request;
1857c478bd9Sstevel@tonic-gate
1867c478bd9Sstevel@tonic-gate /*
1877c478bd9Sstevel@tonic-gate * avail_specs_list is a list of device spec_t
1887c478bd9Sstevel@tonic-gate * corresponding to available devices specified
1897c478bd9Sstevel@tonic-gate * in the request object
1907c478bd9Sstevel@tonic-gate */
1917c478bd9Sstevel@tonic-gate dlist_t *avail_specs_list;
1927c478bd9Sstevel@tonic-gate
1937c478bd9Sstevel@tonic-gate /*
1947c478bd9Sstevel@tonic-gate * unavail_specs_list is a list of device spec_t
1957c478bd9Sstevel@tonic-gate * corresponding to unavailable devices specified
1967c478bd9Sstevel@tonic-gate * in the request object
1977c478bd9Sstevel@tonic-gate */
1987c478bd9Sstevel@tonic-gate dlist_t *unavail_specs_list;
1997c478bd9Sstevel@tonic-gate
2007c478bd9Sstevel@tonic-gate } request_spec_list_t;
2017c478bd9Sstevel@tonic-gate
2027c478bd9Sstevel@tonic-gate dlist_t *_request_spec_list_cache = NULL;
2037c478bd9Sstevel@tonic-gate
2047c478bd9Sstevel@tonic-gate static int destroy_request_spec_list_cache();
2057c478bd9Sstevel@tonic-gate static void destroy_request_spec_list_entry(void *obj);
2067c478bd9Sstevel@tonic-gate
2077c478bd9Sstevel@tonic-gate static int compare_request_to_request_spec_list_request(
2087c478bd9Sstevel@tonic-gate void *object,
2097c478bd9Sstevel@tonic-gate void *list_item);
2107c478bd9Sstevel@tonic-gate
2117c478bd9Sstevel@tonic-gate static int convert_usernames_to_specs(
2127c478bd9Sstevel@tonic-gate char **specs,
2137c478bd9Sstevel@tonic-gate dlist_t **list);
2147c478bd9Sstevel@tonic-gate
2157c478bd9Sstevel@tonic-gate /* other private functions */
2167c478bd9Sstevel@tonic-gate static int is_device_avail(
2177c478bd9Sstevel@tonic-gate dm_descriptor_t desc,
2187c478bd9Sstevel@tonic-gate devconfig_t *request,
2197c478bd9Sstevel@tonic-gate boolean_t *avail);
2207c478bd9Sstevel@tonic-gate
2217c478bd9Sstevel@tonic-gate static int is_named_device_avail(
2227c478bd9Sstevel@tonic-gate devconfig_t *request,
2237c478bd9Sstevel@tonic-gate char *device_name,
2247c478bd9Sstevel@tonic-gate boolean_t check_aliases,
2257c478bd9Sstevel@tonic-gate boolean_t *avail);
2267c478bd9Sstevel@tonic-gate
2277c478bd9Sstevel@tonic-gate static int avail_list_includes_device_name(
2287c478bd9Sstevel@tonic-gate dlist_t *list,
2297c478bd9Sstevel@tonic-gate char *device_name,
2307c478bd9Sstevel@tonic-gate boolean_t check_aliases,
2317c478bd9Sstevel@tonic-gate boolean_t *includes);
2327c478bd9Sstevel@tonic-gate
2337c478bd9Sstevel@tonic-gate static int unavail_list_includes_device_name(
2347c478bd9Sstevel@tonic-gate dlist_t *list,
2357c478bd9Sstevel@tonic-gate char *device_name,
2367c478bd9Sstevel@tonic-gate boolean_t check_aliases,
2377c478bd9Sstevel@tonic-gate boolean_t *includes);
2387c478bd9Sstevel@tonic-gate
2397c478bd9Sstevel@tonic-gate static int spec_includes_device_name(
2407c478bd9Sstevel@tonic-gate device_spec_t *spec,
2417c478bd9Sstevel@tonic-gate char *device_name,
2427c478bd9Sstevel@tonic-gate boolean_t check_aliases,
2437c478bd9Sstevel@tonic-gate boolean_t *includes);
2447c478bd9Sstevel@tonic-gate
2457c478bd9Sstevel@tonic-gate static boolean_t spec_includes_device(
2467c478bd9Sstevel@tonic-gate device_spec_t *spec,
2477c478bd9Sstevel@tonic-gate device_spec_t *device);
2487c478bd9Sstevel@tonic-gate
2497c478bd9Sstevel@tonic-gate static int disk_get_avail_space(
2507c478bd9Sstevel@tonic-gate devconfig_t *request,
2517c478bd9Sstevel@tonic-gate dm_descriptor_t disk,
2527c478bd9Sstevel@tonic-gate uint64_t *avail);
2537c478bd9Sstevel@tonic-gate
2547c478bd9Sstevel@tonic-gate static int compare_hba_n_avail_disks(
2557c478bd9Sstevel@tonic-gate void *obj1,
2567c478bd9Sstevel@tonic-gate void *obj2);
2577c478bd9Sstevel@tonic-gate
2587c478bd9Sstevel@tonic-gate /*
2597c478bd9Sstevel@tonic-gate * FUNCTION: release_request_caches()
2607c478bd9Sstevel@tonic-gate *
2617c478bd9Sstevel@tonic-gate * RETURNS: 0
2627c478bd9Sstevel@tonic-gate *
2637c478bd9Sstevel@tonic-gate * PURPOSE: cleanup the module private caches.
2647c478bd9Sstevel@tonic-gate */
2657c478bd9Sstevel@tonic-gate int
release_request_caches()2667c478bd9Sstevel@tonic-gate release_request_caches()
2677c478bd9Sstevel@tonic-gate {
2687c478bd9Sstevel@tonic-gate (void) destroy_request_spec_list_cache();
2697c478bd9Sstevel@tonic-gate (void) destroy_spec_cache();
2707c478bd9Sstevel@tonic-gate
2717c478bd9Sstevel@tonic-gate return (0);
2727c478bd9Sstevel@tonic-gate }
2737c478bd9Sstevel@tonic-gate /*
2747c478bd9Sstevel@tonic-gate * FUNCTION: int set_request_diskset(char *)
2757c478bd9Sstevel@tonic-gate *
2767c478bd9Sstevel@tonic-gate * INPUT: char * - pointer to the diskset name
2777c478bd9Sstevel@tonic-gate * OUTPUT: 0 - success
2787c478bd9Sstevel@tonic-gate * !0 - validation failure
2797c478bd9Sstevel@tonic-gate * RETURNS:
2807c478bd9Sstevel@tonic-gate *
2817c478bd9Sstevel@tonic-gate * PURPOSE: set the module global diskset name.
2827c478bd9Sstevel@tonic-gate */
2837c478bd9Sstevel@tonic-gate int
set_request_diskset(char * dsname)2847c478bd9Sstevel@tonic-gate set_request_diskset(
2857c478bd9Sstevel@tonic-gate char *dsname)
2867c478bd9Sstevel@tonic-gate {
2877c478bd9Sstevel@tonic-gate _request_diskset = dsname;
2887c478bd9Sstevel@tonic-gate
2897c478bd9Sstevel@tonic-gate if (dsname == NULL || dsname[0] == '\0') {
2907c478bd9Sstevel@tonic-gate volume_set_error(
2917c478bd9Sstevel@tonic-gate gettext("No disk set specified in request\n"));
2927c478bd9Sstevel@tonic-gate return (-1);
2937c478bd9Sstevel@tonic-gate }
2947c478bd9Sstevel@tonic-gate
2957c478bd9Sstevel@tonic-gate return (0);
2967c478bd9Sstevel@tonic-gate }
2977c478bd9Sstevel@tonic-gate
2987c478bd9Sstevel@tonic-gate /*
2997c478bd9Sstevel@tonic-gate * FUNCTION: char *get_request_diskset()
3007c478bd9Sstevel@tonic-gate *
3017c478bd9Sstevel@tonic-gate * INPUT: none -
3027c478bd9Sstevel@tonic-gate * OUTPUT: none -
3037c478bd9Sstevel@tonic-gate * RETURNS: char * - pointer to the currently set diskset name
3047c478bd9Sstevel@tonic-gate *
3057c478bd9Sstevel@tonic-gate * PURPOSE: get the global name of the current diskset.
3067c478bd9Sstevel@tonic-gate */
3077c478bd9Sstevel@tonic-gate char *
get_request_diskset()3087c478bd9Sstevel@tonic-gate get_request_diskset()
3097c478bd9Sstevel@tonic-gate {
3107c478bd9Sstevel@tonic-gate return (_request_diskset);
3117c478bd9Sstevel@tonic-gate }
3127c478bd9Sstevel@tonic-gate
3137c478bd9Sstevel@tonic-gate /*
3147c478bd9Sstevel@tonic-gate * FUNCTION: void unset_request_diskset()
3157c478bd9Sstevel@tonic-gate *
3167c478bd9Sstevel@tonic-gate * PURPOSE: unset the module global diskset name.
3177c478bd9Sstevel@tonic-gate */
3187c478bd9Sstevel@tonic-gate void
unset_request_diskset(char * dsname)3197c478bd9Sstevel@tonic-gate unset_request_diskset(
3207c478bd9Sstevel@tonic-gate char *dsname)
3217c478bd9Sstevel@tonic-gate {
3227c478bd9Sstevel@tonic-gate _request_diskset = NULL;
3237c478bd9Sstevel@tonic-gate }
3247c478bd9Sstevel@tonic-gate
3257c478bd9Sstevel@tonic-gate /*
3267c478bd9Sstevel@tonic-gate * FUNCTION: int set_toplevel_request(devconfig_t *)
3277c478bd9Sstevel@tonic-gate *
3287c478bd9Sstevel@tonic-gate * INPUT: devconfig_t * - pointer to the diskset request
3297c478bd9Sstevel@tonic-gate * OUTPUT: 0 - success
3307c478bd9Sstevel@tonic-gate * !0 - validation failure
3317c478bd9Sstevel@tonic-gate * RETURNS:
3327c478bd9Sstevel@tonic-gate *
3337c478bd9Sstevel@tonic-gate * PURPOSE: set the module global toplevel request struct.
3347c478bd9Sstevel@tonic-gate * this will be set within the only public entry
3357c478bd9Sstevel@tonic-gate * point to the module -- get_layout()
3367c478bd9Sstevel@tonic-gate *
3377c478bd9Sstevel@tonic-gate * SIDEEFFECT: The devconfig_t's list of available and unavailable
3387c478bd9Sstevel@tonic-gate * devices will be validated.
3397c478bd9Sstevel@tonic-gate */
3407c478bd9Sstevel@tonic-gate int
set_toplevel_request(devconfig_t * req)3417c478bd9Sstevel@tonic-gate set_toplevel_request(
3427c478bd9Sstevel@tonic-gate devconfig_t *req)
3437c478bd9Sstevel@tonic-gate {
3447c478bd9Sstevel@tonic-gate _toplevel_request = req;
3457c478bd9Sstevel@tonic-gate
3467c478bd9Sstevel@tonic-gate return (validate_request_avail_unavail(req));
3477c478bd9Sstevel@tonic-gate }
3487c478bd9Sstevel@tonic-gate
3497c478bd9Sstevel@tonic-gate /*
3507c478bd9Sstevel@tonic-gate * FUNCTION: void unset_toplevel_request()
3517c478bd9Sstevel@tonic-gate *
3527c478bd9Sstevel@tonic-gate * PURPOSE: unset the layout module global toplevel request struct.
3537c478bd9Sstevel@tonic-gate *
3547c478bd9Sstevel@tonic-gate */
3557c478bd9Sstevel@tonic-gate void
unset_toplevel_request()3567c478bd9Sstevel@tonic-gate unset_toplevel_request()
3577c478bd9Sstevel@tonic-gate {
3587c478bd9Sstevel@tonic-gate _toplevel_request = NULL;
3597c478bd9Sstevel@tonic-gate }
3607c478bd9Sstevel@tonic-gate
3617c478bd9Sstevel@tonic-gate /*
3627c478bd9Sstevel@tonic-gate * FUNCTION: int set_defaults(devconfig_t *)
3637c478bd9Sstevel@tonic-gate *
3647c478bd9Sstevel@tonic-gate * INPUT: devconfig_t * - pointer to the global defaults devconfig_t
3657c478bd9Sstevel@tonic-gate * OUTPUT: 0 - success
3667c478bd9Sstevel@tonic-gate * !0 - validation failure
3677c478bd9Sstevel@tonic-gate * RETURNS:
3687c478bd9Sstevel@tonic-gate *
3697c478bd9Sstevel@tonic-gate * PURPOSE: set the module global defaults struct.
3707c478bd9Sstevel@tonic-gate * this will be set within the only public entry
3717c478bd9Sstevel@tonic-gate * point to the module -- get_layout()
3727c478bd9Sstevel@tonic-gate *
3737c478bd9Sstevel@tonic-gate * SIDEEFFECT: The devconfig_t's list of available and unavailable
3747c478bd9Sstevel@tonic-gate * devices will be validated.
3757c478bd9Sstevel@tonic-gate */
3767c478bd9Sstevel@tonic-gate int
set_request_defaults(defaults_t * defaults)3777c478bd9Sstevel@tonic-gate set_request_defaults(
3787c478bd9Sstevel@tonic-gate defaults_t *defaults)
3797c478bd9Sstevel@tonic-gate {
3807c478bd9Sstevel@tonic-gate int error = 0;
3817c478bd9Sstevel@tonic-gate devconfig_t *diskset = NULL;
3827c478bd9Sstevel@tonic-gate
3837c478bd9Sstevel@tonic-gate _defaults = defaults;
3847c478bd9Sstevel@tonic-gate
3857c478bd9Sstevel@tonic-gate if ((error = defaults_get_diskset_by_name(
3867c478bd9Sstevel@tonic-gate _defaults, get_request_diskset(), &diskset)) == 0) {
3877c478bd9Sstevel@tonic-gate
3887c478bd9Sstevel@tonic-gate error = validate_request_avail_unavail(diskset);
3897c478bd9Sstevel@tonic-gate
3907c478bd9Sstevel@tonic-gate } else if (error == ENOENT) {
3917c478bd9Sstevel@tonic-gate /* no defaults to verify */
3927c478bd9Sstevel@tonic-gate error = 0;
3937c478bd9Sstevel@tonic-gate }
3947c478bd9Sstevel@tonic-gate
3957c478bd9Sstevel@tonic-gate return (error);
3967c478bd9Sstevel@tonic-gate }
3977c478bd9Sstevel@tonic-gate
3987c478bd9Sstevel@tonic-gate /*
3997c478bd9Sstevel@tonic-gate * FUNCTION: void unset_request_defaults()
4007c478bd9Sstevel@tonic-gate *
4017c478bd9Sstevel@tonic-gate * PURPOSE: unset the layout module global defaults struct.
4027c478bd9Sstevel@tonic-gate *
4037c478bd9Sstevel@tonic-gate */
4047c478bd9Sstevel@tonic-gate void
unset_request_defaults()4057c478bd9Sstevel@tonic-gate unset_request_defaults()
4067c478bd9Sstevel@tonic-gate {
4077c478bd9Sstevel@tonic-gate _defaults = NULL;
4087c478bd9Sstevel@tonic-gate }
4097c478bd9Sstevel@tonic-gate
4107c478bd9Sstevel@tonic-gate /*
4117c478bd9Sstevel@tonic-gate * FUNCTION: get_stripe_min_comp(devconfig_t *req, uint16_t *val)
4127c478bd9Sstevel@tonic-gate * INPUT: req - a devconfig_t pointer to the current request
4137c478bd9Sstevel@tonic-gate * val - pointer to a uint64_t to hold the result
4147c478bd9Sstevel@tonic-gate *
4157c478bd9Sstevel@tonic-gate * RETURNS: int - 0 - on success
4167c478bd9Sstevel@tonic-gate * !0 - otherwise
4177c478bd9Sstevel@tonic-gate *
4187c478bd9Sstevel@tonic-gate * PURPOSE: helper which determines the minimum of components
4197c478bd9Sstevel@tonic-gate * for striped volumes satisfying the input request.
4207c478bd9Sstevel@tonic-gate *
4217c478bd9Sstevel@tonic-gate * The value to use is taken from the input request, the
4227c478bd9Sstevel@tonic-gate * toplevel diskset request, the diskset defaults or the
4237c478bd9Sstevel@tonic-gate * global defaults.
4247c478bd9Sstevel@tonic-gate */
4257c478bd9Sstevel@tonic-gate int
get_stripe_min_comp(devconfig_t * req,uint16_t * val)4267c478bd9Sstevel@tonic-gate get_stripe_min_comp(
4277c478bd9Sstevel@tonic-gate devconfig_t *req,
4287c478bd9Sstevel@tonic-gate uint16_t *val)
4297c478bd9Sstevel@tonic-gate {
4307c478bd9Sstevel@tonic-gate int error = 0;
4317c478bd9Sstevel@tonic-gate
4327c478bd9Sstevel@tonic-gate *val = 0;
4337c478bd9Sstevel@tonic-gate
4347c478bd9Sstevel@tonic-gate if ((error = devconfig_get_stripe_mincomp(req, val)) != 0) {
4357c478bd9Sstevel@tonic-gate if (error != ERR_ATTR_UNSET) {
4367c478bd9Sstevel@tonic-gate return (error);
4377c478bd9Sstevel@tonic-gate }
4387c478bd9Sstevel@tonic-gate }
4397c478bd9Sstevel@tonic-gate
4407c478bd9Sstevel@tonic-gate if (*val == 0) {
4417c478bd9Sstevel@tonic-gate if ((error = defaults_get_stripe_mincomp(
4427c478bd9Sstevel@tonic-gate _defaults, get_request_diskset(), val)) != 0) {
4437c478bd9Sstevel@tonic-gate if (error != ERR_ATTR_UNSET) {
4447c478bd9Sstevel@tonic-gate return (error);
4457c478bd9Sstevel@tonic-gate }
4467c478bd9Sstevel@tonic-gate }
4477c478bd9Sstevel@tonic-gate }
4487c478bd9Sstevel@tonic-gate
4497c478bd9Sstevel@tonic-gate return (error);
4507c478bd9Sstevel@tonic-gate }
4517c478bd9Sstevel@tonic-gate
4527c478bd9Sstevel@tonic-gate /*
4537c478bd9Sstevel@tonic-gate * FUNCTION: get_stripe_max_comp(devconfig_t *req, uint16_t *val)
4547c478bd9Sstevel@tonic-gate * INPUT: req - a devconfig_t pointer to the current request
4557c478bd9Sstevel@tonic-gate * val - pointer to a uint64_t to hold the result
4567c478bd9Sstevel@tonic-gate *
4577c478bd9Sstevel@tonic-gate * RETURNS: int - 0 - on success
4587c478bd9Sstevel@tonic-gate * !0 - otherwise
4597c478bd9Sstevel@tonic-gate *
4607c478bd9Sstevel@tonic-gate * PURPOSE: helper which determines the maximum number of components
4617c478bd9Sstevel@tonic-gate * for striped volumes satisfying the input request.
4627c478bd9Sstevel@tonic-gate *
4637c478bd9Sstevel@tonic-gate * The value to use is taken from the input request, the
4647c478bd9Sstevel@tonic-gate * toplevel diskset request, the diskset defaults or the
4657c478bd9Sstevel@tonic-gate * global defaults.
4667c478bd9Sstevel@tonic-gate */
4677c478bd9Sstevel@tonic-gate int
get_stripe_max_comp(devconfig_t * req,uint16_t * val)4687c478bd9Sstevel@tonic-gate get_stripe_max_comp(
4697c478bd9Sstevel@tonic-gate devconfig_t *req,
4707c478bd9Sstevel@tonic-gate uint16_t *val)
4717c478bd9Sstevel@tonic-gate {
4727c478bd9Sstevel@tonic-gate int error = 0;
4737c478bd9Sstevel@tonic-gate
4747c478bd9Sstevel@tonic-gate *val = 0;
4757c478bd9Sstevel@tonic-gate
4767c478bd9Sstevel@tonic-gate if ((error = devconfig_get_stripe_maxcomp(req, val)) != 0) {
4777c478bd9Sstevel@tonic-gate if (error != ERR_ATTR_UNSET) {
4787c478bd9Sstevel@tonic-gate return (error);
4797c478bd9Sstevel@tonic-gate }
4807c478bd9Sstevel@tonic-gate }
4817c478bd9Sstevel@tonic-gate
4827c478bd9Sstevel@tonic-gate if (*val == 0) {
4837c478bd9Sstevel@tonic-gate if ((error = defaults_get_stripe_maxcomp(
4847c478bd9Sstevel@tonic-gate _defaults, get_request_diskset(), val)) != 0) {
4857c478bd9Sstevel@tonic-gate if (error != ERR_ATTR_UNSET) {
4867c478bd9Sstevel@tonic-gate return (error);
4877c478bd9Sstevel@tonic-gate }
4887c478bd9Sstevel@tonic-gate }
4897c478bd9Sstevel@tonic-gate }
4907c478bd9Sstevel@tonic-gate
4917c478bd9Sstevel@tonic-gate return (error);
4927c478bd9Sstevel@tonic-gate }
4937c478bd9Sstevel@tonic-gate
4947c478bd9Sstevel@tonic-gate /*
4957c478bd9Sstevel@tonic-gate * FUNCTION: get_stripe_interlace(devconfig_t *req, uint64_t *val)
4967c478bd9Sstevel@tonic-gate * INPUT: req - a devconfig_t pointer to the current request
4977c478bd9Sstevel@tonic-gate * val - pointer to a uint64_t to hold the result
4987c478bd9Sstevel@tonic-gate *
4997c478bd9Sstevel@tonic-gate * RETURNS: int - 0 - on success
5007c478bd9Sstevel@tonic-gate * !0 - otherwise
5017c478bd9Sstevel@tonic-gate *
5027c478bd9Sstevel@tonic-gate * PURPOSE: helper which determines the interlace value for striped
5037c478bd9Sstevel@tonic-gate * volumes satisfying the input request.
5047c478bd9Sstevel@tonic-gate *
5057c478bd9Sstevel@tonic-gate * The value to use is taken from the input request, the
5067c478bd9Sstevel@tonic-gate * toplevel diskset request, the diskset defaults or the
5077c478bd9Sstevel@tonic-gate * global defaults.
5087c478bd9Sstevel@tonic-gate *
5097c478bd9Sstevel@tonic-gate * If no value is explictly specified, ERR_ATTR_UNSET is
5107c478bd9Sstevel@tonic-gate * returned.
5117c478bd9Sstevel@tonic-gate */
5127c478bd9Sstevel@tonic-gate int
get_stripe_interlace(devconfig_t * req,uint64_t * val)5137c478bd9Sstevel@tonic-gate get_stripe_interlace(
5147c478bd9Sstevel@tonic-gate devconfig_t *req,
5157c478bd9Sstevel@tonic-gate uint64_t *val)
5167c478bd9Sstevel@tonic-gate {
5177c478bd9Sstevel@tonic-gate int error = 0;
5187c478bd9Sstevel@tonic-gate
5197c478bd9Sstevel@tonic-gate *val = 0;
5207c478bd9Sstevel@tonic-gate
5217c478bd9Sstevel@tonic-gate if ((error = devconfig_get_stripe_interlace(req, val)) != 0) {
5227c478bd9Sstevel@tonic-gate if (error != ERR_ATTR_UNSET) {
5237c478bd9Sstevel@tonic-gate return (error);
5247c478bd9Sstevel@tonic-gate }
5257c478bd9Sstevel@tonic-gate error = 0;
5267c478bd9Sstevel@tonic-gate }
5277c478bd9Sstevel@tonic-gate
5287c478bd9Sstevel@tonic-gate if (*val == 0) {
5297c478bd9Sstevel@tonic-gate if ((error = defaults_get_stripe_interlace(
5307c478bd9Sstevel@tonic-gate _defaults, get_request_diskset(), val)) != 0) {
5317c478bd9Sstevel@tonic-gate if (error != ERR_ATTR_UNSET) {
5327c478bd9Sstevel@tonic-gate return (error);
5337c478bd9Sstevel@tonic-gate }
5347c478bd9Sstevel@tonic-gate }
5357c478bd9Sstevel@tonic-gate }
5367c478bd9Sstevel@tonic-gate
5377c478bd9Sstevel@tonic-gate return (error);
5387c478bd9Sstevel@tonic-gate }
5397c478bd9Sstevel@tonic-gate
5407c478bd9Sstevel@tonic-gate /*
5417c478bd9Sstevel@tonic-gate * FUNCTION: get_mirror_read_strategy(devconfig_t *req,
5427c478bd9Sstevel@tonic-gate * mirror_read_strategy_t *val)
5437c478bd9Sstevel@tonic-gate * INPUT: req - a devconfig_t pointer to the current request
5447c478bd9Sstevel@tonic-gate * val - pointer to a mirror_read_strategy_t to hold the result
5457c478bd9Sstevel@tonic-gate *
5467c478bd9Sstevel@tonic-gate * RETURNS: int - 0 - on success
5477c478bd9Sstevel@tonic-gate * !0 - otherwise
5487c478bd9Sstevel@tonic-gate *
5497c478bd9Sstevel@tonic-gate * PURPOSE: helper which determines the write strategy mirrored volumes
5507c478bd9Sstevel@tonic-gate * should have for volumes satisfying the input request.
5517c478bd9Sstevel@tonic-gate *
5527c478bd9Sstevel@tonic-gate * The value to use is taken from the input request, the
5537c478bd9Sstevel@tonic-gate * toplevel diskset request, the diskset defaults or the
5547c478bd9Sstevel@tonic-gate * global defaults.
5557c478bd9Sstevel@tonic-gate *
5567c478bd9Sstevel@tonic-gate * If no value is explictly specified, ERR_ATTR_UNSET is
5577c478bd9Sstevel@tonic-gate * returned.
5587c478bd9Sstevel@tonic-gate */
5597c478bd9Sstevel@tonic-gate int
get_mirror_read_strategy(devconfig_t * req,mirror_read_strategy_t * val)5607c478bd9Sstevel@tonic-gate get_mirror_read_strategy(
5617c478bd9Sstevel@tonic-gate devconfig_t *req,
5627c478bd9Sstevel@tonic-gate mirror_read_strategy_t *val)
5637c478bd9Sstevel@tonic-gate {
5647c478bd9Sstevel@tonic-gate int error = 0;
5657c478bd9Sstevel@tonic-gate
5667c478bd9Sstevel@tonic-gate *val = 0;
5677c478bd9Sstevel@tonic-gate
5687c478bd9Sstevel@tonic-gate if ((error = devconfig_get_mirror_read(req, val)) != 0) {
5697c478bd9Sstevel@tonic-gate if (error != ERR_ATTR_UNSET) {
5707c478bd9Sstevel@tonic-gate return (error);
5717c478bd9Sstevel@tonic-gate }
5727c478bd9Sstevel@tonic-gate }
5737c478bd9Sstevel@tonic-gate
5747c478bd9Sstevel@tonic-gate if (*val == 0) {
5757c478bd9Sstevel@tonic-gate if ((error = defaults_get_mirror_read(
5767c478bd9Sstevel@tonic-gate _defaults, get_request_diskset(), val)) != 0) {
5777c478bd9Sstevel@tonic-gate if (error != ERR_ATTR_UNSET) {
5787c478bd9Sstevel@tonic-gate return (error);
5797c478bd9Sstevel@tonic-gate }
5807c478bd9Sstevel@tonic-gate }
5817c478bd9Sstevel@tonic-gate }
5827c478bd9Sstevel@tonic-gate
5837c478bd9Sstevel@tonic-gate return (error);
5847c478bd9Sstevel@tonic-gate }
5857c478bd9Sstevel@tonic-gate
5867c478bd9Sstevel@tonic-gate /*
5877c478bd9Sstevel@tonic-gate * FUNCTION: get_mirror_write_strategy(devconfig_t *req,
5887c478bd9Sstevel@tonic-gate * mirror_write_strategy_t *val)
5897c478bd9Sstevel@tonic-gate * INPUT: req - a devconfig_t pointer to the current request
5907c478bd9Sstevel@tonic-gate * val - pointer to a mirror_write_strategy_t to hold result
5917c478bd9Sstevel@tonic-gate *
5927c478bd9Sstevel@tonic-gate * RETURNS: int - 0 - on success
5937c478bd9Sstevel@tonic-gate * !0 - otherwise
5947c478bd9Sstevel@tonic-gate *
5957c478bd9Sstevel@tonic-gate * PURPOSE: helper which determines the write strategy mirrored volumes
5967c478bd9Sstevel@tonic-gate * should have for volumes satisfying the input request.
5977c478bd9Sstevel@tonic-gate *
5987c478bd9Sstevel@tonic-gate * The value to use is taken from the input request, the
5997c478bd9Sstevel@tonic-gate * toplevel diskset request, the diskset defaults or the
6007c478bd9Sstevel@tonic-gate * global defaults.
6017c478bd9Sstevel@tonic-gate *
6027c478bd9Sstevel@tonic-gate * If no value is explictly specified, ERR_ATTR_UNSET is
6037c478bd9Sstevel@tonic-gate * returned.
6047c478bd9Sstevel@tonic-gate */
6057c478bd9Sstevel@tonic-gate int
get_mirror_write_strategy(devconfig_t * req,mirror_write_strategy_t * val)6067c478bd9Sstevel@tonic-gate get_mirror_write_strategy(
6077c478bd9Sstevel@tonic-gate devconfig_t *req,
6087c478bd9Sstevel@tonic-gate mirror_write_strategy_t *val)
6097c478bd9Sstevel@tonic-gate {
6107c478bd9Sstevel@tonic-gate int error = 0;
6117c478bd9Sstevel@tonic-gate
6127c478bd9Sstevel@tonic-gate *val = 0;
6137c478bd9Sstevel@tonic-gate
6147c478bd9Sstevel@tonic-gate if ((error = devconfig_get_mirror_write(req, val)) != 0) {
6157c478bd9Sstevel@tonic-gate if (error != ERR_ATTR_UNSET) {
6167c478bd9Sstevel@tonic-gate return (error);
6177c478bd9Sstevel@tonic-gate }
6187c478bd9Sstevel@tonic-gate }
6197c478bd9Sstevel@tonic-gate
6207c478bd9Sstevel@tonic-gate if (*val == 0) {
6217c478bd9Sstevel@tonic-gate if ((error = defaults_get_mirror_write(
6227c478bd9Sstevel@tonic-gate _defaults, get_request_diskset(), val)) != 0) {
6237c478bd9Sstevel@tonic-gate if (error != ERR_ATTR_UNSET) {
6247c478bd9Sstevel@tonic-gate return (error);
6257c478bd9Sstevel@tonic-gate }
6267c478bd9Sstevel@tonic-gate }
6277c478bd9Sstevel@tonic-gate }
6287c478bd9Sstevel@tonic-gate
6297c478bd9Sstevel@tonic-gate return (error);
6307c478bd9Sstevel@tonic-gate }
6317c478bd9Sstevel@tonic-gate
6327c478bd9Sstevel@tonic-gate /*
6337c478bd9Sstevel@tonic-gate * FUNCTION: get_mirror_pass(devconfig_t *req, uint16_t *val)
6347c478bd9Sstevel@tonic-gate * INPUT: req - a devconfig_t pointer to the current request
6357c478bd9Sstevel@tonic-gate * val - pointer to a uint16_t to hold the result
6367c478bd9Sstevel@tonic-gate *
6377c478bd9Sstevel@tonic-gate * RETURNS: int - 0 - on success
6387c478bd9Sstevel@tonic-gate * !0 - otherwise
6397c478bd9Sstevel@tonic-gate *
6407c478bd9Sstevel@tonic-gate * PURPOSE: helper which determines the resync pass mirrored volumes
6417c478bd9Sstevel@tonic-gate * should have for volumes satisfying the input request.
6427c478bd9Sstevel@tonic-gate *
6437c478bd9Sstevel@tonic-gate * The value to use is taken from the input request, the
6447c478bd9Sstevel@tonic-gate * toplevel diskset request, the diskset defaults or the
6457c478bd9Sstevel@tonic-gate * global defaults.
6467c478bd9Sstevel@tonic-gate *
6477c478bd9Sstevel@tonic-gate * If no value is explictly specified, ERR_ATTR_UNSET is
6487c478bd9Sstevel@tonic-gate * returned.
6497c478bd9Sstevel@tonic-gate */
6507c478bd9Sstevel@tonic-gate int
get_mirror_pass(devconfig_t * req,uint16_t * val)6517c478bd9Sstevel@tonic-gate get_mirror_pass(
6527c478bd9Sstevel@tonic-gate devconfig_t *req,
6537c478bd9Sstevel@tonic-gate uint16_t *val)
6547c478bd9Sstevel@tonic-gate {
6557c478bd9Sstevel@tonic-gate int error = 0;
6567c478bd9Sstevel@tonic-gate
6577c478bd9Sstevel@tonic-gate *val = 0;
6587c478bd9Sstevel@tonic-gate
6597c478bd9Sstevel@tonic-gate if ((error = devconfig_get_mirror_pass(req, val)) != 0) {
6607c478bd9Sstevel@tonic-gate if (error != ERR_ATTR_UNSET) {
6617c478bd9Sstevel@tonic-gate return (error);
6627c478bd9Sstevel@tonic-gate }
6637c478bd9Sstevel@tonic-gate }
6647c478bd9Sstevel@tonic-gate
6657c478bd9Sstevel@tonic-gate if (*val == 0) {
6667c478bd9Sstevel@tonic-gate if ((error = defaults_get_mirror_pass(
6677c478bd9Sstevel@tonic-gate _defaults, get_request_diskset(), val)) != 0) {
6687c478bd9Sstevel@tonic-gate if (error != ERR_ATTR_UNSET) {
6697c478bd9Sstevel@tonic-gate return (error);
6707c478bd9Sstevel@tonic-gate }
6717c478bd9Sstevel@tonic-gate }
6727c478bd9Sstevel@tonic-gate }
6737c478bd9Sstevel@tonic-gate
6747c478bd9Sstevel@tonic-gate return (error);
6757c478bd9Sstevel@tonic-gate }
6767c478bd9Sstevel@tonic-gate
6777c478bd9Sstevel@tonic-gate /*
6787c478bd9Sstevel@tonic-gate * FUNCTION: get_mirror_nsubs(devconfig_t *req, uint16_t *val)
6797c478bd9Sstevel@tonic-gate * INPUT: req - a devconfig_t pointer to the current request
6807c478bd9Sstevel@tonic-gate * val - pointer to a uint16_t to hold the result
6817c478bd9Sstevel@tonic-gate *
6827c478bd9Sstevel@tonic-gate * RETURNS: int - 0 - on success
6837c478bd9Sstevel@tonic-gate * !0 - otherwise
6847c478bd9Sstevel@tonic-gate *
6857c478bd9Sstevel@tonic-gate * PURPOSE: helper which determines how many submirrors mirrored
6867c478bd9Sstevel@tonic-gate * volumes should have for volumes satisfying the input
6877c478bd9Sstevel@tonic-gate * request.
6887c478bd9Sstevel@tonic-gate *
6897c478bd9Sstevel@tonic-gate * The value to use is taken from the input request, the
6907c478bd9Sstevel@tonic-gate * toplevel diskset request, the diskset defaults or the
6917c478bd9Sstevel@tonic-gate * global defaults.
6927c478bd9Sstevel@tonic-gate */
6937c478bd9Sstevel@tonic-gate int
get_mirror_nsubs(devconfig_t * req,uint16_t * val)6947c478bd9Sstevel@tonic-gate get_mirror_nsubs(
6957c478bd9Sstevel@tonic-gate devconfig_t *req,
6967c478bd9Sstevel@tonic-gate uint16_t *val)
6977c478bd9Sstevel@tonic-gate {
6987c478bd9Sstevel@tonic-gate int error = 0;
6997c478bd9Sstevel@tonic-gate
7007c478bd9Sstevel@tonic-gate *val = 0;
7017c478bd9Sstevel@tonic-gate
7027c478bd9Sstevel@tonic-gate if ((error = devconfig_get_mirror_nsubs(req, val)) != 0) {
7037c478bd9Sstevel@tonic-gate if (error != ERR_ATTR_UNSET) {
7047c478bd9Sstevel@tonic-gate return (error);
7057c478bd9Sstevel@tonic-gate }
7067c478bd9Sstevel@tonic-gate }
7077c478bd9Sstevel@tonic-gate
7087c478bd9Sstevel@tonic-gate if (*val == 0) {
7097c478bd9Sstevel@tonic-gate if ((error = defaults_get_mirror_nsubs(
7107c478bd9Sstevel@tonic-gate _defaults, get_request_diskset(), val)) != 0) {
7117c478bd9Sstevel@tonic-gate if (error != ERR_ATTR_UNSET) {
7127c478bd9Sstevel@tonic-gate return (error);
7137c478bd9Sstevel@tonic-gate }
7147c478bd9Sstevel@tonic-gate }
7157c478bd9Sstevel@tonic-gate }
7167c478bd9Sstevel@tonic-gate
7177c478bd9Sstevel@tonic-gate return (error);
7187c478bd9Sstevel@tonic-gate }
7197c478bd9Sstevel@tonic-gate
7207c478bd9Sstevel@tonic-gate /*
7217c478bd9Sstevel@tonic-gate * FUNCTION: get_volume_faultrecov(devconfig_t *req, boolean_t *val)
7227c478bd9Sstevel@tonic-gate * INPUT: req - a devconfig_t pointer to the current request
7237c478bd9Sstevel@tonic-gate * val - pointer to a boolean_t to hold the result
7247c478bd9Sstevel@tonic-gate *
7257c478bd9Sstevel@tonic-gate * RETURNS: int - 0 - on success
7267c478bd9Sstevel@tonic-gate * !0 - otherwise
7277c478bd9Sstevel@tonic-gate *
7287c478bd9Sstevel@tonic-gate * PURPOSE: helper which determines whether data redundant volumes
7297c478bd9Sstevel@tonic-gate * should also have fault recovery (e.g., HSPs) for volumes
7307c478bd9Sstevel@tonic-gate * satisfying the input request.
7317c478bd9Sstevel@tonic-gate *
7327c478bd9Sstevel@tonic-gate * The value to use is taken from the input request, the
7337c478bd9Sstevel@tonic-gate * toplevel diskset request, the diskset defaults or the
7347c478bd9Sstevel@tonic-gate * global defaults.
7357c478bd9Sstevel@tonic-gate */
7367c478bd9Sstevel@tonic-gate int
get_volume_faultrecov(devconfig_t * req,boolean_t * val)7377c478bd9Sstevel@tonic-gate get_volume_faultrecov(
7387c478bd9Sstevel@tonic-gate devconfig_t *req,
7397c478bd9Sstevel@tonic-gate boolean_t *val)
7407c478bd9Sstevel@tonic-gate {
7417c478bd9Sstevel@tonic-gate int error = 0;
7427c478bd9Sstevel@tonic-gate
7437c478bd9Sstevel@tonic-gate *val = B_FALSE;
7447c478bd9Sstevel@tonic-gate
7457c478bd9Sstevel@tonic-gate if ((error = devconfig_get_volume_usehsp(req, val)) != 0) {
7467c478bd9Sstevel@tonic-gate if (error == ERR_ATTR_UNSET) {
7477c478bd9Sstevel@tonic-gate component_type_t type = TYPE_UNKNOWN;
7487c478bd9Sstevel@tonic-gate (void) devconfig_get_type(req, &type);
7497c478bd9Sstevel@tonic-gate
7507c478bd9Sstevel@tonic-gate switch (type) {
7517c478bd9Sstevel@tonic-gate case TYPE_MIRROR:
7527c478bd9Sstevel@tonic-gate error = defaults_get_mirror_usehsp(
7537c478bd9Sstevel@tonic-gate _defaults, get_request_diskset(), val);
7547c478bd9Sstevel@tonic-gate break;
7557c478bd9Sstevel@tonic-gate
7567c478bd9Sstevel@tonic-gate case TYPE_STRIPE:
7577c478bd9Sstevel@tonic-gate error = defaults_get_stripe_usehsp(
7587c478bd9Sstevel@tonic-gate _defaults, get_request_diskset(), val);
7597c478bd9Sstevel@tonic-gate break;
7607c478bd9Sstevel@tonic-gate
7617c478bd9Sstevel@tonic-gate case TYPE_CONCAT:
7627c478bd9Sstevel@tonic-gate error = defaults_get_concat_usehsp(
7637c478bd9Sstevel@tonic-gate _defaults, get_request_diskset(), val);
7647c478bd9Sstevel@tonic-gate break;
7657c478bd9Sstevel@tonic-gate
7667c478bd9Sstevel@tonic-gate case TYPE_VOLUME:
7677c478bd9Sstevel@tonic-gate error = defaults_get_volume_usehsp(
7687c478bd9Sstevel@tonic-gate _defaults, get_request_diskset(), val);
7697c478bd9Sstevel@tonic-gate break;
7707c478bd9Sstevel@tonic-gate }
7717c478bd9Sstevel@tonic-gate }
7727c478bd9Sstevel@tonic-gate }
7737c478bd9Sstevel@tonic-gate
7747c478bd9Sstevel@tonic-gate return (error);
7757c478bd9Sstevel@tonic-gate }
7767c478bd9Sstevel@tonic-gate
7777c478bd9Sstevel@tonic-gate /*
7787c478bd9Sstevel@tonic-gate * FUNCTION: get_volume_redundancy_level(devconfig_t *req, uint16_t val)
7797c478bd9Sstevel@tonic-gate * INPUT: req - a devconfig_t pointer to the current request
7807c478bd9Sstevel@tonic-gate * val - pointer to a uint16-t to hold the result
7817c478bd9Sstevel@tonic-gate *
7827c478bd9Sstevel@tonic-gate * RETURNS: int - 0 - on success
7837c478bd9Sstevel@tonic-gate * !0 - otherwise
7847c478bd9Sstevel@tonic-gate *
7857c478bd9Sstevel@tonic-gate * PURPOSE: helper which determines the appropriate level of data
7867c478bd9Sstevel@tonic-gate * redundancy a volume should have for volumes satisfying
7877c478bd9Sstevel@tonic-gate * the input request.
7887c478bd9Sstevel@tonic-gate *
7897c478bd9Sstevel@tonic-gate * The value to use is taken from the input request, the
7907c478bd9Sstevel@tonic-gate * toplevel diskset request, the diskset defaults or the
7917c478bd9Sstevel@tonic-gate * global defaults.
7927c478bd9Sstevel@tonic-gate */
7937c478bd9Sstevel@tonic-gate int
get_volume_redundancy_level(devconfig_t * req,uint16_t * val)7947c478bd9Sstevel@tonic-gate get_volume_redundancy_level(
7957c478bd9Sstevel@tonic-gate devconfig_t *req,
7967c478bd9Sstevel@tonic-gate uint16_t *val)
7977c478bd9Sstevel@tonic-gate {
7987c478bd9Sstevel@tonic-gate int error = 0;
7997c478bd9Sstevel@tonic-gate
8007c478bd9Sstevel@tonic-gate *val = 0;
8017c478bd9Sstevel@tonic-gate
8027c478bd9Sstevel@tonic-gate if ((error = devconfig_get_volume_redundancy_level(req, val)) != 0) {
8037c478bd9Sstevel@tonic-gate if (error != ERR_ATTR_UNSET) {
8047c478bd9Sstevel@tonic-gate return (error);
8057c478bd9Sstevel@tonic-gate }
8067c478bd9Sstevel@tonic-gate }
8077c478bd9Sstevel@tonic-gate
8087c478bd9Sstevel@tonic-gate if (*val == 0) {
8097c478bd9Sstevel@tonic-gate if ((error = defaults_get_volume_redundancy_level(
8107c478bd9Sstevel@tonic-gate _defaults, get_request_diskset(), val)) != 0) {
8117c478bd9Sstevel@tonic-gate if (error != ERR_ATTR_UNSET) {
8127c478bd9Sstevel@tonic-gate return (error);
8137c478bd9Sstevel@tonic-gate }
8147c478bd9Sstevel@tonic-gate }
8157c478bd9Sstevel@tonic-gate }
8167c478bd9Sstevel@tonic-gate
8177c478bd9Sstevel@tonic-gate return (error);
8187c478bd9Sstevel@tonic-gate }
8197c478bd9Sstevel@tonic-gate
8207c478bd9Sstevel@tonic-gate /*
8217c478bd9Sstevel@tonic-gate * FUNCTION: get_volume_npaths(devconfig_t *req, uint16_t val)
8227c478bd9Sstevel@tonic-gate * INPUT: req - a devconfig_t pointer to the current request
8237c478bd9Sstevel@tonic-gate * val - pointer to a uint16-t to hold the result
8247c478bd9Sstevel@tonic-gate *
8257c478bd9Sstevel@tonic-gate * RETURNS: int - 0 - on success
8267c478bd9Sstevel@tonic-gate * !0 - otherwise
8277c478bd9Sstevel@tonic-gate *
8287c478bd9Sstevel@tonic-gate * PURPOSE: helper which determines the appropriate level of datapath
8297c478bd9Sstevel@tonic-gate * redundancy a slice component should have for volumes
8307c478bd9Sstevel@tonic-gate * satisfying the input request.
8317c478bd9Sstevel@tonic-gate *
8327c478bd9Sstevel@tonic-gate * The value to use is taken from the input request, the
8337c478bd9Sstevel@tonic-gate * toplevel diskset request, the diskset defaults or the
8347c478bd9Sstevel@tonic-gate * global defaults.
8357c478bd9Sstevel@tonic-gate */
8367c478bd9Sstevel@tonic-gate int
get_volume_npaths(devconfig_t * req,uint16_t * val)8377c478bd9Sstevel@tonic-gate get_volume_npaths(
8387c478bd9Sstevel@tonic-gate devconfig_t *req,
8397c478bd9Sstevel@tonic-gate uint16_t *val)
8407c478bd9Sstevel@tonic-gate {
8417c478bd9Sstevel@tonic-gate int error = 0;
8427c478bd9Sstevel@tonic-gate
8437c478bd9Sstevel@tonic-gate *val = 0;
8447c478bd9Sstevel@tonic-gate
8457c478bd9Sstevel@tonic-gate if ((error = devconfig_get_volume_npaths(req, val)) != 0) {
8467c478bd9Sstevel@tonic-gate if (error != ERR_ATTR_UNSET) {
8477c478bd9Sstevel@tonic-gate return (error);
8487c478bd9Sstevel@tonic-gate }
8497c478bd9Sstevel@tonic-gate }
8507c478bd9Sstevel@tonic-gate
8517c478bd9Sstevel@tonic-gate if (*val == 0) {
8527c478bd9Sstevel@tonic-gate if ((error = defaults_get_volume_npaths(
8537c478bd9Sstevel@tonic-gate _defaults, get_request_diskset(), val)) != 0) {
8547c478bd9Sstevel@tonic-gate if (error != ERR_ATTR_UNSET) {
8557c478bd9Sstevel@tonic-gate return (error);
8567c478bd9Sstevel@tonic-gate }
8577c478bd9Sstevel@tonic-gate }
8587c478bd9Sstevel@tonic-gate }
8597c478bd9Sstevel@tonic-gate
8607c478bd9Sstevel@tonic-gate return (error);
8617c478bd9Sstevel@tonic-gate }
8627c478bd9Sstevel@tonic-gate
8637c478bd9Sstevel@tonic-gate /*
8647c478bd9Sstevel@tonic-gate * FUNCTION: get_default_hsp_name(devconfig_t *req, char **hspname)
8657c478bd9Sstevel@tonic-gate * INPUT: req - a devconfig_t pointer to the current request
8667c478bd9Sstevel@tonic-gate * hspname - pointer to a char * to hold the result, if any
8677c478bd9Sstevel@tonic-gate *
8687c478bd9Sstevel@tonic-gate * RETURNS: int - 0 - on success
8697c478bd9Sstevel@tonic-gate * !0 - otherwise
8707c478bd9Sstevel@tonic-gate *
8717c478bd9Sstevel@tonic-gate * PURPOSE: helper which determines the default HSP name for the
8727c478bd9Sstevel@tonic-gate * input request.
8737c478bd9Sstevel@tonic-gate *
8747c478bd9Sstevel@tonic-gate * The value to use is taken from the input request, the
8757c478bd9Sstevel@tonic-gate * toplevel diskset request, the diskset defaults or the
8767c478bd9Sstevel@tonic-gate * global defaults.
8777c478bd9Sstevel@tonic-gate */
8787c478bd9Sstevel@tonic-gate int
get_default_hsp_name(devconfig_t * req,char ** name)8797c478bd9Sstevel@tonic-gate get_default_hsp_name(
8807c478bd9Sstevel@tonic-gate devconfig_t *req,
8817c478bd9Sstevel@tonic-gate char **name)
8827c478bd9Sstevel@tonic-gate {
8837c478bd9Sstevel@tonic-gate int error = 0;
8847c478bd9Sstevel@tonic-gate
8857c478bd9Sstevel@tonic-gate *name = NULL;
8867c478bd9Sstevel@tonic-gate
8877c478bd9Sstevel@tonic-gate if ((error = defaults_get_hsp_name(_defaults,
8887c478bd9Sstevel@tonic-gate get_request_diskset(), name)) != 0) {
8897c478bd9Sstevel@tonic-gate if (error != ENOENT) {
8907c478bd9Sstevel@tonic-gate return (error);
8917c478bd9Sstevel@tonic-gate }
8927c478bd9Sstevel@tonic-gate error = 0;
8937c478bd9Sstevel@tonic-gate }
8947c478bd9Sstevel@tonic-gate
8957c478bd9Sstevel@tonic-gate return (error);
8967c478bd9Sstevel@tonic-gate }
8977c478bd9Sstevel@tonic-gate
8987c478bd9Sstevel@tonic-gate /*
8997c478bd9Sstevel@tonic-gate * FUNCTION: slice_is_available(char *sname, devconfig_t *request,
9007c478bd9Sstevel@tonic-gate * boolean_t bool)
9017c478bd9Sstevel@tonic-gate * INPUT: sname - a slice name
9027c478bd9Sstevel@tonic-gate * request - pointer to a devconfig_t struct representing
9037c478bd9Sstevel@tonic-gate * the current layout request being processed
9047c478bd9Sstevel@tonic-gate * bool - pointer to a boolean to hold the result
9057c478bd9Sstevel@tonic-gate *
9067c478bd9Sstevel@tonic-gate * RETURNS: int - 0 - on success
9077c478bd9Sstevel@tonic-gate * !0 - otherwise
9087c478bd9Sstevel@tonic-gate *
9097c478bd9Sstevel@tonic-gate * PURPOSE: Validation helper which determines if the named slice can
9107c478bd9Sstevel@tonic-gate * be used as a volume component when satisfying the input
9117c478bd9Sstevel@tonic-gate * request.
9127c478bd9Sstevel@tonic-gate *
9137c478bd9Sstevel@tonic-gate * Check if the slice appears in the known slice list,
9147c478bd9Sstevel@tonic-gate * then check the request's available and unavailable
9157c478bd9Sstevel@tonic-gate * device specifications.
9167c478bd9Sstevel@tonic-gate */
9177c478bd9Sstevel@tonic-gate int
slice_is_available(char * sname,devconfig_t * request,boolean_t * bool)9187c478bd9Sstevel@tonic-gate slice_is_available(
9197c478bd9Sstevel@tonic-gate char *sname,
9207c478bd9Sstevel@tonic-gate devconfig_t *request,
9217c478bd9Sstevel@tonic-gate boolean_t *bool)
9227c478bd9Sstevel@tonic-gate {
9237c478bd9Sstevel@tonic-gate dm_descriptor_t slice = (dm_descriptor_t)0;
9247c478bd9Sstevel@tonic-gate int error = 0;
9257c478bd9Sstevel@tonic-gate
9267c478bd9Sstevel@tonic-gate *bool = B_FALSE;
9277c478bd9Sstevel@tonic-gate
9287c478bd9Sstevel@tonic-gate if ((error = slice_get_by_name(sname, &slice)) != 0) {
9297c478bd9Sstevel@tonic-gate return (error);
9307c478bd9Sstevel@tonic-gate }
9317c478bd9Sstevel@tonic-gate
9327c478bd9Sstevel@tonic-gate if (slice == (dm_descriptor_t)0) {
9337c478bd9Sstevel@tonic-gate /* no slice found */
9347c478bd9Sstevel@tonic-gate return (ENODEV);
9357c478bd9Sstevel@tonic-gate }
9367c478bd9Sstevel@tonic-gate
9377c478bd9Sstevel@tonic-gate if (error == 0) {
9387c478bd9Sstevel@tonic-gate error = is_named_device_avail(request, sname, B_TRUE, bool);
9397c478bd9Sstevel@tonic-gate }
9407c478bd9Sstevel@tonic-gate
9417c478bd9Sstevel@tonic-gate return (error);
9427c478bd9Sstevel@tonic-gate }
9437c478bd9Sstevel@tonic-gate
9447c478bd9Sstevel@tonic-gate /*
9457c478bd9Sstevel@tonic-gate * FUNCTION: get_disks_for_target(char *name, dlist_t **disks)
9467c478bd9Sstevel@tonic-gate *
9477c478bd9Sstevel@tonic-gate * INPUT: name - a char* device CTD name
9487c478bd9Sstevel@tonic-gate *
9497c478bd9Sstevel@tonic-gate * OUTPUT: disks - disks matching the input target name
9507c478bd9Sstevel@tonic-gate *
9517c478bd9Sstevel@tonic-gate * RETURNS: int - 0 on success
9527c478bd9Sstevel@tonic-gate * !0 otherwise
9537c478bd9Sstevel@tonic-gate *
9547c478bd9Sstevel@tonic-gate * PURPOSE: Validation helper function which finds all disks "on" the
9557c478bd9Sstevel@tonic-gate * input target.
9567c478bd9Sstevel@tonic-gate *
9577c478bd9Sstevel@tonic-gate * The input name is assumed to be a target name, cXtX, and
9587c478bd9Sstevel@tonic-gate * the list of known disks is searched to find any disk that
9597c478bd9Sstevel@tonic-gate * looks to be "on" that target.
9607c478bd9Sstevel@tonic-gate *
9617c478bd9Sstevel@tonic-gate * "On" is determined by comparing a disk's name and
9627c478bd9Sstevel@tonic-gate * aliases to the target to see if they match.
9637c478bd9Sstevel@tonic-gate */
9647c478bd9Sstevel@tonic-gate int
get_disks_for_target(char * name,dlist_t ** disks)9657c478bd9Sstevel@tonic-gate get_disks_for_target(
9667c478bd9Sstevel@tonic-gate char *name,
9677c478bd9Sstevel@tonic-gate dlist_t **disks)
9687c478bd9Sstevel@tonic-gate {
9697c478bd9Sstevel@tonic-gate int error = 0;
9707c478bd9Sstevel@tonic-gate device_spec_t *targetid = NULL;
9717c478bd9Sstevel@tonic-gate
9727c478bd9Sstevel@tonic-gate error = get_spec_for_name(name, &targetid);
9737c478bd9Sstevel@tonic-gate if (error == 0) {
9747c478bd9Sstevel@tonic-gate dlist_t *known_disks = NULL;
9757c478bd9Sstevel@tonic-gate dlist_t *iter = NULL;
9767c478bd9Sstevel@tonic-gate
9777c478bd9Sstevel@tonic-gate get_known_disks(&known_disks);
9787c478bd9Sstevel@tonic-gate for (iter = known_disks;
9797c478bd9Sstevel@tonic-gate (iter != NULL) && (error == 0);
9807c478bd9Sstevel@tonic-gate iter = iter->next) {
9817c478bd9Sstevel@tonic-gate
9827c478bd9Sstevel@tonic-gate dm_descriptor_t disk = (uintptr_t)iter->obj;
9837c478bd9Sstevel@tonic-gate device_spec_t *diskid = NULL;
9847c478bd9Sstevel@tonic-gate char *diskname = NULL;
9857c478bd9Sstevel@tonic-gate dlist_t *diskaliases = NULL;
9867c478bd9Sstevel@tonic-gate dlist_t *item;
9877c478bd9Sstevel@tonic-gate
9887c478bd9Sstevel@tonic-gate ((error = get_display_name(disk, &diskname)) != 0) ||
9897c478bd9Sstevel@tonic-gate (error = get_aliases(disk, &diskaliases)) ||
9907c478bd9Sstevel@tonic-gate (error = get_spec_for_name(diskname, &diskid));
9917c478bd9Sstevel@tonic-gate
9927c478bd9Sstevel@tonic-gate if (error == 0) {
9937c478bd9Sstevel@tonic-gate if (spec_includes_device(targetid, diskid) == B_TRUE) {
9947c478bd9Sstevel@tonic-gate /* add disk */
995*b6c8bd52Sjeanm if ((item = dlist_new_item((void *)(uintptr_t)disk)) ==
996*b6c8bd52Sjeanm NULL) {
9977c478bd9Sstevel@tonic-gate error = ENOMEM;
9987c478bd9Sstevel@tonic-gate } else {
9997c478bd9Sstevel@tonic-gate *disks = dlist_append(item, *disks, AT_HEAD);
10007c478bd9Sstevel@tonic-gate }
10017c478bd9Sstevel@tonic-gate } else {
10027c478bd9Sstevel@tonic-gate /* check disk's aliases */
10037c478bd9Sstevel@tonic-gate dlist_t *iter2;
10047c478bd9Sstevel@tonic-gate for (iter2 = diskaliases;
10057c478bd9Sstevel@tonic-gate (iter2 != NULL) && (error == 0);
10067c478bd9Sstevel@tonic-gate iter2 = iter2->next) {
10077c478bd9Sstevel@tonic-gate
10087c478bd9Sstevel@tonic-gate char *aliasname = NULL;
10097c478bd9Sstevel@tonic-gate device_spec_t *aliasid = NULL;
10107c478bd9Sstevel@tonic-gate error = get_display_name(disk, &aliasname);
10117c478bd9Sstevel@tonic-gate error = get_spec_for_name(aliasname, &aliasid);
10127c478bd9Sstevel@tonic-gate
10137c478bd9Sstevel@tonic-gate if (spec_includes_device(
10147c478bd9Sstevel@tonic-gate targetid, aliasid) == B_TRUE) {
10157c478bd9Sstevel@tonic-gate
10167c478bd9Sstevel@tonic-gate /* alias matched, add disk */
1017*b6c8bd52Sjeanm item = dlist_new_item((void *)(uintptr_t)disk);
10187c478bd9Sstevel@tonic-gate if (item == NULL) {
10197c478bd9Sstevel@tonic-gate error = ENOMEM;
10207c478bd9Sstevel@tonic-gate } else {
10217c478bd9Sstevel@tonic-gate *disks =
10227c478bd9Sstevel@tonic-gate dlist_append(item, *disks, AT_HEAD);
10237c478bd9Sstevel@tonic-gate }
10247c478bd9Sstevel@tonic-gate }
10257c478bd9Sstevel@tonic-gate }
10267c478bd9Sstevel@tonic-gate }
10277c478bd9Sstevel@tonic-gate }
10287c478bd9Sstevel@tonic-gate }
10297c478bd9Sstevel@tonic-gate }
10307c478bd9Sstevel@tonic-gate
10317c478bd9Sstevel@tonic-gate return (error);
10327c478bd9Sstevel@tonic-gate }
10337c478bd9Sstevel@tonic-gate
10347c478bd9Sstevel@tonic-gate /*
10357c478bd9Sstevel@tonic-gate * FUNCTION: select_hbas_with_n_disks(devconfig_t *request,
10367c478bd9Sstevel@tonic-gate * dlist_t *hbas, int mindisks, dlist_t **selhbas,
10377c478bd9Sstevel@tonic-gate * dlist_t **seldisks)
10387c478bd9Sstevel@tonic-gate *
10397c478bd9Sstevel@tonic-gate * INPUT: request - pointer to a devconfig_t struct representing
10407c478bd9Sstevel@tonic-gate * the current layout request being processed
10417c478bd9Sstevel@tonic-gate * hbas - pointer to a list of HBAs
10427c478bd9Sstevel@tonic-gate * mindisks - minimum number of disks required on the HBAs
10437c478bd9Sstevel@tonic-gate *
10447c478bd9Sstevel@tonic-gate * OUTPUT: selhbas - pointer to a list containing the HBAs with at
10457c478bd9Sstevel@tonic-gate * least mindisks available disks.
10467c478bd9Sstevel@tonic-gate * seldisks - pointer to a list containing the available disks
10477c478bd9Sstevel@tonic-gate * for the HBAs in selhbas
10487c478bd9Sstevel@tonic-gate *
10497c478bd9Sstevel@tonic-gate * RETURNS: int - 0 - on success
10507c478bd9Sstevel@tonic-gate * !0 - otherwise
10517c478bd9Sstevel@tonic-gate *
10527c478bd9Sstevel@tonic-gate * PURPOSE: helper which counts the number of available disks associated
10537c478bd9Sstevel@tonic-gate * with each of the input HBAs and adds those that have at
10547c478bd9Sstevel@tonic-gate * least mindisks to the output list.
10557c478bd9Sstevel@tonic-gate *
10567c478bd9Sstevel@tonic-gate * Only available disks that have available space are counted.
10577c478bd9Sstevel@tonic-gate *
10587c478bd9Sstevel@tonic-gate * Disks connected thru multiple HBAs are only counted for
10597c478bd9Sstevel@tonic-gate * the first HBA they're accessed through.
10607c478bd9Sstevel@tonic-gate *
10617c478bd9Sstevel@tonic-gate * The list of HBAs returned will be in descending order,
10627c478bd9Sstevel@tonic-gate * i.e., HBAs with more disks come before those with fewer.
10637c478bd9Sstevel@tonic-gate *
10647c478bd9Sstevel@tonic-gate * The returned lists of HBAs and disks must be passed to
10657c478bd9Sstevel@tonic-gate * dlist_free_items() to recover the space allocated to hold
10667c478bd9Sstevel@tonic-gate * each list item.
10677c478bd9Sstevel@tonic-gate *
10687c478bd9Sstevel@tonic-gate * for (each HBA) {
10697c478bd9Sstevel@tonic-gate *
10707c478bd9Sstevel@tonic-gate * select HBA
10717c478bd9Sstevel@tonic-gate * get available disks on HBA
10727c478bd9Sstevel@tonic-gate *
10737c478bd9Sstevel@tonic-gate * for (each disk) {
10747c478bd9Sstevel@tonic-gate * if (disk is not in selected disk list)
10757c478bd9Sstevel@tonic-gate * add it to the list
10767c478bd9Sstevel@tonic-gate * else
10777c478bd9Sstevel@tonic-gate * count it as a distinct disk on this HBA
10787c478bd9Sstevel@tonic-gate * }
10797c478bd9Sstevel@tonic-gate *
10807c478bd9Sstevel@tonic-gate * if (this HBA has >= mindisks distinct disks)
10817c478bd9Sstevel@tonic-gate * add this HBA to the list of returned HBAs
10827c478bd9Sstevel@tonic-gate *
10837c478bd9Sstevel@tonic-gate * }
10847c478bd9Sstevel@tonic-gate */
10857c478bd9Sstevel@tonic-gate int
select_hbas_with_n_disks(devconfig_t * request,dlist_t * hbas,int mindisks,dlist_t ** selhbas,dlist_t ** seldisks)10867c478bd9Sstevel@tonic-gate select_hbas_with_n_disks(
10877c478bd9Sstevel@tonic-gate devconfig_t *request,
10887c478bd9Sstevel@tonic-gate dlist_t *hbas,
10897c478bd9Sstevel@tonic-gate int mindisks,
10907c478bd9Sstevel@tonic-gate dlist_t **selhbas,
10917c478bd9Sstevel@tonic-gate dlist_t **seldisks)
10927c478bd9Sstevel@tonic-gate {
10937c478bd9Sstevel@tonic-gate dlist_t *iter = NULL;
10947c478bd9Sstevel@tonic-gate int error = 0;
10957c478bd9Sstevel@tonic-gate
10967c478bd9Sstevel@tonic-gate *selhbas = NULL;
10977c478bd9Sstevel@tonic-gate *seldisks = NULL;
10987c478bd9Sstevel@tonic-gate
10997c478bd9Sstevel@tonic-gate /* for each input HBA */
11007c478bd9Sstevel@tonic-gate for (iter = hbas; (error == 0) && (iter != NULL); iter = iter->next) {
11017c478bd9Sstevel@tonic-gate
11027c478bd9Sstevel@tonic-gate dm_descriptor_t hba = (uintptr_t)iter->obj;
11037c478bd9Sstevel@tonic-gate dlist_t *iter2 = NULL;
11047c478bd9Sstevel@tonic-gate dlist_t *disks = NULL;
11057c478bd9Sstevel@tonic-gate uint64_t space = 0;
11067c478bd9Sstevel@tonic-gate uint16_t ndistinct = 0;
11077c478bd9Sstevel@tonic-gate
11087c478bd9Sstevel@tonic-gate error = hba_get_avail_disks_and_space(request, hba, &disks, &space);
11097c478bd9Sstevel@tonic-gate
11107c478bd9Sstevel@tonic-gate /* for each of this HBA's disks */
11117c478bd9Sstevel@tonic-gate for (iter2 = disks;
11127c478bd9Sstevel@tonic-gate (iter2 != NULL) && (error == 0);
11137c478bd9Sstevel@tonic-gate iter2 = iter2->next) {
11147c478bd9Sstevel@tonic-gate
11157c478bd9Sstevel@tonic-gate dm_descriptor_t disk = (uintptr_t)iter2->obj;
11167c478bd9Sstevel@tonic-gate
11177c478bd9Sstevel@tonic-gate /* unique disk? has it been seen thru some other HBA? */
1118*b6c8bd52Sjeanm if (dlist_contains(*seldisks, (void *)(uintptr_t)disk,
11197c478bd9Sstevel@tonic-gate compare_descriptor_names) != B_TRUE) {
11207c478bd9Sstevel@tonic-gate
11217c478bd9Sstevel@tonic-gate /* distinct, add to list of all_distinct */
1122*b6c8bd52Sjeanm dlist_t *item = dlist_new_item((void *)(uintptr_t)disk);
11237c478bd9Sstevel@tonic-gate if (item == NULL) {
11247c478bd9Sstevel@tonic-gate error = ENOMEM;
11257c478bd9Sstevel@tonic-gate } else {
11267c478bd9Sstevel@tonic-gate
11277c478bd9Sstevel@tonic-gate *seldisks =
11287c478bd9Sstevel@tonic-gate dlist_append(item, *seldisks, AT_HEAD);
11297c478bd9Sstevel@tonic-gate
11307c478bd9Sstevel@tonic-gate /* increment this HBA's distinct disk count */
11317c478bd9Sstevel@tonic-gate ++ndistinct;
11327c478bd9Sstevel@tonic-gate }
11337c478bd9Sstevel@tonic-gate }
11347c478bd9Sstevel@tonic-gate }
11357c478bd9Sstevel@tonic-gate
11367c478bd9Sstevel@tonic-gate if (ndistinct >= mindisks) {
11377c478bd9Sstevel@tonic-gate
11387c478bd9Sstevel@tonic-gate /* this HBA has minimum # of disks, add to output list */
1139*b6c8bd52Sjeanm dlist_t *item = dlist_new_item((void *)(uintptr_t)hba);
11407c478bd9Sstevel@tonic-gate if (item == NULL) {
11417c478bd9Sstevel@tonic-gate error = ENOMEM;
11427c478bd9Sstevel@tonic-gate } else {
11437c478bd9Sstevel@tonic-gate *selhbas =
11447c478bd9Sstevel@tonic-gate dlist_insert_ordered(
11457c478bd9Sstevel@tonic-gate item, *selhbas, DESCENDING,
11467c478bd9Sstevel@tonic-gate compare_hba_n_avail_disks);
11477c478bd9Sstevel@tonic-gate
11487c478bd9Sstevel@tonic-gate /* save # of disks for ordering the list */
11497c478bd9Sstevel@tonic-gate hba_set_n_avail_disks(hba, ndistinct);
11507c478bd9Sstevel@tonic-gate }
11517c478bd9Sstevel@tonic-gate }
11527c478bd9Sstevel@tonic-gate
11537c478bd9Sstevel@tonic-gate dlist_free_items(disks, NULL);
11547c478bd9Sstevel@tonic-gate }
11557c478bd9Sstevel@tonic-gate
11567c478bd9Sstevel@tonic-gate if (error != 0) {
11577c478bd9Sstevel@tonic-gate oprintf(OUTPUT_TERSE,
11587c478bd9Sstevel@tonic-gate gettext("failed selecting HBAs with n disks: %d\n"),
11597c478bd9Sstevel@tonic-gate error);
11607c478bd9Sstevel@tonic-gate
11617c478bd9Sstevel@tonic-gate dlist_free_items(*selhbas, NULL);
11627c478bd9Sstevel@tonic-gate *selhbas = NULL;
11637c478bd9Sstevel@tonic-gate dlist_free_items(*seldisks, NULL);
11647c478bd9Sstevel@tonic-gate *seldisks = NULL;
11657c478bd9Sstevel@tonic-gate }
11667c478bd9Sstevel@tonic-gate
11677c478bd9Sstevel@tonic-gate return (error);
11687c478bd9Sstevel@tonic-gate }
11697c478bd9Sstevel@tonic-gate
11707c478bd9Sstevel@tonic-gate /*
11717c478bd9Sstevel@tonic-gate * FUNCTION: hba_get_avail_disks_and_space(devconfig_t *request,
11727c478bd9Sstevel@tonic-gate * dm_descriptor_t hba, dlist_t **disks, uint64_t *space)
11737c478bd9Sstevel@tonic-gate *
11747c478bd9Sstevel@tonic-gate * INPUT: request - pointer to a devconfig_t struct representing
11757c478bd9Sstevel@tonic-gate * the current layout request being processed
11767c478bd9Sstevel@tonic-gate * hba - dm_descriptor_t handle for an HBA
11777c478bd9Sstevel@tonic-gate *
11787c478bd9Sstevel@tonic-gate * OUTPUT: disks - pointer to a list to hold the computed available
11797c478bd9Sstevel@tonic-gate * disks
11807c478bd9Sstevel@tonic-gate * avail - pointer to a uint64_t to hold the aggregate
11817c478bd9Sstevel@tonic-gate * available space on the available disks
11827c478bd9Sstevel@tonic-gate *
11837c478bd9Sstevel@tonic-gate * RETURNS: int - 0 - on success
11847c478bd9Sstevel@tonic-gate * !0 - otherwise
11857c478bd9Sstevel@tonic-gate *
11867c478bd9Sstevel@tonic-gate * PURPOSE: helper which examines the disks associated with the
11877c478bd9Sstevel@tonic-gate * input HBA and assembles a list of those that are available.
11887c478bd9Sstevel@tonic-gate *
11897c478bd9Sstevel@tonic-gate * Available is defined as being in the usable list, having
11907c478bd9Sstevel@tonic-gate * unused space and not specifically excluded by the request's
11917c478bd9Sstevel@tonic-gate * list of unavailable devices.
11927c478bd9Sstevel@tonic-gate *
11937c478bd9Sstevel@tonic-gate * The returned list must be passed to dlist_free_items()
11947c478bd9Sstevel@tonic-gate * to recover the memory allocated to hold each list item.
11957c478bd9Sstevel@tonic-gate */
11967c478bd9Sstevel@tonic-gate int
hba_get_avail_disks_and_space(devconfig_t * request,dm_descriptor_t hba,dlist_t ** disks,uint64_t * space)11977c478bd9Sstevel@tonic-gate hba_get_avail_disks_and_space(
11987c478bd9Sstevel@tonic-gate devconfig_t *request,
11997c478bd9Sstevel@tonic-gate dm_descriptor_t hba,
12007c478bd9Sstevel@tonic-gate dlist_t **disks,
12017c478bd9Sstevel@tonic-gate uint64_t *space)
12027c478bd9Sstevel@tonic-gate {
12037c478bd9Sstevel@tonic-gate dlist_t *usable_disks = NULL;
12047c478bd9Sstevel@tonic-gate dlist_t *iter = NULL;
12057c478bd9Sstevel@tonic-gate int error = 0;
12067c478bd9Sstevel@tonic-gate
12077c478bd9Sstevel@tonic-gate *disks = NULL;
12087c478bd9Sstevel@tonic-gate
12097c478bd9Sstevel@tonic-gate /* for each usable disk */
12107c478bd9Sstevel@tonic-gate error = get_usable_disks(&usable_disks);
12117c478bd9Sstevel@tonic-gate for (iter = usable_disks;
12127c478bd9Sstevel@tonic-gate (error == 0) && (iter != NULL);
12137c478bd9Sstevel@tonic-gate iter = iter->next) {
12147c478bd9Sstevel@tonic-gate
12157c478bd9Sstevel@tonic-gate dm_descriptor_t disk = (uintptr_t)iter->obj;
12167c478bd9Sstevel@tonic-gate boolean_t avail = B_FALSE;
12177c478bd9Sstevel@tonic-gate dlist_t *hbas = NULL;
12187c478bd9Sstevel@tonic-gate
12197c478bd9Sstevel@tonic-gate /* is disk attached to HBA in question? */
12207c478bd9Sstevel@tonic-gate error = disk_get_hbas(disk, &hbas);
12217c478bd9Sstevel@tonic-gate if (error != 0) {
12227c478bd9Sstevel@tonic-gate continue;
12237c478bd9Sstevel@tonic-gate }
12247c478bd9Sstevel@tonic-gate
1225*b6c8bd52Sjeanm if (dlist_contains(hbas, (void *)(uintptr_t)hba,
12267c478bd9Sstevel@tonic-gate compare_descriptor_names) == B_TRUE) {
12277c478bd9Sstevel@tonic-gate
12287c478bd9Sstevel@tonic-gate /* is disk available? */
12297c478bd9Sstevel@tonic-gate error = is_device_avail(disk, request, &avail);
12307c478bd9Sstevel@tonic-gate if ((error == 0) && (avail == B_TRUE)) {
12317c478bd9Sstevel@tonic-gate uint64_t disk_space = 0;
12327c478bd9Sstevel@tonic-gate
12337c478bd9Sstevel@tonic-gate /* does disk have available space? */
12347c478bd9Sstevel@tonic-gate error = disk_get_avail_space(request, disk, &disk_space);
12357c478bd9Sstevel@tonic-gate if ((error == 0) && (disk_space > 0)) {
12367c478bd9Sstevel@tonic-gate
1237*b6c8bd52Sjeanm dlist_t *item = dlist_new_item((void *)(uintptr_t)disk);
12387c478bd9Sstevel@tonic-gate if (item == NULL) {
12397c478bd9Sstevel@tonic-gate error = ENOMEM;
12407c478bd9Sstevel@tonic-gate } else {
12417c478bd9Sstevel@tonic-gate *disks = dlist_append(item, *disks, AT_HEAD);
12427c478bd9Sstevel@tonic-gate }
12437c478bd9Sstevel@tonic-gate
12447c478bd9Sstevel@tonic-gate *space += disk_space;
12457c478bd9Sstevel@tonic-gate }
12467c478bd9Sstevel@tonic-gate }
12477c478bd9Sstevel@tonic-gate }
12487c478bd9Sstevel@tonic-gate
12497c478bd9Sstevel@tonic-gate dlist_free_items(hbas, NULL);
12507c478bd9Sstevel@tonic-gate }
12517c478bd9Sstevel@tonic-gate
12527c478bd9Sstevel@tonic-gate if (error != 0) {
12537c478bd9Sstevel@tonic-gate dlist_free_items(*disks, NULL);
12547c478bd9Sstevel@tonic-gate *disks = NULL;
12557c478bd9Sstevel@tonic-gate }
12567c478bd9Sstevel@tonic-gate
12577c478bd9Sstevel@tonic-gate return (error);
12587c478bd9Sstevel@tonic-gate }
12597c478bd9Sstevel@tonic-gate
12607c478bd9Sstevel@tonic-gate /*
12617c478bd9Sstevel@tonic-gate * FUNCTION: disk_get_avail_space(devconfig_t *request,
12627c478bd9Sstevel@tonic-gate * dlist_t *disks, uint64_t space)
12637c478bd9Sstevel@tonic-gate *
12647c478bd9Sstevel@tonic-gate * INPUT: request - pointer to a devconfig_t struct representing
12657c478bd9Sstevel@tonic-gate * the current layout request being processed
12667c478bd9Sstevel@tonic-gate * disks - pointer to a list of disks
12677c478bd9Sstevel@tonic-gate * space - pointer to a uint64_t to hold the computed available
12687c478bd9Sstevel@tonic-gate * space
12697c478bd9Sstevel@tonic-gate *
12707c478bd9Sstevel@tonic-gate * RETURNS: int - 0 - on success
12717c478bd9Sstevel@tonic-gate * !0 - otherwise
12727c478bd9Sstevel@tonic-gate *
12737c478bd9Sstevel@tonic-gate * PURPOSE: helper which iterates the input list of disks and determines
12747c478bd9Sstevel@tonic-gate * the aggregate amount of available space they represent.
12757c478bd9Sstevel@tonic-gate *
12767c478bd9Sstevel@tonic-gate * Only disk slices that are in the usable slice list and not
12777c478bd9Sstevel@tonic-gate * specifically excluded by the request's list of unavailable
12787c478bd9Sstevel@tonic-gate * devices will contribute to the aggregate space computation.
12797c478bd9Sstevel@tonic-gate */
12807c478bd9Sstevel@tonic-gate static int
disk_get_avail_space(devconfig_t * request,dm_descriptor_t disk,uint64_t * space)12817c478bd9Sstevel@tonic-gate disk_get_avail_space(
12827c478bd9Sstevel@tonic-gate devconfig_t *request,
12837c478bd9Sstevel@tonic-gate dm_descriptor_t disk,
12847c478bd9Sstevel@tonic-gate uint64_t *space)
12857c478bd9Sstevel@tonic-gate {
12867c478bd9Sstevel@tonic-gate dlist_t *usable_slices = NULL;
12877c478bd9Sstevel@tonic-gate dlist_t *iter = NULL;
12887c478bd9Sstevel@tonic-gate int error = 0;
12897c478bd9Sstevel@tonic-gate
12907c478bd9Sstevel@tonic-gate *space = 0;
12917c478bd9Sstevel@tonic-gate
12927c478bd9Sstevel@tonic-gate /* for each usable slice */
12937c478bd9Sstevel@tonic-gate error = get_usable_slices(&usable_slices);
12947c478bd9Sstevel@tonic-gate for (iter = usable_slices;
12957c478bd9Sstevel@tonic-gate (error == 0) && (iter != NULL);
12967c478bd9Sstevel@tonic-gate iter = iter->next) {
12977c478bd9Sstevel@tonic-gate
12987c478bd9Sstevel@tonic-gate dm_descriptor_t slice = (uintptr_t)iter->obj;
12997c478bd9Sstevel@tonic-gate dm_descriptor_t slice_disk;
13007c478bd9Sstevel@tonic-gate boolean_t avail = B_FALSE;
13017c478bd9Sstevel@tonic-gate boolean_t reserved = B_FALSE;
13027c478bd9Sstevel@tonic-gate boolean_t used = B_FALSE;
13037c478bd9Sstevel@tonic-gate
13047c478bd9Sstevel@tonic-gate /* is slice on disk in question? */
13057c478bd9Sstevel@tonic-gate if (((error = slice_get_disk(slice, &slice_disk)) != 0) ||
1306*b6c8bd52Sjeanm (compare_descriptor_names((void *)(uintptr_t)slice_disk,
1307*b6c8bd52Sjeanm (void *)(uintptr_t)disk) != 0)) {
13087c478bd9Sstevel@tonic-gate continue;
13097c478bd9Sstevel@tonic-gate }
13107c478bd9Sstevel@tonic-gate
13117c478bd9Sstevel@tonic-gate /* is slice reserved by an explicit layout request? */
13127c478bd9Sstevel@tonic-gate if (((error = is_reserved_slice(slice, &reserved)) != 0) ||
13137c478bd9Sstevel@tonic-gate (reserved == B_TRUE)) {
13147c478bd9Sstevel@tonic-gate continue;
13157c478bd9Sstevel@tonic-gate }
13167c478bd9Sstevel@tonic-gate
13177c478bd9Sstevel@tonic-gate /* is slice used by a pending layout request? */
13187c478bd9Sstevel@tonic-gate if (((error = is_used_slice(slice, &used)) != 0) ||
13197c478bd9Sstevel@tonic-gate (used == B_TRUE)) {
13207c478bd9Sstevel@tonic-gate continue;
13217c478bd9Sstevel@tonic-gate }
13227c478bd9Sstevel@tonic-gate
13237c478bd9Sstevel@tonic-gate /* is slice available? */
13247c478bd9Sstevel@tonic-gate if (((error = is_device_avail(slice, request, &avail)) == 0) &&
13257c478bd9Sstevel@tonic-gate (avail == B_TRUE)) {
13267c478bd9Sstevel@tonic-gate
13277c478bd9Sstevel@tonic-gate /* does slice have usable space? */
13287c478bd9Sstevel@tonic-gate uint64_t size = 0;
13297c478bd9Sstevel@tonic-gate if ((error = slice_get_size(slice, &size)) == 0) {
13307c478bd9Sstevel@tonic-gate *space += size;
13317c478bd9Sstevel@tonic-gate }
13327c478bd9Sstevel@tonic-gate }
13337c478bd9Sstevel@tonic-gate }
13347c478bd9Sstevel@tonic-gate
13357c478bd9Sstevel@tonic-gate return (error);
13367c478bd9Sstevel@tonic-gate }
13377c478bd9Sstevel@tonic-gate
13387c478bd9Sstevel@tonic-gate /*
13397c478bd9Sstevel@tonic-gate * FUNCTION: disks_get_avail_slices(devconfig_t *request,
13407c478bd9Sstevel@tonic-gate * dlist_t *disks, dlist_t **slices)
13417c478bd9Sstevel@tonic-gate *
13427c478bd9Sstevel@tonic-gate * INPUT: request - pointer to a devconfig_t struct representing
13437c478bd9Sstevel@tonic-gate * the current layout request being processed
13447c478bd9Sstevel@tonic-gate * disks - pointer to a list of disks
13457c478bd9Sstevel@tonic-gate * slices - pointer to an output list of disks
13467c478bd9Sstevel@tonic-gate *
13477c478bd9Sstevel@tonic-gate * RETURNS: int - 0 - on success
13487c478bd9Sstevel@tonic-gate * !0 - otherwise
13497c478bd9Sstevel@tonic-gate *
13507c478bd9Sstevel@tonic-gate * PURPOSE: helper which iterates the input list of disks and builds a
13517c478bd9Sstevel@tonic-gate * new list which contains disks that are determined to be
13527c478bd9Sstevel@tonic-gate * available for satisfying the input request.
13537c478bd9Sstevel@tonic-gate *
13547c478bd9Sstevel@tonic-gate * A disk must contain at least one slice in the available
13557c478bd9Sstevel@tonic-gate * slice list as well as have available space in order
13567c478bd9Sstevel@tonic-gate * to be available.
13577c478bd9Sstevel@tonic-gate */
13587c478bd9Sstevel@tonic-gate int
disks_get_avail_slices(devconfig_t * request,dlist_t * disks,dlist_t ** slices)13597c478bd9Sstevel@tonic-gate disks_get_avail_slices(
13607c478bd9Sstevel@tonic-gate devconfig_t *request,
13617c478bd9Sstevel@tonic-gate dlist_t *disks,
13627c478bd9Sstevel@tonic-gate dlist_t **slices)
13637c478bd9Sstevel@tonic-gate {
13647c478bd9Sstevel@tonic-gate dlist_t *usable_slices = NULL;
13657c478bd9Sstevel@tonic-gate dlist_t *iter = NULL;
13667c478bd9Sstevel@tonic-gate int error = 0;
13677c478bd9Sstevel@tonic-gate
13687c478bd9Sstevel@tonic-gate *slices = NULL;
13697c478bd9Sstevel@tonic-gate
13707c478bd9Sstevel@tonic-gate /* for each usable slice */
13717c478bd9Sstevel@tonic-gate error = get_usable_slices(&usable_slices);
13727c478bd9Sstevel@tonic-gate for (iter = usable_slices;
13737c478bd9Sstevel@tonic-gate (error == 0) && (iter != NULL);
13747c478bd9Sstevel@tonic-gate iter = iter->next) {
13757c478bd9Sstevel@tonic-gate
13767c478bd9Sstevel@tonic-gate dm_descriptor_t slice = (uintptr_t)iter->obj;
13777c478bd9Sstevel@tonic-gate dm_descriptor_t disk = (dm_descriptor_t)0;
13787c478bd9Sstevel@tonic-gate boolean_t avail = B_FALSE;
13797c478bd9Sstevel@tonic-gate boolean_t reserved = B_FALSE;
13807c478bd9Sstevel@tonic-gate boolean_t used = B_FALSE;
13817c478bd9Sstevel@tonic-gate
13827c478bd9Sstevel@tonic-gate /* is slice on a disk in the input list? */
13837c478bd9Sstevel@tonic-gate if (((error = slice_get_disk(slice, &disk)) != 0) ||
1384*b6c8bd52Sjeanm (dlist_contains(disks, (void *)(uintptr_t)disk,
13857c478bd9Sstevel@tonic-gate compare_descriptor_names) != B_TRUE)) {
13867c478bd9Sstevel@tonic-gate continue;
13877c478bd9Sstevel@tonic-gate }
13887c478bd9Sstevel@tonic-gate
13897c478bd9Sstevel@tonic-gate /* is slice reserved by an explicit layout request? */
13907c478bd9Sstevel@tonic-gate if (((error = is_reserved_slice(slice, &reserved)) != 0) ||
13917c478bd9Sstevel@tonic-gate (reserved == B_TRUE)) {
13927c478bd9Sstevel@tonic-gate continue;
13937c478bd9Sstevel@tonic-gate }
13947c478bd9Sstevel@tonic-gate
13957c478bd9Sstevel@tonic-gate /* is slice used by a pending layout request? */
13967c478bd9Sstevel@tonic-gate if (((error = is_used_slice(slice, &used)) != 0) ||
13977c478bd9Sstevel@tonic-gate (used == B_TRUE)) {
13987c478bd9Sstevel@tonic-gate continue;
13997c478bd9Sstevel@tonic-gate }
14007c478bd9Sstevel@tonic-gate
14017c478bd9Sstevel@tonic-gate /* is slice available? */
14027c478bd9Sstevel@tonic-gate if (((error = is_device_avail(slice, request, &avail)) == 0) &&
14037c478bd9Sstevel@tonic-gate (avail == B_TRUE)) {
14047c478bd9Sstevel@tonic-gate
14057c478bd9Sstevel@tonic-gate /* does slice have available space? */
14067c478bd9Sstevel@tonic-gate uint64_t size = 0;
14077c478bd9Sstevel@tonic-gate error = slice_get_size(slice, &size);
14087c478bd9Sstevel@tonic-gate if ((error == 0) && (size > 0)) {
1409*b6c8bd52Sjeanm dlist_t *item = dlist_new_item((void *)(uintptr_t)slice);
14107c478bd9Sstevel@tonic-gate if (item == NULL) {
14117c478bd9Sstevel@tonic-gate error = ENOMEM;
14127c478bd9Sstevel@tonic-gate } else {
14137c478bd9Sstevel@tonic-gate *slices = dlist_append(item, *slices, AT_TAIL);
14147c478bd9Sstevel@tonic-gate }
14157c478bd9Sstevel@tonic-gate }
14167c478bd9Sstevel@tonic-gate }
14177c478bd9Sstevel@tonic-gate }
14187c478bd9Sstevel@tonic-gate
14197c478bd9Sstevel@tonic-gate if (error != 0) {
14207c478bd9Sstevel@tonic-gate dlist_free_items(*slices, NULL);
14217c478bd9Sstevel@tonic-gate *slices = NULL;
14227c478bd9Sstevel@tonic-gate }
14237c478bd9Sstevel@tonic-gate
14247c478bd9Sstevel@tonic-gate return (error);
14257c478bd9Sstevel@tonic-gate }
14267c478bd9Sstevel@tonic-gate
14277c478bd9Sstevel@tonic-gate
14287c478bd9Sstevel@tonic-gate /*
14297c478bd9Sstevel@tonic-gate * FUNCTION: get_hbas_and_disks_used_by_volumes(dlist_t *volumes,
14307c478bd9Sstevel@tonic-gate * dlist_t **hbas, dlist_t **disks)
14317c478bd9Sstevel@tonic-gate *
14327c478bd9Sstevel@tonic-gate * INPUT: volumes - pointer to a list of devconfig_t volumes
14337c478bd9Sstevel@tonic-gate *
14347c478bd9Sstevel@tonic-gate * OUTPUT: hbas - a list of HBAs utilized by the input volumes
14357c478bd9Sstevel@tonic-gate * disks - a list of disks utilized by the input volumes
14367c478bd9Sstevel@tonic-gate *
14377c478bd9Sstevel@tonic-gate * RETURNS: int - 0 on success
14387c478bd9Sstevel@tonic-gate * !0 otherwise
14397c478bd9Sstevel@tonic-gate *
14407c478bd9Sstevel@tonic-gate * PURPOSE: An aggregate list of HBAs and disks used by the input volumes
14417c478bd9Sstevel@tonic-gate * is built up by iterating the list of volumes and calling
14427c478bd9Sstevel@tonic-gate * get_hbas_disks_used_by_volume() to determine the HBAs and disk
14437c478bd9Sstevel@tonic-gate * used by each volume.
14447c478bd9Sstevel@tonic-gate *
14457c478bd9Sstevel@tonic-gate * The returned lists of HBAs and disks may contain duplicates.
14467c478bd9Sstevel@tonic-gate */
14477c478bd9Sstevel@tonic-gate int
get_hbas_and_disks_used_by_volumes(dlist_t * volumes,dlist_t ** hbas,dlist_t ** disks)14487c478bd9Sstevel@tonic-gate get_hbas_and_disks_used_by_volumes(
14497c478bd9Sstevel@tonic-gate dlist_t *volumes,
14507c478bd9Sstevel@tonic-gate dlist_t **hbas,
14517c478bd9Sstevel@tonic-gate dlist_t **disks)
14527c478bd9Sstevel@tonic-gate {
14537c478bd9Sstevel@tonic-gate dlist_t *iter = NULL;
14547c478bd9Sstevel@tonic-gate int error = 0;
14557c478bd9Sstevel@tonic-gate
14567c478bd9Sstevel@tonic-gate for (iter = volumes;
14577c478bd9Sstevel@tonic-gate (iter != NULL) && (error == 0);
14587c478bd9Sstevel@tonic-gate iter = iter->next) {
14597c478bd9Sstevel@tonic-gate error = get_hbas_and_disks_used_by_volume(
14607c478bd9Sstevel@tonic-gate (devconfig_t *)iter->obj, hbas, disks);
14617c478bd9Sstevel@tonic-gate }
14627c478bd9Sstevel@tonic-gate
14637c478bd9Sstevel@tonic-gate return (error);
14647c478bd9Sstevel@tonic-gate }
14657c478bd9Sstevel@tonic-gate
14667c478bd9Sstevel@tonic-gate /*
14677c478bd9Sstevel@tonic-gate * FUNCTION: get_hbas_and_disks_used_by_volume(devconfig_t *volume,
14687c478bd9Sstevel@tonic-gate * dlist_t **hbas, dlist_t **disks)
14697c478bd9Sstevel@tonic-gate *
14707c478bd9Sstevel@tonic-gate * INPUT: volume - pointer to a devconfig_t volume
14717c478bd9Sstevel@tonic-gate *
14727c478bd9Sstevel@tonic-gate * OUTPUT: hbas - a list of HBAs updated to include those utilized
14737c478bd9Sstevel@tonic-gate * by the input volume
14747c478bd9Sstevel@tonic-gate * disks - a list of disks updated to inlclude those utilized
14757c478bd9Sstevel@tonic-gate * by the input volume
14767c478bd9Sstevel@tonic-gate *
14777c478bd9Sstevel@tonic-gate * RETURNS: int - 0 on success
14787c478bd9Sstevel@tonic-gate * !0 otherwise
14797c478bd9Sstevel@tonic-gate *
14807c478bd9Sstevel@tonic-gate * PURPOSE: The volume's components are iterated and the disks and HBAs
14817c478bd9Sstevel@tonic-gate * for each component are determined and appended to the input
14827c478bd9Sstevel@tonic-gate * lists of HBAs and disks.
14837c478bd9Sstevel@tonic-gate *
14847c478bd9Sstevel@tonic-gate * The returned lists of HBAs and disks may contain duplicates.
14857c478bd9Sstevel@tonic-gate */
14867c478bd9Sstevel@tonic-gate int
get_hbas_and_disks_used_by_volume(devconfig_t * volume,dlist_t ** hbas,dlist_t ** disks)14877c478bd9Sstevel@tonic-gate get_hbas_and_disks_used_by_volume(
14887c478bd9Sstevel@tonic-gate devconfig_t *volume,
14897c478bd9Sstevel@tonic-gate dlist_t **hbas,
14907c478bd9Sstevel@tonic-gate dlist_t **disks)
14917c478bd9Sstevel@tonic-gate {
14927c478bd9Sstevel@tonic-gate dlist_t *iter = NULL;
14937c478bd9Sstevel@tonic-gate int error = 0;
14947c478bd9Sstevel@tonic-gate
14957c478bd9Sstevel@tonic-gate for (iter = devconfig_get_components(volume);
14967c478bd9Sstevel@tonic-gate (iter != NULL) && (error == 0);
14977c478bd9Sstevel@tonic-gate iter = iter->next) {
14987c478bd9Sstevel@tonic-gate
14997c478bd9Sstevel@tonic-gate devconfig_t *dev = (devconfig_t *)iter->obj;
15007c478bd9Sstevel@tonic-gate if (devconfig_isA(dev, TYPE_SLICE)) {
15017c478bd9Sstevel@tonic-gate
15027c478bd9Sstevel@tonic-gate dm_descriptor_t disk = NULL;
15037c478bd9Sstevel@tonic-gate char *name = NULL;
15047c478bd9Sstevel@tonic-gate
15057c478bd9Sstevel@tonic-gate /* get disk for component slice */
15067c478bd9Sstevel@tonic-gate ((error = devconfig_get_name(dev, &name)) != 0) ||
15077c478bd9Sstevel@tonic-gate (error = get_disk_for_named_slice(name, &disk));
15087c478bd9Sstevel@tonic-gate if (error == 0) {
1509*b6c8bd52Sjeanm dlist_t *item = dlist_new_item((void *)(uintptr_t)disk);
15107c478bd9Sstevel@tonic-gate if (item == NULL) {
15117c478bd9Sstevel@tonic-gate error = ENOMEM;
15127c478bd9Sstevel@tonic-gate } else {
15137c478bd9Sstevel@tonic-gate *disks = dlist_append(item, *disks, AT_HEAD);
15147c478bd9Sstevel@tonic-gate }
15157c478bd9Sstevel@tonic-gate }
15167c478bd9Sstevel@tonic-gate
15177c478bd9Sstevel@tonic-gate /* get HBAs for disk */
15187c478bd9Sstevel@tonic-gate if (error == 0) {
15197c478bd9Sstevel@tonic-gate dlist_t *disk_hbas = NULL;
15207c478bd9Sstevel@tonic-gate if ((error = disk_get_hbas(disk, &disk_hbas)) == 0) {
15217c478bd9Sstevel@tonic-gate /* the hba list may contain dups, but that's ok */
15227c478bd9Sstevel@tonic-gate *hbas = dlist_append(disk_hbas, *hbas, AT_HEAD);
15237c478bd9Sstevel@tonic-gate }
15247c478bd9Sstevel@tonic-gate }
15257c478bd9Sstevel@tonic-gate
15267c478bd9Sstevel@tonic-gate } else if (devconfig_isA(dev, TYPE_MIRROR)) {
15277c478bd9Sstevel@tonic-gate
15287c478bd9Sstevel@tonic-gate /* collect info for submirrors */
15297c478bd9Sstevel@tonic-gate dlist_t *iter1;
15307c478bd9Sstevel@tonic-gate for (iter1 = devconfig_get_components(dev);
15317c478bd9Sstevel@tonic-gate (iter1 != NULL) && (error == 0);
15327c478bd9Sstevel@tonic-gate iter1 = iter1->next) {
15337c478bd9Sstevel@tonic-gate error = get_hbas_and_disks_used_by_volume(
15347c478bd9Sstevel@tonic-gate (devconfig_t *)iter1->obj, hbas, disks);
15357c478bd9Sstevel@tonic-gate }
15367c478bd9Sstevel@tonic-gate
15377c478bd9Sstevel@tonic-gate }
15387c478bd9Sstevel@tonic-gate }
15397c478bd9Sstevel@tonic-gate
15407c478bd9Sstevel@tonic-gate return (error);
15417c478bd9Sstevel@tonic-gate }
15427c478bd9Sstevel@tonic-gate
15437c478bd9Sstevel@tonic-gate /*
15447c478bd9Sstevel@tonic-gate * FUNCTION: compare_hba_n_avail_disks(void *obj1, void *obj2)
15457c478bd9Sstevel@tonic-gate *
15467c478bd9Sstevel@tonic-gate * INPUT: obj1 - opaque pointer
15477c478bd9Sstevel@tonic-gate * obj2 - opaque pointer
15487c478bd9Sstevel@tonic-gate *
15497c478bd9Sstevel@tonic-gate * RETURNS: int - <0 - if obj1 has fewer available disks than obj2
15507c478bd9Sstevel@tonic-gate * 0 - if obj1 has the same # of available disks as obj2
15517c478bd9Sstevel@tonic-gate * >0 - if obj1 has more available disks than obj2
15527c478bd9Sstevel@tonic-gate *
15537c478bd9Sstevel@tonic-gate * PURPOSE: dlist_t helper which compares the number of available disks
15547c478bd9Sstevel@tonic-gate * for two HBAs represented as dm_descriptor_t handles.
15557c478bd9Sstevel@tonic-gate *
15567c478bd9Sstevel@tonic-gate * Both input objects are assumed to be dm_descriptor_t handles.
15577c478bd9Sstevel@tonic-gate *
15587c478bd9Sstevel@tonic-gate * The number of available disks associated with the HBAs was
15597c478bd9Sstevel@tonic-gate * computed and saved in select_hbas_with_n_disks(), this
15607c478bd9Sstevel@tonic-gate * function just checks the saved values.
15617c478bd9Sstevel@tonic-gate */
15627c478bd9Sstevel@tonic-gate static int
compare_hba_n_avail_disks(void * obj1,void * obj2)15637c478bd9Sstevel@tonic-gate compare_hba_n_avail_disks(
15647c478bd9Sstevel@tonic-gate void *obj1,
15657c478bd9Sstevel@tonic-gate void *obj2)
15667c478bd9Sstevel@tonic-gate {
15677c478bd9Sstevel@tonic-gate uint16_t n1 = 0;
15687c478bd9Sstevel@tonic-gate uint16_t n2 = 0;
15697c478bd9Sstevel@tonic-gate
15707c478bd9Sstevel@tonic-gate assert(obj1 != NULL);
15717c478bd9Sstevel@tonic-gate assert(obj2 != NULL);
15727c478bd9Sstevel@tonic-gate
15737c478bd9Sstevel@tonic-gate (void) hba_get_n_avail_disks((uintptr_t)obj1, &n1);
15747c478bd9Sstevel@tonic-gate (void) hba_get_n_avail_disks((uintptr_t)obj2, &n2);
15757c478bd9Sstevel@tonic-gate
15767c478bd9Sstevel@tonic-gate return ((int)n1 - n2);
15777c478bd9Sstevel@tonic-gate }
15787c478bd9Sstevel@tonic-gate
15797c478bd9Sstevel@tonic-gate /*
15807c478bd9Sstevel@tonic-gate * FUNCTION: is_device_avail(dm_descriptor_t desc,
15817c478bd9Sstevel@tonic-gate * devconfig_t *request, boolean_t *avail)
15827c478bd9Sstevel@tonic-gate *
15837c478bd9Sstevel@tonic-gate * INPUT: desc - a dm_descriptor_t device handle
15847c478bd9Sstevel@tonic-gate * request - pointer to a devconfig_t struct representing
15857c478bd9Sstevel@tonic-gate * the current layout request being processed
15867c478bd9Sstevel@tonic-gate * avail - pointer to a boolean to hold the result
15877c478bd9Sstevel@tonic-gate *
15887c478bd9Sstevel@tonic-gate * RETURNS: int - 0 - on success
15897c478bd9Sstevel@tonic-gate * !0 - otherwise
15907c478bd9Sstevel@tonic-gate *
15917c478bd9Sstevel@tonic-gate * PURPOSE: Internal helper which determines if the input device can
15927c478bd9Sstevel@tonic-gate * be used as a volume component when satisfying the input
15937c478bd9Sstevel@tonic-gate * request.
15947c478bd9Sstevel@tonic-gate *
15957c478bd9Sstevel@tonic-gate * The device is assumed to be a known valid device.
15967c478bd9Sstevel@tonic-gate *
15977c478bd9Sstevel@tonic-gate * The function checks if the device passes the request's
15987c478bd9Sstevel@tonic-gate * available and unavailable device specifications.
15997c478bd9Sstevel@tonic-gate *
16007c478bd9Sstevel@tonic-gate * The input device name may be either a DID name or a CTD
16017c478bd9Sstevel@tonic-gate * name. All name comparisons are done using the CTD name.
16027c478bd9Sstevel@tonic-gate */
16037c478bd9Sstevel@tonic-gate static int
is_device_avail(dm_descriptor_t desc,devconfig_t * request,boolean_t * avail)16047c478bd9Sstevel@tonic-gate is_device_avail(
16057c478bd9Sstevel@tonic-gate dm_descriptor_t desc,
16067c478bd9Sstevel@tonic-gate devconfig_t *request,
16077c478bd9Sstevel@tonic-gate boolean_t *avail)
16087c478bd9Sstevel@tonic-gate {
16097c478bd9Sstevel@tonic-gate char *name = NULL;
16107c478bd9Sstevel@tonic-gate int error = 0;
16117c478bd9Sstevel@tonic-gate
16127c478bd9Sstevel@tonic-gate *avail = B_FALSE;
16137c478bd9Sstevel@tonic-gate
16147c478bd9Sstevel@tonic-gate if ((error = get_display_name(desc, &name)) == 0) {
16157c478bd9Sstevel@tonic-gate error = is_named_device_avail(request, name, B_TRUE, avail);
16167c478bd9Sstevel@tonic-gate }
16177c478bd9Sstevel@tonic-gate
16187c478bd9Sstevel@tonic-gate return (error);
16197c478bd9Sstevel@tonic-gate }
16207c478bd9Sstevel@tonic-gate
16217c478bd9Sstevel@tonic-gate /*
16227c478bd9Sstevel@tonic-gate * FUNCTION: compare_request_to_request_spec_list_request(
16237c478bd9Sstevel@tonic-gate * void *request, void *list_item)
16247c478bd9Sstevel@tonic-gate *
16257c478bd9Sstevel@tonic-gate * INPUT: request - opaque pointer to a devconfig_t
16267c478bd9Sstevel@tonic-gate * list_item - opaque pointer to a request_spec_list_t
16277c478bd9Sstevel@tonic-gate *
16287c478bd9Sstevel@tonic-gate * RETURNS: int - 0 - if request is the same as list_item->request
16297c478bd9Sstevel@tonic-gate * !0 - otherwise
16307c478bd9Sstevel@tonic-gate *
16317c478bd9Sstevel@tonic-gate * PURPOSE: dlist_t helper which compares the input request pointer
16327c478bd9Sstevel@tonic-gate * to the list_item's request pointer for equality.
16337c478bd9Sstevel@tonic-gate *
16347c478bd9Sstevel@tonic-gate * This function is the lookup mechanism for the lists of
16357c478bd9Sstevel@tonic-gate * cached device_spec_ts representing available/unavailable
16367c478bd9Sstevel@tonic-gate * devices for a given defaults_t request/defaults struct.
16377c478bd9Sstevel@tonic-gate *
16387c478bd9Sstevel@tonic-gate * The defaults_t struct pointer is the lookup key.
16397c478bd9Sstevel@tonic-gate */
16407c478bd9Sstevel@tonic-gate static int
compare_request_to_request_spec_list_request(void * request,void * list_item)16417c478bd9Sstevel@tonic-gate compare_request_to_request_spec_list_request(
16427c478bd9Sstevel@tonic-gate void *request,
16437c478bd9Sstevel@tonic-gate void *list_item)
16447c478bd9Sstevel@tonic-gate {
16457c478bd9Sstevel@tonic-gate request_spec_list_t *entry =
16467c478bd9Sstevel@tonic-gate (request_spec_list_t *)list_item;
16477c478bd9Sstevel@tonic-gate
16487c478bd9Sstevel@tonic-gate assert(request != NULL);
16497c478bd9Sstevel@tonic-gate assert(entry != NULL);
16507c478bd9Sstevel@tonic-gate
16517c478bd9Sstevel@tonic-gate /* compare two devconfig_t pointers, if identical, return 0 */
16527c478bd9Sstevel@tonic-gate return ((devconfig_t *)request != entry->request);
16537c478bd9Sstevel@tonic-gate }
16547c478bd9Sstevel@tonic-gate
16557c478bd9Sstevel@tonic-gate /*
16567c478bd9Sstevel@tonic-gate * FUNCTION: compare_device_spec_specificity(void *spec1, void *spec2)
16577c478bd9Sstevel@tonic-gate *
16587c478bd9Sstevel@tonic-gate * INPUT: spec1 - opaque pointer to a device_spec_t
16597c478bd9Sstevel@tonic-gate * spec2 - opaque pointer to a device_spec_t
16607c478bd9Sstevel@tonic-gate *
16617c478bd9Sstevel@tonic-gate * RETURNS: int - <0 - if spec1 is less specific than spec2
16627c478bd9Sstevel@tonic-gate * 0 - if spec1 is as specific than spec2
16637c478bd9Sstevel@tonic-gate * >0 - if spec1 is more specific than spec2
16647c478bd9Sstevel@tonic-gate *
16657c478bd9Sstevel@tonic-gate * PURPOSE: dlist_t helper which compares the level of specificity
16667c478bd9Sstevel@tonic-gate * in the two input device_spec_t structs. The one
16677c478bd9Sstevel@tonic-gate * which specifies more "components" of a cXtXdXsX device
16687c478bd9Sstevel@tonic-gate * name is considered more specific.
16697c478bd9Sstevel@tonic-gate */
16707c478bd9Sstevel@tonic-gate static int
compare_device_spec_specificity(void * spec1,void * spec2)16717c478bd9Sstevel@tonic-gate compare_device_spec_specificity(
16727c478bd9Sstevel@tonic-gate void *spec1,
16737c478bd9Sstevel@tonic-gate void *spec2)
16747c478bd9Sstevel@tonic-gate {
16757c478bd9Sstevel@tonic-gate if (spec1 == NULL || spec2 == NULL) {
16767c478bd9Sstevel@tonic-gate return (-1);
16777c478bd9Sstevel@tonic-gate }
16787c478bd9Sstevel@tonic-gate
16797c478bd9Sstevel@tonic-gate if ((((device_spec_t *)spec1)->data.ctd->slice != ID_UNSPECIFIED) &&
16807c478bd9Sstevel@tonic-gate (((device_spec_t *)spec2)->data.ctd->slice == ID_UNSPECIFIED)) {
16817c478bd9Sstevel@tonic-gate /* spec1 has slice, spec2 does not, spec1 more specific */
16827c478bd9Sstevel@tonic-gate return (1);
16837c478bd9Sstevel@tonic-gate }
16847c478bd9Sstevel@tonic-gate
16857c478bd9Sstevel@tonic-gate if ((((device_spec_t *)spec2)->data.ctd->slice != ID_UNSPECIFIED) &&
16867c478bd9Sstevel@tonic-gate (((device_spec_t *)spec1)->data.ctd->slice == ID_UNSPECIFIED)) {
16877c478bd9Sstevel@tonic-gate /* spec2 has slice, spec1 does not, spec2 more specific */
16887c478bd9Sstevel@tonic-gate return (-1);
16897c478bd9Sstevel@tonic-gate }
16907c478bd9Sstevel@tonic-gate
16917c478bd9Sstevel@tonic-gate if ((((device_spec_t *)spec2)->data.ctd->slice != ID_UNSPECIFIED) &&
16927c478bd9Sstevel@tonic-gate (((device_spec_t *)spec1)->data.ctd->slice != ID_UNSPECIFIED)) {
16937c478bd9Sstevel@tonic-gate /* both spec1 and spec2 have slice */
16947c478bd9Sstevel@tonic-gate return (0);
16957c478bd9Sstevel@tonic-gate }
16967c478bd9Sstevel@tonic-gate
16977c478bd9Sstevel@tonic-gate if ((((device_spec_t *)spec1)->data.ctd->lun != ID_UNSPECIFIED) &&
16987c478bd9Sstevel@tonic-gate (((device_spec_t *)spec2)->data.ctd->lun == ID_UNSPECIFIED)) {
16997c478bd9Sstevel@tonic-gate /* spec1 has lun, spec2 does not, spec1 more specific */
17007c478bd9Sstevel@tonic-gate return (1);
17017c478bd9Sstevel@tonic-gate }
17027c478bd9Sstevel@tonic-gate
17037c478bd9Sstevel@tonic-gate if ((((device_spec_t *)spec2)->data.ctd->lun != ID_UNSPECIFIED) &&
17047c478bd9Sstevel@tonic-gate (((device_spec_t *)spec1)->data.ctd->lun == ID_UNSPECIFIED)) {
17057c478bd9Sstevel@tonic-gate /* spec2 has lun, spec1 does not, spec2 more specific */
17067c478bd9Sstevel@tonic-gate return (-1);
17077c478bd9Sstevel@tonic-gate }
17087c478bd9Sstevel@tonic-gate
17097c478bd9Sstevel@tonic-gate if ((((device_spec_t *)spec2)->data.ctd->lun != ID_UNSPECIFIED) &&
17107c478bd9Sstevel@tonic-gate (((device_spec_t *)spec1)->data.ctd->lun != ID_UNSPECIFIED)) {
17117c478bd9Sstevel@tonic-gate /* both spec1 and spec2 have lun */
17127c478bd9Sstevel@tonic-gate return (0);
17137c478bd9Sstevel@tonic-gate }
17147c478bd9Sstevel@tonic-gate
17157c478bd9Sstevel@tonic-gate if ((((device_spec_t *)spec1)->data.ctd->target != ID_UNSPECIFIED) &&
17167c478bd9Sstevel@tonic-gate (((device_spec_t *)spec2)->data.ctd->target == ID_UNSPECIFIED)) {
17177c478bd9Sstevel@tonic-gate /* spec1 has target, spec2 does not, spec1 more specific */
17187c478bd9Sstevel@tonic-gate return (1);
17197c478bd9Sstevel@tonic-gate }
17207c478bd9Sstevel@tonic-gate
17217c478bd9Sstevel@tonic-gate if ((((device_spec_t *)spec2)->data.ctd->target != ID_UNSPECIFIED) &&
17227c478bd9Sstevel@tonic-gate (((device_spec_t *)spec1)->data.ctd->target == ID_UNSPECIFIED)) {
17237c478bd9Sstevel@tonic-gate /* spec2 has target, spec1 does not, spec2 more specific */
17247c478bd9Sstevel@tonic-gate return (-1);
17257c478bd9Sstevel@tonic-gate }
17267c478bd9Sstevel@tonic-gate
17277c478bd9Sstevel@tonic-gate if ((((device_spec_t *)spec2)->data.ctd->target != ID_UNSPECIFIED) &&
17287c478bd9Sstevel@tonic-gate (((device_spec_t *)spec1)->data.ctd->target != ID_UNSPECIFIED)) {
17297c478bd9Sstevel@tonic-gate /* both spec1 and spec2 have target */
17307c478bd9Sstevel@tonic-gate return (0);
17317c478bd9Sstevel@tonic-gate }
17327c478bd9Sstevel@tonic-gate
17337c478bd9Sstevel@tonic-gate /* both specify just ctrl */
17347c478bd9Sstevel@tonic-gate return (0);
17357c478bd9Sstevel@tonic-gate }
17367c478bd9Sstevel@tonic-gate
17377c478bd9Sstevel@tonic-gate /*
17387c478bd9Sstevel@tonic-gate * FUNCTION: find_request_spec_list_entry(devconfig_t *request)
17397c478bd9Sstevel@tonic-gate *
17407c478bd9Sstevel@tonic-gate * INPUT: request - pointer to a devconfig_t struct
17417c478bd9Sstevel@tonic-gate *
17427c478bd9Sstevel@tonic-gate * RETURNS: request_spec_list_entry - pointer to a
17437c478bd9Sstevel@tonic-gate * request_spec_list_entry struct
17447c478bd9Sstevel@tonic-gate *
17457c478bd9Sstevel@tonic-gate * PURPOSE: Lookup function which encapsulates the details of locating
17467c478bd9Sstevel@tonic-gate * the device_spec_list_t cache entry for the input request.
17477c478bd9Sstevel@tonic-gate */
17487c478bd9Sstevel@tonic-gate static request_spec_list_t *
find_request_spec_list_entry(devconfig_t * request)17497c478bd9Sstevel@tonic-gate find_request_spec_list_entry(
17507c478bd9Sstevel@tonic-gate devconfig_t *request)
17517c478bd9Sstevel@tonic-gate {
17527c478bd9Sstevel@tonic-gate dlist_t *list_item = NULL;
17537c478bd9Sstevel@tonic-gate request_spec_list_t *entry = NULL;
17547c478bd9Sstevel@tonic-gate
17557c478bd9Sstevel@tonic-gate list_item = dlist_find(
17567c478bd9Sstevel@tonic-gate _request_spec_list_cache,
17577c478bd9Sstevel@tonic-gate (void *)request,
17587c478bd9Sstevel@tonic-gate compare_request_to_request_spec_list_request);
17597c478bd9Sstevel@tonic-gate
17607c478bd9Sstevel@tonic-gate if (list_item != NULL) {
17617c478bd9Sstevel@tonic-gate entry = (request_spec_list_t *)list_item->obj;
17627c478bd9Sstevel@tonic-gate }
17637c478bd9Sstevel@tonic-gate
17647c478bd9Sstevel@tonic-gate return (entry);
17657c478bd9Sstevel@tonic-gate }
17667c478bd9Sstevel@tonic-gate
17677c478bd9Sstevel@tonic-gate /*
17687c478bd9Sstevel@tonic-gate * FUNCTION: add_request_spec_list_entry(devconfig_t *request,
17697c478bd9Sstevel@tonic-gate * char **avail_device_specs, char **unavail_device_specs,
17707c478bd9Sstevel@tonic-gate * request_spec_list_entry_t **entry)
17717c478bd9Sstevel@tonic-gate *
17727c478bd9Sstevel@tonic-gate * INPUT: entry - pointer to the request_spec_list_entry struct to be
17737c478bd9Sstevel@tonic-gate * added to the cache.
17747c478bd9Sstevel@tonic-gate *
17757c478bd9Sstevel@tonic-gate * RETURNS: int - 0 on success
17767c478bd9Sstevel@tonic-gate * !0 otherwise.
17777c478bd9Sstevel@tonic-gate *
17787c478bd9Sstevel@tonic-gate * PURPOSE: Function which encapsulates the details of adding a
17797c478bd9Sstevel@tonic-gate * device_spec_list_t cache entry.
17807c478bd9Sstevel@tonic-gate */
17817c478bd9Sstevel@tonic-gate static int
add_request_spec_list_entry(request_spec_list_t * entry)17827c478bd9Sstevel@tonic-gate add_request_spec_list_entry(
17837c478bd9Sstevel@tonic-gate request_spec_list_t *entry)
17847c478bd9Sstevel@tonic-gate {
17857c478bd9Sstevel@tonic-gate dlist_t *list_item = dlist_new_item((void *)entry);
17867c478bd9Sstevel@tonic-gate
17877c478bd9Sstevel@tonic-gate if (list_item == NULL) {
17887c478bd9Sstevel@tonic-gate return (ENOMEM);
17897c478bd9Sstevel@tonic-gate }
17907c478bd9Sstevel@tonic-gate
17917c478bd9Sstevel@tonic-gate _request_spec_list_cache = dlist_append(list_item,
17927c478bd9Sstevel@tonic-gate _request_spec_list_cache, AT_HEAD);
17937c478bd9Sstevel@tonic-gate
17947c478bd9Sstevel@tonic-gate return (0);
17957c478bd9Sstevel@tonic-gate }
17967c478bd9Sstevel@tonic-gate
17977c478bd9Sstevel@tonic-gate /*
17987c478bd9Sstevel@tonic-gate * FUNCTION: make_request_spec_list_entry(devconfig_t *request,
17997c478bd9Sstevel@tonic-gate * char **avail_device_specs, char **unavail_device_specs,
18007c478bd9Sstevel@tonic-gate * request_spec_list_entry_t **entry)
18017c478bd9Sstevel@tonic-gate *
18027c478bd9Sstevel@tonic-gate * INPUT: request - pointer to a devconfig_t struct
18037c478bd9Sstevel@tonic-gate * avail_device_specs - char * array of user specified available
18047c478bd9Sstevel@tonic-gate * devices associated with the input request
18057c478bd9Sstevel@tonic-gate * unavail_device_specs - char * array of user specified
18067c478bd9Sstevel@tonic-gate * unavailable devices associated with the input
18077c478bd9Sstevel@tonic-gate * request
18087c478bd9Sstevel@tonic-gate *
18097c478bd9Sstevel@tonic-gate * RETURNS: int - 0 on success
18107c478bd9Sstevel@tonic-gate * !0 otherwise.
18117c478bd9Sstevel@tonic-gate *
18127c478bd9Sstevel@tonic-gate * PURPOSE: Function which encapsulates the details of generating a new
18137c478bd9Sstevel@tonic-gate * the device_spec_list_t cache entry for the input request
18147c478bd9Sstevel@tonic-gate * and its lists of avail/unavail devices.
18157c478bd9Sstevel@tonic-gate *
18167c478bd9Sstevel@tonic-gate * Converts the input arrays of (un)available device names into
18177c478bd9Sstevel@tonic-gate * equivalent lists of device_spec_t structs.
18187c478bd9Sstevel@tonic-gate *
18197c478bd9Sstevel@tonic-gate * Creates a new cache entry, populates it and adds it to the
18207c478bd9Sstevel@tonic-gate * cache.
18217c478bd9Sstevel@tonic-gate */
18227c478bd9Sstevel@tonic-gate static int
make_request_spec_list_entry(devconfig_t * request,char ** avail_device_specs,char ** unavail_device_specs,request_spec_list_t ** entry)18237c478bd9Sstevel@tonic-gate make_request_spec_list_entry(
18247c478bd9Sstevel@tonic-gate devconfig_t *request,
18257c478bd9Sstevel@tonic-gate char **avail_device_specs,
18267c478bd9Sstevel@tonic-gate char **unavail_device_specs,
18277c478bd9Sstevel@tonic-gate request_spec_list_t **entry)
18287c478bd9Sstevel@tonic-gate {
18297c478bd9Sstevel@tonic-gate int error = 0;
18307c478bd9Sstevel@tonic-gate dlist_t *list = NULL;
18317c478bd9Sstevel@tonic-gate
18327c478bd9Sstevel@tonic-gate *entry = calloc(1, sizeof (request_spec_list_t));
18337c478bd9Sstevel@tonic-gate if (*entry == NULL) {
18347c478bd9Sstevel@tonic-gate return (ENOMEM);
18357c478bd9Sstevel@tonic-gate }
18367c478bd9Sstevel@tonic-gate
18377c478bd9Sstevel@tonic-gate (*entry)->request = request;
18387c478bd9Sstevel@tonic-gate
18397c478bd9Sstevel@tonic-gate /*
18407c478bd9Sstevel@tonic-gate * map the avail_device_name array into a list of device_spec_t
18417c478bd9Sstevel@tonic-gate * and save the list as the entry's available list
18427c478bd9Sstevel@tonic-gate */
18437c478bd9Sstevel@tonic-gate error = convert_usernames_to_specs(
18447c478bd9Sstevel@tonic-gate avail_device_specs, &list);
18457c478bd9Sstevel@tonic-gate
18467c478bd9Sstevel@tonic-gate if (error == 0) {
18477c478bd9Sstevel@tonic-gate (*entry)->avail_specs_list = list;
18487c478bd9Sstevel@tonic-gate }
18497c478bd9Sstevel@tonic-gate
18507c478bd9Sstevel@tonic-gate /*
18517c478bd9Sstevel@tonic-gate * map the unavail_device_name array into a list of device_spec_t
18527c478bd9Sstevel@tonic-gate * and save the list as the entry's unavailable list
18537c478bd9Sstevel@tonic-gate */
18547c478bd9Sstevel@tonic-gate list = NULL;
18557c478bd9Sstevel@tonic-gate error = convert_usernames_to_specs(
18567c478bd9Sstevel@tonic-gate unavail_device_specs, &list);
18577c478bd9Sstevel@tonic-gate
18587c478bd9Sstevel@tonic-gate if (error == 0) {
18597c478bd9Sstevel@tonic-gate (*entry)->unavail_specs_list = list;
18607c478bd9Sstevel@tonic-gate }
18617c478bd9Sstevel@tonic-gate
18627c478bd9Sstevel@tonic-gate if (error != 0) {
18637c478bd9Sstevel@tonic-gate /* delete the partial entry */
18647c478bd9Sstevel@tonic-gate destroy_request_spec_list_entry((void *)*entry);
18657c478bd9Sstevel@tonic-gate *entry = NULL;
18667c478bd9Sstevel@tonic-gate }
18677c478bd9Sstevel@tonic-gate
18687c478bd9Sstevel@tonic-gate return (error);
18697c478bd9Sstevel@tonic-gate }
18707c478bd9Sstevel@tonic-gate
18717c478bd9Sstevel@tonic-gate /*
18727c478bd9Sstevel@tonic-gate * FUNCTION: convert_usernames_to_specs(char **specs, dlist_t **list)
18737c478bd9Sstevel@tonic-gate *
18747c478bd9Sstevel@tonic-gate * INPUT: specs - char * array of device CTD names
18757c478bd9Sstevel@tonic-gate *
18767c478bd9Sstevel@tonic-gate * OUTPUT: list - pointer to a list of device_spec_t corresponding
18777c478bd9Sstevel@tonic-gate * to each name in the input array
18787c478bd9Sstevel@tonic-gate *
18797c478bd9Sstevel@tonic-gate * RETURNS: int - 0 on success
18807c478bd9Sstevel@tonic-gate * !0 otherwise.
18817c478bd9Sstevel@tonic-gate *
18827c478bd9Sstevel@tonic-gate * PURPOSE: Function which converts the input CTD device names to the
18837c478bd9Sstevel@tonic-gate * equivalent device_spec_t structs.
18847c478bd9Sstevel@tonic-gate *
18857c478bd9Sstevel@tonic-gate * Iterates the input array and converts each CTD name to a
18867c478bd9Sstevel@tonic-gate * device_spec_t using get_spec_for_name().
18877c478bd9Sstevel@tonic-gate */
18887c478bd9Sstevel@tonic-gate static int
convert_usernames_to_specs(char ** specs,dlist_t ** list)18897c478bd9Sstevel@tonic-gate convert_usernames_to_specs(
18907c478bd9Sstevel@tonic-gate char **specs,
18917c478bd9Sstevel@tonic-gate dlist_t **list)
18927c478bd9Sstevel@tonic-gate {
18937c478bd9Sstevel@tonic-gate int i = 0;
18947c478bd9Sstevel@tonic-gate int error = 0;
18957c478bd9Sstevel@tonic-gate
18967c478bd9Sstevel@tonic-gate /*
18977c478bd9Sstevel@tonic-gate * For each spec in the array, get the corresponding
18987c478bd9Sstevel@tonic-gate * device_spec_t and add it to the list.
18997c478bd9Sstevel@tonic-gate *
19007c478bd9Sstevel@tonic-gate * Any spec in the array that looks to be a DID name
19017c478bd9Sstevel@tonic-gate * is first converted to its equivalent CTD name.
19027c478bd9Sstevel@tonic-gate */
19037c478bd9Sstevel@tonic-gate for (i = 0;
19047c478bd9Sstevel@tonic-gate (specs != NULL) && (specs[i] != NULL) && (error == 0);
19057c478bd9Sstevel@tonic-gate i++) {
19067c478bd9Sstevel@tonic-gate
19077c478bd9Sstevel@tonic-gate device_spec_t *spec = NULL;
19087c478bd9Sstevel@tonic-gate char *userspec = specs[i];
19097c478bd9Sstevel@tonic-gate
19107c478bd9Sstevel@tonic-gate error = get_spec_for_name(userspec, &spec);
19117c478bd9Sstevel@tonic-gate if ((error == 0) && (spec != NULL)) {
19127c478bd9Sstevel@tonic-gate dlist_t *list_item = dlist_new_item((void *)spec);
19137c478bd9Sstevel@tonic-gate if (spec == NULL) {
19147c478bd9Sstevel@tonic-gate error = ENOMEM;
19157c478bd9Sstevel@tonic-gate } else {
19167c478bd9Sstevel@tonic-gate *list = dlist_insert_ordered
19177c478bd9Sstevel@tonic-gate (list_item, *list, DESCENDING,
19187c478bd9Sstevel@tonic-gate compare_device_spec_specificity);
19197c478bd9Sstevel@tonic-gate }
19207c478bd9Sstevel@tonic-gate }
19217c478bd9Sstevel@tonic-gate }
19227c478bd9Sstevel@tonic-gate
19237c478bd9Sstevel@tonic-gate if (error != 0) {
19247c478bd9Sstevel@tonic-gate /* the device_spec_t in the list items are maintained */
19257c478bd9Sstevel@tonic-gate /* in a cache elsewhere, so don't free them here. */
19267c478bd9Sstevel@tonic-gate dlist_free_items(*list, NULL);
19277c478bd9Sstevel@tonic-gate *list = NULL;
19287c478bd9Sstevel@tonic-gate }
19297c478bd9Sstevel@tonic-gate
19307c478bd9Sstevel@tonic-gate return (error);
19317c478bd9Sstevel@tonic-gate }
19327c478bd9Sstevel@tonic-gate
19337c478bd9Sstevel@tonic-gate /*
19347c478bd9Sstevel@tonic-gate * FUNCTION: destroy_request_spec_list_entry(void *entry)
19357c478bd9Sstevel@tonic-gate *
19367c478bd9Sstevel@tonic-gate * INPUT: entry - opaque pointer to a request_spec_list_t
19377c478bd9Sstevel@tonic-gate *
19387c478bd9Sstevel@tonic-gate * RETURNS: nothing
19397c478bd9Sstevel@tonic-gate *
19407c478bd9Sstevel@tonic-gate * PURPOSE: Function which reclaims memory allocated to a
19417c478bd9Sstevel@tonic-gate * request_spec_list_t.
19427c478bd9Sstevel@tonic-gate *
19437c478bd9Sstevel@tonic-gate * Frees memory allocated to the avail_spec_list and
19447c478bd9Sstevel@tonic-gate * unavail_spec_list. Entries in the list are not freed,
19457c478bd9Sstevel@tonic-gate * since they are owned by the device_spec cache.
19467c478bd9Sstevel@tonic-gate */
19477c478bd9Sstevel@tonic-gate static void
destroy_request_spec_list_entry(void * obj)19487c478bd9Sstevel@tonic-gate destroy_request_spec_list_entry(
19497c478bd9Sstevel@tonic-gate void *obj)
19507c478bd9Sstevel@tonic-gate {
19517c478bd9Sstevel@tonic-gate request_spec_list_t *entry = (request_spec_list_t *)obj;
19527c478bd9Sstevel@tonic-gate
19537c478bd9Sstevel@tonic-gate if (entry != NULL) {
19547c478bd9Sstevel@tonic-gate /* items in the list are in the spec_cache and will */
19557c478bd9Sstevel@tonic-gate /* be cleaned up when it is destroyed. */
19567c478bd9Sstevel@tonic-gate dlist_free_items(entry->avail_specs_list, NULL);
19577c478bd9Sstevel@tonic-gate dlist_free_items(entry->unavail_specs_list, NULL);
19587c478bd9Sstevel@tonic-gate free(entry);
19597c478bd9Sstevel@tonic-gate }
19607c478bd9Sstevel@tonic-gate }
19617c478bd9Sstevel@tonic-gate
19627c478bd9Sstevel@tonic-gate /*
19637c478bd9Sstevel@tonic-gate * FUNCTION: destroy_request_spec_list_cache()
19647c478bd9Sstevel@tonic-gate *
19657c478bd9Sstevel@tonic-gate * RETURNS: int - 0 on success
19667c478bd9Sstevel@tonic-gate * !0 otherwise.
19677c478bd9Sstevel@tonic-gate *
19687c478bd9Sstevel@tonic-gate * PURPOSE: Function which destroys all entries in the request_spec_list
19697c478bd9Sstevel@tonic-gate * cache.
19707c478bd9Sstevel@tonic-gate */
19717c478bd9Sstevel@tonic-gate static int
destroy_request_spec_list_cache()19727c478bd9Sstevel@tonic-gate destroy_request_spec_list_cache()
19737c478bd9Sstevel@tonic-gate {
19747c478bd9Sstevel@tonic-gate dlist_free_items(_request_spec_list_cache,
19757c478bd9Sstevel@tonic-gate destroy_request_spec_list_entry);
19767c478bd9Sstevel@tonic-gate _request_spec_list_cache = NULL;
19777c478bd9Sstevel@tonic-gate
19787c478bd9Sstevel@tonic-gate return (0);
19797c478bd9Sstevel@tonic-gate }
19807c478bd9Sstevel@tonic-gate
19817c478bd9Sstevel@tonic-gate /*
19827c478bd9Sstevel@tonic-gate * FUNCTION: get_request_avail_spec_list(devconfig_t *request,
19837c478bd9Sstevel@tonic-gate * dlist_t **list)
19847c478bd9Sstevel@tonic-gate *
19857c478bd9Sstevel@tonic-gate * INPUT: request - a pointer to a devconfig_t
19867c478bd9Sstevel@tonic-gate *
19877c478bd9Sstevel@tonic-gate * OUTPUT: list - pointer to a list of device_spec_t corresponding
19887c478bd9Sstevel@tonic-gate * to the devices specified as available by the
19897c478bd9Sstevel@tonic-gate * input request.
19907c478bd9Sstevel@tonic-gate *
19917c478bd9Sstevel@tonic-gate * RETURNS: int - 0 on success
19927c478bd9Sstevel@tonic-gate * !0 otherwise.
19937c478bd9Sstevel@tonic-gate *
19947c478bd9Sstevel@tonic-gate * PURPOSE: Function which locates or builds the list of device_spec_t
19957c478bd9Sstevel@tonic-gate * for the available devices specified in the input request.
19967c478bd9Sstevel@tonic-gate *
19977c478bd9Sstevel@tonic-gate * Looks up the input request in the request_spec_list cache.
19987c478bd9Sstevel@tonic-gate * If there is currently no entry in the cache for the request,
19997c478bd9Sstevel@tonic-gate * an entry is built and added.
20007c478bd9Sstevel@tonic-gate *
20017c478bd9Sstevel@tonic-gate * The entry's list of available device_spec_t is returned.
20027c478bd9Sstevel@tonic-gate */
20037c478bd9Sstevel@tonic-gate static int
get_request_avail_spec_list(devconfig_t * request,dlist_t ** list)20047c478bd9Sstevel@tonic-gate get_request_avail_spec_list(
20057c478bd9Sstevel@tonic-gate devconfig_t *request,
20067c478bd9Sstevel@tonic-gate dlist_t **list)
20077c478bd9Sstevel@tonic-gate {
20087c478bd9Sstevel@tonic-gate request_spec_list_t *entry = NULL;
20097c478bd9Sstevel@tonic-gate int error = 0;
20107c478bd9Sstevel@tonic-gate
20117c478bd9Sstevel@tonic-gate if ((entry = find_request_spec_list_entry(request)) == NULL) {
20127c478bd9Sstevel@tonic-gate
20137c478bd9Sstevel@tonic-gate /* create cache entry for this request */
20147c478bd9Sstevel@tonic-gate error = make_request_spec_list_entry(
20157c478bd9Sstevel@tonic-gate request,
20167c478bd9Sstevel@tonic-gate devconfig_get_available(request),
20177c478bd9Sstevel@tonic-gate devconfig_get_unavailable(request),
20187c478bd9Sstevel@tonic-gate &entry);
20197c478bd9Sstevel@tonic-gate
20207c478bd9Sstevel@tonic-gate if ((error == 0) && (entry != NULL)) {
20217c478bd9Sstevel@tonic-gate if ((error = add_request_spec_list_entry(entry)) != 0) {
20227c478bd9Sstevel@tonic-gate destroy_request_spec_list_entry(entry);
20237c478bd9Sstevel@tonic-gate entry = NULL;
20247c478bd9Sstevel@tonic-gate }
20257c478bd9Sstevel@tonic-gate }
20267c478bd9Sstevel@tonic-gate }
20277c478bd9Sstevel@tonic-gate
20287c478bd9Sstevel@tonic-gate if ((error == 0) && (entry != NULL)) {
20297c478bd9Sstevel@tonic-gate *list = entry->avail_specs_list;
20307c478bd9Sstevel@tonic-gate }
20317c478bd9Sstevel@tonic-gate
20327c478bd9Sstevel@tonic-gate return (error);
20337c478bd9Sstevel@tonic-gate }
20347c478bd9Sstevel@tonic-gate
20357c478bd9Sstevel@tonic-gate /*
20367c478bd9Sstevel@tonic-gate * FUNCTION: get_request_unavail_spec_list(devconfig_t *request,
20377c478bd9Sstevel@tonic-gate * dlist_t **list)
20387c478bd9Sstevel@tonic-gate *
20397c478bd9Sstevel@tonic-gate * INPUT: request - a pointer to a devconfig_t
20407c478bd9Sstevel@tonic-gate *
20417c478bd9Sstevel@tonic-gate * OUTPUT: list - pointer to a list of device_spec_t corresponding
20427c478bd9Sstevel@tonic-gate * to the devices specified as unavailable by the
20437c478bd9Sstevel@tonic-gate * input request.
20447c478bd9Sstevel@tonic-gate *
20457c478bd9Sstevel@tonic-gate * RETURNS: int - 0 on success
20467c478bd9Sstevel@tonic-gate * !0 otherwise.
20477c478bd9Sstevel@tonic-gate *
20487c478bd9Sstevel@tonic-gate * PURPOSE: Function which locates or builds the list of device_spec_t
20497c478bd9Sstevel@tonic-gate * for the unavailable devices specified in the input request.
20507c478bd9Sstevel@tonic-gate *
20517c478bd9Sstevel@tonic-gate * Looks up the input request in the request_spec_list cache.
20527c478bd9Sstevel@tonic-gate * If there is currently no entry in the cache for the request,
20537c478bd9Sstevel@tonic-gate * an entry is built and added.
20547c478bd9Sstevel@tonic-gate *
20557c478bd9Sstevel@tonic-gate * The entry's list of unavailable device_spec_t is returned.
20567c478bd9Sstevel@tonic-gate */
20577c478bd9Sstevel@tonic-gate static int
get_request_unavail_spec_list(devconfig_t * request,dlist_t ** list)20587c478bd9Sstevel@tonic-gate get_request_unavail_spec_list(
20597c478bd9Sstevel@tonic-gate devconfig_t *request,
20607c478bd9Sstevel@tonic-gate dlist_t **list)
20617c478bd9Sstevel@tonic-gate {
20627c478bd9Sstevel@tonic-gate request_spec_list_t *entry = NULL;
20637c478bd9Sstevel@tonic-gate int error = 0;
20647c478bd9Sstevel@tonic-gate
20657c478bd9Sstevel@tonic-gate if ((entry = find_request_spec_list_entry(request)) == NULL) {
20667c478bd9Sstevel@tonic-gate
20677c478bd9Sstevel@tonic-gate /* create new entry for this request */
20687c478bd9Sstevel@tonic-gate error = make_request_spec_list_entry(
20697c478bd9Sstevel@tonic-gate request,
20707c478bd9Sstevel@tonic-gate devconfig_get_available(request),
20717c478bd9Sstevel@tonic-gate devconfig_get_unavailable(request),
20727c478bd9Sstevel@tonic-gate &entry);
20737c478bd9Sstevel@tonic-gate
20747c478bd9Sstevel@tonic-gate if ((error == 0) && (entry != NULL)) {
20757c478bd9Sstevel@tonic-gate if ((error = add_request_spec_list_entry(entry)) != 0) {
20767c478bd9Sstevel@tonic-gate destroy_request_spec_list_entry(entry);
20777c478bd9Sstevel@tonic-gate entry = NULL;
20787c478bd9Sstevel@tonic-gate }
20797c478bd9Sstevel@tonic-gate }
20807c478bd9Sstevel@tonic-gate }
20817c478bd9Sstevel@tonic-gate
20827c478bd9Sstevel@tonic-gate if ((error == 0) && (entry != NULL)) {
20837c478bd9Sstevel@tonic-gate *list = entry->unavail_specs_list;
20847c478bd9Sstevel@tonic-gate }
20857c478bd9Sstevel@tonic-gate
20867c478bd9Sstevel@tonic-gate return (error);
20877c478bd9Sstevel@tonic-gate }
20887c478bd9Sstevel@tonic-gate
20897c478bd9Sstevel@tonic-gate /*
20907c478bd9Sstevel@tonic-gate * FUNCTION: get_default_avail_spec_list(defaults_t *defaults,
20917c478bd9Sstevel@tonic-gate * char *dsname, dlist_t **list)
20927c478bd9Sstevel@tonic-gate *
20937c478bd9Sstevel@tonic-gate * INPUT: defaults - a pointer to a defaults_t struct
20947c478bd9Sstevel@tonic-gate * dsname - the name of the diskset whose defaults should be used
20957c478bd9Sstevel@tonic-gate *
20967c478bd9Sstevel@tonic-gate * OUTPUT: list - pointer to a list of device_spec_t corresponding
20977c478bd9Sstevel@tonic-gate * to the devices specified as available by the
20987c478bd9Sstevel@tonic-gate * defaults for the named diskset, or the global
20997c478bd9Sstevel@tonic-gate * defaults for all disksets.
21007c478bd9Sstevel@tonic-gate *
21017c478bd9Sstevel@tonic-gate * RETURNS: int - 0 on success
21027c478bd9Sstevel@tonic-gate * !0 otherwise.
21037c478bd9Sstevel@tonic-gate *
21047c478bd9Sstevel@tonic-gate * PURPOSE: Function which locates or builds the list of device_spec_t
21057c478bd9Sstevel@tonic-gate * for the available devices for the named diskset.
21067c478bd9Sstevel@tonic-gate *
21077c478bd9Sstevel@tonic-gate * Locates the defaults for the named diskset, if there are none,
21087c478bd9Sstevel@tonic-gate * locates the global defaults for all disksets.
21097c478bd9Sstevel@tonic-gate *
21107c478bd9Sstevel@tonic-gate * The defaults devconfig_t struct is then used to look up the
21117c478bd9Sstevel@tonic-gate * the corresponding entry in the request_spec_list cache.
21127c478bd9Sstevel@tonic-gate *
21137c478bd9Sstevel@tonic-gate * If there is currently no entry in the cache for the defaults,
21147c478bd9Sstevel@tonic-gate * an entry is built and added.
21157c478bd9Sstevel@tonic-gate *
21167c478bd9Sstevel@tonic-gate * The entry's list of available device_spec_t is returned.
21177c478bd9Sstevel@tonic-gate */
21187c478bd9Sstevel@tonic-gate static int
get_default_avail_spec_list(defaults_t * alldefaults,char * dsname,dlist_t ** list)21197c478bd9Sstevel@tonic-gate get_default_avail_spec_list(
21207c478bd9Sstevel@tonic-gate defaults_t *alldefaults,
21217c478bd9Sstevel@tonic-gate char *dsname,
21227c478bd9Sstevel@tonic-gate dlist_t **list)
21237c478bd9Sstevel@tonic-gate {
21247c478bd9Sstevel@tonic-gate request_spec_list_t *entry = NULL;
21257c478bd9Sstevel@tonic-gate devconfig_t *defaults = NULL;
21267c478bd9Sstevel@tonic-gate int error = 0;
21277c478bd9Sstevel@tonic-gate
21287c478bd9Sstevel@tonic-gate /* Get diskset defaults, or global if none for diskset */
21297c478bd9Sstevel@tonic-gate error = defaults_get_diskset_by_name(
21307c478bd9Sstevel@tonic-gate alldefaults, dsname, &defaults);
21317c478bd9Sstevel@tonic-gate
21327c478bd9Sstevel@tonic-gate if (error != 0) {
21337c478bd9Sstevel@tonic-gate if (error == ENOENT) {
21347c478bd9Sstevel@tonic-gate /* to get global defaults, pass a NULL diskset name */
21357c478bd9Sstevel@tonic-gate error = defaults_get_diskset_by_name(
21367c478bd9Sstevel@tonic-gate alldefaults, NULL, &defaults);
21377c478bd9Sstevel@tonic-gate }
21387c478bd9Sstevel@tonic-gate
21397c478bd9Sstevel@tonic-gate if (error != 0) {
21407c478bd9Sstevel@tonic-gate if (error != ENOENT) {
21417c478bd9Sstevel@tonic-gate oprintf(OUTPUT_DEBUG,
21427c478bd9Sstevel@tonic-gate gettext("get defaults for %s returned %d\n"),
21437c478bd9Sstevel@tonic-gate dsname, error);
21447c478bd9Sstevel@tonic-gate } else {
21457c478bd9Sstevel@tonic-gate error = 0;
21467c478bd9Sstevel@tonic-gate }
21477c478bd9Sstevel@tonic-gate }
21487c478bd9Sstevel@tonic-gate }
21497c478bd9Sstevel@tonic-gate
21507c478bd9Sstevel@tonic-gate if ((entry = find_request_spec_list_entry(defaults)) == NULL) {
21517c478bd9Sstevel@tonic-gate
21527c478bd9Sstevel@tonic-gate /* create new entry for these defaults */
21537c478bd9Sstevel@tonic-gate error = make_request_spec_list_entry(
21547c478bd9Sstevel@tonic-gate defaults,
21557c478bd9Sstevel@tonic-gate devconfig_get_available(defaults),
21567c478bd9Sstevel@tonic-gate devconfig_get_unavailable(defaults),
21577c478bd9Sstevel@tonic-gate &entry);
21587c478bd9Sstevel@tonic-gate
21597c478bd9Sstevel@tonic-gate if ((error == 0) && (entry != NULL)) {
21607c478bd9Sstevel@tonic-gate if ((error = add_request_spec_list_entry(entry)) != 0) {
21617c478bd9Sstevel@tonic-gate destroy_request_spec_list_entry(entry);
21627c478bd9Sstevel@tonic-gate entry = NULL;
21637c478bd9Sstevel@tonic-gate }
21647c478bd9Sstevel@tonic-gate }
21657c478bd9Sstevel@tonic-gate }
21667c478bd9Sstevel@tonic-gate
21677c478bd9Sstevel@tonic-gate if ((error == 0) && (entry != NULL)) {
21687c478bd9Sstevel@tonic-gate *list = entry->avail_specs_list;
21697c478bd9Sstevel@tonic-gate }
21707c478bd9Sstevel@tonic-gate
21717c478bd9Sstevel@tonic-gate return (error);
21727c478bd9Sstevel@tonic-gate }
21737c478bd9Sstevel@tonic-gate
21747c478bd9Sstevel@tonic-gate /*
21757c478bd9Sstevel@tonic-gate * FUNCTION: get_default_unavail_spec_list(defaults_t *defaults,
21767c478bd9Sstevel@tonic-gate * char *dsname, dlist_t **list)
21777c478bd9Sstevel@tonic-gate *
21787c478bd9Sstevel@tonic-gate * INPUT: defaults - a pointer to a defaults_t struct
21797c478bd9Sstevel@tonic-gate * dsname - the name of the diskset whose defaults should be used
21807c478bd9Sstevel@tonic-gate *
21817c478bd9Sstevel@tonic-gate * OUTPUT: list - pointer to a list of device_spec_t corresponding
21827c478bd9Sstevel@tonic-gate * to the devices specified as unavailable by the
21837c478bd9Sstevel@tonic-gate * defaults for the named diskset, or the global
21847c478bd9Sstevel@tonic-gate * defaults for all disksets.
21857c478bd9Sstevel@tonic-gate *
21867c478bd9Sstevel@tonic-gate * RETURNS: int - 0 on success
21877c478bd9Sstevel@tonic-gate * !0 otherwise.
21887c478bd9Sstevel@tonic-gate *
21897c478bd9Sstevel@tonic-gate * PURPOSE: Function which locates or builds the list of device_spec_t
21907c478bd9Sstevel@tonic-gate * for the unavailable devices for the named diskset.
21917c478bd9Sstevel@tonic-gate *
21927c478bd9Sstevel@tonic-gate * Locates the defaults for the named diskset, if there are none,
21937c478bd9Sstevel@tonic-gate * locates the global defaults for all disksets.
21947c478bd9Sstevel@tonic-gate *
21957c478bd9Sstevel@tonic-gate * The defaults devconfig_t struct is then used to look up the
21967c478bd9Sstevel@tonic-gate * the corresponding entry in the request_spec_list cache.
21977c478bd9Sstevel@tonic-gate *
21987c478bd9Sstevel@tonic-gate * If there is currently no entry in the cache for the defaults,
21997c478bd9Sstevel@tonic-gate * an entry is built and added.
22007c478bd9Sstevel@tonic-gate *
22017c478bd9Sstevel@tonic-gate * The entry's list of unavailable device_spec_t is returned.
22027c478bd9Sstevel@tonic-gate */
22037c478bd9Sstevel@tonic-gate static int
get_default_unavail_spec_list(defaults_t * alldefaults,char * dsname,dlist_t ** list)22047c478bd9Sstevel@tonic-gate get_default_unavail_spec_list(
22057c478bd9Sstevel@tonic-gate defaults_t *alldefaults,
22067c478bd9Sstevel@tonic-gate char *dsname,
22077c478bd9Sstevel@tonic-gate dlist_t **list)
22087c478bd9Sstevel@tonic-gate {
22097c478bd9Sstevel@tonic-gate request_spec_list_t *entry = NULL;
22107c478bd9Sstevel@tonic-gate devconfig_t *defaults = NULL;
22117c478bd9Sstevel@tonic-gate int error = 0;
22127c478bd9Sstevel@tonic-gate
22137c478bd9Sstevel@tonic-gate /* Get diskset defaults, or global if none for diskset */
22147c478bd9Sstevel@tonic-gate error = defaults_get_diskset_by_name(
22157c478bd9Sstevel@tonic-gate alldefaults, dsname, &defaults);
22167c478bd9Sstevel@tonic-gate
22177c478bd9Sstevel@tonic-gate if (error != 0) {
22187c478bd9Sstevel@tonic-gate
22197c478bd9Sstevel@tonic-gate if (error == ENOENT) {
22207c478bd9Sstevel@tonic-gate /* to get global defaults, pass a NULL diskset name */
22217c478bd9Sstevel@tonic-gate error = defaults_get_diskset_by_name(
22227c478bd9Sstevel@tonic-gate alldefaults, NULL, &defaults);
22237c478bd9Sstevel@tonic-gate }
22247c478bd9Sstevel@tonic-gate
22257c478bd9Sstevel@tonic-gate if (error != 0) {
22267c478bd9Sstevel@tonic-gate if (error != ENOENT) {
22277c478bd9Sstevel@tonic-gate oprintf(OUTPUT_DEBUG,
22287c478bd9Sstevel@tonic-gate gettext("get defaults for %s returned %d\n"),
22297c478bd9Sstevel@tonic-gate dsname, error);
22307c478bd9Sstevel@tonic-gate } else {
22317c478bd9Sstevel@tonic-gate error = 0;
22327c478bd9Sstevel@tonic-gate }
22337c478bd9Sstevel@tonic-gate }
22347c478bd9Sstevel@tonic-gate }
22357c478bd9Sstevel@tonic-gate
22367c478bd9Sstevel@tonic-gate if ((entry = find_request_spec_list_entry(defaults)) == NULL) {
22377c478bd9Sstevel@tonic-gate
22387c478bd9Sstevel@tonic-gate /* create new entry for these defaults */
22397c478bd9Sstevel@tonic-gate error = make_request_spec_list_entry(
22407c478bd9Sstevel@tonic-gate defaults,
22417c478bd9Sstevel@tonic-gate devconfig_get_available(defaults),
22427c478bd9Sstevel@tonic-gate devconfig_get_unavailable(defaults),
22437c478bd9Sstevel@tonic-gate &entry);
22447c478bd9Sstevel@tonic-gate
22457c478bd9Sstevel@tonic-gate if ((error == 0) && (entry != NULL)) {
22467c478bd9Sstevel@tonic-gate if ((error = add_request_spec_list_entry(entry)) != 0) {
22477c478bd9Sstevel@tonic-gate destroy_request_spec_list_entry(entry);
22487c478bd9Sstevel@tonic-gate entry = NULL;
22497c478bd9Sstevel@tonic-gate }
22507c478bd9Sstevel@tonic-gate }
22517c478bd9Sstevel@tonic-gate }
22527c478bd9Sstevel@tonic-gate
22537c478bd9Sstevel@tonic-gate if ((error == 0) && (entry != NULL)) {
22547c478bd9Sstevel@tonic-gate *list = entry->unavail_specs_list;
22557c478bd9Sstevel@tonic-gate }
22567c478bd9Sstevel@tonic-gate
22577c478bd9Sstevel@tonic-gate return (error);
22587c478bd9Sstevel@tonic-gate }
22597c478bd9Sstevel@tonic-gate
22607c478bd9Sstevel@tonic-gate /*
22617c478bd9Sstevel@tonic-gate * FUNCTION: is_named_device_avail(devconfig_t *request, char *device_name,
22627c478bd9Sstevel@tonic-gate * boolean_t check_aliases, boolean_t *avail)
22637c478bd9Sstevel@tonic-gate *
22647c478bd9Sstevel@tonic-gate * INPUT: request - the current request devconfig_t
22657c478bd9Sstevel@tonic-gate * device_name - char * device name
22667c478bd9Sstevel@tonic-gate * check_aliases - boolean_t which indicates whether the device's
22677c478bd9Sstevel@tonic-gate * aliases should be considered by the availability checks.
22687c478bd9Sstevel@tonic-gate *
22697c478bd9Sstevel@tonic-gate * OUTPUT: avail - a boolean_t * to hold the result
22707c478bd9Sstevel@tonic-gate *
22717c478bd9Sstevel@tonic-gate * RETURNS: int - !0 on error
22727c478bd9Sstevel@tonic-gate *
22737c478bd9Sstevel@tonic-gate * avail is set to B_TRUE if the named device is available for
22747c478bd9Sstevel@tonic-gate * the input request, B_FALSE otherwise.
22757c478bd9Sstevel@tonic-gate *
22767c478bd9Sstevel@tonic-gate * PURPOSE: Determine if the named device can be used to satisfy the
22777c478bd9Sstevel@tonic-gate * input request.
22787c478bd9Sstevel@tonic-gate *
22797c478bd9Sstevel@tonic-gate * There are several levels at which device availabiity or
22807c478bd9Sstevel@tonic-gate * unavailability may be specifed:
22817c478bd9Sstevel@tonic-gate *
22827c478bd9Sstevel@tonic-gate * 1. the volume subrequest,
22837c478bd9Sstevel@tonic-gate * 2. the toplevel (diskset) request,
22847c478bd9Sstevel@tonic-gate * 3. the diskset-specific defaults
22857c478bd9Sstevel@tonic-gate * 4. the global defaults
22867c478bd9Sstevel@tonic-gate *
22877c478bd9Sstevel@tonic-gate * If the diskset-specific defaults exist, only they are checked.
22887c478bd9Sstevel@tonic-gate *
22897c478bd9Sstevel@tonic-gate * The precedence ordering that is enforced:
22907c478bd9Sstevel@tonic-gate *
22917c478bd9Sstevel@tonic-gate * 1. if request has an avail list, the name must be in it
22927c478bd9Sstevel@tonic-gate * and not in the request's unavail list.
22937c478bd9Sstevel@tonic-gate * 2. if request has an unavail list, the name must not be in it.
22947c478bd9Sstevel@tonic-gate * 3. if toplevel request has an avail list, the name must be
22957c478bd9Sstevel@tonic-gate * in it and not in the toplevel request's unavailable
22967c478bd9Sstevel@tonic-gate * list.
22977c478bd9Sstevel@tonic-gate * 4. if toplevel request has an unavail list, the name must
22987c478bd9Sstevel@tonic-gate * not be in it.
22997c478bd9Sstevel@tonic-gate * 5. if defaults have an avail list, the name must be in it
23007c478bd9Sstevel@tonic-gate * and not in the defaults unavailable list.
23017c478bd9Sstevel@tonic-gate * 6. if defaults have an unavail list, the name must not be
23027c478bd9Sstevel@tonic-gate * in it.
23037c478bd9Sstevel@tonic-gate */
23047c478bd9Sstevel@tonic-gate static int
is_named_device_avail(devconfig_t * request,char * device_name,boolean_t check_aliases,boolean_t * avail)23057c478bd9Sstevel@tonic-gate is_named_device_avail(
23067c478bd9Sstevel@tonic-gate devconfig_t *request,
23077c478bd9Sstevel@tonic-gate char *device_name,
23087c478bd9Sstevel@tonic-gate boolean_t check_aliases,
23097c478bd9Sstevel@tonic-gate boolean_t *avail)
23107c478bd9Sstevel@tonic-gate {
23117c478bd9Sstevel@tonic-gate typedef enum check_types {
23127c478bd9Sstevel@tonic-gate DEVICE_REQUEST = 0,
23137c478bd9Sstevel@tonic-gate DISKSET_REQUEST,
23147c478bd9Sstevel@tonic-gate DEFAULTS,
23157c478bd9Sstevel@tonic-gate N_CHECKS
23167c478bd9Sstevel@tonic-gate } check_type_t;
23177c478bd9Sstevel@tonic-gate
23187c478bd9Sstevel@tonic-gate check_type_t check_type;
23197c478bd9Sstevel@tonic-gate
23207c478bd9Sstevel@tonic-gate typedef enum list_types {
23217c478bd9Sstevel@tonic-gate AVAIL = 0,
23227c478bd9Sstevel@tonic-gate UNAVAIL,
23237c478bd9Sstevel@tonic-gate N_LISTS
23247c478bd9Sstevel@tonic-gate } list_type_t;
23257c478bd9Sstevel@tonic-gate
23267c478bd9Sstevel@tonic-gate dlist_t *lists[N_CHECKS][N_LISTS];
23277c478bd9Sstevel@tonic-gate boolean_t includes;
23287c478bd9Sstevel@tonic-gate int error = 0;
23297c478bd9Sstevel@tonic-gate
23307c478bd9Sstevel@tonic-gate memset(lists, 0, (N_CHECKS * N_LISTS) * sizeof (dlist_t *));
23317c478bd9Sstevel@tonic-gate
23327c478bd9Sstevel@tonic-gate if (request != NULL) {
23337c478bd9Sstevel@tonic-gate /* get avail/unavail specs for request */
23347c478bd9Sstevel@tonic-gate ((error = get_request_avail_spec_list(
23357c478bd9Sstevel@tonic-gate request, &lists[DEVICE_REQUEST][AVAIL])) != 0) ||
23367c478bd9Sstevel@tonic-gate (error = get_request_unavail_spec_list(
23377c478bd9Sstevel@tonic-gate request, &lists[DEVICE_REQUEST][UNAVAIL]));
23387c478bd9Sstevel@tonic-gate }
23397c478bd9Sstevel@tonic-gate
23407c478bd9Sstevel@tonic-gate if ((error == 0) && (_toplevel_request != NULL)) {
23417c478bd9Sstevel@tonic-gate /* diskset request */
23427c478bd9Sstevel@tonic-gate ((error = get_request_avail_spec_list(
23437c478bd9Sstevel@tonic-gate _toplevel_request, &lists[DISKSET_REQUEST][AVAIL])) != 0) ||
23447c478bd9Sstevel@tonic-gate (error = get_request_unavail_spec_list(
23457c478bd9Sstevel@tonic-gate _toplevel_request, &lists[DISKSET_REQUEST][UNAVAIL]));
23467c478bd9Sstevel@tonic-gate }
23477c478bd9Sstevel@tonic-gate
23487c478bd9Sstevel@tonic-gate if ((error == 0) && (_defaults != NULL)) {
23497c478bd9Sstevel@tonic-gate /* and diskset/global defaults */
23507c478bd9Sstevel@tonic-gate ((error = get_default_avail_spec_list(_defaults,
23517c478bd9Sstevel@tonic-gate get_request_diskset(), &lists[DEFAULTS][AVAIL])) != 0) ||
23527c478bd9Sstevel@tonic-gate (error = get_default_unavail_spec_list(_defaults,
23537c478bd9Sstevel@tonic-gate get_request_diskset(), &lists[DEFAULTS][UNAVAIL]));
23547c478bd9Sstevel@tonic-gate }
23557c478bd9Sstevel@tonic-gate
23567c478bd9Sstevel@tonic-gate if (error != 0) {
23577c478bd9Sstevel@tonic-gate return (error);
23587c478bd9Sstevel@tonic-gate }
23597c478bd9Sstevel@tonic-gate
23607c478bd9Sstevel@tonic-gate *avail = B_TRUE;
23617c478bd9Sstevel@tonic-gate
23627c478bd9Sstevel@tonic-gate for (check_type = DEVICE_REQUEST;
23637c478bd9Sstevel@tonic-gate (check_type < N_CHECKS) && (error == 0);
23647c478bd9Sstevel@tonic-gate check_type++) {
23657c478bd9Sstevel@tonic-gate
23667c478bd9Sstevel@tonic-gate if (lists[check_type][AVAIL] != NULL) {
23677c478bd9Sstevel@tonic-gate
23687c478bd9Sstevel@tonic-gate /* does avail spec list include named device? */
23697c478bd9Sstevel@tonic-gate if ((error = avail_list_includes_device_name(
23707c478bd9Sstevel@tonic-gate lists[check_type][AVAIL], device_name, check_aliases,
23717c478bd9Sstevel@tonic-gate &includes)) == 0) {
23727c478bd9Sstevel@tonic-gate
23737c478bd9Sstevel@tonic-gate if (includes != B_TRUE) {
23747c478bd9Sstevel@tonic-gate *avail = B_FALSE;
23757c478bd9Sstevel@tonic-gate }
23767c478bd9Sstevel@tonic-gate
23777c478bd9Sstevel@tonic-gate if ((includes == B_TRUE) &&
23787c478bd9Sstevel@tonic-gate (lists[check_type][UNAVAIL] != NULL)) {
23797c478bd9Sstevel@tonic-gate
23807c478bd9Sstevel@tonic-gate /* device is available, is it in the unavail list? */
23817c478bd9Sstevel@tonic-gate if ((error = unavail_list_includes_device_name(
23827c478bd9Sstevel@tonic-gate lists[check_type][UNAVAIL], device_name,
23837c478bd9Sstevel@tonic-gate check_aliases, &includes)) == 0) {
23847c478bd9Sstevel@tonic-gate
23857c478bd9Sstevel@tonic-gate if (includes == B_TRUE) {
23867c478bd9Sstevel@tonic-gate *avail = B_FALSE;
23877c478bd9Sstevel@tonic-gate }
23887c478bd9Sstevel@tonic-gate }
23897c478bd9Sstevel@tonic-gate }
23907c478bd9Sstevel@tonic-gate }
23917c478bd9Sstevel@tonic-gate
23927c478bd9Sstevel@tonic-gate /* lists at this level checked, skip remainder */
23937c478bd9Sstevel@tonic-gate break;
23947c478bd9Sstevel@tonic-gate
23957c478bd9Sstevel@tonic-gate } else if (lists[check_type][UNAVAIL] != NULL) {
23967c478bd9Sstevel@tonic-gate
23977c478bd9Sstevel@tonic-gate /* does unavail spec list include named device? */
23987c478bd9Sstevel@tonic-gate if ((error = unavail_list_includes_device_name(
23997c478bd9Sstevel@tonic-gate lists[check_type][UNAVAIL], device_name,
24007c478bd9Sstevel@tonic-gate check_aliases, &includes)) == 0) {
24017c478bd9Sstevel@tonic-gate
24027c478bd9Sstevel@tonic-gate if (includes == B_TRUE) {
24037c478bd9Sstevel@tonic-gate *avail = B_FALSE;
24047c478bd9Sstevel@tonic-gate }
24057c478bd9Sstevel@tonic-gate }
24067c478bd9Sstevel@tonic-gate
24077c478bd9Sstevel@tonic-gate /* list at this level checked, skip remainder */
24087c478bd9Sstevel@tonic-gate break;
24097c478bd9Sstevel@tonic-gate }
24107c478bd9Sstevel@tonic-gate }
24117c478bd9Sstevel@tonic-gate
24127c478bd9Sstevel@tonic-gate return (error);
24137c478bd9Sstevel@tonic-gate }
24147c478bd9Sstevel@tonic-gate
24157c478bd9Sstevel@tonic-gate /*
24167c478bd9Sstevel@tonic-gate * FUNCTION: avail_list_includes_device_name(dlist_t *list,
24177c478bd9Sstevel@tonic-gate * char *device_name, boolean_t check_aliases,
24187c478bd9Sstevel@tonic-gate * boolean_t *includes)
24197c478bd9Sstevel@tonic-gate *
24207c478bd9Sstevel@tonic-gate * INPUT: list - a dlist_t list of available device_spec_t
24217c478bd9Sstevel@tonic-gate * device_name - a char * device CTD name
24227c478bd9Sstevel@tonic-gate * check_aliases - boolean_t which indicates if the device's
24237c478bd9Sstevel@tonic-gate * aliases should be considered in the availability
24247c478bd9Sstevel@tonic-gate * checking.
24257c478bd9Sstevel@tonic-gate *
24267c478bd9Sstevel@tonic-gate * OUTPUT: includes - B_TRUE - if named device is "included" by any
24277c478bd9Sstevel@tonic-gate * specification in the input list
24287c478bd9Sstevel@tonic-gate * B_FALSE - otherwise
24297c478bd9Sstevel@tonic-gate *
24307c478bd9Sstevel@tonic-gate * RETURNS: int - 0 on success
24317c478bd9Sstevel@tonic-gate * - !0 otherwise
24327c478bd9Sstevel@tonic-gate *
24337c478bd9Sstevel@tonic-gate * PURPOSE: Helper used by is_named_device_avail that determines
24347c478bd9Sstevel@tonic-gate * if the input list of device specifications "includes"
24357c478bd9Sstevel@tonic-gate * a specific device.
24367c478bd9Sstevel@tonic-gate *
24377c478bd9Sstevel@tonic-gate * Iterates the elements of the input array and searches
24387c478bd9Sstevel@tonic-gate * for a match using spec_includes_device_name().
24397c478bd9Sstevel@tonic-gate */
24407c478bd9Sstevel@tonic-gate static int
avail_list_includes_device_name(dlist_t * list,char * device_name,boolean_t check_aliases,boolean_t * includes)24417c478bd9Sstevel@tonic-gate avail_list_includes_device_name(
24427c478bd9Sstevel@tonic-gate dlist_t *list,
24437c478bd9Sstevel@tonic-gate char *device_name,
24447c478bd9Sstevel@tonic-gate boolean_t check_aliases,
24457c478bd9Sstevel@tonic-gate boolean_t *includes)
24467c478bd9Sstevel@tonic-gate {
24477c478bd9Sstevel@tonic-gate dlist_t *iter = NULL;
24487c478bd9Sstevel@tonic-gate int error = 0;
24497c478bd9Sstevel@tonic-gate
24507c478bd9Sstevel@tonic-gate *includes = B_FALSE;
24517c478bd9Sstevel@tonic-gate
24527c478bd9Sstevel@tonic-gate for (iter = list;
24537c478bd9Sstevel@tonic-gate (*includes == B_FALSE) && (iter != NULL) && (error == 0);
24547c478bd9Sstevel@tonic-gate iter = iter->next) {
24557c478bd9Sstevel@tonic-gate
24567c478bd9Sstevel@tonic-gate device_spec_t *spec = (device_spec_t *)iter->obj;
24577c478bd9Sstevel@tonic-gate error = spec_includes_device_name(spec, device_name,
24587c478bd9Sstevel@tonic-gate check_aliases, includes);
24597c478bd9Sstevel@tonic-gate }
24607c478bd9Sstevel@tonic-gate
24617c478bd9Sstevel@tonic-gate return (0);
24627c478bd9Sstevel@tonic-gate }
24637c478bd9Sstevel@tonic-gate
24647c478bd9Sstevel@tonic-gate /*
24657c478bd9Sstevel@tonic-gate * FUNCTION: unavail_list_includes_device_name(dlist_t *list,
24667c478bd9Sstevel@tonic-gate * char *device_name, boolean_t check_aliases,
24677c478bd9Sstevel@tonic-gate * boolean_t *includes)
24687c478bd9Sstevel@tonic-gate *
24697c478bd9Sstevel@tonic-gate * INPUT: list - a dlist_t list of unavailable device_spec_t
24707c478bd9Sstevel@tonic-gate * device_name - a char * device CTD name
24717c478bd9Sstevel@tonic-gate * check_aliases - boolean_t which indicates if the device's
24727c478bd9Sstevel@tonic-gate * aliases should be considered in the availability
24737c478bd9Sstevel@tonic-gate * checking.
24747c478bd9Sstevel@tonic-gate *
24757c478bd9Sstevel@tonic-gate * OUTPUT: includes - B_TRUE - if named device is "included" by any
24767c478bd9Sstevel@tonic-gate * specification in the input list
24777c478bd9Sstevel@tonic-gate * B_FALSE - otherwise
24787c478bd9Sstevel@tonic-gate *
24797c478bd9Sstevel@tonic-gate * RETURNS: int - 0 on success
24807c478bd9Sstevel@tonic-gate * - !0 otherwise
24817c478bd9Sstevel@tonic-gate *
24827c478bd9Sstevel@tonic-gate * PURPOSE: Helper used by is_named_device_avail that determines
24837c478bd9Sstevel@tonic-gate * if the input list of device specifications "includes"
24847c478bd9Sstevel@tonic-gate * a specific device.
24857c478bd9Sstevel@tonic-gate *
24867c478bd9Sstevel@tonic-gate * Iterates the elements of the input array and searches
24877c478bd9Sstevel@tonic-gate * for a match using spec_includes_device_name_or_alias().
24887c478bd9Sstevel@tonic-gate */
24897c478bd9Sstevel@tonic-gate static int
unavail_list_includes_device_name(dlist_t * list,char * device_name,boolean_t check_aliases,boolean_t * includes)24907c478bd9Sstevel@tonic-gate unavail_list_includes_device_name(
24917c478bd9Sstevel@tonic-gate dlist_t *list,
24927c478bd9Sstevel@tonic-gate char *device_name,
24937c478bd9Sstevel@tonic-gate boolean_t check_aliases,
24947c478bd9Sstevel@tonic-gate boolean_t *includes)
24957c478bd9Sstevel@tonic-gate {
24967c478bd9Sstevel@tonic-gate dlist_t *iter = NULL;
24977c478bd9Sstevel@tonic-gate int error = 0;
24987c478bd9Sstevel@tonic-gate device_spec_t *unavail_spec;
24997c478bd9Sstevel@tonic-gate boolean_t check_for_alternate_hba = B_FALSE;
25007c478bd9Sstevel@tonic-gate
25017c478bd9Sstevel@tonic-gate *includes = B_FALSE;
25027c478bd9Sstevel@tonic-gate
25037c478bd9Sstevel@tonic-gate /*
25047c478bd9Sstevel@tonic-gate * the specs in the list are in descending order of specificity.
25057c478bd9Sstevel@tonic-gate * so a more exact spec will rule the device out before a less
25067c478bd9Sstevel@tonic-gate * exact spec.
25077c478bd9Sstevel@tonic-gate *
25087c478bd9Sstevel@tonic-gate * Meaning: if the list has { "c3t0d0", ..., "c3", ... } and the
25097c478bd9Sstevel@tonic-gate * input device name is "c3t0d0s0", it will match "c3t0d0"
25107c478bd9Sstevel@tonic-gate * before "c3".
25117c478bd9Sstevel@tonic-gate *
25127c478bd9Sstevel@tonic-gate * This is important for the multi-path alias checking below.
25137c478bd9Sstevel@tonic-gate * If the input device name is ruled out by a non-controller
25147c478bd9Sstevel@tonic-gate * specification, it is really unavailable.
25157c478bd9Sstevel@tonic-gate */
25167c478bd9Sstevel@tonic-gate for (iter = list;
25177c478bd9Sstevel@tonic-gate (*includes == B_FALSE) && (iter != NULL);
25187c478bd9Sstevel@tonic-gate iter = iter->next) {
25197c478bd9Sstevel@tonic-gate
25207c478bd9Sstevel@tonic-gate unavail_spec = (device_spec_t *)iter->obj;
25217c478bd9Sstevel@tonic-gate error = spec_includes_device_name(
25227c478bd9Sstevel@tonic-gate unavail_spec, device_name, check_aliases, includes);
25237c478bd9Sstevel@tonic-gate
25247c478bd9Sstevel@tonic-gate }
25257c478bd9Sstevel@tonic-gate
25267c478bd9Sstevel@tonic-gate if ((error == 0) && (*includes == B_TRUE)) {
25277c478bd9Sstevel@tonic-gate
25287c478bd9Sstevel@tonic-gate /* matched an unavailable spec, was it a controller/HBA? */
25297c478bd9Sstevel@tonic-gate oprintf(OUTPUT_DEBUG,
25307c478bd9Sstevel@tonic-gate "device \"%s\" is unavailable, "
25317c478bd9Sstevel@tonic-gate "it matched \"c(%d)t(%d)d(%d)s(%d)\"\n",
25327c478bd9Sstevel@tonic-gate device_name,
25337c478bd9Sstevel@tonic-gate unavail_spec->data.ctd->ctrl,
25347c478bd9Sstevel@tonic-gate unavail_spec->data.ctd->target,
25357c478bd9Sstevel@tonic-gate unavail_spec->data.ctd->lun,
25367c478bd9Sstevel@tonic-gate unavail_spec->data.ctd->slice);
25377c478bd9Sstevel@tonic-gate
25387c478bd9Sstevel@tonic-gate if ((unavail_spec->data.ctd->ctrl != ID_UNSPECIFIED) &&
25397c478bd9Sstevel@tonic-gate (unavail_spec->data.ctd->target == ID_UNSPECIFIED) &&
25407c478bd9Sstevel@tonic-gate (unavail_spec->data.ctd->lun == ID_UNSPECIFIED) &&
25417c478bd9Sstevel@tonic-gate (unavail_spec->data.ctd->slice == ID_UNSPECIFIED)) {
25427c478bd9Sstevel@tonic-gate
25437c478bd9Sstevel@tonic-gate /*
25447c478bd9Sstevel@tonic-gate * Need to see if the named device is a disk or slice,
25457c478bd9Sstevel@tonic-gate * and if so check to see if the it is multipathed
25467c478bd9Sstevel@tonic-gate * and possibly accessible thru another controller/HBA.
25477c478bd9Sstevel@tonic-gate */
25487c478bd9Sstevel@tonic-gate check_for_alternate_hba = B_TRUE;
25497c478bd9Sstevel@tonic-gate }
25507c478bd9Sstevel@tonic-gate }
25517c478bd9Sstevel@tonic-gate
25527c478bd9Sstevel@tonic-gate if ((error == 0) && (check_for_alternate_hba == B_TRUE)) {
25537c478bd9Sstevel@tonic-gate
25547c478bd9Sstevel@tonic-gate dm_descriptor_t slice = (dm_descriptor_t)0;
25557c478bd9Sstevel@tonic-gate dm_descriptor_t disk = (dm_descriptor_t)0;
25567c478bd9Sstevel@tonic-gate
25577c478bd9Sstevel@tonic-gate ((error = slice_get_by_name(device_name, &slice)) != 0) ||
25587c478bd9Sstevel@tonic-gate (error = disk_get_by_name(device_name, &disk));
25597c478bd9Sstevel@tonic-gate if (error != 0) {
25607c478bd9Sstevel@tonic-gate return (error);
25617c478bd9Sstevel@tonic-gate }
25627c478bd9Sstevel@tonic-gate
25637c478bd9Sstevel@tonic-gate /* if it is a slice, get its disk */
25647c478bd9Sstevel@tonic-gate if ((error == 0) && (slice != (dm_descriptor_t)0)) {
25657c478bd9Sstevel@tonic-gate error = slice_get_disk(slice, &disk);
25667c478bd9Sstevel@tonic-gate }
25677c478bd9Sstevel@tonic-gate
25687c478bd9Sstevel@tonic-gate if ((error == 0) && (disk != (dm_descriptor_t)0)) {
25697c478bd9Sstevel@tonic-gate
25707c478bd9Sstevel@tonic-gate /* see if all the disk's HBAs are unavailable */
25717c478bd9Sstevel@tonic-gate dlist_t *hbas = NULL;
25727c478bd9Sstevel@tonic-gate dlist_t *iter = NULL;
25737c478bd9Sstevel@tonic-gate
25747c478bd9Sstevel@tonic-gate error = disk_get_hbas(disk, &hbas);
25757c478bd9Sstevel@tonic-gate
25767c478bd9Sstevel@tonic-gate if (hbas != NULL) {
25777c478bd9Sstevel@tonic-gate oprintf(OUTPUT_DEBUG,
25787c478bd9Sstevel@tonic-gate gettext(" checking alternate paths for %s\n"),
25797c478bd9Sstevel@tonic-gate device_name);
25807c478bd9Sstevel@tonic-gate } else {
25817c478bd9Sstevel@tonic-gate oprintf(OUTPUT_DEBUG,
25827c478bd9Sstevel@tonic-gate gettext(" no alternate paths for %s\n"),
25837c478bd9Sstevel@tonic-gate device_name);
25847c478bd9Sstevel@tonic-gate }
25857c478bd9Sstevel@tonic-gate
25867c478bd9Sstevel@tonic-gate /* for each of the disk's HBAs */
25877c478bd9Sstevel@tonic-gate for (iter = hbas;
25887c478bd9Sstevel@tonic-gate (iter != NULL) && (*includes == B_TRUE) && (error == 0);
25897c478bd9Sstevel@tonic-gate iter = iter->next) {
25907c478bd9Sstevel@tonic-gate
25917c478bd9Sstevel@tonic-gate dm_descriptor_t hba = (uintptr_t)iter->obj;
25927c478bd9Sstevel@tonic-gate device_spec_t *hbaspec;
25937c478bd9Sstevel@tonic-gate char *hbaname = NULL;
25947c478bd9Sstevel@tonic-gate dlist_t *iter2 = NULL;
25957c478bd9Sstevel@tonic-gate
25967c478bd9Sstevel@tonic-gate *includes = B_FALSE;
25977c478bd9Sstevel@tonic-gate
25987c478bd9Sstevel@tonic-gate ((error = get_display_name(hba, &hbaname)) != 0) ||
25997c478bd9Sstevel@tonic-gate (error = get_spec_for_name(hbaname, &hbaspec));
26007c478bd9Sstevel@tonic-gate
26017c478bd9Sstevel@tonic-gate /* is HBA unavailable? */
26027c478bd9Sstevel@tonic-gate for (iter2 = list;
26037c478bd9Sstevel@tonic-gate (iter2 != NULL) && (error == 0) &&
26047c478bd9Sstevel@tonic-gate (*includes == B_FALSE);
26057c478bd9Sstevel@tonic-gate iter2 = iter2->next) {
26067c478bd9Sstevel@tonic-gate
26077c478bd9Sstevel@tonic-gate device_spec_t *spec =
26087c478bd9Sstevel@tonic-gate (device_spec_t *)iter2->obj;
26097c478bd9Sstevel@tonic-gate
26107c478bd9Sstevel@tonic-gate *includes = spec_includes_device(spec, hbaspec);
26117c478bd9Sstevel@tonic-gate }
26127c478bd9Sstevel@tonic-gate }
26137c478bd9Sstevel@tonic-gate dlist_free_items(hbas, NULL);
26147c478bd9Sstevel@tonic-gate
26157c478bd9Sstevel@tonic-gate /* if *includes==B_TRUE here, all HBAs are unavailable */
26167c478bd9Sstevel@tonic-gate }
26177c478bd9Sstevel@tonic-gate }
26187c478bd9Sstevel@tonic-gate
26197c478bd9Sstevel@tonic-gate return (error);
26207c478bd9Sstevel@tonic-gate }
26217c478bd9Sstevel@tonic-gate
26227c478bd9Sstevel@tonic-gate /*
26237c478bd9Sstevel@tonic-gate * FUNCTION: spec_includes_device_name(device_spec_t *spec,
26247c478bd9Sstevel@tonic-gate * char *device_name, boolean_t check_aliases,
26257c478bd9Sstevel@tonic-gate * boolean_t *includes)
26267c478bd9Sstevel@tonic-gate *
26277c478bd9Sstevel@tonic-gate * INPUT: spec - a device_spec_t CTD specification.
26287c478bd9Sstevel@tonic-gate * device_name - a char * device CTD name
26297c478bd9Sstevel@tonic-gate * check_aliases - boolean_t which indicates if the device's
26307c478bd9Sstevel@tonic-gate * aliases should be considered in the checking.
26317c478bd9Sstevel@tonic-gate *
26327c478bd9Sstevel@tonic-gate * OUTPUT: includes - B_TRUE - if device is "included" by the input
26337c478bd9Sstevel@tonic-gate * specification
26347c478bd9Sstevel@tonic-gate * B_FALSE - otherwise
26357c478bd9Sstevel@tonic-gate *
26367c478bd9Sstevel@tonic-gate * RETURNS: int - 0 on success
26377c478bd9Sstevel@tonic-gate * - !0 otherwise
26387c478bd9Sstevel@tonic-gate *
26397c478bd9Sstevel@tonic-gate * PURPOSE: Helper used by (un)avail_specs_includes_device_name() that
26407c478bd9Sstevel@tonic-gate * determines if the input device specification "includes"
26417c478bd9Sstevel@tonic-gate * the named device.
26427c478bd9Sstevel@tonic-gate *
26437c478bd9Sstevel@tonic-gate * If check_aliases is true and the named device is a slice or
26447c478bd9Sstevel@tonic-gate * a disk drive, its multi-pathed aliases are also checked
26457c478bd9Sstevel@tonic-gate * against the spec.
26467c478bd9Sstevel@tonic-gate */
26477c478bd9Sstevel@tonic-gate static int
spec_includes_device_name(device_spec_t * spec,char * device_name,boolean_t check_aliases,boolean_t * includes)26487c478bd9Sstevel@tonic-gate spec_includes_device_name(
26497c478bd9Sstevel@tonic-gate device_spec_t *spec,
26507c478bd9Sstevel@tonic-gate char *device_name,
26517c478bd9Sstevel@tonic-gate boolean_t check_aliases,
26527c478bd9Sstevel@tonic-gate boolean_t *includes)
26537c478bd9Sstevel@tonic-gate {
26547c478bd9Sstevel@tonic-gate device_spec_t *device_spec;
26557c478bd9Sstevel@tonic-gate int error = 0;
26567c478bd9Sstevel@tonic-gate
26577c478bd9Sstevel@tonic-gate error = get_spec_for_name(device_name, &device_spec);
26587c478bd9Sstevel@tonic-gate if (error == 0) {
26597c478bd9Sstevel@tonic-gate
26607c478bd9Sstevel@tonic-gate *includes = spec_includes_device(spec, device_spec);
26617c478bd9Sstevel@tonic-gate
26627c478bd9Sstevel@tonic-gate if ((*includes == B_FALSE) && (check_aliases == B_TRUE)) {
26637c478bd9Sstevel@tonic-gate
26647c478bd9Sstevel@tonic-gate /* spec doesn't include name, check aliases */
26657c478bd9Sstevel@tonic-gate
26667c478bd9Sstevel@tonic-gate dm_descriptor_t device = (dm_descriptor_t)0;
26677c478bd9Sstevel@tonic-gate dlist_t *aliases = NULL;
26687c478bd9Sstevel@tonic-gate
26697c478bd9Sstevel@tonic-gate /* only slices and disks have aliases */
26707c478bd9Sstevel@tonic-gate error = slice_get_by_name(device_name, &device);
26717c478bd9Sstevel@tonic-gate if (device != (dm_descriptor_t)0) {
26727c478bd9Sstevel@tonic-gate error = get_aliases(device, &aliases);
26737c478bd9Sstevel@tonic-gate } else if (error == 0) {
26747c478bd9Sstevel@tonic-gate error = disk_get_by_name(device_name, &device);
26757c478bd9Sstevel@tonic-gate if (device != (dm_descriptor_t)0) {
26767c478bd9Sstevel@tonic-gate error = get_aliases(device, &aliases);
26777c478bd9Sstevel@tonic-gate }
26787c478bd9Sstevel@tonic-gate }
26797c478bd9Sstevel@tonic-gate
26807c478bd9Sstevel@tonic-gate if ((error == 0) && (aliases != NULL)) {
26817c478bd9Sstevel@tonic-gate
26827c478bd9Sstevel@tonic-gate dlist_t *iter;
26837c478bd9Sstevel@tonic-gate for (iter = aliases;
26847c478bd9Sstevel@tonic-gate (iter != NULL) && (*includes == B_FALSE) &&
26857c478bd9Sstevel@tonic-gate (error == 0);
26867c478bd9Sstevel@tonic-gate iter = iter->next) {
26877c478bd9Sstevel@tonic-gate
26887c478bd9Sstevel@tonic-gate char *alias = (char *)iter->obj;
26897c478bd9Sstevel@tonic-gate device_spec_t *alias_spec;
26907c478bd9Sstevel@tonic-gate
26917c478bd9Sstevel@tonic-gate error = get_spec_for_name(alias, &alias_spec);
26927c478bd9Sstevel@tonic-gate if (error == 0) {
26937c478bd9Sstevel@tonic-gate /* does spec include alias? */
26947c478bd9Sstevel@tonic-gate *includes = spec_includes_device(spec, alias_spec);
26957c478bd9Sstevel@tonic-gate }
26967c478bd9Sstevel@tonic-gate }
26977c478bd9Sstevel@tonic-gate }
26987c478bd9Sstevel@tonic-gate dlist_free_items(aliases, free);
26997c478bd9Sstevel@tonic-gate }
27007c478bd9Sstevel@tonic-gate }
27017c478bd9Sstevel@tonic-gate
27027c478bd9Sstevel@tonic-gate return (error);
27037c478bd9Sstevel@tonic-gate }
27047c478bd9Sstevel@tonic-gate
27057c478bd9Sstevel@tonic-gate /*
27067c478bd9Sstevel@tonic-gate * FUNCTION: destroy_device_spec(device_spec_t *spec)
27077c478bd9Sstevel@tonic-gate *
27087c478bd9Sstevel@tonic-gate * INPUT: spec - pointer to a device_spec_t
27097c478bd9Sstevel@tonic-gate *
27107c478bd9Sstevel@tonic-gate * RETURNS: nothing
27117c478bd9Sstevel@tonic-gate *
27127c478bd9Sstevel@tonic-gate * PURPOSE: Function which reclaims memory allocated to a device_spec_t.
27137c478bd9Sstevel@tonic-gate *
27147c478bd9Sstevel@tonic-gate * Frees memory allocated to hold the specific data in the spec.
27157c478bd9Sstevel@tonic-gate */
27167c478bd9Sstevel@tonic-gate static void
destroy_device_spec(device_spec_t * spec)27177c478bd9Sstevel@tonic-gate destroy_device_spec(
27187c478bd9Sstevel@tonic-gate device_spec_t *spec)
27197c478bd9Sstevel@tonic-gate {
27207c478bd9Sstevel@tonic-gate if (spec != NULL) {
27217c478bd9Sstevel@tonic-gate if (spec->type == SPEC_TYPE_CTD) {
27227c478bd9Sstevel@tonic-gate free(spec->data.ctd);
27237c478bd9Sstevel@tonic-gate } else if (spec->type == SPEC_TYPE_RAW) {
27247c478bd9Sstevel@tonic-gate free(spec->data.raw);
27257c478bd9Sstevel@tonic-gate }
27267c478bd9Sstevel@tonic-gate free(spec);
27277c478bd9Sstevel@tonic-gate }
27287c478bd9Sstevel@tonic-gate }
27297c478bd9Sstevel@tonic-gate
27307c478bd9Sstevel@tonic-gate /*
27317c478bd9Sstevel@tonic-gate * FUNCTION: create_device_spec(char *name, device_spec_t **spec);
27327c478bd9Sstevel@tonic-gate *
27337c478bd9Sstevel@tonic-gate * INPUT: name - pointer to a char* device name
27347c478bd9Sstevel@tonic-gate *
27357c478bd9Sstevel@tonic-gate * OUTPUT: spec - pointer to a device_spec_t to hold the result
27367c478bd9Sstevel@tonic-gate *
27377c478bd9Sstevel@tonic-gate * RETURNS: int - 0 on success
27387c478bd9Sstevel@tonic-gate * !0 otherwise
27397c478bd9Sstevel@tonic-gate *
27407c478bd9Sstevel@tonic-gate * PURPOSE: Function which creates a device_spec_t for the input
27417c478bd9Sstevel@tonic-gate * device name.
27427c478bd9Sstevel@tonic-gate *
27437c478bd9Sstevel@tonic-gate */
27447c478bd9Sstevel@tonic-gate static int
create_device_spec(char * name,device_spec_t ** spec)27457c478bd9Sstevel@tonic-gate create_device_spec(
27467c478bd9Sstevel@tonic-gate char *name,
27477c478bd9Sstevel@tonic-gate device_spec_t **spec)
27487c478bd9Sstevel@tonic-gate {
27497c478bd9Sstevel@tonic-gate int error = 0;
27507c478bd9Sstevel@tonic-gate
27517c478bd9Sstevel@tonic-gate /* allocate the device spec and try various parsing schemes */
27527c478bd9Sstevel@tonic-gate *spec = (device_spec_t *)calloc(1, sizeof (device_spec_t));
27537c478bd9Sstevel@tonic-gate if (*spec == NULL) {
27547c478bd9Sstevel@tonic-gate error = ENOMEM;
27557c478bd9Sstevel@tonic-gate } else {
27567c478bd9Sstevel@tonic-gate if (((error = create_device_ctd_spec(name, spec)) != 0) &&
27577c478bd9Sstevel@tonic-gate (error != ENOMEM)) {
27587c478bd9Sstevel@tonic-gate /* CTD failed, try other parsing schemes */
27597c478bd9Sstevel@tonic-gate error = create_device_raw_spec(name, spec);
27607c478bd9Sstevel@tonic-gate }
27617c478bd9Sstevel@tonic-gate }
27627c478bd9Sstevel@tonic-gate
27637c478bd9Sstevel@tonic-gate return (error);
27647c478bd9Sstevel@tonic-gate }
27657c478bd9Sstevel@tonic-gate
27667c478bd9Sstevel@tonic-gate /*
27677c478bd9Sstevel@tonic-gate * FUNCTION: create_device_ctd_spec(char *name, device_spec_t **spec);
27687c478bd9Sstevel@tonic-gate *
27697c478bd9Sstevel@tonic-gate * INPUT: name - pointer to a char* device name
27707c478bd9Sstevel@tonic-gate *
27717c478bd9Sstevel@tonic-gate * OUTPUT: spec - pointer to a device_spec_t updated with the parsed
27727c478bd9Sstevel@tonic-gate * CTD spec, if successful
27737c478bd9Sstevel@tonic-gate *
27747c478bd9Sstevel@tonic-gate * RETURNS: int - 0 on success
27757c478bd9Sstevel@tonic-gate * !0 otherwise
27767c478bd9Sstevel@tonic-gate *
27777c478bd9Sstevel@tonic-gate * PURPOSE: Function which atttempts to parse the input device name into
27787c478bd9Sstevel@tonic-gate * cXtXdXsX component ids. The ids are the integer values of each
27797c478bd9Sstevel@tonic-gate * specified segment of the input name.
27807c478bd9Sstevel@tonic-gate *
27817c478bd9Sstevel@tonic-gate * If the name doesn't contain a segment, the id is set to
27827c478bd9Sstevel@tonic-gate * ID_UNSPECIFIED.
27837c478bd9Sstevel@tonic-gate *
27847c478bd9Sstevel@tonic-gate * The input name must be well-formed.
27857c478bd9Sstevel@tonic-gate *
27867c478bd9Sstevel@tonic-gate * These are the acceptable forms:
27877c478bd9Sstevel@tonic-gate *
27887c478bd9Sstevel@tonic-gate * cXtXdXsX
27897c478bd9Sstevel@tonic-gate * cXtXdX
27907c478bd9Sstevel@tonic-gate * cXtX
27917c478bd9Sstevel@tonic-gate * cXdXsX
27927c478bd9Sstevel@tonic-gate * cXdX
27937c478bd9Sstevel@tonic-gate * cX
27947c478bd9Sstevel@tonic-gate */
27957c478bd9Sstevel@tonic-gate static int
create_device_ctd_spec(char * name,device_spec_t ** spec)27967c478bd9Sstevel@tonic-gate create_device_ctd_spec(
27977c478bd9Sstevel@tonic-gate char *name,
27987c478bd9Sstevel@tonic-gate device_spec_t **spec)
27997c478bd9Sstevel@tonic-gate {
28007c478bd9Sstevel@tonic-gate uint_t ctrl;
28017c478bd9Sstevel@tonic-gate uint_t target;
28027c478bd9Sstevel@tonic-gate uint_t lun;
28037c478bd9Sstevel@tonic-gate uint_t slice;
28047c478bd9Sstevel@tonic-gate
28057c478bd9Sstevel@tonic-gate uint_t nscan;
28067c478bd9Sstevel@tonic-gate uint_t nchars;
28077c478bd9Sstevel@tonic-gate
28087c478bd9Sstevel@tonic-gate char *device_str;
28097c478bd9Sstevel@tonic-gate char *target_str;
28107c478bd9Sstevel@tonic-gate char *ctd_str;
28117c478bd9Sstevel@tonic-gate char *t_ptr;
28127c478bd9Sstevel@tonic-gate char *d_ptr;
28137c478bd9Sstevel@tonic-gate char *s_ptr;
28147c478bd9Sstevel@tonic-gate
28157c478bd9Sstevel@tonic-gate boolean_t is_ide = B_FALSE;
28167c478bd9Sstevel@tonic-gate boolean_t got_slice = B_FALSE;
28177c478bd9Sstevel@tonic-gate boolean_t got_lun = B_FALSE;
28187c478bd9Sstevel@tonic-gate boolean_t got_target = B_FALSE;
28197c478bd9Sstevel@tonic-gate boolean_t got_ctrl = B_FALSE;
28207c478bd9Sstevel@tonic-gate
28217c478bd9Sstevel@tonic-gate int error = 0;
28227c478bd9Sstevel@tonic-gate
28237c478bd9Sstevel@tonic-gate ctd_str = strdup(name);
28247c478bd9Sstevel@tonic-gate if (ctd_str == NULL) {
28257c478bd9Sstevel@tonic-gate return (ENOMEM);
28267c478bd9Sstevel@tonic-gate }
28277c478bd9Sstevel@tonic-gate
28287c478bd9Sstevel@tonic-gate /* trim any leading path (/dev/dsk/cXtXdXsX) */
28297c478bd9Sstevel@tonic-gate if ((device_str = strrchr(ctd_str, '/')) != NULL) {
28307c478bd9Sstevel@tonic-gate ++device_str;
28317c478bd9Sstevel@tonic-gate } else {
28327c478bd9Sstevel@tonic-gate device_str = ctd_str;
28337c478bd9Sstevel@tonic-gate }
28347c478bd9Sstevel@tonic-gate
28357c478bd9Sstevel@tonic-gate /* find each segment start position */
28367c478bd9Sstevel@tonic-gate t_ptr = strrchr(device_str, 't');
28377c478bd9Sstevel@tonic-gate d_ptr = strrchr(device_str, 'd');
28387c478bd9Sstevel@tonic-gate s_ptr = strrchr(device_str, 's');
28397c478bd9Sstevel@tonic-gate
28407c478bd9Sstevel@tonic-gate /*
28417c478bd9Sstevel@tonic-gate * scan ids from each existing segment working backwards
28427c478bd9Sstevel@tonic-gate * so as to leave the device_str in the correct state
28437c478bd9Sstevel@tonic-gate * for the next expected segment
28447c478bd9Sstevel@tonic-gate */
28457c478bd9Sstevel@tonic-gate if (s_ptr != NULL) {
28467c478bd9Sstevel@tonic-gate
28477c478bd9Sstevel@tonic-gate /* found 's', try to get slice */
28487c478bd9Sstevel@tonic-gate nchars = strlen(s_ptr);
28497c478bd9Sstevel@tonic-gate if ((sscanf(s_ptr, "s%u%n", &slice, &nscan) != 1) ||
28507c478bd9Sstevel@tonic-gate (nscan != nchars)) {
28517c478bd9Sstevel@tonic-gate
28527c478bd9Sstevel@tonic-gate error = -1;
28537c478bd9Sstevel@tonic-gate oprintf(OUTPUT_DEBUG,
28547c478bd9Sstevel@tonic-gate gettext("no slice component in device "
28557c478bd9Sstevel@tonic-gate "name \"%s\".\n"),
28567c478bd9Sstevel@tonic-gate name);
28577c478bd9Sstevel@tonic-gate
28587c478bd9Sstevel@tonic-gate } else {
28597c478bd9Sstevel@tonic-gate got_slice = B_TRUE;
28607c478bd9Sstevel@tonic-gate *s_ptr = '\0';
28617c478bd9Sstevel@tonic-gate }
28627c478bd9Sstevel@tonic-gate }
28637c478bd9Sstevel@tonic-gate
28647c478bd9Sstevel@tonic-gate if ((error == 0) && (d_ptr != NULL)) {
28657c478bd9Sstevel@tonic-gate
28667c478bd9Sstevel@tonic-gate /* found 'd', try to get disk/lun */
28677c478bd9Sstevel@tonic-gate nchars = strlen(d_ptr);
28687c478bd9Sstevel@tonic-gate if ((sscanf(d_ptr, "d%u%n", &lun, &nscan) != 1) ||
28697c478bd9Sstevel@tonic-gate (nscan != nchars)) {
28707c478bd9Sstevel@tonic-gate
28717c478bd9Sstevel@tonic-gate error = -1;
28727c478bd9Sstevel@tonic-gate oprintf(OUTPUT_DEBUG,
28737c478bd9Sstevel@tonic-gate gettext("no disk/lun component "
28747c478bd9Sstevel@tonic-gate "in device name \"%s\".\n"),
28757c478bd9Sstevel@tonic-gate name);
28767c478bd9Sstevel@tonic-gate
28777c478bd9Sstevel@tonic-gate } else {
28787c478bd9Sstevel@tonic-gate got_lun = B_TRUE;
28797c478bd9Sstevel@tonic-gate *d_ptr = '\0';
28807c478bd9Sstevel@tonic-gate }
28817c478bd9Sstevel@tonic-gate }
28827c478bd9Sstevel@tonic-gate
28837c478bd9Sstevel@tonic-gate if ((error == 0) && (t_ptr != NULL)) {
28847c478bd9Sstevel@tonic-gate
28857c478bd9Sstevel@tonic-gate /* found 't', try to get target, it may be a hex WWN id */
28867c478bd9Sstevel@tonic-gate
28877c478bd9Sstevel@tonic-gate /* skip leading 't' and add two for the 'OX' */
28887c478bd9Sstevel@tonic-gate nchars = strlen(t_ptr + 1) + 2;
28897c478bd9Sstevel@tonic-gate if ((target_str = (char *)malloc(nchars+1)) == NULL) {
28907c478bd9Sstevel@tonic-gate
28917c478bd9Sstevel@tonic-gate error = ENOMEM;
28927c478bd9Sstevel@tonic-gate
28937c478bd9Sstevel@tonic-gate } else {
28947c478bd9Sstevel@tonic-gate
28957c478bd9Sstevel@tonic-gate strcpy(target_str, "0X");
28967c478bd9Sstevel@tonic-gate strcpy(target_str+2, t_ptr + 1);
28977c478bd9Sstevel@tonic-gate target_str[nchars] = '\0';
28987c478bd9Sstevel@tonic-gate
28997c478bd9Sstevel@tonic-gate if ((sscanf(target_str, "%x%n", &target, &nscan) != 1) ||
29007c478bd9Sstevel@tonic-gate (nscan != nchars)) {
29017c478bd9Sstevel@tonic-gate
29027c478bd9Sstevel@tonic-gate error = -1;
29037c478bd9Sstevel@tonic-gate oprintf(OUTPUT_DEBUG,
29047c478bd9Sstevel@tonic-gate gettext("no target/WWN component "
29057c478bd9Sstevel@tonic-gate "in device name \"%s\".\n"),
29067c478bd9Sstevel@tonic-gate name);
29077c478bd9Sstevel@tonic-gate
29087c478bd9Sstevel@tonic-gate } else {
29097c478bd9Sstevel@tonic-gate got_target = B_TRUE;
29107c478bd9Sstevel@tonic-gate *t_ptr = '\0';
29117c478bd9Sstevel@tonic-gate }
29127c478bd9Sstevel@tonic-gate
29137c478bd9Sstevel@tonic-gate free(target_str);
29147c478bd9Sstevel@tonic-gate }
29157c478bd9Sstevel@tonic-gate
29167c478bd9Sstevel@tonic-gate } else {
29177c478bd9Sstevel@tonic-gate is_ide = B_TRUE;
29187c478bd9Sstevel@tonic-gate }
29197c478bd9Sstevel@tonic-gate
29207c478bd9Sstevel@tonic-gate if ((error == 0) && (device_str != NULL)) {
29217c478bd9Sstevel@tonic-gate
29227c478bd9Sstevel@tonic-gate /* get controller/hba/channel */
29237c478bd9Sstevel@tonic-gate nchars = strlen(device_str);
29247c478bd9Sstevel@tonic-gate if ((sscanf(device_str, "c%u%n", &ctrl, &nscan) != 1) ||
29257c478bd9Sstevel@tonic-gate (nscan != nchars)) {
29267c478bd9Sstevel@tonic-gate
29277c478bd9Sstevel@tonic-gate error = -1;
29287c478bd9Sstevel@tonic-gate oprintf(OUTPUT_DEBUG,
29297c478bd9Sstevel@tonic-gate gettext("no channel/HBA component "
29307c478bd9Sstevel@tonic-gate "in device name \"%s\".\n"),
29317c478bd9Sstevel@tonic-gate name);
29327c478bd9Sstevel@tonic-gate
29337c478bd9Sstevel@tonic-gate } else {
29347c478bd9Sstevel@tonic-gate got_ctrl = B_TRUE;
29357c478bd9Sstevel@tonic-gate }
29367c478bd9Sstevel@tonic-gate }
29377c478bd9Sstevel@tonic-gate
29387c478bd9Sstevel@tonic-gate free(ctd_str);
29397c478bd9Sstevel@tonic-gate
29407c478bd9Sstevel@tonic-gate if (error == 0) {
29417c478bd9Sstevel@tonic-gate
29427c478bd9Sstevel@tonic-gate /* allocate the ctd_spec_t struct and store the ids */
29437c478bd9Sstevel@tonic-gate (*spec)->type = SPEC_TYPE_CTD;
29447c478bd9Sstevel@tonic-gate (*spec)->data.ctd = (ctd_spec_t *)calloc(1, sizeof (ctd_spec_t));
29457c478bd9Sstevel@tonic-gate
29467c478bd9Sstevel@tonic-gate if ((*spec)->data.ctd == NULL) {
29477c478bd9Sstevel@tonic-gate error = ENOMEM;
29487c478bd9Sstevel@tonic-gate }
29497c478bd9Sstevel@tonic-gate
29507c478bd9Sstevel@tonic-gate (*spec)->data.ctd->slice = ID_UNSPECIFIED;
29517c478bd9Sstevel@tonic-gate (*spec)->data.ctd->lun = ID_UNSPECIFIED;
29527c478bd9Sstevel@tonic-gate (*spec)->data.ctd->target = ID_UNSPECIFIED;
29537c478bd9Sstevel@tonic-gate (*spec)->data.ctd->ctrl = ID_UNSPECIFIED;
29547c478bd9Sstevel@tonic-gate
29557c478bd9Sstevel@tonic-gate if (got_slice == B_TRUE) {
29567c478bd9Sstevel@tonic-gate (*spec)->data.ctd->slice = slice;
29577c478bd9Sstevel@tonic-gate }
29587c478bd9Sstevel@tonic-gate
29597c478bd9Sstevel@tonic-gate if (got_lun == B_TRUE) {
29607c478bd9Sstevel@tonic-gate (*spec)->data.ctd->lun = lun;
29617c478bd9Sstevel@tonic-gate }
29627c478bd9Sstevel@tonic-gate
29637c478bd9Sstevel@tonic-gate if (got_target == B_TRUE) {
29647c478bd9Sstevel@tonic-gate (*spec)->data.ctd->target = target;
29657c478bd9Sstevel@tonic-gate }
29667c478bd9Sstevel@tonic-gate
29677c478bd9Sstevel@tonic-gate if (got_ctrl == B_TRUE) {
29687c478bd9Sstevel@tonic-gate (*spec)->data.ctd->ctrl = ctrl;
29697c478bd9Sstevel@tonic-gate }
29707c478bd9Sstevel@tonic-gate
29717c478bd9Sstevel@tonic-gate (*spec)->data.ctd->is_ide = is_ide;
29727c478bd9Sstevel@tonic-gate }
29737c478bd9Sstevel@tonic-gate
29747c478bd9Sstevel@tonic-gate return (error);
29757c478bd9Sstevel@tonic-gate }
29767c478bd9Sstevel@tonic-gate
29777c478bd9Sstevel@tonic-gate /*
29787c478bd9Sstevel@tonic-gate * FUNCTION: create_device_raw_spec(char *name, device_spec_t **spec);
29797c478bd9Sstevel@tonic-gate *
29807c478bd9Sstevel@tonic-gate * INPUT: name - pointer to a char* device name
29817c478bd9Sstevel@tonic-gate *
29827c478bd9Sstevel@tonic-gate * OUTPUT: spec - pointer to a device_spec_t updated with the raw spec
29837c478bd9Sstevel@tonic-gate *
29847c478bd9Sstevel@tonic-gate * RETURNS: int - 0 on success
29857c478bd9Sstevel@tonic-gate * !0 otherwise
29867c478bd9Sstevel@tonic-gate *
29877c478bd9Sstevel@tonic-gate * PURPOSE: Function which creates a "raw" spec for the input name.
29887c478bd9Sstevel@tonic-gate *
29897c478bd9Sstevel@tonic-gate * This is a last resort if all other spec parsing schemes failed,
29907c478bd9Sstevel@tonic-gate * the "raw" spec is just the input device name.
29917c478bd9Sstevel@tonic-gate */
29927c478bd9Sstevel@tonic-gate static int
create_device_raw_spec(char * name,device_spec_t ** spec)29937c478bd9Sstevel@tonic-gate create_device_raw_spec(
29947c478bd9Sstevel@tonic-gate char *name,
29957c478bd9Sstevel@tonic-gate device_spec_t **spec)
29967c478bd9Sstevel@tonic-gate {
29977c478bd9Sstevel@tonic-gate int error = 0;
29987c478bd9Sstevel@tonic-gate char *ctd_str = strdup(name);
29997c478bd9Sstevel@tonic-gate
30007c478bd9Sstevel@tonic-gate if (ctd_str == NULL) {
30017c478bd9Sstevel@tonic-gate return (ENOMEM);
30027c478bd9Sstevel@tonic-gate }
30037c478bd9Sstevel@tonic-gate
30047c478bd9Sstevel@tonic-gate (*spec)->type = SPEC_TYPE_RAW;
30057c478bd9Sstevel@tonic-gate (*spec)->data.raw = ctd_str;
30067c478bd9Sstevel@tonic-gate
30077c478bd9Sstevel@tonic-gate oprintf(OUTPUT_DEBUG,
30087c478bd9Sstevel@tonic-gate gettext("made raw device spec for \"%s\"\n"), ctd_str);
30097c478bd9Sstevel@tonic-gate
30107c478bd9Sstevel@tonic-gate return (error);
30117c478bd9Sstevel@tonic-gate }
30127c478bd9Sstevel@tonic-gate
30137c478bd9Sstevel@tonic-gate /*
30147c478bd9Sstevel@tonic-gate * FUNCTION: get_spec_for_name(char *name, device_spec_t **id);
30157c478bd9Sstevel@tonic-gate *
30167c478bd9Sstevel@tonic-gate * INPUT: name - pointer to a char* device name
30177c478bd9Sstevel@tonic-gate *
30187c478bd9Sstevel@tonic-gate * OUTPUT: id - pointer to a device_spec_t to hold the result
30197c478bd9Sstevel@tonic-gate *
30207c478bd9Sstevel@tonic-gate * RETURNS: int - 0 on success
30217c478bd9Sstevel@tonic-gate * !0 otherwise
30227c478bd9Sstevel@tonic-gate *
30237c478bd9Sstevel@tonic-gate * PURPOSE: Function which finds the device_spec_t that already
30247c478bd9Sstevel@tonic-gate * exists for the input name or creates it.
30257c478bd9Sstevel@tonic-gate *
30267c478bd9Sstevel@tonic-gate * The returned struct should not be freed, it is maintained
30277c478bd9Sstevel@tonic-gate * in a cache that will be purged when the layout process
30287c478bd9Sstevel@tonic-gate * is complete.
30297c478bd9Sstevel@tonic-gate */
30307c478bd9Sstevel@tonic-gate int
get_spec_for_name(char * name,device_spec_t ** id)30317c478bd9Sstevel@tonic-gate get_spec_for_name(
30327c478bd9Sstevel@tonic-gate char *name,
30337c478bd9Sstevel@tonic-gate device_spec_t **id)
30347c478bd9Sstevel@tonic-gate {
30357c478bd9Sstevel@tonic-gate dlist_t *item;
30367c478bd9Sstevel@tonic-gate int error = 0;
30377c478bd9Sstevel@tonic-gate
30387c478bd9Sstevel@tonic-gate item = dlist_find(_spec_cache, (void *)name,
30397c478bd9Sstevel@tonic-gate compare_name_to_spec_cache_name);
30407c478bd9Sstevel@tonic-gate
30417c478bd9Sstevel@tonic-gate if (item == NULL) {
30427c478bd9Sstevel@tonic-gate if ((error = create_device_spec(name, id)) == 0) {
30437c478bd9Sstevel@tonic-gate
30447c478bd9Sstevel@tonic-gate spec_cache_t *entry = (spec_cache_t *)
30457c478bd9Sstevel@tonic-gate calloc(1, sizeof (spec_cache_t));
30467c478bd9Sstevel@tonic-gate
30477c478bd9Sstevel@tonic-gate if (entry == NULL) {
30487c478bd9Sstevel@tonic-gate destroy_device_spec(*id);
30497c478bd9Sstevel@tonic-gate error = ENOMEM;
30507c478bd9Sstevel@tonic-gate } else {
30517c478bd9Sstevel@tonic-gate char *dup = strdup(name);
30527c478bd9Sstevel@tonic-gate if (dup == NULL) {
30537c478bd9Sstevel@tonic-gate free(entry);
30547c478bd9Sstevel@tonic-gate destroy_device_spec(*id);
30557c478bd9Sstevel@tonic-gate *id = NULL;
30567c478bd9Sstevel@tonic-gate error = ENOMEM;
30577c478bd9Sstevel@tonic-gate } else {
30587c478bd9Sstevel@tonic-gate entry->name = dup;
30597c478bd9Sstevel@tonic-gate entry->device_spec = *id;
30607c478bd9Sstevel@tonic-gate }
30617c478bd9Sstevel@tonic-gate
30627c478bd9Sstevel@tonic-gate if (error == 0) {
30637c478bd9Sstevel@tonic-gate dlist_t *item = dlist_new_item((void *)entry);
30647c478bd9Sstevel@tonic-gate if (item == NULL) {
30657c478bd9Sstevel@tonic-gate free(entry);
30667c478bd9Sstevel@tonic-gate destroy_device_spec(*id);
30677c478bd9Sstevel@tonic-gate *id = NULL;
30687c478bd9Sstevel@tonic-gate error = ENOMEM;
30697c478bd9Sstevel@tonic-gate } else {
30707c478bd9Sstevel@tonic-gate _spec_cache =
30717c478bd9Sstevel@tonic-gate dlist_append(item, _spec_cache, AT_HEAD);
30727c478bd9Sstevel@tonic-gate }
30737c478bd9Sstevel@tonic-gate }
30747c478bd9Sstevel@tonic-gate }
30757c478bd9Sstevel@tonic-gate }
30767c478bd9Sstevel@tonic-gate } else {
30777c478bd9Sstevel@tonic-gate *id = ((spec_cache_t *)item->obj)->device_spec;
30787c478bd9Sstevel@tonic-gate }
30797c478bd9Sstevel@tonic-gate
30807c478bd9Sstevel@tonic-gate return (error);
30817c478bd9Sstevel@tonic-gate }
30827c478bd9Sstevel@tonic-gate
30837c478bd9Sstevel@tonic-gate /*
30847c478bd9Sstevel@tonic-gate * FUNCTION: spec_includes_device(device_spec_t *spec,
30857c478bd9Sstevel@tonic-gate * device_spec_t *device)
30867c478bd9Sstevel@tonic-gate *
30877c478bd9Sstevel@tonic-gate * INPUT: spec - pointer to a device_spec struct
30887c478bd9Sstevel@tonic-gate * device - pointer to a device_spec struct
30897c478bd9Sstevel@tonic-gate *
30907c478bd9Sstevel@tonic-gate * RETURNS: boolean_t - B_TRUE if the device is included in the spec
30917c478bd9Sstevel@tonic-gate * B_FALSE otherwise
30927c478bd9Sstevel@tonic-gate *
30937c478bd9Sstevel@tonic-gate * PURPOSE: Function which determines if the input device matches the
30947c478bd9Sstevel@tonic-gate * input spec.
30957c478bd9Sstevel@tonic-gate *
30967c478bd9Sstevel@tonic-gate * If both specs are of the same type, the appropriate
30977c478bd9Sstevel@tonic-gate * comparison function is called.
30987c478bd9Sstevel@tonic-gate *
30997c478bd9Sstevel@tonic-gate * If the two specs are of different types, no comparison
31007c478bd9Sstevel@tonic-gate * is done and B_FALSE is returned.
31017c478bd9Sstevel@tonic-gate */
31027c478bd9Sstevel@tonic-gate boolean_t
spec_includes_device(device_spec_t * spec,device_spec_t * device)31037c478bd9Sstevel@tonic-gate spec_includes_device(
31047c478bd9Sstevel@tonic-gate device_spec_t *spec,
31057c478bd9Sstevel@tonic-gate device_spec_t *device)
31067c478bd9Sstevel@tonic-gate {
31077c478bd9Sstevel@tonic-gate if ((spec->type == SPEC_TYPE_CTD) && (device->type == SPEC_TYPE_CTD)) {
31087c478bd9Sstevel@tonic-gate return (ctd_spec_includes_device(spec, device));
31097c478bd9Sstevel@tonic-gate } else if ((spec->type == SPEC_TYPE_RAW) &&
31107c478bd9Sstevel@tonic-gate (device->type == SPEC_TYPE_RAW)) {
31117c478bd9Sstevel@tonic-gate return (raw_spec_includes_device(spec, device));
31127c478bd9Sstevel@tonic-gate }
31137c478bd9Sstevel@tonic-gate
31147c478bd9Sstevel@tonic-gate return (B_FALSE);
31157c478bd9Sstevel@tonic-gate }
31167c478bd9Sstevel@tonic-gate
31177c478bd9Sstevel@tonic-gate /*
31187c478bd9Sstevel@tonic-gate * FUNCTION: ctd_spec_includes_device(device_spec_t *spec,
31197c478bd9Sstevel@tonic-gate * device_spec_t *device)
31207c478bd9Sstevel@tonic-gate *
31217c478bd9Sstevel@tonic-gate * INPUT: spec - pointer to a device_spec struct
31227c478bd9Sstevel@tonic-gate * device - pointer to a device_spec struct
31237c478bd9Sstevel@tonic-gate *
31247c478bd9Sstevel@tonic-gate * RETURNS: boolean_t - B_TRUE if the device is included in the spec
31257c478bd9Sstevel@tonic-gate * B_FALSE otherwise
31267c478bd9Sstevel@tonic-gate *
31277c478bd9Sstevel@tonic-gate * PURPOSE: Function which determines if the input CTD device spec
31287c478bd9Sstevel@tonic-gate * matches the input CTD spec.
31297c478bd9Sstevel@tonic-gate *
31307c478bd9Sstevel@tonic-gate * The device_spec_t structs contain component "ids" for
31317c478bd9Sstevel@tonic-gate * both the specification and the device.
31327c478bd9Sstevel@tonic-gate *
31337c478bd9Sstevel@tonic-gate * The device must match each of the ids in the spec that
31347c478bd9Sstevel@tonic-gate * are specified.
31357c478bd9Sstevel@tonic-gate *
31367c478bd9Sstevel@tonic-gate * spec devices matched
31377c478bd9Sstevel@tonic-gate * --------------------------------------------------------
31387c478bd9Sstevel@tonic-gate * cX cX, cXtX, cXtXdX, cXtXdXsX, cXdX, cXdXsX
31397c478bd9Sstevel@tonic-gate * cXtX cXtX, cXtXdX, cXtXdXsX
31407c478bd9Sstevel@tonic-gate * cXtXdX cXtXdX, cXtXdXsX
31417c478bd9Sstevel@tonic-gate * cXtXdXsX cXtXdXsX
31427c478bd9Sstevel@tonic-gate * cXdX cXdX, cXdXsX
31437c478bd9Sstevel@tonic-gate * cXdXsX cXdXsX
31447c478bd9Sstevel@tonic-gate */
31457c478bd9Sstevel@tonic-gate static boolean_t
ctd_spec_includes_device(device_spec_t * spec,device_spec_t * device)31467c478bd9Sstevel@tonic-gate ctd_spec_includes_device(
31477c478bd9Sstevel@tonic-gate device_spec_t *spec,
31487c478bd9Sstevel@tonic-gate device_spec_t *device)
31497c478bd9Sstevel@tonic-gate {
31507c478bd9Sstevel@tonic-gate boolean_t match = B_FALSE;
31517c478bd9Sstevel@tonic-gate
31527c478bd9Sstevel@tonic-gate if (spec->data.ctd->is_ide) {
31537c478bd9Sstevel@tonic-gate
31547c478bd9Sstevel@tonic-gate /* valid IDE names are cX, cXdX, cXdXsX, no target */
31557c478bd9Sstevel@tonic-gate
31567c478bd9Sstevel@tonic-gate if ((spec->data.ctd->ctrl != ID_UNSPECIFIED) &&
31577c478bd9Sstevel@tonic-gate (spec->data.ctd->lun != ID_UNSPECIFIED) &&
31587c478bd9Sstevel@tonic-gate (spec->data.ctd->slice != ID_UNSPECIFIED)) {
31597c478bd9Sstevel@tonic-gate
31607c478bd9Sstevel@tonic-gate match = (spec->data.ctd->ctrl == device->data.ctd->ctrl) &&
31617c478bd9Sstevel@tonic-gate (spec->data.ctd->lun == device->data.ctd->lun) &&
31627c478bd9Sstevel@tonic-gate (spec->data.ctd->slice == device->data.ctd->slice);
31637c478bd9Sstevel@tonic-gate
31647c478bd9Sstevel@tonic-gate } else if ((spec->data.ctd->ctrl != ID_UNSPECIFIED) &&
31657c478bd9Sstevel@tonic-gate (spec->data.ctd->lun != ID_UNSPECIFIED)) {
31667c478bd9Sstevel@tonic-gate
31677c478bd9Sstevel@tonic-gate match = (spec->data.ctd->ctrl == device->data.ctd->ctrl) &&
31687c478bd9Sstevel@tonic-gate (spec->data.ctd->lun == device->data.ctd->lun);
31697c478bd9Sstevel@tonic-gate
31707c478bd9Sstevel@tonic-gate } else if (spec->data.ctd->ctrl != ID_UNSPECIFIED) {
31717c478bd9Sstevel@tonic-gate
31727c478bd9Sstevel@tonic-gate match = (spec->data.ctd->ctrl == device->data.ctd->ctrl);
31737c478bd9Sstevel@tonic-gate
31747c478bd9Sstevel@tonic-gate }
31757c478bd9Sstevel@tonic-gate
31767c478bd9Sstevel@tonic-gate } else {
31777c478bd9Sstevel@tonic-gate
31787c478bd9Sstevel@tonic-gate /* valid names are cX, cXtX, cXtXdX, cXtXdXsX */
31797c478bd9Sstevel@tonic-gate
31807c478bd9Sstevel@tonic-gate if ((spec->data.ctd->ctrl != ID_UNSPECIFIED) &&
31817c478bd9Sstevel@tonic-gate (spec->data.ctd->target != ID_UNSPECIFIED) &&
31827c478bd9Sstevel@tonic-gate (spec->data.ctd->lun != ID_UNSPECIFIED) &&
31837c478bd9Sstevel@tonic-gate (spec->data.ctd->slice != ID_UNSPECIFIED)) {
31847c478bd9Sstevel@tonic-gate
31857c478bd9Sstevel@tonic-gate match = (spec->data.ctd->ctrl == device->data.ctd->ctrl) &&
31867c478bd9Sstevel@tonic-gate (spec->data.ctd->target == device->data.ctd->target) &&
31877c478bd9Sstevel@tonic-gate (spec->data.ctd->lun == device->data.ctd->lun) &&
31887c478bd9Sstevel@tonic-gate (spec->data.ctd->slice == device->data.ctd->slice);
31897c478bd9Sstevel@tonic-gate
31907c478bd9Sstevel@tonic-gate } else if ((spec->data.ctd->ctrl != ID_UNSPECIFIED) &&
31917c478bd9Sstevel@tonic-gate (spec->data.ctd->target != ID_UNSPECIFIED) &&
31927c478bd9Sstevel@tonic-gate (spec->data.ctd->lun != ID_UNSPECIFIED)) {
31937c478bd9Sstevel@tonic-gate
31947c478bd9Sstevel@tonic-gate match = (spec->data.ctd->ctrl == device->data.ctd->ctrl) &&
31957c478bd9Sstevel@tonic-gate (spec->data.ctd->target == device->data.ctd->target) &&
31967c478bd9Sstevel@tonic-gate (spec->data.ctd->lun == device->data.ctd->lun);
31977c478bd9Sstevel@tonic-gate
31987c478bd9Sstevel@tonic-gate } else if ((spec->data.ctd->ctrl != ID_UNSPECIFIED) &&
31997c478bd9Sstevel@tonic-gate (spec->data.ctd->target != ID_UNSPECIFIED)) {
32007c478bd9Sstevel@tonic-gate
32017c478bd9Sstevel@tonic-gate match = (spec->data.ctd->ctrl == device->data.ctd->ctrl) &&
32027c478bd9Sstevel@tonic-gate (spec->data.ctd->target == device->data.ctd->target);
32037c478bd9Sstevel@tonic-gate
32047c478bd9Sstevel@tonic-gate } else if (spec->data.ctd->ctrl != ID_UNSPECIFIED) {
32057c478bd9Sstevel@tonic-gate
32067c478bd9Sstevel@tonic-gate match = (spec->data.ctd->ctrl == device->data.ctd->ctrl);
32077c478bd9Sstevel@tonic-gate
32087c478bd9Sstevel@tonic-gate }
32097c478bd9Sstevel@tonic-gate }
32107c478bd9Sstevel@tonic-gate
32117c478bd9Sstevel@tonic-gate oprintf(OUTPUT_DEBUG,
32127c478bd9Sstevel@tonic-gate gettext("spec: c(%d) t(%d) d(%d) s(%d) "
32137c478bd9Sstevel@tonic-gate "%s: c(%d) t(%d) d(%d) s(%d)\n"),
32147c478bd9Sstevel@tonic-gate spec->data.ctd->ctrl, spec->data.ctd->target,
32157c478bd9Sstevel@tonic-gate spec->data.ctd->lun, spec->data.ctd->slice,
32167c478bd9Sstevel@tonic-gate (match ? gettext("includes") : gettext("does not include")),
32177c478bd9Sstevel@tonic-gate device->data.ctd->ctrl, device->data.ctd->target,
32187c478bd9Sstevel@tonic-gate device->data.ctd->lun, device->data.ctd->slice);
32197c478bd9Sstevel@tonic-gate
32207c478bd9Sstevel@tonic-gate return (match);
32217c478bd9Sstevel@tonic-gate }
32227c478bd9Sstevel@tonic-gate
32237c478bd9Sstevel@tonic-gate /*
32247c478bd9Sstevel@tonic-gate * FUNCTION: raw_spec_includes_device(device_spec_t *spec,
32257c478bd9Sstevel@tonic-gate * device_spec_t *device)
32267c478bd9Sstevel@tonic-gate *
32277c478bd9Sstevel@tonic-gate * INPUT: spec - pointer to a device_spec struct
32287c478bd9Sstevel@tonic-gate * device - pointer to a device_spec struct
32297c478bd9Sstevel@tonic-gate *
32307c478bd9Sstevel@tonic-gate * RETURNS: boolean_t - B_TRUE if the device is included in the spec
32317c478bd9Sstevel@tonic-gate * B_FALSE otherwise
32327c478bd9Sstevel@tonic-gate *
32337c478bd9Sstevel@tonic-gate * PURPOSE: Function which determines if the input raw device spec
32347c478bd9Sstevel@tonic-gate * matches the input spec.
32357c478bd9Sstevel@tonic-gate *
32367c478bd9Sstevel@tonic-gate * The device_spec_t raw elements are checked.
32377c478bd9Sstevel@tonic-gate *
32387c478bd9Sstevel@tonic-gate * If the spec's raw device name is exactly contained at the
32397c478bd9Sstevel@tonic-gate * beginning of the device spec's raw name, then the function
32407c478bd9Sstevel@tonic-gate * evaluates to true.
32417c478bd9Sstevel@tonic-gate */
32427c478bd9Sstevel@tonic-gate static boolean_t
raw_spec_includes_device(device_spec_t * spec,device_spec_t * device)32437c478bd9Sstevel@tonic-gate raw_spec_includes_device(
32447c478bd9Sstevel@tonic-gate device_spec_t *spec,
32457c478bd9Sstevel@tonic-gate device_spec_t *device)
32467c478bd9Sstevel@tonic-gate {
32477c478bd9Sstevel@tonic-gate return (strncasecmp(spec->data.raw,
32487c478bd9Sstevel@tonic-gate device->data.raw, strlen(spec->data.raw)) == 0);
32497c478bd9Sstevel@tonic-gate }
32507c478bd9Sstevel@tonic-gate
32517c478bd9Sstevel@tonic-gate /*
32527c478bd9Sstevel@tonic-gate * FUNCTION: compare_name_to_spec_cache_name(void *name, void *list_item)
32537c478bd9Sstevel@tonic-gate *
32547c478bd9Sstevel@tonic-gate * INPUT: name - opaque pointer to a char * device name
32557c478bd9Sstevel@tonic-gate * list_item - opaque pointer to a spec_cache_t entry
32567c478bd9Sstevel@tonic-gate *
32577c478bd9Sstevel@tonic-gate * RETURNS: int - 0 - if request is the same as list_item->request
32587c478bd9Sstevel@tonic-gate * !0 - otherwise
32597c478bd9Sstevel@tonic-gate *
32607c478bd9Sstevel@tonic-gate * PURPOSE: dlist_t helper which compares the input device name
32617c478bd9Sstevel@tonic-gate * to the list_item's device name for equality.
32627c478bd9Sstevel@tonic-gate *
32637c478bd9Sstevel@tonic-gate * This function is the lookup mechanism for the device_spec
32647c478bd9Sstevel@tonic-gate * associated with the name.
32657c478bd9Sstevel@tonic-gate */
32667c478bd9Sstevel@tonic-gate static int
compare_name_to_spec_cache_name(void * name,void * list_item)32677c478bd9Sstevel@tonic-gate compare_name_to_spec_cache_name(
32687c478bd9Sstevel@tonic-gate void *name,
32697c478bd9Sstevel@tonic-gate void *list_item)
32707c478bd9Sstevel@tonic-gate {
32717c478bd9Sstevel@tonic-gate spec_cache_t *entry = (spec_cache_t *)list_item;
32727c478bd9Sstevel@tonic-gate
32737c478bd9Sstevel@tonic-gate assert(name != NULL);
32747c478bd9Sstevel@tonic-gate assert(entry != NULL);
32757c478bd9Sstevel@tonic-gate
32767c478bd9Sstevel@tonic-gate return (string_case_compare((char *)name, entry->name));
32777c478bd9Sstevel@tonic-gate }
32787c478bd9Sstevel@tonic-gate
32797c478bd9Sstevel@tonic-gate /*
32807c478bd9Sstevel@tonic-gate * FUNCTION: destroy_spec_cache_entry(void *entry)
32817c478bd9Sstevel@tonic-gate *
32827c478bd9Sstevel@tonic-gate * INPUT: entry - opaque pointer to a spec_cache_t
32837c478bd9Sstevel@tonic-gate *
32847c478bd9Sstevel@tonic-gate * RETURNS: nothing
32857c478bd9Sstevel@tonic-gate *
32867c478bd9Sstevel@tonic-gate * PURPOSE: Function which reclaims memory allocated to a
32877c478bd9Sstevel@tonic-gate * spec_cache_t entry.
32887c478bd9Sstevel@tonic-gate *
32897c478bd9Sstevel@tonic-gate * Frees memory allocated to hold the CTD name and the
32907c478bd9Sstevel@tonic-gate * corresponding device_spec_t.
32917c478bd9Sstevel@tonic-gate */
32927c478bd9Sstevel@tonic-gate static void
destroy_spec_cache_entry(void * obj)32937c478bd9Sstevel@tonic-gate destroy_spec_cache_entry(
32947c478bd9Sstevel@tonic-gate void *obj)
32957c478bd9Sstevel@tonic-gate {
32967c478bd9Sstevel@tonic-gate spec_cache_t *entry = (spec_cache_t *)obj;
32977c478bd9Sstevel@tonic-gate
32987c478bd9Sstevel@tonic-gate if (entry != NULL) {
32997c478bd9Sstevel@tonic-gate free(entry->name);
33007c478bd9Sstevel@tonic-gate destroy_device_spec(entry->device_spec);
33017c478bd9Sstevel@tonic-gate free(entry);
33027c478bd9Sstevel@tonic-gate }
33037c478bd9Sstevel@tonic-gate }
33047c478bd9Sstevel@tonic-gate
33057c478bd9Sstevel@tonic-gate /*
33067c478bd9Sstevel@tonic-gate * FUNCTION: destroy_spec_cache()
33077c478bd9Sstevel@tonic-gate *
33087c478bd9Sstevel@tonic-gate * RETURNS: int - 0 on success
33097c478bd9Sstevel@tonic-gate * !0 otherwise.
33107c478bd9Sstevel@tonic-gate *
33117c478bd9Sstevel@tonic-gate * PURPOSE: Function which destroys all entries in the device_spec
33127c478bd9Sstevel@tonic-gate * cache.
33137c478bd9Sstevel@tonic-gate */
33147c478bd9Sstevel@tonic-gate static int
destroy_spec_cache()33157c478bd9Sstevel@tonic-gate destroy_spec_cache()
33167c478bd9Sstevel@tonic-gate {
33177c478bd9Sstevel@tonic-gate dlist_free_items(_spec_cache, destroy_spec_cache_entry);
33187c478bd9Sstevel@tonic-gate _spec_cache = NULL;
33197c478bd9Sstevel@tonic-gate
33207c478bd9Sstevel@tonic-gate return (0);
33217c478bd9Sstevel@tonic-gate }
33227c478bd9Sstevel@tonic-gate
33237c478bd9Sstevel@tonic-gate /*
33247c478bd9Sstevel@tonic-gate * FUNCTION: get_device_access_name(devconfig_t *request,
33257c478bd9Sstevel@tonic-gate * dm_descriptor_t desc, char **name)
33267c478bd9Sstevel@tonic-gate *
33277c478bd9Sstevel@tonic-gate * INPUT: request - a devconfig_t request
33287c478bd9Sstevel@tonic-gate * desc - a dm_descriptor_t device handle
33297c478bd9Sstevel@tonic-gate *
33307c478bd9Sstevel@tonic-gate * OUTPUT: name - a char * pointer to hold the preferred name
33317c478bd9Sstevel@tonic-gate *
33327c478bd9Sstevel@tonic-gate * RETURNS: int - 0 - if request is the same as list_item->request
33337c478bd9Sstevel@tonic-gate * !0 - otherwise
33347c478bd9Sstevel@tonic-gate *
33357c478bd9Sstevel@tonic-gate * PURPOSE: Utility function to determine which of the possible device
33367c478bd9Sstevel@tonic-gate * names should be used to access a known available device.
33377c478bd9Sstevel@tonic-gate *
33387c478bd9Sstevel@tonic-gate * Devices handled are slices and disks.
33397c478bd9Sstevel@tonic-gate *
33407c478bd9Sstevel@tonic-gate * If the input device is a multipathed disk or slice, it
33417c478bd9Sstevel@tonic-gate * can have several possible names. Determine which of the
33427c478bd9Sstevel@tonic-gate * names should be used based on the input request's available
33437c478bd9Sstevel@tonic-gate * or unavailable device specifications.
33447c478bd9Sstevel@tonic-gate *
33457c478bd9Sstevel@tonic-gate */
33467c478bd9Sstevel@tonic-gate int
get_device_access_name(devconfig_t * request,dm_descriptor_t desc,char ** name)33477c478bd9Sstevel@tonic-gate get_device_access_name(
33487c478bd9Sstevel@tonic-gate devconfig_t *request,
33497c478bd9Sstevel@tonic-gate dm_descriptor_t desc,
33507c478bd9Sstevel@tonic-gate char **name)
33517c478bd9Sstevel@tonic-gate {
33527c478bd9Sstevel@tonic-gate int error = 0;
33537c478bd9Sstevel@tonic-gate boolean_t avail = B_FALSE;
33547c478bd9Sstevel@tonic-gate dlist_t *aliases = NULL;
33557c478bd9Sstevel@tonic-gate
33567c478bd9Sstevel@tonic-gate assert(desc != (dm_descriptor_t)0);
33577c478bd9Sstevel@tonic-gate
33587c478bd9Sstevel@tonic-gate *name = NULL;
33597c478bd9Sstevel@tonic-gate
33607c478bd9Sstevel@tonic-gate if ((error = get_display_name(desc, name)) != 0) {
33617c478bd9Sstevel@tonic-gate return (error);
33627c478bd9Sstevel@tonic-gate }
33637c478bd9Sstevel@tonic-gate
33647c478bd9Sstevel@tonic-gate if (is_did_name(*name) == B_TRUE) {
33657c478bd9Sstevel@tonic-gate oprintf(OUTPUT_DEBUG,
33667c478bd9Sstevel@tonic-gate gettext("device DID name %s is preferred\n"),
33677c478bd9Sstevel@tonic-gate *name);
33687c478bd9Sstevel@tonic-gate return (0);
33697c478bd9Sstevel@tonic-gate }
33707c478bd9Sstevel@tonic-gate
33717c478bd9Sstevel@tonic-gate error = is_named_device_avail(request, *name, B_FALSE, &avail);
33727c478bd9Sstevel@tonic-gate if (error != 0) {
33737c478bd9Sstevel@tonic-gate return (error);
33747c478bd9Sstevel@tonic-gate }
33757c478bd9Sstevel@tonic-gate
33767c478bd9Sstevel@tonic-gate if (avail == B_TRUE) {
33777c478bd9Sstevel@tonic-gate oprintf(OUTPUT_DEBUG,
33787c478bd9Sstevel@tonic-gate gettext("device name %s is accessible\n"),
33797c478bd9Sstevel@tonic-gate *name);
33807c478bd9Sstevel@tonic-gate return (0);
33817c478bd9Sstevel@tonic-gate }
33827c478bd9Sstevel@tonic-gate
33837c478bd9Sstevel@tonic-gate /* search aliases for an 'available' name, prefer DID names */
33847c478bd9Sstevel@tonic-gate if ((error = get_aliases(desc, &aliases)) == 0) {
33857c478bd9Sstevel@tonic-gate
33867c478bd9Sstevel@tonic-gate dlist_t *iter = aliases;
33877c478bd9Sstevel@tonic-gate char *availname = NULL;
33887c478bd9Sstevel@tonic-gate char *didname = NULL;
33897c478bd9Sstevel@tonic-gate
33907c478bd9Sstevel@tonic-gate for (; (iter != NULL) && (error == 0); iter = iter->next) {
33917c478bd9Sstevel@tonic-gate
33927c478bd9Sstevel@tonic-gate char *alias = (char *)iter->obj;
33937c478bd9Sstevel@tonic-gate error = is_named_device_avail(request, alias, B_FALSE, &avail);
33947c478bd9Sstevel@tonic-gate
33957c478bd9Sstevel@tonic-gate if ((error == 0) && (avail == B_TRUE)) {
33967c478bd9Sstevel@tonic-gate oprintf(OUTPUT_DEBUG,
33977c478bd9Sstevel@tonic-gate gettext("device alias %s is accessible for %s\n"),
33987c478bd9Sstevel@tonic-gate alias, *name);
33997c478bd9Sstevel@tonic-gate
34007c478bd9Sstevel@tonic-gate availname = alias;
34017c478bd9Sstevel@tonic-gate
34027c478bd9Sstevel@tonic-gate if (is_did_name(availname) == B_TRUE) {
34037c478bd9Sstevel@tonic-gate didname = alias;
34047c478bd9Sstevel@tonic-gate break;
34057c478bd9Sstevel@tonic-gate }
34067c478bd9Sstevel@tonic-gate }
34077c478bd9Sstevel@tonic-gate }
34087c478bd9Sstevel@tonic-gate
34097c478bd9Sstevel@tonic-gate if (error == 0) {
34107c478bd9Sstevel@tonic-gate if (didname != NULL) {
34117c478bd9Sstevel@tonic-gate *name = didname;
34127c478bd9Sstevel@tonic-gate } else if (availname != NULL) {
34137c478bd9Sstevel@tonic-gate *name = availname;
34147c478bd9Sstevel@tonic-gate }
34157c478bd9Sstevel@tonic-gate }
34167c478bd9Sstevel@tonic-gate }
34177c478bd9Sstevel@tonic-gate
34187c478bd9Sstevel@tonic-gate return (error);
34197c478bd9Sstevel@tonic-gate }
3420