Mel Gorman 9f0ef4
From 182e67bdaac446ed7cb9fa926b930ebafb38ed49 Mon Sep 17 00:00:00 2001
Mel Gorman 9f0ef4
From: Amir Goldstein <amir73il@gmail.com>
Mel Gorman 9f0ef4
Date: Tue, 10 Aug 2021 18:12:19 +0300
Mel Gorman 9f0ef4
Subject: [PATCH] fsnotify: count all objects with attached connectors
Mel Gorman 9f0ef4
Mel Gorman 9f0ef4
References: bsc#1190120 (Fsnotify functional and performance backports)
Mel Gorman 9f0ef4
Patch-mainline: v5.15-rc1
Mel Gorman 9f0ef4
Git-commit: ec44610fe2b86daef70f3f53f47d2a2542d7094f
Mel Gorman 9f0ef4
Mel Gorman 9f0ef4
Rename s_fsnotify_inode_refs to s_fsnotify_connectors and count all
Mel Gorman 9f0ef4
objects with attached connectors, not only inodes with attached
Mel Gorman 9f0ef4
connectors.
Mel Gorman 9f0ef4
Mel Gorman 9f0ef4
This will be used to optimize fsnotify() calls on sb without any
Mel Gorman 9f0ef4
type of marks.
Mel Gorman 9f0ef4
Mel Gorman 9f0ef4
Link: https://lore.kernel.org/r/20210810151220.285179-4-amir73il@gmail.com
Mel Gorman 9f0ef4
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
Mel Gorman 9f0ef4
Reviewed-by: Matthew Bobrowski <repnop@google.com>
Mel Gorman 9f0ef4
Signed-off-by: Jan Kara <jack@suse.cz>
Mel Gorman 9f0ef4
Signed-off-by: Mel Gorman <mgorman@suse.de>
Mel Gorman 9f0ef4
---
Mel Gorman 9f0ef4
 fs/notify/fsnotify.c |  6 +++---
Mel Gorman 9f0ef4
 fs/notify/fsnotify.h | 15 +++++++++++++++
Mel Gorman 9f0ef4
 fs/notify/mark.c     | 24 +++++++++++++++++++++---
Mel Gorman 9f0ef4
 include/linux/fs.h   |  7 +++++--
Mel Gorman 9f0ef4
 4 files changed, 44 insertions(+), 8 deletions(-)
Mel Gorman 9f0ef4
Mel Gorman 9f0ef4
diff --git a/fs/notify/fsnotify.c b/fs/notify/fsnotify.c
Mel Gorman 9f0ef4
index 30d422b8c0fc..963e6ce75b96 100644
Mel Gorman 9f0ef4
--- a/fs/notify/fsnotify.c
Mel Gorman 9f0ef4
+++ b/fs/notify/fsnotify.c
Mel Gorman 9f0ef4
@@ -87,15 +87,15 @@ static void fsnotify_unmount_inodes(struct super_block *sb)
Mel Gorman 9f0ef4
 
Mel Gorman 9f0ef4
 	if (iput_inode)
Mel Gorman 9f0ef4
 		iput(iput_inode);
Mel Gorman 9f0ef4
-	/* Wait for outstanding inode references from connectors */
Mel Gorman 9f0ef4
-	wait_var_event(&sb->s_fsnotify_inode_refs,
Mel Gorman 9f0ef4
-		       !atomic_long_read(&sb->s_fsnotify_inode_refs));
Mel Gorman 9f0ef4
 }
Mel Gorman 9f0ef4
 
Mel Gorman 9f0ef4
 void fsnotify_sb_delete(struct super_block *sb)
Mel Gorman 9f0ef4
 {
Mel Gorman 9f0ef4
 	fsnotify_unmount_inodes(sb);
Mel Gorman 9f0ef4
 	fsnotify_clear_marks_by_sb(sb);
Mel Gorman 9f0ef4
+	/* Wait for outstanding object references from connectors */
Mel Gorman 9f0ef4
+	wait_var_event(&sb->s_fsnotify_connectors,
Mel Gorman 9f0ef4
+		       !atomic_long_read(&sb->s_fsnotify_connectors));
Mel Gorman 9f0ef4
 }
Mel Gorman 9f0ef4
 
Mel Gorman 9f0ef4
 /*
Mel Gorman 9f0ef4
diff --git a/fs/notify/fsnotify.h b/fs/notify/fsnotify.h
Mel Gorman 9f0ef4
index ff2063ec6b0f..87d8a50ee803 100644
Mel Gorman 9f0ef4
--- a/fs/notify/fsnotify.h
Mel Gorman 9f0ef4
+++ b/fs/notify/fsnotify.h
Mel Gorman 9f0ef4
@@ -27,6 +27,21 @@ static inline struct super_block *fsnotify_conn_sb(
Mel Gorman 9f0ef4
 	return container_of(conn->obj, struct super_block, s_fsnotify_marks);
Mel Gorman 9f0ef4
 }
Mel Gorman 9f0ef4
 
Mel Gorman 9f0ef4
+static inline struct super_block *fsnotify_connector_sb(
Mel Gorman 9f0ef4
+				struct fsnotify_mark_connector *conn)
Mel Gorman 9f0ef4
+{
Mel Gorman 9f0ef4
+	switch (conn->type) {
Mel Gorman 9f0ef4
+	case FSNOTIFY_OBJ_TYPE_INODE:
Mel Gorman 9f0ef4
+		return fsnotify_conn_inode(conn)->i_sb;
Mel Gorman 9f0ef4
+	case FSNOTIFY_OBJ_TYPE_VFSMOUNT:
Mel Gorman 9f0ef4
+		return fsnotify_conn_mount(conn)->mnt.mnt_sb;
Mel Gorman 9f0ef4
+	case FSNOTIFY_OBJ_TYPE_SB:
Mel Gorman 9f0ef4
+		return fsnotify_conn_sb(conn);
Mel Gorman 9f0ef4
+	default:
Mel Gorman 9f0ef4
+		return NULL;
Mel Gorman 9f0ef4
+	}
Mel Gorman 9f0ef4
+}
Mel Gorman 9f0ef4
+
Mel Gorman 9f0ef4
 /* destroy all events sitting in this groups notification queue */
Mel Gorman 9f0ef4
 extern void fsnotify_flush_notify(struct fsnotify_group *group);
Mel Gorman 9f0ef4
 
Mel Gorman 9f0ef4
diff --git a/fs/notify/mark.c b/fs/notify/mark.c
Mel Gorman 9f0ef4
index 2d8c46e1167d..95006d1d29ab 100644
Mel Gorman 9f0ef4
--- a/fs/notify/mark.c
Mel Gorman 9f0ef4
+++ b/fs/notify/mark.c
Mel Gorman 9f0ef4
@@ -172,7 +172,7 @@ static void fsnotify_connector_destroy_workfn(struct work_struct *work)
Mel Gorman 9f0ef4
 static void fsnotify_get_inode_ref(struct inode *inode)
Mel Gorman 9f0ef4
 {
Mel Gorman 9f0ef4
 	ihold(inode);
Mel Gorman 9f0ef4
-	atomic_long_inc(&inode->i_sb->s_fsnotify_inode_refs);
Mel Gorman 9f0ef4
+	atomic_long_inc(&inode->i_sb->s_fsnotify_connectors);
Mel Gorman 9f0ef4
 }
Mel Gorman 9f0ef4
 
Mel Gorman 9f0ef4
 static void fsnotify_put_inode_ref(struct inode *inode)
Mel Gorman 9f0ef4
@@ -180,8 +180,24 @@ static void fsnotify_put_inode_ref(struct inode *inode)
Mel Gorman 9f0ef4
 	struct super_block *sb = inode->i_sb;
Mel Gorman 9f0ef4
 
Mel Gorman 9f0ef4
 	iput(inode);
Mel Gorman 9f0ef4
-	if (atomic_long_dec_and_test(&sb->s_fsnotify_inode_refs))
Mel Gorman 9f0ef4
-		wake_up_var(&sb->s_fsnotify_inode_refs);
Mel Gorman 9f0ef4
+	if (atomic_long_dec_and_test(&sb->s_fsnotify_connectors))
Mel Gorman 9f0ef4
+		wake_up_var(&sb->s_fsnotify_connectors);
Mel Gorman 9f0ef4
+}
Mel Gorman 9f0ef4
+
Mel Gorman 9f0ef4
+static void fsnotify_get_sb_connectors(struct fsnotify_mark_connector *conn)
Mel Gorman 9f0ef4
+{
Mel Gorman 9f0ef4
+	struct super_block *sb = fsnotify_connector_sb(conn);
Mel Gorman 9f0ef4
+
Mel Gorman 9f0ef4
+	if (sb)
Mel Gorman 9f0ef4
+		atomic_long_inc(&sb->s_fsnotify_connectors);
Mel Gorman 9f0ef4
+}
Mel Gorman 9f0ef4
+
Mel Gorman 9f0ef4
+static void fsnotify_put_sb_connectors(struct fsnotify_mark_connector *conn)
Mel Gorman 9f0ef4
+{
Mel Gorman 9f0ef4
+	struct super_block *sb = fsnotify_connector_sb(conn);
Mel Gorman 9f0ef4
+
Mel Gorman 9f0ef4
+	if (sb && atomic_long_dec_and_test(&sb->s_fsnotify_connectors))
Mel Gorman 9f0ef4
+		wake_up_var(&sb->s_fsnotify_connectors);
Mel Gorman 9f0ef4
 }
Mel Gorman 9f0ef4
 
Mel Gorman 9f0ef4
 static void *fsnotify_detach_connector_from_object(
Mel Gorman 9f0ef4
@@ -203,6 +219,7 @@ static void *fsnotify_detach_connector_from_object(
Mel Gorman 9f0ef4
 		fsnotify_conn_sb(conn)->s_fsnotify_mask = 0;
Mel Gorman 9f0ef4
 	}
Mel Gorman 9f0ef4
 
Mel Gorman 9f0ef4
+	fsnotify_put_sb_connectors(conn);
Mel Gorman 9f0ef4
 	rcu_assign_pointer(*(conn->obj), NULL);
Mel Gorman 9f0ef4
 	conn->obj = NULL;
Mel Gorman 9f0ef4
 	conn->type = FSNOTIFY_OBJ_TYPE_DETACHED;
Mel Gorman 9f0ef4
@@ -504,6 +521,7 @@ static int fsnotify_attach_connector_to_object(fsnotify_connp_t *connp,
Mel Gorman 9f0ef4
 		inode = fsnotify_conn_inode(conn);
Mel Gorman 9f0ef4
 		fsnotify_get_inode_ref(inode);
Mel Gorman 9f0ef4
 	}
Mel Gorman 9f0ef4
+	fsnotify_get_sb_connectors(conn);
Mel Gorman 9f0ef4
 
Mel Gorman 9f0ef4
 	/*
Mel Gorman 9f0ef4
 	 * cmpxchg() provides the barrier so that readers of *connp can see
Mel Gorman 9f0ef4
diff --git a/include/linux/fs.h b/include/linux/fs.h
Mel Gorman 9f0ef4
index b2341c262f78..4d747acf9453 100644
Mel Gorman 9f0ef4
--- a/include/linux/fs.h
Mel Gorman 9f0ef4
+++ b/include/linux/fs.h
Mel Gorman 9f0ef4
@@ -1516,8 +1516,11 @@ struct super_block {
Mel Gorman 9f0ef4
 	/* Number of inodes with nlink == 0 but still referenced */
Mel Gorman 9f0ef4
 	atomic_long_t s_remove_count;
Mel Gorman 9f0ef4
 
Mel Gorman 9f0ef4
-	/* Pending fsnotify inode refs */
Mel Gorman 9f0ef4
-	atomic_long_t s_fsnotify_inode_refs;
Mel Gorman 9f0ef4
+	/*
Mel Gorman 9f0ef4
+	 * Number of inode/mount/sb objects that are being watched, note that
Mel Gorman 9f0ef4
+	 * inodes objects are currently double-accounted.
Mel Gorman 9f0ef4
+	 */
Mel Gorman 9f0ef4
+	atomic_long_t s_fsnotify_connectors;
Mel Gorman 9f0ef4
 
Mel Gorman 9f0ef4
 	/* Being remounted read-only */
Mel Gorman 9f0ef4
 	int s_readonly_remount;