aboutsummaryrefslogtreecommitdiffstats
path: root/fs/kernfs
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2014-04-09 11:07:31 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-04-25 14:43:31 -0400
commitd911d98748018f7c8facc035ba39c30f5cce6f9c (patch)
tree01bd2fd6dac3eddc47f6c0d119c2ffdcaa6b5fef /fs/kernfs
parent7d568a8383bbb9c1f5167781075906acb2bb1550 (diff)
kernfs: make kernfs_notify() trigger inotify events too
kernfs_notify() is used to indicate either new data is available or the content of a file has changed. It currently only triggers poll which may not be the most convenient to monitor especially when there are a lot to monitor. Let's hook it up to fsnotify too so that the events can be monitored via inotify too. fsnotify_modify() requires file * but kernfs_notify() doesn't have any specific file associated; however, we can walk all super_blocks associated with a kernfs_root and as kernfs always associate one ino with inode and one dentry with an inode, it's trivial to look up the dentry associated with a given kernfs_node. As any active monitor would pin dentry, just looking up existing dentry is enough. This patch looks up the dentry associated with the specified kernfs_node and generates events equivalent to fsnotify_modify(). Note that as fsnotify doesn't provide fsnotify_modify() equivalent which can be called with dentry, kernfs_notify() directly calls fsnotify_parent() and fsnotify(). It might be better to add a wrapper in fsnotify.h instead. Signed-off-by: Tejun Heo <tj@kernel.org> Cc: John McCutchan <john@johnmccutchan.com> Cc: Robert Love <rlove@rlove.org> Cc: Eric Paris <eparis@parisplace.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs/kernfs')
-rw-r--r--fs/kernfs/file.c41
1 files changed, 35 insertions, 6 deletions
diff --git a/fs/kernfs/file.c b/fs/kernfs/file.c
index 8034706a7af8..98bacd9ea7fd 100644
--- a/fs/kernfs/file.c
+++ b/fs/kernfs/file.c
@@ -14,6 +14,7 @@
14#include <linux/poll.h> 14#include <linux/poll.h>
15#include <linux/pagemap.h> 15#include <linux/pagemap.h>
16#include <linux/sched.h> 16#include <linux/sched.h>
17#include <linux/fsnotify.h>
17 18
18#include "kernfs-internal.h" 19#include "kernfs-internal.h"
19 20
@@ -785,20 +786,48 @@ static unsigned int kernfs_fop_poll(struct file *filp, poll_table *wait)
785 */ 786 */
786void kernfs_notify(struct kernfs_node *kn) 787void kernfs_notify(struct kernfs_node *kn)
787{ 788{
789 struct kernfs_root *root = kernfs_root(kn);
788 struct kernfs_open_node *on; 790 struct kernfs_open_node *on;
791 struct kernfs_super_info *info;
789 unsigned long flags; 792 unsigned long flags;
790 793
794 if (WARN_ON(kernfs_type(kn) != KERNFS_FILE))
795 return;
796
797 /* kick poll */
791 spin_lock_irqsave(&kernfs_open_node_lock, flags); 798 spin_lock_irqsave(&kernfs_open_node_lock, flags);
792 799
793 if (!WARN_ON(kernfs_type(kn) != KERNFS_FILE)) { 800 on = kn->attr.open;
794 on = kn->attr.open; 801 if (on) {
795 if (on) { 802 atomic_inc(&on->event);
796 atomic_inc(&on->event); 803 wake_up_interruptible(&on->poll);
797 wake_up_interruptible(&on->poll);
798 }
799 } 804 }
800 805
801 spin_unlock_irqrestore(&kernfs_open_node_lock, flags); 806 spin_unlock_irqrestore(&kernfs_open_node_lock, flags);
807
808 /* kick fsnotify */
809 mutex_lock(&kernfs_mutex);
810
811 list_for_each_entry(info, &root->supers, node) {
812 struct inode *inode;
813 struct dentry *dentry;
814
815 inode = ilookup(info->sb, kn->ino);
816 if (!inode)
817 continue;
818
819 dentry = d_find_any_alias(inode);
820 if (dentry) {
821 fsnotify_parent(NULL, dentry, FS_MODIFY);
822 fsnotify(inode, FS_MODIFY, inode, FSNOTIFY_EVENT_INODE,
823 NULL, 0);
824 dput(dentry);
825 }
826
827 iput(inode);
828 }
829
830 mutex_unlock(&kernfs_mutex);
802} 831}
803EXPORT_SYMBOL_GPL(kernfs_notify); 832EXPORT_SYMBOL_GPL(kernfs_notify);
804 833