Commit 1715f710 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'fsnotify_for_v6.9-rc1' of git://git.kernel.org/pub/scm/linux/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
parents babbcc02 0045fb1b
...@@ -228,8 +228,10 @@ static int fanotify_get_response(struct fsnotify_group *group, ...@@ -228,8 +228,10 @@ static int fanotify_get_response(struct fsnotify_group *group,
pr_debug("%s: group=%p event=%p\n", __func__, group, event); pr_debug("%s: group=%p event=%p\n", __func__, group, event);
ret = wait_event_killable(group->fanotify_data.access_waitq, ret = wait_event_state(group->fanotify_data.access_waitq,
event->state == FAN_EVENT_ANSWERED); event->state == FAN_EVENT_ANSWERED,
(TASK_KILLABLE|TASK_FREEZABLE));
/* Signal pending? */ /* Signal pending? */
if (ret < 0) { if (ret < 0) {
spin_lock(&group->notification_lock); spin_lock(&group->notification_lock);
......
...@@ -141,7 +141,7 @@ void __fsnotify_update_child_dentry_flags(struct inode *inode) ...@@ -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? */ /* 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 mask)
{ {
__u32 marks_mask = 0; __u32 marks_mask = 0;
...@@ -160,13 +160,22 @@ static bool fsnotify_event_needs_parent(struct inode *inode, struct mount *mnt, ...@@ -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? */ /* 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_fsnotify_mask);
marks_mask |= fsnotify_parent_needed_mask(inode->i_sb->s_fsnotify_mask); marks_mask |= fsnotify_parent_needed_mask(inode->i_sb->s_fsnotify_mask);
if (mnt) marks_mask |= fsnotify_parent_needed_mask(mnt_mask);
marks_mask |= fsnotify_parent_needed_mask(mnt->mnt_fsnotify_mask);
/* Did they subscribe for this event with parent/name info? */ /* Did they subscribe for this event with parent/name info? */
return mask & marks_mask; 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 * 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 * if parent is watching or if inode/sb/mount are interested in events with
...@@ -179,7 +188,7 @@ int __fsnotify_parent(struct dentry *dentry, __u32 mask, const void *data, ...@@ -179,7 +188,7 @@ int __fsnotify_parent(struct dentry *dentry, __u32 mask, const void *data,
int data_type) int data_type)
{ {
const struct path *path = fsnotify_data_path(data, 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 inode *inode = d_inode(dentry);
struct dentry *parent; struct dentry *parent;
bool parent_watched = dentry->d_flags & DCACHE_FSNOTIFY_PARENT_WATCHED; bool parent_watched = dentry->d_flags & DCACHE_FSNOTIFY_PARENT_WATCHED;
...@@ -190,16 +199,13 @@ int __fsnotify_parent(struct dentry *dentry, __u32 mask, const void *data, ...@@ -190,16 +199,13 @@ int __fsnotify_parent(struct dentry *dentry, __u32 mask, const void *data,
struct qstr *file_name = NULL; struct qstr *file_name = NULL;
int ret = 0; int ret = 0;
/* /* Optimize the likely case of nobody watching this path */
* Do inode/sb/mount care about parent and name info on non-dir? if (likely(!parent_watched &&
* Do they care about any event at all? !fsnotify_object_watched(inode, mnt_mask, mask)))
*/
if (!inode->i_fsnotify_marks && !inode->i_sb->s_fsnotify_marks &&
(!mnt || !mnt->mnt_fsnotify_marks) && !parent_watched)
return 0; return 0;
parent = NULL; 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) if (!parent_watched && !parent_needed)
goto notify; goto notify;
......
...@@ -17,6 +17,12 @@ ...@@ -17,6 +17,12 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/bug.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. * 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 * The directory entry may have turned positive or negative or its inode may
...@@ -30,7 +36,7 @@ static inline int fsnotify_name(__u32 mask, const void *data, int data_type, ...@@ -30,7 +36,7 @@ static inline int fsnotify_name(__u32 mask, const void *data, int data_type,
struct inode *dir, const struct qstr *name, struct inode *dir, const struct qstr *name,
u32 cookie) u32 cookie)
{ {
if (atomic_long_read(&dir->i_sb->s_fsnotify_connectors) == 0) if (!fsnotify_sb_has_watchers(dir->i_sb))
return 0; return 0;
return fsnotify(mask, data, data_type, dir, name, NULL, cookie); return fsnotify(mask, data, data_type, dir, name, NULL, cookie);
...@@ -44,7 +50,7 @@ static inline void fsnotify_dirent(struct inode *dir, struct dentry *dentry, ...@@ -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) 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; return;
if (S_ISDIR(inode->i_mode)) if (S_ISDIR(inode->i_mode))
...@@ -59,7 +65,7 @@ static inline int fsnotify_parent(struct dentry *dentry, __u32 mask, ...@@ -59,7 +65,7 @@ static inline int fsnotify_parent(struct dentry *dentry, __u32 mask,
{ {
struct inode *inode = d_inode(dentry); 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; return 0;
if (S_ISDIR(inode->i_mode)) { if (S_ISDIR(inode->i_mode)) {
......
...@@ -31,8 +31,8 @@ ...@@ -31,8 +31,8 @@
#define FS_ACCESS 0x00000001 /* File was accessed */ #define FS_ACCESS 0x00000001 /* File was accessed */
#define FS_MODIFY 0x00000002 /* File was modified */ #define FS_MODIFY 0x00000002 /* File was modified */
#define FS_ATTRIB 0x00000004 /* Metadata changed */ #define FS_ATTRIB 0x00000004 /* Metadata changed */
#define FS_CLOSE_WRITE 0x00000008 /* Writtable file was closed */ #define FS_CLOSE_WRITE 0x00000008 /* Writable file was closed */
#define FS_CLOSE_NOWRITE 0x00000010 /* Unwrittable file closed */ #define FS_CLOSE_NOWRITE 0x00000010 /* Unwritable file closed */
#define FS_OPEN 0x00000020 /* File was opened */ #define FS_OPEN 0x00000020 /* File was opened */
#define FS_MOVED_FROM 0x00000040 /* File was moved from X */ #define FS_MOVED_FROM 0x00000040 /* File was moved from X */
#define FS_MOVED_TO 0x00000080 /* File was moved to Y */ #define FS_MOVED_TO 0x00000080 /* File was moved to Y */
......
...@@ -8,8 +8,8 @@ ...@@ -8,8 +8,8 @@
#define FAN_ACCESS 0x00000001 /* File was accessed */ #define FAN_ACCESS 0x00000001 /* File was accessed */
#define FAN_MODIFY 0x00000002 /* File was modified */ #define FAN_MODIFY 0x00000002 /* File was modified */
#define FAN_ATTRIB 0x00000004 /* Metadata changed */ #define FAN_ATTRIB 0x00000004 /* Metadata changed */
#define FAN_CLOSE_WRITE 0x00000008 /* Writtable file closed */ #define FAN_CLOSE_WRITE 0x00000008 /* Writable file closed */
#define FAN_CLOSE_NOWRITE 0x00000010 /* Unwrittable file closed */ #define FAN_CLOSE_NOWRITE 0x00000010 /* Unwritable file closed */
#define FAN_OPEN 0x00000020 /* File was opened */ #define FAN_OPEN 0x00000020 /* File was opened */
#define FAN_MOVED_FROM 0x00000040 /* File was moved from X */ #define FAN_MOVED_FROM 0x00000040 /* File was moved from X */
#define FAN_MOVED_TO 0x00000080 /* File was moved to Y */ #define FAN_MOVED_TO 0x00000080 /* File was moved to Y */
......
...@@ -30,8 +30,8 @@ struct inotify_event { ...@@ -30,8 +30,8 @@ struct inotify_event {
#define IN_ACCESS 0x00000001 /* File was accessed */ #define IN_ACCESS 0x00000001 /* File was accessed */
#define IN_MODIFY 0x00000002 /* File was modified */ #define IN_MODIFY 0x00000002 /* File was modified */
#define IN_ATTRIB 0x00000004 /* Metadata changed */ #define IN_ATTRIB 0x00000004 /* Metadata changed */
#define IN_CLOSE_WRITE 0x00000008 /* Writtable file was closed */ #define IN_CLOSE_WRITE 0x00000008 /* Writable file was closed */
#define IN_CLOSE_NOWRITE 0x00000010 /* Unwrittable file closed */ #define IN_CLOSE_NOWRITE 0x00000010 /* Unwritable file closed */
#define IN_OPEN 0x00000020 /* File was opened */ #define IN_OPEN 0x00000020 /* File was opened */
#define IN_MOVED_FROM 0x00000040 /* File was moved from X */ #define IN_MOVED_FROM 0x00000040 /* File was moved from X */
#define IN_MOVED_TO 0x00000080 /* File was moved to Y */ #define IN_MOVED_TO 0x00000080 /* File was moved to Y */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment