In the Linux kernel source scenario analysis-File system installation, in the article, sudo mount-t ext2/dev/sdb1/mnt/sdb has been called, and the file system is mounted on the/MNT/SDB node, then we then visit/mnt/sdb/ The HELLO.C node. Let's see what's the difference between Path_walk's execution?
int Path_walk (const char * name, struct nameidata *nd) {struct dentry *dentry;struct inode *inode;int err;unsigned int look Up_flags = Nd->flags;while (*name== '/') name++;if (!*name) goto Return_base;inode = Nd->dentry->d_inode;if ( Current->link_count) Lookup_flags = lookup_follow;/* at the "We know we have a real path component. */for (;;) {unsigned long hash;struct qstr this;unsigned int c;err = permission (inode, may_exec);d entry = Err_ptr (err); if (err) break ; this.name = name;c = * (const unsigned char *) Name;hash = Init_name_hash ();d o {name++;hash = Partial_name_hash (c, hash); c = * (const unsigned char *) name;} while (c && (c! = '/')); This.len = name-(const char *) This.name;this.hash = End_name_hash (hash);/* Remove Trail ing slashes? */if (!c) goto last_component;while (*++name = = '/'); if (!*name) goto last_with_slashes;/* * "." and ":" Is special-". Especially so because it have * to is able to know is about the current root directory and * parent relationships. */if (this.name[0] = = '. ') switch (this.len) {default:break;case 2:if (this.name[1]! = '. ') Break;follow_dotdot (nd); inode = nd->dentry->d_inode;/* fallthrough */case 1:continue;} /* * See if the low-level filesystem might want * to use its own hash. */if (nd->dentry->d_op && nd->dentry->d_op->d_hash) {err = Nd->dentry->d_op->d_hash ( Nd->dentry, &this); if (Err < 0) break;} /* This does the actual lookups. */dentry = Cached_lookup (Nd->dentry, &this, lookup_continue); if (!dentry) {dentry = Real_lookup (Nd->dentry, & Amp;this, lookup_continue); err = Ptr_err (dentry); if (Is_err (dentry)) break;} /* Check mountpoints. */while (D_mountpoint (dentry) && __follow_down (&nd->mnt, &dentry)); err =-enoent;inode = dentry- >d_inode;if (!inode) goto out_dput;err =-enotdir; if (!inode->i_op) goto out_dput;if (inode->i_op->follow_link) {err = Do_follow_link (dentry, ND);dp ut (dentry); if (err) goto Return_err;err =-enoent;inode= Nd->dentry->d_inode;if (!inode) break;err =-enotdir; if (!inode->i_op) break;} else {dput (nd->dentry); nd->dentry = Dentry;} err =-enotdir; if (!inode->i_op->lookup) break;continue;/* here ends the main loop */last_with_slashes:lookup_flags |= LOOKUP_ Follow | Lookup_directory;last_component:if (Lookup_flags & lookup_parent) goto lookup_parent;if (this.name[0] = = '. ') Switch (this.len) {default:break;case 2:if (this.name[1]! = '. ') Break;follow_dotdot (nd); inode = nd->dentry->d_inode;/* Fallthrough */case 1:goto return_base;} if (nd->dentry->d_op && nd->dentry->d_op->d_hash) {err = Nd->dentry->d_op->d_hash ( Nd->dentry, &this); if (Err < 0) break;} Dentry = Cached_lookup (nd->dentry, &this, 0); if (!dentry) {dentry = Real_lookup (nd->dentry, &this, 0); err = Ptr_err (Dentry); if (Is_err (dentry)) break;} while (D_mountpoint (dentry) && __follow_down (&nd->mnt, &dentry))//After finding the/MNT/SDB node, will be executed here, is also different ; inOde = Dentry->d_inode;if ((lookup_flags & Lookup_follow) && inode && inode->i_op && I Node->i_op->follow_link) {err = Do_follow_link (dentry, ND);dp ut (dentry); if (err) goto Return_err;inode = nd-> Dentry->d_inode;} else {dput (nd->dentry); nd->dentry = Dentry;} Err =-enoent;if (!inode) goto no_inode;if (Lookup_flags & lookup_directory) {err =-enotdir; if (!inode->i_op | |!i node->i_op->lookup) break;} Goto Return_base;no_inode:err =-enoent;if (Lookup_flags & (lookup_positive| lookup_directory)) Break;goto return_base;lookup_parent:nd->last = This;nd->last_type = LAST_NORM;if (this.name [0]! = '. ') Goto return_base;if (This.len = = 1) Nd->last_type = Last_dot;else if (This.len = = 2 && this.name[1] = = '. ') Nd->last_type = Last_dotdot;return_base:return 0;out_dput:dput (dentry); Path_release (ND); Return_err:return err;}
D_mountpoint to see if it is a mount point.
static __inline__ int d_mountpoint (struct dentry *dentry) {return!list_empty (&DENTRY->D_VFSMNT);}
Remember in the Linux kernel source code scenario analysis-File system installation, in the article, the last add_vfsmnt.
List_add (&mnt->mnt_clash, &nd->dentry->d_vfsmnt);
So here is not NULL, return True, then execute __follow_down, the code is as follows:
static inline int __follow_down (struct vfsmount **mnt, struct dentry **dentry) {struct List_head *p;spin_lock (&dcache _lock);p = (*dentry)->d_vfsmnt.next;while (P! = & (*dentry)->d_vfsmnt) {//reference file system installation Add_vfsmntstruct Vfsmount *tmp;tmp = List_entry (p, struct vfsmount, mnt_clash); if (tmp->mnt_parent = = *mnt) {//reference file system installation Add_vfsmnt*mn t = mntget (TMP);//nd->mnt is the vfsmount structure of the installed device Spin_unlock (&dcache_lock); Mntput (tmp->mnt_parent);/* TMP holds The Mountpoint, so ... */dput (*dentry); *dentry = Dget (tmp->mnt_root);//dentry the dentry structure of the root node of the installed device return 1;} p = p->next;} Spin_unlock (&dcache_lock); return 0;}
There is also a knowledge point, that is, the middle node is dot or dotdot processing.
if (this.name[0] = = '. ') switch (this.len) {default:break;case 2:if (this.name[1]! = '. ') Break;follow_dotdot (nd); inode = nd->dentry->d_inode;/* Fallthrough */case 1:continue;
If it is dot, then continue to the next cycle. If it is Dotdot, it will call Follow_dotdot, the code is as follows:
static inline void Follow_dotdot (struct nameidata *nd) {while (1) {struct Vfsmount *parent;struct dentry *dentry;read_lock (¤t->fs->lock); if (nd->dentry = = Current->fs->root && nd->mnt = = current->fs-& GT;ROOTMNT) {//The nd->dentry reached is the root node of this process and can no longer run up, so keep the Nd->dentry constant Read_unlock (¤t->fs->lock ); break;} Read_unlock (¤t->fs->lock); Spin_lock (&dcache_lock); if (nd->dentry! = Nd->mnt->mnt_ Root) {//reached nd->dentry dentry structure dentry = Dget (nd->dentry->d_parent); Spin_unlock (&dcache_lock); Dput (nd->dentry); nd->dentry = Dentry;//dentry structure goes up, the MNT structure is not changed;} parent=nd->mnt->mnt_parent;//Walk Here, it shows that Nd->dentry is already the dentry structure of the root node, can only run to another device, read the parent device's VFSMOUNT structure if (parent = = ND->MNT) {//If the VFSMOUNT structure of the parent device is the same as the vmfmount structure of this device, then no more spin_unlock (&dcache_lock) can be run on the parent device; Mntget (parent);//If the VFSMOUNT structure of the parent device is not the same as the vmfmount structure of the device dentry=dget (nd->mnt->mnt_mountpoint); Dentry is the dentry structure of the Mount node for the current device Spin_unlock (&AMp;dcache_lock);dp ut (nd->dentry), nd->dentry = Dentry;mntput (nd->mnt); nd->mnt = parent;//nd-> MNT is also assigned the VFSMOUNT structure of the Parent device}}
Linux kernel source scenario analysis-Access after file system installation