diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2014-02-27 14:40:10 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2014-04-01 23:19:09 -0400 |
commit | c7999c3627bc6d49aa6fb9451063938cfd2c2082 (patch) | |
tree | 05dba953a6e648864cfa580ae6f754b1570e1f46 | |
parent | f2ebb3a921c1ca1e2ddd9242e95a1989a50c4c68 (diff) | |
download | linux-stable-c7999c3627bc6d49aa6fb9451063938cfd2c2082.tar.gz linux-stable-c7999c3627bc6d49aa6fb9451063938cfd2c2082.tar.bz2 linux-stable-c7999c3627bc6d49aa6fb9451063938cfd2c2082.zip |
reduce m_start() cost...
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r-- | fs/mount.h | 5 | ||||
-rw-r--r-- | fs/namespace.c | 21 | ||||
-rw-r--r-- | fs/proc_namespace.c | 1 |
3 files changed, 23 insertions, 4 deletions
diff --git a/fs/mount.h b/fs/mount.h index b29e42f05f34..d55297f2fa05 100644 --- a/fs/mount.h +++ b/fs/mount.h @@ -10,7 +10,7 @@ struct mnt_namespace { struct user_namespace *user_ns; u64 seq; /* Sequence number to prevent loops */ wait_queue_head_t poll; - int event; + u64 event; }; struct mnt_pcp { @@ -104,6 +104,9 @@ struct proc_mounts { struct mnt_namespace *ns; struct path root; int (*show)(struct seq_file *, struct vfsmount *); + void *cached_mount; + u64 cached_event; + loff_t cached_index; }; #define proc_mounts(p) (container_of((p), struct proc_mounts, m)) diff --git a/fs/namespace.c b/fs/namespace.c index 65233a5f390a..a66aff5bd3fe 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -52,7 +52,7 @@ static int __init set_mphash_entries(char *str) } __setup("mphash_entries=", set_mphash_entries); -static int event; +static u64 event; static DEFINE_IDA(mnt_id_ida); static DEFINE_IDA(mnt_group_ida); static DEFINE_SPINLOCK(mnt_id_lock); @@ -1100,14 +1100,29 @@ static void *m_start(struct seq_file *m, loff_t *pos) struct proc_mounts *p = proc_mounts(m); down_read(&namespace_sem); - return seq_list_start(&p->ns->list, *pos); + if (p->cached_event == p->ns->event) { + void *v = p->cached_mount; + if (*pos == p->cached_index) + return v; + if (*pos == p->cached_index + 1) { + v = seq_list_next(v, &p->ns->list, &p->cached_index); + return p->cached_mount = v; + } + } + + p->cached_event = p->ns->event; + p->cached_mount = seq_list_start(&p->ns->list, *pos); + p->cached_index = *pos; + return p->cached_mount; } static void *m_next(struct seq_file *m, void *v, loff_t *pos) { struct proc_mounts *p = proc_mounts(m); - return seq_list_next(v, &p->ns->list, pos); + p->cached_mount = seq_list_next(v, &p->ns->list, pos); + p->cached_index = *pos; + return p->cached_mount; } static void m_stop(struct seq_file *m, void *v) diff --git a/fs/proc_namespace.c b/fs/proc_namespace.c index 7be26f03a3f5..1a81373947f3 100644 --- a/fs/proc_namespace.c +++ b/fs/proc_namespace.c @@ -267,6 +267,7 @@ static int mounts_open_common(struct inode *inode, struct file *file, p->root = root; p->m.poll_event = ns->event; p->show = show; + p->cached_event = ~0ULL; return 0; |