mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2025-04-12 04:38:07 +07:00
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>
This commit is contained in:
parent
7d568a8383
commit
d911d98748
@ -14,6 +14,7 @@
|
|||||||
#include <linux/poll.h>
|
#include <linux/poll.h>
|
||||||
#include <linux/pagemap.h>
|
#include <linux/pagemap.h>
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
|
#include <linux/fsnotify.h>
|
||||||
|
|
||||||
#include "kernfs-internal.h"
|
#include "kernfs-internal.h"
|
||||||
|
|
||||||
@ -785,20 +786,48 @@ static unsigned int kernfs_fop_poll(struct file *filp, poll_table *wait)
|
|||||||
*/
|
*/
|
||||||
void kernfs_notify(struct kernfs_node *kn)
|
void kernfs_notify(struct kernfs_node *kn)
|
||||||
{
|
{
|
||||||
|
struct kernfs_root *root = kernfs_root(kn);
|
||||||
struct kernfs_open_node *on;
|
struct kernfs_open_node *on;
|
||||||
|
struct kernfs_super_info *info;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
|
if (WARN_ON(kernfs_type(kn) != KERNFS_FILE))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* kick poll */
|
||||||
spin_lock_irqsave(&kernfs_open_node_lock, flags);
|
spin_lock_irqsave(&kernfs_open_node_lock, flags);
|
||||||
|
|
||||||
if (!WARN_ON(kernfs_type(kn) != KERNFS_FILE)) {
|
on = kn->attr.open;
|
||||||
on = kn->attr.open;
|
if (on) {
|
||||||
if (on) {
|
atomic_inc(&on->event);
|
||||||
atomic_inc(&on->event);
|
wake_up_interruptible(&on->poll);
|
||||||
wake_up_interruptible(&on->poll);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_unlock_irqrestore(&kernfs_open_node_lock, flags);
|
spin_unlock_irqrestore(&kernfs_open_node_lock, flags);
|
||||||
|
|
||||||
|
/* kick fsnotify */
|
||||||
|
mutex_lock(&kernfs_mutex);
|
||||||
|
|
||||||
|
list_for_each_entry(info, &root->supers, node) {
|
||||||
|
struct inode *inode;
|
||||||
|
struct dentry *dentry;
|
||||||
|
|
||||||
|
inode = ilookup(info->sb, kn->ino);
|
||||||
|
if (!inode)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
dentry = d_find_any_alias(inode);
|
||||||
|
if (dentry) {
|
||||||
|
fsnotify_parent(NULL, dentry, FS_MODIFY);
|
||||||
|
fsnotify(inode, FS_MODIFY, inode, FSNOTIFY_EVENT_INODE,
|
||||||
|
NULL, 0);
|
||||||
|
dput(dentry);
|
||||||
|
}
|
||||||
|
|
||||||
|
iput(inode);
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_unlock(&kernfs_mutex);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(kernfs_notify);
|
EXPORT_SYMBOL_GPL(kernfs_notify);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user