没有介绍
分类: 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);