Skip to content

Commit d911d98

Browse files
htejungregkh
authored andcommitted
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 <[email protected]> Cc: John McCutchan <[email protected]> Cc: Robert Love <[email protected]> Cc: Eric Paris <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 7d568a8 commit d911d98

File tree

1 file changed

+35
-6
lines changed

1 file changed

+35
-6
lines changed

fs/kernfs/file.c

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <linux/poll.h>
1515
#include <linux/pagemap.h>
1616
#include <linux/sched.h>
17+
#include <linux/fsnotify.h>
1718

1819
#include "kernfs-internal.h"
1920

@@ -785,20 +786,48 @@ static unsigned int kernfs_fop_poll(struct file *filp, poll_table *wait)
785786
*/
786787
void kernfs_notify(struct kernfs_node *kn)
787788
{
789+
struct kernfs_root *root = kernfs_root(kn);
788790
struct kernfs_open_node *on;
791+
struct kernfs_super_info *info;
789792
unsigned long flags;
790793

794+
if (WARN_ON(kernfs_type(kn) != KERNFS_FILE))
795+
return;
796+
797+
/* kick poll */
791798
spin_lock_irqsave(&kernfs_open_node_lock, flags);
792799

793-
if (!WARN_ON(kernfs_type(kn) != KERNFS_FILE)) {
794-
on = kn->attr.open;
795-
if (on) {
796-
atomic_inc(&on->event);
797-
wake_up_interruptible(&on->poll);
798-
}
800+
on = kn->attr.open;
801+
if (on) {
802+
atomic_inc(&on->event);
803+
wake_up_interruptible(&on->poll);
799804
}
800805

801806
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);
802831
}
803832
EXPORT_SYMBOL_GPL(kernfs_notify);
804833

0 commit comments

Comments
 (0)