===
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
===
Signed-off-by: Satoru Takeuchi <satoru.takeuchi@gmail.com>
CC: Signed-off-by: Mark Fasheh <mfasheh@suse.de>
---
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(-)
@@ -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");
@@ -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;
+}
@@ -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)
{
@@ -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;
}
@@ -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;
}
@@ -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;
}
@@ -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 */