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 | |
| 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')
| -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 | ||
