[RFC][PATCH 0/2] btrfs/vfs: Return same device in stat(2) and /proc/pid/maps

2 messages, 1 author, 2011-05-13 · open the first message on its own page

[RFC][PATCH 0/2] btrfs/vfs: Return same device in stat(2) and /proc/pid/maps

From: Mark Fasheh <hidden>
Date: 2011-05-13 23:21:36

I originally posted about this issue some weeks ago but unfortunately didn't
get a response:

http://comments.gmane.org/gmane.comp.file-systems.btrfs/9682


To recap:

btrfs_getattr() is filling stat->dev with an anonymous device
(for per-snapshot root?):

stat->dev = BTRFS_I(inode)->root->anon_super.s_dev;

but /proc/pid/maps uses the "real" block device:

dev = inode->i_sb->s_dev;


This results in some unfortunate behavior for lsof as it reports some
duplicate paths (except on different block devices). The easiest way to see
this (if your root partition is btrfs):

$ lsof | grep lsof
<snip>
lsof       9238            root  txt       REG               0,19   139736 14478 /usr/bin/lsof
lsof       9238            root  mem       REG               0,17   14478 /usr/bin/lsof (path dev=0,19)


As was noted in my original mail, this winds up breaking userspace software
(zypper in my case).

The following patch series fixes this issue by allowing a file
system to supply a custom method for the device reported in /proc/pid/maps.
It fixes the issue for me, but I'm not 100% sold on the approach taken -
it's an admittedly brute-force solution hence the RFC tag. Any comments are
appreciated and welcome.

Thanks,
	--Mark

[RFC][PATCH 1/2] vfs: allow /proc/pid/maps to return a custom device

From: Mark Fasheh <hidden>
Date: 2011-05-13 23:21:58

This patch introduces a callback in the super_operations structure,
'get_maps_dev' which is then used by procfs to query which device to return
for reporting in /proc/[PID]/maps.

btrfs wants this so that it can return the same device as it uses from
stat(2) calls.

Signed-off-by: Mark Fasheh <redacted>
---
 fs/proc/task_mmu.c   |    2 +-
 fs/proc/task_nommu.c |    2 +-
 include/linux/fs.h   |    8 ++++++++
 3 files changed, 10 insertions(+), 2 deletions(-)
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 2e7addf..c0acc19 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -220,7 +220,7 @@ static void show_map_vma(struct seq_file *m, struct vm_area_struct *vma)
 
 	if (file) {
 		struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
-		dev = inode->i_sb->s_dev;
+		dev = get_maps_dev(inode);
 		ino = inode->i_ino;
 		pgoff = ((loff_t)vma->vm_pgoff) << PAGE_SHIFT;
 	}
diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c
index 980de54..6769efe 100644
--- a/fs/proc/task_nommu.c
+++ b/fs/proc/task_nommu.c
@@ -148,7 +148,7 @@ static int nommu_vma_show(struct seq_file *m, struct vm_area_struct *vma)
 
 	if (file) {
 		struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
-		dev = inode->i_sb->s_dev;
+		dev = get_maps_dev(inode);
 		ino = inode->i_ino;
 		pgoff = (loff_t)vma->vm_pgoff << PAGE_SHIFT;
 	}
diff --git a/include/linux/fs.h b/include/linux/fs.h
index dbd860a..ad683ad 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1637,8 +1637,16 @@ struct super_operations {
 	ssize_t (*quota_write)(struct super_block *, int, const char *, size_t, loff_t);
 #endif
 	int (*bdev_try_to_free_page)(struct super_block*, struct page*, gfp_t);
+	dev_t (*get_maps_dev)(struct inode *);
 };
 
+static inline dev_t get_maps_dev(struct inode *inode)
+{
+	if (inode->i_sb->s_op->get_maps_dev)
+		return inode->i_sb->s_op->get_maps_dev(inode);
+	return inode->i_sb->s_dev;
+}
+
 /*
  * Inode state bits.  Protected by inode->i_lock
  *
-- 
1.6.4.2
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help