mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-23 19:04:45 +03:00
zpool iostat: refresh pool list every interval
When running zpool iostat in interval mode, it would not notice any new
pools created or imported, and would forget any destroyed or exported,
so would not notice if they came back. This leads to outputting "no
pools available" every interval until killed.
It looks like this was at least intended to work; the comment above
zpool_do_iostat() indicates that it is expected to "deal with pool
creation/destruction" and that pool_list_update() would detect new
pools. That call however was removed in 3e43edd2c5, though its unclear
if that broke this behaviour and it wasn't noticed, or if it never
worked, or if something later broke it. That said, the lack of
pool_list_update() is only part of the reason it doesn't work properly.
The fundamental problem is that the various things involved in
refreshing or updating the list of pools would aggressively ignore,
remove, skip or fail on pools that stop existing, or that already exist.
Mostly this meant that once a pool is removed from the list, it will
never be seen again. Restoring pool_list_update() to the
zpool_do_iostat() loop only partially fixes this - it would find "new"
pools again, but only in the "all pools" (no args) mode, and because its
iterator callback add_pool() would abort the iterator if it already has
a pool listed, it would only add pools if there weren't any already.
So, this commit reworks the structure somewhat. pool_list_update()
becomes pool_list_refresh(), and will ensure the state of all pools in
the list are updated. In the "all pools" mode, it will also add new
pools and remove pools that disappear, but when a fixed list of pools is
used, the list doesn't change, only the state of the pools within it.
The rest of the commit is adjusting things for this much simpler
structure. Regardless of the mode in use, pool_list_refresh() will
always do the right thing, so the driver code can just get on with the
display.
Now that pools can appear and disappear, I've made it so the header (if
enabled) is re-printed when the list changes, so that its easier to see
what's happening if the column widths change.
Since this is all rather complicated, I've included tests for the "all
pools" and "set of pools" modes.
Sponsored-by: Klara, Inc.
Sponsored-by: Wasabi Technology, Inc.
Reviewed-by: Tony Hutter <hutter2@llnl.gov>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: Igor Kozhukhov <igor@dilos.org>
Signed-off-by: Rob Norris <rob.norris@klarasystems.com>
Closes #17786
This commit is contained in:
+21
-33
@@ -33,7 +33,7 @@
|
||||
* Copyright (c) 2017, Intel Corporation.
|
||||
* Copyright (c) 2019, loli10K <ezomori.nozomu@gmail.com>
|
||||
* Copyright (c) 2021, Colm Buckley <colm@tuatha.org>
|
||||
* Copyright (c) 2021, 2023, Klara Inc.
|
||||
* Copyright (c) 2021, 2023, 2025, Klara, Inc.
|
||||
* Copyright (c) 2021, 2025 Hewlett Packard Enterprise Development LP.
|
||||
*/
|
||||
|
||||
@@ -5761,24 +5761,6 @@ children:
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int
|
||||
refresh_iostat(zpool_handle_t *zhp, void *data)
|
||||
{
|
||||
iostat_cbdata_t *cb = data;
|
||||
boolean_t missing;
|
||||
|
||||
/*
|
||||
* If the pool has disappeared, remove it from the list and continue.
|
||||
*/
|
||||
if (zpool_refresh_stats(zhp, &missing) != 0)
|
||||
return (-1);
|
||||
|
||||
if (missing)
|
||||
pool_list_remove(cb->cb_list, zhp);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Callback to print out the iostats for the given pool.
|
||||
*/
|
||||
@@ -6359,15 +6341,14 @@ get_namewidth_iostat(zpool_handle_t *zhp, void *data)
|
||||
* This command can be tricky because we want to be able to deal with pool
|
||||
* creation/destruction as well as vdev configuration changes. The bulk of this
|
||||
* processing is handled by the pool_list_* routines in zpool_iter.c. We rely
|
||||
* on pool_list_update() to detect the addition of new pools. Configuration
|
||||
* changes are all handled within libzfs.
|
||||
* on pool_list_refresh() to detect the addition and removal of pools.
|
||||
* Configuration changes are all handled within libzfs.
|
||||
*/
|
||||
int
|
||||
zpool_do_iostat(int argc, char **argv)
|
||||
{
|
||||
int c;
|
||||
int ret;
|
||||
int npools;
|
||||
float interval = 0;
|
||||
unsigned long count = 0;
|
||||
zpool_list_t *list;
|
||||
@@ -6618,10 +6599,24 @@ zpool_do_iostat(int argc, char **argv)
|
||||
return (1);
|
||||
}
|
||||
|
||||
int last_npools = 0;
|
||||
for (;;) {
|
||||
if ((npools = pool_list_count(list)) == 0)
|
||||
/*
|
||||
* Refresh all pools in list, adding or removing pools as
|
||||
* necessary.
|
||||
*/
|
||||
int npools = pool_list_refresh(list);
|
||||
if (npools == 0) {
|
||||
(void) fprintf(stderr, gettext("no pools available\n"));
|
||||
else {
|
||||
} else {
|
||||
/*
|
||||
* If the list of pools has changed since last time
|
||||
* around, reset the iteration count to force the
|
||||
* header to be redisplayed.
|
||||
*/
|
||||
if (last_npools != npools)
|
||||
cb.cb_iteration = 0;
|
||||
|
||||
/*
|
||||
* If this is the first iteration and -y was supplied
|
||||
* we skip any printing.
|
||||
@@ -6629,15 +6624,6 @@ zpool_do_iostat(int argc, char **argv)
|
||||
boolean_t skip = (omit_since_boot &&
|
||||
cb.cb_iteration == 0);
|
||||
|
||||
/*
|
||||
* Refresh all statistics. This is done as an
|
||||
* explicit step before calculating the maximum name
|
||||
* width, so that any * configuration changes are
|
||||
* properly accounted for.
|
||||
*/
|
||||
(void) pool_list_iter(list, B_FALSE, refresh_iostat,
|
||||
&cb);
|
||||
|
||||
/*
|
||||
* Iterate over all pools to determine the maximum width
|
||||
* for the pool / device name column across all pools.
|
||||
@@ -6728,6 +6714,8 @@ zpool_do_iostat(int argc, char **argv)
|
||||
|
||||
(void) fflush(stdout);
|
||||
(void) fsleep(interval);
|
||||
|
||||
last_npools = npools;
|
||||
}
|
||||
|
||||
pool_list_free(list);
|
||||
|
||||
Reference in New Issue
Block a user