Linux内核源代码情景分析-从路径名到目标节点

来源:互联网 发布:淘宝等级查询网站 编辑:程序博客网 时间:2024/06/04 18:19
先看外包装,__user_walk,假设name为/usr/local/hello.c

[cpp] view plain copy
  1. int __user_walk(const char *name, unsigned flags, struct nameidata *nd)  
  2. {  
  3.     char *tmp;  
  4.     int err;  
  5.   
  6.     tmp = getname(name);//在系统空间分配一个页面,并从用户空间把文件名复制到这个页面  
  7.     err = PTR_ERR(tmp);  
  8.     if (!IS_ERR(tmp)) {  
  9.         err = 0;  
  10.         if (path_init(tmp, flags, nd))  
  11.             err = path_walk(tmp, nd);  
  12.         putname(tmp);  
  13.     }  
  14.     return err;  
  15. }  
    第一个参数name为路径名。

    第二个参数flags可以为以下的标志:

[cpp] view plain copy
  1. #define LOOKUP_FOLLOW       (1) //如果找到的目标只是"符号连接"到其它文件或者目录的一个目录项,则要顺着连接链一直找到终点  
  2. #define LOOKUP_DIRECTORY    (2) //表示要寻找的目标必须是个目录  
  3. #define LOOKUP_CONTINUE     (4)  
  4. #define LOOKUP_POSITIVE     (8)  
  5. #define LOOKUP_PARENT       (16) //找到父节点  
  6. #define LOOKUP_NOALT        (32)  
    第三个参数nd是个结构指针,数据结构nameidata的定义如下:

[cpp] view plain copy
  1. struct nameidata {  
  2.     struct dentry *dentry;  
  3.     struct vfsmount *mnt;  
  4.     struct qstr last;  
  5.     unsigned int flags;  
  6.     int last_type;  
  7. };  

    

    path_init,代码如下:

[cpp] view plain copy
  1. int path_init(const char *name, unsigned int flags, struct nameidata *nd)  
  2. {  
  3.     nd->last_type = LAST_ROOT; /* if there are only slashes... */  
  4.     nd->flags = flags;  
  5.     if (*name=='/')  
  6.         return walk_init_root(name,nd);//如果路径名是以"/"开头的绝对路径,那就要通过这个函数从根目录开始查找  
  7.     read_lock(&current->fs->lock);  
  8.     nd->mnt = mntget(current->fs->pwdmnt);//如果路径名不以"/"开头,那就当前目录开始  
  9.     nd->dentry = dget(current->fs->pwd);  
  10.     read_unlock(&current->fs->lock);  
  11.     return 1;  
  12. }  

[cpp] view plain copy
  1. static inline int  
  2. walk_init_root(const char *name, struct nameidata *nd)  
  3. {  
  4.     read_lock(&current->fs->lock);  
  5.     if (current->fs->altroot && !(nd->flags & LOOKUP_NOALT)) {  
  6.         nd->mnt = mntget(current->fs->altrootmnt);  
  7.         nd->dentry = dget(current->fs->altroot);  
  8.         read_unlock(&current->fs->lock);  
  9.         if (__emul_lookup_dentry(name,nd))  
  10.             return 0;  
  11.         read_lock(&current->fs->lock);  
  12.     }  
  13.     nd->mnt = mntget(current->fs->rootmnt);  
  14.     nd->dentry = dget(current->fs->root);  
  15.     read_unlock(&current->fs->lock);  
  16.     return 1;  
  17. }  


    返回到__user_walk,继续执行path_walk,代码如下:

[cpp] view plain copy
  1. int path_walk(const char * name, struct nameidata *nd)//name为/usr/local/hello.c  
  2. {  
  3.     struct dentry *dentry;  
  4.     struct inode *inode;  
  5.     int err;  
  6.     unsigned int lookup_flags = nd->flags;  
  7.   
  8.     while (*name=='/')//跳过/usr/local/hello.c最开始的'/'  
  9.         name++;  
  10.     if (!*name)//如果只有'/',那么直接退出  
  11.         goto return_base;  
  12.   
  13.     inode = nd->dentry->d_inode;//根节点的indode结构  
  14.     if (current->link_count)  
  15.         lookup_flags = LOOKUP_FOLLOW;//如果找到的目标只是"符号连接"到其它文件或者目录的一个目录项,则要顺着连接链一直找到终点  
  16.   
  17.     /* At this point we know we have a real path component. */  
  18.     for(;;) {//第一次循环  
  19.         unsigned long hash;  
  20.         struct qstr this;  
  21.         unsigned int c;  
  22.   
  23.         err = permission(inode, MAY_EXEC);  
  24.         dentry = ERR_PTR(err);  
  25.         if (err)  
  26.             break;  
  27.   
  28.         this.name = name;//已经指向了usr的首字符'u'  
  29.         c = *(const unsigned char *)name;  
  30.   
  31.         hash = init_name_hash();  
  32.         do {  
  33.             name++;  
  34.             hash = partial_name_hash(c, hash);  
  35.             c = *(const unsigned char *)name;  
  36.         } while (c && (c != '/'));//如果字符c为空或者遇到了'/'则退出循环,本例中c指向的usr后面的'/'  
  37.         this.len = name - (const char *) this.name;//usr的长度  
  38.         this.hash = end_name_hash(hash);  
  39.   
  40.         /* remove trailing slashes? */  
  41.         if (!c)//如果字符c为空,那么说明是最后一个节点,且最后一个节点是文件  
  42.             goto last_component;  
  43.         while (*++name == '/');//跳过'/'  
  44.         if (!*name)//如果'/'后面为空,那么说明这也是最后一个节点,且最后一个节点是目录  
  45.             goto last_with_slashes;  
  46.   
  47.         /* 
  48.          * "." and ".." are special - ".." especially so because it has 
  49.          * to be able to know about the current root directory and 
  50.          * parent relationships. 
  51.          */  
  52.         if (this.name[0] == '.'switch (this.len) {//执行到这里,this代表中间节点,中间节点一定是目录  
  53.             default:  
  54.                 break;  
  55.             case 2:   
  56.                 if (this.name[1] != '.')//如果当前节点是..,那么要表示上一级目录  
  57.                     break;  
  58.                 follow_dotdot(nd);  
  59.                 inode = nd->dentry->d_inode;  
  60.                 /* fallthrough */  
  61.             case 1://如果当前的节点是 . ,表示当前目录  
  62.                 continue;  
  63.         }  
  64.         /* 
  65.          * See if the low-level filesystem might want 
  66.          * to use its own hash.. 
  67.          */  
  68.         if (nd->dentry->d_op && nd->dentry->d_op->d_hash) {//如果有d_hash这个函数  
  69.             err = nd->dentry->d_op->d_hash(nd->dentry, &this);//使用这个函数,重新计算hash值  
  70.             if (err < 0)  
  71.                 break;  
  72.         }  
  73.         /* This does the actual lookups.. */  
  74.         dentry = cached_lookup(nd->dentry, &this, LOOKUP_CONTINUE);//在内存中寻找该节点业已建立的dentry结构  
  75.         if (!dentry) {//如果没有找到  
  76.             dentry = real_lookup(nd->dentry, &this, LOOKUP_CONTINUE);//那么就要建立该节点的dentry结构  
  77.             err = PTR_ERR(dentry);  
  78.             if (IS_ERR(dentry))  
  79.                 break;  
  80.         }  
  81.         /* Check mountpoints.. */  
  82.         while (d_mountpoint(dentry) && __follow_down(&nd->mnt, &dentry))//检查是否是挂载点  
  83.             ;  
  84.   
  85.         err = -ENOENT;  
  86.         inode = dentry->d_inode;  
  87.         if (!inode)  
  88.             goto out_dput;  
  89.         err = -ENOTDIR;   
  90.         if (!inode->i_op)  
  91.             goto out_dput;  
  92.   
  93.         if (inode->i_op->follow_link) {//看看这个指针是否为NULL,这个指针是在ext2_read_inode中设置的  
  94.             err = do_follow_link(dentry, nd);  
  95.             dput(dentry);  
  96.             if (err)  
  97.                 goto return_err;  
  98.             err = -ENOENT;  
  99.             inode = nd->dentry->d_inode;  
  100.             if (!inode)  
  101.                 break;  
  102.             err = -ENOTDIR;   
  103.             if (!inode->i_op)  
  104.                 break;  
  105.         } else {  
  106.             dput(nd->dentry);  
  107.             nd->dentry = dentry;//如果没有,直接附给nd->dentry  
  108.         }  
  109.         err = -ENOTDIR;   
  110.         if (!inode->i_op->lookup)//iop指针也是ext2_read_inode中设置的为ext2_dir_inode_operations,因为当前/usr为目录节点,所以一定要有ext2_lookup这个指针  
  111.             break;  
  112.         continue;  
  113.         /* here ends the main loop */  
  114.   
  115. last_with_slashes:  
  116.         ......  
  117. last_component:  
  118.         ......  
  119. }  
[cpp] view plain copy
  1. struct qstr {  
  2.     const unsigned char * name;  
  3.     unsigned int len;  
  4.     unsigned int hash;  
  5. };  
    

    cached_lookup,在内存中寻找该节点业已建立的dentry结构,代码如下:

[cpp] view plain copy
  1. static struct dentry * cached_lookup(struct dentry * parent, struct qstr * name, int flags)  
  2. {  
  3.     struct dentry * dentry = d_lookup(parent, name);  
  4.   
  5.     if (dentry && dentry->d_op && dentry->d_op->d_revalidate) {  
  6.         if (!dentry->d_op->d_revalidate(dentry, flags) && !d_invalidate(dentry)) {  
  7.             dput(dentry);  
  8.             dentry = NULL;  
  9.         }  
  10.     }  
  11.     return dentry;  
  12. }  
[cpp] view plain copy
  1. struct dentry * d_lookup(struct dentry * parent, struct qstr * name)  
  2. {  
  3.     unsigned int len = name->len;  
  4.     unsigned int hash = name->hash;  
  5.     const unsigned char *str = name->name;  
  6.     struct list_head *head = d_hash(parent,hash);  
  7.     struct list_head *tmp;  
  8.   
  9.     spin_lock(&dcache_lock);  
  10.     tmp = head->next;  
  11.     for (;;) {  
  12.         struct dentry * dentry = list_entry(tmp, struct dentry, d_hash);  
  13.         if (tmp == head)  
  14.             break;  
  15.         tmp = tmp->next;  
  16.         if (dentry->d_name.hash != hash)//比较hash值  
  17.             continue;  
  18.         if (dentry->d_parent != parent)//比较父节点的dentry结构是否一样  
  19.             continue;  
  20.         if (parent->d_op && parent->d_op->d_compare) {  
  21.             if (parent->d_op->d_compare(parent, &dentry->d_name, name))  
  22.                 continue;  
  23.         } else {  
  24.             if (dentry->d_name.len != len)//比较长度  
  25.                 continue;  
  26.             if (memcmp(dentry->d_name.name, str, len))//比较名字  
  27.                 continue;  
  28.         }  
  29.         __dget_locked(dentry);  
  30.         dentry->d_flags |= DCACHE_REFERENCED;  
  31.         spin_unlock(&dcache_lock);  
  32.         return dentry;//如果找到则返回节点的dentry结构  
  33.     }  
  34.     spin_unlock(&dcache_lock);  
  35.     return NULL;//如果没有找到,返回NULL  
  36. }  
    内核中有个杂凑表dentry_hashtable,是一个list_head指针数组,一旦在内存中建立起一个目录节点的dentry结构,就根据其节点名的杂凑值挂入杂凑表中的某个队列,需要寻找时则还是根据杂凑值从杂凑表查找。d_hash就是根据杂凑值找到杂凑表中的某一个队列头。

[cpp] view plain copy
  1. static inline struct list_head * d_hash(struct dentry * parent, unsigned long hash)  
  2. {  
  3.     hash += (unsigned long) parent / L1_CACHE_BYTES;  
  4.     hash = hash ^ (hash >> D_HASHBITS) ^ (hash >> D_HASHBITS*2);  
  5.     return dentry_hashtable + (hash & D_HASHMASK);  
  6. }  
    根据name在队列里中寻找,是否已经存在这个dentry结构。

 

    如果没有找到,那么要建立该节点的dentry结构,real_lookup代码如下:

[cpp] view plain copy
  1. static struct dentry * real_lookup(struct dentry * parent, struct qstr * name, int flags)  
  2. {  
  3.     struct dentry * result;  
  4.     struct inode *dir = parent->d_inode;  
  5.   
  6.     down(&dir->i_sem);  
  7.     /* 
  8.      * First re-do the cached lookup just in case it was created 
  9.      * while we waited for the directory semaphore.. 
  10.      * 
  11.      * FIXME! This could use version numbering or similar to 
  12.      * avoid unnecessary cache lookups. 
  13.      */  
  14.     result = d_lookup(parent, name);//再一次在内存中寻找该节点业已建立的dentry结构  
  15.     if (!result) {//如果还是没有找到  
  16.         struct dentry * dentry = d_alloc(parent, name);//分配该节点的dentry结构  
  17.         result = ERR_PTR(-ENOMEM);  
  18.         if (dentry) {  
  19.             lock_kernel();  
  20.             result = dir->i_op->lookup(dir, dentry);//分配该节点的inode结构,并挂在dentry结构上  
  21.             unlock_kernel();  
  22.             if (result)  
  23.                 dput(dentry);  
  24.             else  
  25.                 result = dentry;  
  26.         }  
  27.         up(&dir->i_sem);  
  28.         return result;  
  29.     }  
  30.   
  31.     /* 
  32.      * Uhhuh! Nasty case: the cache was re-populated while 
  33.      * we waited on the semaphore. Need to revalidate. 
  34.      */  
  35.     up(&dir->i_sem);  
  36.     if (result->d_op && result->d_op->d_revalidate) {  
  37.         if (!result->d_op->d_revalidate(result, flags) && !d_invalidate(result)) {  
  38.             dput(result);  
  39.             result = ERR_PTR(-ENOENT);  
  40.         }  
  41.     }  
  42.     return result;  
  43. }  
    d_alloc,分配该节点的dentry结构,代码如下:

[cpp] view plain copy
  1. struct dentry * d_alloc(struct dentry * parent, const struct qstr *name)  
  2. {  
  3.     char * str;  
  4.     struct dentry *dentry;  
  5.   
  6.     dentry = kmem_cache_alloc(dentry_cache, GFP_KERNEL); //分配了dentry结构  
  7.     if (!dentry)  
  8.         return NULL;  
  9.   
  10.     if (name->len > DNAME_INLINE_LEN-1) {  
  11.         str = kmalloc(NAME_ALLOC_LEN(name->len), GFP_KERNEL);  
  12.         if (!str) {  
  13.             kmem_cache_free(dentry_cache, dentry);   
  14.             return NULL;  
  15.         }  
  16.     } else  
  17.         str = dentry->d_iname;   
  18.   
  19.     memcpy(str, name->name, name->len);  
  20.     str[name->len] = 0;  
  21.   
  22.     atomic_set(&dentry->d_count, 1);  
  23.     dentry->d_flags = 0;  
  24.     dentry->d_inode = NULL;  
  25.     dentry->d_parent = NULL;  
  26.     dentry->d_sb = NULL;  
  27.     dentry->d_name.name = str;//名字  
  28.     dentry->d_name.len = name->len;//长度  
  29.     dentry->d_name.hash = name->hash;//hash值  
  30.     dentry->d_op = NULL;  
  31.     dentry->d_fsdata = NULL;  
  32.     INIT_LIST_HEAD(&dentry->d_vfsmnt);//见下面关于dentry的说明  
  33.     INIT_LIST_HEAD(&dentry->d_hash);  
  34.     INIT_LIST_HEAD(&dentry->d_lru);  
  35.     INIT_LIST_HEAD(&dentry->d_subdirs);  
  36.     INIT_LIST_HEAD(&dentry->d_alias);  
  37.     if (parent) {  
  38.         dentry->d_parent = dget(parent);  
  39.         dentry->d_sb = parent->d_sb;  
  40.         spin_lock(&dcache_lock);  
  41.         list_add(&dentry->d_child, &parent->d_subdirs);  
  42.         spin_unlock(&dcache_lock);  
  43.     } else  
  44.         INIT_LIST_HEAD(&dentry->d_child);  
  45.   
  46.     dentry_stat.nr_dentry++;  
  47.     return dentry;  
  48. }  
    其中dentry结构,如下:

[cpp] view plain copy
  1. struct dentry {  
  2.     atomic_t d_count;  
  3.     unsigned int d_flags;  
  4.     struct inode  * d_inode;    /* Where the name belongs to - NULL is negative */  
  5.     struct dentry * d_parent;   /* parent directory */  
  6.     struct list_head d_vfsmnt;  
  7.     struct list_head d_hash;    /* lookup hash list */  
  8.     struct list_head d_lru;     /* d_count = 0 LRU list */  
  9.     struct list_head d_child;   /* child of parent list */  
  10.     struct list_head d_subdirs; /* our children */  
  11.     struct list_head d_alias;   /* inode alias list */  
  12.     struct qstr d_name;  
  13.     unsigned long d_time;       /* used by d_revalidate */  
  14.     struct dentry_operations  *d_op;  
  15.     struct super_block * d_sb;  /* The root of the dentry tree */  
  16.     unsigned long d_reftime;    /* last time referenced */  
  17.     void * d_fsdata;        /* fs-specific data */  
  18.     unsigned char d_iname[DNAME_INLINE_LEN]; /* small names */  
  19. };  
    1、每个dentry结构都通过队列头d_hash链入杂凑表dentry_hashtable中的某个队列里。

    2、共享计数为0的dentry结构都通过队列头d_lru链入LRU队列dentry_unused。在队列中等待释放或者"东山再起"。

    3、每个dentry结构都通过指针d_inode指向一个inode数据结构。但是多个dentry结构可以指向同一个indoe数据结构。

    4、指向同一个inode数据结构的dentry结构都通过队列头d_alias链接在一起,都在该inode结构的i_dentry队列中。

    5、每个dentry结构都通过指针d_parent指向其父目录节点的dentry结构,并通过队列头d_child跟同一目录中的其它节点的dentry结构链接在一起,都在父目录节点的d_subdirs队列中。

    6、每个dentry结构都通过指针d_sb指向一个super_block数据结构。

    7、每个dentry结构都通过指针d_op指向一个dentry_operations数据结构。

    8、每个dentry结构都有个队列头d_vfsmnt,用于文件系统的安装。

    返回到real_lookup中,如果该节点的dentry结构分配成功,那么调用dir->i_op->lookup(dir, dentry)来分配该节点的inode结构,并挂在dentry结构上。其中dir是父目录节点的inode结构。

    对于ext2文件系统来说,lookup为ext2_lookup。代码如下:

[cpp] view plain copy
  1. static struct dentry *ext2_lookup(struct inode * dir, struct dentry *dentry)  
  2. {  
  3.     struct inode * inode;  
  4.     struct ext2_dir_entry_2 * de;  
  5.     struct buffer_head * bh;  
  6.   
  7.     if (dentry->d_name.len > EXT2_NAME_LEN)  
  8.         return ERR_PTR(-ENAMETOOLONG);  
  9.   
  10.     bh = ext2_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &de);//根据父节点的inode结构中inode->u.ext2_i.i_data找到对应的目录项  
  11.     inode = NULL;  
  12.     if (bh) {  
  13.         unsigned long ino = le32_to_cpu(de->inode);//得到该节点inode结构的节点号  
  14.         brelse (bh);  
  15.         inode = iget(dir->i_sb, ino);//通过这个节点号寻找该节点的inode结构  
  16.   
  17.         if (!inode)  
  18.             return ERR_PTR(-EACCES);  
  19.     }  
  20.     d_add(dentry, inode);//把该节点的inode结构和dentry连接在一起  
  21.     return NULL;  
  22. }  
    有关文件系统的细节,请看文件系统,用这篇文章的术语,ext2_find_entry根据父节点的inode结构中inode->u.ext2_i.i_data找到对应的目录项,这个目录项的结构是ext2_dir_entry_2结构,读者在前面已经看过dentry结构,它们的区别是ext2_dir_entry_2结构对应硬盘上的页目录项结构,而dentry是动态建立的。

[cpp] view plain copy
  1. struct ext2_dir_entry_2 {  
  2.     __u32   inode;          /* Inode number */  
  3.     __u16   rec_len;        /* Directory entry length */  
  4.     __u8    name_len;       /* Name length */  
  5.     __u8    file_type;  
  6.     char    name[EXT2_NAME_LEN];    /* File name */  
  7. };  
    ext2_find_entry找到的数据块通常有许多目录项,根据dentry->d_name.name, dentry->d_name.len找到对应的目录项结构ext2_dir_entry_2。


    然后根据de->inode,得到该节点inode结构的节点号,通过这个节点号寻找该节点的inode结构,iget如下:

[cpp] view plain copy
  1. static inline struct inode *iget(struct super_block *sb, unsigned long ino)  
  2. {  
  3.     return iget4(sb, ino, NULL, NULL);  
  4. }  
[cpp] view plain copy
  1. struct inode *iget4(struct super_block *sb, unsigned long ino, find_inode_t find_actor, void *opaque)  
  2. {  
  3.     struct list_head * head = inode_hashtable + hash(sb,ino);  
  4.     struct inode * inode;  
  5.   
  6.     spin_lock(&inode_lock);  
  7.     inode = find_inode(sb, ino, head, find_actor, opaque);//在杂凑表队列中寻找  
  8.     if (inode) {//找到了  
  9.         __iget(inode);//递增计数  
  10.         spin_unlock(&inode_lock);  
  11.         wait_on_inode(inode);  
  12.         return inode;  
  13.     }  
  14.     spin_unlock(&inode_lock);  
  15.   
  16.     /* 
  17.      * get_new_inode() will do the right thing, re-trying the search 
  18.      * in case it had to block at any point. 
  19.      */  
  20.     return get_new_inode(sb, ino, head, find_actor, opaque);//分配一个新的该节点的inode结构  
  21. }  
    inode结构也有个杂凑表inode_hashtable,已经建立的inode结构都通过结构中的i_hash(也是一个list_head)挂在该杂凑表的某一队列中,所以首先要通过find_inode()在杂凑表队列中寻找。
[cpp] view plain copy
  1. static struct inode * find_inode(struct super_block * sb, unsigned long ino, struct list_head *head, find_inode_t find_actor, void *opaque)  
  2. {  
  3.     struct list_head *tmp;  
  4.     struct inode * inode;  
  5.   
  6.     tmp = head;  
  7.     for (;;) {  
  8.         tmp = tmp->next;  
  9.         inode = NULL;  
  10.         if (tmp == head)  
  11.             break;  
  12.         inode = list_entry(tmp, struct inode, i_hash);  
  13.         if (inode->i_ino != ino)//对比节点号  
  14.             continue;  
  15.         if (inode->i_sb != sb)//和超级块结构  
  16.             continue;  
  17.         if (find_actor && !find_actor(inode, ino, opaque))  
  18.             continue;  
  19.         break;  
  20.     }  
  21.     return inode;  
  22. }  
    如果没有找到,get_new_inode分配一个新的该节点的inode结构,代码如下:
[cpp] view plain copy
  1. static struct inode * get_new_inode(struct super_block *sb, unsigned long ino, struct list_head *head, find_inode_t find_actor, void *opaque)  
  2. {  
  3.     struct inode * inode;  
  4.   
  5.     inode = alloc_inode();  
  6.     if (inode) {  
  7.         struct inode * old;  
  8.   
  9.         spin_lock(&inode_lock);  
  10.         /* We released the lock, so.. */  
  11.         old = find_inode(sb, ino, head, find_actor, opaque);//再一次在杂凑表队列中寻找  
  12.         if (!old) {//如果没有找到  
  13.             inodes_stat.nr_inodes++;  
  14.             list_add(&inode->i_list, &inode_in_use);  
  15.             list_add(&inode->i_hash, head);//加入到对应的hash表  
  16.             inode->i_sb = sb;//超级块结构  
  17.             inode->i_dev = sb->s_dev;//设备号  
  18.             inode->i_ino = ino;//节点号  
  19.             inode->i_flags = 0;  
  20.             atomic_set(&inode->i_count, 1);  
  21.             inode->i_state = I_LOCK;  
  22.             spin_unlock(&inode_lock);  
  23.   
  24.             clean_inode(inode);  
  25.             sb->s_op->read_inode(inode);  
  26.   
  27.             /* 
  28.              * This is special!  We do not need the spinlock 
  29.              * when clearing I_LOCK, because we're guaranteed 
  30.              * that nobody else tries to do anything about the 
  31.              * state of the inode when it is locked, as we 
  32.              * just created it (so there can be no old holders 
  33.              * that haven't tested I_LOCK). 
  34.              */  
  35.             inode->i_state &= ~I_LOCK;  
  36.             wake_up(&inode->i_wait);  
  37.   
  38.             return inode;  
  39.         }  
  40.   
  41.         /* 
  42.          * Uhhuh, somebody else created the same inode under 
  43.          * us. Use the old inode instead of the one we just 
  44.          * allocated. 
  45.          */  
  46.         __iget(old);//如果找到了inode结构  
  47.         spin_unlock(&inode_lock);  
  48.         destroy_inode(inode);  
  49.         inode = old;//使用找到的inode结构  
  50.         wait_on_inode(inode);  
  51.     }  
  52.     return inode;  
  53. }  
    alloc_inode,分配一个新的inode结构,代码如下:

[cpp] view plain copy
  1. #define alloc_inode() \  
  2.      ((struct inode *) kmem_cache_alloc(inode_cachep, SLAB_KERNEL))  
    sb->s_op->read_inode,把硬盘上的inode结构读入,并合理的赋值给内存中这个动态的inode。下面我们分别介绍下动态的inode结构和硬盘上的ext2_inode结构。

    动态的inode结构:

[cpp] view plain copy
  1. struct inode {  
  2.     struct list_head    i_hash;  
  3.     struct list_head    i_list;  
  4.     struct list_head    i_dentry;  
  5.       
  6.     struct list_head    i_dirty_buffers;  
  7.   
  8.     unsigned long       i_ino;  
  9.     atomic_t        i_count;  
  10.     kdev_t          i_dev;  
  11.     umode_t         i_mode;  
  12.     nlink_t         i_nlink;  
  13.     uid_t           i_uid;  
  14.     gid_t           i_gid;  
  15.     kdev_t          i_rdev;  
  16.     loff_t          i_size;  
  17.     time_t          i_atime;  
  18.     time_t          i_mtime;  
  19.     time_t          i_ctime;  
  20.     unsigned long       i_blksize;  
  21.     unsigned long       i_blocks;  
  22.     unsigned long       i_version;  
  23.     struct semaphore    i_sem;  
  24.     struct semaphore    i_zombie;  
  25.     struct inode_operations *i_op;  
  26.     struct file_operations  *i_fop; /* former ->i_op->default_file_ops */  
  27.     struct super_block  *i_sb;  
  28.     wait_queue_head_t   i_wait;  
  29.     struct file_lock    *i_flock;  
  30.     struct address_space    *i_mapping;  
  31.     struct address_space    i_data;   
  32.     struct dquot        *i_dquot[MAXQUOTAS];  
  33.     struct pipe_inode_info  *i_pipe;  
  34.     struct block_device *i_bdev;  
  35.   
  36.     unsigned long       i_dnotify_mask; /* Directory notify events */  
  37.     struct dnotify_struct   *i_dnotify; /* for directory notifications */  
  38.   
  39.     unsigned long       i_state;  
  40.   
  41.     unsigned int        i_flags;  
  42.     unsigned char       i_sock;  
  43.   
  44.     atomic_t        i_writecount;  
  45.     unsigned int        i_attr_flags;  
  46.     __u32           i_generation;  
  47.     union {  
  48.         struct minix_inode_info     minix_i;  
  49.         struct ext2_inode_info      ext2_i;  
  50.         struct hpfs_inode_info      hpfs_i;  
  51.         struct ntfs_inode_info      ntfs_i;  
  52.         struct msdos_inode_info     msdos_i;  
  53.         struct umsdos_inode_info    umsdos_i;  
  54.         struct iso_inode_info       isofs_i;  
  55.         struct nfs_inode_info       nfs_i;  
  56.         struct sysv_inode_info      sysv_i;  
  57.         struct affs_inode_info      affs_i;  
  58.         struct ufs_inode_info       ufs_i;  
  59.         struct efs_inode_info       efs_i;  
  60.         struct romfs_inode_info     romfs_i;  
  61.         struct shmem_inode_info     shmem_i;  
  62.         struct coda_inode_info      coda_i;  
  63.         struct smb_inode_info       smbfs_i;  
  64.         struct hfs_inode_info       hfs_i;  
  65.         struct adfs_inode_info      adfs_i;  
  66.         struct qnx4_inode_info      qnx4_i;  
  67.         struct bfs_inode_info       bfs_i;  
  68.         struct udf_inode_info       udf_i;  
  69.         struct ncp_inode_info       ncpfs_i;  
  70.         struct proc_inode_info      proc_i;  
  71.         struct socket           socket_i;  
  72.         struct usbdev_inode_info        usbdev_i;  
  73.         void                *generic_ip;  
  74.     } u;  
  75. }  


    硬盘上的ext2_inode结构

[cpp] view plain copy
  1. struct ext2_inode {  
  2.     __u16   i_mode;     /* File mode */  
  3.     __u16   i_uid;      /* Low 16 bits of Owner Uid */  
  4.     __u32   i_size;     /* Size in bytes */  
  5.     __u32   i_atime;    /* Access time */  
  6.     __u32   i_ctime;    /* Creation time */  
  7.     __u32   i_mtime;    /* Modification time */  
  8.     __u32   i_dtime;    /* Deletion Time */  
  9.     __u16   i_gid;      /* Low 16 bits of Group Id */  
  10.     __u16   i_links_count;  /* Links count */  
  11.     __u32   i_blocks;   /* Blocks count */  
  12.     __u32   i_flags;    /* File flags */  
  13.     union {  
  14.         struct {  
  15.             __u32  l_i_reserved1;  
  16.         } linux1;  
  17.         struct {  
  18.             __u32  h_i_translator;  
  19.         } hurd1;  
  20.         struct {  
  21.             __u32  m_i_reserved1;  
  22.         } masix1;  
  23.     } osd1;             /* OS dependent 1 */  
  24.     __u32   i_block[EXT2_N_BLOCKS];/* Pointers to blocks */  
  25.     __u32   i_generation;   /* File version (for NFS) */  
  26.     __u32   i_file_acl; /* File ACL */  
  27.     __u32   i_dir_acl;  /* Directory ACL */  
  28.     __u32   i_faddr;    /* Fragment address */  
  29.     union {  
  30.         struct {  
  31.             __u8    l_i_frag;   /* Fragment number */  
  32.             __u8    l_i_fsize;  /* Fragment size */  
  33.             __u16   i_pad1;  
  34.             __u16   l_i_uid_high;   /* these 2 fields    */  
  35.             __u16   l_i_gid_high;   /* were reserved2[0] */  
  36.             __u32   l_i_reserved2;  
  37.         } linux2;  
  38.         struct {  
  39.             __u8    h_i_frag;   /* Fragment number */  
  40.             __u8    h_i_fsize;  /* Fragment size */  
  41.             __u16   h_i_mode_high;  
  42.             __u16   h_i_uid_high;  
  43.             __u16   h_i_gid_high;  
  44.             __u32   h_i_author;  
  45.         } hurd2;  
  46.         struct {  
  47.             __u8    m_i_frag;   /* Fragment number */  
  48.             __u8    m_i_fsize;  /* Fragment size */  
  49.             __u16   m_pad1;  
  50.             __u32   m_i_reserved2[2];  
  51.         } masix2;  
  52.     } osd2;             /* OS dependent 2 */  
  53. }  
     sb->s_op->read_inode,把硬盘上的inode结构读入,并合理的赋值给内存中这个动态的inode。
[cpp] view plain copy
  1. void ext2_read_inode (struct inode * inode)  
  2. {  
  3.     struct buffer_head * bh;  
  4.     struct ext2_inode * raw_inode;  
  5.     unsigned long block_group;  
  6.     unsigned long group_desc;  
  7.     unsigned long desc;  
  8.     unsigned long block;  
  9.     unsigned long offset;  
  10.     struct ext2_group_desc * gdp;  
  11.   
  12.     if ((inode->i_ino != EXT2_ROOT_INO && inode->i_ino != EXT2_ACL_IDX_INO &&  
  13.          inode->i_ino != EXT2_ACL_DATA_INO &&  
  14.          inode->i_ino < EXT2_FIRST_INO(inode->i_sb)) ||  
  15.         inode->i_ino > le32_to_cpu(inode->i_sb->u.ext2_sb.s_es->s_inodes_count)) {  
  16.         ext2_error (inode->i_sb, "ext2_read_inode",  
  17.                 "bad inode number: %lu", inode->i_ino);  
  18.         goto bad_inode;  
  19.     }  
  20.     block_group = (inode->i_ino - 1) / EXT2_INODES_PER_GROUP(inode->i_sb);  
  21.     if (block_group >= inode->i_sb->u.ext2_sb.s_groups_count) {  
  22.         ext2_error (inode->i_sb, "ext2_read_inode",  
  23.                 "group >= groups count");  
  24.         goto bad_inode;  
  25.     }  
  26.     group_desc = block_group >> EXT2_DESC_PER_BLOCK_BITS(inode->i_sb);  
  27.     desc = block_group & (EXT2_DESC_PER_BLOCK(inode->i_sb) - 1);  
  28.     bh = inode->i_sb->u.ext2_sb.s_group_desc[group_desc];  
  29.     if (!bh) {  
  30.         ext2_error (inode->i_sb, "ext2_read_inode",  
  31.                 "Descriptor not loaded");  
  32.         goto bad_inode;  
  33.     }  
  34.   
  35.     gdp = (struct ext2_group_desc *) bh->b_data;  
  36.     /* 
  37.      * Figure out the offset within the block group inode table 
  38.      */  
  39.     offset = ((inode->i_ino - 1) % EXT2_INODES_PER_GROUP(inode->i_sb)) *  
  40.         EXT2_INODE_SIZE(inode->i_sb);  
  41.     block = le32_to_cpu(gdp[desc].bg_inode_table) +  
  42.         (offset >> EXT2_BLOCK_SIZE_BITS(inode->i_sb));  
  43.     if (!(bh = bread (inode->i_dev, block, inode->i_sb->s_blocksize))) {  
  44.         ext2_error (inode->i_sb, "ext2_read_inode",  
  45.                 "unable to read inode block - "  
  46.                 "inode=%lu, block=%lu", inode->i_ino, block);  
  47.         goto bad_inode;  
  48.     }  
  49.     offset &= (EXT2_BLOCK_SIZE(inode->i_sb) - 1);  
  50.     raw_inode = (struct ext2_inode *) (bh->b_data + offset);//根据节点号,找到硬盘上的ext2_inode结构  
  51.   
  52.     inode->i_mode = le16_to_cpu(raw_inode->i_mode);//mode也来来源于ext2_inode结构  
  53.     inode->i_uid = (uid_t)le16_to_cpu(raw_inode->i_uid_low);  
  54.     inode->i_gid = (gid_t)le16_to_cpu(raw_inode->i_gid_low);  
  55.     if(!(test_opt (inode->i_sb, NO_UID32))) {  
  56.         inode->i_uid |= le16_to_cpu(raw_inode->i_uid_high) << 16;  
  57.         inode->i_gid |= le16_to_cpu(raw_inode->i_gid_high) << 16;  
  58.     }  
  59.     inode->i_nlink = le16_to_cpu(raw_inode->i_links_count);  
  60.     inode->i_size = le32_to_cpu(raw_inode->i_size);  
  61.     inode->i_atime = le32_to_cpu(raw_inode->i_atime);  
  62.     inode->i_ctime = le32_to_cpu(raw_inode->i_ctime);  
  63.     inode->i_mtime = le32_to_cpu(raw_inode->i_mtime);  
  64.     inode->u.ext2_i.i_dtime = le32_to_cpu(raw_inode->i_dtime);  
  65.     /* We now have enough fields to check if the inode was active or not. 
  66.      * This is needed because nfsd might try to access dead inodes 
  67.      * the test is that same one that e2fsck uses 
  68.      * NeilBrown 1999oct15 
  69.      */  
  70.     if (inode->i_nlink == 0 && (inode->i_mode == 0 || inode->u.ext2_i.i_dtime)) {  
  71.         /* this inode is deleted */  
  72.         brelse (bh);  
  73.         goto bad_inode;  
  74.     }  
  75.     inode->i_blksize = PAGE_SIZE;    /* This is the optimal IO size (for stat), not the fs block size */  
  76.     inode->i_blocks = le32_to_cpu(raw_inode->i_blocks);  
  77.     inode->i_version = ++event;  
  78.     inode->u.ext2_i.i_flags = le32_to_cpu(raw_inode->i_flags);//联合体的ext2_i被复制  
  79.     inode->u.ext2_i.i_faddr = le32_to_cpu(raw_inode->i_faddr);  
  80.     inode->u.ext2_i.i_frag_no = raw_inode->i_frag;  
  81.     inode->u.ext2_i.i_frag_size = raw_inode->i_fsize;  
  82.     inode->u.ext2_i.i_file_acl = le32_to_cpu(raw_inode->i_file_acl);  
  83.     if (S_ISDIR(inode->i_mode))  
  84.         inode->u.ext2_i.i_dir_acl = le32_to_cpu(raw_inode->i_dir_acl);  
  85.     else {  
  86.         inode->u.ext2_i.i_high_size = le32_to_cpu(raw_inode->i_size_high);  
  87.         inode->i_size |= ((__u64)le32_to_cpu(raw_inode->i_size_high)) << 32;  
  88.     }  
  89.     inode->i_generation = le32_to_cpu(raw_inode->i_generation);  
  90.     inode->u.ext2_i.i_block_group = block_group;  
  91.   
  92.     /* 
  93.      * NOTE! The in-memory inode i_data array is in little-endian order 
  94.      * even on big-endian machines: we do NOT byteswap the block numbers! 
  95.      */  
  96.     for (block = 0; block < EXT2_N_BLOCKS; block++)  
  97.         inode->u.ext2_i.i_data[block] = raw_inode->i_block[block];  
  98.   
  99.     if (inode->i_ino == EXT2_ACL_IDX_INO ||  
  100.         inode->i_ino == EXT2_ACL_DATA_INO)  
  101.         /* Nothing to do */ ;  
  102.     else if (S_ISREG(inode->i_mode)) {//根据不同的该节点的inode结构不同状态,设置不同的指针  
  103.         inode->i_op = &ext2_file_inode_operations;  
  104.         inode->i_fop = &ext2_file_operations;  
  105.         inode->i_mapping->a_ops = &ext2_aops;  
  106.     } else if (S_ISDIR(inode->i_mode)) {//目前是目录  
  107.         inode->i_op = &ext2_dir_inode_operations;  
  108.         inode->i_fop = &ext2_dir_operations;  
  109.     } else if (S_ISLNK(inode->i_mode)) {  
  110.         if (!inode->i_blocks)  
  111.             inode->i_op = &ext2_fast_symlink_inode_operations;  
  112.         else {  
  113.             inode->i_op = &page_symlink_inode_operations;  
  114.             inode->i_mapping->a_ops = &ext2_aops;  
  115.         }  
  116.     } else   
  117.         init_special_inode(inode, inode->i_mode,  
  118.                    le32_to_cpu(raw_inode->i_block[0]));  
  119.     brelse (bh);  
  120.     inode->i_attr_flags = 0;  
  121.     if (inode->u.ext2_i.i_flags & EXT2_SYNC_FL) {  
  122.         inode->i_attr_flags |= ATTR_FLAG_SYNCRONOUS;  
  123.         inode->i_flags |= S_SYNC;  
  124.     }  
  125.     if (inode->u.ext2_i.i_flags & EXT2_APPEND_FL) {  
  126.         inode->i_attr_flags |= ATTR_FLAG_APPEND;  
  127.         inode->i_flags |= S_APPEND;  
  128.     }  
  129.     if (inode->u.ext2_i.i_flags & EXT2_IMMUTABLE_FL) {  
  130.         inode->i_attr_flags |= ATTR_FLAG_IMMUTABLE;  
  131.         inode->i_flags |= S_IMMUTABLE;  
  132.     }  
  133.     if (inode->u.ext2_i.i_flags & EXT2_NOATIME_FL) {  
  134.         inode->i_attr_flags |= ATTR_FLAG_NOATIME;  
  135.         inode->i_flags |= S_NOATIME;  
  136.     }  
  137.     return;  
  138.       
  139. bad_inode:  
  140.     make_bad_inode(inode);  
  141.     return;  
  142. }  
    其中ext2_dir_inode_operations如下:

[cpp] view plain copy
  1. struct inode_operations ext2_dir_inode_operations = {  
  2.     create:     ext2_create,  
  3.     lookup:     ext2_lookup,  
  4.     link:       ext2_link,  
  5.     unlink:     ext2_unlink,  
  6.     symlink:    ext2_symlink,  
  7.     mkdir:      ext2_mkdir,  
  8.     rmdir:      ext2_rmdir,  
  9.     mknod:      ext2_mknod,  
  10.     rename:     ext2_rename,  
  11. };  

    iget获取到该节点的inode结构后,就返回ext2_lookup,继续执行d_add(dentry, inode),把该节点的inode结构和dentry连接在一起。

[cpp] view plain copy
  1. static __inline__ void d_add(struct dentry * entry, struct inode * inode)  
  2. {  
  3.     d_instantiate(entry, inode);//该节点的inode结构和dentry连接在一起  
  4.     d_rehash(entry);//把dentry结构放入杂凑表的某一个队里中  
  5. }  
[cpp] view plain copy
  1. void d_instantiate(struct dentry *entry, struct inode * inode)  
  2. {  
  3.     spin_lock(&dcache_lock);  
  4.     if (inode)  
  5.         list_add(&entry->d_alias, &inode->i_dentry);//可能一个inode结构对应多个entry结构  
  6.     entry->d_inode = inode;//链接在一起了  
  7.     spin_unlock(&dcache_lock);  
  8. }  
[cpp] view plain copy
  1. void d_rehash(struct dentry * entry)  
  2. {  
  3.     struct list_head *list = d_hash(entry->d_parent, entry->d_name.hash);  
  4.     spin_lock(&dcache_lock);  
  5.     list_add(&entry->d_hash, list);  
  6.     spin_unlock(&dcache_lock);  
  7. }  
    而inode结构放入杂凑表的某个队列是在get_new_inode里面:
[cpp] view plain copy
  1. list_add(&inode->i_hash, head);  
    

    real_lookup返回该节点的dentry结构。然后检查是否是挂在点,如果不是nd->dentry被赋值为dentry。由于是目录节点,所有lookup指针不能为NULL。

    第一轮循环,执行到这里,continue开始第二轮循环。

[cpp] view plain copy
  1. if (!inode->i_op->lookup)  
  2.     break;  
  3. continue;  
    

    第二轮循环,如下:

[cpp] view plain copy
  1. int path_walk(const char * name, struct nameidata *nd)  
  2. {  
  3.     struct dentry *dentry;  
  4.     struct inode *inode;  
  5.     int err;  
  6.     unsigned int lookup_flags = nd->flags;  
  7.   
  8.     while (*name=='/')  
  9.         name++;  
  10.     if (!*name)  
  11.         goto return_base;  
  12.   
  13.     inode = nd->dentry->d_inode;  
  14.     if (current->link_count)  
  15.         lookup_flags = LOOKUP_FOLLOW;  
  16.   
  17.     /* At this point we know we have a real path component. */  
  18.     for(;;) {  
  19.         unsigned long hash;  
  20.         struct qstr this;  
  21.         unsigned int c;  
  22.   
  23.         err = permission(inode, MAY_EXEC);  
  24.         dentry = ERR_PTR(err);  
  25.         if (err)  
  26.             break;  
  27.   
  28.         this.name = name;//指向local的第一个字符'l'  
  29.         c = *(const unsigned char *)name;  
  30.   
  31.         hash = init_name_hash();  
  32.         do {  
  33.             name++;  
  34.             hash = partial_name_hash(c, hash);  
  35.             c = *(const unsigned char *)name;  
  36.         } while (c && (c != '/'));  
  37.         this.len = name - (const char *) this.name;//local的长度  
  38.         this.hash = end_name_hash(hash);//hash值  
  39.   
  40.         /* remove trailing slashes? */  
  41.         if (!c)  
  42.             goto last_component;  
  43.         while (*++name == '/');  
  44.         if (!*name)  
  45.             goto last_with_slashes;  
  46.   
  47.         /* 
  48.          * "." and ".." are special - ".." especially so because it has 
  49.          * to be able to know about the current root directory and 
  50.          * parent relationships. 
  51.          */  
  52.         if (this.name[0] == '.'switch (this.len) {  
  53.             default:  
  54.                 break;  
  55.             case 2:   
  56.                 if (this.name[1] != '.')  
  57.                     break;  
  58.                 follow_dotdot(nd);  
  59.                 inode = nd->dentry->d_inode;  
  60.                 /* fallthrough */  
  61.             case 1:  
  62.                 continue;  
  63.         }  
  64.         /* 
  65.          * See if the low-level filesystem might want 
  66.          * to use its own hash.. 
  67.          */  
  68.         if (nd->dentry->d_op && nd->dentry->d_op->d_hash) {  
  69.             err = nd->dentry->d_op->d_hash(nd->dentry, &this);  
  70.             if (err < 0)  
  71.                 break;  
  72.         }  
  73.         /* This does the actual lookups.. */  
  74.         dentry = cached_lookup(nd->dentry, &this, LOOKUP_CONTINUE);  
  75.         if (!dentry) {  
  76.             dentry = real_lookup(nd->dentry, &this, LOOKUP_CONTINUE);  
  77.             err = PTR_ERR(dentry);  
  78.             if (IS_ERR(dentry))  
  79.                 break;  
  80.         }  
  81.         /* Check mountpoints.. */  
  82.         while (d_mountpoint(dentry) && __follow_down(&nd->mnt, &dentry))  
  83.             ;  
  84.   
  85.         err = -ENOENT;  
  86.         inode = dentry->d_inode;  
  87.         if (!inode)  
  88.             goto out_dput;  
  89.         err = -ENOTDIR;   
  90.         if (!inode->i_op)  
  91.             goto out_dput;  
  92.   
  93.         if (inode->i_op->follow_link) {  
  94.             err = do_follow_link(dentry, nd);  
  95.             dput(dentry);  
  96.             if (err)  
  97.                 goto return_err;  
  98.             err = -ENOENT;  
  99.             inode = nd->dentry->d_inode;  
  100.             if (!inode)  
  101.                 break;  
  102.             err = -ENOTDIR;   
  103.             if (!inode->i_op)  
  104.                 break;  
  105.         } else {  
  106.             dput(nd->dentry);  
  107.             nd->dentry = dentry;  
  108.         }  
  109.         err = -ENOTDIR;   
  110.         if (!inode->i_op->lookup)  
  111.             break;  
  112.         continue;  
  113.         /* here ends the main loop */  
  114.   
  115. last_with_slashes:  
  116.         ......  
  117. last_component:  
  118.         ......  
  119. }  
    除上面注释外,其他的流程和和第一次循环都一样。

    第二轮循环,也是执行到这里,continue开始第三轮循环:

[cpp] view plain copy
  1. if (!inode->i_op->lookup)//由于/usr/local/hello.c,local仍然是目录节点  
  2.     break;  
  3. continue;  


    第三轮循环,如下:

[cpp] view plain copy
  1. int path_walk(const char * name, struct nameidata *nd)  
  2. {  
  3.     struct dentry *dentry;  
  4.     struct inode *inode;  
  5.     int err;  
  6.     unsigned int lookup_flags = nd->flags;  
  7.   
  8.     while (*name=='/')  
  9.         name++;  
  10.     if (!*name)  
  11.         goto return_base;  
  12.   
  13.     inode = nd->dentry->d_inode;  
  14.     if (current->link_count)  
  15.         lookup_flags = LOOKUP_FOLLOW;  
  16.   
  17.     /* At this point we know we have a real path component. */  
  18.     for(;;) {  
  19.         unsigned long hash;  
  20.         struct qstr this;  
  21.         unsigned int c;  
  22.   
  23.         err = permission(inode, MAY_EXEC);  
  24.         dentry = ERR_PTR(err);  
  25.         if (err)  
  26.             break;  
  27.   
  28.         this.name = name;//指向了hello.c的第一个字符'h'  
  29.         c = *(const unsigned char *)name;  
  30.   
  31.         hash = init_name_hash();  
  32.         do {  
  33.             name++;  
  34.             hash = partial_name_hash(c, hash);  
  35.             c = *(const unsigned char *)name;  
  36.         } while (c && (c != '/'));  
  37.         this.len = name - (const char *) this.name;//hello.c的长度  
  38.         this.hash = end_name_hash(hash);  
  39.   
  40.         /* remove trailing slashes? */  
  41.         if (!c)//c为NULL了  
  42.             goto last_component;  
  43.         while (*++name == '/');  
  44.         if (!*name)  
  45.             goto last_with_slashes;  
  46.   
  47.         .....  
  48.   
  49. last_with_slashes:  
  50.         lookup_flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY;//如果最后一个节点是目录,那么要加上这两个标志位  
  51. last_component:  
  52.         if (lookup_flags & LOOKUP_PARENT)//这个标志位表示是要寻找父节点  
  53.             goto lookup_parent;  
  54.         if (this.name[0] == '.'switch (this.len) {//如果最后一个节点是目录,且是dot或者dotdot  
  55.             default:  
  56.                 break;  
  57.             case 2:   
  58.                 if (this.name[1] != '.')  
  59.                     break;  
  60.                 follow_dotdot(nd);  
  61.                 inode = nd->dentry->d_inode;  
  62.                 /* fallthrough */  
  63.             case 1:  
  64.                 goto return_base;  
  65.         }  
  66.         if (nd->dentry->d_op && nd->dentry->d_op->d_hash) {  
  67.             err = nd->dentry->d_op->d_hash(nd->dentry, &this);  
  68.             if (err < 0)  
  69.                 break;  
  70.         }  
  71.         dentry = cached_lookup(nd->dentry, &this, 0);  
  72.         if (!dentry) {  
  73.             dentry = real_lookup(nd->dentry, &this, 0);//本次寻找的节点是文件  
  74.             err = PTR_ERR(dentry);  
  75.             if (IS_ERR(dentry))  
  76.                 break;  
  77.         }  
  78.         while (d_mountpoint(dentry) && __follow_down(&nd->mnt, &dentry))//是否是挂载点  
  79.             ;  
  80.         inode = dentry->d_inode;  
  81.         if ((lookup_flags & LOOKUP_FOLLOW)//和第一次和第二次循环不同,必须LOOKUP_FOLLOW标志位置1  
  82.             && inode && inode->i_op && inode->i_op->follow_link) {  
  83.             err = do_follow_link(dentry, nd);  
  84.             dput(dentry);  
  85.             if (err)  
  86.                 goto return_err;  
  87.             inode = nd->dentry->d_inode;  
  88.         } else {  
  89.             dput(nd->dentry);  
  90.             nd->dentry = dentry;//赋值给nd->dentry  
  91.         }  
  92.         err = -ENOENT;  
  93.         if (!inode)  
  94.             goto no_inode;  
  95.         if (lookup_flags & LOOKUP_DIRECTORY) {//如果最后一个节点是目录,也就是这个标志为置1的时候,还要检查指针是否为NULL  
  96.             err = -ENOTDIR;   
  97.             if (!inode->i_op || !inode->i_op->lookup)  
  98.                 break;  
  99.         }  
  100.         goto return_base;  
  101. no_inode:  
  102.         err = -ENOENT;  
  103.         if (lookup_flags & (LOOKUP_POSITIVE|LOOKUP_DIRECTORY))  
  104.             break;  
  105.         goto return_base;  
  106. lookup_parent: ////nd->dentry是父节点的dentry结构  
  107.         nd->last = this;//nd->last是最后一个节点的名字  
  108.         nd->last_type = LAST_NORM;//最后一个节点的类型  
  109.         if (this.name[0] != '.')  
  110.             goto return_base;  
  111.         if (this.len == 1)  
  112.             nd->last_type = LAST_DOT;  
  113.         else if (this.len == 2 && this.name[1] == '.')  
  114.             nd->last_type = LAST_DOTDOT;  
  115. return_base:  
  116.         return 0;  
  117. out_dput:  
  118.         dput(dentry);  
  119.         break;  
  120.     }  
  121.     path_release(nd);  
  122. return_err:  
  123.     return err;  
  124. }  
    real_lookup由于hello.c节点是文件,所以执行如下代码段:
[cpp] view plain copy
  1. if (inode->i_ino == EXT2_ACL_IDX_INO ||  
  2.         inode->i_ino == EXT2_ACL_DATA_INO)  
  3.         /* Nothing to do */ ;  
  4.     else if (S_ISREG(inode->i_mode)) {//hello.c是文件,所以执行这段代码  
  5.         inode->i_op = &ext2_file_inode_operations;  
  6.         inode->i_fop = &ext2_file_operations;  
  7.         inode->i_mapping->a_ops = &ext2_aops;  
  8.     } else if (S_ISDIR(inode->i_mode)) {  
  9.         inode->i_op = &ext2_dir_inode_operations;  
  10.         inode->i_fop = &ext2_dir_operations;  
  11.     } else if (S_ISLNK(inode->i_mode)) {  
  12.         if (!inode->i_blocks)  
  13.             inode->i_op = &ext2_fast_symlink_inode_operations;  
  14.         else {  
  15.             inode->i_op = &page_symlink_inode_operations;  
  16.             inode->i_mapping->a_ops = &ext2_aops;  
  17.         }  
  18.     } else   
  19.         init_special_inode(inode, inode->i_mode,  
  20.                    le32_to_cpu(raw_inode->i_block[0]));  
    至此,path_walk的三层循环,都分析完了,nd->dentry最终指向了/usr/local/hello.c这个文件节点的dentry结构,其中的d_inode指向了该节点的inode结构。