aboutsummaryrefslogtreecommitdiff
path: root/sys/contrib/openzfs/lib/libzfs/libzfs_pool.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/contrib/openzfs/lib/libzfs/libzfs_pool.c')
-rw-r--r--sys/contrib/openzfs/lib/libzfs/libzfs_pool.c47
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)