[PATCH 6/6] fs: Introduce kern_mount_special() to mount special vfs

From: Eric Dumazet
Date: Wed Nov 26 2008 - 18:34:37 EST


This function arms a flag (MNT_SPECIAL) on the vfs, to avoid
refcounting on permanent system vfs.
Use this function for sockets, pipes, anonymous fds.

(socket8 bench result : from 2.94s to 2.23s)

Signed-off-by: Eric Dumazet <dada1@xxxxxxxxxxxxx>
---
fs/anon_inodes.c | 2 +-
fs/pipe.c | 2 +-
fs/super.c | 9 +++++++++
include/linux/fs.h | 1 +
include/linux/mount.h | 5 +++--
net/socket.c | 2 +-
6 files changed, 16 insertions(+), 5 deletions(-)

diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c
index a0212b3..42dfe28 100644
--- a/fs/anon_inodes.c
+++ b/fs/anon_inodes.c
@@ -153,7 +153,7 @@ static int __init anon_inode_init(void)
error = register_filesystem(&anon_inode_fs_type);
if (error)
goto err_exit;
- anon_inode_mnt = kern_mount(&anon_inode_fs_type);
+ anon_inode_mnt = kern_mount_special(&anon_inode_fs_type);
if (IS_ERR(anon_inode_mnt)) {
error = PTR_ERR(anon_inode_mnt);
goto err_unregister_filesystem;
diff --git a/fs/pipe.c b/fs/pipe.c
index 6fca681..391d4fe 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -1074,7 +1074,7 @@ static int __init init_pipe_fs(void)
int err = register_filesystem(&pipe_fs_type);

if (!err) {
- pipe_mnt = kern_mount(&pipe_fs_type);
+ pipe_mnt = kern_mount_special(&pipe_fs_type);
if (IS_ERR(pipe_mnt)) {
err = PTR_ERR(pipe_mnt);
unregister_filesystem(&pipe_fs_type);
diff --git a/fs/super.c b/fs/super.c
index 400a760..a8e14f7 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -982,3 +982,12 @@ struct vfsmount *kern_mount_data(struct file_system_type *type, void *data)
}

EXPORT_SYMBOL_GPL(kern_mount_data);
+
+struct vfsmount *kern_mount_special(struct file_system_type *type)
+{
+ struct vfsmount *res = kern_mount_data(type, NULL);
+
+ if (!IS_ERR(res))
+ res->mnt_flags |= MNT_SPECIAL;
+ return res;
+}
diff --git a/include/linux/fs.h b/include/linux/fs.h
index dd0e8a5..a92544a 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1591,6 +1591,7 @@ extern int register_filesystem(struct file_system_type *);
extern int unregister_filesystem(struct file_system_type *);
extern struct vfsmount *kern_mount_data(struct file_system_type *, void *data);
#define kern_mount(type) kern_mount_data(type, NULL)
+extern struct vfsmount *kern_mount_special(struct file_system_type *);
extern int may_umount_tree(struct vfsmount *);
extern int may_umount(struct vfsmount *);
extern long do_mount(char *, char *, char *, unsigned long, void *);
diff --git a/include/linux/mount.h b/include/linux/mount.h
index cab2a85..cb4fa90 100644
--- a/include/linux/mount.h
+++ b/include/linux/mount.h
@@ -30,6 +30,7 @@ struct mnt_namespace;

#define MNT_SHRINKABLE 0x100
#define MNT_IMBALANCED_WRITE_COUNT 0x200 /* just for debugging */
+#define MNT_SPECIAL 0x400 /* special mount (pipes,sockets,...) */

#define MNT_SHARED 0x1000 /* if the vfsmount is a shared mount */
#define MNT_UNBINDABLE 0x2000 /* if the vfsmount is a unbindable mount */
@@ -73,7 +74,7 @@ struct vfsmount {

static inline struct vfsmount *mntget(struct vfsmount *mnt)
{
- if (mnt)
+ if (mnt && !(mnt->mnt_flags & MNT_SPECIAL))
atomic_inc(&mnt->mnt_count);
return mnt;
}
@@ -87,7 +88,7 @@ extern int __mnt_is_readonly(struct vfsmount *mnt);

static inline void mntput(struct vfsmount *mnt)
{
- if (mnt) {
+ if (mnt && !(mnt->mnt_flags & MNT_SPECIAL)) {
mnt->mnt_expiry_mark = 0;
mntput_no_expire(mnt);
}
diff --git a/net/socket.c b/net/socket.c
index 4177456..2857d70 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -2204,7 +2204,7 @@ static int __init sock_init(void)

init_inodecache();
register_filesystem(&sock_fs_type);
- sock_mnt = kern_mount(&sock_fs_type);
+ sock_mnt = kern_mount_special(&sock_fs_type);
sock_mnt->mnt_sb->s_flags |= MS_SPECIAL;

/* The real protocol initialization is performed in later initcalls.