9pfs
1. 基础数据结构
1.1 9pdev
1 | /** |
- ops:设备基础的一些传输操作,包括connect、disconnect、request
- a: 用于connect的内存分配器
- state:设备的状态,包括已连接(默认)和disconnect后的状态,在后者任何的请求都是非法的,当所有的资源都释放后9pdev也会释放
- msize:一个消息最大的大小,这个值可以自己指定
- max_msize:一个消息对于传输的最大大小,这个值是这个dev支持的最大大小
- priv:传输的数据
- _fid_mgmt:内部fid管理,用于描述fid的可用性,里面有自旋锁、下一个可用的fid、和可用的fid的链表、在使用中的fid的链表
- _req_mgmt:内部的request管理,包括自旋锁、可用的tag的位图,已经被分配但是还没有被销毁的request链表,空闲的request链表。
1.2 9pdev_trans
1 | /** 用来描述传输的结构 |
- name:传输的名字,例如virtio或者xen
- ops:传输的操作,即connect、disconnect、request
1.3 9pfs_mount_data
1 | // 用来与上层vfs mount绑定的数据,即mount->m_data = uk_9pfs_mount_data |
- dev:即用于传输的9p设备
- trans:传输的具体操作,例如连接、发送等
- proto:即9p具体的协议名,现在unikraft仅实现了9P2000.u
- uname:尝试在远程服务器上挂载的用户名
- aname:当有多个文件系统的时候选择的文件树
1.4 9pfs_file_data
1 | // 对应一个9P文件的结构体,即vfscore_file->f_data = uk_9pfs_file_data |
- fid:和9p文件系统关联的标识符
- readdir_buf:通过readdir()操作获取的9p读取操作的持久化缓冲区
- readdir_off:在缓冲区中的偏移量,在这个偏移量下一个child会被找到
- readdir_sz:缓冲区中数据的大小
1.5 9pfs_node_data
1 | // 对应上层vfs vnode的结构体 即vnode->v_data = uk_9pfs_node_data |
- fid:与vnode关联的fid
- nb_open_files:从这个vnode同时打开的文件数量
- removed:当打开文件数量为0时应该removed掉
1.6 一些9P协议规定的类型
1.6.1 9p_type
1 | // 9p message的类型 |
1.6.2 qid type
1 |
1.6.3 open mode
1 |
1.6.4 9p_qid
1 | struct uk_9p_qid { |
1.6.5 9p_fid
1 | // 描述一个被管理的fid |
1.6.6 9p_str
1 | struct uk_9p_str { |
1.6.7 9p_stat
1 | struct uk_9p_stat { |
1.6.8 一些定义
1 | /** |
1.7 9preq_fcall
1 | struct uk_9preq_fcall { |
- size:整个fcall的大小,最初是buffer的大小,在传输和接受就绪后将变成发送/接受的消息的大小。
- type:fcall的类型,T就是发送,R就是接受
- offset:序列化或者解序列化的偏移量
- buf:指向9preq中的xmit_buf(发送)/recv_buf(接受)
- zc_buf:零拷贝的缓冲区
- zc_size:零拷贝缓冲区的大小
- zc_offset:在9preq的接受缓冲中的偏移量,即从偏移量开始读入zc
1.8 9preq
1 | /** |
- xmit_buf:发送的buffer缓冲区,大小为1024B,用于大多数message,大message是通过从用户提供的缓冲区零拷贝来的。
- recv_buf:接受的buffer缓冲区,同发送。这两个缓冲区占了2KB。
- xmit:用于传输的数据结构
- recv:用于接收的数据结构
- state:代表request的状态,分为五种:NONE(刚刚被创建)、INITIALIZED(初始化了——可以开始接受序列化的数据),READY(准备好了——可以发送了),SENT(已经发送到传输层了)、RECEIVED(从传输层接收到信息并且重要的9P信息例如类型、标签、大小都已经被验证了)
- tag:这个9p request的tag 占2位
- refcount:引用计数
2. 与生成9preq有关的基础操作
2.1 9preq_init(9preq.c)
1 | // 初始化一个9preq的操作 |
2.2 request_create(9p.c)->9pdev_req_create(9pdev.c)
1 | // 创建一个与9pdev绑定的req, type是9p消息的类型 |
2.3 9preq_{write/read}[size](9preq.h) -> 9preq_{write/readbuf}
1 | // 将从buf地址开始的size字节长度的信息写入req的发送缓存中 |
1 | // 从req中的接受缓存中将信息读size大小到buf中 |
3. 与9pdev相关的基础操作
3.1 9pdev_trans_register(9pdev_trans.c)
1 | static struct uk_9pdev_trans *uk_9pdev_trans_saved_default; // 先定义了一个默认的trans |
3.2 9pdev_connect(9pdev.c)
1 | // 创建一个9pdev,并且这个dev拥有一些传输相关的操作 |
4. 9p整体的操作
4.1 send_and_wait_zc(9p.c) -> 9preq_ready(9preq.c)-> 9pdev_request(9pdev.c)-> 9preq_waitreply(9preq.c)
1 | // 构造Tmessage并且发送、等待Rmessage的最主要函数,一共有三个步骤:构造->发送->等待回复 |
4.1.1 9preq_ready(9preq.c)
1 | // 构造message,并且准备好缓存区域 zc(零拷贝,即需要读/写的外部缓存区域) |
4.1.2 9pdev_request(9pdev.c)
1 | // 发送READY的请求 |
4.1.3 9preq_waitreply(9preq.c)
1 | // 等待下层vritio的回复 |
4.2 9p_read(9p.c,一个例子)
1 | // 请求:size[4] Tread tag[2] fid[4] offset[8] count[4] |
5. 9pfs的操作
5.1 9pfs_mount(9pfs_vfsops.c)
1 | // 注册为上层的vfsops.vfs_mount,即挂载9p文件系统 |
5.2 9pfs_create(9pfs_vnops.c)->9pfs_create_generic
1 | // 是上层vops->vop_create的实现,即vnode的创建 |
5.3 9pfs_open(9pfs_vnops.c)
1 | // 注册为上层的vnops中vop_open = uk_9pfs_open |
5.4 9pfs_read(9pfs_vnops.c,一个例子)
1 | // 通过打开的文件fp、文件的vnode、要写入的缓存uio来读文件 |