summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikolay Borisov <kernel@kyup.com>2016-08-17 16:18:46 -0400
committerJeff Layton <jlayton@redhat.com>2016-08-18 13:49:41 -0400
commitd67fd44f697dff293d7cdc29af929241b669affe (patch)
tree0c1e26c0d0669db52f4a50f6cb15a9e7fa4b2ea6
parent5ff132c07aa155d759ab3da946c86351313d3020 (diff)
locks: Filter /proc/locks output on proc pid ns
On busy container servers reading /proc/locks shows all the locks created by all clients. This can cause large latency spikes. In my case I observed lsof taking up to 5-10 seconds while processing around 50k locks. Fix this by limiting the locks shown only to those created in the same pidns as the one the proc fs was mounted in. When reading /proc/locks from the init_pid_ns proc instance then perform no filtering [ jlayton: reformat comments for 80 columns ] Signed-off-by: Nikolay Borisov <kernel@kyup.com> Suggested-by: Eric W. Biederman <ebiederm@xmission.com> Signed-off-by: Jeff Layton <jlayton@redhat.com>
-rw-r--r--fs/locks.c21
1 files changed, 18 insertions, 3 deletions
diff --git a/fs/locks.c b/fs/locks.c
index ee1b15f6fc13..7e428b78be07 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -2574,9 +2574,20 @@ static void lock_get_status(struct seq_file *f, struct file_lock *fl,
struct inode *inode = NULL;
unsigned int fl_pid;
- if (fl->fl_nspid)
- fl_pid = pid_vnr(fl->fl_nspid);
- else
+ if (fl->fl_nspid) {
+ struct pid_namespace *proc_pidns = file_inode(f->file)->i_sb->s_fs_info;
+
+ /* Don't let fl_pid change based on who is reading the file */
+ fl_pid = pid_nr_ns(fl->fl_nspid, proc_pidns);
+
+ /*
+ * If there isn't a fl_pid don't display who is waiting on
+ * the lock if we are called from locks_show, or if we are
+ * called from __show_fd_info - skip lock entirely
+ */
+ if (fl_pid == 0)
+ return;
+ } else
fl_pid = fl->fl_pid;
if (fl->fl_file != NULL)
@@ -2648,9 +2659,13 @@ static int locks_show(struct seq_file *f, void *v)
{
struct locks_iterator *iter = f->private;
struct file_lock *fl, *bfl;
+ struct pid_namespace *proc_pidns = file_inode(f->file)->i_sb->s_fs_info;
fl = hlist_entry(v, struct file_lock, fl_link);
+ if (fl->fl_nspid && !pid_nr_ns(fl->fl_nspid, proc_pidns))
+ return 0;
+
lock_get_status(f, fl, iter->li_pos, "");
list_for_each_entry(bfl, &fl->fl_block, fl_block)