针对打开文件的操作主要体现在struct file_operations数据结构中。在cephfs kernel client中具体实现如下:
const struct file_operations ceph_file_fops = {
.open = ceph_open,
.release = ceph_release,
.llseek = ceph_llseek,
.read_iter = ceph_read_iter,
.write_iter = ceph_write_iter,
.mmap = ceph_mmap,
.fsync = ceph_fsync,
.lock = ceph_lock,
.flock = ceph_flock,
.splice_read = generic_file_splice_read,
.splice_write = iter_file_splice_write,
.unlocked_ioctl = ceph_ioctl,
.compat_ioctl = ceph_ioctl,
.fallocate = ceph_fallocate,
};
ceph_open(struct inode *inode, struct file *file) 该函数在打开文件时被调用
|__调用prepare_open_request()函数来创建ceph_mds_request请求
|__调用ceph_mdsc_do_request()函数将ceph_mds_request请求同步的发送给mds进程
|__调用ceph_init_file()函数创建ceph_file_info数据结构且将该数据结构放入到file->private_data中
ceph_release(struct inode *inode, struct file *file) 该函数在关闭文件时被调用
|__调用ceph_put_fmode()函数减少打开文件的引用次数,若引用次数为0,则从本地cache中删除该文件
ceph_llseek(struct file *file, loff_t offset, int whence)
|__若whence是SEEK_END|SEEK_DATA|SEEK_HOLE
|__调用ceph_do_getattr()函数从mds集群中获取指定inode的attrs属性
|__调用i_size_read()函数得到当前inode的实际大小
|__根据whence的值调整offset的值
|__调用vfs_setpos()函数设置文件的当前位置为offset
ceph_read_iter(struct kiocb *iocb, struct iov_iter *to) 该函数在读取文件内容的时候被调用
|__调用ceph_get_caps()函数得到caps
|__对于同步读数据操作来说
|__若iocb->ki_flags&IOCB_DIRECT
|__调用ceph_direct_read_write()函数从osds集群中读取数据
|__若!iocb->ki_flags&IOCB_DIRECT
|__调用ceph_sync_read()函数从osds集群中读取数据
|__对于非同步读取数据操作来说
|__调用generic_file_read_iter()函数实现异步数据的读取操作
ceph_write_iter(structd kiocb *iocb, struct iov_iter *from) 执行写操作时调用该函数执行
|__调用 generic_write_check()函数在实际写之前进行必要的检查
|__调用ceph_get_caps()得到写权限
|__对于同步写操作
|__对于iocb->ki_flags & IOCB_DIRECT
|__调用ceph_direct_read_write()函数向osds集群中写入数据
|__对于! iocb->ki_flags & IOCB_DIRECT
|__调用ceph_sync_write()函数向osds集群中红写入数据
|__对于非同步写操作
|__调用generic_perform_write()函数执行写操作
ceph_mmap(struct file *file, struct vm_area_struct *vma) 将文件内容影射到内存的操作时调用该函数执行
|__设置vma的vm_ops=ceph_vmops
ceph_fsync(struct file *file, loff_t start , loff_t end, int datasync)
|__调用ceph_sync_write_wait()函数等待inode上所有未完成的osd请求执行完毕
|__调用try_flush_caps()函数将所有dirty的caps刷回到mds
|__调用unsafe_request_wait()函数等待inode上所有针对mds请求执行完毕
ceph_lock(struct file *file, int cmd, struct file_lock *fl) 当用户态程序执行fcntl lock时调用该函数执行
|__调用ceph_lock_message()函数创建文件锁命令请求后,将该请求发送给mds集群
ceph_flock(struct file *file, int cmd, struct file_lock *fl)
|__调用ceph_lock_message()函数创建文件锁命令请求后,将该请求发送给mds集群
ceph_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|__根据cmd的值做不同的处理
|__cmd==CEPH_IOC_GET_LAYOUT
|__ceph_ioctl_get_layout()
|__ceph_do_getattr(CEPH_STAT_CAP_LAYOUT)从mds集群中读取file对应的inode的layout信息到ceph_inode_info的i_layout中
|__将i_layout信息写入到struct ceph_ioctl_layout数据结构中且通过copy_to_user()函数将数据返回给用户态
|__cmd==CEPH_IOC_SET_LAYOUT
|__ceph_ioctl_set_layout()
|__调用copy_from_user()函数将新的layout信息从用户态复制到内核态
|__调用ceph_do_getattr()函数从mds集群中读取当前的layout信息
|__调用__validate_layout()函数检查新设置的layout是否有效
|__调用ceph_mdsc_create_request()函数创建request请求
|__调用ceph_mdsc_do_request()函数同步的发送request请求到mds集群
|__cmd==CEPH_IOC_SET_LAYOUT_POLICY
|__ceph_ioctl_set_layout_policy()
|__调用copy_from_user()函数将新的layout信息从用户态复制到内核态
|__调用__validate_layout()函数检查新设置的layout是否有效
|__调用ceph_mdsc_create_request()函数创建request请求
|__调用ceph_mdsc_do_request()函数同步的发送request请求到mds集群
|__cmd==CEPH_IOC_GET_DATALOC 计算data所在的ceph集群中的位置信息
|__ceph_ioctl_get_dataloc()
|__调用copy_from_user()函数将ceph_ioctl_dataloc信息复制到内核态
|__调用ceph_calc_file_object_mapping()函数计算ceph_ioctl_dataloc信息中指定文件所在的oid等信息
|__调用ceph_object_locator_to_pg()函数计算出oid所在的pg信息
|__调用ceph_pg_to_acting_primary()函数计算出pg所在的主osd信息
|__调用copy_to_user()函数将计算出来的信息发送回给用户态
|__cmd==CEPH_IOC_LAZYIO 设置LAZYIO标识
|__ceph_ioctl_lazyio()
|__ 判断struct ceph_file_info中的fmode是否未设置CEPH_FILE_MODE_LAZY
|__设置struct ceph_file_info中的fmode拥有CEPH_FILE_MODE_LAZY标识
|__更新ceph_inode_info中的i_nr_by_mode数组
|__调用ceph_check_caps()函数更新caps
|__cmd==CEPH_IOC_SYNCIO
|__ceph_ioctl_syncio()
|__设置struct ceph_file_info结构中的flags的CEPH_F_SYNC位
ceph_fallocate(struct file *file, int mode, loff_t offset, loff_t length)
|__若mode==FALLOC_FL_PUNCH_HOLE
|__调用ceph_zero_object()函数在文件的指定offset开始到offset+length结束的地方设置文件内容为0
|__若offset+length>size
|__调用ceph_inode_set_size()将文件的大小设置为offset+length
|__调用ceph_check_caps()函数校验文件caps的认证是否有效
针对文件映射到内存的相关操作主要体现在struct vm_operations_struct数据结构中,具体内容如下:
static const struct vm_operations_struct ceph_vmops = {
.fault = ceph_filemap_fault,
.page_mkwrite = ceph_page_mkwrite,
};
ceph_filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf) 该函数在读取内存中的数据时发生内存缺页的时候被调用
|__调用find_or_create_page()函数从物理内存中获取到物理内存页
|__调用__ceph_do_getattr(CEPH_STAT_CAP_INLINE_DATA)函数从mds集群中读取到数据
|__调用flush_dcache_page()函数将读取到的数据写入到物理内存页
|__调用SetPageUptodate()函数设置该物理内存页已经被更新
|__设置vmf->page=page,即:将物理内存页添加到虚拟内存中
ceph_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) 当页面从readonly状态变迁到writeable状态时该函数被调用
|__调用ceph_update_writeable_page()函数来设置vmf->page页为writeable
|__调用set_page_diry()函数设置该物理内存页为dirty的
来源:oschina
链接:https://my.oschina.net/u/206258/blog/731191