Pathname lookup — The Linux Kernel documentation
The Linux Kernel
7.1.0-rc5
Quick search
Contents
Development process
Submitting patches
Code of conduct
Maintainer handbook
All development-process docs
Core API
Driver APIs
Subsystems<br>Core subsystems
Human interfaces
Networking interfaces
Storage interfaces<br>Filesystems in the Linux kernel
Block
CD-ROM
SCSI Subsystem
TCM Virtual Device
NVMe Subsystem
Other subsystems
Locking
Licensing rules
Writing documentation
Development tools
Testing guide
Hacking guide
Tracing
Fault injection
Livepatching
Rust
Administration
Build system
Reporting issues
Userspace tools
Userspace API
Firmware
Firmware and Devicetree
CPU architectures
Unsorted documentation
Translations
This Page
Show Source
Pathname lookup¶
This write-up is based on three articles published at lwn.net:
https://lwn.net/Articles/649115/> Pathname lookup in Linux
https://lwn.net/Articles/649729/> RCU-walk: faster pathname lookup in Linux
https://lwn.net/Articles/650786/> A walk among the symlinks
Written by Neil Brown with help from Al Viro and Jon Corbet.<br>It has subsequently been updated to reflect changes in the kernel<br>including:
per-directory parallel name lookup.
openat2() resolution restriction flags.
Introduction to pathname lookup¶
The most obvious aspect of pathname lookup, which very little<br>exploration is needed to discover, is that it is complex. There are<br>many rules, special cases, and implementation alternatives that all<br>combine to confuse the unwary reader. Computer science has long been<br>acquainted with such complexity and has tools to help manage it. One<br>tool that we will make extensive use of is “divide and conquer”. For<br>the early parts of the analysis we will divide off symlinks - leaving<br>them until the final part. Well before we get to symlinks we have<br>another major division based on the VFS’s approach to locking which<br>will allow us to review “REF-walk” and “RCU-walk” separately. But we<br>are getting ahead of ourselves. There are some important low level<br>distinctions we need to clarify first.
There are two sorts of ...¶
Pathnames (sometimes “file names”), used to identify objects in the<br>filesystem, will be familiar to most readers. They contain two sorts<br>of elements: “slashes” that are sequences of one or more “/”<br>characters, and “components” that are sequences of one or more<br>non-”/” characters. These form two kinds of paths. Those that<br>start with slashes are “absolute” and start from the filesystem root.<br>The others are “relative” and start from the current directory, or<br>from some other location specified by a file descriptor given to<br>“*at()” system calls such as openat().
It is tempting to describe the second kind as starting with a<br>component, but that isn’t always accurate: a pathname can lack both<br>slashes and components, it can be empty, in other words. This is<br>generally forbidden in POSIX, but some of those “*at()” system calls<br>in Linux permit it when the AT_EMPTY_PATH flag is given. For<br>example, if you have an open file descriptor on an executable file you<br>can execute it by calling execveat() passing<br>the file descriptor, an empty path, and the AT_EMPTY_PATH flag.
These paths can be divided into two sections: the final component and<br>everything else. The “everything else” is the easy bit. In all cases<br>it must identify a directory that already exists, otherwise an error<br>such as ENOENT or ENOTDIR will be reported.
The final component is not so simple. Not only do different system<br>calls interpret it quite differently (e.g. some create it, some do<br>not), but it might not even exist: neither the empty pathname nor the<br>pathname that is just slashes have a final component. If it does<br>exist, it could be “.” or “..” which are handled quite differently<br>from other components.
If a pathname ends with a slash, such as “/tmp/foo/” it might be<br>tempting to consider that to have an empty final component. In many<br>ways that would lead to correct results, but not always. In<br>particular, mkdir() and rmdir() each create or remove a directory named<br>by the final component, and they are required to work with pathnames<br>ending in “/”. According to POSIX:
A pathname that contains at least one non- character and<br>that ends with one or more trailing characters shall not<br>be resolved successfully unless the last pathname component before<br>the trailing characters names an existing directory or a<br>directory entry that is to be created for a directory immediately<br>after the pathname is resolved.
The Linux pathname walking code (mostly in fs/namei.c) deals with<br>all of these issues: breaking the path into components, handling the<br>“everything else” quite separately from the final component, and<br>checking that the trailing slash is not used where it isn’t<br>permitted. It also addresses the important issue of concurrent<br>access.
While one process is looking up a pathname, another might be making<br>changes that affect that lookup. One fairly extreme case is that if<br>“a/b” were...