diff options
Diffstat (limited to 'sys/contrib/openzfs/lib/libzfs/libzfs_pool.c')
-rw-r--r-- | sys/contrib/openzfs/lib/libzfs/libzfs_pool.c | 47 |
1 files changed, 45 insertions, 2 deletions
diff --git a/sys/contrib/openzfs/lib/libzfs/libzfs_pool.c b/sys/contrib/openzfs/lib/libzfs/libzfs_pool.c index 4ebd112f452f..71cf029deff5 100644 --- a/sys/contrib/openzfs/lib/libzfs/libzfs_pool.c +++ b/sys/contrib/openzfs/lib/libzfs/libzfs_pool.c @@ -3378,6 +3378,7 @@ zpool_vdev_attach(zpool_handle_t *zhp, const char *old_disk, boolean_t avail_spare, l2cache, islog; uint64_t val; char *newname; + const char *type; nvlist_t **child; uint_t children; nvlist_t *config_root; @@ -3412,6 +3413,14 @@ zpool_vdev_attach(zpool_handle_t *zhp, const char *old_disk, return (zfs_error(hdl, EZFS_POOL_NOTSUP, errbuf)); } + type = fnvlist_lookup_string(tgt, ZPOOL_CONFIG_TYPE); + if (strcmp(type, VDEV_TYPE_RAIDZ) == 0 && + zfeature_lookup_guid("org.openzfs:raidz_expansion", NULL) != 0) { + zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, + "the loaded zfs module doesn't support raidz expansion")); + return (zfs_error(hdl, EZFS_POOL_NOTSUP, errbuf)); + } + if (nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN, &child, &children) != 0 || children != 1) { zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, @@ -3479,6 +3488,10 @@ zpool_vdev_attach(zpool_handle_t *zhp, const char *old_disk, zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "cannot replace a replacing device")); } + } else if (strcmp(type, VDEV_TYPE_RAIDZ) == 0) { + zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, + "raidz_expansion feature must be enabled " + "in order to attach a device to raidz")); } else { char status[64] = {0}; zpool_prop_get_feature(zhp, @@ -3508,8 +3521,7 @@ zpool_vdev_attach(zpool_handle_t *zhp, const char *old_disk, break; case EBUSY: - zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "%s is busy, " - "or device removal is in progress"), + zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "%s is busy"), new_disk); (void) zfs_error(hdl, EZFS_BADDEV, errbuf); break; @@ -3540,6 +3552,34 @@ zpool_vdev_attach(zpool_handle_t *zhp, const char *old_disk, (void) zfs_error(hdl, EZFS_DEVOVERFLOW, errbuf); break; + case ENXIO: + /* + * The existing raidz vdev has offline children + */ + if (strcmp(type, VDEV_TYPE_RAIDZ) == 0) { + zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, + "raidz vdev has devices that are are offline or " + "being replaced")); + (void) zfs_error(hdl, EZFS_BADDEV, errbuf); + break; + } else { + (void) zpool_standard_error(hdl, errno, errbuf); + } + break; + + case EADDRINUSE: + /* + * The boot reserved area is already being used (FreeBSD) + */ + if (strcmp(type, VDEV_TYPE_RAIDZ) == 0) { + zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, + "the reserved boot area needed for the expansion " + "is already being used by a boot loader")); + (void) zfs_error(hdl, EZFS_BADDEV, errbuf); + } else { + (void) zpool_standard_error(hdl, errno, errbuf); + } + break; default: (void) zpool_standard_error(hdl, errno, errbuf); } @@ -5222,6 +5262,9 @@ zpool_get_vdev_prop_value(nvlist_t *nvprop, vdev_prop_t prop, char *prop_name, } else { src = ZPROP_SRC_DEFAULT; intval = vdev_prop_default_numeric(prop); + /* Only use if provided by the RAIDZ VDEV above */ + if (prop == VDEV_PROP_RAIDZ_EXPANDING) + return (ENOENT); } if (vdev_prop_index_to_string(prop, intval, (const char **)&strval) != 0) |