Skip to content

Commit eb4f794

Browse files
calebsanderigaw
authored andcommitted
sysfs: minimize heap allocations of sysfs paths
11a0918 ("nvme: allow to overwrite base sysfs path") added support for changing the sysfs path via an environment variable. Unfortunately, it added a heap allocation every time a sysfs path was requested. Modify the callers to not free the paths, which allows a string constant to be returned if the path isn't overridden, avoiding an allocation. Cache the path in a static variable so that if it is overridden, the heap-allocated string only needs to be constructed once and afterwards can be reused. Create a file sysfs.c to consolidate this logic instead of spreading them across 3 files. Also introduce a helper to factor out the duplicated code. Fixes: 11a0918 ("nvme: allow to overwrite base sysfs path") Signed-off-by: Caleb Sander Mateos <[email protected]>
1 parent c2f23b3 commit eb4f794

6 files changed

Lines changed: 105 additions & 126 deletions

File tree

src/meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ sources = [
1212
'nvme/ioctl.c',
1313
'nvme/linux.c',
1414
'nvme/log.c',
15+
'nvme/sysfs.c',
1516
'nvme/tree.c',
1617
'nvme/util.c',
1718
'nvme/base64.c',

src/nvme/fabrics.c

Lines changed: 2 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1186,29 +1186,12 @@ struct nvmf_discovery_log *nvmf_get_discovery_wargs(struct nvme_get_discovery_ar
11861186
return log;
11871187
}
11881188

1189-
#define PATH_UUID_IBM "/proc/device-tree/ibm,partition-uuid"
1190-
1191-
static char *uuid_ibm_filename(void)
1192-
{
1193-
char *basepath = getenv("LIBNVME_SYSFS_PATH");
1194-
char *str;
1195-
1196-
if (!basepath)
1197-
return strdup(PATH_UUID_IBM);
1198-
1199-
if (!asprintf(&str, "%s" PATH_UUID_IBM, basepath))
1200-
return NULL;
1201-
1202-
return str;
1203-
}
1204-
12051189
static int uuid_from_device_tree(char *system_uuid)
12061190
{
1207-
_cleanup_free_ char *filename = uuid_ibm_filename();
12081191
_cleanup_fd_ int f = -1;
12091192
ssize_t len;
12101193

1211-
f = open(filename, O_RDONLY);
1194+
f = open(nvme_uuid_ibm_filename(), O_RDONLY);
12121195
if (f < 0)
12131196
return -ENXIO;
12141197

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

1223-
#define PATH_DMI_ENTRIES "/sys/firmware/dmi/entries"
1224-
1225-
static char *dmi_entries_dir(void)
1226-
{
1227-
char *basepath = getenv("LIBNVME_SYSFS_PATH");
1228-
char *str;
1229-
1230-
if (!basepath)
1231-
return strdup(PATH_DMI_ENTRIES);
1232-
1233-
if (!asprintf(&str, "%s" PATH_DMI_ENTRIES, basepath))
1234-
return NULL;
1235-
1236-
return str;
1237-
}
1238-
12391206
/*
12401207
* See System Management BIOS (SMBIOS) Reference Specification
12411208
* https://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.2.0.pdf
@@ -1264,7 +1231,7 @@ static bool is_dmi_uuid_valid(const char *buf, size_t len)
12641231
static int uuid_from_dmi_entries(char *system_uuid)
12651232
{
12661233
_cleanup_dir_ DIR *d = NULL;
1267-
_cleanup_free_ char *entries_dir = dmi_entries_dir();
1234+
const char *entries_dir = nvme_dmi_entries_dir();
12681235
int f;
12691236
struct dirent *de;
12701237
char buf[512] = {0};

src/nvme/filters.c

Lines changed: 3 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -6,68 +6,12 @@
66
* Authors: Keith Busch <[email protected]>
77
* Chaitanya Kulkarni <[email protected]>
88
*/
9-
#include <stdlib.h>
109
#include <stdio.h>
1110
#include <string.h>
1211
#include <dirent.h>
13-
#include <libgen.h>
14-
15-
#include <sys/param.h>
16-
#include <sys/stat.h>
17-
#include <sys/types.h>
18-
#include <fcntl.h>
19-
#include <unistd.h>
2012

2113
#include "filters.h"
22-
#include "types.h"
23-
#include "util.h"
24-
#include "cleanup.h"
25-
26-
#define PATH_SYSFS_NVME "/sys/class/nvme"
27-
#define PATH_SYSFS_NVME_SUBSYSTEM "/sys/class/nvme-subsystem"
28-
#define PATH_SYSFS_BLOCK "/sys/block"
29-
30-
char *nvme_ctrl_sysfs_dir(void)
31-
{
32-
char *basepath = getenv("LIBNVME_SYSFS_PATH");
33-
char *str;
34-
35-
if (!basepath)
36-
return strdup(PATH_SYSFS_NVME);
37-
38-
if (!asprintf(&str, "%s" PATH_SYSFS_NVME, basepath))
39-
return NULL;
40-
41-
return str;
42-
}
43-
44-
char *nvme_ns_sysfs_dir(void)
45-
{
46-
char *basepath = getenv("LIBNVME_SYSFS_PATH");
47-
char *str;
48-
49-
if (!basepath)
50-
return strdup(PATH_SYSFS_BLOCK);
51-
52-
if (!asprintf(&str, "%s" PATH_SYSFS_BLOCK, basepath))
53-
return NULL;
54-
55-
return str;
56-
}
57-
58-
char *nvme_subsys_sysfs_dir(void)
59-
{
60-
char *basepath = getenv("LIBNVME_SYSFS_PATH");
61-
char *str;
62-
63-
if (!basepath)
64-
return strdup(PATH_SYSFS_NVME_SUBSYSTEM);
65-
66-
if (!asprintf(&str, "%s" PATH_SYSFS_NVME_SUBSYSTEM, basepath))
67-
return NULL;
68-
69-
return str;
70-
}
14+
#include "private.h"
7115

7216
int nvme_namespace_filter(const struct dirent *d)
7317
{
@@ -132,7 +76,7 @@ int nvme_subsys_filter(const struct dirent *d)
13276

13377
int nvme_scan_subsystems(struct dirent ***subsys)
13478
{
135-
_cleanup_free_ char *dir = nvme_subsys_sysfs_dir();
79+
const char *dir = nvme_subsys_sysfs_dir();
13680

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

14690
int nvme_scan_ctrls(struct dirent ***ctrls)
14791
{
148-
_cleanup_free_ char *dir = nvme_ctrl_sysfs_dir();
92+
const char *dir = nvme_ctrl_sysfs_dir();
14993

15094
return scandir(dir, ctrls, nvme_ctrls_filter, alphasort);
15195
}

src/nvme/private.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,12 @@
1717
#include "mi.h"
1818

1919

20-
char *nvme_ctrl_sysfs_dir(void);
21-
char *nvme_subsys_sysfs_dir(void);
22-
char *nvme_ns_sysfs_dir(void);
20+
const char *nvme_subsys_sysfs_dir(void);
21+
const char *nvme_ctrl_sysfs_dir(void);
22+
const char *nvme_ns_sysfs_dir(void);
23+
const char *nvme_slots_sysfs_dir(void);
24+
const char *nvme_uuid_ibm_filename(void);
25+
const char *nvme_dmi_entries_dir(void);
2326

2427
struct nvme_path {
2528
struct list_node entry;

src/nvme/sysfs.c

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
// SPDX-License-Identifier: LGPL-2.1-or-later
2+
#include <stdio.h>
3+
#include <stdlib.h>
4+
5+
#include "private.h"
6+
7+
#define PATH_UUID_IBM "/proc/device-tree/ibm,partition-uuid"
8+
#define PATH_SYSFS_BLOCK "/sys/block"
9+
#define PATH_SYSFS_SLOTS "/sys/bus/pci/slots"
10+
#define PATH_SYSFS_NVME_SUBSYSTEM "/sys/class/nvme-subsystem"
11+
#define PATH_SYSFS_NVME "/sys/class/nvme"
12+
#define PATH_DMI_ENTRIES "/sys/firmware/dmi/entries"
13+
14+
static const char *make_sysfs_dir(const char *path)
15+
{
16+
char *basepath = getenv("LIBNVME_SYSFS_PATH");
17+
char *str;
18+
19+
if (!basepath)
20+
return path;
21+
22+
if (asprintf(&str, "%s%s", basepath, path) < 0)
23+
return NULL;
24+
25+
return str;
26+
}
27+
28+
const char *nvme_subsys_sysfs_dir(void)
29+
{
30+
static const char *str;
31+
32+
if (str)
33+
return str;
34+
35+
return str = make_sysfs_dir(PATH_SYSFS_NVME_SUBSYSTEM);
36+
}
37+
38+
const char *nvme_ctrl_sysfs_dir(void)
39+
{
40+
static const char *str;
41+
42+
if (str)
43+
return str;
44+
45+
return str = make_sysfs_dir(PATH_SYSFS_NVME);
46+
}
47+
48+
const char *nvme_ns_sysfs_dir(void)
49+
{
50+
static const char *str;
51+
52+
if (str)
53+
return str;
54+
55+
return str = make_sysfs_dir(PATH_SYSFS_BLOCK);
56+
}
57+
58+
const char *nvme_slots_sysfs_dir(void)
59+
{
60+
static const char *str;
61+
62+
if (str)
63+
return str;
64+
65+
return str = make_sysfs_dir(PATH_SYSFS_SLOTS);
66+
}
67+
68+
const char *nvme_uuid_ibm_filename(void)
69+
{
70+
static const char *str;
71+
72+
if (str)
73+
return str;
74+
75+
return str = make_sysfs_dir(PATH_UUID_IBM);
76+
}
77+
78+
const char *nvme_dmi_entries_dir(void)
79+
{
80+
static const char *str;
81+
82+
if (str)
83+
return str;
84+
85+
return str = make_sysfs_dir(PATH_DMI_ENTRIES);
86+
}

src/nvme/tree.c

Lines changed: 7 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -61,22 +61,6 @@ struct candidate_args {
6161
};
6262
typedef bool (*ctrl_match_t)(struct nvme_ctrl *c, struct candidate_args *candidate);
6363

64-
#define PATH_SYSFS_SLOTS "/sys/bus/pci/slots"
65-
66-
static char *nvme_slots_sysfs_dir(void)
67-
{
68-
char *basepath = getenv("LIBNVME_SYSFS_PATH");
69-
char *str;
70-
71-
if (!basepath)
72-
return strdup(PATH_SYSFS_SLOTS);
73-
74-
if (!asprintf(&str, "%s" PATH_SYSFS_SLOTS, basepath))
75-
return NULL;
76-
77-
return str;
78-
}
79-
8064
static struct nvme_host *default_host;
8165

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

673657
static int nvme_init_subsystem(nvme_subsystem_t s, const char *name)
674658
{
675-
_cleanup_free_ char *subsys_dir = nvme_subsys_sysfs_dir();
676659
char *path;
677660

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

681664
s->model = nvme_get_attr(path, "model");
@@ -716,12 +699,11 @@ static int nvme_scan_subsystem(struct nvme_root *r, const char *name,
716699
{
717700
struct nvme_subsystem *s = NULL, *_s;
718701
_cleanup_free_ char *path = NULL, *subsysnqn = NULL;
719-
_cleanup_free_ char *subsys_dir = nvme_subsys_sysfs_dir();
720702
nvme_host_t h = NULL;
721703
int ret;
722704

723705
nvme_msg(r, LOG_DEBUG, "scan subsystem %s\n", name);
724-
ret = asprintf(&path, "%s/%s", subsys_dir, name);
706+
ret = asprintf(&path, "%s/%s", nvme_subsys_sysfs_dir(), name);
725707
if (ret < 0)
726708
return ret;
727709

@@ -1703,7 +1685,7 @@ static int nvme_ctrl_scan_namespaces(nvme_root_t r, struct nvme_ctrl *c)
17031685
static char *nvme_ctrl_lookup_subsystem_name(nvme_root_t r,
17041686
const char *ctrl_name)
17051687
{
1706-
_cleanup_free_ char *subsys_dir = nvme_subsys_sysfs_dir();
1688+
const char *subsys_dir = nvme_subsys_sysfs_dir();
17071689
_cleanup_dirents_ struct dirents subsys = {};
17081690
int i;
17091691

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

17311713
static char *nvme_ctrl_lookup_phy_slot(nvme_root_t r, const char *address)
17321714
{
1733-
_cleanup_free_ char *slots_sysfs_dir = nvme_slots_sysfs_dir();
1715+
const char *slots_sysfs_dir = nvme_slots_sysfs_dir();
17341716
_cleanup_free_ char *target_addr = NULL;
17351717
_cleanup_dir_ DIR *slots_dir = NULL;
17361718
int ret;
@@ -1827,7 +1809,6 @@ static int nvme_configure_ctrl(nvme_root_t r, nvme_ctrl_t c, const char *path,
18271809

18281810
int nvme_init_ctrl(nvme_host_t h, nvme_ctrl_t c, int instance)
18291811
{
1830-
_cleanup_free_ char *ctrl_dir = nvme_ctrl_sysfs_dir();
18311812
_cleanup_free_ char *subsys_name = NULL;
18321813
_cleanup_free_ char *name = NULL;
18331814
nvme_subsystem_t s;
@@ -1839,7 +1820,7 @@ int nvme_init_ctrl(nvme_host_t h, nvme_ctrl_t c, int instance)
18391820
errno = ENOMEM;
18401821
return -1;
18411822
}
1842-
ret = asprintf(&path, "%s/nvme%d", ctrl_dir, instance);
1823+
ret = asprintf(&path, "%s/%s", nvme_ctrl_sysfs_dir(), name);
18431824
if (ret < 0) {
18441825
errno = ENOMEM;
18451826
return ret;
@@ -1983,11 +1964,10 @@ nvme_ctrl_t nvme_scan_ctrl(nvme_root_t r, const char *name)
19831964
_cleanup_free_ char *path = NULL;
19841965
_cleanup_free_ char *hostnqn = NULL, *hostid = NULL;
19851966
_cleanup_free_ char *subsysnqn = NULL, *subsysname = NULL;
1986-
_cleanup_free_ char *ctrl_dir = nvme_ctrl_sysfs_dir();
19871967
int ret;
19881968

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

26162596
nvme_ns_t nvme_scan_namespace(const char *name)
26172597
{
2618-
_cleanup_free_ char *ns_dir = nvme_ns_sysfs_dir();
2619-
2620-
return __nvme_scan_namespace(ns_dir, name);
2598+
return __nvme_scan_namespace(nvme_ns_sysfs_dir(), name);
26212599
}
26222600

26232601
static int nvme_ctrl_scan_namespace(nvme_root_t r, struct nvme_ctrl *c,

0 commit comments

Comments
 (0)