fix inconsistent device between /proc/pid/maps and stat
Subsystems (4)
PATCH 1/1 fix inconsistent device between /proc/pid/maps and stat
There have been some discussions about inconsistent device between /proc/pid/maps and stat(2).
http://thr3ads.net/btrfs-devel/2011/05/2346176-RFC-PATCH-0-2-btrfs-vfs-Return-same-device-in-stat-2-and-proc-pid-maps
https://www.spinics.net/lists/linux-btrfs/msg09044.html
https://patchwork.kernel.org/patch/2825842/
https://patchwork.kernel.org/patch/2831525/
It's important since it breaks user programs like lsof(8). There was a patche by Mark to fix this problem. However, unfortunately, that patch is not merged so far.
NOTE:
1) This patch is inspired by the Mark's one and I tweak it as follows.
- move a flag for this fix from sb->s_flags to kernel internal sb->s_iflags
- change that flag's name from MS_STAT_FOR_DEV to SB_I_LOGICALVOL, to make its meaning clearer
2) This patch is for Chris's for-linus-4.11 (commit e1699d2d7bf6e6cce3e1baff19f9dd4595a58664 ("")). It should modify to apply to 4.11-rcX because of statx patches changes
struct inode_operations->getattr() interface.
For more information about this problem, please refer to the patchat the end of this mail.
---
Subject: [PATCH] fix inconsistent devie between /proc/pid/maps and stat
/proc/pid/maps returns each device as follows.
===
dev = inode->i_sb->s_dev;
===
However, stat(2) returns it as follows.
===stat->dev = BTRFS_I(inode)->root->anon_dev;
===
It results in device mismatch and this inconsistency breaks users programs like lsof(8) as follows.
Without this patch:
===
$ mount | grep /home/vagrant/mnt /dev/vda5 on /home/vagrant/mnt type btrfs (rw,relatime,noacl,space_cache,subvolid=5,subvol=/) $ /home/vagrant/mnt/lsof | grep /home/vagrant/mnt lsof 19292 root txt REG 0,44 163136 257 /home/sat/mnt/lsof lsof 19292 root mem REG 0,42 257 /home/sat/mnt/lsof (path dev=0,44) lsof 19294 root txt REG 0,44 163136 257 /home/sat/mnt/lsof lsof 19294 root mem REG 0,42 257 /home/sat/mnt/lsof (path dev=0,44) ===
With this patch:
===
$ mount | grep /home/vagrant/mnt /dev/vda5 on /home/vagrant/mnt type btrfs (rw,relatime,noacl,space_cache,subvolid=5,subvol=/) $ /home/vagrant/mnt/lsof | grep /home/vagrant/mnt lsof 752 root txt REG 0,44 163224 263 /home/vagrant/mnt/lsof lsof 754 root txt REG 0,44 163224 263 /home/vagrant/mnt/lsof ===
--- fs/btrfs/super.c | 1 + fs/proc/generic.c | 13 +++++++++++++ fs/proc/internal.h | 1 + fs/proc/nommu.c | 2 +- fs/proc/task_mmu.c | 2 +- fs/proc/task_nommu.c | 2 +- include/linux/fs.h | 1 + 7 files changed, 19 insertions(+), 3 deletions(-)
fs/btrfs/super.c +1 -0
@@ -1133,6 +1133,7 @@ static int btrfs_fill_super(struct super_block *sb,#endif sb->s_flags |=MS_I_VERSION ; sb->s_iflags |=SB_I_CGROUPWB ; + sb->s_iflags |=SB_I_LOGICALVOL ; err =open_ctree (sb, fs_devices, (char *)data);if (err) {btrfs_err (fs_info,"open_ctree failed" );
fs/proc/generic.c +13 -0
@@ -646,3 +646,16 @@ void *PDE_DATA(const struct inode *inode)return __PDE_DATA (inode); }EXPORT_SYMBOL (PDE_DATA ); + +dev_t proc_get_map_dev (struct dentry *dentry) +{ +struct inode *inode = dentry->d_inode; +struct kstat kstat; + +if (inode->i_sb->s_iflags &SB_I_LOGICALVOL && + inode->i_op->getattr && + inode->i_op->getattr (NULL , dentry, &kstat) ==0 ) +return kstat.dev; + +return inode->i_sb->s_dev; +}
fs/proc/internal.h +1 -0
@@ -190,6 +190,7 @@ static inline struct proc_dir_entry *pde_get(struct proc_dir_entry *pde)return pde; }extern void pde_put (struct proc_dir_entry *); +dev_t proc_get_map_dev (struct dentry *);static inline bool is_empty_pde (const struct proc_dir_entry *pde) {
fs/proc/nommu.c +1 -1
@@ -46,7 +46,7 @@ static int nommu_region_show(struct seq_file *m, struct vm_region *region)if (file) {struct inode *inode =file_inode (region->vm_file); - dev = inode->i_sb->s_dev; + dev =proc_get_map_dev (vma->vm_file->f_path.dentry); ino = inode->i_ino; }
fs/proc/task_mmu.c +1 -1
@@ -292,7 +292,7 @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma, int is_pid)if (file) {struct inode *inode =file_inode (vma->vm_file); - dev = inode->i_sb->s_dev; + dev =proc_get_map_dev (vma->vm_file->f_path.dentry); ino = inode->i_ino; pgoff = ((loff_t )vma->vm_pgoff) <<PAGE_SHIFT ; }
fs/proc/task_nommu.c +1 -1
@@ -156,7 +156,7 @@ static int nommu_vma_show(struct seq_file *m, struct vm_area_struct *vma,if (file) {struct inode *inode =file_inode (vma->vm_file); - dev = inode->i_sb->s_dev; + dev =proc_get_map_dev (vma->vm_file->f_path.dentry); ino = inode->i_ino; pgoff = (loff_t )vma->vm_pgoff <<PAGE_SHIFT ; }
include/linux/fs.h +1 -0
@@ -1262,6 +1262,7 @@ struct mm_struct;#define SB_I_CGROUPWB 0x00000001/* cgroup-aware writeback enabled */ #define SB_I_NOEXEC 0x00000002/* Ignore executables on this fs */ #define SB_I_NODEV 0x00000004/* Ignore devices on this fs */ +#define SB_I_LOGICALVOL 0x00000008/* this fs supports logical volumes */ /* sb->s_iflags to limit user namespace mounts */ #define SB_I_USERNS_VISIBLE 0x00000010/* fstype already mounted */
Signature · 1 line
2.11.0
Quoted 9 lines · Satoru Takeuchi
There have been some discussions about inconsistent device between
/proc/pid/mapsand stat(2).http://thr3ads.net/btrfs-devel/2011/05/2346176-RFC-PATCH-0-2-btrfs-vfs-Return-same-device-in-stat-2-and-proc-pid-maps
https://www.spinics.net/lists/linux-btrfs/msg09044.html
https://patchwork.kernel.org/patch/2825842/
https://patchwork.kernel.org/patch/2831525/It's important since it breaks user programs like lsof(8). There was a patche by Mark to fix this problem. However, unfortunately, that patch is not merged so far.
And no variant of the get_map_dev will ever be merged. Reworking this requires extensions to the superblock and subvolume structures, making it more generic and suitable for VFS.
2017-03-24 20:58 GMT+09:00 David Sterba <[email protected]>:
Quoted 8 lines · Satoru Takeuchi
Quoted 7 lines
There have been some discussions about inconsistent device between
/proc/pid/mapsand stat(2).http://thr3ads.net/btrfs-devel/2011/05/2346176-RFC-PATCH-0-2-btrfs-vfs-Return-same-device-in-stat-2-and-proc-pid-maps
https://www.spinics.net/lists/linux-btrfs/msg09044.html
https://patchwork.kernel.org/patch/2825842/
https://patchwork.kernel.org/patch/2831525/
Quoted 6 lines
Quoted 2 lines
It's important since it breaks user programs like lsof(8). There was a patche by Mark to fix this problem. However, unfortunately, that patch is not merged so far.
And no variant of the
get_map_devwill ever be merged. Reworking this requires extensions to the superblock and subvolume structures, making it more generic and suitable for VFS.
Thank you for your comment. I'm going to reconsider how to fix this problem.
Thanks,
Satoru