From 7e8fb0fa14f4da340c4e49fc2500a12a4adc40e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 19 Nov 2025 19:05:40 +0800 Subject: [PATCH] Zpool: simplifies impl; exposes allocated/guid/readOnly --- CMakeLists.txt | 2 +- src/detection/zpool/libzfs_simplified.h | 7 +-- src/detection/zpool/zpool.h | 4 +- src/detection/zpool/zpool_linux.c | 65 +++++++------------------ src/modules/zpool/zpool.c | 50 ++++++++++++++----- 5 files changed, 64 insertions(+), 64 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 49f2d6553..e1fe347ef 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -92,7 +92,7 @@ cmake_dependent_option(ENABLE_DDCUTIL "Enable ddcutil" ON "LINUX" OFF) cmake_dependent_option(ENABLE_DIRECTX_HEADERS "Enable DirectX headers for WSL" ON "LINUX" OFF) cmake_dependent_option(ENABLE_ELF "Enable libelf" ON "LINUX OR ANDROID OR DragonFly OR Haiku OR GNU" OFF) cmake_dependent_option(ENABLE_THREADS "Enable multithreading" ON "Threads_FOUND" OFF) -cmake_dependent_option(ENABLE_LIBZFS "Enable libzfs" ON "LINUX OR FreeBSD OR SunOS" OFF) +cmake_dependent_option(ENABLE_LIBZFS "Enable libzfs" ON "LINUX OR FreeBSD OR SunOS OR NetBSD" OFF) cmake_dependent_option(ENABLE_PCIACCESS "Enable libpciaccess" ON "GNU" OFF) option(ENABLE_ZLIB "Enable zlib" ON) diff --git a/src/detection/zpool/libzfs_simplified.h b/src/detection/zpool/libzfs_simplified.h index 3b97c222d..d1984e220 100644 --- a/src/detection/zpool/libzfs_simplified.h +++ b/src/detection/zpool/libzfs_simplified.h @@ -84,6 +84,7 @@ extern int zpool_iter(libzfs_handle_t *, zpool_iter_f, void *); extern libzfs_handle_t *libzfs_init(void); extern void libzfs_fini(libzfs_handle_t *); -extern uint64_t zpool_get_prop_int(zpool_handle_t *, zpool_prop_t, zprop_source_t *); -extern const char *zpool_get_name(zpool_handle_t *); -extern const char *zpool_get_state_str(zpool_handle_t *); +// https://github.com/openzfs/zfs/blob/06c73cffabc30b61a695988ec8e290f43cb3768d/lib/libzfs/libzfs_pool.c#L300 +extern uint64_t zpool_get_prop_int(zpool_handle_t *zhp, zpool_prop_t prop, zprop_source_t *srctype); +extern int zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *buf, size_t len, zprop_source_t *srctype, boolean_t literal); +extern void zpool_close(zpool_handle_t *); diff --git a/src/detection/zpool/zpool.h b/src/detection/zpool/zpool.h index e8a5191ae..bc2d4061a 100644 --- a/src/detection/zpool/zpool.h +++ b/src/detection/zpool/zpool.h @@ -7,10 +7,12 @@ typedef struct FFZpoolResult { FFstrbuf name; FFstrbuf state; + uint64_t guid; uint64_t used; uint64_t total; - uint64_t version; + uint64_t allocated; double fragmentation; + bool readOnly; } FFZpoolResult; const char* ffDetectZpool(FFlist* result /* list of FFZpoolResult */); diff --git a/src/detection/zpool/zpool_linux.c b/src/detection/zpool/zpool_linux.c index 72ec65b55..f902f7484 100644 --- a/src/detection/zpool/zpool_linux.c +++ b/src/detection/zpool/zpool_linux.c @@ -1,41 +1,10 @@ #include "zpool.h" -#ifdef FF_HAVE_LIBZFS #include "util/kmod.h" #ifdef __sun #define FF_DISABLE_DLOPEN #include - -const char* zpool_get_state_str(zpool_handle_t* zpool) -{ - if (zpool_get_state(zpool) == POOL_STATE_UNAVAIL) - return "FAULTED"; - else - { - const char *str; - zpool_errata_t errata; - zpool_status_t status = zpool_get_status(zpool, (char**) &str, &errata); - if (status == ZPOOL_STATUS_IO_FAILURE_WAIT || - status == ZPOOL_STATUS_IO_FAILURE_CONTINUE || - status == ZPOOL_STATUS_IO_FAILURE_MMP) - return "SUSPENDED"; - else - { - nvlist_t *nvroot = fnvlist_lookup_nvlist(zpool_get_config(zpool, NULL), ZPOOL_CONFIG_VDEV_TREE); - uint_t vsc; - vdev_stat_t *vs; - #ifdef __x86_64__ - if (nvlist_lookup_uint64_array(nvroot, ZPOOL_CONFIG_VDEV_STATS, (uint64_t**) &vs, &vsc) != 0) - #else - if (nvlist_lookup_uint32_array(nvroot, ZPOOL_CONFIG_VDEV_STATS, (uint32_t**) &vs, &vsc) != 0) - #endif - return "UNKNOWN"; - else - return zpool_state_to_name(vs->vs_state, vs->vs_aux); - } - } -} #else #include "libzfs_simplified.h" #endif @@ -45,10 +14,9 @@ const char* zpool_get_state_str(zpool_handle_t* zpool) typedef struct FFZfsData { FF_LIBRARY_SYMBOL(libzfs_fini) - FF_LIBRARY_SYMBOL(zpool_iter) FF_LIBRARY_SYMBOL(zpool_get_prop_int) - FF_LIBRARY_SYMBOL(zpool_get_name) - FF_LIBRARY_SYMBOL(zpool_get_state_str) + FF_LIBRARY_SYMBOL(zpool_get_prop) + FF_LIBRARY_SYMBOL(zpool_close) libzfs_handle_t* handle; FFlist* result; @@ -68,13 +36,23 @@ static int enumZpoolCallback(zpool_handle_t* zpool, void* param) FFZfsData* data = (FFZfsData*) param; zprop_source_t source; FFZpoolResult* item = ffListAdd(data->result); - ffStrbufInitS(&item->name, data->ffzpool_get_name(zpool)); - ffStrbufInitS(&item->state, data->ffzpool_get_state_str(zpool)); - item->version = data->ffzpool_get_prop_int(zpool, ZPOOL_PROP_VERSION, &source); + char buf[1024]; + if (data->ffzpool_get_prop(zpool, ZPOOL_PROP_NAME, buf, ARRAY_SIZE(buf), &source, false) == 0) + ffStrbufInitS(&item->name, buf); + else + ffStrbufInitStatic(&item->name, "unknown"); + if (data->ffzpool_get_prop(zpool, ZPOOL_PROP_HEALTH, buf, ARRAY_SIZE(buf), &source, false) == 0) + ffStrbufInitS(&item->state, buf); + else + ffStrbufInitStatic(&item->state, "unknown"); + item->guid = data->ffzpool_get_prop_int(zpool, ZPOOL_PROP_GUID, &source); item->total = data->ffzpool_get_prop_int(zpool, ZPOOL_PROP_SIZE, &source); item->used = item->total - data->ffzpool_get_prop_int(zpool, ZPOOL_PROP_FREE, &source); + item->allocated = data->ffzpool_get_prop_int(zpool, ZPOOL_PROP_ALLOCATED, &source); uint64_t fragmentation = data->ffzpool_get_prop_int(zpool, ZPOOL_PROP_FRAGMENTATION, &source); item->fragmentation = fragmentation == UINT64_MAX ? -DBL_MAX : (double) fragmentation; + item->readOnly = (bool) data->ffzpool_get_prop_int(zpool, ZPOOL_PROP_READONLY, &source); + data->ffzpool_close(zpool); return 0; } @@ -98,20 +76,11 @@ const char* ffDetectZpool(FFlist* result /* list of FFZpoolResult */) FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libzfs, zpool_iter); FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libzfs, data, libzfs_fini); FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libzfs, data, zpool_get_prop_int); - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libzfs, data, zpool_get_name); - FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libzfs, data, zpool_get_state_str); + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libzfs, data, zpool_get_prop); + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libzfs, data, zpool_close); if (ffzpool_iter(handle, enumZpoolCallback, &data) < 0) return "zpool_iter() failed"; return NULL; } - -#else - -const char* ffDetectZpool(FF_MAYBE_UNUSED FFlist* result) -{ - return "Fastfetch was compiled without libzfs support"; -} - -#endif diff --git a/src/modules/zpool/zpool.c b/src/modules/zpool/zpool.c index 4193a25b9..b518eae85 100644 --- a/src/modules/zpool/zpool.c +++ b/src/modules/zpool/zpool.c @@ -4,6 +4,7 @@ #include "common/size.h" #include "detection/zpool/zpool.h" #include "modules/zpool/zpool.h" +#include "util/FFstrbuf.h" #include "util/stringUtils.h" static void printZpool(FFZpoolOptions* options, FFZpoolResult* result, uint8_t index) @@ -22,6 +23,7 @@ static void printZpool(FFZpoolOptions* options, FFZpoolResult* result, uint8_t i FF_PARSE_FORMAT_STRING_CHECKED(&buffer, &options->moduleArgs.key, ((FFformatarg[]) { FF_FORMAT_ARG(index, "index"), FF_FORMAT_ARG(result->name, "name"), + FF_FORMAT_ARG(result->guid, "guid"), FF_FORMAT_ARG(options->moduleArgs.keyIcon, "icon"), })); } @@ -29,10 +31,14 @@ static void printZpool(FFZpoolOptions* options, FFZpoolResult* result, uint8_t i FF_STRBUF_AUTO_DESTROY usedPretty = ffStrbufCreate(); ffSizeAppendNum(result->used, &usedPretty); + FF_STRBUF_AUTO_DESTROY allocatedPretty = ffStrbufCreate(); + ffSizeAppendNum(result->allocated, &allocatedPretty); + FF_STRBUF_AUTO_DESTROY totalPretty = ffStrbufCreate(); ffSizeAppendNum(result->total, &totalPretty); - double bytesPercentage = result->total > 0 ? (double) result->used / (double) result->total * 100.0 : 0; + double usedPercentage = result->total > 0 ? (double) result->used / (double) result->total * 100.0 : 0; + double allocatedPercentage = result->total > 0 ? (double) result->allocated / (double) result->total * 100.0 : 0; FFPercentageTypeFlags percentType = options->percent.type == 0 ? instance.config.display.percentType : options->percent.type; if(options->moduleArgs.outputFormat.length == 0) @@ -41,20 +47,31 @@ static void printZpool(FFZpoolOptions* options, FFZpoolResult* result, uint8_t i ffStrbufClear(&buffer); ffStrbufSetF(&buffer, "%s / %s (", usedPretty.chars, totalPretty.chars); - ffPercentAppendNum(&buffer, bytesPercentage, options->percent, false, &options->moduleArgs); + ffPercentAppendNum(&buffer, usedPercentage, options->percent, false, &options->moduleArgs); ffStrbufAppendS(&buffer, ", "); + ffPercentAppendNum(&buffer, allocatedPercentage, options->percent, false, &options->moduleArgs); + ffStrbufAppendS(&buffer, " allocated, "); ffPercentAppendNum(&buffer, result->fragmentation, options->percent, false, &options->moduleArgs); ffStrbufAppendF(&buffer, " frag) - %s", result->state.chars); + if (result->readOnly) + ffStrbufAppendS(&buffer, " [Read-only]"); ffStrbufPutTo(&buffer, stdout); } else { - FF_STRBUF_AUTO_DESTROY bytesPercentageNum = ffStrbufCreate(); + FF_STRBUF_AUTO_DESTROY usedPercentageNum = ffStrbufCreate(); if (percentType & FF_PERCENTAGE_TYPE_NUM_BIT) - ffPercentAppendNum(&bytesPercentageNum, bytesPercentage, options->percent, false, &options->moduleArgs); - FF_STRBUF_AUTO_DESTROY bytesPercentageBar = ffStrbufCreate(); + ffPercentAppendNum(&usedPercentageNum, usedPercentage, options->percent, false, &options->moduleArgs); + FF_STRBUF_AUTO_DESTROY usedPercentageBar = ffStrbufCreate(); if (percentType & FF_PERCENTAGE_TYPE_BAR_BIT) - ffPercentAppendBar(&bytesPercentageBar, bytesPercentage, options->percent, &options->moduleArgs); + ffPercentAppendBar(&usedPercentageBar, usedPercentage, options->percent, &options->moduleArgs); + + FF_STRBUF_AUTO_DESTROY allocatedPercentageNum = ffStrbufCreate(); + if (percentType & FF_PERCENTAGE_TYPE_NUM_BIT) + ffPercentAppendNum(&allocatedPercentageNum, allocatedPercentage, options->percent, false, &options->moduleArgs); + FF_STRBUF_AUTO_DESTROY allocatedPercentageBar = ffStrbufCreate(); + if (percentType & FF_PERCENTAGE_TYPE_BAR_BIT) + ffPercentAppendBar(&allocatedPercentageBar, allocatedPercentage, options->percent, &options->moduleArgs); FF_STRBUF_AUTO_DESTROY fragPercentageNum = ffStrbufCreate(); if (percentType & FF_PERCENTAGE_TYPE_NUM_BIT) @@ -65,13 +82,18 @@ static void printZpool(FFZpoolOptions* options, FFZpoolResult* result, uint8_t i FF_PRINT_FORMAT_CHECKED(buffer.chars, 0, &options->moduleArgs, FF_PRINT_TYPE_NO_CUSTOM_KEY, ((FFformatarg[]) { FF_FORMAT_ARG(result->name, "name"), + FF_FORMAT_ARG(result->guid, "guid"), FF_FORMAT_ARG(result->state, "state"), FF_FORMAT_ARG(usedPretty, "size-used"), + FF_FORMAT_ARG(allocatedPretty, "size-allocated"), FF_FORMAT_ARG(totalPretty, "size-total"), - FF_FORMAT_ARG(bytesPercentageNum, "size-percentage"), + FF_FORMAT_ARG(usedPercentageNum, "used-percentage"), + FF_FORMAT_ARG(allocatedPercentageNum, "allocated-percentage"), FF_FORMAT_ARG(fragPercentageNum, "frag-percentage"), - FF_FORMAT_ARG(bytesPercentageBar, "size-percentage-bar"), + FF_FORMAT_ARG(usedPercentageBar, "used-percentage-bar"), + FF_FORMAT_ARG(allocatedPercentageBar, "allocated-percentage-bar"), FF_FORMAT_ARG(fragPercentageBar, "frag-percentage-bar"), + FF_FORMAT_ARG(result->readOnly, "is-readonly"), })); } } @@ -149,13 +171,15 @@ bool ffGenerateZpoolJsonResult(FF_MAYBE_UNUSED FFZpoolOptions* options, yyjson_m yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr); yyjson_mut_obj_add_strbuf(doc, obj, "name", &zpool->name); yyjson_mut_obj_add_strbuf(doc, obj, "state", &zpool->state); + yyjson_mut_obj_add_uint(doc, obj, "guid", zpool->guid); yyjson_mut_obj_add_uint(doc, obj, "used", zpool->used); + yyjson_mut_obj_add_uint(doc, obj, "allocated", zpool->allocated); yyjson_mut_obj_add_uint(doc, obj, "total", zpool->total); - yyjson_mut_obj_add_uint(doc, obj, "version", zpool->version); if (zpool->fragmentation != -DBL_MAX) yyjson_mut_obj_add_real(doc, obj, "fragmentation", zpool->fragmentation); else yyjson_mut_obj_add_null(doc, obj, "fragmentation"); + yyjson_mut_obj_add_bool(doc, obj, "readOnly", zpool->readOnly); } FF_LIST_FOR_EACH(FFZpoolResult, zpool, results) @@ -188,12 +212,16 @@ FFModuleBaseInfo ffZpoolModuleInfo = { .generateJsonConfig = (void*) ffGenerateZpoolJsonConfig, .formatArgs = FF_FORMAT_ARG_LIST(((FFModuleFormatArg[]) { {"Zpool name", "name"}, + {"Zpool guid", "guid"}, {"Zpool state", "state"}, {"Size used", "used"}, + {"Size allocated", "allocated"}, {"Size total", "total"}, - {"Size percentage num", "used-percentage"}, + {"Size used percentage num", "used-percentage"}, + {"Size allocated percentage num", "allocated-percentage"}, {"Fragmentation percentage num", "fragmentation-percentage"}, - {"Size percentage bar", "used-percentage-bar"}, + {"Size used percentage bar", "used-percentage-bar"}, + {"Size allocated percentage bar", "allocated-percentage-bar"}, {"Fragmentation percentage bar", "fragmentation-percentage-bar"}, })) };