Module Name:    src
Committed By:   riastradh
Date:           Wed Aug  2 07:11:31 UTC 2023

Modified Files:
        src/sys/kern: kern_fileassoc.c

Log Message:
fileassoc(9): Fast paths to skip global locks when not in use.

PR kern/57552


To generate a diff of this commit:
cvs rdiff -u -r1.36 -r1.37 src/sys/kern/kern_fileassoc.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/kern/kern_fileassoc.c
diff -u src/sys/kern/kern_fileassoc.c:1.36 src/sys/kern/kern_fileassoc.c:1.37
--- src/sys/kern/kern_fileassoc.c:1.36	Thu Jul 10 15:00:28 2014
+++ src/sys/kern/kern_fileassoc.c	Wed Aug  2 07:11:31 2023
@@ -1,4 +1,4 @@
-/* $NetBSD: kern_fileassoc.c,v 1.36 2014/07/10 15:00:28 christos Exp $ */
+/* $NetBSD: kern_fileassoc.c,v 1.37 2023/08/02 07:11:31 riastradh Exp $ */
 
 /*-
  * Copyright (c) 2006 Elad Efrat <e...@netbsd.org>
@@ -28,7 +28,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_fileassoc.c,v 1.36 2014/07/10 15:00:28 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_fileassoc.c,v 1.37 2023/08/02 07:11:31 riastradh Exp $");
 
 #include "opt_fileassoc.h"
 
@@ -42,6 +42,8 @@ __KERNEL_RCSID(0, "$NetBSD: kern_fileass
 #include <sys/hash.h>
 #include <sys/kmem.h>
 #include <sys/once.h>
+#include <sys/mutex.h>
+#include <sys/xcall.h>
 
 #define	FILEASSOC_INITIAL_TABLESIZE	128
 
@@ -88,6 +90,52 @@ struct fileassoc_table {
 	(hash32_buf((handle), FHANDLE_SIZE(handle), HASH32_BUF_INIT) \
 	 & ((tbl)->tbl_mask))
 
+/*
+ * Global usage counting.  This is bad for parallelism of updates, but
+ * good for avoiding calls to fileassoc when it's not in use.  Unclear
+ * if parallelism of updates matters much.  If you want to improve
+ * fileassoc(9) update performance, feel free to rip this out as long
+ * as you don't cause the fast paths to take any global locks or incur
+ * memory barriers when fileassoc(9) is not in use.
+ */
+static struct {
+	kmutex_t lock;
+	uint64_t nassocs;
+	volatile bool inuse;
+} fileassoc_global __cacheline_aligned;
+
+static void
+fileassoc_incuse(void)
+{
+
+	mutex_enter(&fileassoc_global.lock);
+	if (fileassoc_global.nassocs++ == 0) {
+		KASSERT(!fileassoc_global.inuse);
+		atomic_store_relaxed(&fileassoc_global.inuse, true);
+		xc_barrier(0);
+	}
+	mutex_exit(&fileassoc_global.lock);
+}
+
+static void
+fileassoc_decuse(void)
+{
+
+	mutex_enter(&fileassoc_global.lock);
+	KASSERT(fileassoc_global.nassocs > 0);
+	KASSERT(fileassoc_global.inuse);
+	if (--fileassoc_global.nassocs == 0)
+		atomic_store_relaxed(&fileassoc_global.inuse, false);
+	mutex_exit(&fileassoc_global.lock);
+}
+
+static bool
+fileassoc_inuse(void)
+{
+
+	return __predict_false(atomic_load_relaxed(&fileassoc_global.inuse));
+}
+
 static void *
 file_getdata(struct fileassoc_file *faf, const struct fileassoc *assoc)
 {
@@ -128,6 +176,7 @@ file_free(struct fileassoc_file *faf)
 
 	LIST_FOREACH(assoc, &fileassoc_list, assoc_list) {
 		file_cleanup(faf, assoc);
+		fileassoc_decuse();
 	}
 	vfs_composefh_free(faf->faf_handle);
 	specificdata_fini(fileassoc_domain, &faf->faf_data);
@@ -226,6 +275,9 @@ fileassoc_table_lookup(struct mount *mp)
 {
 	int error;
 
+	if (!fileassoc_inuse())
+		return NULL;
+
 	error = RUN_ONCE(&control, fileassoc_init);
 	if (error) {
 		return NULL;
@@ -437,6 +489,8 @@ fileassoc_table_clear(struct mount *mp, 
 		LIST_FOREACH(faf, &tbl->tbl_hash[i], faf_list) {
 			file_cleanup(faf, assoc);
 			file_setdata(faf, assoc, NULL);
+			/* XXX missing faf->faf_nassocs--? */
+			fileassoc_decuse();
 		}
 	}
 
@@ -510,10 +564,9 @@ fileassoc_file_delete(struct vnode *vp)
 	struct fileassoc_table *tbl;
 	struct fileassoc_file *faf;
 
-	/* Pre-check if fileassoc is used. XXX */
-	if (!fileassoc_domain) {
+	if (!fileassoc_inuse())
 		return ENOENT;
-	}
+
 	KERNEL_LOCK(1, NULL);
 
 	faf = fileassoc_file_lookup(vp, NULL);
@@ -553,6 +606,8 @@ fileassoc_add(struct vnode *vp, fileasso
 	if (olddata != NULL)
 		return (EEXIST);
 
+	fileassoc_incuse();
+
 	file_setdata(faf, assoc, data);
 
 	faf->faf_nassocs++;
@@ -577,5 +632,7 @@ fileassoc_clear(struct vnode *vp, fileas
 
 	--(faf->faf_nassocs); /* XXX gc? */
 
+	fileassoc_decuse();
+
 	return (0);
 }

Reply via email to