@@ -271,6 +271,8 @@ static struct inode *fanotify_fid_inode(struct inode *to_tell, u32 event_mask,
return to_tell;
else if (data_type == FSNOTIFY_EVENT_INODE)
return (struct inode *)data;
+ else if (data_type == FSNOTIFY_EVENT_DENTRY)
+ return d_inode(data);
else if (data_type == FSNOTIFY_EVENT_PATH)
return d_inode(((struct path *)data)->dentry);
return NULL;
@@ -172,8 +172,8 @@ int __fsnotify_parent(const struct path *path, struct dentry *dentry, __u32 mask
ret = fsnotify(p_inode, mask, path, FSNOTIFY_EVENT_PATH,
&name.name, 0);
else
- ret = fsnotify(p_inode, mask, dentry->d_inode, FSNOTIFY_EVENT_INODE,
- &name.name, 0);
+ ret = fsnotify(p_inode, mask, dentry,
+ FSNOTIFY_EVENT_DENTRY, &name.name, 0);
release_dentry_name_snapshot(&name);
}
@@ -41,9 +41,15 @@ static inline int fsnotify_parent(const struct path *path,
}
/*
- * Simple wrapper to consolidate calls fsnotify_parent()/fsnotify() when
- * an event is on a path.
+ * Simple wrappers to consolidate calls fsnotify_parent()/fsnotify() when
+ * an event is on a path/dentry.
*/
+static inline void fsnotify_dentry(struct dentry *dentry, __u32 mask)
+{
+ fsnotify_parent(NULL, dentry, mask);
+ fsnotify(d_inode(dentry), mask, dentry, FSNOTIFY_EVENT_DENTRY, NULL, 0);
+}
+
static inline int fsnotify_path(struct inode *inode, const struct path *path,
__u32 mask)
{
@@ -301,8 +307,7 @@ static inline void fsnotify_xattr(struct dentry *dentry)
if (S_ISDIR(inode->i_mode))
mask |= FS_ISDIR;
- fsnotify_parent(NULL, dentry, mask);
- fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE, NULL, 0);
+ fsnotify_dentry(dentry, mask);
}
/*
@@ -336,8 +341,7 @@ static inline void fsnotify_change(struct dentry *dentry, unsigned int ia_valid)
if (S_ISDIR(inode->i_mode))
mask |= FS_ISDIR;
- fsnotify_parent(NULL, dentry, mask);
- fsnotify(inode, mask, inode, FSNOTIFY_EVENT_INODE, NULL, 0);
+ fsnotify_dentry(dentry, mask);
}
}
@@ -212,10 +212,11 @@ struct fsnotify_group {
};
};
-/* when calling fsnotify tell it if the data is a path or inode */
+/* when calling fsnotify tell it if the data is a path or inode or dentry */
#define FSNOTIFY_EVENT_NONE 0
#define FSNOTIFY_EVENT_PATH 1
#define FSNOTIFY_EVENT_INODE 2
+#define FSNOTIFY_EVENT_DENTRY 3
enum fsnotify_obj_type {
FSNOTIFY_OBJ_TYPE_INODE,
@@ -168,7 +168,10 @@ static int audit_mark_handle_event(struct fsnotify_group *group,
switch (data_type) {
case (FSNOTIFY_EVENT_PATH):
- inode = ((const struct path *)data)->dentry->d_inode;
+ inode = d_inode(((const struct path *)data)->dentry);
+ break;
+ case (FSNOTIFY_EVENT_DENTRY):
+ inode = d_inode(data);
break;
case (FSNOTIFY_EVENT_INODE):
inode = (const struct inode *)data;
@@ -482,7 +482,10 @@ static int audit_watch_handle_event(struct fsnotify_group *group,
switch (data_type) {
case (FSNOTIFY_EVENT_PATH):
- inode = d_backing_inode(((const struct path *)data)->dentry);
+ inode = d_inode(((const struct path *)data)->dentry);
+ break;
+ case (FSNOTIFY_EVENT_DENTRY):
+ inode = d_inode(data);
break;
case (FSNOTIFY_EVENT_INODE):
inode = (const struct inode *)data;
Most events that can be reported to watching parent pass FSNOTIFY_EVENT_PATH as event data, except for FS_ARRTIB and FS_MODIFY as a result of truncate. Define a new data type to pass for event - FSNOTIFY_EVENT_DENTRY and use it to pass the dentry instead of it's ->d_inode for those events. Add a helper fsnotify_dentry(), similar to fsnotify_path() to report those events to child and parent. Soon, we are going to use the dentry data type to report events with name info in fanotify backend. Signed-off-by: Amir Goldstein <amir73il@gmail.com> --- fs/notify/fanotify/fanotify.c | 2 ++ fs/notify/fsnotify.c | 4 ++-- include/linux/fsnotify.h | 16 ++++++++++------ include/linux/fsnotify_backend.h | 3 ++- kernel/audit_fsnotify.c | 5 ++++- kernel/audit_watch.c | 5 ++++- 6 files changed, 24 insertions(+), 11 deletions(-)