数据结构修改:
1. 在exfs_inode_i结构中,复用i_flags,标志是否处于重构状态,并添加每个副本的错误区段链表。
3.增加全局变量:rebuild_inode_list,存储所有处于重构状态的exfs_inode_i指针。
4.在extent结构中添加副本状态,并根据状态切分extent。此处涉及到一个粒度的问题:由于exfs支持的最小粒度是1M,则三个副本中,小于1M的可用区段是没有意义的(此处可以优化)。
客户端流程修改:
Bio的回调函数中,若发现错误,则将错误区段添加到nfs_inode中的副本区段链表中,选择一个合适时机,把错误情况发送到服务器。
这个合适的时机,有两个选择:
1. 一次下刷结束时候。
2. 文件close的时候。
客户端Find_get_extent()时候,要考虑副本状态,以及nfs_inode中的错误区段链表。。
文件close时候,删除副本区段链表,确保已经发送到服务器。
服务器端流程修改:
OPEN流程修改:
若是以写权限打开文件,则检查对应的exfs_inode是否处于重构状态,若是,则返回失败。
实现重构时候,可读不可写。
get_layout流程:
需要检查对应的inode中是否有错误区段,并根据不同区段的状态,切分extent。
服务器收到客户端错误报告后,
1. 设置对应inode为重构状态
2. 将错误区段添加到exfs_inode_i结构中
3. 添加重构任务到工作队列(可以是另开的线程)
4. 返回给客户端,客户端收到此回复后,在nfs_inode中增加引用计数(防止被释放),并修改标志位,延迟释放delegation。
服务器重构:
每个重构例程针对一个inode,
1. 检查并设置inode中的某个标志位,若此inode已经处于被重构的状态(防止多次重构同一个inode),则退出。
2. 对所有拥有此layout的client进行召回(这么做的原因是对于某块磁盘坏区,多个客户端可能都会报错,召回可触发客户端下刷或读取磁盘数据,使得客户端报告出错区段,可以统一处理)
3. 根据inode中记录的错误区段在exfs中进行重新分配。
对于这点不是很明确,例如,若是网络原因导致客户端读写出错,若简单的丢弃对应的磁盘空间,再重新分配其他一段空间是否不够妥当?是否可以带内检测一下?另外,是否需要检查下客户端和服务器是否掉盘?请宫勐师兄完善此处exfs的处理过程。
4. 检查入口参数携带client,若非空,则此client为担任重构任务的client,否则通过某种方式,选定一个。
5. 将此inode的fh(若不存在,需要创建一个),和layout信息,发送给客户端,要求客户端重构(需要添加一个新的rpc回调函数)
客户端收到重构的要求:
1. 为减小延迟,启动一个异步的线程,立即回复此rpc。
在异步线程中,检测本地是否缓存此文件的inode,若有则直接利用,并将走已有的layoutget流程,获取相关信息。若没有缓存,则利用nfs_instantiate(); 以及nfs_fhget()创建新的nfs_inode。
2. 复用已有代码,完成重构。
3. 完成后,向服务器发送完成的rpc。
服务器收到客户端的重构完成rpc后,
1. 修改exfs_inode_i中的错误区段链表。
2. 修改重构标志位。
有待解决的问题
1. 重构中再出现错误,该如何解决?
2. 三副本都不一致,如何解决?
3. Inode map
4. 副本状态如何记录到磁盘。