When debugging anything related to a device driver, the first step is often finding the struct device that represents the device in the kernel. One way to find a device is by its sysfs path. However, drgn doesn't currently have an easy way to do that. You can kind of do it with something like:
path_lookup() walks the dentry cache, which may not be populated for a particular path depending on memory pressure.
path_lookup() doesn't resolve symlinks (yet, see #216), so you have to use the canonical path instead of a more convenient symlink like /sys/block/nvme0n1.
Instead, we should improve our kernfs helpers and provide sysfs-specific helpers on top of those. This can be broken down into multiple smaller features.
kernfs
sysfs is actually an instance of kernfs, which is generic infrastructure for pseudo file systems. A kernfs filesystem comprises a tree of struct kernfs_node, each of which represents a file or directory.
[ ] Add a kernfs_children() helper that returns an iterator over the children of a directory in kernfs. Children are represented by struct kernfs_node::dir::children.
[ ] Extend the kernfs_walk() helper to follow symlinks. These are represented by struct kernfs_node::symlink::target_kn. We should probably also have a follow_symlinks parameter that controls what we do if the last component of a path is a symlink, similar to the Python os module.
sysfs
Once we have the kernfs changes, we can add sysfs-specific helpers that use the new kernfs features.
[ ] Add a sysfs_lookup_node() helper that returns the struct kernfs_node * at a given path.
[ ] Add a sysfs_lookup() helper that returns the actual object (e.g., struct device *, struct bus *, etc.) represented by a given path.
[ ] Add a sysfs_listdir() helper that lists the names of the children of a sysfs directory at a given path.
Background
When debugging anything related to a device driver, the first step is often finding the
struct device
that represents the device in the kernel. One way to find a device is by its sysfs path. However, drgn doesn't currently have an easy way to do that. You can kind of do it with something like:But this has a few issues:
path_lookup()
walks the dentry cache, which may not be populated for a particular path depending on memory pressure.path_lookup()
doesn't resolve symlinks (yet, see #216), so you have to use the canonical path instead of a more convenient symlink like/sys/block/nvme0n1
.Instead, we should improve our kernfs helpers and provide sysfs-specific helpers on top of those. This can be broken down into multiple smaller features.
kernfs
sysfs is actually an instance of kernfs, which is generic infrastructure for pseudo file systems. A kernfs filesystem comprises a tree of
struct kernfs_node
, each of which represents a file or directory.We already have a few basic helpers for inspecting kernfs: https://drgn.readthedocs.io/en/latest/helpers.html#kernfs. I would like two extensions to those:
kernfs_children()
helper that returns an iterator over the children of a directory in kernfs. Children are represented bystruct kernfs_node::dir::children
.kernfs_walk()
helper to follow symlinks. These are represented bystruct kernfs_node::symlink::target_kn
. We should probably also have afollow_symlinks
parameter that controls what we do if the last component of a path is a symlink, similar to the Pythonos
module.sysfs
Once we have the kernfs changes, we can add sysfs-specific helpers that use the new kernfs features.
sysfs_lookup_node()
helper that returns thestruct kernfs_node *
at a given path.sysfs_lookup()
helper that returns the actual object (e.g.,struct device *
,struct bus *
, etc.) represented by a given path.sysfs_listdir()
helper that lists the names of the children of a sysfs directory at a given path.