summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/zpool/zpool_vdev.c485
-rw-r--r--usr/src/lib/libdiskmgt/common/disks_private.h5
-rw-r--r--usr/src/lib/libdiskmgt/common/entry.c211
-rw-r--r--usr/src/lib/libdiskmgt/common/inuse_zpool.c48
-rw-r--r--usr/src/lib/libdiskmgt/common/libdiskmgt.h7
-rw-r--r--usr/src/lib/libdiskmgt/common/slice.c30
-rw-r--r--usr/src/lib/libdiskmgt/spec/diskmgt.spec6
-rw-r--r--usr/src/lib/libzfs/common/libzfs.h3
-rw-r--r--usr/src/lib/libzfs/common/libzfs_import.c31
-rw-r--r--usr/src/uts/common/sys/fs/zfs.h12
10 files changed, 367 insertions, 471 deletions
diff --git a/usr/src/cmd/zpool/zpool_vdev.c b/usr/src/cmd/zpool/zpool_vdev.c
index c53a81e980..2dd85062be 100644
--- a/usr/src/cmd/zpool/zpool_vdev.c
+++ b/usr/src/cmd/zpool/zpool_vdev.c
@@ -20,7 +20,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -109,371 +109,55 @@ vdev_error(const char *fmt, ...)
va_end(ap);
}
-void
-_libdskmgt_error(int err, const char *file, int line)
+static void
+libdiskmgt_error(int error)
{
- if (err == 0)
- no_memory();
-
- /*
- * Some of the libdiskmgt stuff requires root privileges in order to
- * examine devices. Bail out gracefully in this case.
- */
- if (err == EACCES) {
- (void) fprintf(stderr, gettext("cannot determine disk "
- "configuration: permission denied\n"));
- exit(1);
- }
-
- (void) fprintf(stderr, gettext("internal error: disk configuration "
- "error %d at line %d of file %s\n"), err, line, file);
- abort();
-}
-
-#define libdskmgt_error(err) (_libdskmgt_error((err), __FILE__, __LINE__))
-
-/*
- * Checks whether a single slice overlaps with any of the slices in the provided
- * list. Called by check_overlapping().
- */
-int
-is_overlapping(dm_descriptor_t slice, dm_descriptor_t media,
- dm_descriptor_t *slice_list, int *error, char **overlaps_with)
-{
- 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;
- nvlist_t *slice_attrs;
-
- media_attrs = dm_get_attributes(media, error);
- if (*error != 0) {
- return (-1);
- }
-
- if (media_attrs == NULL) {
- return (0);
- }
-
- *error = nvlist_lookup_uint64(media_attrs, DM_NACCESSIBLE, &media_size);
- if (*error != 0) {
- nvlist_free(media_attrs);
- return (-1);
- }
-
- slice_attrs = dm_get_attributes(slice, error);
- if (*error != 0) {
- nvlist_free(media_attrs);
- return (-1);
- }
- /*
- * Not really possible, but the error above would catch any system
- * errors.
- */
- if (slice_attrs == NULL) {
- nvlist_free(media_attrs);
- return (0);
- }
-
- *error = nvlist_lookup_uint64(slice_attrs, DM_START, &start_block);
- if (*error != 0) {
- nvlist_free(media_attrs);
- nvlist_free(slice_attrs);
- return (-1);
- }
-
- *error = nvlist_lookup_uint64(slice_attrs, DM_SIZE, &size);
- if (*error != 0) {
- nvlist_free(media_attrs);
- nvlist_free(slice_attrs);
- return (-1);
- }
- *error = nvlist_lookup_uint32(slice_attrs, DM_INDEX, &in_snum);
- if (*error != 0) {
- nvlist_free(media_attrs);
- nvlist_free(slice_attrs);
- return (-1);
- }
-
- end_block = (start_block + size) - 1;
-
- for (i = 0; slice_list[i]; i ++) {
- uint64_t other_start;
- uint64_t other_end;
- uint64_t other_size;
- uint32_t snum;
-
- nvlist_t *other_attrs = dm_get_attributes(slice_list[i], error);
- if (*error != 0) {
- return (-1);
- }
-
- if (other_attrs == NULL)
- continue;
-
- *error = nvlist_lookup_uint64(other_attrs, DM_START,
- &other_start);
- if (*error) {
- nvlist_free(media_attrs);
- nvlist_free(slice_attrs);
- nvlist_free(other_attrs);
- return (-1);
- }
-
- *error = nvlist_lookup_uint64(other_attrs, DM_SIZE,
- &other_size);
-
- if (*error) {
- nvlist_free(media_attrs);
- nvlist_free(slice_attrs);
- nvlist_free(other_attrs);
- return (-1);
- }
-
- other_end = (other_size + other_start) - 1;
-
- *error = nvlist_lookup_uint32(other_attrs, DM_INDEX,
- &snum);
-
- if (*error) {
- nvlist_free(media_attrs);
- nvlist_free(slice_attrs);
- nvlist_free(other_attrs);
- return (-1);
- }
-
- /*
- * 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(slice_list[i], error);
- if (*error != 0) {
- nvlist_free(media_attrs);
- nvlist_free(slice_attrs);
- nvlist_free(other_attrs);
- return (-1);
- }
- *overlaps_with = strdup(str);
- dm_free_name(str);
- nvlist_free(media_attrs);
- nvlist_free(slice_attrs);
- nvlist_free(other_attrs);
- return (1);
- }
- } 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(slice_list[i], error);
- if (*error != 0) {
- nvlist_free(media_attrs);
- nvlist_free(slice_attrs);
- nvlist_free(other_attrs);
- return (-1);
- }
- *overlaps_with = strdup(str);
- dm_free_name(str);
- nvlist_free(media_attrs);
- nvlist_free(slice_attrs);
- nvlist_free(other_attrs);
- return (1);
- }
- }
- nvlist_free(other_attrs);
- }
- nvlist_free(media_attrs);
- nvlist_free(slice_attrs);
- return (0);
+ (void) fprintf(stderr, gettext("warning: device in use checking "
+ "failed: %s\n"), strerror(error));
}
/*
- * Check to see whether the given slice overlaps with any other slices. Get the
- * associated slice information and pass on to is_overlapping().
+ * Validate a device, passing the bulk of the work off to libdiskmgt.
*/
int
-check_overlapping(const char *slicename, dm_descriptor_t slice)
+check_slice(const char *path, int force, int wholedisk)
{
- dm_descriptor_t *media;
- dm_descriptor_t *slices;
- int error;
- char *overlaps;
+ char *msg;
+ int error = 0;
int ret = 0;
- /*
- * Get the list of slices be fetching the associated media, and then all
- * associated slices.
- */
- media = dm_get_associated_descriptors(slice, DM_MEDIA, &error);
- if (media == NULL || *media == NULL || error != 0)
- libdskmgt_error(error);
-
- slices = dm_get_associated_descriptors(*media, DM_SLICE, &error);
- if (slices == NULL || *slices == NULL || error != 0)
- libdskmgt_error(error);
-
-
- overlaps = NULL;
- if (is_overlapping(slice, *media, slices, &error, &overlaps)) {
- vdev_error(gettext("device '%s' overlaps with '%s'\n"),
- slicename, overlaps);
- ret = -1;
- }
-
- if (overlaps != NULL)
- free(overlaps);
- dm_free_descriptors(slices);
- dm_free_descriptors(media);
-
- return (ret);
-}
-
-/*
- * Validate the given slice. If 'diskname' is non-NULL, then this is a single
- * slice on a complete disk. If 'force' is set, then the user specified '-f'
- * and we only want to report error for completely forbidden uses.
- */
-int
-check_slice(const char *slicename, dm_descriptor_t slice, int force,
- int overlap)
-{
- nvlist_t *stats;
- int err;
- nvpair_t *nvwhat, *nvdesc;
- char *what, *desc, *name;
- int found = FALSE;
- int found_zfs = FALSE;
- int fd;
-
- if ((stats = dm_get_stats(slice, DM_SLICE_STAT_USE, &err)) == NULL)
- libdskmgt_error(err);
-
- /*
- * Always check to see if this is used by an active ZFS pool.
- */
- if ((fd = open(slicename, O_RDONLY)) > 0) {
- if (zpool_in_use(fd, &desc, &name)) {
-
- if (!force) {
- vdev_error(gettext("%s is part of %s pool "
- "'%s'\n"), slicename, desc, name);
- found = found_zfs = TRUE;
- }
-
- free(desc);
- free(name);
+ if (dm_inuse((char *)path, &msg,
+ force ? DM_WHO_ZPOOL_FORCE : DM_WHO_ZPOOL, &error) || error) {
+ if (error != 0) {
+ libdiskmgt_error(error);
+ return (0);
+ } else {
+ vdev_error("%s", msg);
+ free(msg);
}
- (void) close(fd);
+ ret = -1;
}
/*
- * This slice is in use. Print out a descriptive message describing who
- * is using it. The 'used_by' nvlist is formatted as:
- *
- * (used_by=what, used_name=desc, ...)
- *
- * Each 'used_by' must be accompanied by a 'used_name'.
+ * If we're given a whole disk, ignore overlapping slices since we're
+ * about to label it anyway.
*/
- nvdesc = NULL;
- for (;;) {
- nvwhat = nvlist_next_nvpair(stats, nvdesc);
- nvdesc = nvlist_next_nvpair(stats, nvwhat);
-
- if (nvwhat == NULL || nvdesc == NULL)
- break;
-
- assert(strcmp(nvpair_name(nvwhat), DM_USED_BY) == 0);
- assert(strcmp(nvpair_name(nvdesc), DM_USED_NAME) == 0);
-
- verify(nvpair_value_string(nvwhat, &what) == 0);
- verify(nvpair_value_string(nvdesc, &desc) == 0);
-
- /*
- * For currently mounted filesystems, filesystems in
- * /etc/vfstab, or dedicated dump devices, we can never use
- * them, even if '-f' is specified. The rest of the errors
- * indicate that a filesystem was detected on disk, which can be
- * overridden with '-f'.
- */
- if (strcmp(what, DM_USE_MOUNT) == 0 ||
- strcmp(what, DM_USE_VFSTAB) == 0 ||
- strcmp(what, DM_USE_DUMP) == 0) {
- found = TRUE;
- if (strcmp(what, DM_USE_MOUNT) == 0) {
- vdev_error(gettext("%s is "
- "currently mounted on %s\n"),
- slicename, desc);
- } else if (strcmp(what, DM_USE_VFSTAB) == 0) {
- vdev_error(gettext("%s is usually "
- "mounted at %s in /etc/vfstab\n"),
- slicename, desc);
- } else if (strcmp(what, DM_USE_DUMP) == 0) {
- vdev_error(gettext("%s is the "
- "dedicated dump device\n"), slicename);
- }
- } else if (!force) {
- found = TRUE;
- if (strcmp(what, DM_USE_SVM) == 0) {
- vdev_error(gettext("%s is part of "
- "SVM volume %s\n"), slicename, desc);
- } else if (strcmp(what, DM_USE_LU) == 0) {
- vdev_error(gettext("%s is in use "
- "for live upgrade %s\n"), slicename, desc);
- } else if (strcmp(what, DM_USE_VXVM) == 0) {
- vdev_error(gettext("%s is part of "
- "VxVM volume %s\n"), slicename, desc);
- } else if (strcmp(what, DM_USE_FS) == 0) {
- /*
- * We should have already caught ZFS in-use
- * filesystems above. If the ZFS version is
- * different, or there was some other critical
- * failure, it's possible for fstyp to report it
- * as in-use, but zpool_open_by_dev() to fail.
- */
- if (strcmp(desc, MNTTYPE_ZFS) != 0)
- vdev_error(gettext("%s contains a %s "
- "filesystem\n"), slicename, desc);
- else if (!found_zfs)
- vdev_error(gettext("%s is part of an "
- "outdated or damaged ZFS "
- "pool\n"), slicename);
- } else {
- vdev_error(gettext("is used by %s as %s\n"),
- slicename, what, desc);
- }
+ error = 0;
+ if (!wholedisk && !force &&
+ (dm_isoverlapping((char *)path, &msg, &error) || error)) {
+ if (error != 0) {
+ libdiskmgt_error(error);
+ return (0);
} else {
- found = FALSE;
+ vdev_error("%s overlaps with %s\n", path, msg);
+ free(msg);
}
- }
- /*
- * Perform any overlap checking if requested to do so.
- */
- if (overlap && !force)
- found |= (check_overlapping(slicename, slice) != 0);
+ ret = -1;
+ }
- return (found ? -1 : 0);
+ return (ret);
}
/*
@@ -494,12 +178,19 @@ check_disk(const char *name, dm_descriptor_t disk, int force)
* because we already have an alias handle open for the device.
*/
if ((drive = dm_get_associated_descriptors(disk, DM_DRIVE,
- &err)) == NULL || *drive == NULL)
- libdskmgt_error(err);
+ &err)) == NULL || *drive == NULL) {
+ if (err)
+ libdiskmgt_error(err);
+ return (0);
+ }
if ((media = dm_get_associated_descriptors(*drive, DM_MEDIA,
- &err)) == NULL)
- libdskmgt_error(err);
+ &err)) == NULL) {
+ dm_free_descriptors(drive);
+ if (err)
+ libdiskmgt_error(err);
+ return (0);
+ }
dm_free_descriptors(drive);
@@ -508,14 +199,18 @@ check_disk(const char *name, dm_descriptor_t disk, int force)
* and the media is not present.
*/
if (*media == NULL) {
- vdev_error(gettext("'%s' has no media in drive\n"), name);
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)
- libdskmgt_error(err);
+ &err)) == NULL) {
+ dm_free_descriptors(media);
+ if (err)
+ libdiskmgt_error(err);
+ return (0);
+ }
dm_free_descriptors(media);
@@ -526,8 +221,7 @@ check_disk(const char *name, dm_descriptor_t disk, int force)
* overlapping slices because we are using the whole disk.
*/
for (i = 0; slice[i] != NULL; i++) {
- if (check_slice(dm_get_name(slice[i], &err), slice[i],
- force, FALSE) != 0)
+ if (check_slice(dm_get_name(slice[i], &err), force, TRUE) != 0)
ret = -1;
}
@@ -535,17 +229,15 @@ check_disk(const char *name, dm_descriptor_t disk, int force)
return (ret);
}
-
/*
- * Validate a device. Determines whether the device is a disk, slice, or
- * partition, and passes it off to an appropriate function.
+ * Validate a device.
*/
int
check_device(const char *path, int force)
{
dm_descriptor_t desc;
int err;
- char *dev, rpath[MAXPATHLEN];
+ char *dev;
/*
* For whole disks, libdiskmgt does not include the leading dev path.
@@ -553,47 +245,13 @@ check_device(const char *path, int force)
dev = strrchr(path, '/');
assert(dev != NULL);
dev++;
- if ((desc = dm_get_descriptor_by_name(DM_ALIAS, dev, &err)) != NULL)
- return (check_disk(path, desc, force));
-
- /*
- * If 'err' is not ENODEV, then we've had an unexpected error from
- * libdiskmgt. The only explanation is that we ran out of memory.
- */
- if (err != ENODEV)
- libdskmgt_error(err);
-
- /*
- * Determine if this is a slice.
- */
- if ((desc = dm_get_descriptor_by_name(DM_SLICE, (char *)path, &err))
- != NULL)
- return (check_slice(path, desc, force, TRUE));
-
- if (err != ENODEV)
- libdskmgt_error(err);
-
- /*
- * Check for a partition. libdiskmgt expects path of /dev/rdsk when
- * dealing with partitions, so convert it.
- */
- (void) snprintf(rpath, sizeof (rpath), "/dev/rdsk/%s", dev);
- if ((desc = dm_get_descriptor_by_name(DM_PARTITION, rpath, &err))
- != NULL) {
- /* XXZFS perform checking on partitions */
- return (0);
+ if ((desc = dm_get_descriptor_by_name(DM_ALIAS, dev, &err)) != NULL) {
+ err = check_disk(path, desc, force);
+ dm_free_descriptor(desc);
+ return (err);
}
- if (err != ENODEV)
- libdskmgt_error(err);
-
- /*
- * At this point, libdiskmgt failed to find the device as either a whole
- * disk or a slice. Ignore these errors, as we know that it at least a
- * block device. The user may have provided us with some unknown device
- * that libdiskmgt doesn't know about.
- */
- return (0);
+ return (check_slice(path, force, FALSE));
}
/*
@@ -603,22 +261,41 @@ check_device(const char *path, int force)
int
check_file(const char *file, int force)
{
- char *desc, *name;
+ char *name;
int fd;
int ret = 0;
+ pool_state_t state;
if ((fd = open(file, O_RDONLY)) < 0)
return (0);
- if (zpool_in_use(fd, &desc, &name)) {
- if (strcmp(desc, gettext("active")) == 0 ||
- !force) {
+ if (zpool_in_use(fd, &state, &name)) {
+ const char *desc;
+
+ switch (state) {
+ case POOL_STATE_ACTIVE:
+ desc = gettext("active");
+ break;
+
+ case POOL_STATE_EXPORTED:
+ desc = gettext("exported");
+ break;
+
+ case POOL_STATE_POTENTIALLY_ACTIVE:
+ desc = gettext("potentially active");
+ break;
+
+ default:
+ desc = gettext("unknown");
+ break;
+ }
+
+ if (state == POOL_STATE_ACTIVE || !force) {
vdev_error(gettext("%s is part of %s pool '%s'\n"),
file, desc, name);
ret = -1;
}
- free(desc);
free(name);
}
diff --git a/usr/src/lib/libdiskmgt/common/disks_private.h b/usr/src/lib/libdiskmgt/common/disks_private.h
index 99e8801640..2d738dfcbf 100644
--- a/usr/src/lib/libdiskmgt/common/disks_private.h
+++ b/usr/src/lib/libdiskmgt/common/disks_private.h
@@ -20,7 +20,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -262,7 +262,8 @@ int libdiskmgt_str_eq(char *nm1, char *nm2);
int inuse_mnt(char *slice, nvlist_t *attrs, int *errp);
int inuse_svm(char *slice, nvlist_t *attrs, int *errp);
int inuse_lu(char *slice, nvlist_t *attrs, int *errp);
-int inuse_zpool(char *slice, nvlist_t *attrs, int *errp);
+int inuse_active_zpool(char *slice, nvlist_t *attrs, int *errp);
+int inuse_exported_zpool(char *slice, nvlist_t *attrs, int *errp);
int inuse_dump(char *slice, nvlist_t *attrs, int *errp);
int inuse_vxvm(char *slice, nvlist_t *attrs, int *errp);
int inuse_fs(char *slice, nvlist_t *attrs, int *errp);
diff --git a/usr/src/lib/libdiskmgt/common/entry.c b/usr/src/lib/libdiskmgt/common/entry.c
index bf8f703f42..860801b41d 100644
--- a/usr/src/lib/libdiskmgt/common/entry.c
+++ b/usr/src/lib/libdiskmgt/common/entry.c
@@ -20,7 +20,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -555,6 +555,179 @@ dm_get_slice_stats(char *slice, nvlist_t **dev_stats, int *errp)
}
/*
+ * 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);
+}
+
+/*
* Returns 'in use' details, if found, about a specific dev_name,
* based on the caller(who). It is important to note that it is possible
* for there to be more than one 'in use' statistic regarding a dev_name.
@@ -648,7 +821,8 @@ dm_inuse(char *dev_name, char **msg, dm_who_type_t who, int *errp)
* All others are in use.
*/
if (strcmp(by, DM_USE_LU) == 0 ||
- strcmp(by, DM_USE_FS) == 0) {
+ strcmp(by, DM_USE_FS) == 0 ||
+ strcmp(by, DM_USE_EXPORTED_ZPOOL) == 0) {
break;
}
if (build_usage_string(dname,
@@ -663,7 +837,8 @@ dm_inuse(char *dev_name, char **msg, dm_who_type_t who, int *errp)
* Not in use for this.
*/
if (strcmp(by, DM_USE_DUMP) == 0 ||
- strcmp(by, DM_USE_FS) == 0) {
+ strcmp(by, DM_USE_FS) == 0 ||
+ strcmp(by, DM_USE_EXPORTED_ZPOOL) == 0) {
break;
}
@@ -681,7 +856,8 @@ dm_inuse(char *dev_name, char **msg, dm_who_type_t who, int *errp)
if ((strcmp(by, DM_USE_MOUNT) == 0 &&
strcmp(data, "swap") == 0) ||
strcmp(by, DM_USE_DUMP) == 0 ||
- strcmp(by, DM_USE_FS) == 0) {
+ strcmp(by, DM_USE_FS) == 0 ||
+ strcmp(by, DM_USE_EXPORTED_ZPOOL) == 0) {
break;
}
if (build_usage_string(dname,
@@ -693,7 +869,8 @@ dm_inuse(char *dev_name, char **msg, dm_who_type_t who, int *errp)
break;
case DM_WHO_FORMAT:
- if (strcmp(by, DM_USE_FS) == 0)
+ if (strcmp(by, DM_USE_FS) == 0 ||
+ strcmp(by, DM_USE_EXPORTED_ZPOOL) == 0)
break;
if (build_usage_string(dname,
by, data, msg, &found, errp) != 0) {
@@ -702,6 +879,20 @@ dm_inuse(char *dev_name, char **msg, dm_who_type_t who, int *errp)
}
}
break;
+
+ case DM_WHO_ZPOOL_FORCE:
+ if (strcmp(by, DM_USE_FS) == 0 ||
+ strcmp(by, DM_USE_EXPORTED_ZPOOL) == 0)
+ break;
+ /* FALLTHROUGH */
+ case DM_WHO_ZPOOL:
+ if (build_usage_string(dname,
+ by, data, msg, &found, errp) != 0) {
+ if (*errp)
+ goto out;
+ }
+ break;
+
default:
/*
* nothing found in use for this client
@@ -745,7 +936,7 @@ dm_get_usage_string(char *what, char *how, char **usage_string)
"Please remove this entry to use this device.\n");
} else if (strcmp(what, DM_USE_FS) == 0) {
*usage_string = dgettext(TEXT_DOMAIN,
- "Warning: %s contains a %s filesystem.\n");
+ "%s contains a %s filesystem.\n");
} else if (strcmp(what, DM_USE_SVM) == 0) {
if (strcmp(how, "mdb") == 0) {
*usage_string = dgettext(TEXT_DOMAIN,
@@ -767,9 +958,13 @@ dm_get_usage_string(char *what, char *how, char **usage_string)
*usage_string = dgettext(TEXT_DOMAIN,
"%s is in use by %s. Please see dumpadm(1M)."
"\n");
- } else if (strcmp(what, DM_USE_ZPOOL) == 0) {
+ } else if (strcmp(what, DM_USE_EXPORTED_ZPOOL) == 0) {
+ *usage_string = dgettext(TEXT_DOMAIN,
+ "%s is part of exported or potentially active ZFS pool %s. "
+ "Please see zpool(1M).\n");
+ } else if (strcmp(what, DM_USE_ACTIVE_ZPOOL) == 0) {
*usage_string = dgettext(TEXT_DOMAIN,
- "%s is in use by zpool %s. Please see zpool(1M)."
+ "%s is part of active ZFS pool %s. Please see zpool(1M)."
"\n");
}
}
diff --git a/usr/src/lib/libdiskmgt/common/inuse_zpool.c b/usr/src/lib/libdiskmgt/common/inuse_zpool.c
index 9913b7ef22..9c6d3a0ecc 100644
--- a/usr/src/lib/libdiskmgt/common/inuse_zpool.c
+++ b/usr/src/lib/libdiskmgt/common/inuse_zpool.c
@@ -20,7 +20,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -44,6 +44,7 @@
#include <dlfcn.h>
#include <link.h>
#include <ctype.h>
+#include <sys/fs/zfs.h>
#include "libdiskmgt.h"
#include "disks_private.h"
@@ -51,7 +52,7 @@
/*
* Pointers to libzfs.so functions that we dynamically resolve.
*/
-static int (*zfsdl_zpool_in_use)(int fd, char **desc, char **name);
+static int (*zfsdl_zpool_in_use)(int fd, pool_state_t *state, char **name);
static mutex_t init_lock = DEFAULTMUTEX;
static rwlock_t zpool_lock = DEFAULTRWLOCK;
@@ -59,12 +60,13 @@ static int initialized = 0;
static void *init_zpool();
-int
-inuse_zpool(char *slice, nvlist_t *attrs, int *errp)
+static int
+inuse_zpool_common(char *slice, nvlist_t *attrs, int *errp, char *type)
{
int found = 0;
- char *desc, *name;
+ char *name;
int fd;
+ pool_state_t state;
*errp = 0;
if (slice == NULL) {
@@ -86,12 +88,20 @@ inuse_zpool(char *slice, nvlist_t *attrs, int *errp)
(void) mutex_unlock(&init_lock);
(void) rw_rdlock(&zpool_lock);
if ((fd = open(slice, O_RDONLY)) > 0) {
- if (zfsdl_zpool_in_use(fd, &desc, &name)) {
- libdiskmgt_add_str(attrs, DM_USED_BY,
- DM_USE_ZPOOL, errp);
- libdiskmgt_add_str(attrs, DM_USED_NAME,
- name, errp);
- found = 1;
+ if (zfsdl_zpool_in_use(fd, &state, &name)) {
+ if (strcmp(type, DM_USE_ACTIVE_ZPOOL) == 0) {
+ if (state == POOL_STATE_ACTIVE)
+ found = 1;
+ } else {
+ found = 1;
+ }
+
+ if (found) {
+ libdiskmgt_add_str(attrs, DM_USED_BY,
+ type, errp);
+ libdiskmgt_add_str(attrs, DM_USED_NAME,
+ name, errp);
+ }
}
}
(void) rw_unlock(&zpool_lock);
@@ -99,6 +109,18 @@ inuse_zpool(char *slice, nvlist_t *attrs, int *errp)
return (found);
}
+int
+inuse_active_zpool(char *slice, nvlist_t *attrs, int *errp)
+{
+ return (inuse_zpool_common(slice, attrs, errp, DM_USE_ACTIVE_ZPOOL));
+}
+
+int
+inuse_exported_zpool(char *slice, nvlist_t *attrs, int *errp)
+{
+ return (inuse_zpool_common(slice, attrs, errp, DM_USE_EXPORTED_ZPOOL));
+}
+
/*
* Try to dynamically link the zfs functions we need.
*/
@@ -114,8 +136,8 @@ init_zpool()
* Instantiate the functions needed to get zpool configuration
* data
*/
- if ((zfsdl_zpool_in_use = (int (*)(int, char **, char **))dlsym(lh,
- "zpool_in_use")) == NULL) {
+ if ((zfsdl_zpool_in_use = (int (*)(int, pool_state_t *, char **))
+ dlsym(lh, "zpool_in_use")) == NULL) {
(void) dlclose(lh);
return (NULL);
}
diff --git a/usr/src/lib/libdiskmgt/common/libdiskmgt.h b/usr/src/lib/libdiskmgt/common/libdiskmgt.h
index 93998899c1..aa6df0967e 100644
--- a/usr/src/lib/libdiskmgt/common/libdiskmgt.h
+++ b/usr/src/lib/libdiskmgt/common/libdiskmgt.h
@@ -20,7 +20,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -46,6 +46,7 @@ typedef uint64_t dm_descriptor_t;
typedef enum {
DM_WHO_MKFS = 0,
DM_WHO_ZPOOL,
+ DM_WHO_ZPOOL_FORCE,
DM_WHO_FORMAT,
DM_WHO_SWAP,
DM_WHO_DUMP
@@ -212,7 +213,8 @@ typedef enum {
#define DM_USE_VXVM "vxvm"
#define DM_USE_FS "fs"
#define DM_USE_VFSTAB "vfstab"
-#define DM_USE_ZPOOL "zpool"
+#define DM_USE_EXPORTED_ZPOOL "exported_zpool"
+#define DM_USE_ACTIVE_ZPOOL "active_zpool"
/* event */
#define DM_EV_NAME "name"
@@ -255,6 +257,7 @@ void dm_get_slice_stats(char *slice, nvlist_t **dev_stats,
void dm_get_usage_string(char *who, char *data, char **msg);
int dm_inuse(char *dev_name, char **msg, dm_who_type_t who,
int *errp);
+int dm_isoverlapping(char *dev_name, char **msg, int *errp);
#ifdef __cplusplus
}
diff --git a/usr/src/lib/libdiskmgt/common/slice.c b/usr/src/lib/libdiskmgt/common/slice.c
index 33997e1b0c..e94c443cfb 100644
--- a/usr/src/lib/libdiskmgt/common/slice.c
+++ b/usr/src/lib/libdiskmgt/common/slice.c
@@ -20,7 +20,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -54,18 +54,18 @@
#define FMT_VTOC 1
#define FMT_EFI 2
-static struct inuse_detectors {
- int (*detectorp)(char *slice, nvlist_t *attrs, int *errp);
- char *used_by;
-} detectors[] = {
- {inuse_mnt, DM_USE_MOUNT},
- {inuse_svm, DM_USE_SVM},
- {inuse_zpool, DM_USE_ZPOOL},
- {inuse_lu, DM_USE_LU},
- {inuse_dump, DM_USE_DUMP},
- {inuse_vxvm, DM_USE_VXVM},
- {inuse_fs, DM_USE_FS}, /* fs should always be last */
- {NULL, NULL}
+typedef int (*detectorp)(char *, nvlist_t *, int *);
+
+static detectorp detectors[] = {
+ inuse_mnt,
+ inuse_svm,
+ inuse_active_zpool,
+ inuse_lu,
+ inuse_dump,
+ inuse_vxvm,
+ inuse_exported_zpool,
+ inuse_fs, /* fs should always be last */
+ NULL
};
static int add_inuse(char *name, nvlist_t *attrs);
@@ -358,8 +358,8 @@ add_inuse(char *name, nvlist_t *attrs)
int i;
int error;
- for (i = 0; detectors[i].detectorp != NULL; i ++) {
- if ((detectors[i].detectorp)(name, attrs, &error) || error != 0) {
+ for (i = 0; detectors[i] != NULL; i ++) {
+ if (detectors[i](name, attrs, &error) || error != 0) {
if (error != 0) {
return (error);
}
diff --git a/usr/src/lib/libdiskmgt/spec/diskmgt.spec b/usr/src/lib/libdiskmgt/spec/diskmgt.spec
index e2d364dc7f..cd86d49b36 100644
--- a/usr/src/lib/libdiskmgt/spec/diskmgt.spec
+++ b/usr/src/lib/libdiskmgt/spec/diskmgt.spec
@@ -1,5 +1,5 @@
#
-# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
# CDDL HEADER START
@@ -131,3 +131,7 @@ declaration void dm_inuse(char * dev_name, char **msg, dm_who_type_t who,
version SUNWprivate_1.1
end
+function dm_isoverlapping
+declaration int dm_isoverlapping(char *dev_name, char **msg, int *errp)
+version SUNWprivate_1.1
+end
diff --git a/usr/src/lib/libzfs/common/libzfs.h b/usr/src/lib/libzfs/common/libzfs.h
index 63e394c376..7da0a674e0 100644
--- a/usr/src/lib/libzfs/common/libzfs.h
+++ b/usr/src/lib/libzfs/common/libzfs.h
@@ -261,8 +261,7 @@ extern int zfs_remove_link(zfs_handle_t *);
/*
* Given a device or file, determine if it is part of a pool.
*/
-extern int zpool_in_use(int fd, char **state,
- char **name);
+extern int zpool_in_use(int fd, pool_state_t *state, char **name);
/*
* ftyp special. Read the label from a given device.
diff --git a/usr/src/lib/libzfs/common/libzfs_import.c b/usr/src/lib/libzfs/common/libzfs_import.c
index b7eb81873d..6c56a1a2da 100644
--- a/usr/src/lib/libzfs/common/libzfs_import.c
+++ b/usr/src/lib/libzfs/common/libzfs_import.c
@@ -20,7 +20,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -670,16 +670,16 @@ find_guid(nvlist_t *nv, uint64_t guid)
* must be freed by the caller.
*/
int
-zpool_in_use(int fd, char **statestr, char **namestr)
+zpool_in_use(int fd, pool_state_t *state, char **namestr)
{
nvlist_t *config;
- uint64_t state;
char *name;
int ret;
zfs_cmd_t zc = { 0 };
uint64_t guid, vdev_guid;
zpool_handle_t *zhp;
nvlist_t *pool_config;
+ uint64_t stateval;
if ((config = zpool_read_label(fd)) == NULL)
return (FALSE);
@@ -687,16 +687,14 @@ zpool_in_use(int fd, char **statestr, char **namestr)
verify(nvlist_lookup_string(config, ZPOOL_CONFIG_POOL_NAME,
&name) == 0);
verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE,
- &state) == 0);
+ &stateval) == 0);
verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID,
&guid) == 0);
verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_GUID,
&vdev_guid) == 0);
- switch (state) {
+ switch (stateval) {
case POOL_STATE_EXPORTED:
- *statestr = zfs_strdup(dgettext(TEXT_DOMAIN, "exported"));
- *namestr = zfs_strdup(name);
ret = TRUE;
break;
@@ -726,21 +724,12 @@ zpool_in_use(int fd, char **statestr, char **namestr)
verify(nvlist_lookup_nvlist(pool_config,
ZPOOL_CONFIG_VDEV_TREE, &nvroot) == 0);
- if (find_guid(nvroot, vdev_guid)) {
- *statestr = zfs_strdup(
- dgettext(TEXT_DOMAIN, "active"));
- *namestr = zfs_strdup(name);
- ret = TRUE;
- } else {
- ret = FALSE;
- }
+ ret = find_guid(nvroot, vdev_guid);
} else {
ret = FALSE;
}
} else {
- *statestr = zfs_strdup(dgettext(TEXT_DOMAIN,
- "potentially active"));
- *namestr = zfs_strdup(name);
+ stateval = POOL_STATE_POTENTIALLY_ACTIVE;
ret = TRUE;
}
break;
@@ -749,6 +738,12 @@ zpool_in_use(int fd, char **statestr, char **namestr)
ret = FALSE;
}
+
+ if (ret) {
+ *namestr = zfs_strdup(name);
+ *state = (pool_state_t)stateval;
+ }
+
nvlist_free(config);
return (ret);
}
diff --git a/usr/src/uts/common/sys/fs/zfs.h b/usr/src/uts/common/sys/fs/zfs.h
index 1af3770e4f..cce14d4237 100644
--- a/usr/src/uts/common/sys/fs/zfs.h
+++ b/usr/src/uts/common/sys/fs/zfs.h
@@ -20,7 +20,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -182,17 +182,17 @@ typedef enum vdev_aux {
} vdev_aux_t;
/*
- * pool state. The following states are actually written to disk as part of the
- * normal SPA lifecycle: ACTIVE, EXPORTED, DESTROYED. The remaining states
- * (UNITIALIZED, UNAVAIL) are software abstractions used at various levels to
- * communicate pool state.
+ * pool state. The following states are written to disk as part of the normal
+ * SPA lifecycle: ACTIVE, EXPORTED, DESTROYED. The remaining states are
+ * software abstractions used at various levels to communicate pool state.
*/
typedef enum pool_state {
POOL_STATE_ACTIVE = 0, /* In active use */
POOL_STATE_EXPORTED, /* Explicitly exported */
POOL_STATE_DESTROYED, /* Explicitly destroyed */
POOL_STATE_UNINITIALIZED, /* Internal spa_t state */
- POOL_STATE_UNAVAIL /* Internal libzfs state */
+ POOL_STATE_UNAVAIL, /* Internal libzfs state */
+ POOL_STATE_POTENTIALLY_ACTIVE /* Internal libzfs state */
} pool_state_t;
/*