diff options
Diffstat (limited to 'usr/src/lib/libdiskmgt/common')
| -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 |
5 files changed, 261 insertions, 40 deletions
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); } |
