aboutsummaryrefslogtreecommitdiffstats
path: root/fs/notify/fsnotify.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/notify/fsnotify.c')
-rw-r--r--fs/notify/fsnotify.c35
1 files changed, 21 insertions, 14 deletions
diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c
index 4498a208df94..20dc218707ca 100644
--- a/fs/notify/fsnotify.c
+++ b/fs/notify/fsnotify.c
@@ -84,16 +84,17 @@ void __fsnotify_update_child_dentry_flags(struct inode *inode)
84} 84}
85 85
86/* Notify this dentry's parent about a child's events. */ 86/* Notify this dentry's parent about a child's events. */
87void __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask) 87int __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask)
88{ 88{
89 struct dentry *parent; 89 struct dentry *parent;
90 struct inode *p_inode; 90 struct inode *p_inode;
91 int ret = 0;
91 92
92 if (!dentry) 93 if (!dentry)
93 dentry = path->dentry; 94 dentry = path->dentry;
94 95
95 if (!(dentry->d_flags & DCACHE_FSNOTIFY_PARENT_WATCHED)) 96 if (!(dentry->d_flags & DCACHE_FSNOTIFY_PARENT_WATCHED))
96 return; 97 return 0;
97 98
98 parent = dget_parent(dentry); 99 parent = dget_parent(dentry);
99 p_inode = parent->d_inode; 100 p_inode = parent->d_inode;
@@ -106,14 +107,16 @@ void __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask)
106 mask |= FS_EVENT_ON_CHILD; 107 mask |= FS_EVENT_ON_CHILD;
107 108
108 if (path) 109 if (path)
109 fsnotify(p_inode, mask, path, FSNOTIFY_EVENT_PATH, 110 ret = fsnotify(p_inode, mask, path, FSNOTIFY_EVENT_PATH,
110 dentry->d_name.name, 0); 111 dentry->d_name.name, 0);
111 else 112 else
112 fsnotify(p_inode, mask, dentry->d_inode, FSNOTIFY_EVENT_INODE, 113 ret = fsnotify(p_inode, mask, dentry->d_inode, FSNOTIFY_EVENT_INODE,
113 dentry->d_name.name, 0); 114 dentry->d_name.name, 0);
114 } 115 }
115 116
116 dput(parent); 117 dput(parent);
118
119 return ret;
117} 120}
118EXPORT_SYMBOL_GPL(__fsnotify_parent); 121EXPORT_SYMBOL_GPL(__fsnotify_parent);
119 122
@@ -252,20 +255,23 @@ int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is,
252 255
253 if (inode_group > vfsmount_group) { 256 if (inode_group > vfsmount_group) {
254 /* handle inode */ 257 /* handle inode */
255 send_to_group(to_tell, NULL, inode_mark, NULL, mask, data, 258 ret = send_to_group(to_tell, NULL, inode_mark, NULL, mask, data,
256 data_is, cookie, file_name, &event); 259 data_is, cookie, file_name, &event);
257 /* we didn't use the vfsmount_mark */ 260 /* we didn't use the vfsmount_mark */
258 vfsmount_group = NULL; 261 vfsmount_group = NULL;
259 } else if (vfsmount_group > inode_group) { 262 } else if (vfsmount_group > inode_group) {
260 send_to_group(to_tell, mnt, NULL, vfsmount_mark, mask, data, 263 ret = send_to_group(to_tell, mnt, NULL, vfsmount_mark, mask, data,
261 data_is, cookie, file_name, &event); 264 data_is, cookie, file_name, &event);
262 inode_group = NULL; 265 inode_group = NULL;
263 } else { 266 } else {
264 send_to_group(to_tell, mnt, inode_mark, vfsmount_mark, 267 ret = send_to_group(to_tell, mnt, inode_mark, vfsmount_mark,
265 mask, data, data_is, cookie, file_name, 268 mask, data, data_is, cookie, file_name,
266 &event); 269 &event);
267 } 270 }
268 271
272 if (ret && (mask & ALL_FSNOTIFY_PERM_EVENTS))
273 goto out;
274
269 if (inode_group) 275 if (inode_group)
270 inode_node = srcu_dereference(inode_node->next, 276 inode_node = srcu_dereference(inode_node->next,
271 &fsnotify_mark_srcu); 277 &fsnotify_mark_srcu);
@@ -273,7 +279,8 @@ int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is,
273 vfsmount_node = srcu_dereference(vfsmount_node->next, 279 vfsmount_node = srcu_dereference(vfsmount_node->next,
274 &fsnotify_mark_srcu); 280 &fsnotify_mark_srcu);
275 } 281 }
276 282 ret = 0;
283out:
277 srcu_read_unlock(&fsnotify_mark_srcu, idx); 284 srcu_read_unlock(&fsnotify_mark_srcu, idx);
278 /* 285 /*
279 * fsnotify_create_event() took a reference so the event can't be cleaned 286 * fsnotify_create_event() took a reference so the event can't be cleaned