From: Amir Goldstein <amir73il@gmail.com> To: Jan Kara <jack@suse.cz> Cc: linux-fsdevel@vger.kernel.org Subject: [PATCH v5 15/22] fsnotify: send event with parent/name info to sb/mount/non-dir marks Date: Thu, 16 Jul 2020 11:42:23 +0300 [thread overview] Message-ID: <20200716084230.30611-16-amir73il@gmail.com> (raw) In-Reply-To: <20200716084230.30611-1-amir73il@gmail.com> Similar to events "on child" to watching directory, send event "on child" with parent/name info if sb/mount/non-dir marks are interested in parent/name info. The FS_EVENT_ON_CHILD flag can be set on sb/mount/non-dir marks to specify interest in parent/name info for events on non-directory inodes. Events on "orphan" children (disconnected dentries) are sent without parent/name info. Events on direcories are send with parent/name info only if the parent directory is watching. Signed-off-by: Amir Goldstein <amir73il@gmail.com> --- fs/notify/fsnotify.c | 54 ++++++++++++++++++++++++++++---- include/linux/fsnotify.h | 10 ++++-- include/linux/fsnotify_backend.h | 32 ++++++++++++++++--- 3 files changed, 84 insertions(+), 12 deletions(-) diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c index 7120c675e9a6..efa5c1c4908a 100644 --- a/fs/notify/fsnotify.c +++ b/fs/notify/fsnotify.c @@ -142,31 +142,73 @@ void __fsnotify_update_child_dentry_flags(struct inode *inode) spin_unlock(&inode->i_lock); } +/* Are inode/sb/mount interested in parent and name info with this event? */ +static bool fsnotify_event_needs_parent(struct inode *inode, struct mount *mnt, + __u32 mask) +{ + __u32 marks_mask = 0; + + /* We only send parent/name to inode/sb/mount for events on non-dir */ + if (mask & FS_ISDIR) + return false; + + /* Did either inode/sb/mount subscribe for events with parent/name? */ + marks_mask |= fsnotify_parent_needed_mask(inode->i_fsnotify_mask); + marks_mask |= fsnotify_parent_needed_mask(inode->i_sb->s_fsnotify_mask); + if (mnt) + marks_mask |= fsnotify_parent_needed_mask(mnt->mnt_fsnotify_mask); + + /* Did they subscribe for this event with parent/name info? */ + return mask & marks_mask; +} + /* * Notify this dentry's parent about a child's events with child name info - * if parent is watching. - * Notify only the child without name info if parent is not watching. + * if parent is watching or if inode/sb/mount are interested in events with + * parent and name info. + * + * Notify only the child without name info if parent is not watching and + * inode/sb/mount are not interested in events with parent and name info. */ int __fsnotify_parent(struct dentry *dentry, __u32 mask, const void *data, int data_type) { + const struct path *path = fsnotify_data_path(data, data_type); + struct mount *mnt = path ? real_mount(path->mnt) : NULL; struct inode *inode = d_inode(dentry); struct dentry *parent; + bool parent_watched = dentry->d_flags & DCACHE_FSNOTIFY_PARENT_WATCHED; + __u32 p_mask; struct inode *p_inode; struct name_snapshot name; struct qstr *file_name = NULL; int ret = 0; + /* + * Do inode/sb/mount care about parent and name info on non-dir? + * Do they care about any event at all? + */ + if (!inode->i_fsnotify_marks && !inode->i_sb->s_fsnotify_marks && + (!mnt || !mnt->mnt_fsnotify_marks) && !parent_watched) + return 0; + parent = NULL; - if (!(dentry->d_flags & DCACHE_FSNOTIFY_PARENT_WATCHED)) + if (!parent_watched && !fsnotify_event_needs_parent(inode, mnt, mask)) goto notify; + /* Does parent inode care about events on children? */ parent = dget_parent(dentry); p_inode = parent->d_inode; - - if (unlikely(!fsnotify_inode_watches_children(p_inode))) { + p_mask = fsnotify_inode_watches_children(p_inode); + if (unlikely(parent_watched && !p_mask)) __fsnotify_update_child_dentry_flags(p_inode); - } else if (p_inode->i_fsnotify_mask & mask & ALL_FSNOTIFY_EVENTS) { + + /* + * Include parent/name in notification either if some notification + * groups require parent info (!parent_watched case) or the parent is + * interested in this event. + */ + if (!parent_watched || (mask & p_mask & ALL_FSNOTIFY_EVENTS)) { /* When notifying parent, child should be passed as data */ WARN_ON_ONCE(inode != fsnotify_data_inode(data, data_type)); diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h index 9b2566d273a9..044cae3a0628 100644 --- a/include/linux/fsnotify.h +++ b/include/linux/fsnotify.h @@ -44,10 +44,16 @@ static inline int fsnotify_parent(struct dentry *dentry, __u32 mask, { struct inode *inode = d_inode(dentry); - if (S_ISDIR(inode->i_mode)) + if (S_ISDIR(inode->i_mode)) { mask |= FS_ISDIR; - if (!(dentry->d_flags & DCACHE_FSNOTIFY_PARENT_WATCHED)) + /* sb/mount marks are not interested in name of directory */ + if (!(dentry->d_flags & DCACHE_FSNOTIFY_PARENT_WATCHED)) + goto notify_child; + } + + /* disconnected dentry cannot notify parent */ + if (IS_ROOT(dentry)) goto notify_child; return __fsnotify_parent(dentry, mask, data, data_type); diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index 2c62628566c5..6f0df110e9f8 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h @@ -49,8 +49,11 @@ #define FS_OPEN_EXEC_PERM 0x00040000 /* open/exec event in a permission hook */ #define FS_EXCL_UNLINK 0x04000000 /* do not send events if object is unlinked */ -/* This inode cares about things that happen to its children. Always set for - * dnotify and inotify. */ +/* + * Set on inode mark that cares about things that happen to its children. + * Always set for dnotify and inotify. + * Set on inode/sb/mount marks that care about parenet/name info. + */ #define FS_EVENT_ON_CHILD 0x08000000 #define FS_DN_RENAME 0x10000000 /* file renamed */ @@ -72,14 +75,22 @@ FS_OPEN_EXEC_PERM) /* - * This is a list of all events that may get sent to a parent based on fs event - * happening to inodes inside that directory. + * This is a list of all events that may get sent to a parent that is watching + * with flag FS_EVENT_ON_CHILD based on fs event on a child of that directory. */ #define FS_EVENTS_POSS_ON_CHILD (ALL_FSNOTIFY_PERM_EVENTS | \ FS_ACCESS | FS_MODIFY | FS_ATTRIB | \ FS_CLOSE_WRITE | FS_CLOSE_NOWRITE | \ FS_OPEN | FS_OPEN_EXEC) +/* + * This is a list of all events that may get sent with the parent inode as the + * @to_tell argument of fsnotify(). + * It may include events that can be sent to an inode/sb/mount mark, but cannot + * be sent to a parent watching children. + */ +#define FS_EVENTS_POSS_TO_PARENT (FS_EVENTS_POSS_ON_CHILD) + /* Events that can be reported to backends */ #define ALL_FSNOTIFY_EVENTS (ALL_FSNOTIFY_DIRENT_EVENTS | \ FS_EVENTS_POSS_ON_CHILD | \ @@ -398,6 +409,19 @@ extern void __fsnotify_vfsmount_delete(struct vfsmount *mnt); extern void fsnotify_sb_delete(struct super_block *sb); extern u32 fsnotify_get_cookie(void); +static inline __u32 fsnotify_parent_needed_mask(__u32 mask) +{ + /* FS_EVENT_ON_CHILD is set on marks that want parent/name info */ + if (!(mask & FS_EVENT_ON_CHILD)) + return 0; + /* + * This object might be watched by a mark that cares about parent/name + * info, does it care about the specific set of events that can be + * reported with parent/name info? + */ + return mask & FS_EVENTS_POSS_TO_PARENT; +} + static inline int fsnotify_inode_watches_children(struct inode *inode) { /* FS_EVENT_ON_CHILD is set if the inode may care */ -- 2.17.1
next prev parent reply other threads:[~2020-07-16 8:43 UTC|newest] Thread overview: 45+ messages / expand[flat|nested] mbox.gz Atom feed top 2020-07-16 8:42 [PATCH v5 00/22] fanotify events with name info Amir Goldstein 2020-07-16 8:42 ` [PATCH v5 01/22] fanotify: generalize the handling of extra event flags Amir Goldstein 2020-07-16 8:42 ` [PATCH v5 02/22] fanotify: generalize merge logic of events on dir Amir Goldstein 2020-07-16 8:42 ` [PATCH v5 03/22] fanotify: distinguish between fid encode error and null fid Amir Goldstein 2020-07-16 8:42 ` [PATCH v5 04/22] fanotify: generalize test for FAN_REPORT_FID Amir Goldstein 2020-07-16 8:42 ` [PATCH v5 05/22] fanotify: mask out special event flags from ignored mask Amir Goldstein 2020-07-16 8:42 ` [PATCH v5 06/22] fanotify: prepare for implicit event flags in mark mask Amir Goldstein 2020-07-16 8:42 ` [PATCH v5 07/22] fanotify: use FAN_EVENT_ON_CHILD as implicit flag on sb/mount/non-dir marks Amir Goldstein 2020-07-16 8:42 ` [PATCH v5 08/22] fsnotify: add object type "child" to object type iterator Amir Goldstein 2020-07-16 8:42 ` [PATCH v5 09/22] fanotify: use struct fanotify_info to parcel the variable size buffer Amir Goldstein 2020-07-16 8:42 ` [PATCH v5 10/22] fanotify: no external fh buffer in fanotify_name_event Amir Goldstein 2020-07-16 12:44 ` Jan Kara 2020-07-16 13:30 ` Amir Goldstein 2020-07-16 8:42 ` [PATCH v5 11/22] dnotify: report both events on parent and child with single callback Amir Goldstein 2020-07-16 8:42 ` [PATCH v5 12/22] inotify: " Amir Goldstein 2020-07-16 12:52 ` Jan Kara 2020-07-16 14:25 ` Amir Goldstein 2020-07-16 15:17 ` Jan Kara 2020-07-16 8:42 ` [PATCH v5 13/22] fanotify: " Amir Goldstein 2020-07-16 8:42 ` [PATCH v5 14/22] fsnotify: send event to " Amir Goldstein 2020-07-16 8:42 ` Amir Goldstein [this message] 2020-07-16 17:01 ` [PATCH v5 15/22] fsnotify: send event with parent/name info to sb/mount/non-dir marks Jan Kara 2020-07-16 17:20 ` Amir Goldstein 2020-07-16 17:57 ` Jan Kara 2020-07-16 18:42 ` Amir Goldstein 2020-07-16 22:34 ` Jan Kara 2020-07-17 3:49 ` Amir Goldstein 2020-07-16 8:42 ` [PATCH v5 16/22] fsnotify: remove check that source dentry is positive Amir Goldstein 2020-07-16 13:13 ` Jan Kara 2020-07-16 13:29 ` Jan Kara 2020-07-16 13:54 ` Amir Goldstein 2020-07-16 14:06 ` Jan Kara 2020-07-16 8:42 ` [PATCH v5 17/22] fsnotify: send MOVE_SELF event with parent/name info Amir Goldstein 2020-07-16 13:45 ` Jan Kara 2020-07-16 13:59 ` Amir Goldstein 2020-07-16 14:10 ` Amir Goldstein 2020-07-16 15:57 ` Amir Goldstein 2020-07-16 8:42 ` [PATCH v5 18/22] fanotify: add basic support for FAN_REPORT_DIR_FID Amir Goldstein 2020-07-16 8:42 ` [PATCH v5 19/22] fanotify: report events with parent dir fid to sb/mount/non-dir marks Amir Goldstein 2020-07-16 8:42 ` [PATCH v5 20/22] fanotify: add support for FAN_REPORT_NAME Amir Goldstein 2020-07-16 8:42 ` [PATCH v5 21/22] fanotify: report parent fid + name + child fid Amir Goldstein 2020-07-16 15:59 ` Jan Kara 2020-07-16 16:08 ` Amir Goldstein 2020-07-16 8:42 ` [PATCH v5 22/22] fanotify: report parent fid " Amir Goldstein 2020-07-16 17:13 ` [PATCH v5 00/22] fanotify events with name info Jan Kara
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20200716084230.30611-16-amir73il@gmail.com \ --to=amir73il@gmail.com \ --cc=jack@suse.cz \ --cc=linux-fsdevel@vger.kernel.org \ --subject='Re: [PATCH v5 15/22] fsnotify: send event with parent/name info to sb/mount/non-dir marks' \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).