Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sysfs: minimize heap allocations of sysfs paths #797

Merged
merged 1 commit into from
Mar 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ sources = [
'nvme/ioctl.c',
'nvme/linux.c',
'nvme/log.c',
'nvme/sysfs.c',
'nvme/tree.c',
'nvme/util.c',
'nvme/base64.c',
Expand Down
37 changes: 2 additions & 35 deletions src/nvme/fabrics.c
Original file line number Diff line number Diff line change
Expand Up @@ -1186,29 +1186,12 @@ struct nvmf_discovery_log *nvmf_get_discovery_wargs(struct nvme_get_discovery_ar
return log;
}

#define PATH_UUID_IBM "/proc/device-tree/ibm,partition-uuid"

static char *uuid_ibm_filename(void)
{
char *basepath = getenv("LIBNVME_SYSFS_PATH");
char *str;

if (!basepath)
return strdup(PATH_UUID_IBM);

if (!asprintf(&str, "%s" PATH_UUID_IBM, basepath))
return NULL;

return str;
}

static int uuid_from_device_tree(char *system_uuid)
{
_cleanup_free_ char *filename = uuid_ibm_filename();
_cleanup_fd_ int f = -1;
ssize_t len;

f = open(filename, O_RDONLY);
f = open(nvme_uuid_ibm_filename(), O_RDONLY);
if (f < 0)
return -ENXIO;

Expand All @@ -1220,22 +1203,6 @@ static int uuid_from_device_tree(char *system_uuid)
return strlen(system_uuid) ? 0 : -ENXIO;
}

#define PATH_DMI_ENTRIES "/sys/firmware/dmi/entries"

static char *dmi_entries_dir(void)
{
char *basepath = getenv("LIBNVME_SYSFS_PATH");
char *str;

if (!basepath)
return strdup(PATH_DMI_ENTRIES);

if (!asprintf(&str, "%s" PATH_DMI_ENTRIES, basepath))
return NULL;

return str;
}

/*
* See System Management BIOS (SMBIOS) Reference Specification
* https://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.2.0.pdf
Expand Down Expand Up @@ -1264,7 +1231,7 @@ static bool is_dmi_uuid_valid(const char *buf, size_t len)
static int uuid_from_dmi_entries(char *system_uuid)
{
_cleanup_dir_ DIR *d = NULL;
_cleanup_free_ char *entries_dir = dmi_entries_dir();
const char *entries_dir = nvme_dmi_entries_dir();
int f;
struct dirent *de;
char buf[512] = {0};
Expand Down
62 changes: 3 additions & 59 deletions src/nvme/filters.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,68 +6,12 @@
* Authors: Keith Busch <keith.busch@wdc.com>
* Chaitanya Kulkarni <chaitanya.kulkarni@wdc.com>
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <dirent.h>
#include <libgen.h>

#include <sys/param.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>

#include "filters.h"
#include "types.h"
#include "util.h"
#include "cleanup.h"

#define PATH_SYSFS_NVME "/sys/class/nvme"
#define PATH_SYSFS_NVME_SUBSYSTEM "/sys/class/nvme-subsystem"
#define PATH_SYSFS_BLOCK "/sys/block"

char *nvme_ctrl_sysfs_dir(void)
{
char *basepath = getenv("LIBNVME_SYSFS_PATH");
char *str;

if (!basepath)
return strdup(PATH_SYSFS_NVME);

if (!asprintf(&str, "%s" PATH_SYSFS_NVME, basepath))
return NULL;

return str;
}

char *nvme_ns_sysfs_dir(void)
{
char *basepath = getenv("LIBNVME_SYSFS_PATH");
char *str;

if (!basepath)
return strdup(PATH_SYSFS_BLOCK);

if (!asprintf(&str, "%s" PATH_SYSFS_BLOCK, basepath))
return NULL;

return str;
}

char *nvme_subsys_sysfs_dir(void)
{
char *basepath = getenv("LIBNVME_SYSFS_PATH");
char *str;

if (!basepath)
return strdup(PATH_SYSFS_NVME_SUBSYSTEM);

if (!asprintf(&str, "%s" PATH_SYSFS_NVME_SUBSYSTEM, basepath))
return NULL;

return str;
}
#include "private.h"

int nvme_namespace_filter(const struct dirent *d)
{
Expand Down Expand Up @@ -132,7 +76,7 @@ int nvme_subsys_filter(const struct dirent *d)

int nvme_scan_subsystems(struct dirent ***subsys)
{
_cleanup_free_ char *dir = nvme_subsys_sysfs_dir();
const char *dir = nvme_subsys_sysfs_dir();

return scandir(dir, subsys, nvme_subsys_filter, alphasort);
}
Expand All @@ -145,7 +89,7 @@ int nvme_scan_subsystem_namespaces(nvme_subsystem_t s, struct dirent ***ns)

int nvme_scan_ctrls(struct dirent ***ctrls)
{
_cleanup_free_ char *dir = nvme_ctrl_sysfs_dir();
const char *dir = nvme_ctrl_sysfs_dir();

return scandir(dir, ctrls, nvme_ctrls_filter, alphasort);
}
Expand Down
9 changes: 6 additions & 3 deletions src/nvme/private.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,12 @@
#include "mi.h"


char *nvme_ctrl_sysfs_dir(void);
char *nvme_subsys_sysfs_dir(void);
char *nvme_ns_sysfs_dir(void);
const char *nvme_subsys_sysfs_dir(void);
const char *nvme_ctrl_sysfs_dir(void);
const char *nvme_ns_sysfs_dir(void);
const char *nvme_slots_sysfs_dir(void);
const char *nvme_uuid_ibm_filename(void);
const char *nvme_dmi_entries_dir(void);

struct nvme_path {
struct list_node entry;
Expand Down
86 changes: 86 additions & 0 deletions src/nvme/sysfs.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
#include <stdio.h>
#include <stdlib.h>

#include "private.h"

#define PATH_UUID_IBM "/proc/device-tree/ibm,partition-uuid"
#define PATH_SYSFS_BLOCK "/sys/block"
#define PATH_SYSFS_SLOTS "/sys/bus/pci/slots"
#define PATH_SYSFS_NVME_SUBSYSTEM "/sys/class/nvme-subsystem"
#define PATH_SYSFS_NVME "/sys/class/nvme"
#define PATH_DMI_ENTRIES "/sys/firmware/dmi/entries"

static const char *make_sysfs_dir(const char *path)
{
char *basepath = getenv("LIBNVME_SYSFS_PATH");
char *str;

if (!basepath)
return path;

if (asprintf(&str, "%s%s", basepath, path) < 0)
return NULL;

return str;
}

const char *nvme_subsys_sysfs_dir(void)
{
static const char *str;

if (str)
return str;

return str = make_sysfs_dir(PATH_SYSFS_NVME_SUBSYSTEM);
}

const char *nvme_ctrl_sysfs_dir(void)
{
static const char *str;

if (str)
return str;

return str = make_sysfs_dir(PATH_SYSFS_NVME);
}

const char *nvme_ns_sysfs_dir(void)
{
static const char *str;

if (str)
return str;

return str = make_sysfs_dir(PATH_SYSFS_BLOCK);
}

const char *nvme_slots_sysfs_dir(void)
{
static const char *str;

if (str)
return str;

return str = make_sysfs_dir(PATH_SYSFS_SLOTS);
}

const char *nvme_uuid_ibm_filename(void)
{
static const char *str;

if (str)
return str;

return str = make_sysfs_dir(PATH_UUID_IBM);
}

const char *nvme_dmi_entries_dir(void)
{
static const char *str;

if (str)
return str;

return str = make_sysfs_dir(PATH_DMI_ENTRIES);
}
36 changes: 7 additions & 29 deletions src/nvme/tree.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,22 +61,6 @@ struct candidate_args {
};
typedef bool (*ctrl_match_t)(struct nvme_ctrl *c, struct candidate_args *candidate);

#define PATH_SYSFS_SLOTS "/sys/bus/pci/slots"

static char *nvme_slots_sysfs_dir(void)
{
char *basepath = getenv("LIBNVME_SYSFS_PATH");
char *str;

if (!basepath)
return strdup(PATH_SYSFS_SLOTS);

if (!asprintf(&str, "%s" PATH_SYSFS_SLOTS, basepath))
return NULL;

return str;
}

static struct nvme_host *default_host;

static void __nvme_free_host(nvme_host_t h);
Expand Down Expand Up @@ -672,10 +656,9 @@ static int nvme_subsystem_scan_namespaces(nvme_root_t r, nvme_subsystem_t s,

static int nvme_init_subsystem(nvme_subsystem_t s, const char *name)
{
_cleanup_free_ char *subsys_dir = nvme_subsys_sysfs_dir();
char *path;

if (asprintf(&path, "%s/%s", subsys_dir, name) < 0)
if (asprintf(&path, "%s/%s", nvme_subsys_sysfs_dir(), name) < 0)
return -1;

s->model = nvme_get_attr(path, "model");
Expand Down Expand Up @@ -716,12 +699,11 @@ static int nvme_scan_subsystem(struct nvme_root *r, const char *name,
{
struct nvme_subsystem *s = NULL, *_s;
_cleanup_free_ char *path = NULL, *subsysnqn = NULL;
_cleanup_free_ char *subsys_dir = nvme_subsys_sysfs_dir();
nvme_host_t h = NULL;
int ret;

nvme_msg(r, LOG_DEBUG, "scan subsystem %s\n", name);
ret = asprintf(&path, "%s/%s", subsys_dir, name);
ret = asprintf(&path, "%s/%s", nvme_subsys_sysfs_dir(), name);
if (ret < 0)
return ret;

Expand Down Expand Up @@ -1703,7 +1685,7 @@ static int nvme_ctrl_scan_namespaces(nvme_root_t r, struct nvme_ctrl *c)
static char *nvme_ctrl_lookup_subsystem_name(nvme_root_t r,
const char *ctrl_name)
{
_cleanup_free_ char *subsys_dir = nvme_subsys_sysfs_dir();
const char *subsys_dir = nvme_subsys_sysfs_dir();
_cleanup_dirents_ struct dirents subsys = {};
int i;

Expand All @@ -1730,7 +1712,7 @@ static char *nvme_ctrl_lookup_subsystem_name(nvme_root_t r,

static char *nvme_ctrl_lookup_phy_slot(nvme_root_t r, const char *address)
{
_cleanup_free_ char *slots_sysfs_dir = nvme_slots_sysfs_dir();
const char *slots_sysfs_dir = nvme_slots_sysfs_dir();
_cleanup_free_ char *target_addr = NULL;
_cleanup_dir_ DIR *slots_dir = NULL;
int ret;
Expand Down Expand Up @@ -1827,7 +1809,6 @@ static int nvme_configure_ctrl(nvme_root_t r, nvme_ctrl_t c, const char *path,

int nvme_init_ctrl(nvme_host_t h, nvme_ctrl_t c, int instance)
{
_cleanup_free_ char *ctrl_dir = nvme_ctrl_sysfs_dir();
_cleanup_free_ char *subsys_name = NULL;
_cleanup_free_ char *name = NULL;
nvme_subsystem_t s;
Expand All @@ -1839,7 +1820,7 @@ int nvme_init_ctrl(nvme_host_t h, nvme_ctrl_t c, int instance)
errno = ENOMEM;
return -1;
}
ret = asprintf(&path, "%s/nvme%d", ctrl_dir, instance);
ret = asprintf(&path, "%s/%s", nvme_ctrl_sysfs_dir(), name);
if (ret < 0) {
errno = ENOMEM;
return ret;
Expand Down Expand Up @@ -1983,11 +1964,10 @@ nvme_ctrl_t nvme_scan_ctrl(nvme_root_t r, const char *name)
_cleanup_free_ char *path = NULL;
_cleanup_free_ char *hostnqn = NULL, *hostid = NULL;
_cleanup_free_ char *subsysnqn = NULL, *subsysname = NULL;
_cleanup_free_ char *ctrl_dir = nvme_ctrl_sysfs_dir();
int ret;

nvme_msg(r, LOG_DEBUG, "scan controller %s\n", name);
ret = asprintf(&path, "%s/%s", ctrl_dir, name);
ret = asprintf(&path, "%s/%s", nvme_ctrl_sysfs_dir(), name);
if (ret < 0) {
errno = ENOMEM;
return NULL;
Expand Down Expand Up @@ -2615,9 +2595,7 @@ static struct nvme_ns *__nvme_scan_namespace(const char *sysfs_dir, const char *

nvme_ns_t nvme_scan_namespace(const char *name)
{
_cleanup_free_ char *ns_dir = nvme_ns_sysfs_dir();

return __nvme_scan_namespace(ns_dir, name);
return __nvme_scan_namespace(nvme_ns_sysfs_dir(), name);
}

static int nvme_ctrl_scan_namespace(nvme_root_t r, struct nvme_ctrl *c,
Expand Down