fsnotify: use dget_parent
Use dget_parent instead of opencoding it. This simplifies the code, but more importanly prepares for the more complicated locking for a parent dget in the dcache scale patch series. It means we do grab a reference to the parent now if need to be watched, but not with the specified mask. If this turns out to be a problem we'll have to revisit it, but for now let's keep as much as possible dcache internals inside dcache.[ch]. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
Родитель
be9eee2e8b
Коммит
4d4eb36679
|
@ -88,8 +88,6 @@ void __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask)
|
||||||
{
|
{
|
||||||
struct dentry *parent;
|
struct dentry *parent;
|
||||||
struct inode *p_inode;
|
struct inode *p_inode;
|
||||||
bool send = false;
|
|
||||||
bool should_update_children = false;
|
|
||||||
|
|
||||||
if (!dentry)
|
if (!dentry)
|
||||||
dentry = path->dentry;
|
dentry = path->dentry;
|
||||||
|
@ -97,29 +95,12 @@ void __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask)
|
||||||
if (!(dentry->d_flags & DCACHE_FSNOTIFY_PARENT_WATCHED))
|
if (!(dentry->d_flags & DCACHE_FSNOTIFY_PARENT_WATCHED))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
spin_lock(&dentry->d_lock);
|
parent = dget_parent(dentry);
|
||||||
parent = dentry->d_parent;
|
|
||||||
p_inode = parent->d_inode;
|
p_inode = parent->d_inode;
|
||||||
|
|
||||||
if (fsnotify_inode_watches_children(p_inode)) {
|
if (unlikely(!fsnotify_inode_watches_children(p_inode)))
|
||||||
if (p_inode->i_fsnotify_mask & mask) {
|
__fsnotify_update_child_dentry_flags(p_inode);
|
||||||
dget(parent);
|
else if (p_inode->i_fsnotify_mask & mask) {
|
||||||
send = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* The parent doesn't care about events on it's children but
|
|
||||||
* at least one child thought it did. We need to run all the
|
|
||||||
* children and update their d_flags to let them know p_inode
|
|
||||||
* doesn't care about them any more.
|
|
||||||
*/
|
|
||||||
dget(parent);
|
|
||||||
should_update_children = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
spin_unlock(&dentry->d_lock);
|
|
||||||
|
|
||||||
if (send) {
|
|
||||||
/* we are notifying a parent so come up with the new mask which
|
/* we are notifying a parent so come up with the new mask which
|
||||||
* specifies these are events which came from a child. */
|
* specifies these are events which came from a child. */
|
||||||
mask |= FS_EVENT_ON_CHILD;
|
mask |= FS_EVENT_ON_CHILD;
|
||||||
|
@ -130,14 +111,10 @@ void __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask)
|
||||||
else
|
else
|
||||||
fsnotify(p_inode, mask, dentry->d_inode, FSNOTIFY_EVENT_INODE,
|
fsnotify(p_inode, mask, dentry->d_inode, FSNOTIFY_EVENT_INODE,
|
||||||
dentry->d_name.name, 0);
|
dentry->d_name.name, 0);
|
||||||
dput(parent);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unlikely(should_update_children)) {
|
|
||||||
__fsnotify_update_child_dentry_flags(p_inode);
|
|
||||||
dput(parent);
|
dput(parent);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
EXPORT_SYMBOL_GPL(__fsnotify_parent);
|
EXPORT_SYMBOL_GPL(__fsnotify_parent);
|
||||||
|
|
||||||
static int send_to_group(struct inode *to_tell, struct vfsmount *mnt,
|
static int send_to_group(struct inode *to_tell, struct vfsmount *mnt,
|
||||||
|
|
Загрузка…
Ссылка в новой задаче