Page MenuHomeFreeBSD

LinuxKPI drm-kmod debugfs support
ClosedPublic

Authored by jfree on Jul 23 2022, 1:55 AM.
Referenced Files
Unknown Object (File)
Feb 13 2024, 1:14 AM
Unknown Object (File)
Feb 12 2024, 5:45 PM
Unknown Object (File)
Feb 11 2024, 5:01 PM
Unknown Object (File)
Feb 11 2024, 5:01 PM
Unknown Object (File)
Feb 11 2024, 5:01 PM
Unknown Object (File)
Feb 11 2024, 5:01 PM
Unknown Object (File)
Feb 11 2024, 5:00 PM
Unknown Object (File)
Feb 11 2024, 5:00 PM

Details

Summary

This diff extends LinuxKPI to support simple attribute files in debugfs. These simple attributes are an essential component for compiling drm-kmod with CONFIG_DEBUG_FS enabled. This will allow for easier graphics driver debugging using Intel's igt-gpu-tools.

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Skipped
Unit
Tests Skipped

Event Timeline

jfree requested review of this revision.Jul 23 2022, 1:55 AM
hselasky added inline comments.
sys/compat/lindebugfs/lindebugfs.c
145

if sb->s_size == 0
return (-EINVAL);

or

MPASS(sb->s_size != 0);

147

What if the length is equal to the buffer size?

You are repeating strlen(buf), should cache value in a variable.

sys/compat/linuxkpi/common/include/linux/debugfs.h
127

BSD style: All return values should be wrapped by ()'s.

jfree marked 2 inline comments as done.
jfree edited the summary of this revision. (Show Details)

Added parenthesis around return values per FreeBSD kernel style guide

@jfree if you generate another diff to update this review please include full context, e.g. git diff -U999999 or git show -U999999

jfree marked an inline comment as done.
  • Moved static inline functions out of debugfs.h and into lindebugfs.c.
  • Removed unnecessary functions from debugfs.h.
  • Generated diff with -U999999 flag.

Minor modifications to lindebugfs.c

Added manual page for lindebugfs

Return positive values in lindebugfs.c so pseudofs vnops does not get confused.

share/man/man5/lindebugfs.5
2

We don't include "$FreeBSD$" in new files. Typically you'd add a copyright statement instead of a simple "written by."

19

Isn't lindebugfs solely for supporting drivers using the LinuxKPI? If so I'd suggest stating that directly. In other words, this is not a general-purpose filesystem but rather 1) exists mostly for the benefit of developers, and 2) only for LinuxKPI-based drivers.

53

Oh, this filesystem should really be called "lindebugfs".

70

You need to update share/man/man5/Makefile to ensure that this makefile gets installed.

sys/compat/lindebugfs/lindebugfs.c
122

Declaring variable-length arrays on the stack is not a good idea. Kernel threads have limited stack space and only primitive means of detecting stack overflow (one guard page at the end of the stack). You should malloc() a temporary buffer instead.

215

What does "this behaviour" refer to exactly?

sys/compat/linuxkpi/common/include/linux/fs.h
328

Why is this commented out?

sys/compat/linuxkpi/common/include/linux/string.h
108
113

I think this could probably be committed separately?

sys/compat/linuxkpi/common/src/linux_seq_file.c
52

Is this a bug fix?

sys/compat/linuxkpi/common/src/linux_simple_attr.c
61

Style, continuation lines should be indented by four spaces.

183

buf has a __user annotation, which indicates that buf is a userspace pointer. If that's actually the case (i.e., the annotation is correct), then we must not dereference the user pointer directly. Data should be copied into the kernel's address space first, then kstrtoull() can be called.

Also I don't think this call needs to happen under the mutex?

jfree marked 11 inline comments as done.

Updated diff per markj@'s review and comments

Fixed function parameter list indentation

sys/compat/lindebugfs/lindebugfs.c
399

If there is no return value, you can skip the return statement. Ditto for the other cases below.

jfree marked an inline comment as not done.

Removed return statements from void functions per hselasky's advice

sys/compat/linuxkpi/common/src/linux_simple_attr.c
126

off-by-one ??

176

I think this is off-by-one. Should be:

*ppos >= sizeof(data)

Do you agree?

jfree marked 2 inline comments as done.

Corrected pointer position errors in linux_simple_attr.c thanks to hselasky@

jfree marked an inline comment as done.
This comment was removed by jfree.
  • Updated seq_file seq_read() to report number of bytes read correctly
  • Adjusted lindebugfs.c module declaration - this is done through the PSEUDOFS() macro
  • Changed internal debugfs filesystem name to lindebugfs
  • Modified man page to reflect changes
  • Corrected off-by-one errors in linux_simple_attr.c
sys/compat/lindebugfs/lindebugfs.c
147

In this error case you should call d->dm_fops->release() before returning ?

In other words,

set "rc" and goto below ?

jfree marked an inline comment as done.

Fixed memory leak where lf was not released due to a potential failed malloc() during read. Thanks to @hselasky for pointing this out.

Fixed off-by-one error in linux_seq_file.c

sys/compat/linuxkpi/common/include/linux/fs.h
302

Can you make this a static inline function, instead of using a macro?

static inline loff_t
default_llseek(....)

This avoids the macro, which may match more than it should.

328

Please remove this comment.

jfree marked 2 inline comments as done.
  • Created default_llseek() function in substitution of macro
  • removed i_size_write() comment
jfree marked an inline comment as done.
  • Removed unnecessary code from linux_simple_attr.c

Looks good to me. Make sure you bump the FreeBSD version along this commit.

This revision is now accepted and ready to land.Sep 2 2022, 9:05 AM
This revision was automatically updated to reflect the committed changes.

There's more to fix in this (debugfs) world now it seems beyond the comment. Is anyone still interested please let me know.

sys/compat/lindebugfs/lindebugfs.c
146

This doesn't work for anything but your specific case most likely. The read implementations are expecting a user address and not a kernel one returned from malloc; this makes a lot of debugfs implementations fail with -EFAULT.

In D35883#842122, @bz wrote:

There's more to fix in this (debugfs) world now it seems beyond the comment. Is anyone still interested please let me know.

I tested with FreeBSD seq_file and simple attribute file implementations. Both of these were modified in this patch to accommodate the kernel buffer. I did not realize that there were more implementations that are commonly used. This is my mistake, so I would be happy to finish the work. Sorry for any inconvenience that I may have caused. I'll start right away.

sys/compat/lindebugfs/lindebugfs.c
145

The buf[0] = '\0' exists for situations where nothing is written into buf. A good example is the seq_file ->read() implementation which uses seq_printfs to print into its local sbuf instead of writing into buf. Other ->read() implementations write file contents into buf and return their own error codes when read failures occur.

I could do if (sbuf_len(sb) == 0) { sbuf_bcpy(sb, buf, strlen(buf)) } to see if a seq_printf went through and sbuf_bcpy based on that, but I feel like the existing code is more readable.

Either way, I need the buf[0] = '\0' for strlen(). Please tell me if I am misunderstanding.

147

If the length is equal to the buffer size, the if statement will go through. Perhaps I am not understanding what you're suggesting?

The compiler (assuming optimizations are turned on) should optimize this out and cache the strlen() value.

147

Absolutely. Silly mistake on my part. Thanks for pointing that out.

sys/compat/linuxkpi/common/include/linux/debugfs.h
127

Got it. I will change that! :)

sys/compat/linuxkpi/common/src/linux_seq_file.c
52

Yes.

sys/compat/linuxkpi/common/src/linux_simple_attr.c
126

After some investigation, it appears that strscpy will error out during a zero byte transfer. I am going to apply your suggestion to make the error message more transparent. Thanks.

176

I do agree. I'm also changing sizeof(data) to strlen(buf) since this function applies the offset to buf, not data. Thanks for pointing that out.

183

The buffer was meant to be a userspace pointer at one time, but lindebugfs uses sbufs to transfer data. I am under the impression that the user to kernel space conversion has already been done by pseudofs in pseudofs_vnops.c:1082. If I use LinuxKPI's copy_from_user() on the data in buf, I get errors. I will remove the misleading __user.

The mutex is necessary if multiple simple_attr_write()s are executed at the same time asynchronously. We don't want multiple sources overwriting each other.

In D35883#842122, @bz wrote:

There's more to fix in this (debugfs) world now it seems beyond the comment. Is anyone still interested please let me know.

I tested with FreeBSD seq_file and simple attribute file implementations. Both of these were modified in this patch to accommodate the kernel buffer. I did not realize that there were more implementations that are commonly used. This is my mistake, so I would be happy to finish the work. Sorry for any inconvenience that I may have caused. I'll start right away.

There is a lot of code using simple_open with a private read function which at the end simply calls simple_read_from_buffer() or even calls the copy_to_user() or for write copy_from_user() itself (e.g. when doing memory dumps). simple_read_from_buffer() as implemented here will also call the linux copy_to_user().

I am under the impression that it should be the implementation's problem to handle that bit and how to hide it (like seq_file does working on the sbuf)?

PS: I am also looking at debugfs_create_blob() and some other bits. If you are happy I'll try to get bits into here Saturday.

In D35883#842153, @bz wrote:
In D35883#842122, @bz wrote:

There's more to fix in this (debugfs) world now it seems beyond the comment. Is anyone still interested please let me know.

I tested with FreeBSD seq_file and simple attribute file implementations. Both of these were modified in this patch to accommodate the kernel buffer. I did not realize that there were more implementations that are commonly used. This is my mistake, so I would be happy to finish the work. Sorry for any inconvenience that I may have caused. I'll start right away.

There is a lot of code using simple_open with a private read function which at the end simply calls simple_read_from_buffer() or even calls the copy_to_user() or for write copy_from_user() itself (e.g. when doing memory dumps). simple_read_from_buffer() as implemented here will also call the linux copy_to_user().

I am under the impression that it should be the implementation's problem to handle that bit and how to hide it (like seq_file does working on the sbuf)?

PS: I am also looking at debugfs_create_blob() and some other bits. If you are happy I'll try to get bits into here Saturday.

Bjoern,

At second glance, you are certainly right. It is the implementation's responsibility to handle the user -> kernel buffer conversion.
I'm not at my desktop right now, but some quick intuition leads me to believe that buf = uio->uio_iov[0].iov_base; might grab
the appropriate user buffer. I will test this when I get home.