Pathname Lookup

In this section, we illustrate how the VFS derives an inode from the corresponding file pathname. When a process must identify a file, it passes its file pathname to some VFS system call, such as open( ) , mkdir( ) , rename( ) , or stat( ) .

The standard procedure for performing this task consists of analyzing the pathname and breaking it into a sequence of filenames. All filenames except the last must identify directories.

If the first character of the pathname is / , the pathname is absolute, and the search starts from the directory identified by current->fs->root (the process root directory). Otherwise, the pathname is relative and the search starts from the directory identified by current->fs->pwd (the process-current directory).

Having in hand the inode of the initial directory, the code examines the entry matching the first name to derive the corresponding inode. Then the directory file that has that inode is read from disk and the entry matching the second name is examined to derive the corresponding inode. This procedure is repeated for each name included in the path.

The dentry cache considerably speeds up the procedure, since it keeps the most recently used dentry objects in memory. As we saw before, each such object associates a filename in a specific directory to its corresponding inode. In many cases, therefore, the analysis of the pathname can avoid reading the intermediate directories from the disk.

However, things are not as simple as they look, since the following Unix and VFS filesystem features must be taken into consideration:

• The access rights of each directory must be checked to verify whether the process is allowed to read the directory's content.

• A filename can be a symbolic link that corresponds to an arbitrary pathname; in this case, the analysis must be extended to all components of that pathname.

• Symbolic links may induce circular references; the kernel must take this possibility into account and break endless loops when they occur.

• A filename can be the mount point of a mounted filesystem. This situation must be detected, and the lookup operation must continue into the new filesystem.

Pathname lookup is performed by three functions: path_init( ), path_walk( ), and path_release( ). They are always invoked in this exact order.

The path_init( ) function receives three parameters:

name

A pointer to the file pathname to be resolved.

flags

The value of flags that represent how the looked-up file is going to be accessed. The

[7] There is, however, a small difference in how the o_rdonly, o_wronly, and o_rdwr flags are encoded. The bit at index 0 (lowest-order) of the flags parameter is set only if the file access requires read privileges; similarly, the bit at index 1 is set only if the file access requires write privileges. Conversely, for the open( ) system call, the value of the o_wronly flag is stored in the bit at index 0, while the o_rdwr flag is stored in the bit at index 1; thus, the o_rdonly flag is true when both bits are cleared. Notice that it is not possible to specify in the open( ) system call that a file access does not require either read or write privileges; this makes sense, however, in a pathname lookup operation involving symbolic links.

The address of a struct nameidata data structure.

The struct nameidata data structure is filled by path_walk( ) with data pertaining to the pathname lookup operation. The fields of this structure are shown in Table 12-14.

Table 12-14. The fields of the nameidata data structure

Type

Field

Description

struct dentry *

dentry

Address of the dentry object

struct vfs mount *

mnt

Address of the mounted filesystem object

struct qstr

last

Last component of the pathname (used when the

LOOKUP parent flag is set)

unsigned int

flags

Lookup flags

int

last type

Type of last component of the pathname (used when the lookup parent flag is set)

The dentry and mnt fields point respectively to the dentry object and the mounted filesystem object of the last resolved component in the pathname. Once path_walk( )

successfully returns, these two fields "describe" the file that is identified by the given pathname.

The flags field stores the value of some flags used in the lookup operation; they are listed in Table 12-15.

Table 12-15. The flags of the lookup operation

Macro

Description

LOOKUP FOLLOW

If the last component is a symbolic link, interpret (follow) it.

LOOKUP DIRECTORY

The last component must be a directory.

LOOKUP CONTINUE

There are still filenames to be examined in the pathname (used only by NFS).

LOOKUP POSITIVE

The pathname must identify an existing file.

LOOKUP PARENT

Look up the directory including the last component of the pathname.

LOOKUP NOALT

Do not consider the emulated root directory (always set for the 80 x 86 architecture).

The goal of the path_init( ) function consists of initializing the nameidata structure, which it does in the following manner:

1. Sets the dentry field with the address of the dentry object of the directory where the pathname lookup operation starts. If the pathname is relative (it doesn't start with a slash), the field points to the dentry of the working directory (current->fs->pwd); otherwise it points to the dentry of the root directory of the process

2. Sets the mnt field with the address of the mounted filesystem object relative to the directory where the pathname lookup operation starts: either current->fs->pwdmnt or current->fs->rootmnt, according to whether the pathname is relative or absolute.

3. Initializes the flags field with the value of the flags parameter.

4. Initializes the last_type field to last_root.

Once path_init( ) initializes the nameidata data structure, the path_walk( ) function takes care of the lookup operation, and stores in the nameidata structure the pointers to the dentry object and mounted filesystem object relative to the last component of the pathname. The function also increments the usage counters of the objects referenced by nd->dentry and nd->mnt so that the caller function may safely access them once path_walk( ) returns. When the caller finishes accessing them, it invokes the third function of the set, path_release( ), which receives as a parameter the address of the nameidata data structure and decrements the two usage counters of nd->dentry and nd->mnt.

We are now ready to describe the core of the pathname lookup operation, namely the path_walk( ) function. It receives as parameters a pointer name to the pathname to be resolved and the address nd of the nameidata data structure. The function initializes to zero the total_link_count of the current process (see the later section Section 12.5.3), and then invokes link_path_walk( ). This latter function acts on the same two parameters of path_walk( ).

To make things a bit easier, we first describe what link_path_walk( ) does when lookup_parent is not set and the pathname does not contain symbolic links (standard pathname lookup). Next, we discuss the case in which lookup_parent is set: this type of lookup is required when creating, deleting, or renaming a directory entry, that is, during a parent pathname lookup. Finally, we explain how the function resolves the symbolic links.

Was this article helpful?

0 0

Post a comment