符号链接也是一种文件,只不过其内容是另一个文件的路径名。对于符号链接的处理,要注意避免死循环的产生,如一个符号链接指向其本身。符号链接可能包含了符号链接,因此内核采用递归的方式来处理这个问题,为了避免符号链接的死循环而导致无穷递归,内核采用link_count和total_link_count来跟踪符号链接的处理,其中前者表示连续的符号链接数,后者表示总共的符号链接数,两者都不能超过各自的限制,否则内核会放弃解析。相关阅读: http://www.linuxidc.com/search.aspx?where=nkey&keyword=3305
- staticinlineint do_follow_link(struct path *path, struct nameidata *nd)
- {
- int err = -ELOOP;
- /*如果处理的链接数超过下面的限制则会放弃搜索(因为有可能陷入死循环)*/
- /*link_count表示连续的符号链接数,其值不能超过8,total_link_count表示总共的
- 链接数,气值不能超过40*/
- if (current->link_count >= MAX_NESTED_LINKS)
- goto loop;
- if (current->total_link_count >= 40)
- goto loop;
- BUG_ON(nd->depth >= MAX_NESTED_LINKS);
- cond_resched();
- err = security_inode_follow_link(path->dentry, nd);
- if (err)
- goto loop;
- /*每处理一次符号链接,link_count,total_link_count和depth都要加1*/
- current->link_count++;
- current->total_link_count++;//
- nd->depth++;
- /*主要是调用特定于文件系统的follow_link函数进行符号链接的跟踪*/
- err = __do_follow_link(path, nd);
- /*每执行完一次符号链接,link_count和depth都要减1*/
- current->link_count--;
- nd->depth--;
- return err;
- loop:
- path_put_conditional(path, nd);
- path_put(&nd->path);
- return err;
- }
- static __always_inline int __do_follow_link(struct path *path, struct nameidata *nd)
- {
- int error;
- void *cookie;
- struct dentry *dentry = path->dentry;
- touch_atime(path->mnt, dentry);
- nd_set_link(nd, NULL);//在saved_names中清除当前解析的符号链接路径
- if (path->mnt != nd->path.mnt) {
- path_to_nameidata(path, nd);
- dget(dentry);
- }
- mntget(path->mnt);
- /*调用特定于文件系统的follow_link方法来跟踪符号链接,并将符号链接中保存的路径名提取出来
- 存放在nd的saved_names中*/
- cookie = dentry->d_inode->i_op->follow_link(dentry, nd);
- error = PTR_ERR(cookie);
- if (!IS_ERR(cookie)) {
- char *s = nd_get_link(nd);//提取saved_names中的路径
- error = 0;
- if (s)//路径存在,则继续解析,__vfs_follow_link将会调用link_path_walk,因此对于
- //路径中存在多个符号链接的情况,这是一个递归的过程
- error = __vfs_follow_link(nd, s);
- if (dentry->d_inode->i_op->put_link)
- dentry->d_inode->i_op->put_link(dentry, nd, cookie);
- }
- path_put(path);
- return error;
- }
- static __always_inline int __vfs_follow_link(struct nameidata *nd, constchar *link)
- {
- int res = 0;
- char *name;
- if (IS_ERR(link))
- goto fail;
- if (*link == "/") {
- set_root(nd);
- path_put(&nd->path);
- nd->path = nd->root;
- path_get(&nd->root);
- }
- res = link_path_walk(link, nd);
- if (nd->depth || res || nd->last_type!=LAST_NORM)
- return res;
- /*
- * If it is an iterative symlinks resolution in open_namei() we
- * have to copy the last component. And all that crap because of
- * bloody create() on broken symlinks. Furrfu...
- */
- name = __getname();
- if (unlikely(!name)) {
- path_put(&nd->path);
- return -ENOMEM;
- }
- strcpy(name, nd->last.name);
- nd->last.name = name;
- return 0;
- fail:
- path_put(&nd->path);
- return PTR_ERR(link);
- }
Linux虚拟文件系统--open()Linux虚拟文件系统--文件路径名的解析(3)--普通文件名相关资讯 Linux文件系统 Linux虚拟文件系统
- Linux文件系统简介及其系统管理工 (今 13:21)
- 哪个文件系统最适合你的 Linux 系 (01月19日)
- Linux文件系统管理 (12/15/2015 20:58:29)
| - Linux虚拟文件系统VFS (04月04日)
- Linux磁盘及文件系统概念 (12/22/2015 15:02:55)
- Linux 文件系统(inode和block) (12/02/2015 19:34:16)
|
本文评论 查看全部评论 (0)