diff --git a/tools/bpf/bpftool/Documentation/bpftool-map.rst b/tools/bpf/bpftool/Documentation/bpftool-map.rst index 3221be1b9cccd18319b8586e87554bd57f2d46dc..64b001b4f777812c2e87083c0117bedad2a5561d 100644 --- a/tools/bpf/bpftool/Documentation/bpftool-map.rst +++ b/tools/bpf/bpftool/Documentation/bpftool-map.rst @@ -128,6 +128,10 @@ OPTIONS -f, --bpffs Show file names of pinned maps. + -n, --nomount + Do not automatically attempt to mount any virtual file system + (such as tracefs or BPF virtual file system) when necessary. + EXAMPLES ======== **# bpftool map show** diff --git a/tools/bpf/bpftool/Documentation/bpftool-prog.rst b/tools/bpf/bpftool/Documentation/bpftool-prog.rst index 53920ffc48dd444ae8093bf9ef05338d63d2c057..58c8369b77dd556f59c10f8f3266b97cbb671c57 100644 --- a/tools/bpf/bpftool/Documentation/bpftool-prog.rst +++ b/tools/bpf/bpftool/Documentation/bpftool-prog.rst @@ -161,6 +161,10 @@ OPTIONS -m, --mapcompat Allow loading maps with unknown map definitions. + -n, --nomount + Do not automatically attempt to mount any virtual file system + (such as tracefs or BPF virtual file system) when necessary. + EXAMPLES ======== **# bpftool prog show** diff --git a/tools/bpf/bpftool/Documentation/bpftool.rst b/tools/bpf/bpftool/Documentation/bpftool.rst index 129b7a9c0f9bce5ac78f49d6678e39c8c6fbaa8b..e1677e81ed594a81d9bf8330e46b1d860038f663 100644 --- a/tools/bpf/bpftool/Documentation/bpftool.rst +++ b/tools/bpf/bpftool/Documentation/bpftool.rst @@ -60,6 +60,10 @@ OPTIONS -m, --mapcompat Allow loading maps with unknown map definitions. + -n, --nomount + Do not automatically attempt to mount any virtual file system + (such as tracefs or BPF virtual file system) when necessary. + SEE ALSO ======== diff --git a/tools/bpf/bpftool/common.c b/tools/bpf/bpftool/common.c index 24582e8a96fb8edbbcb1962e4141c0d45d37a7cd..897483457bf0306b9831e3dae4f63d4643c2555e 100644 --- a/tools/bpf/bpftool/common.c +++ b/tools/bpf/bpftool/common.c @@ -76,7 +76,8 @@ void set_max_rlimit(void) setrlimit(RLIMIT_MEMLOCK, &rinf); } -static int mnt_bpffs(const char *target, char *buff, size_t bufflen) +static int +mnt_fs(const char *target, const char *type, char *buff, size_t bufflen) { bool bind_done = false; @@ -98,15 +99,29 @@ static int mnt_bpffs(const char *target, char *buff, size_t bufflen) bind_done = true; } - if (mount("bpf", target, "bpf", 0, "mode=0700")) { - snprintf(buff, bufflen, "mount -t bpf bpf %s failed: %s", - target, strerror(errno)); + if (mount(type, target, type, 0, "mode=0700")) { + snprintf(buff, bufflen, "mount -t %s %s %s failed: %s", + type, type, target, strerror(errno)); return -1; } return 0; } +int mount_tracefs(const char *target) +{ + char err_str[ERR_MAX_LEN]; + int err; + + err = mnt_fs(target, "tracefs", err_str, ERR_MAX_LEN); + if (err) { + err_str[ERR_MAX_LEN - 1] = '\0'; + p_err("can't mount tracefs: %s", err_str); + } + + return err; +} + int open_obj_pinned(char *path, bool quiet) { int fd; @@ -162,7 +177,13 @@ int mount_bpffs_for_pin(const char *name) /* nothing to do if already mounted */ goto out_free; - err = mnt_bpffs(dir, err_str, ERR_MAX_LEN); + if (block_mount) { + p_err("no BPF file system found, not mounting it due to --nomount option"); + err = -1; + goto out_free; + } + + err = mnt_fs(dir, "bpf", err_str, ERR_MAX_LEN); if (err) { err_str[ERR_MAX_LEN - 1] = '\0'; p_err("can't mount BPF file system to pin the object (%s): %s", diff --git a/tools/bpf/bpftool/main.c b/tools/bpf/bpftool/main.c index 9e657e7d5172c3e0d5096976d4597db419c52e97..f44a1c2c4ea06f5ff4793e93bdcff344092c8871 100644 --- a/tools/bpf/bpftool/main.c +++ b/tools/bpf/bpftool/main.c @@ -24,6 +24,7 @@ json_writer_t *json_wtr; bool pretty_output; bool json_output; bool show_pinned; +bool block_mount; int bpf_flags; struct pinned_obj_table prog_table; struct pinned_obj_table map_table; @@ -313,6 +314,7 @@ int main(int argc, char **argv) { "version", no_argument, NULL, 'V' }, { "bpffs", no_argument, NULL, 'f' }, { "mapcompat", no_argument, NULL, 'm' }, + { "nomount", no_argument, NULL, 'n' }, { 0 } }; int opt, ret; @@ -321,13 +323,14 @@ int main(int argc, char **argv) pretty_output = false; json_output = false; show_pinned = false; + block_mount = false; bin_name = argv[0]; hash_init(prog_table.table); hash_init(map_table.table); opterr = 0; - while ((opt = getopt_long(argc, argv, "Vhpjfm", + while ((opt = getopt_long(argc, argv, "Vhpjfmn", options, NULL)) >= 0) { switch (opt) { case 'V': @@ -354,6 +357,9 @@ int main(int argc, char **argv) case 'm': bpf_flags = MAPS_RELAX_COMPAT; break; + case 'n': + block_mount = true; + break; default: p_err("unrecognized option '%s'", argv[optind - 1]); if (json_output) diff --git a/tools/bpf/bpftool/main.h b/tools/bpf/bpftool/main.h index 9487345b04a79c1b0677b3bae158530c669596dc..052c91d4dc5585b46f420da26498e6808695401f 100644 --- a/tools/bpf/bpftool/main.h +++ b/tools/bpf/bpftool/main.h @@ -44,7 +44,8 @@ #define HELP_SPEC_PROGRAM \ "PROG := { id PROG_ID | pinned FILE | tag PROG_TAG }" #define HELP_SPEC_OPTIONS \ - "OPTIONS := { {-j|--json} [{-p|--pretty}] | {-f|--bpffs} | {-m|--mapcompat}" + "OPTIONS := { {-j|--json} [{-p|--pretty}] | {-f|--bpffs} |\n" \ + "\t {-m|--mapcompat} | {-n|--nomount} }" #define HELP_SPEC_MAP \ "MAP := { id MAP_ID | pinned FILE }" @@ -85,6 +86,7 @@ extern const char *bin_name; extern json_writer_t *json_wtr; extern bool json_output; extern bool show_pinned; +extern bool block_mount; extern int bpf_flags; extern struct pinned_obj_table prog_table; extern struct pinned_obj_table map_table; @@ -98,6 +100,8 @@ void usage(void) __noreturn; void set_max_rlimit(void); +int mount_tracefs(const char *target); + struct pinned_obj_table { DECLARE_HASHTABLE(table, 16); }; diff --git a/tools/bpf/bpftool/tracelog.c b/tools/bpf/bpftool/tracelog.c index 1fa8e513f5906315986874655c8f267da90cafda..e80a5c79b38f0ba2a35425d2cdcea806d0616b22 100644 --- a/tools/bpf/bpftool/tracelog.c +++ b/tools/bpf/bpftool/tracelog.c @@ -54,7 +54,7 @@ find_tracefs_mnt_single(unsigned long magic, char *mnt, const char *mntpt) return true; } -static bool find_tracefs_pipe(char *mnt) +static bool get_tracefs_pipe(char *mnt) { static const char * const known_mnts[] = { "/sys/kernel/debug/tracing", @@ -88,7 +88,20 @@ static bool find_tracefs_pipe(char *mnt) fclose(fp); /* The string from fscanf() might be truncated, check mnt is valid */ - if (!found || validate_tracefs_mnt(mnt, TRACEFS_MAGIC)) + if (found && validate_tracefs_mnt(mnt, TRACEFS_MAGIC)) + goto exit_found; + + if (block_mount) + return false; + + p_info("could not find tracefs, attempting to mount it now"); + /* Most of the time, tracefs is automatically mounted by debugfs at + * /sys/kernel/debug/tracing when we try to access it. If we could not + * find it, it is likely that debugfs is not mounted. Let's give one + * attempt at mounting just tracefs at /sys/kernel/tracing. + */ + strcpy(mnt, known_mnts[1]); + if (mount_tracefs(mnt)) return false; exit_found: @@ -115,17 +128,13 @@ int do_tracelog(int argc, char **argv) .sa_handler = exit_tracelog }; char trace_pipe[PATH_MAX]; - bool found_trace_pipe; size_t buff_len = 0; if (json_output) jsonw_start_array(json_wtr); - found_trace_pipe = find_tracefs_pipe(trace_pipe); - if (!found_trace_pipe) { - p_err("could not find trace pipe, tracefs not mounted?"); + if (!get_tracefs_pipe(trace_pipe)) return -1; - } trace_pipe_fd = fopen(trace_pipe, "r"); if (!trace_pipe_fd) {