Linux虚拟文件系统--文件路径名的解析(4)--符号链接

字体大小: 中小 标准 ->行高大小: 标准

符号链接也是一种文件,只不过其内容是另一个文件的路径名。对于符号链接的处理,要注意避免死循环的产生,如一个符号链接指向其本身。符号链接可能包含了符号链接,因此内核采用递归的方式来处理这个问题,为了避免符号链接的死循环而导致无穷递归,内核采用link_count和total_link_count来跟踪符号链接的处理,其中前者表示连续的符号链接数,后者表示总共的符号链接数,两者都不能超过各自的限制,否则内核会放弃解析。

相关阅读: http://www.linuxidc.com/search.aspx?where=nkey&keyword=3305

  1. staticinlineint do_follow_link(struct path *path, struct nameidata *nd) {
  2. int err = -ELOOP; /*如果处理的链接数超过下面的限制则会放弃搜索(因为有可能陷入死循环)*/
  3. /*link_count表示连续的符号链接数,其值不能超过8,total_link_count表示总共的 链接数,气值不能超过40*/
  4. if (current->link_count >= MAX_NESTED_LINKS) goto loop;
  5. if (current->total_link_count >= 40) goto loop;
  6. BUG_ON(nd->depth >= MAX_NESTED_LINKS); cond_resched();
  7. err = security_inode_follow_link(path->dentry, nd); if (err)
  8. goto loop; /*每处理一次符号链接,link_count,total_link_count和depth都要加1*/
  9. current->link_count++; current->total_link_count++;//
  10. nd->depth++; /*主要是调用特定于文件系统的follow_link函数进行符号链接的跟踪*/
  11. err = __do_follow_link(path, nd); /*每执行完一次符号链接,link_count和depth都要减1*/
  12. current->link_count--; nd->depth--;
  13. return err; loop:
  14. path_put_conditional(path, nd); path_put(&nd->path);
  15. return err; }
  1. static __always_inline int __do_follow_link(struct path *path, struct nameidata *nd) {
  2. int error; void *cookie;
  3. struct dentry *dentry = path->dentry;
  4. touch_atime(path->mnt, dentry); nd_set_link(nd, NULL);//在saved_names中清除当前解析的符号链接路径
  5. if (path->mnt != nd->path.mnt) {
  6. path_to_nameidata(path, nd); dget(dentry);
  7. } mntget(path->mnt);
  8. /*调用特定于文件系统的follow_link方法来跟踪符号链接,并将符号链接中保存的路径名提取出来 存放在nd的saved_names中*/
  9. cookie = dentry->d_inode->i_op->follow_link(dentry, nd); error = PTR_ERR(cookie);
  10. if (!IS_ERR(cookie)) { char *s = nd_get_link(nd);//提取saved_names中的路径
  11. error = 0; if (s)//路径存在,则继续解析,__vfs_follow_link将会调用link_path_walk,因此对于
  12. //路径中存在多个符号链接的情况,这是一个递归的过程 error = __vfs_follow_link(nd, s);
  13. if (dentry->d_inode->i_op->put_link) dentry->d_inode->i_op->put_link(dentry, nd, cookie);
  14. } path_put(path);
  15. return error;
  16. }
  1. static __always_inline int __vfs_follow_link(struct nameidata *nd, constchar *link) {
  2. int res = 0; char *name;
  3. if (IS_ERR(link)) goto fail;
  4. if (*link == '/') {
  5. set_root(nd); path_put(&nd->path);
  6. nd->path = nd->root; path_get(&nd->root);
  7. }
  8. res = link_path_walk(link, nd); if (nd->depth || res || nd->last_type!=LAST_NORM)
  9. return res; /*
  10. * If it is an iterative symlinks resolution in open_namei() we * have to copy the last component. And all that crap because of
  11. * bloody create() on broken symlinks. Furrfu... */
  12. name = __getname(); if (unlikely(!name)) {
  13. path_put(&nd->path); return -ENOMEM;
  14. } strcpy(name, nd->last.name);
  15. nd->last.name = name; return 0;
  16. fail: path_put(&nd->path);
  17. return PTR_ERR(link); } 

此文章由 http://www.ositren.com 收集整理 ,地址为: http://www.ositren.com/htmls/64843.html