diff options
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/cmd/zpool/zpool_vdev.c | 485 | ||||
-rw-r--r-- | usr/src/lib/libdiskmgt/common/disks_private.h | 5 | ||||
-rw-r--r-- | usr/src/lib/libdiskmgt/common/entry.c | 211 | ||||
-rw-r--r-- | usr/src/lib/libdiskmgt/common/inuse_zpool.c | 48 | ||||
-rw-r--r-- | usr/src/lib/libdiskmgt/common/libdiskmgt.h | 7 | ||||
-rw-r--r-- | usr/src/lib/libdiskmgt/common/slice.c | 30 | ||||
-rw-r--r-- | usr/src/lib/libdiskmgt/spec/diskmgt.spec | 6 | ||||
-rw-r--r-- | usr/src/lib/libzfs/common/libzfs.h | 3 | ||||
-rw-r--r-- | usr/src/lib/libzfs/common/libzfs_import.c | 31 | ||||
-rw-r--r-- | usr/src/uts/common/sys/fs/zfs.h | 12 |
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; /* |