diff mbox

[v2,12/20] fsnotify: introduce prototype struct fsnotify_obj

Message ID 1522934301-6520-13-git-send-email-amir73il@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Amir Goldstein April 5, 2018, 1:18 p.m. UTC
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

Comments

Jan Kara April 19, 2018, 12:14 p.m. UTC | #1
On Thu 05-04-18 16:18:13, Amir Goldstein wrote:
> 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>

I like this!

								Honza
diff mbox

Patch

diff --git a/fs/inode.c b/fs/inode.c
index ef362364d396..121baae0453d 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -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);
diff --git a/fs/mount.h b/fs/mount.h
index f39bc9da4d73..54de165ea032 100644
--- a/fs/mount.h
+++ b/fs/mount.h
@@ -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 */
diff --git a/fs/notify/dnotify/dnotify.c b/fs/notify/dnotify/dnotify.c
index e2bea2ac5dfb..d46167c69c99 100644
--- a/fs/notify/dnotify/dnotify.c
+++ b/fs/notify/dnotify/dnotify.c
@@ -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);
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c
index c07eb3d655ea..54ab6aafbc76 100644
--- a/fs/notify/fanotify/fanotify_user.c
+++ b/fs/notify/fanotify/fanotify_user.c
@@ -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);
diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c
index d6e38aac9463..6a235091d2e4 100644
--- a/fs/notify/fsnotify.c
+++ b/fs/notify/fsnotify.c
@@ -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));
 	}
 
 	/*
diff --git a/fs/notify/fsnotify.h b/fs/notify/fsnotify.h
index 34515d2c4ba3..8f4d3e43b5b5 100644
--- a/fs/notify/fsnotify.h
+++ b/fs/notify/fsnotify.h
@@ -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);
diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c
index af3efe78b599..2d6c6f2fed04 100644
--- a/fs/notify/inotify/inotify_user.c
+++ b/fs/notify/inotify/inotify_user.c
@@ -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);
 
 	}
 
diff --git a/fs/notify/mark.c b/fs/notify/mark.c
index 3df2d5ecf0b7..97bf4d0fae7a 100644
--- a/fs/notify/mark.c
+++ b/fs/notify/mark.c
@@ -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);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index c6baf767619e..144a488fb74b 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -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)
diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h
index d96bbc6e77ce..0940b78df4b6 100644
--- a/include/linux/fsnotify_backend.h
+++ b/include/linux/fsnotify_backend.h
@@ -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;
 }
 
 /*
diff --git a/include/linux/fsnotify_obj.h b/include/linux/fsnotify_obj.h
new file mode 100644
index 000000000000..437e78e60f82
--- /dev/null
+++ b/include/linux/fsnotify_obj.h
@@ -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
diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c
index 9d50821f8ad8..9f83676aec64 100644
--- a/kernel/audit_tree.c
+++ b/kernel/audit_tree.c
@@ -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);
diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c
index 439a3a01368c..1b017875b8d2 100644
--- a/kernel/audit_watch.c
+++ b/kernel/audit_watch.c
@@ -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);
 
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index e80459f7e132..6c3f9e0ea2ed 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -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) {