Standard Pathname Lookup

When the lookup_parent flag is cleared, link_path_walk( ) performs the following steps.

1. Initializes the lookup_flags local variable with nd->flags.

2. Skips any leading slash ( / ) before the first component of the pathname.

3. If the remaining pathname is empty, returns the value 0. In the nameidata data structure, the dentry and mnt fields point to the object relative to the last resolved component of the original pathname.

4. If the link_count field in the descriptor of the current process is positive, sets the lookup_follow flag in the lookup_flags local variable (see Section 12.5.3).

5. Executes a cycle that breaks name into components (the intermediate slashes are treated as filename separators); for each component found, the function:

a. Retrieves the address of the inode object of the last resolved component from nd->dentry->d inode.

b. Checks that the permissions of the last resolved component stored into the inode allow execution (in Unix, a directory can be traversed only if it is executable). If the inode has a custom permission method, the function executes it; otherwise, it executes the vfs_permission( ) function, which examines the access mode stored in the i_mode inode field and the privileges of the running process.

c. Considers the next component to be resolved. From its name, it computes a hash value for the dentry cache hash table.

d. Skips any trailing slash ( / ) after the slash that terminates the name of the component to be resolved.

e. If the component to be resolved is the last one in the original pathname, jump to Step 6.

f. If the name of the component is "." (a single dot), continues with the next component ("." refers to the current directory, so it has no effect inside a pathname).

g. If the name of the component is ". ." (two dots), tries to climb to the parent directory:

1. If the last resolved directory is the process's root directory (nd-

>dentry is equal to current->fs->root and nd->mnt is equal to current->fs->rootmnt), continues with the next component.

2. If the last resolved directory is the root directory of a mounted filesystem (nd->dentry is equal to nd->mnt->mnt_root), sets nd->mnt to nd->mnt->mnt parent and nd->dentry to nd->mnt->mnt_mountpoint, and then restarts Step 5.g. (Recall that several filesystems can be mounted on the same mount point).

3. If the last resolved directory is not the root directory of a mounted filesystem, sets nd->dentry to nd->dentry->d_parent and continues with the next component.

h. The component name is neither "." nor ". .", so the function must look it up in the dentry cache. If the low-level filesystem has a custom d_hash dentry method, the function invokes it to modify the hash value already computed in Step 5.c.

i. Invokes cached_lookup( ), passing as parameters nd->dentry, the name of the component to be resolved, the hash value, and the lookup_continue flag, which specifies that this is not the last component of the pathname. The function invokes d_lookup( ) to search the dentry object of the component in the dentry cache. If cached_lookup( ) fails in finding the dentry in the cache, link_walk_path( ) invokes real_lookup( ) to read the directory from disk and create a new dentry object. In either case, we can assume at the end of this step that the dentry local variable points to the dentry object of the component name to be resolved in this cycle.

j. Checks whether the component just resolved (dentry local variable) refers to a directory that is a mount point for some filesystem (dentry->d_mounted is set to 1). In this case, invokes lookup_mnt( ), passing to it dentry and nd->mnt, in order to get the address mounted of the child mounted filesystem object. Next, it sets dentry to mounted->mnt_root and nd->mnt to mounted. Then it repeats the whole step (several filesystems can be mounted on the same mount point).

k. Checks whether the inode object dentry->d_inode has a custom follow_link method. If this is the case, the component is a symbolic link, which is described in the later section Section 12.5.3.

l. Checks that dentry points to the dentry object of a directory (dentry->d_inode->i_op->lookup method is defined). If not, returns the error -enotdir, because the component is in the middle of the original pathname.

m. Sets nd->dentry to dentry and continues with the next component of the pathname.

6. Now all components of the original pathname are resolved except the last one. If the pathname has a trailing slash, it sets the lookup_follow and lookup_directory in the lookup_flags local variable to force interpretation of the last component as a directory name.

7. Checks the value of the lookup_parent flag in the lookup_flags variable. In the following, we assume that the flag is set to 0, and we postpone the opposite case to the next section.

8. If the name of the last component is "." (a single dot), terminates the execution returning the value 0 (no error). In the nameidata structure that nd points to, the dentry and mnt fields refer to the objects relative to the next-to-last component of the pathname (any component "." has no effect inside a pathname).

9. If the name of the last component is ". ." (two dots), tries to climb to the parent directory:

a. If the last resolved directory is the process's root directory (nd->dentry is equal to current->fs->root and nd->mnt is equal to current->fs->rootmnt), terminates the execution returning the value 0 (no error). nd->dentry and nd->mnt refer to the objects relative to the next to the last component of the pathname—that is, to the root directory of the process.

b. If the last resolved directory is the root directory of a mounted filesystem

(nd->dentry is equal to nd->mnt->mnt_root), sets nd->mnt to nd->mnt->mnt parent and nd->dentry to nd->mnt->mnt mountpoint, and then restarts Step 5.j.

c. If the last resolved directory is not the root directory of a mounted filesystem, sets nd->dentry to nd->dentry->d_parent, and terminates the execution returning the value 0 (no error). nd->dentry and nd->mnt refer to the objects relative to the next-to-last component of the pathname.

10. The name of the last component is neither "." nor ". .", so the function must look it up in the dentry cache. If the low-level filesystem has a custom d_hash dentry method, the function invokes it to modify the hash value already computed in Step 5.c.

11. Invokes cached_lookup( ), passing as parameters nd->dentry, the name of the component to be resolved, the hash value, and no flag (lookup_continue is not set because this is the last component of the pathname). If cached_lookup( ) fails in finding the dentry in the cache, it also invokes real_lookup( ) to read the directory from disk and create a new dentry object. In either case, we can assume at the end of this step that the dentry local variable points to the dentry object of the component name to be resolved in this cycle.

12. Checks whether the component just resolved (dentry local variable) refers to a directory that is a mount point for some filesystem (dentry->d_mounted is set to 1). In this case, invokes lookup_mnt( ), passing to it dentry and nd->mnt, in order to get the address mounted of the child mounted filesystem object. Next, it sets dentry to mounted->mnt root and nd->mnt to mounted. Then it repeats the whole step (because several filesystems can be mounted on the same mount point).

13. Checks whether lookup_follow flag is set in lookup_flags and the inode object dentry->d_inode has a custom follow_link method. If this is the case, the component is a symbolic link that must be interpreted, as described in the later section Section 12.5.3.

14. Sets nd->dentry with the value stored in the dentry local variable. This dentry object is "the result" of the lookup operation.

15. Checks whether nd->dentry->d_inode is null. This happens when there is no inode associated with the dentry object, usually because the pathname refers to a nonexisting file. In this case:

a. If either lookup_positive or lookup_directory is set in lookup_flags, it terminates, returning the error code -enoent.

b. Otherwise, it terminates returning the value 0 (no error). nd->dentry points to the negative dentry object created by the lookup operation.

16. There is an inode associated with the last component of the pathname. If the lookup_directory flag is set in lookup_flags, checks that the inode has a custom lookup method—that is, it is a directory. If not, terminates returning the error code -enotdir.

17. Terminates returning the value 0 (no error). nd->dentry and nd->mnt refer to the last component of the pathname.