aboutsummaryrefslogtreecommitdiffstats
path: root/fs/proc
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2005-11-07 17:15:49 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2005-11-07 21:18:10 -0500
commit5addc5dd8836aa061f6efc4a0d9ba6323726297a (patch)
treea5ce3703bbb421c93482b6043ebd57137276808f /fs/proc
parent1abe77b0fc4b485927f1f798ae81a752677e1d05 (diff)
[PATCH] make /proc/mounts pollable
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs/proc')
-rw-r--r--fs/proc/base.c62
1 files changed, 47 insertions, 15 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c
index a170450aadb1..634355e16986 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -70,6 +70,7 @@
70#include <linux/seccomp.h> 70#include <linux/seccomp.h>
71#include <linux/cpuset.h> 71#include <linux/cpuset.h>
72#include <linux/audit.h> 72#include <linux/audit.h>
73#include <linux/poll.h>
73#include "internal.h" 74#include "internal.h"
74 75
75/* 76/*
@@ -660,26 +661,38 @@ static struct file_operations proc_smaps_operations = {
660#endif 661#endif
661 662
662extern struct seq_operations mounts_op; 663extern struct seq_operations mounts_op;
664struct proc_mounts {
665 struct seq_file m;
666 int event;
667};
668
663static int mounts_open(struct inode *inode, struct file *file) 669static int mounts_open(struct inode *inode, struct file *file)
664{ 670{
665 struct task_struct *task = proc_task(inode); 671 struct task_struct *task = proc_task(inode);
666 int ret = seq_open(file, &mounts_op); 672 struct namespace *namespace;
673 struct proc_mounts *p;
674 int ret = -EINVAL;
667 675
668 if (!ret) { 676 task_lock(task);
669 struct seq_file *m = file->private_data; 677 namespace = task->namespace;
670 struct namespace *namespace; 678 if (namespace)
671 task_lock(task); 679 get_namespace(namespace);
672 namespace = task->namespace; 680 task_unlock(task);
673 if (namespace) 681
674 get_namespace(namespace); 682 if (namespace) {
675 task_unlock(task); 683 ret = -ENOMEM;
676 684 p = kmalloc(sizeof(struct proc_mounts), GFP_KERNEL);
677 if (namespace) 685 if (p) {
678 m->private = namespace; 686 file->private_data = &p->m;
679 else { 687 ret = seq_open(file, &mounts_op);
680 seq_release(inode, file); 688 if (!ret) {
681 ret = -EINVAL; 689 p->m.private = namespace;
690 p->event = namespace->event;
691 return 0;
692 }
693 kfree(p);
682 } 694 }
695 put_namespace(namespace);
683 } 696 }
684 return ret; 697 return ret;
685} 698}
@@ -692,11 +705,30 @@ static int mounts_release(struct inode *inode, struct file *file)
692 return seq_release(inode, file); 705 return seq_release(inode, file);
693} 706}
694 707
708static unsigned mounts_poll(struct file *file, poll_table *wait)
709{
710 struct proc_mounts *p = file->private_data;
711 struct namespace *ns = p->m.private;
712 unsigned res = 0;
713
714 poll_wait(file, &ns->poll, wait);
715
716 spin_lock(&vfsmount_lock);
717 if (p->event != ns->event) {
718 p->event = ns->event;
719 res = POLLERR;
720 }
721 spin_unlock(&vfsmount_lock);
722
723 return res;
724}
725
695static struct file_operations proc_mounts_operations = { 726static struct file_operations proc_mounts_operations = {
696 .open = mounts_open, 727 .open = mounts_open,
697 .read = seq_read, 728 .read = seq_read,
698 .llseek = seq_lseek, 729 .llseek = seq_lseek,
699 .release = mounts_release, 730 .release = mounts_release,
731 .poll = mounts_poll,
700}; 732};
701 733
702#define PROC_BLOCK_SIZE (3*1024) /* 4K page size but our output routines use some slack for overruns */ 734#define PROC_BLOCK_SIZE (3*1024) /* 4K page size but our output routines use some slack for overruns */