diff options
-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 { | |||
10 | struct user_namespace *user_ns; | 10 | struct user_namespace *user_ns; |
11 | u64 seq; /* Sequence number to prevent loops */ | 11 | u64 seq; /* Sequence number to prevent loops */ |
12 | wait_queue_head_t poll; | 12 | wait_queue_head_t poll; |
13 | int event; | 13 | u64 event; |
14 | }; | 14 | }; |
15 | 15 | ||
16 | struct mnt_pcp { | 16 | struct mnt_pcp { |
@@ -104,6 +104,9 @@ struct proc_mounts { | |||
104 | struct mnt_namespace *ns; | 104 | struct mnt_namespace *ns; |
105 | struct path root; | 105 | struct path root; |
106 | int (*show)(struct seq_file *, struct vfsmount *); | 106 | int (*show)(struct seq_file *, struct vfsmount *); |
107 | void *cached_mount; | ||
108 | u64 cached_event; | ||
109 | loff_t cached_index; | ||
107 | }; | 110 | }; |
108 | 111 | ||
109 | #define proc_mounts(p) (container_of((p), struct proc_mounts, m)) | 112 | #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) | |||
52 | } | 52 | } |
53 | __setup("mphash_entries=", set_mphash_entries); | 53 | __setup("mphash_entries=", set_mphash_entries); |
54 | 54 | ||
55 | static int event; | 55 | static u64 event; |
56 | static DEFINE_IDA(mnt_id_ida); | 56 | static DEFINE_IDA(mnt_id_ida); |
57 | static DEFINE_IDA(mnt_group_ida); | 57 | static DEFINE_IDA(mnt_group_ida); |
58 | static DEFINE_SPINLOCK(mnt_id_lock); | 58 | static DEFINE_SPINLOCK(mnt_id_lock); |
@@ -1100,14 +1100,29 @@ static void *m_start(struct seq_file *m, loff_t *pos) | |||
1100 | struct proc_mounts *p = proc_mounts(m); | 1100 | struct proc_mounts *p = proc_mounts(m); |
1101 | 1101 | ||
1102 | down_read(&namespace_sem); | 1102 | down_read(&namespace_sem); |
1103 | return seq_list_start(&p->ns->list, *pos); | 1103 | if (p->cached_event == p->ns->event) { |
1104 | void *v = p->cached_mount; | ||
1105 | if (*pos == p->cached_index) | ||
1106 | return v; | ||
1107 | if (*pos == p->cached_index + 1) { | ||
1108 | v = seq_list_next(v, &p->ns->list, &p->cached_index); | ||
1109 | return p->cached_mount = v; | ||
1110 | } | ||
1111 | } | ||
1112 | |||
1113 | p->cached_event = p->ns->event; | ||
1114 | p->cached_mount = seq_list_start(&p->ns->list, *pos); | ||
1115 | p->cached_index = *pos; | ||
1116 | return p->cached_mount; | ||
1104 | } | 1117 | } |
1105 | 1118 | ||
1106 | static void *m_next(struct seq_file *m, void *v, loff_t *pos) | 1119 | static void *m_next(struct seq_file *m, void *v, loff_t *pos) |
1107 | { | 1120 | { |
1108 | struct proc_mounts *p = proc_mounts(m); | 1121 | struct proc_mounts *p = proc_mounts(m); |
1109 | 1122 | ||
1110 | return seq_list_next(v, &p->ns->list, pos); | 1123 | p->cached_mount = seq_list_next(v, &p->ns->list, pos); |
1124 | p->cached_index = *pos; | ||
1125 | return p->cached_mount; | ||
1111 | } | 1126 | } |
1112 | 1127 | ||
1113 | static void m_stop(struct seq_file *m, void *v) | 1128 | 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, | |||
267 | p->root = root; | 267 | p->root = root; |
268 | p->m.poll_event = ns->event; | 268 | p->m.poll_event = ns->event; |
269 | p->show = show; | 269 | p->show = show; |
270 | p->cached_event = ~0ULL; | ||
270 | 271 | ||
271 | return 0; | 272 | return 0; |
272 | 273 | ||