The btrfs inspect-internal logical-resolve command is used to find a file related to a logical-address. This can be useful when btrfs reports a corruption at an specific logical address, making it easy for the user to find the corrupted file. But, for all current users of openSUSE/SUSE Enterprise Linux, this command was failing as shown below:
|
|
An openSUSE/SLE installation would create a set of subvolumes, starting from /@. These subvolumes are mounted on /, but @ is never mounted. For example, subvolume /@/home is mounted at /home. We can confirm this behavior by looking at the subvolume list:
|
|
By checking the fstab file we can verify that all subvolumes are mounted at /, but starting from the subvolume ‘@’:
|
|
The code related to logical-address look at the full subvolume path (/@/home) and tries to follow it, but subvolume /@ isn’t mounted, returning an error. To address it, we need to find the exact mountpoint of the subvolume where the file is mounted, and show the path starting from it.
These two patches (patch 1, path 2) fix the issue: finding the correct mountpoint of a subvolume and using it to show the path to the file related to the logical-address.
In this post I’ll discuss about the first patch: how to reliably find the correct mountpoint related to a subvolume and a subvolume id.
Searching for mounted subvolumes
As btrfs mount options always show subvolume and subvolume id, it would be simple as:
|
|
The command above searches in the /proc/mounts file which contain all mountpoints, source, target, filesystem type and filesystem options used to mount.
In this case, it works as expect, but what if we have a bind mount mounting from a directory within the current mountpoint? Look at the example below:
|
|
Now, if we run the same command as before, we have a problem:
|
|
As shown, the subvolid and subvol fields are the same, but the content isn’t:
|
|
Prior to kernel 5.9-rc1, btrfs would show a diferent subvol= option when a bind mount was used. The issue was fixed by this patch. Before this change the /proc/mounts file would differentiate bind mounts:
|
|
This was wrong, since the subvolume shown should be the same for a bind mount. The patch above fixed the behavior, and now a bind mount will show the same subvol and subvolid fields on a mountpoint:
|
|
As /proc/mounts can’t be used to differentiate bind mounts, how can we proceed?
Using /proc/<pid>/mountinfo
There is a different proc file that shows all mountpoints, accessible by /proc/<pid>/mountinfo. The <pid> comes form the fact that the process can be in a different mount namespace. By using the pid the kernel knows which mountpoints are visible to the process. You can also use self if you want the mountpoints of the current process namespace.
The description of all mountinfo fields, along with the /proc/mounts one, can be see in the procfs manpage.
What does mountinfo shows in this setup?
|
|
By looking at the forth field, we can see an interesting info. The manpage describes this field as:
root: the pathname of the directory in the filesystem which forms the root of this mount.
The mountinfo proc file can show the path within the filesystem used at the mount time. In this case, we just need to check if the forth field contains the same subvolume path specified in the filesystem options.
What if we create a bind mount using the same directory of the original mount?
|
|
As we can see, both mount roots are the same since both mountpoints have the same contents. The bind mount is just another way of accessing the same content of /mnt.
I used this approach in this patch in order to solve one of the logical-resolve issues when running the comannd on a openSUSE/SLE distribution. Now the command runs correctly and reports the file related to a logical-address in the filesystem:
|
|
The patch was merged and is already part of btrfs-progs v5.10.1 along with other important fixes.
Thanks for reading!