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@xxxxxxxxx> --- 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(-) diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c index 5778d1347b35..b4cd90afece1 100644 --- a/fs/notify/fanotify/fanotify.c +++ b/fs/notify/fanotify/fanotify.c @@ -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; diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c index 46f225580009..13578372aee8 100644 --- a/fs/notify/fsnotify.c +++ b/fs/notify/fsnotify.c @@ -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); } diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h index a2d5d175d3c1..5746420bb121 100644 --- a/include/linux/fsnotify.h +++ b/include/linux/fsnotify.h @@ -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); } } diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index db3cabb4600e..cb47759b1ce9 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h @@ -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, diff --git a/kernel/audit_fsnotify.c b/kernel/audit_fsnotify.c index f0d243318452..ec6d00fd11b4 100644 --- a/kernel/audit_fsnotify.c +++ b/kernel/audit_fsnotify.c @@ -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; diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c index 4508d5e0cf69..85e007184677 100644 --- a/kernel/audit_watch.c +++ b/kernel/audit_watch.c @@ -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; -- 2.17.1