Example #1
0
static char *
get_device_name(dm_descriptor_t device, int *error)
{
    char *dup = NULL;
    char *name;

    *error = 0;
    name = dm_get_name(device, error);
    if (*error) {
        handle_error("could not determine name of device");
    } else {
        dup = strdup(name);
        if (dup == NULL) {
            handle_error("out of memory");
            *error = -1;
        }

        dm_free_name(name);
    }

    return (dup);
}
Example #2
0
/*
 * Checks for overlapping slices.   If the given device is a slice, and it
 * overlaps with any non-backup slice on the disk, return true with a detailed
 * description similar to dm_inuse().
 */
int
dm_isoverlapping(char *slicename, char **overlaps_with, int *errp)
{
	dm_descriptor_t slice = NULL;
	dm_descriptor_t *media = NULL;
	dm_descriptor_t *slices = NULL;
	int 		i = 0;
	uint32_t	in_snum;
	uint64_t 	start_block = 0;
	uint64_t 	end_block = 0;
	uint64_t 	media_size = 0;
	uint64_t 	size = 0;
	nvlist_t 	*media_attrs = NULL;
	nvlist_t 	*slice_attrs = NULL;
	int		ret = 0;

	slice = dm_get_descriptor_by_name(DM_SLICE, slicename, errp);
	if (slice == NULL)
		goto out;

	/*
	 * Get the list of slices be fetching the associated media, and then all
	 * associated slices.
	 */
	media = dm_get_associated_descriptors(slice, DM_MEDIA, errp);
	if (media == NULL || *media == NULL || *errp != 0)
		goto out;

	slices = dm_get_associated_descriptors(*media, DM_SLICE, errp);
	if (slices == NULL || *slices == NULL || *errp != 0)
		goto out;

	media_attrs = dm_get_attributes(*media, errp);
	if (media_attrs == NULL || *errp)
		goto out;

	*errp = nvlist_lookup_uint64(media_attrs, DM_NACCESSIBLE, &media_size);
	if (*errp != 0)
		goto out;

	slice_attrs = dm_get_attributes(slice, errp);
	if (slice_attrs == NULL || *errp != 0)
		goto out;

	*errp = nvlist_lookup_uint64(slice_attrs, DM_START, &start_block);
	if (*errp != 0)
		goto out;

	*errp = nvlist_lookup_uint64(slice_attrs, DM_SIZE, &size);
	if (*errp != 0)
		goto out;

	*errp = nvlist_lookup_uint32(slice_attrs, DM_INDEX, &in_snum);
	if (*errp != 0)
		goto out;

	end_block = (start_block + size) - 1;

	for (i = 0; slices[i]; i ++) {
		uint64_t other_start;
		uint64_t other_end;
		uint64_t other_size;
		uint32_t snum;

		nvlist_t *other_attrs = dm_get_attributes(slices[i], errp);

		if (other_attrs == NULL)
			continue;

		if (*errp != 0)
			goto out;

		*errp = nvlist_lookup_uint64(other_attrs, DM_START,
		    &other_start);
		if (*errp) {
			nvlist_free(other_attrs);
			goto out;
		}

		*errp = nvlist_lookup_uint64(other_attrs, DM_SIZE,
		    &other_size);

		if (*errp) {
			nvlist_free(other_attrs);
			ret = -1;
			goto out;
		}

		other_end = (other_size + other_start) - 1;

		*errp = nvlist_lookup_uint32(other_attrs, DM_INDEX,
		    &snum);

		if (*errp) {
			nvlist_free(other_attrs);
			ret = -1;
			goto out;
		}

		/*
		 * Check to see if there are > 2 overlapping regions
		 * on this media in the same region as this slice.
		 * This is done by assuming the following:
		 *   	Slice 2 is the backup slice if it is the size
		 *	of the whole disk
		 * If slice 2 is the overlap and slice 2 is the size of
		 * the whole disk, continue. If another slice is found
		 * that overlaps with our slice, return it.
		 * There is the potential that there is more than one slice
		 * that our slice overlaps with, however, we only return
		 * the first overlapping slice we find.
		 *
		 */
		if (start_block >= other_start && start_block <= other_end) {
			if ((snum == 2 && (other_size == media_size)) ||
			    snum == in_snum) {
				continue;
			} else {
				char *str = dm_get_name(slices[i], errp);
				if (*errp != 0) {
					nvlist_free(other_attrs);
					ret = -1;
					goto out;
				}
				*overlaps_with = strdup(str);
				dm_free_name(str);
				nvlist_free(other_attrs);
				ret = 1;
				goto out;
			}
		} else if (other_start >= start_block &&
		    other_start <= end_block) {
			if ((snum == 2 && (other_size == media_size)) ||
			    snum == in_snum) {
				continue;
			} else {
				char *str = dm_get_name(slices[i], errp);
				if (*errp != 0) {
					nvlist_free(other_attrs);
					ret = -1;
					goto out;
				}
				*overlaps_with = strdup(str);
				dm_free_name(str);
				nvlist_free(other_attrs);
				ret = 1;
				goto out;
			}
		}
		nvlist_free(other_attrs);
	}

out:
	if (media_attrs)
		nvlist_free(media_attrs);
	if (slice_attrs)
		nvlist_free(slice_attrs);

	if (slices)
		dm_free_descriptors(slices);
	if (media)
		dm_free_descriptors(media);
	if (slice)
		dm_free_descriptor(slice);

	return (ret);
}
/* ARGSUSED */
int
check_disk(const char *name, dm_descriptor_t disk, int force, int isspare)
{
	dm_descriptor_t *drive, *media, *slice;
	int err = 0;
	int i;
	int ret;

	/*
	 * Get the drive associated with this disk.  This should never fail,
	 * because we already have an alias handle open for the device.
	 */
	if ((drive = dm_get_associated_descriptors(disk, DM_DRIVE,
	    &err)) == NULL || *drive == NULL) {
		if (err)
			libdiskmgt_error(err);
		return (0);
	}

	if ((media = dm_get_associated_descriptors(*drive, DM_MEDIA,
	    &err)) == NULL) {
		dm_free_descriptors(drive);
		if (err)
			libdiskmgt_error(err);
		return (0);
	}

	dm_free_descriptors(drive);

	/*
	 * It is possible that the user has specified a removable media drive,
	 * and the media is not present.
	 */
	if (*media == NULL) {
		dm_free_descriptors(media);
		vdev_error(gettext("'%s' has no media in drive\n"), name);
		return (-1);
	}

	if ((slice = dm_get_associated_descriptors(*media, DM_SLICE,
	    &err)) == NULL) {
		dm_free_descriptors(media);
		if (err)
			libdiskmgt_error(err);
		return (0);
	}

	dm_free_descriptors(media);

	ret = 0;

	/*
	 * Iterate over all slices and report any errors.  We don't care about
	 * overlapping slices because we are using the whole disk.
	 */
	for (i = 0; slice[i] != NULL; i++) {
		char *name = dm_get_name(slice[i], &err);

		if (check_slice(name, force, B_TRUE, isspare) != 0)
			ret = -1;

		dm_free_name(name);
	}

	dm_free_descriptors(slice);
	return (ret);
}