From b7b325c00635852dfffe8c8deff10b361101d175 Mon Sep 17 00:00:00 2001 From: Broc Going Date: Thu, 23 Apr 2026 09:48:56 -0700 Subject: [PATCH] compat: Adds more platform compatibility headers and mem compatibility. - Adds compatibility headers that provides functionality missing from Windows headers and cross-platform compatibility macros. - Adds memory management compatibility for aligned memory allocation and freeing. Windows has a seprate aligned free that needs to be used for aligned memory. Signed-off-by: Broc Going Signed-off-by: Brandon Capener --- common.h | 4 + libnvme/src/meson.build | 6 + libnvme/src/nvme/cleanup.h | 8 +- libnvme/src/nvme/fabrics.c | 4 +- libnvme/src/nvme/lib.h | 2 + libnvme/src/nvme/log.c | 3 +- libnvme/src/nvme/malloc.h | 19 ++ libnvme/src/nvme/mkdir.h | 19 ++ libnvme/src/nvme/private.h | 2 + libnvme/src/nvme/signal.h | 48 +++++ libnvme/src/nvme/stdio.h | 110 +++++++++++ libnvme/src/nvme/stdlib.h | 55 ++++++ libnvme/src/nvme/unistd.h | 36 ++++ libnvme/src/nvme/util.c | 14 +- nvme-models.c | 4 +- nvme-print-stdout.c | 3 +- nvme-rpmb.c | 2 +- nvme.c | 212 +++++++++++----------- plugins/amzn/amzn-nvme.c | 3 +- plugins/feat/feat-nvme.c | 2 +- plugins/memblaze/memblaze-nvme.c | 2 +- plugins/micron/micron-nvme.c | 4 +- plugins/netapp/netapp-nvme.c | 4 +- plugins/ocp/ocp-nvme.c | 6 +- plugins/shannon/shannon-nvme.c | 4 +- plugins/solidigm/solidigm-internal-logs.c | 4 +- plugins/toshiba/toshiba-nvme.c | 8 +- plugins/wdc/wdc-nvme.c | 4 +- plugins/wdc/wdc-utils.c | 2 + plugins/zns/zns.c | 6 +- util/cleanup.h | 6 + util/mem-linux.c | 83 +++++++++ util/mem-windows.c | 100 ++++++++++ util/mem.c | 80 +------- util/mem.h | 1 + util/meson.build | 10 +- util/sighdl.c | 3 +- util/table.c | 3 +- 38 files changed, 671 insertions(+), 215 deletions(-) create mode 100644 libnvme/src/nvme/malloc.h create mode 100644 libnvme/src/nvme/mkdir.h create mode 100644 libnvme/src/nvme/signal.h create mode 100644 libnvme/src/nvme/stdio.h create mode 100644 libnvme/src/nvme/stdlib.h create mode 100644 libnvme/src/nvme/unistd.h create mode 100644 util/mem-linux.c create mode 100644 util/mem-windows.c diff --git a/common.h b/common.h index 9e3a367bc3..b61d9cb7c0 100644 --- a/common.h +++ b/common.h @@ -9,8 +9,12 @@ #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) +#ifndef min #define min(x, y) ((x) > (y) ? (y) : (x)) +#endif +#ifndef max #define max(x, y) ((x) > (y) ? (x) : (y)) +#endif #ifdef __packed #else /* __packed */ diff --git a/libnvme/src/meson.build b/libnvme/src/meson.build index 2099222c1c..6f58757f24 100644 --- a/libnvme/src/meson.build +++ b/libnvme/src/meson.build @@ -32,10 +32,16 @@ headers = [ 'nvme/lib-types.h', 'nvme/lib.h', 'nvme/linux.h', + 'nvme/malloc.h', + 'nvme/mkdir.h', 'nvme/nvme-cmds.h', 'nvme/nvme-types.h', + 'nvme/signal.h', + 'nvme/stdio.h', + 'nvme/stdlib.h', 'nvme/tree.h', 'nvme/types.h', + 'nvme/unistd.h', 'nvme/util.h', ] diff --git a/libnvme/src/nvme/cleanup.h b/libnvme/src/nvme/cleanup.h index 5c7c550e24..d9b324e93e 100644 --- a/libnvme/src/nvme/cleanup.h +++ b/libnvme/src/nvme/cleanup.h @@ -2,7 +2,7 @@ #ifndef __CLEANUP_H #define __CLEANUP_H -#include +#include #define __cleanup(fn) __attribute__((cleanup(fn))) @@ -22,4 +22,10 @@ static inline void freep(void *p) } #define __cleanup_free __cleanup(freep) +static inline void libnvme_freep(void *p) +{ + aligned_free(*(void **)p); +} +#define __cleanup_libnvme_free __cleanup(libnvme_freep) + #endif diff --git a/libnvme/src/nvme/fabrics.c b/libnvme/src/nvme/fabrics.c index b0db83fe4c..99f97af6df 100644 --- a/libnvme/src/nvme/fabrics.c +++ b/libnvme/src/nvme/fabrics.c @@ -1418,7 +1418,7 @@ static int nvme_discovery_log(libnvme_ctrl_t ctrl, if (numrec == 0) break; - free(log); + __libnvme_free(log); entries_size = sizeof(*log->entries) * numrec; log = __libnvme_alloc(sizeof(*log) + entries_size); if (!log) { @@ -1475,7 +1475,7 @@ static int nvme_discovery_log(libnvme_ctrl_t ctrl, } out_free_log: - free(log); + __libnvme_free(log); return err; } diff --git a/libnvme/src/nvme/lib.h b/libnvme/src/nvme/lib.h index 92b8cd3762..3e46d6bcd1 100644 --- a/libnvme/src/nvme/lib.h +++ b/libnvme/src/nvme/lib.h @@ -12,6 +12,8 @@ #include #include +#include +#include enum libnvme_log_level { LIBNVME_LOG_ERR = 0, diff --git a/libnvme/src/nvme/log.c b/libnvme/src/nvme/log.c index a436e005f7..143aefa9dd 100644 --- a/libnvme/src/nvme/log.c +++ b/libnvme/src/nvme/log.c @@ -10,10 +10,11 @@ #include #include -#include #include #include +#include + #include #include "cleanup.h" diff --git a/libnvme/src/nvme/malloc.h b/libnvme/src/nvme/malloc.h new file mode 100644 index 0000000000..61eb7f8cb7 --- /dev/null +++ b/libnvme/src/nvme/malloc.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * This file is part of libnvme. + * Copyright (c) 2026 Micron Technology, Inc. + * + * Cross-platform compatibility for malloc.h. + * Provides functionality that may be missing on some platforms. + * Compatibility is not comprehensive. Only functionality required by + * nvme-cli and libnvme is included. + * + * Authors: Brandon Capener + */ +#pragma once + +#include + +#if defined(_WIN32) +#define malloc_usable_size _msize +#endif diff --git a/libnvme/src/nvme/mkdir.h b/libnvme/src/nvme/mkdir.h new file mode 100644 index 0000000000..f3edb4b8b0 --- /dev/null +++ b/libnvme/src/nvme/mkdir.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * This file is part of libnvme. + * Copyright (c) 2026 Micron Technology, Inc. + * + * Cross-platform compatibility for mkdir (sys/stat.h). + * + * Authors: Brandon Busacker + */ +#pragma once + +#if defined(_WIN32) + +#include + +/* Windows mkdir doesn't take the mode parameter */ +#define mkdir(path, mode) _mkdir(path) + +#endif diff --git a/libnvme/src/nvme/private.h b/libnvme/src/nvme/private.h index 36c51f4ef1..76f7c10ef4 100644 --- a/libnvme/src/nvme/private.h +++ b/libnvme/src/nvme/private.h @@ -425,6 +425,8 @@ bool _libnvme_ctrl_match_config(struct libnvme_ctrl *c, void *__libnvme_alloc(size_t len); +void __libnvme_free(void *p); + void *__libnvme_realloc(void *p, size_t len); void nvme_deconfigure_ctrl(struct libnvme_ctrl *c); diff --git a/libnvme/src/nvme/signal.h b/libnvme/src/nvme/signal.h new file mode 100644 index 0000000000..9f9201f060 --- /dev/null +++ b/libnvme/src/nvme/signal.h @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * This file is part of libnvme. + * Copyright (c) 2026 Micron Technology, Inc. + * + * Cross-platform compatibility for signal.h. + * Provides functionality that may be missing on some platforms. + * Compatibility is not comprehensive. Only functionality required by + * nvme-cli and libnvme is included. + * + * Authors: Brandon Busacker + */ +#pragma once + +#include + +#if defined(_WIN32) + +/* signal.h POSIX compatibility - Windows doesn't have sigaction */ + +struct sigaction { + void (*sa_handler)(int); + int sa_flags; + int sa_mask; /* simplified - normally sigset_t */ +}; + +static inline int sigemptyset(int *set) +{ + *set = 0; + return 0; +} + +/* + * Simplified signal handling using Windows signal() function + * This is sufficient for handling SIGINT with no mask or flags. + */ +static inline int sigaction(int signum, const struct sigaction *act, + struct sigaction *oldact) +{ + (void)oldact; /* ignore old action for simplicity */ + if (act && act->sa_handler) { + signal(signum, act->sa_handler); + return 0; + } + return -1; +} + +#endif diff --git a/libnvme/src/nvme/stdio.h b/libnvme/src/nvme/stdio.h new file mode 100644 index 0000000000..c92a9a170d --- /dev/null +++ b/libnvme/src/nvme/stdio.h @@ -0,0 +1,110 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * This file is part of libnvme. + * Copyright (c) 2026 Micron Technology, Inc. + * + * Cross-platform compatibility for stdio.h. + * Provides functionality that may be missing on some platforms. + * Compatibility is not comprehensive. Only functionality required by + * nvme-cli and libnvme is included. + * + * Authors: Brandon Busacker + */ +#pragma once + +#include + +#if defined(_WIN32) + +#include +#include +#include +#include + +/* stdio.h POSIX extensions */ + +/* dprintf implementation for Windows */ +static inline int dprintf(int fd, const char *format, ...) +{ + va_list args; + char buffer[4096]; + int result; + + va_start(args, format); + result = vsnprintf(buffer, sizeof(buffer), format, args); + va_end(args); + if (fd == STDERR_FILENO) + fputs(buffer, stderr); + else if (fd == STDOUT_FILENO) + fputs(buffer, stdout); + return result; +} + +/* getline implementation for Windows */ +static inline ssize_t getline(char **lineptr, size_t *n, FILE *stream) +{ + char *bufptr = NULL; + char *p = bufptr; + size_t size; + int c; + + if (lineptr == NULL || stream == NULL || n == NULL) { + errno = EINVAL; + return -1; + } + + bufptr = *lineptr; + size = *n; + + c = fgetc(stream); + if (c == EOF) + return -1; + + if (bufptr == NULL) { + bufptr = (char *)malloc(128); + if (bufptr == NULL) { + errno = ENOMEM; + return -1; + } + size = 128; + } + + p = bufptr; + while (c != EOF) { + if ((size_t)(p - bufptr) + 1 >= size) { + size_t pos = (size_t)(p - bufptr); + + size = size + 128; + bufptr = (char *)realloc(bufptr, size); + if (bufptr == NULL) { + errno = ENOMEM; + return -1; + } + p = bufptr + pos; + } + *p++ = c; + if (c == '\n') + break; + c = fgetc(stream); + } + + *p = '\0'; + *lineptr = bufptr; + *n = size; + + return p - bufptr; +} + +/* open_memstream workaround for Windows - returns a temporary file instead */ +static inline FILE *open_memstream(char **ptr, size_t *sizeloc) +{ + FILE *f = tmpfile(); + + if (ptr) + *ptr = NULL; + if (sizeloc) + *sizeloc = 0; + return f; +} + +#endif diff --git a/libnvme/src/nvme/stdlib.h b/libnvme/src/nvme/stdlib.h new file mode 100644 index 0000000000..d95c6ecf85 --- /dev/null +++ b/libnvme/src/nvme/stdlib.h @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * This file is part of libnvme. + * Copyright (c) 2026 Micron Technology, Inc. + * + * Cross-platform compatibility for stdlib.h. + * Provides functionality that may be missing on some platforms. + * Compatibility is not comprehensive. Only functionality required by + * nvme-cli and libnvme is included. + * + * Authors: Brandon Capener + */ +#pragma once + +#include + +/* + * Cross-platform compatible free for aligned memory allocations. + * Use when posix_memalign is used to allocate memory. + */ +#if defined(_WIN32) +#define aligned_free _aligned_free +#else +#define aligned_free free +#endif + +#if defined(_WIN32) + +#include +#include +#include + +/* Aligned memory allocation function, use aligned_free to free. */ +static inline int posix_memalign(void **memptr, size_t alignment, size_t size) +{ + *memptr = _aligned_malloc(size, alignment); + return (*memptr == NULL) ? ENOMEM : 0; +} + +/* reallocarray implementation for Windows */ +static inline void *reallocarray(void *ptr, size_t nmemb, size_t size) +{ + size_t total_size; + + /* Check for multiplication overflow */ + if (nmemb != 0 && size > SIZE_MAX / nmemb) { + errno = ENOMEM; + return NULL; + } + + total_size = nmemb * size; + return realloc(ptr, total_size); +} + +#endif diff --git a/libnvme/src/nvme/unistd.h b/libnvme/src/nvme/unistd.h new file mode 100644 index 0000000000..9968212ab5 --- /dev/null +++ b/libnvme/src/nvme/unistd.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * This file is part of libnvme. + * Copyright (c) 2026 Micron Technology, Inc. + * + * Cross-platform compatibility for unistd.h. + * Provides functionality that may be missing on some platforms. + * Compatibility is not comprehensive. Only functionality required by + * nvme-cli and libnvme is included. + * + * Authors: Brandon Busacker + */ +#pragma once + +#include + +#if defined(_WIN32) + +#include +#include +#include /* for gethostname */ + +/* unistd.h POSIX compatibility */ + +#define fsync _commit + +/* getpagesize implementation for Windows */ +static inline int getpagesize(void) +{ + SYSTEM_INFO si; + + GetSystemInfo(&si); + return si.dwPageSize; +} + +#endif diff --git a/libnvme/src/nvme/util.c b/libnvme/src/nvme/util.c index da4449ceb4..1b33bfd57f 100644 --- a/libnvme/src/nvme/util.c +++ b/libnvme/src/nvme/util.c @@ -9,12 +9,9 @@ #include #include -#include #include #include -#include #include -#include #if defined(HAVE_NETDB) || defined(CONFIG_FABRICS) #include @@ -30,6 +27,10 @@ #include #include +#include +#include +#include + #include #include "cleanup.h" @@ -966,6 +967,11 @@ void *__libnvme_alloc(size_t len) return p; } +void __libnvme_free(void *p) +{ + aligned_free(p); +} + void *__libnvme_realloc(void *p, size_t len) { size_t old_len = malloc_usable_size(p); @@ -974,7 +980,7 @@ void *__libnvme_realloc(void *p, size_t len) if (p && result) { memcpy(result, p, min(old_len, len)); - free(p); + __libnvme_free(p); } return result; diff --git a/nvme-models.c b/nvme-models.c index 4a94906deb..3092d6ecfe 100644 --- a/nvme-models.c +++ b/nvme-models.c @@ -2,13 +2,15 @@ #include #include #include -#include #include #include #include #include #include + +#include + #include "nvme-models.h" #include "nvme.h" diff --git a/nvme-print-stdout.c b/nvme-print-stdout.c index 6c4567f814..8b88d94f6b 100644 --- a/nvme-print-stdout.c +++ b/nvme-print-stdout.c @@ -1,7 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include #include -#include #include #include #include @@ -18,6 +17,8 @@ #include #include +#include + #include #include "nvme.h" diff --git a/nvme-rpmb.c b/nvme-rpmb.c index a68e488039..913a45720a 100644 --- a/nvme-rpmb.c +++ b/nvme-rpmb.c @@ -194,7 +194,7 @@ static int read_file(const char *file, unsigned char **data, unsigned int *len) err = -errno; fprintf(stderr, "Failed to read data from file" " %s with %s\n", file, libnvme_strerror(errno)); - free(buf); + aligned_free(buf); goto out; } *data = buf; diff --git a/nvme.c b/nvme.c index e3378b042a..4d4327f721 100644 --- a/nvme.c +++ b/nvme.c @@ -494,7 +494,7 @@ static int get_smart_log(int argc, char **argv, struct command *acmd, struct plu "(or optionally a namespace) in either decoded format " "(default) or binary."; - __cleanup_free struct nvme_smart_log *smart_log = NULL; + __cleanup_nvme_free struct nvme_smart_log *smart_log = NULL; __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; const char *namespace = "(optional) desired namespace"; @@ -559,8 +559,8 @@ static int get_ana_log(int argc, char **argv, struct command *acmd, __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; - __cleanup_free struct nvme_id_ctrl *ctrl = NULL; - __cleanup_free struct nvme_ana_log *ana_log = NULL; + __cleanup_nvme_free struct nvme_id_ctrl *ctrl = NULL; + __cleanup_nvme_free struct nvme_ana_log *ana_log = NULL; size_t max_ana_log_len; __u32 ana_log_len; nvme_print_flags_t flags; @@ -683,7 +683,7 @@ static int get_log_telemetry_ctrl(struct libnvme_transport_handle *hdl, bool rae err = nvme_get_log_telemetry_ctrl(hdl, rae, 0, log, size); if (err) { - free(log); + nvme_free(log); return err; } @@ -703,7 +703,7 @@ static int get_log_telemetry_host(struct libnvme_transport_handle *hdl, size_t s err = nvme_get_log_telemetry_host(hdl, 0, log, size); if (err) { - free(log); + nvme_free(log); return err; } @@ -717,7 +717,7 @@ static int __create_telemetry_log_host(struct libnvme_transport_handle *hdl, struct nvme_telemetry_log **buf, bool da4_support) { - __cleanup_free struct nvme_telemetry_log *log = NULL; + __cleanup_nvme_free struct nvme_telemetry_log *log = NULL; int err; log = nvme_alloc(sizeof(*log)); @@ -779,7 +779,7 @@ static int __get_telemetry_log_ctrl(struct libnvme_transport_handle *hdl, return get_log_telemetry_ctrl(hdl, rae, *size, buf); free: - free(log); + nvme_free(log); return err; } @@ -789,7 +789,7 @@ static int __get_telemetry_log_host(struct libnvme_transport_handle *hdl, struct nvme_telemetry_log **buf, bool da4_support) { - __cleanup_free struct nvme_telemetry_log *log = NULL; + __cleanup_nvme_free struct nvme_telemetry_log *log = NULL; int err; log = nvme_alloc(sizeof(*log)); @@ -819,8 +819,8 @@ static int get_telemetry_log(int argc, char **argv, struct command *acmd, const char *mcda = "Host-init Maximum Created Data Area. Valid options are 0 ~ 4 " "If given, This option will override dgen. 0 : controller determines data area"; - __cleanup_free struct nvme_telemetry_log *log = NULL; - __cleanup_free struct nvme_id_ctrl *id_ctrl = NULL; + __cleanup_nvme_free struct nvme_telemetry_log *log = NULL; + __cleanup_nvme_free struct nvme_id_ctrl *id_ctrl = NULL; __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; __cleanup_fd int output = -1; @@ -983,7 +983,7 @@ static int get_endurance_log(int argc, char **argv, struct command *acmd, struct const char *desc = "Retrieves endurance groups log page and prints the log."; const char *group_id = "The endurance group identifier"; - __cleanup_free struct nvme_endurance_group_log *endurance_log = NULL; + __cleanup_nvme_free struct nvme_endurance_group_log *endurance_log = NULL; __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; nvme_print_flags_t flags; @@ -1041,7 +1041,7 @@ static int collect_effects_log(struct libnvme_transport_handle *hdl, enum nvme_c err = nvme_get_log_cmd_effects(hdl, csi, &node->effects); if (err) { - free(node); + nvme_free(node); return err; } list_add(list, &node->node); @@ -1148,7 +1148,7 @@ static int get_supported_log_pages(int argc, char **argv, struct command *acmd, { const char *desc = "Retrieve supported logs and print the table."; - __cleanup_free struct nvme_supported_log_pages *supports = NULL; + __cleanup_nvme_free struct nvme_supported_log_pages *supports = NULL; __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; nvme_print_flags_t flags; @@ -1193,7 +1193,7 @@ static int get_error_log(int argc, char **argv, struct command *acmd, struct plu const char *log_entries = "number of entries to retrieve"; const char *raw = "dump in binary format"; - __cleanup_free struct nvme_error_log_page *err_log = NULL; + __cleanup_nvme_free struct nvme_error_log_page *err_log = NULL; __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; struct nvme_id_ctrl ctrl = { 0 }; @@ -1263,7 +1263,7 @@ static int get_fw_log(int argc, char **argv, struct command *acmd, struct plugin const char *desc = "Retrieve the firmware log for the " "specified device in either decoded format (default) or binary."; - __cleanup_free struct nvme_firmware_slot *fw_log = NULL; + __cleanup_nvme_free struct nvme_firmware_slot *fw_log = NULL; __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; nvme_print_flags_t flags; @@ -1311,7 +1311,7 @@ static int get_fw_log(int argc, char **argv, struct command *acmd, struct plugin static int get_changed_ns_list_log(int argc, char **argv, bool alloc) { __cleanup_free char *desc = NULL; - __cleanup_free struct nvme_ns_list *changed_ns_list_log = NULL; + __cleanup_nvme_free struct nvme_ns_list *changed_ns_list_log = NULL; __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; nvme_print_flags_t flags; @@ -1389,7 +1389,7 @@ static int get_pred_lat_per_nvmset_log(int argc, char **argv, "format(default),json or binary."; const char *nvmset_id = "NVM Set Identifier"; - __cleanup_free struct nvme_nvmset_predictable_lat_log *plpns_log = NULL; + __cleanup_nvme_free struct nvme_nvmset_predictable_lat_log *plpns_log = NULL; __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; nvme_print_flags_t flags; @@ -1449,8 +1449,8 @@ static int get_pred_lat_event_agg_log(int argc, char **argv, __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; - __cleanup_free struct nvme_id_ctrl *ctrl = NULL; - __cleanup_free void *pea_log = NULL; + __cleanup_nvme_free struct nvme_id_ctrl *ctrl = NULL; + __cleanup_nvme_free void *pea_log = NULL; nvme_print_flags_t flags; __u32 log_size; int err; @@ -1530,7 +1530,7 @@ static int get_persistent_event_log(int argc, char **argv, "processing this persistent log page command."; const char *log_len = "number of bytes to retrieve"; - __cleanup_free struct nvme_persistent_event_log *pevent = NULL; + __cleanup_nvme_free struct nvme_persistent_event_log *pevent = NULL; struct nvme_persistent_event_log *pevent_collected = NULL; __cleanup_huge struct nvme_mem_huge mh = { 0, }; __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; @@ -1645,8 +1645,8 @@ static int get_endurance_event_agg_log(int argc, char **argv, __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; - __cleanup_free struct nvme_id_ctrl *ctrl = NULL; - __cleanup_free void *endurance_log = NULL; + __cleanup_nvme_free struct nvme_id_ctrl *ctrl = NULL; + __cleanup_nvme_free void *endurance_log = NULL; nvme_print_flags_t flags; __u32 log_size; int err; @@ -1727,7 +1727,7 @@ static int get_lba_status_log(int argc, char **argv, __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; - __cleanup_free void *lba_status = NULL; + __cleanup_nvme_free void *lba_status = NULL; nvme_print_flags_t flags; __u32 lslplen; int err; @@ -1783,7 +1783,7 @@ static int get_resv_notif_log(int argc, char **argv, "log page and prints it, for the given " "device in either decoded format(default), json or binary."; - __cleanup_free struct nvme_resv_notification_log *resv = NULL; + __cleanup_nvme_free struct nvme_resv_notification_log *resv = NULL; __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; nvme_print_flags_t flags; @@ -1827,8 +1827,8 @@ static int get_boot_part_log(int argc, char **argv, struct command *acmd, struct __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; - __cleanup_free struct nvme_boot_partition *boot = NULL; - __cleanup_free __u8 *bp_log = NULL; + __cleanup_nvme_free struct nvme_boot_partition *boot = NULL; + __cleanup_nvme_free __u8 *bp_log = NULL; nvme_print_flags_t flags; int err = -1; __cleanup_fd int output = -1; @@ -1916,7 +1916,7 @@ static int get_phy_rx_eom_log(int argc, char **argv, struct command *acmd, "Measurement log for the given device in decoded format " "(default), json or binary."; const char *controller = "Target Controller ID."; - __cleanup_free struct nvme_phy_rx_eom_log *phy_rx_eom_log = NULL; + __cleanup_nvme_free struct nvme_phy_rx_eom_log *phy_rx_eom_log = NULL; size_t phy_rx_eom_log_len; nvme_print_flags_t flags; __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; @@ -2003,7 +2003,7 @@ static int get_media_unit_stat_log(int argc, char **argv, struct command *acmd, { const char *desc = "Retrieve the configuration and wear of media units and print it"; - __cleanup_free struct nvme_media_unit_stat_log *mus = NULL; + __cleanup_nvme_free struct nvme_media_unit_stat_log *mus = NULL; __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; nvme_print_flags_t flags; @@ -2056,7 +2056,7 @@ static int get_supp_cap_config_log(int argc, char **argv, struct command *acmd, { const char *desc = "Retrieve the list of Supported Capacity Configuration Descriptors"; - __cleanup_free struct nvme_supported_cap_config_list_log *cap_log = NULL; + __cleanup_nvme_free struct nvme_supported_cap_config_list_log *cap_log = NULL; __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; nvme_print_flags_t flags; @@ -2112,7 +2112,7 @@ static int io_mgmt_send(int argc, char **argv, struct command *acmd, struct plug __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; __cleanup_fd int dfd = STDIN_FILENO; - __cleanup_free void *buf = NULL; + __cleanup_nvme_free void *buf = NULL; struct libnvme_passthru_cmd cmd; int err = -1; @@ -2187,7 +2187,7 @@ static int io_mgmt_recv(int argc, char **argv, struct command *acmd, struct plug __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; - __cleanup_free void *buf = NULL; + __cleanup_nvme_free void *buf = NULL; struct libnvme_passthru_cmd cmd; __cleanup_fd int dfd = -1; int err = -1; @@ -2275,7 +2275,7 @@ static int get_log(int argc, char **argv, struct command *acmd, struct plugin *p __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; - __cleanup_free unsigned char *log = NULL; + __cleanup_nvme_free unsigned char *log = NULL; struct libnvme_passthru_cmd cmd; int err; nvme_print_flags_t flags; @@ -2477,7 +2477,7 @@ static int sanitize_log(int argc, char **argv, struct command *acmd, struct plug { const char *desc = "Retrieve sanitize log and show it."; - __cleanup_free struct nvme_sanitize_log_page *sanitize_log = NULL; + __cleanup_nvme_free struct nvme_sanitize_log_page *sanitize_log = NULL; __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; nvme_print_flags_t flags; @@ -2537,7 +2537,7 @@ static int get_fid_support_effects_log(int argc, char **argv, struct command *ac { const char *desc = "Retrieve FID Support and Effects log and show it."; - __cleanup_free struct nvme_fid_supported_effects_log *fid_support_log = NULL; + __cleanup_nvme_free struct nvme_fid_supported_effects_log *fid_support_log = NULL; __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; nvme_print_flags_t flags; @@ -2589,7 +2589,7 @@ static int get_mi_cmd_support_effects_log(int argc, char **argv, struct command { const char *desc = "Retrieve NVMe-MI Command Support and Effects log and show it."; - __cleanup_free struct nvme_mi_cmd_supported_effects_log *mi_cmd_support_log = NULL; + __cleanup_nvme_free struct nvme_mi_cmd_supported_effects_log *mi_cmd_support_log = NULL; __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; nvme_print_flags_t flags; @@ -2641,7 +2641,7 @@ static int list_ctrl(int argc, char **argv, struct command *acmd, struct plugin "given device is part of, or optionally controllers attached to a specific namespace."; const char *controller = "controller to display"; - __cleanup_free struct nvme_ctrl_list *cntlist = NULL; + __cleanup_nvme_free struct nvme_ctrl_list *cntlist = NULL; __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; struct libnvme_passthru_cmd cmd; @@ -2701,7 +2701,7 @@ static int list_ns(int argc, char **argv, struct command *acmd, struct plugin *p const char *csi = "I/O command set identifier"; const char *all = "show all namespaces in the subsystem, whether attached or inactive"; - __cleanup_free struct nvme_ns_list *ns_list = NULL; + __cleanup_nvme_free struct nvme_ns_list *ns_list = NULL; __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; enum nvme_identify_cns cns; @@ -2776,7 +2776,7 @@ static int id_ns_lba_format(int argc, char **argv, struct command *acmd, struct __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; - __cleanup_free struct nvme_id_ns *ns = NULL; + __cleanup_nvme_free struct nvme_id_ns *ns = NULL; nvme_print_flags_t flags; int err = -1; @@ -2831,7 +2831,7 @@ static int id_endurance_grp_list(int argc, char **argv, struct command *acmd, const char *desc = "Show endurance group list information for the given endurance group id"; const char *endurance_grp_id = "Endurance Group ID"; - __cleanup_free struct nvme_id_endurance_group_list *endgrp_list = NULL; + __cleanup_nvme_free struct nvme_id_endurance_group_list *endgrp_list = NULL; __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; struct libnvme_passthru_cmd cmd; @@ -2880,7 +2880,7 @@ static bool is_ns_mgmt_support(struct libnvme_transport_handle *hdl) { int err; - __cleanup_free struct nvme_id_ctrl *ctrl = nvme_alloc(sizeof(*ctrl)); + __cleanup_nvme_free struct nvme_id_ctrl *ctrl = nvme_alloc(sizeof(*ctrl)); if (ctrl) return false; @@ -2979,7 +2979,7 @@ static int nvme_attach_ns(int argc, char **argv, int attach, const char *desc, s __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; - __cleanup_free struct nvme_ctrl_list *cntlist = NULL; + __cleanup_nvme_free struct nvme_ctrl_list *cntlist = NULL; __u16 list[NVME_ID_CTRL_LIST_MAX]; struct libnvme_passthru_cmd cmd; nvme_print_flags_t flags; @@ -3092,9 +3092,9 @@ static int detach_ns(int argc, char **argv, struct command *acmd, struct plugin static int parse_lba_num_si(struct libnvme_transport_handle *hdl, const char *opt, const char *val, __u8 flbas, __u64 *num, __u64 align) { - __cleanup_free struct nvme_ns_list *ns_list = NULL; - __cleanup_free struct nvme_id_ctrl *ctrl = NULL; - __cleanup_free struct nvme_id_ns *ns = NULL; + __cleanup_nvme_free struct nvme_ns_list *ns_list = NULL; + __cleanup_nvme_free struct nvme_id_ctrl *ctrl = NULL; + __cleanup_nvme_free struct nvme_id_ns *ns = NULL; __u32 nsid = 1; __u8 lbaf; unsigned int remainder; @@ -3198,11 +3198,11 @@ static int create_ns(int argc, char **argv, struct command *acmd, struct plugin const char *phndls = "Comma separated list of Placement Handle Associated RUH"; __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; - __cleanup_free struct nvme_ns_mgmt_host_sw_specified *data = NULL; - __cleanup_free struct nvme_id_ns_granularity_list *gr_list = NULL; + __cleanup_nvme_free struct nvme_ns_mgmt_host_sw_specified *data = NULL; + __cleanup_nvme_free struct nvme_id_ns_granularity_list *gr_list = NULL; __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; - __cleanup_free struct nvme_id_ctrl *id = NULL; - __cleanup_free struct nvme_id_ns *ns = NULL; + __cleanup_nvme_free struct nvme_id_ctrl *id = NULL; + __cleanup_nvme_free struct nvme_id_ns *ns = NULL; __u64 align_nsze = 1 << 20; /* Default 1 MiB */ __u64 align_ncap = align_nsze; struct libnvme_passthru_cmd cmd; @@ -3583,7 +3583,7 @@ int __id_ctrl(int argc, char **argv, struct command *acmd, struct plugin *plugin "controller attributes in hex-dump if requested."; const char *vendor_specific = "dump binary vendor field"; - __cleanup_free struct nvme_id_ctrl *ctrl = NULL; + __cleanup_nvme_free struct nvme_id_ctrl *ctrl = NULL; __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; nvme_print_flags_t flags; @@ -3652,7 +3652,7 @@ static int nvm_id_ctrl(int argc, char **argv, struct command *acmd, "command to the given device and report information about " "the specified controller in various formats."; - __cleanup_free struct nvme_id_ctrl_nvm *ctrl_nvm = NULL; + __cleanup_nvme_free struct nvme_id_ctrl_nvm *ctrl_nvm = NULL; __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; struct libnvme_passthru_cmd cmd; @@ -3697,8 +3697,8 @@ static int nvm_id_ns(int argc, char **argv, struct command *acmd, "command to the given device and report information about " "the specified namespace in various formats."; - __cleanup_free struct nvme_nvm_id_ns *id_ns = NULL; - __cleanup_free struct nvme_id_ns *ns = NULL; + __cleanup_nvme_free struct nvme_nvm_id_ns *id_ns = NULL; + __cleanup_nvme_free struct nvme_id_ns *ns = NULL; __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; nvme_print_flags_t flags; @@ -3771,8 +3771,8 @@ static int nvm_id_ns_lba_format(int argc, char **argv, struct command *acmd, str "command to the given device, returns capability field properties of " "the specified LBA Format index in the specified namespace in various formats."; - __cleanup_free struct nvme_nvm_id_ns *nvm_ns = NULL; - __cleanup_free struct nvme_id_ns *ns = NULL; + __cleanup_nvme_free struct nvme_nvm_id_ns *nvm_ns = NULL; + __cleanup_nvme_free struct nvme_id_ns *ns = NULL; __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; nvme_print_flags_t flags; @@ -3842,7 +3842,7 @@ static int ns_descs(int argc, char **argv, struct command *acmd, struct plugin * __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; - __cleanup_free void *nsdescs = NULL; + __cleanup_nvme_free void *nsdescs = NULL; nvme_print_flags_t flags; int err; @@ -3910,7 +3910,7 @@ static int id_ns(int argc, char **argv, struct command *acmd, struct plugin *plu __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; - __cleanup_free struct nvme_id_ns *ns = NULL; + __cleanup_nvme_free struct nvme_id_ns *ns = NULL; struct libnvme_passthru_cmd cmd; nvme_print_flags_t flags; int err; @@ -3993,7 +3993,7 @@ static int cmd_set_independent_id_ns(int argc, char **argv, struct command *acmd "Namespace command to the given device, returns properties of the " "specified namespace in human-readable or binary or json format."; - __cleanup_free struct nvme_id_independent_id_ns *ns = NULL; + __cleanup_nvme_free struct nvme_id_independent_id_ns *ns = NULL; __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; struct libnvme_passthru_cmd cmd; @@ -4065,7 +4065,7 @@ static int id_ns_granularity(int argc, char **argv, struct command *acmd, struct "given device, returns namespace granularity list " "in either human-readable or binary format."; - __cleanup_free struct nvme_id_ns_granularity_list *granularity_list = NULL; + __cleanup_nvme_free struct nvme_id_ns_granularity_list *granularity_list = NULL; __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; nvme_print_flags_t flags; @@ -4106,7 +4106,7 @@ static int id_nvmset(int argc, char **argv, struct command *acmd, struct plugin "in either binary format or json format"; const char *nvmset_id = "NVM Set Identify value"; - __cleanup_free struct nvme_id_nvmset_list *nvmset = NULL; + __cleanup_nvme_free struct nvme_id_nvmset_list *nvmset = NULL; __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; struct libnvme_passthru_cmd cmd; @@ -4159,7 +4159,7 @@ static int id_uuid(int argc, char **argv, struct command *acmd, struct plugin *p const char *raw = "show uuid in binary format"; const char *human_readable = "show uuid in readable format"; - __cleanup_free struct nvme_id_uuid_list *uuid_list = NULL; + __cleanup_nvme_free struct nvme_id_uuid_list *uuid_list = NULL; __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; nvme_print_flags_t flags; @@ -4217,7 +4217,7 @@ static int id_iocs(int argc, char **argv, struct command *acmd, struct plugin *p "in either human-readable or binary format."; const char *controller_id = "identifier of desired controller"; - __cleanup_free struct nvme_id_iocs *iocs = NULL; + __cleanup_nvme_free struct nvme_id_iocs *iocs = NULL; __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; struct libnvme_passthru_cmd cmd; @@ -4272,7 +4272,7 @@ static int id_domain(int argc, char **argv, struct command *acmd, struct plugin "in either normal|json|binary format."; const char *domain_id = "identifier of desired domain"; - __cleanup_free struct nvme_id_domain_list *id_domain = NULL; + __cleanup_nvme_free struct nvme_id_domain_list *id_domain = NULL; __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; struct libnvme_passthru_cmd cmd; @@ -4418,7 +4418,7 @@ static int primary_ctrl_caps(int argc, char **argv, struct command *acmd, struct "command to the given device and report the information in a " "decoded format (default), json or binary."; - __cleanup_free struct nvme_primary_ctrl_cap *caps = NULL; + __cleanup_nvme_free struct nvme_primary_ctrl_cap *caps = NULL; __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; struct libnvme_passthru_cmd cmd; @@ -4475,7 +4475,7 @@ static int list_secondary_ctrl(int argc, char **argv, struct command *acmd, stru const char *controller = "lowest controller identifier to display"; const char *num_entries = "number of entries to retrieve"; - __cleanup_free struct nvme_secondary_ctrl_list *sc_list = NULL; + __cleanup_nvme_free struct nvme_secondary_ctrl_list *sc_list = NULL; __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; struct libnvme_passthru_cmd cmd; @@ -4544,8 +4544,8 @@ static int sleep_self_test(unsigned int seconds) static int wait_self_test(struct libnvme_transport_handle *hdl) { static const char spin[] = {'-', '\\', '|', '/' }; - __cleanup_free struct nvme_self_test_log *log = NULL; - __cleanup_free struct nvme_id_ctrl *ctrl = NULL; + __cleanup_nvme_free struct nvme_self_test_log *log = NULL; + __cleanup_nvme_free struct nvme_id_ctrl *ctrl = NULL; int err, i = 0, p = 0, cnt = 0; int wthr; @@ -4680,7 +4680,7 @@ static int device_self_test(int argc, char **argv, struct command *acmd, struct } if (cfg.stc == NVME_ST_CODE_RESERVED) { - __cleanup_free struct nvme_self_test_log *log = NULL; + __cleanup_nvme_free struct nvme_self_test_log *log = NULL; log = nvme_alloc(sizeof(*log)); if (!log) @@ -4743,7 +4743,7 @@ static int self_test_log(int argc, char **argv, struct command *acmd, struct plu const char *dst_entries = "Indicate how many DST log entries to be retrieved, " "by default all the 20 entries will be retrieved"; - __cleanup_free struct nvme_self_test_log *log = NULL; + __cleanup_nvme_free struct nvme_self_test_log *log = NULL; __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; nvme_print_flags_t flags; @@ -4864,8 +4864,8 @@ static bool is_get_feature_result_set(enum nvme_features_id feature_id) static int get_feature_id_changed(struct libnvme_transport_handle *hdl, struct feat_cfg cfg, nvme_print_flags_t flags) { - __cleanup_free void *buf_def = NULL; - __cleanup_free void *buf = NULL; + __cleanup_nvme_free void *buf_def = NULL; + __cleanup_nvme_free void *buf = NULL; __u64 result_def = 0; __u64 result; int err_def = 0; @@ -5256,7 +5256,7 @@ static char *nvme_fw_status_reset_type(__u16 status) static bool fw_commit_support_mud(struct libnvme_transport_handle *hdl) { - __cleanup_free struct nvme_id_ctrl *ctrl = NULL; + __cleanup_nvme_free struct nvme_id_ctrl *ctrl = NULL; int err; ctrl = nvme_alloc(sizeof(*ctrl)); @@ -6602,8 +6602,8 @@ static int format_cmd(int argc, char **argv, struct command *acmd, struct plugin __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; - __cleanup_free struct nvme_id_ctrl *ctrl = NULL; - __cleanup_free struct nvme_id_ns *ns = NULL; + __cleanup_nvme_free struct nvme_id_ctrl *ctrl = NULL; + __cleanup_nvme_free struct nvme_id_ns *ns = NULL; nvme_print_flags_t flags = NORMAL; struct libnvme_passthru_cmd cmd; __u32 timeout_ms = 600000; @@ -6864,7 +6864,7 @@ static int set_feature(int argc, char **argv, struct command *acmd, struct plugi __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; - __cleanup_free void *buf = NULL; + __cleanup_nvme_free void *buf = NULL; __cleanup_fd int ffd = STDIN_FILENO; int err; __u64 result; @@ -7010,7 +7010,7 @@ static int sec_send(int argc, char **argv, struct command *acmd, struct plugin * __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; struct libnvme_passthru_cmd cmd; - __cleanup_free void *sec_buf = NULL; + __cleanup_nvme_free void *sec_buf = NULL; __cleanup_fd int sec_fd = -1; unsigned int sec_size; int err; @@ -7121,7 +7121,7 @@ static int dir_send(int argc, char **argv, struct command *acmd, struct plugin * __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; - __cleanup_free void *buf = NULL; + __cleanup_nvme_free void *buf = NULL; struct libnvme_passthru_cmd cmd; __u32 dw12 = 0; __cleanup_fd int ffd = STDIN_FILENO; @@ -7362,8 +7362,8 @@ static int get_pi_info(struct libnvme_transport_handle *hdl, __u32 nsid, __u8 prinfo, __u64 ilbrt, __u64 lbst, unsigned int *logical_block_size, __u16 *metadata_size) { - __cleanup_free struct nvme_nvm_id_ns *nvm_ns = NULL; - __cleanup_free struct nvme_id_ns *ns = NULL; + __cleanup_nvme_free struct nvme_nvm_id_ns *nvm_ns = NULL; + __cleanup_nvme_free struct nvme_id_ns *ns = NULL; __u8 sts = 0, pif = 0; unsigned int lbs = 0; __u8 lba_index; @@ -7425,8 +7425,8 @@ static int init_pi_tags(struct libnvme_transport_handle *hdl, struct libnvme_passthru_cmd *cmd, __u32 nsid, __u64 ilbrt, __u64 lbst, __u16 lbat, __u16 lbatm) { - __cleanup_free struct nvme_nvm_id_ns *nvm_ns = NULL; - __cleanup_free struct nvme_id_ns *ns = NULL; + __cleanup_nvme_free struct nvme_nvm_id_ns *nvm_ns = NULL; + __cleanup_nvme_free struct nvme_id_ns *ns = NULL; __u8 sts = 0, pif = 0; int err = 0; @@ -7609,7 +7609,7 @@ static int dsm(int argc, char **argv, struct command *acmd, struct plugin *plugi __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; - __cleanup_free struct nvme_dsm_range *dsm = NULL; + __cleanup_nvme_free struct nvme_dsm_range *dsm = NULL; struct libnvme_passthru_cmd cmd; __u32 ctx_attrs[256] = {0,}; __u32 nlbs[256] = {0,}; @@ -7750,7 +7750,7 @@ static int copy_cmd(int argc, char **argv, struct command *acmd, struct plugin * __u16 elbatms[256] = { 0 }; __u16 elbats[256] = { 0 }; - __cleanup_free union { + __cleanup_nvme_free union { struct nvme_copy_range_f0 f0[256]; struct nvme_copy_range_f1 f1[256]; struct nvme_copy_range_f2 f2[256]; @@ -8224,8 +8224,8 @@ static int resv_report(int argc, char **argv, struct command *acmd, struct plugi __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; - __cleanup_free struct nvme_resv_status *status = NULL; - __cleanup_free struct nvme_id_ctrl *ctrl = NULL; + __cleanup_nvme_free struct nvme_resv_status *status = NULL; + __cleanup_nvme_free struct nvme_id_ctrl *ctrl = NULL; struct libnvme_passthru_cmd cmd; nvme_print_flags_t flags; int err, size; @@ -8320,9 +8320,9 @@ static int submit_io(int opcode, char *command, const char *desc, int argc, char __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; unsigned long long buffer_size = 0, mbuffer_size = 0; - __cleanup_free struct nvme_nvm_id_ns *nvm_ns = NULL; + __cleanup_nvme_free struct nvme_nvm_id_ns *nvm_ns = NULL; __cleanup_huge struct nvme_mem_huge mh = { 0, }; - __cleanup_free struct nvme_id_ns *ns = NULL; + __cleanup_nvme_free struct nvme_id_ns *ns = NULL; unsigned int logical_block_size = 0; struct timeval start_time, end_time; __cleanup_free void *mbuffer = NULL; @@ -8778,7 +8778,7 @@ static int sec_recv(int argc, char **argv, struct command *acmd, struct plugin * __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; - __cleanup_free void *sec_buf = NULL; + __cleanup_nvme_free void *sec_buf = NULL; struct libnvme_passthru_cmd cmd; nvme_print_flags_t flags; int err; @@ -8871,7 +8871,7 @@ static int get_lba_status(int argc, char **argv, struct command *acmd, __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; struct libnvme_passthru_cmd cmd; - __cleanup_free void *buf = NULL; + __cleanup_nvme_free void *buf = NULL; nvme_print_flags_t flags; unsigned long buf_len; int err; @@ -9034,7 +9034,7 @@ static int dir_receive(int argc, char **argv, struct command *acmd, struct plugi nvme_print_flags_t flags = NORMAL; __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; - __cleanup_free void *buf = NULL; + __cleanup_nvme_free void *buf = NULL; struct libnvme_passthru_cmd cmd; __u32 dw12 = 0; int err; @@ -10564,7 +10564,7 @@ static int get_mgmt_addr_list_log(int argc, char **argv, struct command *acmd, s nvme_print_flags_t flags; int err = -1; - __cleanup_free struct nvme_mgmt_addr_list_log *ma_log = NULL; + __cleanup_nvme_free struct nvme_mgmt_addr_list_log *ma_log = NULL; __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; @@ -10602,7 +10602,7 @@ static int get_rotational_media_info_log(int argc, char **argv, struct command * nvme_print_flags_t flags; int err = -1; - __cleanup_free struct nvme_rotational_media_info_log *info = NULL; + __cleanup_nvme_free struct nvme_rotational_media_info_log *info = NULL; __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; @@ -10678,7 +10678,7 @@ static int get_dispersed_ns_psub(struct libnvme_transport_handle *hdl, __u32 nsi return 0; err_free: - free(log); + nvme_free(log); return err; } @@ -10691,7 +10691,7 @@ static int get_dispersed_ns_participating_nss_log(int argc, char **argv, struct __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; - __cleanup_free struct nvme_dispersed_ns_participating_nss_log *log = NULL; + __cleanup_nvme_free struct nvme_dispersed_ns_participating_nss_log *log = NULL; struct config { __u32 namespace_id; @@ -10733,7 +10733,7 @@ static int get_power_measurement_log(int argc, char **argv, struct command *acmd __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; - __cleanup_free struct nvme_power_meas_log *log = NULL; + __cleanup_nvme_free struct nvme_power_meas_log *log = NULL; nvme_print_flags_t flags; __u32 min_log_size = sizeof(struct nvme_power_meas_log); __u32 log_size; @@ -10863,7 +10863,7 @@ static int get_reachability_group_desc(struct libnvme_transport_handle *hdl, str return 0; err_free: - free(log); + nvme_free(log); *logp = NULL; return err; } @@ -10899,7 +10899,7 @@ static int get_reachability_groups(struct libnvme_transport_handle *hdl, bool rg return 0; err_free: - free(log); + nvme_free(log); return err; } @@ -10911,7 +10911,7 @@ static int get_reachability_groups_log(int argc, char **argv, struct command *ac nvme_print_flags_t flags; int err; __u64 len = 0; - __cleanup_free struct nvme_reachability_groups_log *log = NULL; + __cleanup_nvme_free struct nvme_reachability_groups_log *log = NULL; __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; @@ -10974,7 +10974,7 @@ static int get_reachability_association_desc(struct libnvme_transport_handle *hd return 0; err_free: - free(log); + nvme_free(log); *logp = NULL; return err; } @@ -11010,7 +11010,7 @@ static int get_reachability_associations(struct libnvme_transport_handle *hdl, b return 0; err_free: - free(log); + nvme_free(log); return err; } @@ -11022,7 +11022,7 @@ static int get_reachability_associations_log(int argc, char **argv, struct comma nvme_print_flags_t flags; int err; __u64 len = 0; - __cleanup_free struct nvme_reachability_associations_log *log = NULL; + __cleanup_nvme_free struct nvme_reachability_associations_log *log = NULL; __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; @@ -11092,7 +11092,7 @@ static int get_host_discovery(struct libnvme_transport_handle *hdl, bool allhost return 0; err_free: - free(log); + nvme_free(log); return err; } @@ -11102,7 +11102,7 @@ static int get_host_discovery_log(int argc, char **argv, struct command *acmd, s const char *allhoste = "All Host Entries"; nvme_print_flags_t flags; int err; - __cleanup_free struct nvme_host_discover_log *log = NULL; + __cleanup_nvme_free struct nvme_host_discover_log *log = NULL; __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; @@ -11171,7 +11171,7 @@ static int get_ave_discovery(struct libnvme_transport_handle *hdl, bool rae, str return 0; err_free: - free(log); + nvme_free(log); return err; } @@ -11181,7 +11181,7 @@ static int get_ave_discovery_log(int argc, char **argv, struct command *acmd, st nvme_print_flags_t flags; int err; - __cleanup_free struct nvme_ave_discover_log *log = NULL; + __cleanup_nvme_free struct nvme_ave_discover_log *log = NULL; __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; @@ -11246,7 +11246,7 @@ static int get_pull_model_ddc_req(struct libnvme_transport_handle *hdl, return 0; err_free: - free(log); + nvme_free(log); return err; } @@ -11257,7 +11257,7 @@ static int get_pull_model_ddc_req_log(int argc, char **argv, struct command *acm nvme_print_flags_t flags; int err; - __cleanup_free struct nvme_pull_model_ddc_req_log *log = NULL; + __cleanup_nvme_free struct nvme_pull_model_ddc_req_log *log = NULL; __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; diff --git a/plugins/amzn/amzn-nvme.c b/plugins/amzn/amzn-nvme.c index 307ef48fdf..849a36e5dc 100644 --- a/plugins/amzn/amzn-nvme.c +++ b/plugins/amzn/amzn-nvme.c @@ -1,12 +1,13 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include #include -#include #include #include #include #include +#include + #include #include "common.h" diff --git a/plugins/feat/feat-nvme.c b/plugins/feat/feat-nvme.c index 7f0f165b65..847fe39781 100644 --- a/plugins/feat/feat-nvme.c +++ b/plugins/feat/feat-nvme.c @@ -70,7 +70,7 @@ static int feat_get_nsid(struct libnvme_transport_handle *hdl, __u32 nsid, int err; __u32 len = 0; - __cleanup_free void *buf = NULL; + __cleanup_nvme_free void *buf = NULL; if (!NVME_CHECK(sel, GET_FEATURES_SEL, SUPPORTED)) libnvme_get_feature_length(fid, cdw11, NVME_DATA_TFR_CTRL_TO_HOST, &len); diff --git a/plugins/memblaze/memblaze-nvme.c b/plugins/memblaze/memblaze-nvme.c index 2ce7020e72..12e6a7685c 100644 --- a/plugins/memblaze/memblaze-nvme.c +++ b/plugins/memblaze/memblaze-nvme.c @@ -861,7 +861,7 @@ static int mb_selective_download(int argc, char **argv, struct command *acmd, st } out_free: - free(fw_buf); + aligned_free(fw_buf); out_close: close(fw_fd); out: diff --git a/plugins/micron/micron-nvme.c b/plugins/micron/micron-nvme.c index 9330b18e26..2158e29658 100644 --- a/plugins/micron/micron-nvme.c +++ b/plugins/micron/micron-nvme.c @@ -25,6 +25,8 @@ #include #include +#include + #include #include "common.h" @@ -684,7 +686,7 @@ static int micron_selective_download(int argc, char **argv, } out_free: - free(fw_buf); + aligned_free(fw_buf); out: close(fw_fd); return err; diff --git a/plugins/netapp/netapp-nvme.c b/plugins/netapp/netapp-nvme.c index 71eeb237bf..7e3d50227b 100644 --- a/plugins/netapp/netapp-nvme.c +++ b/plugins/netapp/netapp-nvme.c @@ -831,12 +831,12 @@ static int netapp_ontapdevices_get_info(struct libnvme_transport_handle *hdl, fprintf(stderr, "Unable to identify namespace descriptor for %s (%s)\n", dev, err < 0 ? libnvme_strerror(-err) : libnvme_status_to_string(err, false)); - free(nsdescs); + aligned_free(nsdescs); return 0; } memcpy(item->uuid, nsdescs + sizeof(struct nvme_ns_id_desc), sizeof(item->uuid)); - free(nsdescs); + aligned_free(nsdescs); err = nvme_get_ontap_c2_log(hdl, item->nsid, item->log_data, ONTAP_C2_LOG_SIZE); if (err) { diff --git a/plugins/ocp/ocp-nvme.c b/plugins/ocp/ocp-nvme.c index 0d30227ec2..655c229368 100644 --- a/plugins/ocp/ocp-nvme.c +++ b/plugins/ocp/ocp-nvme.c @@ -2629,7 +2629,7 @@ static int fw_activation_history_log(int argc, char **argv, struct command *acmd static int error_injection_get(struct libnvme_transport_handle *hdl, const __u8 sel, bool uuid, __u32 nsid) { - __cleanup_free struct erri_entry *entry = NULL; + __cleanup_nvme_free struct erri_entry *entry = NULL; struct erri_get_cq_entry cq_entry; const __u8 fid = OCP_FID_ERRI; __u64 result; @@ -2712,7 +2712,7 @@ static int get_error_injection(int argc, char **argv, struct command *acmd, stru static int error_injection_set(struct libnvme_transport_handle *hdl, struct erri_config *cfg, bool uuid, __u32 nsid) { - __cleanup_free struct erri_entry *entry = NULL; + __cleanup_nvme_free struct erri_entry *entry = NULL; __cleanup_fd int ffd = -1; __u32 data_len; __u8 uidx = 0; @@ -2935,7 +2935,7 @@ static int ocp_get_persistent_event_log(int argc, char **argv, "processing this persistent log page command."; const char *log_len = "number of bytes to retrieve"; - __cleanup_free struct nvme_persistent_event_log *pevent = NULL; + __cleanup_nvme_free struct nvme_persistent_event_log *pevent = NULL; struct nvme_persistent_event_log *pevent_collected = NULL; __cleanup_huge struct nvme_mem_huge mh = { 0, }; __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; diff --git a/plugins/shannon/shannon-nvme.c b/plugins/shannon/shannon-nvme.c index 54658e7743..4aa945c3b4 100644 --- a/plugins/shannon/shannon-nvme.c +++ b/plugins/shannon/shannon-nvme.c @@ -230,7 +230,7 @@ static int get_additional_feature(int argc, char **argv, struct command *acmd, s cfg.cdw11, 0, buf, cfg.data_len, &result); if (err > 0) nvme_show_status(err); - free(buf); + aligned_free(buf); return err; } @@ -255,7 +255,7 @@ static int set_additional_feature(int argc, char **argv, struct command *acmd, s const char *save = "specifies that the controller shall save the attribute"; __cleanup_nvme_global_ctx struct libnvme_global_ctx *ctx = NULL; __cleanup_nvme_transport_handle struct libnvme_transport_handle *hdl = NULL; - __cleanup_free void *buf = NULL; + __cleanup_nvme_free void *buf = NULL; int ffd = STDIN_FILENO; __u64 result; int err; diff --git a/plugins/solidigm/solidigm-internal-logs.c b/plugins/solidigm/solidigm-internal-logs.c index db2b230b1d..c4cdaea120 100644 --- a/plugins/solidigm/solidigm-internal-logs.c +++ b/plugins/solidigm/solidigm-internal-logs.c @@ -15,6 +15,8 @@ #include #include +#include + #include #include "common.h" @@ -776,7 +778,7 @@ static int ilog_dump_no_lsp_log_pages(struct libnvme_transport_handle *hdl, stru static int ilog_dump_pel(struct libnvme_transport_handle *hdl, struct ilog *ilog) { - __cleanup_free struct nvme_persistent_event_log *pevent = NULL; + __cleanup_nvme_free struct nvme_persistent_event_log *pevent = NULL; __cleanup_huge struct nvme_mem_huge mh = {0}; void *pevent_log_full; size_t max_data_tx; diff --git a/plugins/toshiba/toshiba-nvme.c b/plugins/toshiba/toshiba-nvme.c index 6b67609243..76a9979d66 100644 --- a/plugins/toshiba/toshiba-nvme.c +++ b/plugins/toshiba/toshiba-nvme.c @@ -110,7 +110,7 @@ static int nvme_get_sct_status(struct libnvme_transport_handle *hdl, __u32 devic } } end: - free(data); + aligned_free(data); return err; } @@ -134,7 +134,7 @@ static int nvme_sct_command_transfer_log(struct libnvme_transport_handle *hdl, b memcpy(data + 2, &function_code, sizeof(function_code)); err = nvme_sct_op(hdl, OP_SCT_COMMAND_TRANSFER, DW10_SCT_COMMAND_TRANSFER, DW11_SCT_COMMAND_TRANSFER, data, data_len); - free(data); + aligned_free(data); return err; } @@ -314,7 +314,7 @@ static int nvme_get_internal_log(struct libnvme_transport_handle *hdl, end: if (o_fd >= 0) close(o_fd); - free(page_data); + aligned_free(page_data); return err; } @@ -411,7 +411,7 @@ static int nvme_get_vendor_log(struct libnvme_transport_handle *hdl, d(log, log_len, 16, 1); } end: - free(log); + aligned_free(log); return err; } diff --git a/plugins/wdc/wdc-nvme.c b/plugins/wdc/wdc-nvme.c index 0cd20874d9..88d91755d1 100644 --- a/plugins/wdc/wdc-nvme.c +++ b/plugins/wdc/wdc-nvme.c @@ -31,6 +31,8 @@ #include #include +#include + #include #include "common.h" @@ -2873,7 +2875,7 @@ static bool wdc_nvme_check_supported_log_page(struct libnvme_global_ctx *ctx, int err = -1; struct wdc_c2_cbs_data *cbs_data = NULL; - __cleanup_free struct nvme_supported_log_pages *supports = NULL; + __cleanup_nvme_free struct nvme_supported_log_pages *supports = NULL; /* Check log page id 0 (supported log pages) first */ supports = nvme_alloc(sizeof(*supports)); diff --git a/plugins/wdc/wdc-utils.c b/plugins/wdc/wdc-utils.c index 81ace2dfc7..b52ce37373 100644 --- a/plugins/wdc/wdc-utils.c +++ b/plugins/wdc/wdc-utils.c @@ -25,6 +25,8 @@ #include #include +#include + #include #include "nvme-cmds.h" diff --git a/plugins/zns/zns.c b/plugins/zns/zns.c index c89fc0a299..ff97b292d7 100644 --- a/plugins/zns/zns.c +++ b/plugins/zns/zns.c @@ -426,7 +426,7 @@ static int zone_mgmt_send(int argc, char **argv, struct command *acmd, struct pl if (cfg.file) close(ffd); free: - free(buf); + aligned_free(buf); return err; } @@ -1076,12 +1076,12 @@ static int zone_append(int argc, char **argv, struct command *acmd, struct plugi perror("zns zone-append"); free_meta: - free(mbuf); + aligned_free(mbuf); close_mfd: if (cfg.metadata) close(mfd); free_data: - free(buf); + aligned_free(buf); close_dfd: if (cfg.data) close(dfd); diff --git a/util/cleanup.h b/util/cleanup.h index e2a70b03fa..ea1fe4d51f 100644 --- a/util/cleanup.h +++ b/util/cleanup.h @@ -27,6 +27,12 @@ static inline void freep(void *p) } #define __cleanup_free __cleanup(freep) +static inline void nvme_freep(void *p) +{ + nvme_free(*(void **)p); +} +#define __cleanup_nvme_free __cleanup(nvme_freep) + #define __cleanup_huge __cleanup(nvme_free_huge) static inline void cleanup_fd(int *fd) diff --git a/util/mem-linux.c b/util/mem-linux.c new file mode 100644 index 0000000000..143ff3f533 --- /dev/null +++ b/util/mem-linux.c @@ -0,0 +1,83 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +#include +#include +#include +#include +#include + +#include "mem.h" + +#include "common.h" + +#define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S)) +#define HUGE_MIN 0x80000 + +void *nvme_alloc_huge(size_t len, struct nvme_mem_huge *mh) +{ + memset(mh, 0, sizeof(*mh)); + + len = ROUND_UP(len, 0x1000); + + /* + * For smaller allocation we just use posix_memalign and hope the kernel + * is able to convert to a contiguous memory region. + */ + if (len < HUGE_MIN) { + mh->p = nvme_alloc(len); + if (!mh->p) + return NULL; + mh->posix_memalign = true; + mh->len = len; + return mh->p; + } + + /* + * Larger allocation will almost certainly fail with the small + * allocation approach. Instead try pre-allocating memory from the + * HugeTLB pool. + * + * https://www.kernel.org/doc/Documentation/vm/hugetlbpage.txt + */ + mh->p = mmap(NULL, len, PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_PRIVATE | MAP_HUGETLB, -1, 0); + if (mh->p != MAP_FAILED) { + mh->len = len; + return mh->p; + } + + /* + * And if mmap fails because the pool is empty, try to use + * posix_memalign/madvise as fallback with a 2MB aligmnent in order to + * fullfil the request. This gives the kernel a chance to try to claim + * some huge pages. This might still fail though. + */ + len = ROUND_UP(len, 0x200000); + if (posix_memalign(&mh->p, 0x200000, len)) + return NULL; + mh->posix_memalign = true; + mh->len = len; + + memset(mh->p, 0, mh->len); + + if (madvise(mh->p, mh->len, MADV_HUGEPAGE) < 0) { + nvme_free_huge(mh); + return NULL; + } + + return mh->p; +} + +void nvme_free_huge(struct nvme_mem_huge *mh) + +{ + if (!mh || mh->len == 0) + return; + + if (mh->posix_memalign) + nvme_free(mh->p); + else + munmap(mh->p, mh->len); + + mh->len = 0; + mh->p = NULL; +} diff --git a/util/mem-windows.c b/util/mem-windows.c new file mode 100644 index 0000000000..2d9678d249 --- /dev/null +++ b/util/mem-windows.c @@ -0,0 +1,100 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +/* + * This file is part of libnvme. + * Copyright (c) 2026 Micron Technology, Inc. + * + * Authors: Brandon Capener + */ + +#include +#include + +#include + +#include +#include + +#include "mem.h" +#include "common.h" + +#define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S)) +#define HUGE_MIN 0x80000 /* policy threshold when large pages unavailable */ + +void *nvme_alloc_huge(size_t len, struct nvme_mem_huge *mh) +{ + SIZE_T large_min = GetLargePageMinimum(); /* 0 if unsupported/unavailable */ + SIZE_T huge_min = large_min ? large_min : HUGE_MIN; + SIZE_T page_size = getpagesize(); + SIZE_T align; + + memset(mh, 0, sizeof(*mh)); + + len = ROUND_UP(len, page_size); + + /* + * For smaller allocations, use regular allocator. + */ + if (len < huge_min) { + mh->p = nvme_alloc(len); + if (!mh->p) + return NULL; + mh->posix_memalign = true; + mh->len = len; + return mh->p; + } + + /* + * Try large pages first when available. + * Requires SeLockMemoryPrivilege and size multiple of large_min. + */ + if (large_min) { + SIZE_T lp_len = ROUND_UP(len, large_min); + + mh->p = VirtualAlloc(NULL, lp_len, + MEM_COMMIT | MEM_RESERVE | MEM_LARGE_PAGES, + PAGE_READWRITE); + if (mh->p != NULL) { + mh->len = lp_len; + mh->posix_memalign = false; + return mh->p; + } + } + + /* + * Fallback to regular VirtualAlloc. + */ + mh->p = VirtualAlloc(NULL, len, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); + if (mh->p != NULL) { + mh->len = len; + mh->posix_memalign = false; + return mh->p; + } + + /* + * Final fallback: aligned heap allocation. + * Prefer large page size if known, otherwise page size. + */ + align = large_min ? large_min : page_size; + len = ROUND_UP(len, align); + if (posix_memalign(&mh->p, align, len)) + return NULL; + + mh->posix_memalign = true; + mh->len = len; + memset(mh->p, 0, mh->len); + return mh->p; +} + +void nvme_free_huge(struct nvme_mem_huge *mh) +{ + if (!mh || mh->len == 0) + return; + + if (mh->posix_memalign) + nvme_free(mh->p); + else + VirtualFree(mh->p, 0, MEM_RELEASE); + + mh->len = 0; + mh->p = NULL; +} diff --git a/util/mem.c b/util/mem.c index 2b97632d82..db0673a71e 100644 --- a/util/mem.c +++ b/util/mem.c @@ -1,16 +1,15 @@ /* SPDX-License-Identifier: GPL-2.0-or-later */ -#include -#include -#include #include -#include + +#include +#include +#include #include "mem.h" #include "common.h" #define ROUND_UP(N, S) ((((N) + (S) - 1) / (S)) * (S)) -#define HUGE_MIN 0x80000 void *nvme_alloc(size_t len) { @@ -34,78 +33,13 @@ void *nvme_realloc(void *p, size_t len) if (p) { memcpy(result, p, min(old_len, len)); - free(p); + nvme_free(p); } return result; } -void *nvme_alloc_huge(size_t len, struct nvme_mem_huge *mh) -{ - memset(mh, 0, sizeof(*mh)); - - len = ROUND_UP(len, 0x1000); - - /* - * For smaller allocation we just use posix_memalign and hope the kernel - * is able to convert to a contiguous memory region. - */ - if (len < HUGE_MIN) { - mh->p = nvme_alloc(len); - if (!mh->p) - return NULL; - mh->posix_memalign = true; - mh->len = len; - return mh->p; - } - - /* - * Larger allocation will almost certainly fail with the small - * allocation approach. Instead try pre-allocating memory from the - * HugeTLB pool. - * - * https://www.kernel.org/doc/Documentation/vm/hugetlbpage.txt - */ - mh->p = mmap(NULL, len, PROT_READ | PROT_WRITE, - MAP_ANONYMOUS | MAP_PRIVATE | MAP_HUGETLB, -1, 0); - if (mh->p != MAP_FAILED) { - mh->len = len; - return mh->p; - } - - /* - * And if mmap fails because the pool is empty, try to use - * posix_memalign/madvise as fallback with a 2MB aligmnent in order to - * fullfil the request. This gives the kernel a chance to try to claim - * some huge pages. This might still fail though. - */ - len = ROUND_UP(len, 0x200000); - if (posix_memalign(&mh->p, 0x200000, len)) - return NULL; - mh->posix_memalign = true; - mh->len = len; - - memset(mh->p, 0, mh->len); - - if (madvise(mh->p, mh->len, MADV_HUGEPAGE) < 0) { - nvme_free_huge(mh); - return NULL; - } - - return mh->p; -} - -void nvme_free_huge(struct nvme_mem_huge *mh) - +void nvme_free(void *p) { - if (!mh || mh->len == 0) - return; - - if (mh->posix_memalign) - free(mh->p); - else - munmap(mh->p, mh->len); - - mh->len = 0; - mh->p = NULL; + aligned_free(p); } diff --git a/util/mem.h b/util/mem.h index d13eb3a213..a792457cbc 100644 --- a/util/mem.h +++ b/util/mem.h @@ -7,6 +7,7 @@ void *nvme_alloc(size_t len); void *nvme_realloc(void *p, size_t len); +void nvme_free(void *p); struct nvme_mem_huge { size_t len; diff --git a/util/meson.build b/util/meson.build index 42412705d2..30757fc1f9 100644 --- a/util/meson.build +++ b/util/meson.build @@ -1,15 +1,19 @@ # SPDX-License-Identifier: GPL-2.0-or-later -util_sources = [] +util_sources = [ + 'util/mem.c' +] if host_system == 'windows' - util_sources += [] + util_sources += [ + 'util/mem-windows.c' + ] else util_sources += [ 'util/argconfig.c', 'util/base64.c', 'util/crc32.c', - 'util/mem.c', + 'util/mem-linux.c', 'util/sighdl.c', 'util/suffix.c', 'util/types.c', diff --git a/util/sighdl.c b/util/sighdl.c index 146591e5df..5e966da4b7 100644 --- a/util/sighdl.c +++ b/util/sighdl.c @@ -1,8 +1,9 @@ // SPDX-License-Identifier: GPL-2.0-or-later -#include #include #include +#include + #include "sighdl.h" bool nvme_sigint_received; diff --git a/util/table.c b/util/table.c index 76366b93da..f3bf91ecb8 100644 --- a/util/table.c +++ b/util/table.c @@ -16,10 +16,11 @@ */ #include -#include #include #include +#include + #include "table.h" static int table_get_value_width(struct value *v)