diff options
author | Tejun Heo <tj@kernel.org> | 2014-04-09 11:07:31 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-04-25 14:43:31 -0400 |
commit | d911d98748018f7c8facc035ba39c30f5cce6f9c (patch) | |
tree | 01bd2fd6dac3eddc47f6c0d119c2ffdcaa6b5fef /fs/kernfs | |
parent | 7d568a8383bbb9c1f5167781075906acb2bb1550 (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.c | 41 |
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 | */ |
786 | void kernfs_notify(struct kernfs_node *kn) | 787 | void 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 | } |
803 | EXPORT_SYMBOL_GPL(kernfs_notify); | 832 | EXPORT_SYMBOL_GPL(kernfs_notify); |
804 | 833 | ||