fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * CDDL HEADER START
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
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 *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
fa9e4066f08beec538e775443c5be79dd423fcabahrens * or http://www.opensolaris.org/os/licensing.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * See the License for the specific language governing permissions
fa9e4066f08beec538e775443c5be79dd423fcabahrens * and limitations under the License.
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
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 *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * CDDL HEADER END
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Use is subject to license terms.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens
f83b46baf98d276f5f84fa84c8b461f412ac1f5ePaul Dagnelie/*
f83b46baf98d276f5f84fa84c8b461f412ac1f5ePaul Dagnelie * Copyright (c) 2015 by Delphix. All rights reserved.
f83b46baf98d276f5f84fa84c8b461f412ac1f5ePaul Dagnelie */
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include "libzfs_jni_diskmgt.h"
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include "libzfs_jni_util.h"
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <strings.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <libzfs.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens#include <sys/mnttab.h>
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Function prototypes
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens
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,
fa9e4066f08beec538e775443c5be79dd423fcabahrens const char *name, uint32_t blocksize, int *error);
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,
fa9e4066f08beec538e775443c5be79dd423fcabahrens uint64_t *size, uint32_t *blocksize, int *error);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void get_slice_use(dm_descriptor_t slice, char *name,
fa9e4066f08beec538e775443c5be79dd423fcabahrens char **used_name, char **used_by, int *error);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic dmgt_slice_t *get_slice(
fa9e4066f08beec538e775443c5be79dd423fcabahrens dm_descriptor_t slice, uint32_t blocksize, int *error);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void handle_error(const char *format, ...);
32f884e0ef76c8ab2a6e26895696620c8d49ad05talleystatic int slice_in_use(dmgt_slice_t *slice, int *error);
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int slice_too_small(dmgt_slice_t *slice);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Static data
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void (*error_func)(const char *, va_list);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Static functions
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic char *
fa9e4066f08beec538e775443c5be79dd423fcabahrensget_device_name(dm_descriptor_t device, int *error)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
f83b46baf98d276f5f84fa84c8b461f412ac1f5ePaul Dagnelie char *dup = NULL;
fa9e4066f08beec538e775443c5be79dd423fcabahrens char *name;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens *error = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens name = dm_get_name(device, error);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (*error) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens handle_error("could not determine name of device");
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else {
fa9e4066f08beec538e775443c5be79dd423fcabahrens dup = strdup(name);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (dup == NULL) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens handle_error("out of memory");
fa9e4066f08beec538e775443c5be79dd423fcabahrens *error = -1;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens dm_free_name(name);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (dup);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Gets a dmgt_disk_t for the given disk dm_descriptor_t.
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Results:
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * 1. Success: error is set to 0 and a dmgt_disk_t is returned
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * 2. Failure: error is set to -1 and NULL is returned
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic dmgt_disk_t *
fa9e4066f08beec538e775443c5be79dd423fcabahrensget_disk(dm_descriptor_t disk, int *error)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens dmgt_disk_t *dp;
fa9e4066f08beec538e775443c5be79dd423fcabahrens *error = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens dp = (dmgt_disk_t *)calloc(1, sizeof (dmgt_disk_t));
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (dp == NULL) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens handle_error("out of memory");
fa9e4066f08beec538e775443c5be79dd423fcabahrens *error = -1;
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else {
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Get name */
fa9e4066f08beec538e775443c5be79dd423fcabahrens dp->name = get_device_name(disk, error);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (!*error) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Get aliases */
fa9e4066f08beec538e775443c5be79dd423fcabahrens dp->aliases = get_disk_aliases(disk, dp->name, error);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (!*error) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Get media */
fa9e4066f08beec538e775443c5be79dd423fcabahrens dm_descriptor_t *media =
fa9e4066f08beec538e775443c5be79dd423fcabahrens dm_get_associated_descriptors(disk,
f83b46baf98d276f5f84fa84c8b461f412ac1f5ePaul Dagnelie DM_MEDIA, error);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (*error != 0 || media == NULL ||
fa9e4066f08beec538e775443c5be79dd423fcabahrens *media == NULL) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens handle_error(
fa9e4066f08beec538e775443c5be79dd423fcabahrens "could not get media from disk %s",
fa9e4066f08beec538e775443c5be79dd423fcabahrens dp->name);
fa9e4066f08beec538e775443c5be79dd423fcabahrens *error = -1;
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Get size */
fa9e4066f08beec538e775443c5be79dd423fcabahrens get_disk_size(media[0], dp->name,
fa9e4066f08beec538e775443c5be79dd423fcabahrens &(dp->size), &(dp->blocksize),
fa9e4066f08beec538e775443c5be79dd423fcabahrens error);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (!*error) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Get free slices */
fa9e4066f08beec538e775443c5be79dd423fcabahrens dp->slices =
fa9e4066f08beec538e775443c5be79dd423fcabahrens get_disk_usable_slices(
f83b46baf98d276f5f84fa84c8b461f412ac1f5ePaul Dagnelie media[0], dp->name,
f83b46baf98d276f5f84fa84c8b461f412ac1f5ePaul Dagnelie dp->blocksize,
f83b46baf98d276f5f84fa84c8b461f412ac1f5ePaul Dagnelie &(dp->in_use), error);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens dm_free_descriptors(media);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (*error) {
dc307942eac821bc70a7a69cbb1ddec4184607c1talley /* Normalize error */
dc307942eac821bc70a7a69cbb1ddec4184607c1talley *error = -1;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (dp != NULL) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens dmgt_free_disk(dp);
fa9e4066f08beec538e775443c5be79dd423fcabahrens dp = NULL;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (dp);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic char **
fa9e4066f08beec538e775443c5be79dd423fcabahrensget_disk_aliases(dm_descriptor_t disk, char *name, int *error)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens char **names = NULL;
fa9e4066f08beec538e775443c5be79dd423fcabahrens dm_descriptor_t *aliases;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens *error = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens aliases = dm_get_associated_descriptors(disk, DM_ALIAS, error);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (*error || aliases == NULL) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens *error = -1;
fa9e4066f08beec538e775443c5be79dd423fcabahrens handle_error("could not get aliases for disk %s", name);
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else {
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens int j;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Count aliases */
f83b46baf98d276f5f84fa84c8b461f412ac1f5ePaul Dagnelie for (j = 0; aliases[j] != NULL; j++)
f83b46baf98d276f5f84fa84c8b461f412ac1f5ePaul Dagnelie ;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens names = (char **)calloc(j + 1, sizeof (char *));
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (names == NULL) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens *error = -1;
fa9e4066f08beec538e775443c5be79dd423fcabahrens handle_error("out of memory");
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else {
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* For each alias... */
fa9e4066f08beec538e775443c5be79dd423fcabahrens for (j = 0; *error == 0 && aliases[j] != NULL; j++) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens dm_descriptor_t alias = aliases[j];
fa9e4066f08beec538e775443c5be79dd423fcabahrens char *aname = dm_get_name(alias, error);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (*error) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens handle_error("could not get alias %d "
fa9e4066f08beec538e775443c5be79dd423fcabahrens "for disk %s", (j + 1), name);
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else {
fa9e4066f08beec538e775443c5be79dd423fcabahrens names[j] = strdup(aname);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (names[j] == NULL) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens *error = -1;
fa9e4066f08beec538e775443c5be79dd423fcabahrens handle_error("out of memory");
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens dm_free_name(aname);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens dm_free_descriptors(aliases);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (*error && names != NULL) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Free previously-allocated names */
c8e9ed14d97e244b9753db14caf8481f181f5750talley zjni_free_array((void **)names, free);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (names);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int
fa9e4066f08beec538e775443c5be79dd423fcabahrensget_disk_online(dm_descriptor_t disk, int *error)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens uint32_t status = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens nvlist_t *attrs;
fa9e4066f08beec538e775443c5be79dd423fcabahrens *error = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens attrs = dm_get_attributes(disk, error);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (*error) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens handle_error("could not get disk attributes for disk");
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else {
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Try to get the status */
fa9e4066f08beec538e775443c5be79dd423fcabahrens nvpair_t *match = zjni_nvlist_walk_nvpair(
fa9e4066f08beec538e775443c5be79dd423fcabahrens attrs, DM_STATUS, DATA_TYPE_UINT32, NULL);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (match == NULL || nvpair_value_uint32(match, &status)) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens handle_error("could not get status of disk");
fa9e4066f08beec538e775443c5be79dd423fcabahrens *error = 1;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens nvlist_free(attrs);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (status != 0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Gets the slices for the given disk.
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Results:
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * 1. Success: error is set to 0 and slices are returned
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * 2. Failure: error is set to -1 and NULL is returned
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic dmgt_slice_t **
fa9e4066f08beec538e775443c5be79dd423fcabahrensget_disk_slices(dm_descriptor_t media, const char *name, uint32_t blocksize,
fa9e4066f08beec538e775443c5be79dd423fcabahrens int *error)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens dm_descriptor_t *slices;
fa9e4066f08beec538e775443c5be79dd423fcabahrens dmgt_slice_t **sap = NULL;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens *error = 0;
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 } else {
fa9e4066f08beec538e775443c5be79dd423fcabahrens int j;
fa9e4066f08beec538e775443c5be79dd423fcabahrens int nslices = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* For each slice... */
fa9e4066f08beec538e775443c5be79dd423fcabahrens for (j = 0; *error == 0 &&
fa9e4066f08beec538e775443c5be79dd423fcabahrens slices != NULL && slices[j] != NULL; j++) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Get slice */
fa9e4066f08beec538e775443c5be79dd423fcabahrens dmgt_slice_t *slice =
fa9e4066f08beec538e775443c5be79dd423fcabahrens get_slice(slices[j], blocksize, error);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (!*error) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley dmgt_slice_t **mem =
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley (dmgt_slice_t **)realloc(sap,
fa9e4066f08beec538e775443c5be79dd423fcabahrens (nslices + 2) * sizeof (dmgt_slice_t *));
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley if (mem == NULL) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens handle_error("out of memory");
fa9e4066f08beec538e775443c5be79dd423fcabahrens *error = -1;
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else {
fa9e4066f08beec538e775443c5be79dd423fcabahrens
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley sap = mem;
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* NULL-terminated array */
fa9e4066f08beec538e775443c5be79dd423fcabahrens sap[nslices] = slice;
fa9e4066f08beec538e775443c5be79dd423fcabahrens sap[nslices + 1] = NULL;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens nslices++;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens dm_free_descriptors(slices);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (*error) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Normalize error */
fa9e4066f08beec538e775443c5be79dd423fcabahrens *error = -1;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley if (sap != NULL) {
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley zjni_free_array((void **)sap,
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley (zjni_free_f)dmgt_free_slice);
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley sap = NULL;
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (sap);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void
fa9e4066f08beec538e775443c5be79dd423fcabahrensremove_slice_from_list(dmgt_slice_t **slices, int index)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens int i;
fa9e4066f08beec538e775443c5be79dd423fcabahrens for (i = index; slices[i] != NULL; i++) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens slices[i] = slices[i + 1];
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int
fa9e4066f08beec538e775443c5be79dd423fcabahrensslices_overlap(dmgt_slice_t *slice1, dmgt_slice_t *slice2)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens uint64_t start1 = slice1->start;
fa9e4066f08beec538e775443c5be79dd423fcabahrens uint64_t end1 = start1 + slice1->size - 1;
fa9e4066f08beec538e775443c5be79dd423fcabahrens uint64_t start2 = slice2->start;
c8e9ed14d97e244b9753db14caf8481f181f5750talley uint64_t end2 = start2 + slice2->size - 1;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens int overlap = (start2 <= end1 && start1 <= end2);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens#ifdef DEBUG
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (overlap) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) fprintf(stderr, "can't use %s: overlaps with %s\n",
fa9e4066f08beec538e775443c5be79dd423fcabahrens slice2->name, slice1->name);
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) fprintf(stderr, " 1: start: %llu - %llu\n",
fa9e4066f08beec538e775443c5be79dd423fcabahrens (unsigned long long)start1, (unsigned long long)end1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) fprintf(stderr, " 2: start: %llu - %llu\n",
fa9e4066f08beec538e775443c5be79dd423fcabahrens (unsigned long long)start2, (unsigned long long)end2);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens#endif
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (overlap);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Gets the slices for the given disk.
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Results:
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * 1. Success: error is set to 0 and slices are returned
fa9e4066f08beec538e775443c5be79dd423fcabahrens *
fa9e4066f08beec538e775443c5be79dd423fcabahrens * 2. Failure: error is set to -1 and NULL is returned
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic dmgt_slice_t **
fa9e4066f08beec538e775443c5be79dd423fcabahrensget_disk_usable_slices(dm_descriptor_t media, const char *name,
fa9e4066f08beec538e775443c5be79dd423fcabahrens uint32_t blocksize, int *in_use, int *error)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens dmgt_slice_t **slices = get_disk_slices(media, name, blocksize, error);
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley if (*error) {
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley slices = NULL;
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens *in_use = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley if (slices != NULL) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens int i, nslices;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
f83b46baf98d276f5f84fa84c8b461f412ac1f5ePaul Dagnelie for (nslices = 0; slices[nslices] != NULL; nslices++)
f83b46baf98d276f5f84fa84c8b461f412ac1f5ePaul Dagnelie ;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Prune slices based on use */
fa9e4066f08beec538e775443c5be79dd423fcabahrens for (i = nslices - 1; i >= 0; i--) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens dmgt_slice_t *slice = slices[i];
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley int s_in_use;
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley /*
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley * Slice at this index could be NULL if
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley * removed in earlier iteration
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley */
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (slice == NULL) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens continue;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley s_in_use = slice_in_use(slice, error);
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley if (*error) {
f83b46baf98d276f5f84fa84c8b461f412ac1f5ePaul Dagnelie break;
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley }
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley if (s_in_use) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens int j;
fa9e4066f08beec538e775443c5be79dd423fcabahrens remove_slice_from_list(slices, i);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley /* Disk is in use */
fa9e4066f08beec538e775443c5be79dd423fcabahrens *in_use = 1;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Remove any slice that overlaps with this
fa9e4066f08beec538e775443c5be79dd423fcabahrens * in-use slice
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens for (j = nslices - 1; j >= 0; j--) {
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley dmgt_slice_t *slice2 = slices[j];
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley if (slice2 != NULL &&
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley slices_overlap(slice, slice2)) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens remove_slice_from_list(slices,
fa9e4066f08beec538e775443c5be79dd423fcabahrens j);
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley dmgt_free_slice(slice2);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley dmgt_free_slice(slice);
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley } else if (slice_too_small(slice)) {
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley remove_slice_from_list(slices, i);
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley dmgt_free_slice(slice);
dc307942eac821bc70a7a69cbb1ddec4184607c1talley }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley if (*error) {
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley /* Normalize error */
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley *error = -1;
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley if (slices != NULL) {
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley zjni_free_array((void **)slices,
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley (zjni_free_f)dmgt_free_slice);
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley slices = NULL;
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley }
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley }
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (slices);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void
fa9e4066f08beec538e775443c5be79dd423fcabahrensget_disk_size(dm_descriptor_t media, char *name, uint64_t *size,
fa9e4066f08beec538e775443c5be79dd423fcabahrens uint32_t *blocksize, int *error)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens nvlist_t *attrs;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens *size = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens *error = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens attrs = dm_get_attributes(media, error);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (*error) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens handle_error("could not get media attributes from disk: %s",
fa9e4066f08beec538e775443c5be79dd423fcabahrens name);
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Try to get the number of accessible blocks */
fa9e4066f08beec538e775443c5be79dd423fcabahrens nvpair_t *match = zjni_nvlist_walk_nvpair(
fa9e4066f08beec538e775443c5be79dd423fcabahrens attrs, DM_NACCESSIBLE, DATA_TYPE_UINT64, NULL);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (match == NULL || nvpair_value_uint64(match, size)) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Disk is probably not labeled, get raw size instead */
fa9e4066f08beec538e775443c5be79dd423fcabahrens match = zjni_nvlist_walk_nvpair(
fa9e4066f08beec538e775443c5be79dd423fcabahrens attrs, DM_SIZE, DATA_TYPE_UINT64, NULL);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (match == NULL || nvpair_value_uint64(match, size)) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens handle_error("could not get size of disk: %s",
fa9e4066f08beec538e775443c5be79dd423fcabahrens name);
fa9e4066f08beec538e775443c5be79dd423fcabahrens *error = 1;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (*error == 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens match = zjni_nvlist_walk_nvpair(
fa9e4066f08beec538e775443c5be79dd423fcabahrens attrs, DM_BLOCKSIZE, DATA_TYPE_UINT32, NULL);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (match == NULL ||
fa9e4066f08beec538e775443c5be79dd423fcabahrens nvpair_value_uint32(match, blocksize)) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens handle_error("could not get "
fa9e4066f08beec538e775443c5be79dd423fcabahrens "block size of disk: %s", name);
fa9e4066f08beec538e775443c5be79dd423fcabahrens *error = 1;
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else {
fa9e4066f08beec538e775443c5be79dd423fcabahrens *size *= *blocksize;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens nvlist_free(attrs);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void
fa9e4066f08beec538e775443c5be79dd423fcabahrensget_slice_use(dm_descriptor_t slice, char *name, char **used_name,
fa9e4066f08beec538e775443c5be79dd423fcabahrens char **used_by, int *error)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
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 } else {
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens *used_name = NULL;
fa9e4066f08beec538e775443c5be79dd423fcabahrens *used_by = NULL;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (stats != NULL) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens char *tmp;
fa9e4066f08beec538e775443c5be79dd423fcabahrens nvpair_t *match;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Get the type of usage for this slice */
fa9e4066f08beec538e775443c5be79dd423fcabahrens match = zjni_nvlist_walk_nvpair(
fa9e4066f08beec538e775443c5be79dd423fcabahrens stats, DM_USED_BY, DATA_TYPE_STRING, NULL);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (match != NULL &&
fa9e4066f08beec538e775443c5be79dd423fcabahrens nvpair_value_string(match, &tmp) == 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens *used_name = strdup(tmp);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (*used_name == NULL) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens *error = -1;
fa9e4066f08beec538e775443c5be79dd423fcabahrens handle_error("out of memory");
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else {
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Get the object using this slice */
fa9e4066f08beec538e775443c5be79dd423fcabahrens match =
fa9e4066f08beec538e775443c5be79dd423fcabahrens zjni_nvlist_walk_nvpair(stats,
fa9e4066f08beec538e775443c5be79dd423fcabahrens DM_USED_NAME, DATA_TYPE_STRING,
fa9e4066f08beec538e775443c5be79dd423fcabahrens NULL);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (match != NULL &&
fa9e4066f08beec538e775443c5be79dd423fcabahrens nvpair_value_string(match, &tmp) ==
fa9e4066f08beec538e775443c5be79dd423fcabahrens 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens *used_by = strdup(tmp);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (*used_by == NULL) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens *error = -1;
fa9e4066f08beec538e775443c5be79dd423fcabahrens handle_error(
fa9e4066f08beec538e775443c5be79dd423fcabahrens "out of memory");
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens nvlist_free(stats);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic dmgt_slice_t *
fa9e4066f08beec538e775443c5be79dd423fcabahrensget_slice(dm_descriptor_t slice, uint32_t blocksize, int *error)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens dmgt_slice_t *sp;
fa9e4066f08beec538e775443c5be79dd423fcabahrens *error = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens sp = (dmgt_slice_t *)calloc(1, sizeof (dmgt_slice_t));
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (sp == NULL) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens *error = -1;
fa9e4066f08beec538e775443c5be79dd423fcabahrens handle_error("out of memory");
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else {
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Get name */
fa9e4066f08beec538e775443c5be79dd423fcabahrens sp->name = get_device_name(slice, error);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (!*error) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens nvlist_t *attrs = dm_get_attributes(slice, error);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (*error) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens handle_error("could not get "
fa9e4066f08beec538e775443c5be79dd423fcabahrens "attributes from slice: %s", sp->name);
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Get the size in blocks */
fa9e4066f08beec538e775443c5be79dd423fcabahrens nvpair_t *match = zjni_nvlist_walk_nvpair(
fa9e4066f08beec538e775443c5be79dd423fcabahrens attrs, DM_SIZE, DATA_TYPE_UINT64, NULL);
fa9e4066f08beec538e775443c5be79dd423fcabahrens uint64_t size_blocks;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens sp->size = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (match == NULL ||
fa9e4066f08beec538e775443c5be79dd423fcabahrens nvpair_value_uint64(match, &size_blocks)) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens handle_error("could not get "
fa9e4066f08beec538e775443c5be79dd423fcabahrens "size of slice: %s", sp->name);
fa9e4066f08beec538e775443c5be79dd423fcabahrens *error = 1;
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else {
fa9e4066f08beec538e775443c5be79dd423fcabahrens uint64_t start_blocks;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Convert to bytes */
fa9e4066f08beec538e775443c5be79dd423fcabahrens sp->size = blocksize * size_blocks;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Get the starting block */
fa9e4066f08beec538e775443c5be79dd423fcabahrens match = zjni_nvlist_walk_nvpair(
fa9e4066f08beec538e775443c5be79dd423fcabahrens attrs, DM_START, DATA_TYPE_UINT64,
fa9e4066f08beec538e775443c5be79dd423fcabahrens NULL);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (match == NULL ||
fa9e4066f08beec538e775443c5be79dd423fcabahrens nvpair_value_uint64(match,
fa9e4066f08beec538e775443c5be79dd423fcabahrens &start_blocks)) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens handle_error(
fa9e4066f08beec538e775443c5be79dd423fcabahrens "could not get "
fa9e4066f08beec538e775443c5be79dd423fcabahrens "start block of slice: %s",
fa9e4066f08beec538e775443c5be79dd423fcabahrens sp->name);
fa9e4066f08beec538e775443c5be79dd423fcabahrens *error = 1;
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else {
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Convert to bytes */
fa9e4066f08beec538e775443c5be79dd423fcabahrens sp->start =
fa9e4066f08beec538e775443c5be79dd423fcabahrens blocksize * start_blocks;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Set slice use */
fa9e4066f08beec538e775443c5be79dd423fcabahrens get_slice_use(slice, sp->name,
fa9e4066f08beec538e775443c5be79dd423fcabahrens &(sp->used_name),
fa9e4066f08beec538e775443c5be79dd423fcabahrens &(sp->used_by), error);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (*error && sp != NULL) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens dmgt_free_slice(sp);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (sp);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic void
fa9e4066f08beec538e775443c5be79dd423fcabahrenshandle_error(const char *format, ...)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens va_list ap;
fa9e4066f08beec538e775443c5be79dd423fcabahrens va_start(ap, format);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (error_func != NULL) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens error_func(format, ap);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens va_end(ap);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/* Should go away once 6285992 is fixed */
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int
fa9e4066f08beec538e775443c5be79dd423fcabahrensslice_too_small(dmgt_slice_t *slice)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Check size */
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (slice->size < SPA_MINDEVSIZE) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens#ifdef DEBUG
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) fprintf(stderr, "can't use %s: slice too small: %llu\n",
f83b46baf98d276f5f84fa84c8b461f412ac1f5ePaul Dagnelie slice->name, (unsigned long long)slice->size);
fa9e4066f08beec538e775443c5be79dd423fcabahrens#endif
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensstatic int
32f884e0ef76c8ab2a6e26895696620c8d49ad05talleyslice_in_use(dmgt_slice_t *slice, int *error)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley char *msg = NULL;
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley int in_use;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
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 if (*error) {
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley handle_error("%s: could not determine usage", slice->name);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens#ifdef DEBUG
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (in_use) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens (void) fprintf(stderr,
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley "can't use %s: used name: %s: used by: %s\n message: %s\n",
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley slice->name, slice->used_name, slice->used_by, msg);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens#endif
fa9e4066f08beec538e775443c5be79dd423fcabahrens
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley if (msg != NULL) {
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley free(msg);
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley }
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (in_use);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Extern functions
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
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.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrensint
fa9e4066f08beec538e775443c5be79dd423fcabahrensdmgt_avail_disk_iter(dmgt_disk_iter_f func, void *data)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens int error = 0;
fa9e4066f08beec538e775443c5be79dd423fcabahrens int filter[] = { DM_DT_FIXED, -1 };
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Search for fixed disks */
fa9e4066f08beec538e775443c5be79dd423fcabahrens dm_descriptor_t *disks = dm_get_descriptors(DM_DRIVE, filter, &error);
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (error) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens handle_error("unable to communicate with libdiskmgt");
fa9e4066f08beec538e775443c5be79dd423fcabahrens } else {
fa9e4066f08beec538e775443c5be79dd423fcabahrens int i;
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* For each disk... */
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley for (i = 0; disks != NULL && disks[i] != NULL; i++) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens dm_descriptor_t disk = (dm_descriptor_t)disks[i];
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley int online;
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley /* Reset error flag for each disk */
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley error = 0;
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley /* Is this disk online? */
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley online = get_disk_online(disk, &error);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (!error && online) {
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley /* Get a dmgt_disk_t for this dm_descriptor_t */
fa9e4066f08beec538e775443c5be79dd423fcabahrens dmgt_disk_t *dp = get_disk(disk, &error);
dc307942eac821bc70a7a69cbb1ddec4184607c1talley if (!error) {
32f884e0ef76c8ab2a6e26895696620c8d49ad05talley
dc307942eac821bc70a7a69cbb1ddec4184607c1talley /*
dc307942eac821bc70a7a69cbb1ddec4184607c1talley * If this disk or any of its
dc307942eac821bc70a7a69cbb1ddec4184607c1talley * slices is usable...
dc307942eac821bc70a7a69cbb1ddec4184607c1talley */
dc307942eac821bc70a7a69cbb1ddec4184607c1talley if (!dp->in_use ||
dc307942eac821bc70a7a69cbb1ddec4184607c1talley zjni_count_elements(
dc307942eac821bc70a7a69cbb1ddec4184607c1talley (void **)dp->slices) != 0) {
dc307942eac821bc70a7a69cbb1ddec4184607c1talley
fa9e4066f08beec538e775443c5be79dd423fcabahrens /* Run the given function */
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (func(dp, data)) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens error = -1;
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens dmgt_free_disk(dp);
dc307942eac821bc70a7a69cbb1ddec4184607c1talley#ifdef DEBUG
dc307942eac821bc70a7a69cbb1ddec4184607c1talley } else {
dc307942eac821bc70a7a69cbb1ddec4184607c1talley (void) fprintf(stderr, "disk "
dc307942eac821bc70a7a69cbb1ddec4184607c1talley "has no available slices: "
dc307942eac821bc70a7a69cbb1ddec4184607c1talley "%s\n", dp->name);
dc307942eac821bc70a7a69cbb1ddec4184607c1talley#endif
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
dc307942eac821bc70a7a69cbb1ddec4184607c1talley
dc307942eac821bc70a7a69cbb1ddec4184607c1talley }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens dm_free_descriptors(disks);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (error);
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensvoid
fa9e4066f08beec538e775443c5be79dd423fcabahrensdmgt_free_disk(dmgt_disk_t *disk)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (disk != NULL) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens free(disk->name);
c8e9ed14d97e244b9753db14caf8481f181f5750talley zjni_free_array((void **)disk->aliases, free);
c8e9ed14d97e244b9753db14caf8481f181f5750talley zjni_free_array((void **)disk->slices,
c8e9ed14d97e244b9753db14caf8481f181f5750talley (zjni_free_f)dmgt_free_slice);
fa9e4066f08beec538e775443c5be79dd423fcabahrens free(disk);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrensvoid
fa9e4066f08beec538e775443c5be79dd423fcabahrensdmgt_free_slice(dmgt_slice_t *slice)
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (slice != NULL) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens free(slice->name);
fa9e4066f08beec538e775443c5be79dd423fcabahrens free(slice->used_name);
fa9e4066f08beec538e775443c5be79dd423fcabahrens free(slice->used_by);
fa9e4066f08beec538e775443c5be79dd423fcabahrens free(slice);
fa9e4066f08beec538e775443c5be79dd423fcabahrens }
fa9e4066f08beec538e775443c5be79dd423fcabahrens}
fa9e4066f08beec538e775443c5be79dd423fcabahrens
fa9e4066f08beec538e775443c5be79dd423fcabahrens/*
fa9e4066f08beec538e775443c5be79dd423fcabahrens * For clients that need to capture error output.
fa9e4066f08beec538e775443c5be79dd423fcabahrens */
fa9e4066f08beec538e775443c5be79dd423fcabahrensvoid
fa9e4066f08beec538e775443c5be79dd423fcabahrensdmgt_set_error_handler(void (*func)(const char *, va_list))
fa9e4066f08beec538e775443c5be79dd423fcabahrens{
fa9e4066f08beec538e775443c5be79dd423fcabahrens error_func = func;
fa9e4066f08beec538e775443c5be79dd423fcabahrens}