Skip to content

Commit

Permalink
Merge tag 'fsnotify_for_v6.9-rc1' of git://git.kernel.org/pub/scm/lin…
Browse files Browse the repository at this point in the history
…ux/kernel/git/jack/linux-fs

Pull fsnotify updates from Jan Kara:

 - fsnotify optimizations to reduce cost of fsnotify when nobody is
   watching

 - fix longstanding wart that system could not be suspended when some
   process was waiting for response to fanotify permission event

 - some spelling fixes

* tag 'fsnotify_for_v6.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs:
  fanotify: allow freeze when waiting response for permission events
  fanotify: Fix misspelling of "writable"
  fsnotify: Fix misspelling of "writable"
  inotify: Fix misspelling of "writable"
  fsnotify: Add fsnotify_sb_has_watchers() helper
  fsnotify: optimize the case of no parent watcher
  • Loading branch information
torvalds committed Mar 13, 2024
2 parents babbcc0 + 0045fb1 commit 1715f71
Show file tree
Hide file tree
Showing 6 changed files with 36 additions and 22 deletions.
6 changes: 4 additions & 2 deletions fs/notify/fanotify/fanotify.c
Original file line number Diff line number Diff line change
Expand Up @@ -228,8 +228,10 @@ static int fanotify_get_response(struct fsnotify_group *group,

pr_debug("%s: group=%p event=%p\n", __func__, group, event);

ret = wait_event_killable(group->fanotify_data.access_waitq,
event->state == FAN_EVENT_ANSWERED);
ret = wait_event_state(group->fanotify_data.access_waitq,
event->state == FAN_EVENT_ANSWERED,
(TASK_KILLABLE|TASK_FREEZABLE));

/* Signal pending? */
if (ret < 0) {
spin_lock(&group->notification_lock);
Expand Down
28 changes: 17 additions & 11 deletions fs/notify/fsnotify.c
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ void __fsnotify_update_child_dentry_flags(struct inode *inode)
}

/* 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,
static bool fsnotify_event_needs_parent(struct inode *inode, __u32 mnt_mask,
__u32 mask)
{
__u32 marks_mask = 0;
Expand All @@ -160,13 +160,22 @@ static bool fsnotify_event_needs_parent(struct inode *inode, struct mount *mnt,
/* 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);
marks_mask |= fsnotify_parent_needed_mask(mnt_mask);

/* Did they subscribe for this event with parent/name info? */
return mask & marks_mask;
}

/* Are there any inode/mount/sb objects that are interested in this event? */
static inline bool fsnotify_object_watched(struct inode *inode, __u32 mnt_mask,
__u32 mask)
{
__u32 marks_mask = inode->i_fsnotify_mask | mnt_mask |
inode->i_sb->s_fsnotify_mask;

return mask & marks_mask & ALL_FSNOTIFY_EVENTS;
}

/*
* Notify this dentry's parent about a child's events with child name info
* if parent is watching or if inode/sb/mount are interested in events with
Expand All @@ -179,7 +188,7 @@ 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;
__u32 mnt_mask = path ? real_mount(path->mnt)->mnt_fsnotify_mask : 0;
struct inode *inode = d_inode(dentry);
struct dentry *parent;
bool parent_watched = dentry->d_flags & DCACHE_FSNOTIFY_PARENT_WATCHED;
Expand All @@ -190,16 +199,13 @@ int __fsnotify_parent(struct dentry *dentry, __u32 mask, const void *data,
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)
/* Optimize the likely case of nobody watching this path */
if (likely(!parent_watched &&
!fsnotify_object_watched(inode, mnt_mask, mask)))
return 0;

parent = NULL;
parent_needed = fsnotify_event_needs_parent(inode, mnt, mask);
parent_needed = fsnotify_event_needs_parent(inode, mnt_mask, mask);
if (!parent_watched && !parent_needed)
goto notify;

Expand Down
12 changes: 9 additions & 3 deletions include/linux/fsnotify.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@
#include <linux/slab.h>
#include <linux/bug.h>

/* Are there any inode/mount/sb objects that are being watched at all? */
static inline bool fsnotify_sb_has_watchers(struct super_block *sb)
{
return atomic_long_read(&sb->s_fsnotify_connectors);
}

/*
* Notify this @dir inode about a change in a child directory entry.
* The directory entry may have turned positive or negative or its inode may
Expand All @@ -30,7 +36,7 @@ static inline int fsnotify_name(__u32 mask, const void *data, int data_type,
struct inode *dir, const struct qstr *name,
u32 cookie)
{
if (atomic_long_read(&dir->i_sb->s_fsnotify_connectors) == 0)
if (!fsnotify_sb_has_watchers(dir->i_sb))
return 0;

return fsnotify(mask, data, data_type, dir, name, NULL, cookie);
Expand All @@ -44,7 +50,7 @@ static inline void fsnotify_dirent(struct inode *dir, struct dentry *dentry,

static inline void fsnotify_inode(struct inode *inode, __u32 mask)
{
if (atomic_long_read(&inode->i_sb->s_fsnotify_connectors) == 0)
if (!fsnotify_sb_has_watchers(inode->i_sb))
return;

if (S_ISDIR(inode->i_mode))
Expand All @@ -59,7 +65,7 @@ static inline int fsnotify_parent(struct dentry *dentry, __u32 mask,
{
struct inode *inode = d_inode(dentry);

if (atomic_long_read(&inode->i_sb->s_fsnotify_connectors) == 0)
if (!fsnotify_sb_has_watchers(inode->i_sb))
return 0;

if (S_ISDIR(inode->i_mode)) {
Expand Down
4 changes: 2 additions & 2 deletions include/linux/fsnotify_backend.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@
#define FS_ACCESS 0x00000001 /* File was accessed */
#define FS_MODIFY 0x00000002 /* File was modified */
#define FS_ATTRIB 0x00000004 /* Metadata changed */
#define FS_CLOSE_WRITE 0x00000008 /* Writtable file was closed */
#define FS_CLOSE_NOWRITE 0x00000010 /* Unwrittable file closed */
#define FS_CLOSE_WRITE 0x00000008 /* Writable file was closed */
#define FS_CLOSE_NOWRITE 0x00000010 /* Unwritable file closed */
#define FS_OPEN 0x00000020 /* File was opened */
#define FS_MOVED_FROM 0x00000040 /* File was moved from X */
#define FS_MOVED_TO 0x00000080 /* File was moved to Y */
Expand Down
4 changes: 2 additions & 2 deletions include/uapi/linux/fanotify.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
#define FAN_ACCESS 0x00000001 /* File was accessed */
#define FAN_MODIFY 0x00000002 /* File was modified */
#define FAN_ATTRIB 0x00000004 /* Metadata changed */
#define FAN_CLOSE_WRITE 0x00000008 /* Writtable file closed */
#define FAN_CLOSE_NOWRITE 0x00000010 /* Unwrittable file closed */
#define FAN_CLOSE_WRITE 0x00000008 /* Writable file closed */
#define FAN_CLOSE_NOWRITE 0x00000010 /* Unwritable file closed */
#define FAN_OPEN 0x00000020 /* File was opened */
#define FAN_MOVED_FROM 0x00000040 /* File was moved from X */
#define FAN_MOVED_TO 0x00000080 /* File was moved to Y */
Expand Down
4 changes: 2 additions & 2 deletions include/uapi/linux/inotify.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ struct inotify_event {
#define IN_ACCESS 0x00000001 /* File was accessed */
#define IN_MODIFY 0x00000002 /* File was modified */
#define IN_ATTRIB 0x00000004 /* Metadata changed */
#define IN_CLOSE_WRITE 0x00000008 /* Writtable file was closed */
#define IN_CLOSE_NOWRITE 0x00000010 /* Unwrittable file closed */
#define IN_CLOSE_WRITE 0x00000008 /* Writable file was closed */
#define IN_CLOSE_NOWRITE 0x00000010 /* Unwritable file closed */
#define IN_OPEN 0x00000020 /* File was opened */
#define IN_MOVED_FROM 0x00000040 /* File was moved from X */
#define IN_MOVED_TO 0x00000080 /* File was moved to Y */
Expand Down

0 comments on commit 1715f71

Please sign in to comment.