Module Name:    src
Committed By:   ad
Date:           Thu Jan 23 12:33:18 UTC 2020

Modified Files:
        src/sys/kern [ad-namecache]: vfs_cache.c

Log Message:
Update comments.


To generate a diff of this commit:
cvs rdiff -u -r1.126.2.9 -r1.126.2.10 src/sys/kern/vfs_cache.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/vfs_cache.c
diff -u src/sys/kern/vfs_cache.c:1.126.2.9 src/sys/kern/vfs_cache.c:1.126.2.10
--- src/sys/kern/vfs_cache.c:1.126.2.9	Sun Jan 19 21:19:25 2020
+++ src/sys/kern/vfs_cache.c	Thu Jan 23 12:33:18 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: vfs_cache.c,v 1.126.2.9 2020/01/19 21:19:25 ad Exp $	*/
+/*	$NetBSD: vfs_cache.c,v 1.126.2.10 2020/01/23 12:33:18 ad Exp $	*/
 
 /*-
  * Copyright (c) 2008, 2019, 2020 The NetBSD Foundation, Inc.
@@ -63,92 +63,104 @@
 /*
  * Name caching:
  *
- * 	Names found by directory scans are retained in a cache for future
- * 	reference.  It is managed pseudo-LRU, so frequently used names will
- * 	hang around.  Cache is indexed by directory.
- *
- *	Upon reaching the last segment of a path, if the reference is for
- *	DELETE, or NOCACHE is set (rewrite), and name is located in the
- *	cache, it will be dropped.
+ *	Names found by directory scans are retained in a cache for future
+ *	reference.  It is managed pseudo-LRU, so frequently used names will
+ *	hang around.  The cache is indexed by directory.
  *
  * Background:
  *
  *	XXX add a bit of history
  *
- * Data structures:
+ * Data structures
  *
- *	The original BSD implementation used a global hash table, which
- *	works very well but can cause difficulties for the CPU cache on
- *	modern CPUs, and concurrency headaches for the kernel hacker on
- *	multiprocessor systems.  The global hash table is also difficult to
- *	size dynamically.  To try and address these concerns, the focus of
- *	interest in this implementation is the directory itself: a
- *	per-directory red-black tree is used to look up names.  Other than
- *	the choice of data structure, it works largely the same way as the
- *	BSD implementation.
+ *	Typically DNLCs use a global hash table for lookup, which works very
+ *	well but can cause challenges for the CPU cache on modern CPUs, and
+ *	concurrency headaches for the kernel hacker.  The focus of interest
+ *	in this implementation is the directory itself: a per-directory data
+ *	structure is used to index names.  Currently this is a red-black
+ *	tree.  There are no special concurrency requirements placed on the
+ *	index, so it should not be difficult to experiment with other
+ *	structures.
+ *
+ *	Each cached name is stored in a struct namecache, along with a
+ *	pointer the associated vnode (nc_vp).  For simplicity (and economy
+ *	of storage), names longer than a maximum length of NCHNAMLEN are
+ *	allocated with kmem_alloc(); they occur infrequently.  Names shorter
+ *	than this are stored directly in struct namecache.  If it is a
+ *	"negative" entry, (i.e.  for a name that is known NOT to exist) the
+ *	vnode pointer will be NULL.
  *
- * Replacement:
- *
- *	XXX LRU blurb.
- *
- * Concurrency:
- *
- *	XXX need new blurb here
- *
- *	See definition of "struct namecache" in src/sys/namei.src for the
- *	particulars.
- *
- *	Per-CPU statistics, and "numcache" are read unlocked, since an
- *	approximate value is OK.  We maintain uintptr_t sized per-CPU
- *	counters and 64-bit global counters under the theory that uintptr_t
- *	sized counters are less likely to be hosed by nonatomic increment.
- *
- * Lock order:
- *
- *	1) nc_dvp->vi_ncdlock
- *	2) nc_dvp->vi_ncvlock
- *	3) cache_lru_lock, vp->v_interlock
- *
- * Ugly ASCII diagram:
- *
- *	XXX replace tabs with spaces, make less ugly
+ *	The nchnode (XXXAD vnode) and namecache structures are connected together thusly
+ *	(the root is at the bottom of the diagram):
  *
  *          ...
  *           ^
- *           |
- *      -----o-----
- *      |  VDIR   |
- *      | nchnode |
- *      -----------
- *           ^
- *           |- nd_tree
+ *           |- nn_tree
  *           |                                                           
- *      -----o-----               -----------               -----------
+ *      +----o----+               +---------+               +---------+
  *      |  VDIR   |               |  VCHR   |               |  VREG   |
  *      | nchnode o-----+         | nchnode o-----+         | nchnode o------+
- *      -----------     |         -----------     |         -----------      |
+ *      +---------+     |         +---------+     |         +---------+      |
  *           ^          |              ^          |              ^           |
  *           |- nc_nn   |- nn_list     |- nc_nn   |- nn_list     |- nc_nn    |
  *           |          |              |          |              |           |
- *      -----o-----     |         -----o-----     |         -----o-----      |
+ *      +----o----+     |         +----o----+     |         +----o----+      |
  *  +---onamecache|<----+     +---onamecache|<----+     +---onamecache|<-----+
- *  |   -----------           |   -----------           |   -----------
+ *  |   +---------+           |   +---------+           |   +---------+
  *  |        ^                |        ^                |        ^
  *  |        |                |        |                |        |
  *  |        |  +----------------------+                |        |
  *  |-nc_dnn | +-------------------------------------------------+
- *  |        |/- nd_tree      |                         |
+ *  |        |/- nn_tree      |                         |
  *  |        |                |- nc_dnn                 |- nc_dnn
- *  |   -----o-----           |                         |
+ *  |   +----o----+           |                         |
  *  +-->|  VDIR   |<----------+                         |
  *      | nchnode |<------------------------------------+
- *      -----------
+ *      +---------+
  *
  *      START HERE
+ *
+ * Replacement:
+ *
+ *	As the cache becomes full, old and unused entries are purged as new
+ *	entries are added.  It would be too expensive to maintain a strict
+ *	LRU list based on last access, so instead we ape the VM system and
+ *	maintain lits of active and inactive entries.  New entries go to the
+ *	tail of the active list.  After they age out, they are placed on the
+ *	tail of the inactive list.  Any subsequent use of the cache entry
+ *	reactivates it, saving it from impending doom; if not reactivated,
+ *	the entry will eventually be purged.
+ *
+ * Concurrency:
+ *
+ *	From a performance perspective, cache_lookup(nameiop == LOOKUP) and
+ *	its siblings are what really matters; insertion of new entries with
+ *	cache_enter() is comparatively infrequent.  This dictates the
+ *	concurrency strategy: lookups must be easy, never difficult.
+ *
+ *	struct namecache is mostly stable except for list and tree related
+ *	entries, which don't affect the cached name or vnode, and entries
+ *	are purged in preference to modifying them.  Read access to
+ *	namecache entries is made via tree, list, or LRU list.  A lock
+ *	corresponding to the direction of access should be held.  See
+ *	definition of "struct namecache" in src/sys/namei.src, and the
+ *	definition of "struct nchnode" XXXAD vnode for the particulars.
+ *
+ *	Per-CPU statistics, and "numcache" are read unlocked, since an
+ *	approximate value is OK.  We maintain uintptr_t sized per-CPU
+ *	counters and 64-bit global counters under the theory that uintptr_t
+ *	sized counters are less likely to be hosed by nonatomic increment.
+ *
+ *	The lock order is:
+ *
+ *	1) nn->nn_lock		(tree or parent->child direction)
+ *	2) nn->nn_listlock	(list or child->parent direction)
+ *	3) cache_lru_lock	(LRU list direction)
+ *	4) vp->v_interlock
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vfs_cache.c,v 1.126.2.9 2020/01/19 21:19:25 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vfs_cache.c,v 1.126.2.10 2020/01/23 12:33:18 ad Exp $");
 
 #define __NAMECACHE_PRIVATE
 #ifdef _KERNEL_OPT
@@ -175,9 +187,9 @@ __KERNEL_RCSID(0, "$NetBSD: vfs_cache.c,
 #include <miscfs/genfs/genfs.h>
 
 /*
- * Per-vnode state for the namecache.  This is allocated apart from struct
- * vnode to make the best use of memory, and best use of CPU cache.  Field
- * markings and corresponding locks:
+ * Per-vnode state for the namecache.  Field markings and corresponding
+ * locks.  XXXAD this needs to be folded back into struct vnode, but
+ * struct vnode_impl_t needs to be folded back into struct vnode first.
  *
  *	-	stable throught the lifetime of the vnode
  *	n	protected by nn_lock

Reply via email to