Module Name: src Committed By: ad Date: Sat Jan 18 15:42:02 UTC 2020
Modified Files: src/sys/kern [ad-namecache]: vfs_cache.c Log Message: - Adjust comments & assertions. - Ditch memcmp(). To generate a diff of this commit: cvs rdiff -u -r1.126.2.6 -r1.126.2.7 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.6 src/sys/kern/vfs_cache.c:1.126.2.7 --- src/sys/kern/vfs_cache.c:1.126.2.6 Fri Jan 17 22:26:25 2020 +++ src/sys/kern/vfs_cache.c Sat Jan 18 15:42:02 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: vfs_cache.c,v 1.126.2.6 2020/01/17 22:26:25 ad Exp $ */ +/* $NetBSD: vfs_cache.c,v 1.126.2.7 2020/01/18 15:42:02 ad Exp $ */ /*- * Copyright (c) 2008, 2019, 2020 The NetBSD Foundation, Inc. @@ -148,7 +148,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: vfs_cache.c,v 1.126.2.6 2020/01/17 22:26:25 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: vfs_cache.c,v 1.126.2.7 2020/01/18 15:42:02 ad Exp $"); #define __NAMECACHE_PRIVATE #ifdef _KERNEL_OPT @@ -330,6 +330,22 @@ cache_key(const char *name, size_t nlen) } /* + * Like memcmp() but tuned for small strings of equal length. + */ +static inline int +cache_namecmp(struct namecache *nc, const char *name, size_t namelen) +{ + size_t i; + int d; + + KASSERT(nc->nc_nlen == namelen); + for (d = 0, i = 0; i < namelen; i++) { + d |= (nc->nc_name[i] ^ name[i]); + } + return d; +} + +/* * Remove an entry from the cache. The directory lock must be held, and if * "dir2node" is true, then we're locking in the conventional direction and * the list lock will be acquired when removing the entry from the vnode @@ -378,11 +394,10 @@ cache_remove(struct namecache *nc, const } /* - * Find a single cache entry and return it locked. The directory lock must - * be held. + * Find a single cache entry and return it. The nchnode lock must be held. * * Marked __noinline, and with everything unnecessary excluded, the compiler - * (gcc 8.3.0 x86_64) does a great job on this. + * (gcc 8.3.0 x86_64) does a good job on this. */ static struct namecache * __noinline cache_lookup_entry(struct nchnode *dnn, const char *name, size_t namelen, @@ -394,12 +409,12 @@ cache_lookup_entry(struct nchnode *dnn, KASSERT(rw_lock_held(&dnn->nn_lock)); /* - * Search the RB tree for the key. This is one of the most - * performance sensitive code paths in the system, so here is an - * inlined version of rb_tree_find_node() tailored for exactly - * what's needed here (64-bit key and so on). Elsewhere during - * entry/removal the generic functions are used as it doesn't - * matter so much there. + * Search the RB tree for the key. File lookup is very performance + * sensitive, so here is an inlined lookup tailored for exactly + * what's needed here (64-bit key and so on) that is much faster + * than using rb_tree_find_node(). Elsewhere during entry/removal + * the generic functions are used as it doesn't matter so much + * there. */ for (;;) { if (__predict_false(RB_SENTINEL_P(node))) { @@ -415,8 +430,7 @@ cache_lookup_entry(struct nchnode *dnn, } /* Exclude collisions. */ - KASSERT(nc->nc_nlen == namelen); - if (__predict_false(memcmp(nc->nc_name, name, namelen) != 0)) { + if (__predict_false(cache_namecmp(nc, name, namelen))) { return NULL; } @@ -666,7 +680,7 @@ cache_lookup_linked(struct vnode *dvp, c rw_exit(*plock); } *plock = &dnn->nn_lock; - } else { + } else if (*plock == NULL) { KASSERT(dvp->v_usecount > 0); } @@ -674,6 +688,8 @@ cache_lookup_linked(struct vnode *dvp, c * First up check if the user is allowed to look up files in this * directory. */ + KASSERT(dnn->nn_mode != VNOVAL && dnn->nn_uid != VNOVAL && + dnn->nn_gid != VNOVAL); error = kauth_authorize_vnode(cred, KAUTH_ACCESS_ACTION(VEXEC, dvp->v_type, dnn->nn_mode & ALLPERMS), dvp, NULL, genfs_can_access(dvp->v_type, dnn->nn_mode & ALLPERMS, @@ -857,7 +873,7 @@ cache_enter(struct vnode *dvp, struct vn onc = rb_tree_find_node(&dnn->nn_tree, &nc->nc_key); if (onc) { KASSERT(onc->nc_nlen == nc->nc_nlen); - if (memcmp(onc->nc_name, nc->nc_name, nc->nc_nlen) != 0) { + if (cache_namecmp(onc, name, namelen)) { COUNT(ncs_collisions); } cache_remove(onc, true);