[RFC PATCH v2] vfs: optimization to /proc/<pid>/mountinfo patch

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



1) reports deleted inode in dentry_path() consistent with that in __d_path()
2) modified __d_path() to use prepend(), reducing the size of __d_path()
3) moved all the functionality that reports mount information in /proc under
	CONFIG_PROC_FS.


Code compile tested only with and without CONFIG_PROC_FS.


Signed-off-by: Ram Pai <linuxram@xxxxxxxxxx>
---
 fs/dcache.c              |   66 +++++++++++++++++++----------------------------
 fs/namespace.c           |   15 +++++++++-
 fs/pnode.c               |   24 +++++++++++------
 fs/pnode.h               |    6 +++-
 fs/seq_file.c            |    2 +
 include/linux/dcache.h   |    3 ++
 include/linux/mount.h    |    2 +
 include/linux/seq_file.h |    3 ++
 8 files changed, 73 insertions(+), 48 deletions(-)

Index: linux-2.6.24/fs/dcache.c
===================================================================
--- linux-2.6.24.orig/fs/dcache.c
+++ linux-2.6.24/fs/dcache.c
@@ -1747,6 +1747,17 @@ shouldnt_be_hashed:
 	goto shouldnt_be_hashed;
 }
 
+static int prepend(char **buffer, int *buflen, const char *str,
+			  int namelen)
+{
+	*buflen -= namelen;
+	if (*buflen < 0)
+		return -ENAMETOOLONG;
+	*buffer -= namelen;
+	memcpy(*buffer, str, namelen);
+	return 0;
+}
+
 /**
  * d_path - return the path of a dentry
  * @dentry: dentry to report
@@ -1768,17 +1779,11 @@ static char *__d_path(struct dentry *den
 {
 	char * end = buffer+buflen;
 	char * retval;
-	int namelen;
 
-	*--end = '\0';
-	buflen--;
-	if (!IS_ROOT(dentry) && d_unhashed(dentry)) {
-		buflen -= 10;
-		end -= 10;
-		if (buflen < 0)
+	prepend(&end, &buflen, "\0", 1);
+	if (!IS_ROOT(dentry) && d_unhashed(dentry) &&
+		(prepend(&end, &buflen, " (deleted)", 10) != 0))
 			goto Elong;
-		memcpy(end, " (deleted)", 10);
-	}
 
 	if (buflen < 1)
 		goto Elong;
@@ -1805,13 +1810,10 @@ static char *__d_path(struct dentry *den
 		}
 		parent = dentry->d_parent;
 		prefetch(parent);
-		namelen = dentry->d_name.len;
-		buflen -= namelen + 1;
-		if (buflen < 0)
+		if ((prepend(&end, &buflen, dentry->d_name.name,
+				dentry->d_name.len) != 0) ||
+		    (prepend(&end, &buflen, "/", 1) != 0))
 			goto Elong;
-		end -= namelen;
-		memcpy(end, dentry->d_name.name, namelen);
-		*--end = '/';
 		retval = end;
 		dentry = parent;
 	}
@@ -1819,12 +1821,10 @@ static char *__d_path(struct dentry *den
 	return retval;
 
 global_root:
-	namelen = dentry->d_name.len;
-	buflen -= namelen;
-	if (buflen < 0)
-		goto Elong;
-	retval -= namelen-1;	/* hit the slash */
-	memcpy(retval, dentry->d_name.name, namelen);
+	retval += 1;	/* hit the slash */
+	if (prepend(&retval, &buflen, dentry->d_name.name,
+			dentry->d_name.len) !=0 )
+			goto Elong;
 	return retval;
 Elong:
 	return ERR_PTR(-ENAMETOOLONG);
@@ -1890,17 +1890,8 @@ char *dynamic_dname(struct dentry *dentr
 	return memcpy(buffer, temp, sz);
 }
 
-static int prepend(char **buffer, int *buflen, const char *str,
-			  int namelen)
-{
-	*buflen -= namelen;
-	if (*buflen < 0)
-		return 1;
-	*buffer -= namelen;
-	memcpy(*buffer, str, namelen);
-	return 0;
-}
 
+#ifdef CONFIG_PROC_FS
 /*
  * Write full pathname from the root of the filesystem into the buffer.
  */
@@ -1910,11 +1901,9 @@ char *dentry_path(struct dentry *dentry,
 	char *retval;
 
 	spin_lock(&dcache_lock);
-	prepend(&end, &buflen, "\0", 1);
-	if (!IS_ROOT(dentry) && d_unhashed(dentry)) {
-		if (prepend(&end, &buflen, "//deleted", 9))
+	if (!IS_ROOT(dentry) && d_unhashed(dentry) &&
+		(prepend(&end, &buflen, " (deleted)", 10) != 0))
 			goto Elong;
-	}
 	if (buflen < 1)
 		goto Elong;
 	/* Get '/' right */
@@ -1929,9 +1918,9 @@ char *dentry_path(struct dentry *dentry,
 		parent = dentry->d_parent;
 		prefetch(parent);
 
-		if (prepend(&end, &buflen, dentry->d_name.name,
-				dentry->d_name.len) ||
-		    prepend(&end, &buflen, "/", 1))
+		if ((prepend(&end, &buflen, dentry->d_name.name,
+				dentry->d_name.len) != 0) ||
+		    (prepend(&end, &buflen, "/", 1) != 0))
 			goto Elong;
 
 		retval = end;
@@ -1943,6 +1932,7 @@ Elong:
 	spin_unlock(&dcache_lock);
 	return ERR_PTR(-ENAMETOOLONG);
 }
+#endif /* CONFIG_PROC_FS */
 
 /*
  * NOTE! The user-level library version returns a
Index: linux-2.6.24/fs/namespace.c
===================================================================
--- linux-2.6.24.orig/fs/namespace.c
+++ linux-2.6.24/fs/namespace.c
@@ -40,7 +40,10 @@
 __cacheline_aligned_in_smp DEFINE_SPINLOCK(vfsmount_lock);
 
 static int event;
+
+#ifdef CONFIG_PROC_FS
 static DEFINE_IDA(mnt_id_ida);
+#endif /* CONFIG_PROC_FS */
 
 static struct list_head *mount_hashtable __read_mostly;
 static struct kmem_cache *mnt_cache __read_mostly;
@@ -60,6 +63,7 @@ static inline unsigned long hash(struct 
 
 #define MNT_WRITER_UNDERFLOW_LIMIT -(1<<16)
 
+#ifdef CONFIG_PROC_FS
 static int mnt_alloc_id(struct vfsmount *mnt)
 {
 	int res;
@@ -82,11 +86,14 @@ static void mnt_free_id(struct vfsmount 
 	ida_remove(&mnt_id_ida, mnt->mnt_id);
 	spin_unlock(&vfsmount_lock);
 }
+#endif /* CONFIG_PROC_FS */
 
 struct vfsmount *alloc_vfsmnt(const char *name)
 {
 	struct vfsmount *mnt = kmem_cache_zalloc(mnt_cache, GFP_KERNEL);
 	if (mnt) {
+
+#ifdef CONFIG_PROC_FS
 		int err;
 
 		err = mnt_alloc_id(mnt);
@@ -96,6 +103,8 @@ struct vfsmount *alloc_vfsmnt(const char
 		}
 
 		mnt->mnt_pgid = -1;
+#endif /* CONFIG_PROC_FS */
+
 		atomic_set(&mnt->mnt_count, 1);
 		INIT_LIST_HEAD(&mnt->mnt_hash);
 		INIT_LIST_HEAD(&mnt->mnt_child);
@@ -381,7 +390,9 @@ EXPORT_SYMBOL(simple_set_mnt);
 void free_vfsmnt(struct vfsmount *mnt)
 {
 	kfree(mnt->mnt_devname);
+#ifdef CONFIG_PROC_FS
 	mnt_free_id(mnt);
+#endif /* CONFIG_PROC_FS */
 	kmem_cache_free(mnt_cache, mnt);
 }
 
@@ -679,6 +690,7 @@ void save_mount_options(struct super_blo
 }
 EXPORT_SYMBOL(save_mount_options);
 
+#ifdef CONFIG_PROC_FS
 /* iterator */
 static void *m_start(struct seq_file *m, loff_t *pos)
 {
@@ -808,7 +820,7 @@ static int show_mountinfo(struct seq_fil
 			if (IS_MNT_SHARED(mnt))
 				seq_putc(m, ',');
 
-			seq_printf(m, "slave:%i", get_master_id(mnt));
+			seq_printf(m, "slave:%i", get_master_group_id(mnt));
 			if (dominator_id != -1)
 				seq_printf(m, ":%i", dominator_id);
 		}
@@ -866,6 +878,7 @@ const struct seq_operations mountstats_o
 	.stop	= m_stop,
 	.show	= show_vfsstat,
 };
+#endif  /* CONFIG_PROC_FS */
 
 /**
  * may_umount_tree - check if a mount tree is busy
Index: linux-2.6.24/fs/seq_file.c
===================================================================
--- linux-2.6.24.orig/fs/seq_file.c
+++ linux-2.6.24/fs/seq_file.c
@@ -391,6 +391,7 @@ int seq_path(struct seq_file *m, struct 
 }
 EXPORT_SYMBOL(seq_path);
 
+#ifdef CONFIG_PROC_FS
 /*
  * returns the path of the 'dentry' from the root of its filesystem.
  */
@@ -412,6 +413,7 @@ int seq_dentry(struct seq_file *m, struc
 	return -1;
 }
 EXPORT_SYMBOL(seq_dentry);
+#endif /* CONFIG_PROC_FS */
 
 static void *single_start(struct seq_file *p, loff_t *pos)
 {
Index: linux-2.6.24/include/linux/dcache.h
===================================================================
--- linux-2.6.24.orig/include/linux/dcache.h
+++ linux-2.6.24/include/linux/dcache.h
@@ -303,7 +303,10 @@ extern int d_validate(struct dentry *, s
 extern char *dynamic_dname(struct dentry *, char *, int, const char *, ...);
 
 extern char *d_path(struct path *, char *, int);
+
+#ifdef CONFIG_PROC_FS
 extern char *dentry_path(struct dentry *, char *, int);
+#endif /* CONFIG_PROC_FS */
 
 /* Allocation counts.. */
 
Index: linux-2.6.24/include/linux/seq_file.h
===================================================================
--- linux-2.6.24.orig/include/linux/seq_file.h
+++ linux-2.6.24/include/linux/seq_file.h
@@ -44,7 +44,10 @@ int seq_printf(struct seq_file *, const 
 	__attribute__ ((format (printf,2,3)));
 
 int seq_path(struct seq_file *, struct path *, char *);
+
+#ifdef CONFIG_PROC_FS
 int seq_dentry(struct seq_file *, struct dentry *, char *);
+#endif /* CONFIG_PROC_FS */
 
 int single_open(struct file *, int (*)(struct seq_file *, void *), void *);
 int single_release(struct inode *, struct file *);
Index: linux-2.6.24/fs/pnode.c
===================================================================
--- linux-2.6.24.orig/fs/pnode.c
+++ linux-2.6.24/fs/pnode.c
@@ -12,8 +12,10 @@
 #include <linux/idr.h>
 #include "pnode.h"
 
+#ifdef CONFIG_PROC_FS
 static DEFINE_SPINLOCK(mnt_pgid_lock);
 static DEFINE_IDA(mnt_pgid_ida);
+#endif /* CONFIG_PROC_FS */
 
 /* return the next shared peer mount of @p */
 static inline struct vfsmount *next_peer(struct vfsmount *p)
@@ -42,18 +44,18 @@ void set_mnt_shared(struct vfsmount *mnt
 	int res;
 
  retry:
-	spin_lock(&mnt_pgid_lock);
-	if (IS_MNT_SHARED(mnt)) {
-		spin_unlock(&mnt_pgid_lock);
+	if (IS_MNT_SHARED(mnt))
 		return;
-	}
 
+#ifdef CONFIG_PROC_FS
+	spin_lock(&mnt_pgid_lock);
 	res = ida_get_new(&mnt_pgid_ida, &mnt->mnt_pgid);
 	spin_unlock(&mnt_pgid_lock);
 	if (res == -EAGAIN) {
 		if (ida_pre_get(&mnt_pgid_ida, GFP_KERNEL))
 			goto retry;
 	}
+#endif /* CONFIG_PROC_FS */
 	__set_mnt_shared(mnt);
 }
 
@@ -61,10 +63,13 @@ void clear_mnt_shared(struct vfsmount *m
 {
 	if (IS_MNT_SHARED(mnt)) {
 		mnt->mnt_flags &= ~MNT_SHARED;
+#ifdef CONFIG_PROC_FS
 		mnt->mnt_pgid = -1;
+#endif /* CONFIG_PROC_FS */
 	}
 }
 
+#ifdef CONFIG_PROC_FS
 void make_mnt_peer(struct vfsmount *old, struct vfsmount *mnt)
 {
 	mnt->mnt_pgid = old->mnt_pgid;
@@ -77,7 +82,7 @@ int get_peer_group_id(struct vfsmount *m
 	return mnt->mnt_pgid;
 }
 
-int get_master_id(struct vfsmount *mnt)
+int get_master_group_id(struct vfsmount *mnt)
 {
 	int id;
 
@@ -119,6 +124,7 @@ int get_dominator_id_same_ns(struct vfsm
 
 	return id;
 }
+#endif /* CONFIG_PROC_FS */
 
 static int do_make_slave(struct vfsmount *mnt)
 {
@@ -138,13 +144,15 @@ static int do_make_slave(struct vfsmount
 		if (peer_mnt == mnt)
 			peer_mnt = NULL;
 	}
-	if (!list_empty(&mnt->mnt_share))
-		list_del_init(&mnt->mnt_share);
-	else if (IS_MNT_SHARED(mnt)) {
+
+#ifdef CONFIG_PROC_FS
+	if (IS_MNT_SHARED(mnt) && list_empty(&mnt->mnt_share)) {
 		spin_lock(&mnt_pgid_lock);
 		ida_remove(&mnt_pgid_ida, mnt->mnt_pgid);
 		spin_unlock(&mnt_pgid_lock);
 	}
+#endif /* CONFIG_PROC_FS */
+	list_del_init(&mnt->mnt_share);
 
 	if (peer_mnt)
 		master = peer_mnt;
Index: linux-2.6.24/fs/pnode.h
===================================================================
--- linux-2.6.24.orig/fs/pnode.h
+++ linux-2.6.24/fs/pnode.h
@@ -31,7 +31,11 @@ int propagate_mnt(struct vfsmount *, str
 		struct list_head *);
 int propagate_umount(struct list_head *);
 int propagate_mount_busy(struct vfsmount *, int);
+
+#ifdef CONFIG_PROC_FS
 int get_peer_group_id(struct vfsmount *);
-int get_master_id(struct vfsmount *);
+int get_master_group_id(struct vfsmount *);
 int get_dominator_id_same_ns(struct vfsmount *);
+#endif /* CONFIG_PROC_FS */
+
 #endif /* _LINUX_PNODE_H */
Index: linux-2.6.24/include/linux/mount.h
===================================================================
--- linux-2.6.24.orig/include/linux/mount.h
+++ linux-2.6.24/include/linux/mount.h
@@ -56,8 +56,10 @@ struct vfsmount {
 	struct list_head mnt_slave;	/* slave list entry */
 	struct vfsmount *mnt_master;	/* slave is on master->mnt_slave_list */
 	struct mnt_namespace *mnt_ns;	/* containing namespace */
+#ifdef CONFIG_PROC_FS
 	int mnt_id;			/* mount identifier */
 	int mnt_pgid;			/* peer group identifier */
+#endif /* CONFIG_PROC_FS */
 	/*
 	 * We put mnt_count & mnt_expiry_mark at the end of struct vfsmount
 	 * to let these frequently modified fields in a separate cache line


--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]
  Powered by Linux