summaryrefslogtreecommitdiff
path: root/usr/src/lib/libdiskmgt/common
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libdiskmgt/common')
-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
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);
}