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

Add fd_path builtin function #1060

Closed
wants to merge 4 commits into from
Closed

Conversation

olsajiri
Copy link
Contributor

@olsajiri olsajiri commented Jan 3, 2020

Adding fd_path builtin function that returns full path
for given file descriptor, syntax:

char *fd_path(int fd);

Example:

  $ cat ex.bt
  tracepoint:syscalls:sys_enter_newfstat
  {
    printf("comm %s, pid %d, fd %d %s\n", comm, pid, args->fd, fd_path(args->fd));
  }

  $ sudo bpftrace ex.bt
  Attaching 1 probe...
  comm NetworkManager, pid 1178, fd 24 /proc/sys/net/ipv6/conf/eno2/disable_ipv6
  comm ls, pid 5878, fd 3 /etc/ld.so.cache
  comm ls, pid 5878, fd 3 /usr/lib/locale/en_US.utf8/LC_MESSAGES/SYS_LC_MESSAGES
  comm ls, pid 5878, fd 1 /dev/pts/0
  comm systemd, pid 1, fd 19 /proc/945/cgroup

The fd_path returns the string with the path or empty string
on error. I don't think it's necessary to return error code
at the moment, however it can be added later in the second
optional argument.

Copy link
Contributor

@fbs fbs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hah, this wasn't even merged yesterday (#29 )

Looks ok for a first version. It would be nice to be able to limit the string length in a future to save some stack space

@@ -2163,6 +2164,24 @@ Attaching 320 probes...
@[mpv, tracepoint:syscalls:sys_enter_getpid]: 31178
@[mpv, tracepoint:syscalls:sys_enter_futex]: 403868
```
## 20. `fd_path()`: Returns path of the file refferenced with file descriptor in argument
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
## 20. `fd_path()`: Returns path of the file refferenced with file descriptor in argument
## 20. `fd_path()`: Returns path of the file referenced by file descriptor in argument

@@ -94,6 +94,9 @@ set_property(
endif()
target_compile_definitions(bpftrace_test PRIVATE HAVE_SEND_SIGNAL)

if(HAVE_GET_FD_PATH)
target_compile_definitions(bpftrace_test PRIVATE HAVE_GET_FD_PATH)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For send_signal I've always defined this(unconditionally), and manually defined BPF_FUNC_send_signal to always have the tests work, as we can do semantic and codegen tests without kernel support. You'll will have to do the same thing here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, sounds good

{
test("kprobe:f { $k = fd_path( 1 ) }", 0);
test("kretprobe:f { $k = fd_path( 1 ) }", 0);
test("tracepoint:category:event { $k = fd_path( 1 ) }", 0);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would be good to test some failures too fd_path(-100) fd_path("abc").

And fd_path(arg0) as that is valid too.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

@@ -1534,6 +1534,7 @@ Tracing block I/O sizes > 0 bytes
- `ustack([StackMode mode, ][int level])` - User stack trace
- `ntop([int af, ]int|char[4|16] addr)` - Convert IP address data to text
- `cat(char *filename)` - Print file content
- `fd_path(int fd)` - Returns path of the file refferenced with file descriptor in argument
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as below

@danobi
Copy link
Member

danobi commented Jan 3, 2020

All our other 2-word helpers have been _ free (eg kstack, ustack, cgroupid). Would it be better if this was path or fdpath?

@olsajiri
Copy link
Contributor Author

olsajiri commented Jan 3, 2020

All our other 2-word helpers have been _ free (eg kstack, ustack, cgroupid). Would it be better if this was path or fdpath?

I have another helper coming that gives path from 'struct file',
so I'd prefer the prefix.. 'fdpath' is ok for me.. the other one could
be filepath

@olsajiri
Copy link
Contributor Author

olsajiri commented Jan 3, 2020

All our other 2-word helpers have been _ free (eg kstack, ustack, cgroupid). Would it be better if this was path or fdpath?

I have another helper coming that gives path from 'struct file',
so I'd prefer the prefix.. 'fdpath' is ok for me.. the other one could
be filepath

or we could make one polymorph path function ;-) we could actually check
on the argument type and call appropriate helper.. will check

@brendangregg
Copy link
Contributor

Thanks Jiri,

Good to see BPF_FUNC_get_fd_path get picked up so quick. :)

I'd prefer no underscore, so just "fdpath" and the next one can be "filepath".

I'm not sure about polymorph, I don't think we have anything else in bpftrace like that. How would it work? If it was, say, fpath(), then people might assume it works for everything, and try a dentry with it. The docs would have to say it's for fds and files only. Would that be confusing that it's not anything? Might be ok if it was documented as "fpath(): return a file path from int fd or struct file".

@olsajiri
Copy link
Contributor Author

olsajiri commented Jan 4, 2020

on the second thought there's not too much gain in this given the confusion it could
cause plus the added complexity in the code.. fdpath and filepath will be better

It's sometimes convenient to use other kernel headers,
now it's possible possible with new KERNEL_INCLUDE_DIRS
build variable, like:

  $ cd <kernel-dir>
  $ make INSTALL_HDR_PATH=/tmp/headers headers_install
  $ cd <bpftrace-dir>
  $ cmake -DKERNEL_INCLUDE_DIRS=/tmp/headers/include/ ...

Signed-off-by: Jiri Olsa <jolsa@redhat.com>
And based on that define HAVE_GET_FD_PATH macro for c++ code.

Signed-off-by: Jiri Olsa <jolsa@redhat.com>
Adding fdpath builtin function that returns full path
for given file descriptor, syntax:

  char *fdpath(int fd);

Example:

  $ cat ex.bt
  tracepoint:syscalls:sys_enter_newfstat
  {
    printf("comm %s, pid %d, fd %d %s\n", comm, pid, args->fd, fdpath(args->fd));
  }

  $ sudo bpftrace ex.bt
  Attaching 1 probe...
  comm NetworkManager, pid 1178, fd 24 /proc/sys/net/ipv6/conf/eno2/disable_ipv6
  comm ls, pid 5878, fd 3 /etc/ld.so.cache
  comm ls, pid 5878, fd 3 /usr/lib/locale/en_US.utf8/LC_MESSAGES/SYS_LC_MESSAGES
  comm ls, pid 5878, fd 1 /dev/pts/0
  comm systemd, pid 1, fd 19 /proc/945/cgroup

The fdpath returns the string with the path or empty string
on error. I don't think it's necessary to return error code
at the moment, however it can be added later in the second
optional argument.

Signed-off-by: Jiri Olsa <jolsa@redhat.com>
Adding codegen and semantic_analyser tests.

Signed-off-by: Jiri Olsa <jolsa@redhat.com>
@@ -62,6 +62,7 @@ class IRBuilderBPF : public IRBuilder<>
void CreateGetCurrentComm(AllocaInst *buf, size_t size);
void CreatePerfEventOutput(Value *ctx, Value *data, size_t size);
void CreateSignal(Value *sig);
void CreateFdPath(AllocaInst *path, Value *fd);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you indent this one? I've opened #1074 stop clang-format from complaining about this

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

Copy link
Contributor

@fbs fbs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Found some typing issues in the ir. They don't really break llvm but good to fix them anyway

// int bpf_get_fdpath(char *path, u32 size, int fd)
// Return: 0 or error
FunctionType *fdpath_func_type = FunctionType::get(
getInt64Ty(), { getInt8PtrTy(), getInt32Ty(), getInt32Ty() }, false);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
getInt64Ty(), { getInt8PtrTy(), getInt32Ty(), getInt32Ty() }, false);
getInt64Ty(), { path->getType(), getInt32Ty(), getInt32Ty() }, false);

To avoid type issues.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

right, thanks

Constant *fdpath_func = ConstantExpr::getCast(Instruction::IntToPtr,
getInt64(BPF_FUNC_get_fd_path),
fdpath_func_ptr_type);
CreateCall(fdpath_func, { path, getInt64(bpftrace_.strlen_), fd }, "fdpath");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
CreateCall(fdpath_func, { path, getInt64(bpftrace_.strlen_), fd }, "fdpath");
CreateCall(fdpath_func, { path, getInt32(bpftrace_.strlen_), CreateIntCast(fd, getInt32Ty(), false) }, "fdpath");

To match the types used in the function prototype

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oops, thanks

#ifdef HAVE_GET_FD_PATH
if (check_varargs(call, 1, 1))
{
check_arg(call, Type::integer, 0);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does fdpath work for all probe types or should we restrict it? E.g i:s:1 { @[pid,fdpath(1)]++ }

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added the check.. it's supported by tracepoints, I'm using kernel patch that adds it for kprobes,which I'll post

however the helper still did not get merged.. moreover got outrun by another one, so the ID changed ;-)) I'll wait with new push until it's merged, to avoid any confusion

@fbs fbs mentioned this pull request Jan 17, 2020
@brendangregg
Copy link
Contributor

I'd merge this, but get_fd_path() hasn't quite landed in Linux yet. Next release maybe?

@olsajiri
Copy link
Contributor Author

let's hope ;-) the kernel change waits for vfs review, I asked al Viro for review

bpftrace change actually needs the new helper ID hardcoded, so we need to
wait for the kernel in any case, because new helpers are coming all the time

@danobi
Copy link
Member

danobi commented Nov 19, 2020

#1492 supercedes

@danobi danobi closed this Nov 19, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants