Chinaunix首页 | 论坛 | 博客
  • 博客访问: 269955
  • 博文数量: 38
  • 博客积分: 2208
  • 博客等级: 大尉
  • 技术积分: 374
  • 用 户 组: 普通用户
  • 注册时间: 2008-05-22 13:50
个人简介

没有介绍

文章分类

全部博文(38)

文章存档

2017年(2)

2014年(1)

2012年(2)

2011年(5)

2008年(28)

vfs

分类: LINUX

2011-06-06 23:13:11

---> d_alloc        创建root的dentry 
   ---> atomic_set(&dentry->d_count, 1); dentry创建时,**** 引用计数为1**** ,此时dentry不在dcache中
   ---> dentry->d_parent = dget(parent); 调用可以看到只要子dentry存在,parent dentry就必然会被引用一次

vfs_kern_mount
1) 调用alloc_vfsmnt创建vfsmount,意味着 vfsmount对象是由VFS创建,必然会创建;sb由底层FS创建,不一定创建,可能共用。
2) type->get_sb;底层FS创建 sb,并与vfsmount挂接。

woodfs_get_sb
   ---> get_sb_nodev 

      ---> sget   判断是否重用sb;否则调用 alloc_super创建一个sb;调用set_anon_super ;建立sb与file_system对象的关系;
  ---> set_anon_super  主要是设置匿名的无设备的s->s_dev。

      ---> woodfs_fill_super  创建root的inode与dentry

         ---> woodfs_get_inode  创建root的inode,
            ---> new_inode
               ---> alloc_inode
                  ---> sb->s_op->alloc_inode 创建FS专有inode信息,VFS inode是它的一部分
                     ---> inode_init_once 从slab申请后第一次初始化
                  ---> inode_init_always 第二次初始化inode其它信息,**** 设置 i_count 为1 ****

            ---> 初始化mode,uid,gid, i_op,i_fop(分类型), i_data.a_ops( mapping->a_ops)及backing_dev_info

         ---> d_alloc_root      根据inode创建root的dentry。由于是root,因此它内部调用 d_alloc 传入parent为NULL
            ---> d_alloc(NULL, "/");      创建root的dentry             ---> res->d_parent = res;     因此dentry的parent是自己
            ---> d_instantiate            关联dentry与inode
         ---> 使用 dentry 更新 sb->s_root;

      ---> simple_set_mnt  更新 mnt->mnt_sb(sb)和mnt->mnt_root(dentry),且dget(sb->s_root)

nfs4_get_sb
   ---> nfs4_try_mount
      ---> nfs4_remote_get_sb (nfs_do_root_mount (nfs4_remote_fs_type))
         ---> nfs4_create_server  创建 nfs_server 对象
         ---> nfs4_fill_super 
         ---> sget             判断是否重用sb;否则调用 alloc_super创建一个sb;调用set_anon_super ;建立sb与file_system对象的关系;
            ---> nfs_set_super  内部调用 set_anon_super

         ---> nfs4_get_root    创建 inode与dentry,相当于  ramfs_fill_super
            ---> nfs_fhget   创建inode,相当于 woodfs_get_inode/ramfs_get_inode
               ---> iget5_locked 获取一个inode,先尝试从内存,再分配一个
                  ---> get_new_inode 类似于 new_inode,
                     ---> sb->s_op->alloc_inode 创建FS专有inode信息,VFS inode是它的一部分
                        ---> inode_init_once 从slab申请后第一次初始化
                     ---> inode_init_always 第二次初始化inode其它信息,**** 设置 i_count 为1 ****

               ---> 初始化 inode的信息,包括 i_op,i_fop(分类型),i_data.a_ops及 backing_dev_info

            ---> d_obtain_alias  根据inode创建dentry,有点类似于 ramfs_fill_super流程中调用 d_alloc_root
               ---> d_alloc(NULL, ""); 相当于ramfs调用d_alloc,很奇怪,这里的dentry没有名称
               ---> tmp->d_parent = tmp     因此dentry的parent是自己
               ---> 关联dentry与inode

         ---> 更新 mnt->mnt_sb(sb)和mnt->mnt_root(dentry),相当于ramfs_fill_super流程中调用simple_set_mnt 

---------------------------------------------------------------------------------------------------------------------------------

sys_newstat--->vfs_stat ---> vfs_fstatat
sys_newlstat--->vfs_lstat ---> vfs_fstatat
   ---> user_path_at

      ---> do_path_lookup
         ---> path_init          初始化 nameidata *nd,   path_get(&fs->pwd);
         ---> path_walk ---> link_path_walk  
            ---> path_get(&save);
            ---> __link_path_walk        最主要的遍历函数,根据/一级一级的循环
             for
               ---> do_lookup            真实的lookup
               ---> inode = next.dentry->d_inode;
               ---> path_to_nameidata           
            ---> path_put(&save);
   ---> vfs_getattr   调用 inode->i_op->getattr 或通用generic_fillattr

do_lookup
   ---> __d_lookup      在dcache hlist中查找,也会根据FS的d_op->d_compare来判断,一般为NULL
   if 找到
      ---> do_revalidate         ---> dentry->d_op->d_revalidate  如果找到,则需要校验dentry合法性

   else 如果没有找到
      ---> real_lookup     如果没有找到,真实地在fs中查找
         ---> d_lookup     再一次在dcache 查找
         if 找到
            ---> do_revalidate ---> dentry->d_op->d_revalidate  如果找到,则需要校验dentry合法性
         else
            ---> dentry = d_alloc(parent, name);    如果未找到,创建一个新的dentry,parent
            ---> dir->i_op->lookup(dir, dentry, nd);

   ---> path->mnt = mnt;
   ---> path->dentry = dentry;      更换path的内容到当前搜索到的dentry
   ---> __follow_mount(path);       如果找到的dentry是一个挂载点,则处理一些有关vfsmount的操作

nfs_atomic_lookup   struct inode *dir父目录, struct dentry *dentry新创建的子dentry, struct nameidata *nd 搜索的状态
    if 不是打开文件,在父目录下搜索dentry
    ---> nfs_lookup
       ---> dentry->d_op = nfs4_dentry_operations;    --- 主要是VFS在dcache中找到此dentry后的一些校验工作
       ---> NFS_PROTO(dir)->lookup
       ---> nfs_fhget          创建inode,见nfs4_get_sb 流程中的解释
       ---> d_materialise_unique      关联dentry与inode

    else  打开文件
    ---> dentry->d_op = nfs4_dentry_operations;    同上
    ---> nfs4_atomic_open           打开
       ---> nfs4_do_open
          ---> _nfs4_do_open
             ---> _nfs4_proc_open
             ---> nfs4_opendata_to_nfs4_state   
                --->  nfs_fhget        创建inode,见 nfs4_get_sb 流程
       ---> d_add_unique            关联dentry与inode


---------------------------------------------------------------------------------------------------------------------------------

sys_getdents
   ---> vfs_readdir
      ---> woodfs_readdir
         for  循环对该目录下的每一个都进行遍历
         ---> filldir

sys_mkdir
   ---> sys_mkdirat
      ---> user_path_parent       寻找需要创建的目录的父目录,user_path_at则找指定项
      ---> lookup_create          查找需要创建的目录项,这里会创建一个dentry
         ---> lookup_hash ---> __lookup_hash
            ---> cached_lookup    在cache中寻找
            ---> d_alloc          创建一个dentry项
            ---> i_op->lookup     查找一个inode (woodfs_lookup) --- 这里的查找并没有创建一个inode

      ---> vfs_mkdir
         ---> dir->i_op->mkdir    创建目录woodfs_mkdir,传入 lookup_hash 创建的dentry项,创建inode,并与dentry关联

sys_open  创建文件
   ---> do_sys_open
      ---> do_filp_open
         ---> lookup_hash ---> __lookup_hash  查找一个dentry
            ---> cached_lookup    在cache中寻找
            ---> d_alloc          创建一个dentry项
            ---> i_op->lookup     查找一个inode (woodfs_lookup)   --- 这里的查找并没有创建一个inode

         ---> __open_namei_create
            ---> vfs_create  ---> dir->i_op->create  创建一个文件
         ---> nameidata_to_filp

sys_open  打开文件
   ---> do_sys_open
      ---> do_filp_open
         ---> path_lookup_open ---> do_path_lookup 查找一个dentry
         ---> may_open
         ---> nameidata_to_filp

问题,现在 i_op->lookup 的场景:

1. stat一个inode
2. open一个文件          
3. create一个文件         肯定不能创建inode    好像nfs还是会在lookup创建一个文件?
4. mkdir一个目录          肯定不能创建inode

到底是否该在 i_op->lookup 创建一个inode

---------------------------------------------------------------------------------------------------------------------------------

const struct file_operations woodfs_dir_operations = {
 .open  = woodfs_dir_open,        打开一个目录
 .release = woodfs_dir_close,       关闭一个目录
 .llseek  = dcache_dir_lseek,
 .read  = generic_read_dir,
 .readdir = woodfs_readdir,         sys_getdents 遍历目录项系统调用
 .fsync  = simple_sync_file,
};

static const struct inode_operations woodfs_dir_inode_operations = {
 .create  = woodfs_create,          在一个目录下创建一个文件
 .lookup  = woodfs_lookup,          在一个目录下搜索一个项
 .link  = simple_link,
 .unlink  = simple_unlink,
 .symlink = woodfs_symlink,
 .mkdir  = woodfs_mkdir,           在一个目录下创建目录
 .rmdir  = simple_rmdir,
 .mknod  = woodfs_mknod,
 .rename  = simple_rename,
};

const struct file_operations woodfs_file_operations = {  一个文件打开后的,read/write/mmap/seek/fsync
 /*
 .read  = do_sync_read,
 .aio_read = generic_file_aio_read,
 .write  = do_sync_write,
 .aio_write = generic_file_aio_write,
 .mmap  = generic_file_mmap,
 .fsync  = simple_sync_file,
 .splice_read = generic_file_splice_read,
 .splice_write = generic_file_splice_write,
 .llseek  = generic_file_llseek,*/
};

static const struct inode_operations nfs4_file_inode_operations = {  获取或设置一个文件或目录的inode属性
 .permission = nfs_permission,
 .getattr = nfs_getattr,    一般在fstat, stat, lstat等接口中调用
 .setattr = nfs_setattr,    一般在修改文件之后,如truncate等操作后的内部隐含属性处理
 .getxattr = nfs4_getxattr,
 .setxattr = nfs4_setxattr,
 .listxattr = nfs4_listxattr,
};

static struct backing_dev_info woodfs_backing_dev_info = { 预读的一些处理
 .name  = "woodfs",
 .ra_pages = 0, /* No readahead */
 .capabilities = BDI_CAP_NO_ACCT_AND_WRITEBACK |
     BDI_CAP_MAP_DIRECT | BDI_CAP_MAP_COPY |
     BDI_CAP_READ_MAP | BDI_CAP_WRITE_MAP | BDI_CAP_EXEC_MAP,
};

nfs backing_dev_info:
 server->backing_dev_info.name = "nfs";
 server->backing_dev_info.ra_pages = server->rpages * NFS_MAX_READAHEAD (15);


阅读(3294) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~