Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf tools: Add kmod_path__parse function

Provides united way of parsing kernel module path
into several components.

The new kmod_path__parse function and few defines:

int __kmod_path__parse(struct kmod_path *m, const char *path,
bool alloc_name, bool alloc_ext);

#define kmod_path__parse(__m, __p) __kmod_path__parse(__m, __p, false, false)
#define kmod_path__parse_name(__m, __p) __kmod_path__parse(__m, __p, true , false)
#define kmod_path__parse_ext(__m, __p) __kmod_path__parse(__m, __p, false, true)

parse kernel module @path and updates @m argument like:

@comp - true if @path contains supported compression suffix,
false otherwise
@kmod - true if @path contains '.ko' suffix in right position,
false otherwise
@name - if (@alloc_name && @kmod) is true, it contains strdup-ed base name
of the kernel module without suffixes, otherwise strudup-ed
base name of @path
@ext - if (@alloc_ext && @comp) is true, it contains strdup-ed string
the compression suffix

It returns 0 if there's no strdup error, -ENOMEM otherwise.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Acked-by: Namhyung Kim <namhyung@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-9t6eqg8j610r94l743hkntiv@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Jiri Olsa and committed by
Arnaldo Carvalho de Melo
3c8a67f5 80a32e5b

+159
+1
tools/perf/tests/Build
··· 30 30 perf-y += code-reading.o 31 31 perf-y += sample-parsing.o 32 32 perf-y += parse-no-sample-id-all.o 33 + perf-y += kmod-path.o 33 34 34 35 perf-$(CONFIG_X86) += perf-time-to-tsc.o 35 36
+4
tools/perf/tests/builtin-test.c
··· 167 167 .func = test__fdarray__add, 168 168 }, 169 169 { 170 + .desc = "Test kmod_path__parse function", 171 + .func = test__kmod_path__parse, 172 + }, 173 + { 170 174 .func = NULL, 171 175 }, 172 176 };
+73
tools/perf/tests/kmod-path.c
··· 1 + #include <stdbool.h> 2 + #include "tests.h" 3 + #include "dso.h" 4 + #include "debug.h" 5 + 6 + static int test(const char *path, bool alloc_name, bool alloc_ext, 7 + bool kmod, bool comp, const char *name, const char *ext) 8 + { 9 + struct kmod_path m; 10 + 11 + memset(&m, 0x0, sizeof(m)); 12 + 13 + TEST_ASSERT_VAL("kmod_path__parse", 14 + !__kmod_path__parse(&m, path, alloc_name, alloc_ext)); 15 + 16 + pr_debug("%s - alloc name %d, alloc ext %d, kmod %d, comp %d, name '%s', ext '%s'\n", 17 + path, alloc_name, alloc_ext, m.kmod, m.comp, m.name, m.ext); 18 + 19 + TEST_ASSERT_VAL("wrong kmod", m.kmod == kmod); 20 + TEST_ASSERT_VAL("wrong comp", m.comp == comp); 21 + 22 + if (ext) 23 + TEST_ASSERT_VAL("wrong ext", m.ext && !strcmp(ext, m.ext)); 24 + else 25 + TEST_ASSERT_VAL("wrong ext", !m.ext); 26 + 27 + if (name) 28 + TEST_ASSERT_VAL("wrong name", m.name && !strcmp(name, m.name)); 29 + else 30 + TEST_ASSERT_VAL("wrong name", !m.name); 31 + 32 + free(m.name); 33 + free(m.ext); 34 + return 0; 35 + } 36 + 37 + #define T(path, an, ae, k, c, n, e) \ 38 + TEST_ASSERT_VAL("failed", !test(path, an, ae, k, c, n, e)) 39 + 40 + int test__kmod_path__parse(void) 41 + { 42 + /* path alloc_name alloc_ext kmod comp name ext */ 43 + T("/xxxx/xxxx/x-x.ko", true , true , true, false, "[x_x]", NULL); 44 + T("/xxxx/xxxx/x-x.ko", false , true , true, false, NULL , NULL); 45 + T("/xxxx/xxxx/x-x.ko", true , false , true, false, "[x_x]", NULL); 46 + T("/xxxx/xxxx/x-x.ko", false , false , true, false, NULL , NULL); 47 + 48 + /* path alloc_name alloc_ext kmod comp name ext */ 49 + T("/xxxx/xxxx/x.ko.gz", true , true , true, true, "[x]", "gz"); 50 + T("/xxxx/xxxx/x.ko.gz", false , true , true, true, NULL , "gz"); 51 + T("/xxxx/xxxx/x.ko.gz", true , false , true, true, "[x]", NULL); 52 + T("/xxxx/xxxx/x.ko.gz", false , false , true, true, NULL , NULL); 53 + 54 + /* path alloc_name alloc_ext kmod comp name ext */ 55 + T("/xxxx/xxxx/x.gz", true , true , false, true, "x.gz" ,"gz"); 56 + T("/xxxx/xxxx/x.gz", false , true , false, true, NULL ,"gz"); 57 + T("/xxxx/xxxx/x.gz", true , false , false, true, "x.gz" , NULL); 58 + T("/xxxx/xxxx/x.gz", false , false , false, true, NULL , NULL); 59 + 60 + /* path alloc_name alloc_ext kmod comp name ext */ 61 + T("x.gz", true , true , false, true, "x.gz", "gz"); 62 + T("x.gz", false , true , false, true, NULL , "gz"); 63 + T("x.gz", true , false , false, true, "x.gz", NULL); 64 + T("x.gz", false , false , false, true, NULL , NULL); 65 + 66 + /* path alloc_name alloc_ext kmod comp name ext */ 67 + T("x.ko.gz", true , true , true, true, "[x]", "gz"); 68 + T("x.ko.gz", false , true , true, true, NULL , "gz"); 69 + T("x.ko.gz", true , false , true, true, "[x]", NULL); 70 + T("x.ko.gz", false , false , true, true, NULL , NULL); 71 + 72 + return 0; 73 + }
+1
tools/perf/tests/tests.h
··· 51 51 int test__switch_tracking(void); 52 52 int test__fdarray__filter(void); 53 53 int test__fdarray__add(void); 54 + int test__kmod_path__parse(void); 54 55 55 56 #if defined(__x86_64__) || defined(__i386__) || defined(__arm__) 56 57 #ifdef HAVE_DWARF_UNWIND_SUPPORT
+66
tools/perf/util/dso.c
··· 212 212 } 213 213 214 214 /* 215 + * Parses kernel module specified in @path and updates 216 + * @m argument like: 217 + * 218 + * @comp - true if @path contains supported compression suffix, 219 + * false otherwise 220 + * @kmod - true if @path contains '.ko' suffix in right position, 221 + * false otherwise 222 + * @name - if (@alloc_name && @kmod) is true, it contains strdup-ed base name 223 + * of the kernel module without suffixes, otherwise strudup-ed 224 + * base name of @path 225 + * @ext - if (@alloc_ext && @comp) is true, it contains strdup-ed string 226 + * the compression suffix 227 + * 228 + * Returns 0 if there's no strdup error, -ENOMEM otherwise. 229 + */ 230 + int __kmod_path__parse(struct kmod_path *m, const char *path, 231 + bool alloc_name, bool alloc_ext) 232 + { 233 + const char *name = strrchr(path, '/'); 234 + const char *ext = strrchr(path, '.'); 235 + 236 + memset(m, 0x0, sizeof(*m)); 237 + name = name ? name + 1 : path; 238 + 239 + /* No extension, just return name. */ 240 + if (ext == NULL) { 241 + if (alloc_name) { 242 + m->name = strdup(name); 243 + return m->name ? 0 : -ENOMEM; 244 + } 245 + return 0; 246 + } 247 + 248 + if (is_supported_compression(ext + 1)) { 249 + m->comp = true; 250 + ext -= 3; 251 + } 252 + 253 + /* Check .ko extension only if there's enough name left. */ 254 + if (ext > name) 255 + m->kmod = !strncmp(ext, ".ko", 3); 256 + 257 + if (alloc_name) { 258 + if (m->kmod) { 259 + if (asprintf(&m->name, "[%.*s]", (int) (ext - name), name) == -1) 260 + return -ENOMEM; 261 + } else { 262 + if (asprintf(&m->name, "%s", name) == -1) 263 + return -ENOMEM; 264 + } 265 + 266 + strxfrchar(m->name, '-', '_'); 267 + } 268 + 269 + if (alloc_ext && m->comp) { 270 + m->ext = strdup(ext + 4); 271 + if (!m->ext) { 272 + free((void *) m->name); 273 + return -ENOMEM; 274 + } 275 + } 276 + 277 + return 0; 278 + } 279 + 280 + /* 215 281 * Global list of open DSOs and the counter. 216 282 */ 217 283 static LIST_HEAD(dso__data_open);
+14
tools/perf/util/dso.h
··· 195 195 bool decompress_to_file(const char *ext, const char *filename, int output_fd); 196 196 bool dso__needs_decompress(struct dso *dso); 197 197 198 + struct kmod_path { 199 + char *name; 200 + char *ext; 201 + bool comp; 202 + bool kmod; 203 + }; 204 + 205 + int __kmod_path__parse(struct kmod_path *m, const char *path, 206 + bool alloc_name, bool alloc_ext); 207 + 208 + #define kmod_path__parse(__m, __p) __kmod_path__parse(__m, __p, false, false) 209 + #define kmod_path__parse_name(__m, __p) __kmod_path__parse(__m, __p, true , false) 210 + #define kmod_path__parse_ext(__m, __p) __kmod_path__parse(__m, __p, false, true) 211 + 198 212 /* 199 213 * The dso__data_* external interface provides following functions: 200 214 * dso__data_fd