lsfd: fill NAME column of inotify files with the information about their monitoring targets#2308
Conversation
| INODES_RAW=$(${TS_CMD_LSFD} -n -o INOTIFY.INODES.RAW -Q "${EXPR}") | ||
| echo "INOTIFY.INODES.RAW": $? | ||
| if [[ "$INODES_RAW" == "$FSTAB","$ROOT" ]]; then | ||
| echo "INOTIFY.INODES.RAW" == "FSTAB","ROOT" |
Check warning
Code scanning / shellcheck
Word is of the form "A"B"C" (B indicated). Did you mean "ABC" or "A\"B\"C"?
df895f9 to
cd601e4
Compare
| PID= | ||
| FD=3 | ||
| ROOT_DEV=$(stat -c %d /) | ||
| ROOT="$(stat -c %i /)"@"$(((ROOT_DEV >> 8) & 255)):$((ROOT_DEV & 255))" |
Check warning
Code scanning / shellcheck
Word is of the form "A"B"C" (B indicated). Did you mean "ABC" or "A\"B\"C"?
| ROOT_DEV=$(stat -c %d /) | ||
| ROOT="$(stat -c %i /)"@"$(((ROOT_DEV >> 8) & 255)):$((ROOT_DEV & 255))" | ||
| FSTAB_DEV=$(stat -c %d /etc/fstab) | ||
| FSTAB="$(stat -c %i /etc/fstab)"@"$(((FSTAB_DEV >> 8) & 255)):$((FSTAB_DEV & 255))" |
Check warning
Code scanning / shellcheck
Word is of the form "A"B"C" (B indicated). Did you mean "ABC" or "A\"B\"C"?
misc-utils/lsfd-file.c
Outdated
| if (dev_major == 0) { | ||
| const char *filesystem = get_nodev_filesystem(dev_minor); | ||
| if (filesystem) | ||
| return snprintf(buf, bufsize, "%s", filesystem); |
There was a problem hiding this comment.
It would probably be more effective to use xstrncpy(buf, filesystem, bufsiz) than snprinf("%s"). The decode_source() return code is nowhere used, so 0/-1 or void would be also good enough.
Signed-off-by: Masatake YAMATO <[email protected]>
…eir monitoring targets
# ./lsfd -p 1 -Q '(TYPE == "inotify") and (FD > 7)'
COMMAND PID USER ASSOC MODE TYPE SOURCE MNTID INODE NAME
systemd 1 root 11 r-- inotify anon_inodefs 15 1060 inodes=116@dm-0
systemd 1 root 13 r-- inotify anon_inodefs 15 1060 inodes=299@tmpfs
systemd 1 root 19 r-- inotify anon_inodefs 15 1060 inodes=41@tmpfs,2@tmpfs,1@tmpfs,96@dm-0
systemd 1 root 21 r-- inotify anon_inodefs 15 1060 inodes=41@tmpfs,2@tmpfs,1@tmpfs,96@dm-0
In addition, INOTIFY.INODES and INOTIFY.INODES.RAW column are added.
Signed-off-by: Masatake YAMATO <[email protected]>
Signed-off-by: Masatake YAMATO <[email protected]>
Signed-off-by: Masatake YAMATO <[email protected]>
Signed-off-by: Masatake YAMATO <[email protected]>
|
@masatake FYI this fails the testsuite for me reliably: Maybe because it's on btrfs. |
When filling SOURCE column, lsfd decodes the name of device where the file object is. If the file object is sourced a file system, lsfd fills the column with the name of the file system. As util-linux#2349 and util-linux#2308, if the file system is btrfs, lsfd couldn't decode the name correctly. This change and its preceeding changes fix this bug. "devnum offset" causes the trouble. On btrfs, the device number reported by stat syscall and proc fs are different. About the details of "devnum offset", see "Mechanisum behind the devnum offset". About the way to fix, see "How to adjust the output of lsfd". Mechanisum behind the devnum offset ----------------------------------- Both stat command and the inotify field in fdinfo refer to an inode. filename_lookup(https://elixir.bootlin.com/linux/v6.2.9/source/fs/namei.c#L2495) is the function getting the inode for a given file name. filename_lookup returns a struct path. Via path->detnry->inode, the caller of filename_lookup can get the inode. stat command calls statx system call. statx calls filename_lookup eventually. inotify_add_watch system call takes a file name. The inotify_add_watch calls the filename_lookup eventually for getting the inode for the file name. The inode number that inotify_add_watch gets via filename_lookup is printed in the inotify field in fdinfo. The device number, the subject of this issue, can be obtained via path->detnry->inode->i_sb->s_dev. Both the stat command and the inotify field in fdinfo use the filename_lookup for getting path. If they use the same function, why don't the device numbers match? I monitored the device numbers obtained via path->detnry->inode->i_sb->s_dev by inserting a systemtap probe to filename_lookup. I saw the numbers matched. However, the number monitored via systemtap did not match the number printed by the stat command. statx system call doesn't use path->detnry->inode->i_sb->s_dev , the value obtained via filename_lookup, directly. statx calls vfs_statx. vfs_statx calls vfs_getattr after calling the filename_lookup for filling struct kstat. vfs_getattr calls inode->i_op->getattr, a file system specific method for filling struct kstat if it is available. btrfs has an implementation for the method, btrfs_getattr(https://elixir.bootlin.com/linux/v6.2.9/source/fs/btrfs/inode.c#L9007): stat->dev = BTRFS_I(inode)->root->anon_dev; The dev member is overwritten with btrfs specific value. How to adjust the output of lsfd -------------------------------- lsfd already reads mountinfo files. 1. Get the "rawnum" and mount point The device numbers in a mountinfo file are raw; btrfs is not considered. Let's call the number "rawnum" here. When reading the mountinfo file, lsfd can know the mount points of btrfs. grep btrfs /proc/self/mountinfo 72 1 0:35 /root / rw,relatime shared:1 - btrfs 2. Get the cooked num By calling "stat" system call for the mount point getting in the step 1, lsdf can know the device number the btrfs customizes with its getattr method. Let's call the device number "cookednum". 3. Make a table mapping "rawnum" to "cookednum". 4. Look up the table when printing inodes. Signed-off-by: Masatake YAMATO <[email protected]>
When filling SOURCE column, lsfd decodes the name of device where the file object is. If the file object is sourced a file system, lsfd fills the column with the name of the file system. As util-linux#2349 and util-linux#2308, if the file system is btrfs, lsfd couldn't decode the name correctly. This change and its preceeding changes fix this bug. "devnum offset" causes the trouble. On btrfs, the device number reported by stat syscall and proc fs are different. About the details of "devnum offset", see "Mechanisum behind the devnum offset". About the way to fix, see "How to adjust the output of lsfd". Without this change: $ ./lsfd -Q '(ASSOC == "exe")' -p $$ COMMAND PID USER ASSOC XMODE TYPE SOURCE MNTID INODE NAME zsh 19318 yamato exe ------ REG 0:38 0 589767 /usr/bin/zsh With this change: $ ./lsfd -Q '(ASSOC == "exe")' -p $$ COMMAND PID USER ASSOC XMODE TYPE SOURCE MNTID INODE NAME zsh 19318 yamato exe ------ REG btrfs 0 589767 /usr/bin/zsh Mechanisum behind the devnum offset ----------------------------------- Both stat command and the inotify field in fdinfo refer to an inode. filename_lookup(https://elixir.bootlin.com/linux/v6.2.9/source/fs/namei.c#L2495) is the function getting the inode for a given file name. filename_lookup returns a struct path. Via path->detnry->inode, the caller of filename_lookup can get the inode. stat command calls statx system call. statx calls filename_lookup eventually. inotify_add_watch system call takes a file name. The inotify_add_watch calls the filename_lookup eventually for getting the inode for the file name. The inode number that inotify_add_watch gets via filename_lookup is printed in the inotify field in fdinfo. The device number, the subject of this issue, can be obtained via path->detnry->inode->i_sb->s_dev. Both the stat command and the inotify field in fdinfo use the filename_lookup for getting path. If they use the same function, why don't the device numbers match? I monitored the device numbers obtained via path->detnry->inode->i_sb->s_dev by inserting a systemtap probe to filename_lookup. I saw the numbers matched. However, the number monitored via systemtap did not match the number printed by the stat command. statx system call doesn't use path->detnry->inode->i_sb->s_dev , the value obtained via filename_lookup, directly. statx calls vfs_statx. vfs_statx calls vfs_getattr after calling the filename_lookup for filling struct kstat. vfs_getattr calls inode->i_op->getattr, a file system specific method for filling struct kstat if it is available. btrfs has an implementation for the method, btrfs_getattr(https://elixir.bootlin.com/linux/v6.2.9/source/fs/btrfs/inode.c#L9007): stat->dev = BTRFS_I(inode)->root->anon_dev; The dev member is overwritten with btrfs specific value. How to adjust the output of lsfd -------------------------------- lsfd already reads mountinfo files. 1. Get the "rawnum" and mount point The device numbers in a mountinfo file are raw; btrfs is not considered. Let's call the number "rawnum" here. When reading the mountinfo file, lsfd can know the mount points of btrfs. grep btrfs /proc/self/mountinfo 72 1 0:35 /root / rw,relatime shared:1 - btrfs 2. Get the cooked num By calling "stat" system call for the mount point getting in the step 1, lsdf can know the device number the btrfs customizes with its getattr method. Let's call the device number "cookednum". 3. Make a table mapping "rawnum" to "cookednum". 4. Look up the table when printing inodes. Signed-off-by: Masatake YAMATO <[email protected]>
When filling SOURCE column, lsfd decodes the name of the device where the file object is. If the file object is sourced from a file system, lsfd fills the column with the file system's name. As util-linux#2349 and util-linux#2308, if the file system is btrfs, lsfd couldn't decode the name correctly. This change and its preceding changes fix this bug. "devnum offset" causes the trouble. On btrfs, the device number reported by stat syscall and proc fs are different. For the details of "devnum offset", see "Mechanism behind the devnum offset". About the way to fix it, see "How to adjust the output of lsfd". Without this change: $ ./lsfd -Q '(ASSOC == "exe")' -p $$ COMMAND PID USER ASSOC XMODE TYPE SOURCE MNTID INODE NAME zsh 19318 yamato exe ------ REG 0:38 0 589767 /usr/bin/zsh With this change: $ ./lsfd -Q '(ASSOC == "exe")' -p $$ COMMAND PID USER ASSOC XMODE TYPE SOURCE MNTID INODE NAME zsh 19318 yamato exe ------ REG btrfs 0 589767 /usr/bin/zsh Mechanisum behind the devnum offset ----------------------------------- Both stat command and the inotify field in fdinfo refer to an inode. filename_lookup(https://elixir.bootlin.com/linux/v6.2.9/source/fs/namei.c#L2495) is the function getting the inode for a given file name. filename_lookup returns a struct path. Via path->detnry->inode, the caller of filename_lookup can get the inode. stat command calls statx system call. statx calls filename_lookup eventually. inotify_add_watch system call takes a file name. The inotify_add_watch calls the filename_lookup eventually for getting the inode for the file name. The inode number that inotify_add_watch gets via filename_lookup is printed in the inotify field in fdinfo. The device number, the subject of this issue, can be obtained via path->detnry->inode->i_sb->s_dev. Both the stat command and the inotify field in fdinfo use the filename_lookup for getting path. If they use the same function, why don't the device numbers match? I monitored the device numbers obtained via path->detnry->inode->i_sb->s_dev by inserting a systemtap probe to filename_lookup. I saw the numbers matched. However, the number monitored via systemtap did not match the number printed by the stat command. statx system call doesn't use path->detnry->inode->i_sb->s_dev , the value obtained via filename_lookup, directly. statx calls vfs_statx. vfs_statx calls vfs_getattr after calling the filename_lookup for filling struct kstat. vfs_getattr calls inode->i_op->getattr, a file system specific method for filling struct kstat if it is available. btrfs has an implementation for the method, btrfs_getattr(https://elixir.bootlin.com/linux/v6.2.9/source/fs/btrfs/inode.c#L9007): stat->dev = BTRFS_I(inode)->root->anon_dev; The dev member is overwritten with btrfs specific value. How to adjust the output of lsfd -------------------------------- lsfd already reads mountinfo files. 1. Get the "rawnum" and mount point The device numbers in a mountinfo file are raw; btrfs is not considered. Let's call the number "rawnum" here. When reading the mountinfo file, lsfd can know the mount points of btrfs. grep btrfs /proc/self/mountinfo 72 1 0:35 /root / rw,relatime shared:1 - btrfs 2. Get the cooked num By calling "stat" system call for the mount point getting in the step 1, lsdf can know the device number the btrfs customizes with its getattr method. Let's call the device number "cookednum". 3. Make a table mapping "rawnum" to "cookednum". 4. Look up the table when printing inodes. Signed-off-by: Masatake YAMATO <[email protected]>
When filling SOURCE column, lsfd decodes the name of the device where the file object is. If the file object is sourced from a file system, lsfd fills the column with the file system's name. As util-linux#2349 and util-linux#2308, if the file system is btrfs, lsfd couldn't decode the name correctly. This change and its preceding changes fix this bug. "devnum offset" causes the trouble. On btrfs, the device number reported by stat syscall and proc fs are different. For the details of "devnum offset", see "Mechanism behind the devnum offset". About the way to fix it, see "How to adjust the output of lsfd". Without this change: $ ./lsfd -Q '(ASSOC == "exe")' -p $$ COMMAND PID USER ASSOC XMODE TYPE SOURCE MNTID INODE NAME zsh 19318 yamato exe ------ REG 0:38 0 589767 /usr/bin/zsh With this change: $ ./lsfd -Q '(ASSOC == "exe")' -p $$ COMMAND PID USER ASSOC XMODE TYPE SOURCE MNTID INODE NAME zsh 19318 yamato exe ------ REG btrfs 0 589767 /usr/bin/zsh Mechanisum behind the devnum offset ----------------------------------- Both stat command and the inotify field in fdinfo refer to an inode. filename_lookup(https://elixir.bootlin.com/linux/v6.2.9/source/fs/namei.c#L2495) is the function getting the inode for a given file name. filename_lookup returns a struct path. Via path->detnry->inode, the caller of filename_lookup can get the inode. stat command calls statx system call. statx calls filename_lookup eventually. inotify_add_watch system call takes a file name. The inotify_add_watch calls the filename_lookup eventually for getting the inode for the file name. The inode number that inotify_add_watch gets via filename_lookup is printed in the inotify field in fdinfo. The device number, the subject of this issue, can be obtained via path->detnry->inode->i_sb->s_dev. Both the stat command and the inotify field in fdinfo use the filename_lookup for getting path. If they use the same function, why don't the device numbers match? I monitored the device numbers obtained via path->detnry->inode->i_sb->s_dev by inserting a systemtap probe to filename_lookup. I saw the numbers matched. However, the number monitored via systemtap did not match the number printed by the stat command. statx system call doesn't use path->detnry->inode->i_sb->s_dev , the value obtained via filename_lookup, directly. statx calls vfs_statx. vfs_statx calls vfs_getattr after calling the filename_lookup for filling struct kstat. vfs_getattr calls inode->i_op->getattr, a file system specific method for filling struct kstat if it is available. btrfs has an implementation for the method, btrfs_getattr(https://elixir.bootlin.com/linux/v6.2.9/source/fs/btrfs/inode.c#L9007): stat->dev = BTRFS_I(inode)->root->anon_dev; The dev member is overwritten with btrfs specific value. How to adjust the output of lsfd -------------------------------- lsfd already reads mountinfo files. 1. Get the "rawnum" and mount point The device numbers in a mountinfo file are raw; btrfs is not considered. Let's call the number "rawnum" here. When reading the mountinfo file, lsfd can know the mount points of btrfs. grep btrfs /proc/self/mountinfo 72 1 0:35 /root / rw,relatime shared:1 - btrfs 2. Get the cooked num By calling "stat" system call for the mount point getting in the step 1, lsdf can know the device number the btrfs customizes with its getattr method. Let's call the device number "cookednum". 3. Make a table mapping "rawnum" to "cookednum". 4. Look up the table when printing inodes. Signed-off-by: Masatake YAMATO <[email protected]>
In addition, INOTIFY.INODES and INOTIFY.INODES.RAW column are added.