/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" #define _LAYOUT_DLIST_UTIL_C #include #include #include #include #include "volume_devconfig.h" #include "volume_dlist.h" #include "volume_output.h" #include "layout_device_cache.h" #include "layout_dlist_util.h" #include "layout_request.h" #include "layout_slice.h" /* destroy_new_slice */ #include "layout_svm_util.h" /* * FUNCTION: compare_strings(void *str1, void *str2) * * INPUT: str1 - opaque pointer to a char * * str2 - opaque pointer to a char * * * RETURNS: int - <0 - if str1 < str2 * 0 - if str1 == str2 * >0 - if str1 > str2 * * PURPOSE: dlist_t helper which compares the two input strings. * * Comparison is done with string_case_compare() */ int compare_strings( void *str1, void *str2) { assert(str1 != NULL); assert(str2 != NULL); return (string_case_compare((char *)str1, (char *)str2)); } /* * FUNCTION: compare_devconfig_sizes(void *devconf1, void *devconf2) * * INPUT: devconf1 - opaque pointer * devconf2 - opaque pointer * * RETURNS: int - <0 - if devconf1.size_in_blks < devconf2.size_in_blks * 0 - if devconf1.size_in_blks == devconf2.size_in_blks * >0 - if devconf1.size.in_blks > devconf2.size_in_blks * * PURPOSE: dlist_t helper which compares the sizes of two devconfig_t * structs. * * Both input objects are assumed to be devconfig_t pointers. */ int compare_devconfig_sizes( void *devconf1, void *devconf2) { uint64_t size1 = 0; uint64_t size2 = 0; assert(devconf1 != NULL); assert(devconf2 != NULL); (void) devconfig_get_size_in_blocks((devconfig_t *)devconf1, &size1); (void) devconfig_get_size_in_blocks((devconfig_t *)devconf2, &size2); return (size1 - size2); } /* * FUNCTION: compare_slice_sizes(void *desc1, void *desc2) * * INPUT: desc1 - opaque pointer to a dm_descriptor_t slice handle * desc2 - opaque pointer to a dm_descriptor_t slice handle * * RETURNS: int - <0 - if desc1.slicesize < desc2.slicesize * 0 - if desc1.slicesize == desc2.slicesize * >0 - if desc1.slicesize > desc2.slicesize * * PURPOSE: dlist_t helper which compares the sizes of two slices * represented as dm_descriptor_t handles. */ int compare_slice_sizes( void *desc1, void *desc2) { uint64_t size1 = 0; uint64_t size2 = 0; assert(desc1 != NULL); assert(desc2 != NULL); (void) slice_get_size((uintptr_t)desc1, &size1); (void) slice_get_size((uintptr_t)desc2, &size2); return (size1 - size2); } /* * FUNCTION: compare_devconfig_and_descriptor_names(void *devconf, * void *desc) * * INPUT: devconf - opaque pointer to a devconfig_t * desc - opaque pointer to a dm_descriptor_t * * RETURNS: int - <0 - if devconf name is "less than" descr name * 0 - if devconf name is "equal to" descr name * >0 - if devconf name is "greater than" desc name * * PURPOSE: dlist_t helper which compares the name of a devconfig_t * struct to the name for a dm_descriptor_t. * * Note that the order of the arguments is important. * This function is intended to be passed into the various * dlist_* functions which take a comparison function. */ int compare_devconfig_and_descriptor_names( void *devconf, void *desc) { char *volname = NULL; char *descname = NULL; assert(devconf != NULL); assert(desc != NULL); (void) devconfig_get_name((devconfig_t *)devconf, &volname); (void) get_display_name((uintptr_t)desc, &descname); return (string_case_compare(volname, descname)); } /* * FUNCTION: compare_string_to_devconfig_name(void *str, void *devconf) * * INPUT: str - opaque pointer to a char *str * devconf - opaque pointer to a devconfig_t * * RETURNS: int - <0 - if devconf name is "less than" str * 0 - if devconf name is "equal to" str * >0 - if devconf name is "greater than" str * * PURPOSE: dlist_t helper which compares a string to the name of * a devconfig_t struct. */ int compare_string_to_devconfig_name( void *str, void *devconf) { char *volname = NULL; assert(str != NULL); assert(devconf != NULL); (void) devconfig_get_name((devconfig_t *)devconf, &volname); if (volname == NULL) { /* no memory for new string(s) */ return (-1); } return (string_case_compare(volname, (char *)str)); } /* * FUNCTION: free_devconfig_object(void *obj) * * INPUT: obj - an opaque pointer * * RETURNS: void * * PURPOSE: helper which decomposes a devconfig_t struct after a * failed layout attempt. * * reclaims allocated space. * releases reserved volume/HSP names * undoes slicing */ void free_devconfig_object( void *obj) { devconfig_t *dev = NULL; char *name = NULL; dlist_t *iter = NULL; component_type_t type = TYPE_UNKNOWN; if (obj == NULL) { return; } dev = (devconfig_t *)obj; (void) devconfig_get_type(dev, &type); (void) devconfig_get_name(dev, &name); oprintf(OUTPUT_DEBUG, gettext(" -->decomposing %s\n"), name); switch (type) { case TYPE_MIRROR: case TYPE_CONCAT: case TYPE_RAID5: case TYPE_HSP: case TYPE_STRIPE: /* release name */ if (devconfig_isA(dev, TYPE_HSP)) { release_hsp_name(name); } else { release_volume_name(name); } /* decompose volume's components */ iter = devconfig_get_components(dev); dlist_free_items(iter, free_devconfig_object); (void) devconfig_set_components(dev, NULL); break; case TYPE_SLICE: (void) destroy_new_slice(dev); break; default: break; } free_devconfig(dev); } /* * FUNCTION: compare_device_names( * void *str1, void *str2) * * INPUT: str1 - opaque pointer * str2 - opaque pointer * * RETURNS: int - <0 - if str1 < str2 * 0 - if str1 == str2 * >0 - if str1 > str2 * * PURPOSE: dlist_t helper which compares two device name strings. * * Both names are assumed to be in CTD form. * * Either name may be fully qualified by an absolute * path. If only one name is fully qualified, the * leading path with be stripped off prior to the * comparison. * * Uses string_case_compare() to compare the names. */ int compare_device_names( void *str1, void *str2) { char *name1 = (char *)str1; char *name2 = (char *)str2; int val = 0; assert(str1 != NULL); assert(str2 != NULL); /* if one doesn't start with '/', just compare device names */ if (*name1 != '/' || *name2 != '/') { char *short1 = strrchr(name1, '/'); char *short2 = strrchr(name2, '/'); if (short1 == NULL) { short1 = name1; } else { ++short1; } if (short2 == NULL) { short2 = name2; } else { ++short2; } val = string_case_compare(short2, short1); } else { /* if they both start with '/', assume they're full paths */ val = string_case_compare(name2, name1); } return (val); } /* * FUNCTION: compare_descriptors( * void *desc1, void *desc2) * * INPUT: desc1 - opaque pointer * desc2 - opaque pointer * * RETURNS: int - <0 - if desc1 < desc2 * 0 - if desc1 == desc2 * >0 - if desc1 > desc2 * * PURPOSE: dlist_t helper which compares two dm_descriptor_t handles. */ int compare_descriptors( void *desc1, void *desc2) { assert(desc1 != NULL); assert(desc2 != NULL); return ((uintptr_t)desc1 - (uintptr_t)desc2); } /* * FUNCTION: compare_descriptor_names( * void *desc1, void *desc2) * * INPUT: desc1 - opaque pointer * desc2 - opaque pointer * * RETURNS: int - <0 - if desc1.name < desc2.name * 0 - if desc1.name == desc2.name * >0 - if desc1.name > desc2.name * * PURPOSE: dlist_t helper which compares the names associated * with the input dm_descriptor_t handles. * * Retrieves the names associated with both descriptors * and compares them using string_case_compare. */ int compare_descriptor_names( void *desc1, void *desc2) { char *name1 = NULL; char *name2 = NULL; assert(desc1 != NULL); assert(desc2 != NULL); (void) get_name((uintptr_t)desc1, &name1); (void) get_name((uintptr_t)desc2, &name2); return (string_case_compare(name1, name2)); } /* * FUNCTION: compare_slices_on_same_hba( * void *slice1, void *slice2) * * INPUT: slice1 - opaque pointer * slice2 - opaque pointer * * RETURNS: int - 0 - if slice1 is on the same hba as slice2 * !0 - otherwise * * PURPOSE: dlist_t helper which checks whether slice1 is on the * same hba as slice2 */ int compare_slices_on_same_hba( void *slice1, void *slice2) { char *name1, *name2; /* Retrieve the names of the slices */ if (devconfig_get_name((devconfig_t *)slice1, &name1) == 0 && devconfig_get_name((devconfig_t *)slice2, &name2) == 0) { dm_descriptor_t desc1, desc2; /* Retrieve the disk descriptors for the slices */ if (get_disk_for_named_slice(name1, &desc1) == 0 && get_disk_for_named_slice(name2, &desc2) == 0) { dlist_t *hbas1 = NULL; dlist_t *hbas2 = NULL; assert(desc1 != (dm_descriptor_t)0); assert(desc2 != (dm_descriptor_t)0); /* Retrieve list of HBA descriptors for the slices */ if (disk_get_hbas(desc1, &hbas1) == 0 && disk_get_hbas(desc2, &hbas2) == 0) { dlist_t *itr1; for (itr1 = hbas1; itr1 != NULL; itr1 = itr1->next) { dm_descriptor_t hba1 = (uintptr_t)itr1->obj; dlist_t *itr2; for (itr2 = hbas2; itr2 != NULL; itr2 = itr2->next) { dm_descriptor_t hba2 = (uintptr_t)itr2->obj; if (hba1 == hba2) { return (0); } } } } } } return (1); }