summaryrefslogtreecommitdiff
path: root/usr/src/lib/libzfs/common/libzfs_pool.c
diff options
context:
space:
mode:
authorLin Ling <Lin.Ling@Sun.COM>2009-06-04 17:15:02 -0700
committerLin Ling <Lin.Ling@Sun.COM>2009-06-04 17:15:02 -0700
commit21ecdf64e1e200cd74cadf771fc7ddc3d0062080 (patch)
treeaab7042a0ca5ddba6c62fe4d425612f6713edcf0 /usr/src/lib/libzfs/common/libzfs_pool.c
parentf0d4deecc693927742796b7b0bb1a751ff9b0b54 (diff)
downloadillumos-joyent-21ecdf64e1e200cd74cadf771fc7ddc3d0062080.tar.gz
6747441 GRUB/vdev_get_bootpath, spa_get_rootconf, zpool_get_physpath should take care of spare vdev
6844158 assertion failed: vd->vdev_ops == &vdev_mirror_ops, file: ../../common/fs/zfs/zvol.c, line: 1054 6846024 allow grub to findroot /boot/grub/menu.lst if opening menu.lst from the boot device fails
Diffstat (limited to 'usr/src/lib/libzfs/common/libzfs_pool.c')
-rw-r--r--usr/src/lib/libzfs/common/libzfs_pool.c101
1 files changed, 63 insertions, 38 deletions
diff --git a/usr/src/lib/libzfs/common/libzfs_pool.c b/usr/src/lib/libzfs/common/libzfs_pool.c
index 1accfecdbe..6377d8a81f 100644
--- a/usr/src/lib/libzfs/common/libzfs_pool.c
+++ b/usr/src/lib/libzfs/common/libzfs_pool.c
@@ -1504,10 +1504,10 @@ vdev_online(nvlist_t *nv)
}
/*
- * Helper function for zpool_get_config_physpath().
+ * Helper function for zpool_get_physpaths().
*/
static int
-vdev_get_physpath(nvlist_t *config, char *physpath, size_t physpath_size,
+vdev_get_one_physpath(nvlist_t *config, char *physpath, size_t physpath_size,
size_t *bytes_written)
{
size_t bytes_left, pos, rsz;
@@ -1535,6 +1535,57 @@ vdev_get_physpath(nvlist_t *config, char *physpath, size_t physpath_size,
return (0);
}
+static int
+vdev_get_physpaths(nvlist_t *nv, char *physpath, size_t phypath_size,
+ size_t *rsz, boolean_t is_spare)
+{
+ char *type;
+ int ret;
+
+ if (nvlist_lookup_string(nv, ZPOOL_CONFIG_TYPE, &type) != 0)
+ return (EZFS_INVALCONFIG);
+
+ if (strcmp(type, VDEV_TYPE_DISK) == 0) {
+ /*
+ * An active spare device has ZPOOL_CONFIG_IS_SPARE set.
+ * For a spare vdev, we only want to boot from the active
+ * spare device.
+ */
+ if (is_spare) {
+ uint64_t spare = 0;
+ (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_IS_SPARE,
+ &spare);
+ if (!spare)
+ return (EZFS_INVALCONFIG);
+ }
+
+ if (vdev_online(nv)) {
+ if ((ret = vdev_get_one_physpath(nv, physpath,
+ phypath_size, rsz)) != 0)
+ return (ret);
+ }
+ } else if (strcmp(type, VDEV_TYPE_MIRROR) == 0 ||
+ strcmp(type, VDEV_TYPE_REPLACING) == 0 ||
+ (is_spare = (strcmp(type, VDEV_TYPE_SPARE) == 0))) {
+ nvlist_t **child;
+ uint_t count;
+ int i, ret;
+
+ if (nvlist_lookup_nvlist_array(nv,
+ ZPOOL_CONFIG_CHILDREN, &child, &count) != 0)
+ return (EZFS_INVALCONFIG);
+
+ for (i = 0; i < count; i++) {
+ ret = vdev_get_physpaths(child[i], physpath,
+ phypath_size, rsz, is_spare);
+ if (ret == EZFS_NOSPC)
+ return (ret);
+ }
+ }
+
+ return (EZFS_POOL_INVALARG);
+}
+
/*
* Get phys_path for a root pool config.
* Return 0 on success; non-zero on failure.
@@ -1545,10 +1596,8 @@ zpool_get_config_physpath(nvlist_t *config, char *physpath, size_t phypath_size)
size_t rsz;
nvlist_t *vdev_root;
nvlist_t **child;
- nvlist_t **child2;
uint_t count;
char *type;
- int j, ret;
rsz = 0;
@@ -1569,40 +1618,8 @@ zpool_get_config_physpath(nvlist_t *config, char *physpath, size_t phypath_size)
pool_uses_efi(vdev_root))
return (EZFS_POOL_INVALARG);
- if (nvlist_lookup_string(child[0], ZPOOL_CONFIG_TYPE, &type) != 0)
- return (EZFS_INVALCONFIG);
-
- if (strcmp(type, VDEV_TYPE_DISK) == 0) {
- if (vdev_online(child[0])) {
- if ((ret = vdev_get_physpath(child[0], physpath,
- phypath_size, &rsz)) != 0)
- return (ret);
- }
- } else if (strcmp(type, VDEV_TYPE_MIRROR) == 0) {
-
- if (nvlist_lookup_nvlist_array(child[0],
- ZPOOL_CONFIG_CHILDREN, &child2, &count) != 0)
- return (EZFS_INVALCONFIG);
-
- for (j = 0; j < count; j++) {
- if (nvlist_lookup_string(child2[j], ZPOOL_CONFIG_TYPE,
- &type) != 0)
- return (EZFS_INVALCONFIG);
-
- if (strcmp(type, VDEV_TYPE_DISK) != 0)
- return (EZFS_POOL_INVALARG);
-
- if (vdev_online(child2[j])) {
- ret = vdev_get_physpath(child2[j],
- physpath, phypath_size, &rsz);
-
- if (ret == EZFS_NOSPC)
- return (ret);
- }
- }
- } else {
- return (EZFS_POOL_INVALARG);
- }
+ (void) vdev_get_physpaths(child[0], physpath, phypath_size, &rsz,
+ B_FALSE);
/* No online devices */
if (rsz == 0)
@@ -1938,6 +1955,14 @@ zpool_vdev_attach(zpool_handle_t *zhp,
(void) fprintf(stderr, dgettext(TEXT_DOMAIN, "Please "
"be sure to invoke %s to make '%s' bootable.\n"),
BOOTCMD, new_disk);
+
+ /*
+ * XXX need a better way to prevent user from
+ * booting up a half-baked vdev.
+ */
+ (void) fprintf(stderr, dgettext(TEXT_DOMAIN, "Make "
+ "sure to wait until resilver is done "
+ "before rebooting.\n"));
}
return (0);
}