tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

NCHNAMLEN vnode cache limitation removal



Comments?

Thanks,

christos

Index: sys/namei.h
===================================================================
RCS file: /cvsroot/src/sys/sys/namei.h,v
retrieving revision 1.98
diff -u -p -u -r1.98 namei.h
--- sys/namei.h	3 Jun 2019 06:05:39 -0000	1.98
+++ sys/namei.h	10 Sep 2019 23:20:48 -0000
@@ -196,19 +196,9 @@ struct nameidata {
 #endif
 
 /*
+ * Namecache entry.  
  * This structure describes the elements in the cache of recent
- * names looked up by namei. NCHNAMLEN is sized to make structure
- * size a power of two to optimize allocations.  Minimum reasonable
- * size is 15.
- */
-
-#define	NCHNAMLEN	31	/* maximum name segment length we bother with */
-
-/*
- * Namecache entry.  This structure is arranged so that frequently
- * accessed and mostly read-only data is toward the front, with
- * infrequently accessed data and the lock towards the rear.  The
- * lock is then more likely to be in a separate cache line.
+ * names looked up by namei.
  *
  * Locking rules:
  *
@@ -225,14 +215,14 @@ struct namecache {
 	struct	vnode *nc_dvp;		/* N vnode of parent of name */
 	struct	vnode *nc_vp;		/* N vnode the name refers to */
 	int	nc_flags;		/* - copy of componentname ISWHITEOUT */
-	char	nc_nlen;		/* - length of name */
-	char	nc_name[NCHNAMLEN];	/* - segment name */
 	void	*nc_gcqueue;		/* N queue for garbage collection */
-	TAILQ_ENTRY(namecache) nc_lru;	/* L psuedo-lru chain */
+	TAILQ_ENTRY(namecache) nc_lru;	/* L pseudo-lru chain */
 	LIST_ENTRY(namecache) nc_dvlist;/* L dvp's list of cache entries */
 	LIST_ENTRY(namecache) nc_vlist; /* L vp's list of cache entries */
 	kmutex_t nc_lock;		/*   lock on this entry */
 	int	nc_hittime;		/* N last time scored a hit */
+	u_short	nc_nlen;		/* - length of name */
+	char	nc_name[0];		/* - segment name */
 };
 
 #ifdef _KERNEL
Index: sys/namei.src
===================================================================
RCS file: /cvsroot/src/sys/sys/namei.src,v
retrieving revision 1.42
diff -u -p -u -r1.42 namei.src
--- sys/namei.src	3 Jun 2019 06:04:21 -0000	1.42
+++ sys/namei.src	10 Sep 2019 23:20:48 -0000
@@ -188,19 +188,9 @@ NAMEIFL	PARAMASK	0x02ee300	/* mask of pa
 #endif
 
 /*
+ * Namecache entry. 
  * This structure describes the elements in the cache of recent
- * names looked up by namei. NCHNAMLEN is sized to make structure
- * size a power of two to optimize allocations.  Minimum reasonable
- * size is 15.
- */
-
-#define	NCHNAMLEN	31	/* maximum name segment length we bother with */
-
-/*
- * Namecache entry.  This structure is arranged so that frequently
- * accessed and mostly read-only data is toward the front, with
- * infrequently accessed data and the lock towards the rear.  The
- * lock is then more likely to be in a separate cache line.
+ * names looked up by namei.
  *
  * Locking rules:
  *
@@ -217,14 +207,14 @@ struct namecache {
 	struct	vnode *nc_dvp;		/* N vnode of parent of name */
 	struct	vnode *nc_vp;		/* N vnode the name refers to */
 	int	nc_flags;		/* - copy of componentname ISWHITEOUT */
-	char	nc_nlen;		/* - length of name */
-	char	nc_name[NCHNAMLEN];	/* - segment name */
 	void	*nc_gcqueue;		/* N queue for garbage collection */
 	TAILQ_ENTRY(namecache) nc_lru;	/* L psuedo-lru chain */
 	LIST_ENTRY(namecache) nc_dvlist;/* L dvp's list of cache entries */
 	LIST_ENTRY(namecache) nc_vlist; /* L vp's list of cache entries */
 	kmutex_t nc_lock;		/*   lock on this entry */
 	int	nc_hittime;		/* N last time scored a hit */
+	char	nc_nlen;		/* - length of name */
+	char	nc_name[0];		/* - segment name */
 };
 
 #ifdef _KERNEL
Index: kern/vfs_cache.c
===================================================================
RCS file: /cvsroot/src/sys/kern/vfs_cache.c,v
retrieving revision 1.120
diff -u -p -u -r1.120 vfs_cache.c
--- kern/vfs_cache.c	18 Mar 2017 22:36:56 -0000	1.120
+++ kern/vfs_cache.c	10 Sep 2019 23:20:48 -0000
@@ -94,13 +94,13 @@ __KERNEL_RCSID(0, "$NetBSD: vfs_cache.c,
  * containing name.
  *
  * For simplicity (and economy of storage), names longer than
- * a maximum length of NCHNAMLEN are not cached; they occur
- * infrequently in any case, and are almost never of interest.
+ * a maximum length of NCHNAMLEN are stored in non-pooled storage.
  *
  * Upon reaching the last segment of a path, if the reference
  * is for DELETE, or NOCACHE is set (rewrite), and the
  * name is located in the cache, it will be dropped.
  */
+#define NCHNAMLEN	30
 
 /*
  * Cache entry lifetime:
@@ -589,7 +589,7 @@ cache_lookup(struct vnode *dvp, const ch
 
 	cpup = curcpu()->ci_data.cpu_nch;
 	mutex_enter(&cpup->cpu_lock);
-	if (__predict_false(namelen > NCHNAMLEN)) {
+	if (__predict_false(namelen > USHRT_MAX)) {
 		SDT_PROBE(vfs, namecache, lookup, toolong, dvp,
 		    name, namelen, 0, 0);
 		COUNT(cpup, ncs_long);
@@ -703,7 +703,7 @@ cache_lookup_raw(struct vnode *dvp, cons
 
 	cpup = curcpu()->ci_data.cpu_nch;
 	mutex_enter(&cpup->cpu_lock);
-	if (__predict_false(namelen > NCHNAMLEN)) {
+	if (__predict_false(namelen > USHRT_MAX)) {
 		COUNT(cpup, ncs_long);
 		mutex_exit(&cpup->cpu_lock);
 		/* found nothing */
@@ -868,7 +868,7 @@ cache_enter(struct vnode *dvp, struct vn
 
 	/* First, check whether we can/should add a cache entry. */
 	if ((cnflags & MAKEENTRY) == 0 ||
-	    __predict_false(namelen > NCHNAMLEN || !doingcache)) {
+	    __predict_false(namelen > USHRT_MAX || !doingcache)) {
 		SDT_PROBE(vfs, namecache, enter, toolong, vp, name, namelen,
 		    0, 0);
 		return;
@@ -882,7 +882,11 @@ cache_enter(struct vnode *dvp, struct vn
 		mutex_exit(namecache_lock);
 	}
 
-	ncp = pool_cache_get(namecache_cache, PR_WAITOK);
+	if (namelen > NCHNAMLEN) {
+		ncp = kmem_alloc(sizeof(*ncp) + namelen, KM_SLEEP);
+		cache_ctor(NULL, ncp, 0);
+	} else
+		ncp = pool_cache_get(namecache_cache, PR_WAITOK);
 	mutex_enter(namecache_lock);
 	numcache++;
 
@@ -919,7 +923,7 @@ cache_enter(struct vnode *dvp, struct vn
 		ncp->nc_vlist.le_prev = NULL;
 		ncp->nc_vlist.le_next = NULL;
 	}
-	KASSERT(namelen <= NCHNAMLEN);
+	KASSERT(namelen <= USHRT_MAX);
 	ncp->nc_nlen = namelen;
 	memcpy(ncp->nc_name, name, (unsigned)ncp->nc_nlen);
 	TAILQ_INSERT_TAIL(&nclruhead, ncp, nc_lru);
@@ -970,7 +974,7 @@ nchinit(void)
 	int error;
 
 	TAILQ_INIT(&nclruhead);
-	namecache_cache = pool_cache_init(sizeof(struct namecache),
+	namecache_cache = pool_cache_init(sizeof(struct namecache) + NCHNAMLEN,
 	    coherency_unit, 0, 0, "ncache", NULL, IPL_NONE, cache_ctor,
 	    cache_dtor, NULL);
 	KASSERT(namecache_cache != NULL);
@@ -1248,7 +1252,11 @@ cache_reclaim(void)
 			LIST_REMOVE(ncp, nc_hash);
 			ncp->nc_hash.le_prev = NULL;
 		}
-		pool_cache_put(namecache_cache, ncp);
+		if (ncp->nc_nlen > NCHNAMLEN) {
+			cache_dtor(NULL, ncp);
+			kmem_free(ncp, sizeof(*ncp) + ncp->nc_nlen);
+		} else
+			pool_cache_put(namecache_cache, ncp);
 		ncp = next;
 	}
 	cache_unlock_cpus();


Home | Main Index | Thread Index | Old Index