@@ -190,7 +190,7 @@ int inode_init_always(struct super_block *sb, struct inode *inode)
#endif
#ifdef CONFIG_FSNOTIFY
- inode->i_fsnotify_mask = 0;
+ inode->i_fsnotify.mask = 0;
#endif
inode->i_flctx = NULL;
this_cpu_inc(nr_inodes);
@@ -4,6 +4,7 @@
#include <linux/poll.h>
#include <linux/ns_common.h>
#include <linux/fs_pin.h>
+#include <linux/fsnotify_obj.h>
struct mnt_namespace {
atomic_t count;
@@ -61,8 +62,7 @@ struct mount {
struct hlist_node mnt_mp_list; /* list mounts with the same mountpoint */
struct list_head mnt_umounting; /* list entry for umount propagation */
#ifdef CONFIG_FSNOTIFY
- struct fsnotify_mark_connector __rcu *mnt_fsnotify_marks;
- __u32 mnt_fsnotify_mask;
+ struct fsnotify_obj mnt_fsnotify;
#endif
int mnt_id; /* mount identifier */
int mnt_group_id; /* peer group identifier */
@@ -33,7 +33,7 @@ static struct kmem_cache *dnotify_mark_cache __read_mostly;
static struct fsnotify_group *dnotify_group __read_mostly;
/*
- * dnotify will attach one of these to each inode (i_fsnotify_marks) which
+ * dnotify will attach one of these to each inode (i_fsnotify.marks) which
* is being watched by dnotify. If multiple userspace applications are watching
* the same directory with dnotify their information is chained in dn
*/
@@ -158,7 +158,7 @@ void dnotify_flush(struct file *filp, fl_owner_t id)
if (!S_ISDIR(inode->i_mode))
return;
- fsn_mark = fsnotify_find_mark(&inode->i_fsnotify_marks, dnotify_group);
+ fsn_mark = fsnotify_find_mark(&inode->i_fsnotify.marks, dnotify_group);
if (!fsn_mark)
return;
dn_mark = container_of(fsn_mark, struct dnotify_mark, fsn_mark);
@@ -218,7 +218,7 @@ static __u32 convert_arg(unsigned long arg)
/*
* If multiple processes watch the same inode with dnotify there is only one
- * dnotify mark in inode->i_fsnotify_marks but we chain a dnotify_struct
+ * dnotify mark in inode->i_fsnotify.marks but we chain a dnotify_struct
* onto that mark. This function either attaches the new dnotify_struct onto
* that list, or it |= the mask onto an existing dnofiy_struct.
*/
@@ -314,7 +314,7 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg)
mutex_lock(&dnotify_group->mark_mutex);
/* add the new_fsn_mark or find an old one. */
- fsn_mark = fsnotify_find_mark(&inode->i_fsnotify_marks, dnotify_group);
+ fsn_mark = fsnotify_find_mark(&inode->i_fsnotify.marks, dnotify_group);
if (fsn_mark) {
dn_mark = container_of(fsn_mark, struct dnotify_mark, fsn_mark);
spin_lock(&fsn_mark->lock);
@@ -533,7 +533,7 @@ static int fanotify_remove_vfsmount_mark(struct fsnotify_group *group,
int destroy_mark;
mutex_lock(&group->mark_mutex);
- fsn_mark = fsnotify_find_mark(&real_mount(mnt)->mnt_fsnotify_marks,
+ fsn_mark = fsnotify_find_mark(&real_mount(mnt)->mnt_fsnotify.marks,
group);
if (!fsn_mark) {
mutex_unlock(&group->mark_mutex);
@@ -542,8 +542,8 @@ static int fanotify_remove_vfsmount_mark(struct fsnotify_group *group,
removed = fanotify_mark_remove_from_mask(fsn_mark, mask, flags,
&destroy_mark);
- if (removed & real_mount(mnt)->mnt_fsnotify_mask)
- fsnotify_recalc_mask(real_mount(mnt)->mnt_fsnotify_marks);
+ if (removed & real_mount(mnt)->mnt_fsnotify.mask)
+ fsnotify_recalc_mask(real_mount(mnt)->mnt_fsnotify.marks);
if (destroy_mark)
fsnotify_detach_mark(fsn_mark);
mutex_unlock(&group->mark_mutex);
@@ -563,7 +563,7 @@ static int fanotify_remove_inode_mark(struct fsnotify_group *group,
int destroy_mark;
mutex_lock(&group->mark_mutex);
- fsn_mark = fsnotify_find_mark(&inode->i_fsnotify_marks, group);
+ fsn_mark = fsnotify_find_mark(&inode->i_fsnotify.marks, group);
if (!fsn_mark) {
mutex_unlock(&group->mark_mutex);
return -ENOENT;
@@ -571,8 +571,8 @@ static int fanotify_remove_inode_mark(struct fsnotify_group *group,
removed = fanotify_mark_remove_from_mask(fsn_mark, mask, flags,
&destroy_mark);
- if (removed & inode->i_fsnotify_mask)
- fsnotify_recalc_mask(inode->i_fsnotify_marks);
+ if (removed & inode->i_fsnotify.mask)
+ fsnotify_recalc_mask(inode->i_fsnotify.marks);
if (destroy_mark)
fsnotify_detach_mark(fsn_mark);
mutex_unlock(&group->mark_mutex);
@@ -647,7 +647,7 @@ static int fanotify_add_vfsmount_mark(struct fsnotify_group *group,
__u32 added;
mutex_lock(&group->mark_mutex);
- fsn_mark = fsnotify_find_mark(&real_mount(mnt)->mnt_fsnotify_marks,
+ fsn_mark = fsnotify_find_mark(&real_mount(mnt)->mnt_fsnotify.marks,
group);
if (!fsn_mark) {
fsn_mark = fanotify_add_new_mark(group, NULL, mnt);
@@ -657,8 +657,8 @@ static int fanotify_add_vfsmount_mark(struct fsnotify_group *group,
}
}
added = fanotify_mark_add_to_mask(fsn_mark, mask, flags);
- if (added & ~real_mount(mnt)->mnt_fsnotify_mask)
- fsnotify_recalc_mask(real_mount(mnt)->mnt_fsnotify_marks);
+ if (added & ~real_mount(mnt)->mnt_fsnotify.mask)
+ fsnotify_recalc_mask(real_mount(mnt)->mnt_fsnotify.marks);
mutex_unlock(&group->mark_mutex);
fsnotify_put_mark(fsn_mark);
@@ -685,7 +685,7 @@ static int fanotify_add_inode_mark(struct fsnotify_group *group,
return 0;
mutex_lock(&group->mark_mutex);
- fsn_mark = fsnotify_find_mark(&inode->i_fsnotify_marks, group);
+ fsn_mark = fsnotify_find_mark(&inode->i_fsnotify.marks, group);
if (!fsn_mark) {
fsn_mark = fanotify_add_new_mark(group, inode, NULL);
if (IS_ERR(fsn_mark)) {
@@ -694,8 +694,8 @@ static int fanotify_add_inode_mark(struct fsnotify_group *group,
}
}
added = fanotify_mark_add_to_mask(fsn_mark, mask, flags);
- if (added & ~inode->i_fsnotify_mask)
- fsnotify_recalc_mask(inode->i_fsnotify_marks);
+ if (added & ~inode->i_fsnotify.mask)
+ fsnotify_recalc_mask(inode->i_fsnotify.marks);
mutex_unlock(&group->mark_mutex);
fsnotify_put_mark(fsn_mark);
@@ -160,7 +160,7 @@ int __fsnotify_parent(const struct path *path, struct dentry *dentry, __u32 mask
if (unlikely(!fsnotify_inode_watches_children(p_inode)))
__fsnotify_update_child_dentry_flags(p_inode);
- else if (p_inode->i_fsnotify_mask & mask) {
+ else if (p_inode->i_fsnotify.mask & mask) {
struct name_snapshot name;
/* we are notifying a parent so come up with the new mask which
@@ -326,13 +326,13 @@ int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int data_is,
/*
* Optimization: srcu_read_lock() has a memory barrier which can
- * be expensive. It protects walking the *_fsnotify_marks lists.
+ * be expensive. It protects walking the *_fsnotify.marks lists.
* However, if we do not walk the lists, we do not have to do
* SRCU because we have no references to any objects and do not
* need SRCU to keep them "alive".
*/
- if (!to_tell->i_fsnotify_marks &&
- (!mnt || !mnt->mnt_fsnotify_marks))
+ if (!to_tell->i_fsnotify.marks &&
+ (!mnt || !mnt->mnt_fsnotify.marks))
return 0;
/*
* if this is a modify event we may need to clear the ignored masks
@@ -340,24 +340,24 @@ int fsnotify(struct inode *to_tell, __u32 mask, const void *data, int data_is,
* this type of event.
*/
if (!(mask & FS_MODIFY) &&
- !(test_mask & to_tell->i_fsnotify_mask) &&
- !(mnt && test_mask & mnt->mnt_fsnotify_mask))
+ !(test_mask & to_tell->i_fsnotify.mask) &&
+ !(mnt && test_mask & mnt->mnt_fsnotify.mask))
return 0;
iter_info.srcu_idx = srcu_read_lock(&fsnotify_mark_srcu);
if ((mask & FS_MODIFY) ||
- (test_mask & to_tell->i_fsnotify_mask)) {
+ (test_mask & to_tell->i_fsnotify.mask)) {
fsnotify_iter_set_inode_mark(&iter_info,
- fsnotify_first_mark(&to_tell->i_fsnotify_marks));
+ fsnotify_first_mark(&to_tell->i_fsnotify.marks));
}
if (mnt && ((mask & FS_MODIFY) ||
- (test_mask & mnt->mnt_fsnotify_mask))) {
+ (test_mask & mnt->mnt_fsnotify.mask))) {
fsnotify_iter_set_inode_mark(&iter_info,
- fsnotify_first_mark(&to_tell->i_fsnotify_marks));
+ fsnotify_first_mark(&to_tell->i_fsnotify.marks));
fsnotify_iter_set_vfsmount_mark(&iter_info,
- fsnotify_first_mark(&mnt->mnt_fsnotify_marks));
+ fsnotify_first_mark(&mnt->mnt_fsnotify.marks));
}
/*
@@ -24,12 +24,12 @@ extern void fsnotify_destroy_marks(struct fsnotify_mark_connector __rcu **connp)
/* run the list of all marks associated with inode and destroy them */
static inline void fsnotify_clear_marks_by_inode(struct inode *inode)
{
- fsnotify_destroy_marks(&inode->i_fsnotify_marks);
+ fsnotify_destroy_marks(&inode->i_fsnotify.marks);
}
/* run the list of all marks associated with vfsmount and destroy them */
static inline void fsnotify_clear_marks_by_mount(struct vfsmount *mnt)
{
- fsnotify_destroy_marks(&real_mount(mnt)->mnt_fsnotify_marks);
+ fsnotify_destroy_marks(&real_mount(mnt)->mnt_fsnotify.marks);
}
/* Wait until all marks queued for destruction are destroyed */
extern void fsnotify_wait_marks_destroyed(void);
@@ -498,7 +498,7 @@ static int inotify_update_existing_watch(struct fsnotify_group *group,
mask = inotify_arg_to_mask(arg);
- fsn_mark = fsnotify_find_mark(&inode->i_fsnotify_marks, group);
+ fsn_mark = fsnotify_find_mark(&inode->i_fsnotify.marks, group);
if (!fsn_mark)
return -ENOENT;
@@ -517,11 +517,11 @@ static int inotify_update_existing_watch(struct fsnotify_group *group,
/* more bits in old than in new? */
int dropped = (old_mask & ~new_mask);
/* more bits in this fsn_mark than the inode's mask? */
- int do_inode = (new_mask & ~inode->i_fsnotify_mask);
+ int do_inode = (new_mask & ~inode->i_fsnotify.mask);
/* update the inode with this new fsn_mark */
if (dropped || do_inode)
- fsnotify_recalc_mask(inode->i_fsnotify_marks);
+ fsnotify_recalc_mask(inode->i_fsnotify.marks);
}
@@ -120,9 +120,9 @@ static void __fsnotify_recalc_mask(struct fsnotify_mark_connector *conn)
new_mask |= mark->mask;
}
if (conn->type == FSNOTIFY_OBJ_TYPE_INODE)
- conn->inode->i_fsnotify_mask = new_mask;
+ conn->inode->i_fsnotify.mask = new_mask;
else if (conn->type == FSNOTIFY_OBJ_TYPE_VFSMOUNT)
- real_mount(conn->mnt)->mnt_fsnotify_mask = new_mask;
+ real_mount(conn->mnt)->mnt_fsnotify.mask = new_mask;
}
/*
@@ -168,14 +168,14 @@ static struct inode *fsnotify_detach_connector_from_object(
if (conn->type == FSNOTIFY_OBJ_TYPE_INODE) {
inode = conn->inode;
- rcu_assign_pointer(inode->i_fsnotify_marks, NULL);
- inode->i_fsnotify_mask = 0;
+ rcu_assign_pointer(inode->i_fsnotify.marks, NULL);
+ inode->i_fsnotify.mask = 0;
conn->inode = NULL;
conn->type = FSNOTIFY_OBJ_TYPE_DETACHED;
} else if (conn->type == FSNOTIFY_OBJ_TYPE_VFSMOUNT) {
- rcu_assign_pointer(real_mount(conn->mnt)->mnt_fsnotify_marks,
+ rcu_assign_pointer(real_mount(conn->mnt)->mnt_fsnotify.marks,
NULL);
- real_mount(conn->mnt)->mnt_fsnotify_mask = 0;
+ real_mount(conn->mnt)->mnt_fsnotify.mask = 0;
conn->mnt = NULL;
conn->type = FSNOTIFY_OBJ_TYPE_DETACHED;
}
@@ -515,9 +515,9 @@ static int fsnotify_add_mark_list(struct fsnotify_mark *mark,
if (WARN_ON(!inode && !mnt))
return -EINVAL;
if (inode)
- connp = &inode->i_fsnotify_marks;
+ connp = &inode->i_fsnotify.marks;
else
- connp = &real_mount(mnt)->mnt_fsnotify_marks;
+ connp = &real_mount(mnt)->mnt_fsnotify.marks;
restart:
spin_lock(&mark->lock);
conn = fsnotify_grab_connector(connp);
@@ -35,6 +35,7 @@
#include <linux/delayed_call.h>
#include <linux/uuid.h>
#include <linux/errseq.h>
+#include <linux/fsnotify_obj.h>
#include <asm/byteorder.h>
#include <uapi/linux/fs.h>
@@ -560,8 +561,6 @@ is_uncached_acl(struct posix_acl *acl)
#define IOP_XATTR 0x0008
#define IOP_DEFAULT_READLINK 0x0010
-struct fsnotify_mark_connector;
-
/*
* Keep mostly read-only and often accessed (especially for
* the RCU path lookup and 'stat' data) fields at the beginning
@@ -661,8 +660,7 @@ struct inode {
__u32 i_generation;
#ifdef CONFIG_FSNOTIFY
- __u32 i_fsnotify_mask; /* all events this inode cares about */
- struct fsnotify_mark_connector __rcu *i_fsnotify_marks;
+ struct fsnotify_obj i_fsnotify;
#endif
#if IS_ENABLED(CONFIG_FS_ENCRYPTION)
@@ -19,6 +19,7 @@
#include <linux/atomic.h>
#include <linux/user_namespace.h>
#include <linux/refcount.h>
+#include <linux/fsnotify_obj.h>
/*
* IN_* from inotfy.h lines up EXACTLY with FS_*, this is so we can easily
@@ -335,11 +336,11 @@ extern u32 fsnotify_get_cookie(void);
static inline int fsnotify_inode_watches_children(struct inode *inode)
{
/* FS_EVENT_ON_CHILD is set if the inode may care */
- if (!(inode->i_fsnotify_mask & FS_EVENT_ON_CHILD))
+ if (!(inode->i_fsnotify.mask & FS_EVENT_ON_CHILD))
return 0;
/* this inode might care about child events, does it care about the
* specific set of events that can happen on a child? */
- return inode->i_fsnotify_mask & FS_EVENTS_POSS_ON_CHILD;
+ return inode->i_fsnotify.mask & FS_EVENTS_POSS_ON_CHILD;
}
/*
new file mode 100644
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_FSNOTIFY_OBJ_H
+#define _LINUX_FSNOTIFY_OBJ_H
+
+struct fsnotify_mark_connector;
+
+/* struct to embed in objects, which marks can be attached to */
+struct fsnotify_obj {
+ struct fsnotify_mark_connector __rcu *marks;
+ /* all events this object cares about */
+ __u32 mask;
+};
+
+#endif
@@ -393,7 +393,7 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree)
struct node *p;
int n;
- old_entry = fsnotify_find_mark(&inode->i_fsnotify_marks,
+ old_entry = fsnotify_find_mark(&inode->i_fsnotify.marks,
audit_tree_group);
if (!old_entry)
return create_chunk(inode, tree);
@@ -103,7 +103,7 @@ static inline struct audit_parent *audit_find_parent(struct inode *inode)
struct audit_parent *parent = NULL;
struct fsnotify_mark *entry;
- entry = fsnotify_find_mark(&inode->i_fsnotify_marks, audit_watch_group);
+ entry = fsnotify_find_mark(&inode->i_fsnotify.marks, audit_watch_group);
if (entry)
parent = container_of(entry, struct audit_parent, mark);
@@ -1600,7 +1600,7 @@ static inline void handle_one(const struct inode *inode)
struct audit_tree_refs *p;
struct audit_chunk *chunk;
int count;
- if (likely(!inode->i_fsnotify_marks))
+ if (likely(!inode->i_fsnotify.marks))
return;
context = current->audit_context;
p = context->trees;
@@ -1643,7 +1643,7 @@ static void handle_path(const struct dentry *dentry)
seq = read_seqbegin(&rename_lock);
for(;;) {
struct inode *inode = d_backing_inode(d);
- if (inode && unlikely(inode->i_fsnotify_marks)) {
+ if (inode && unlikely(inode->i_fsnotify.marks)) {
struct audit_chunk *chunk;
chunk = audit_tree_lookup(inode);
if (chunk) {
struct inode and struct vfsmount are both types of objects, which marks can be attached to. Let them "inherit" from a prototype struct, so that marks manipulation code can be made more generic. Signed-off-by: Amir Goldstein <amir73il@gmail.com> --- fs/inode.c | 2 +- fs/mount.h | 4 ++-- fs/notify/dnotify/dnotify.c | 8 ++++---- fs/notify/fanotify/fanotify_user.c | 24 ++++++++++++------------ fs/notify/fsnotify.c | 22 +++++++++++----------- fs/notify/fsnotify.h | 4 ++-- fs/notify/inotify/inotify_user.c | 6 +++--- fs/notify/mark.c | 16 ++++++++-------- include/linux/fs.h | 6 ++---- include/linux/fsnotify_backend.h | 5 +++-- include/linux/fsnotify_obj.h | 14 ++++++++++++++ kernel/audit_tree.c | 2 +- kernel/audit_watch.c | 2 +- kernel/auditsc.c | 4 ++-- 14 files changed, 66 insertions(+), 53 deletions(-) create mode 100644 include/linux/fsnotify_obj.h