VFS_CACHE(9)
β¨ VFS_CACHE(9) β the kernel dev manual's greatest hits β¨
okay so bestie, you know how name lookups can be slow? this is the whole page about the kernel's little β¨name lookup cacheβ¨ and the vfs_cache API. it's giving "we memorized the answers so we don't have to re-do the homework" and honestly? iconic. π
πΈ SYNOPSIS πΈ
#include <sys/vnode.h>
#include <sys/namei.h>
int
cache_lookup(struct vnode *dvp, struct vnode **vpp,
struct componentname *cnp);
void
cache_enter(struct vnode *dvp, struct vnode *vp,
struct componentname *cnp);
void
cache_purge(struct vnode *vp);
void
cache_purgevfs(struct mount *mp);
int
cache_revlookup(struct vnode *vp, struct vnode **dvpp, char **bpp,
char *bufp);
π¦ DESCRIPTION π¦
so like, to speed up file name look-up operations (peep VOP_LOOKUP(9) if you wanna know more), the kernel ships an interface for maintaining a cache of the most recently looked-up file name translations. lowkey genius. β¨ entries in this cache have the following definition:
struct namecache {
TAILQ_ENTRY(namecache) nc_lru; /* Regular Entry LRU chain */
TAILQ_ENTRY(namecache) nc_neg; /* Negative Entry LRU chain */
RBT_ENTRY(namecache) n_rbcache; /* Namecache rb tree from vnode */
TAILQ_ENTRY(namecache) nc_me; /* ncp's referring to me */
struct vnode *nc_dvp; /* vnode of parent of name */
u_long nc_dvpid; /* capability number of nc_dvp */
struct vnode *nc_vp; /* vnode the name refers to */
u_long nc_vpid; /* capability number of nc_vp */
char nc_nlen; /* length of name */
char nc_name[NAMECACHE_MAXLEN]; /* segment name */
};
the cache is indexed by a hash value based on the file's base name and its encompassing directory's vnode generation number. we also do negative caching so that when you keep asking for files that don't exist (we've all been there π), it doesn't turn into an expensive lookup every single time. main character energy from the kernel fr fr.
file names with length longer than NAMECACHE_MAXLEN are not cached β this simplifies lookups and saves space. those names are rare and generally not worth caching, so it's a whole vibe check and they did not pass. π
the vfs_cache API contains the following routines:
cache_lookup(dvp, vpp, cnp)β look up the given name in the cache.dvppoints to the directory to search,vpppoints to a pointer where the vnode of the name being sought will be stored, andcnpcontains the last component of the path name.cnpmust have thecn_nameptr,cn_namelen, andcn_hashfields filled in. if no entry is found for the given name, a new one will be created β even if the path name fails (i.e. it will be negative cached) β unless thenamei(9)lookup operation wasDELETEor theNOCACHEflag was set for the call tonamei(9).
upon success, a pointer to a locked vnode is stored in vpp and a zero value is returned. if locking the vnode fails, the vnode will remain unlocked, *vpp will be set to NULL, and the corresponding error will be returned. if the cache entry is negative cached β meaning the name is no longer valid β ENOENT is returned. otherwise, the cache lookup has failed and a -1 value is returned. ok so that's three whole outcomes, memorize them bestie π«Ά
cache_enter(dvp, vp, cnp)β add a new entry for the translation in the directorydvpfor the vnodevpwith namecnpto the cache.cnpmust have thecn_nameptr,cn_namelen, andcn_hashfields filled in. (yes, same three fields, it's a whole thing π )cache_purge(vp)β flush all cache entries corresponding with the given vnodevp. this is called after rename operations to hide entries that would no longer be valid. like cleaning out your camera roll after a glow-up, periodt.cache_purgevfs(mp)β flush all cache entries for name translations associated with the file system mount described bymp. this is called when unmounting file systems, which would make all name translations pertaining to the mount invalid. bye bye bestie πcache_revlookup(vp, dvpp, bpp, bufp)β scan the cache for the name of the directory entry that points tovp.dvpppoints to where a pointer to the encompassing directory will be stored. ifbufpis notNULL, the name will be written to the end of the space between this pointer and the value inbpp, andbppwill be updated on return to point to the start of the copied name. the way that little pointer dance works is so satisfying ngl.
on success, *dvpp will be set to point to the encompassing directory and zero will be returned. if the cache misses, dvpp will be set to NULL and -1 will be returned. otherwise, failure has occurred, dvpp will be set to NULL, and an appropriate error code will be returned. π€
π₯ CODE REFERENCES π₯
the vfs_cache API is implemented in the file sys/kern/vfs_cache.c. go read it, it's lowkey a fun time. π
π SEE ALSO π
π HISTORY π
the vfs_cache API first appeared in 4.2BSD. she's an oldie but a goodie, and she still ate. π
okay so that's literally the whole page, no cap. now go forth and cache responsibly, bestie π
and that's a wrap! this gem is from the Debian edition, dated June 4, 2018, header VFS_CACHE(9) and all β stan a classic manual page fr fr πβ¨π¦
π¦ where this page comes from
- nixpkgs unstable: cvs-export
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms