Pathname lookup – The Linux Kernel documentation

ankitg121 pts0 comments

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...

pathname lookup linux component directory final

Related Articles