fa9e4066f08beec538e775443c5be79dd423fcabahrens * CDDL HEADER START
fa9e4066f08beec538e775443c5be79dd423fcabahrens * The contents of this file are subject to the terms of the
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley * Common Development and Distribution License (the "License").
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley * You may not use this file except in compliance with the License.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
fa9e4066f08beec538e775443c5be79dd423fcabahrens * See the License for the specific language governing permissions
fa9e4066f08beec538e775443c5be79dd423fcabahrens * and limitations under the License.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * When distributing Covered Code, include this CDDL HEADER in each
fa9e4066f08beec538e775443c5be79dd423fcabahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * If applicable, add the following below this CDDL HEADER, with the
fa9e4066f08beec538e775443c5be79dd423fcabahrens * fields enclosed by brackets "[]" replaced with your own identifying
fa9e4066f08beec538e775443c5be79dd423fcabahrens * information: Portions Copyright [yyyy] [name of copyright owner]
fa9e4066f08beec538e775443c5be79dd423fcabahrens * CDDL HEADER END
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Use is subject to license terms.
f83b46baf98d276f5f84fa84c8b461f412ac1f5ePaul Dagnelie * Copyright (c) 2015 by Delphix. All rights reserved.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Function prototypes
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic char *get_device_name(dm_descriptor_t device, int *error);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic dmgt_disk_t *get_disk(dm_descriptor_t disk, int *error);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic char **get_disk_aliases(dm_descriptor_t disk, char *name, int *error);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int get_disk_online(dm_descriptor_t disk, int *error);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void remove_slice_from_list(dmgt_slice_t **slices, int index);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic dmgt_slice_t **get_disk_slices(dm_descriptor_t media,
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic dmgt_slice_t **get_disk_usable_slices(dm_descriptor_t media,
fa9e4066f08beec538e775443c5be79dd423fcabahrens const char *name, uint32_t blocksize, int *in_use, int *error);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void get_disk_size(dm_descriptor_t media, char *name,
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void get_slice_use(dm_descriptor_t slice, char *name,
fa9e4066f08beec538e775443c5be79dd423fcabahrens dm_descriptor_t slice, uint32_t blocksize, int *error);
32f884e0ef76c8ab2a6e26895696620c8d49ad05talleystatic int slice_in_use(dmgt_slice_t *slice, int *error);
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Static data
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Static functions
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic char *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Gets a dmgt_disk_t for the given disk dm_descriptor_t.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * 1. Success: error is set to 0 and a dmgt_disk_t is returned
fa9e4066f08beec538e775443c5be79dd423fcabahrens * 2. Failure: error is set to -1 and NULL is returned
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Get name */
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Get aliases */
fa9e4066f08beec538e775443c5be79dd423fcabahrens dp->aliases = get_disk_aliases(disk, dp->name, error);
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Get media */
fa9e4066f08beec538e775443c5be79dd423fcabahrens "could not get media from disk %s",
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Get size */
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Get free slices */
dc307942eac821bc70a7a69cbb1ddec4184607c1talley /* Normalize error */
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic char **
fa9e4066f08beec538e775443c5be79dd423fcabahrensget_disk_aliases(dm_descriptor_t disk, char *name, int *error)
fa9e4066f08beec538e775443c5be79dd423fcabahrens aliases = dm_get_associated_descriptors(disk, DM_ALIAS, error);
fa9e4066f08beec538e775443c5be79dd423fcabahrens handle_error("could not get aliases for disk %s", name);
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Count aliases */
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* For each alias... */
fa9e4066f08beec538e775443c5be79dd423fcabahrens for (j = 0; *error == 0 && aliases[j] != NULL; j++) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Free previously-allocated names */
fa9e4066f08beec538e775443c5be79dd423fcabahrens handle_error("could not get disk attributes for disk");
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Try to get the status */
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (match == NULL || nvpair_value_uint32(match, &status)) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (status != 0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Gets the slices for the given disk.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * 1. Success: error is set to 0 and slices are returned
fa9e4066f08beec538e775443c5be79dd423fcabahrens * 2. Failure: error is set to -1 and NULL is returned
fa9e4066f08beec538e775443c5be79dd423fcabahrensget_disk_slices(dm_descriptor_t media, const char *name, uint32_t blocksize,
fa9e4066f08beec538e775443c5be79dd423fcabahrens slices = dm_get_associated_descriptors(media, DM_SLICE, error);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (*error != 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens handle_error("could not get slices of disk %s", name);
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* For each slice... */
fa9e4066f08beec538e775443c5be79dd423fcabahrens for (j = 0; *error == 0 &&
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Get slice */
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* NULL-terminated array */
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Normalize error */
fa9e4066f08beec538e775443c5be79dd423fcabahrensremove_slice_from_list(dmgt_slice_t **slices, int index)
fa9e4066f08beec538e775443c5be79dd423fcabahrensslices_overlap(dmgt_slice_t *slice1, dmgt_slice_t *slice2)
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) fprintf(stderr, "can't use %s: overlaps with %s\n",
fa9e4066f08beec538e775443c5be79dd423fcabahrens (unsigned long long)start1, (unsigned long long)end1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens (unsigned long long)start2, (unsigned long long)end2);
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Gets the slices for the given disk.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * 1. Success: error is set to 0 and slices are returned
fa9e4066f08beec538e775443c5be79dd423fcabahrens * 2. Failure: error is set to -1 and NULL is returned
fa9e4066f08beec538e775443c5be79dd423fcabahrensget_disk_usable_slices(dm_descriptor_t media, const char *name,
fa9e4066f08beec538e775443c5be79dd423fcabahrens dmgt_slice_t **slices = get_disk_slices(media, name, blocksize, error);
f83b46baf98d276f5f84fa84c8b461f412ac1f5ePaul Dagnelie for (nslices = 0; slices[nslices] != NULL; nslices++)
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Prune slices based on use */
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley * Slice at this index could be NULL if
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley * removed in earlier iteration
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley /* Disk is in use */
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Remove any slice that overlaps with this
fa9e4066f08beec538e775443c5be79dd423fcabahrens * in-use slice
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley /* Normalize error */
fa9e4066f08beec538e775443c5be79dd423fcabahrensget_disk_size(dm_descriptor_t media, char *name, uint64_t *size,
fa9e4066f08beec538e775443c5be79dd423fcabahrens handle_error("could not get media attributes from disk: %s",
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Try to get the number of accessible blocks */
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (match == NULL || nvpair_value_uint64(match, size)) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Disk is probably not labeled, get raw size instead */
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (match == NULL || nvpair_value_uint64(match, size)) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (*error == 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrensget_slice_use(dm_descriptor_t slice, char *name, char **used_name,
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Get slice use statistics */
fa9e4066f08beec538e775443c5be79dd423fcabahrens nvlist_t *stats = dm_get_stats(slice, DM_SLICE_STAT_USE, error);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (*error != 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens handle_error("could not get stats of slice %s", name);
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Get the type of usage for this slice */
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Get the object using this slice */
fa9e4066f08beec538e775443c5be79dd423fcabahrens "out of memory");
fa9e4066f08beec538e775443c5be79dd423fcabahrensget_slice(dm_descriptor_t slice, uint32_t blocksize, int *error)
fa9e4066f08beec538e775443c5be79dd423fcabahrens sp = (dmgt_slice_t *)calloc(1, sizeof (dmgt_slice_t));
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Get name */
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Get the size in blocks */
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Convert to bytes */
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Get the starting block */
fa9e4066f08beec538e775443c5be79dd423fcabahrens "could not get "
fa9e4066f08beec538e775443c5be79dd423fcabahrens "start block of slice: %s",
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Convert to bytes */
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Set slice use */
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* Should go away once 6285992 is fixed */
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Check size */
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) fprintf(stderr, "can't use %s: slice too small: %llu\n",
f83b46baf98d276f5f84fa84c8b461f412ac1f5ePaul Dagnelie slice->name, (unsigned long long)slice->size);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley /* Determine whether this slice could be passed to "zpool -f" */
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley in_use = dm_inuse(slice->name, &msg, DM_WHO_ZPOOL_FORCE, error);
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley handle_error("%s: could not determine usage", slice->name);
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley "can't use %s: used name: %s: used by: %s\n message: %s\n",
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Extern functions
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Iterates through each available disk on the system. For each free
fa9e4066f08beec538e775443c5be79dd423fcabahrens * dmgt_disk_t *, runs the given function with the dmgt_disk_t * as
fa9e4066f08beec538e775443c5be79dd423fcabahrens * the first arg and the given void * as the second arg.
fa9e4066f08beec538e775443c5be79dd423fcabahrensdmgt_avail_disk_iter(dmgt_disk_iter_f func, void *data)
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Search for fixed disks */
fa9e4066f08beec538e775443c5be79dd423fcabahrens dm_descriptor_t *disks = dm_get_descriptors(DM_DRIVE, filter, &error);
fa9e4066f08beec538e775443c5be79dd423fcabahrens handle_error("unable to communicate with libdiskmgt");
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* For each disk... */
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley for (i = 0; disks != NULL && disks[i] != NULL; i++) {
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley /* Reset error flag for each disk */
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley /* Is this disk online? */
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley /* Get a dmgt_disk_t for this dm_descriptor_t */
dc307942eac821bc70a7a69cbb1ddec4184607c1talley * If this disk or any of its
dc307942eac821bc70a7a69cbb1ddec4184607c1talley * slices is usable...
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Run the given function */
dc307942eac821bc70a7a69cbb1ddec4184607c1talley "has no available slices: "
fa9e4066f08beec538e775443c5be79dd423fcabahrens * For clients that need to capture error output.
fa9e4066f08beec538e775443c5be79dd423fcabahrensdmgt_set_error_handler(void (*func)(const char *, va_list))