aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorTony Hutter <[email protected]>2023-12-21 10:53:16 -0800
committerTony Hutter <[email protected]>2024-01-29 15:12:06 -0800
commit69142125d75b7405e0f1cf141dbe7913448daedf (patch)
tree26de02691ede11de6ea1fe6e772920a309d450dc /include
parent59112ca27d94edd793dbfda6ed5d2fc7a97dddaa (diff)
zpool: Add slot power control, print power status
Add `zpool` flags to control the slot power to drives. This assumes your SAS or NVMe enclosure supports slot power control via sysfs. The new `--power` flag is added to `zpool offline|online|clear`: zpool offline --power <pool> <device> Turn off device slot power zpool online --power <pool> <device> Turn on device slot power zpool clear --power <pool> [device] Turn on device slot power If the ZPOOL_AUTO_POWER_ON_SLOT env var is set, then the '--power' option is automatically implied for `zpool online` and `zpool clear` and does not need to be passed. zpool status also gets a --power option to print the slot power status. Reviewed-by: Brian Behlendorf <[email protected]> Reviewed-by: Mart Frauenlob <[email protected]> Signed-off-by: Tony Hutter <[email protected]> Closes #15662
Diffstat (limited to 'include')
-rw-r--r--include/libzfs.h3
-rw-r--r--include/libzutil.h57
2 files changed, 60 insertions, 0 deletions
diff --git a/include/libzfs.h b/include/libzfs.h
index 4adfa38e8..770c5e1f2 100644
--- a/include/libzfs.h
+++ b/include/libzfs.h
@@ -318,6 +318,9 @@ _LIBZFS_H int zpool_vdev_remove_wanted(zpool_handle_t *, const char *);
_LIBZFS_H int zpool_vdev_fault(zpool_handle_t *, uint64_t, vdev_aux_t);
_LIBZFS_H int zpool_vdev_degrade(zpool_handle_t *, uint64_t, vdev_aux_t);
+_LIBZFS_H int zpool_vdev_set_removed_state(zpool_handle_t *, uint64_t,
+ vdev_aux_t);
+
_LIBZFS_H int zpool_vdev_clear(zpool_handle_t *, uint64_t);
_LIBZFS_H nvlist_t *zpool_find_vdev(zpool_handle_t *, const char *, boolean_t *,
diff --git a/include/libzutil.h b/include/libzutil.h
index 9842c225b..839486fb6 100644
--- a/include/libzutil.h
+++ b/include/libzutil.h
@@ -97,6 +97,7 @@ _LIBZUTIL_H int zpool_find_config(libpc_handle_t *, const char *, nvlist_t **,
_LIBZUTIL_H const char * const * zpool_default_search_paths(size_t *count);
_LIBZUTIL_H int zpool_read_label(int, nvlist_t **, int *);
_LIBZUTIL_H int zpool_label_disk_wait(const char *, int);
+_LIBZUTIL_H int zpool_disk_wait(const char *);
struct udev_device;
@@ -163,6 +164,8 @@ _LIBZUTIL_H void zfs_niceraw(uint64_t, char *, size_t);
_LIBZUTIL_H void zpool_dump_ddt(const ddt_stat_t *, const ddt_histogram_t *);
_LIBZUTIL_H int zpool_history_unpack(char *, uint64_t, uint64_t *, nvlist_t ***,
uint_t *);
+_LIBZUTIL_H void fsleep(float sec);
+_LIBZUTIL_H int zpool_getenv_int(const char *env, int default_val);
struct zfs_cmd;
@@ -205,6 +208,60 @@ _LIBZUTIL_H void zfs_setproctitle(const char *fmt, ...);
typedef int (*pool_vdev_iter_f)(void *, nvlist_t *, void *);
int for_each_vdev_cb(void *zhp, nvlist_t *nv, pool_vdev_iter_f func,
void *data);
+int for_each_vdev_macro_helper_func(void *zhp_data, nvlist_t *nv, void *data);
+int for_each_real_leaf_vdev_macro_helper_func(void *zhp_data, nvlist_t *nv,
+ void *data);
+/*
+ * Often you'll want to iterate over all the vdevs in the pool, but don't want
+ * to use for_each_vdev() since it requires a callback function.
+ *
+ * Instead you can use FOR_EACH_VDEV():
+ *
+ * zpool_handle_t *zhp // Assume this is initialized
+ * nvlist_t *nv
+ * ...
+ * FOR_EACH_VDEV(zhp, nv) {
+ * const char *path = NULL;
+ * nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path);
+ * printf("Looking at vdev %s\n", path);
+ * }
+ *
+ * Note: FOR_EACH_VDEV runs in O(n^2) time where n = number of vdevs. However,
+ * there's an upper limit of 256 vdevs per dRAID top-level vdevs (TLDs), 255 for
+ * raidz2 TLDs, a real world limit of ~500 vdevs for mirrors, so this shouldn't
+ * really be an issue.
+ *
+ * Here are some micro-benchmarks of a complete FOR_EACH_VDEV loop on a RAID0
+ * pool:
+ *
+ * 100 vdevs = 0.7ms
+ * 500 vdevs = 17ms
+ * 750 vdevs = 40ms
+ * 1000 vdevs = 82ms
+ *
+ * The '__nv += 0' at the end of the for() loop gets around a "comma or
+ * semicolon followed by non-blank" checkstyle error. Note on most compliers
+ * the '__nv += 0' can just be replaced with 'NULL', but gcc on Centos 7
+ * will give a 'warning: statement with no effect' error if you do that.
+ */
+#define __FOR_EACH_VDEV(__zhp, __nv, __func) { \
+ __nv = zpool_get_config(__zhp, NULL); \
+ VERIFY0(nvlist_lookup_nvlist(__nv, ZPOOL_CONFIG_VDEV_TREE, &__nv)); \
+ } \
+ for (nvlist_t *__root_nv = __nv, *__state = (nvlist_t *)0; \
+ for_each_vdev_cb(&__state, __root_nv, __func, &__nv) == 1; \
+ __nv += 0)
+
+#define FOR_EACH_VDEV(__zhp, __nv) \
+ __FOR_EACH_VDEV(__zhp, __nv, for_each_vdev_macro_helper_func)
+
+/*
+ * "real leaf" vdevs are leaf vdevs that are real devices (disks or files).
+ * This excludes leaf vdevs like like draid spares.
+ */
+#define FOR_EACH_REAL_LEAF_VDEV(__zhp, __nv) \
+ __FOR_EACH_VDEV(__zhp, __nv, for_each_real_leaf_vdev_macro_helper_func)
+
int for_each_vdev_in_nvlist(nvlist_t *nvroot, pool_vdev_iter_f func,
void *data);
void update_vdevs_config_dev_sysfs_path(nvlist_t *config);