alibaba / tfs

TFS (Taobao File System) is a distributed file system similar to GFS.
http://tfs.taobao.org
GNU General Public License v2.0
1.24k stars 457 forks source link

追加写入数据之后,关闭tfs文件,dataserver出现CRC校验错误 #15

Closed lanyuliuyun closed 8 years ago

lanyuliuyun commented 8 years ago

先以 T_WRITE | T_CREATE 方式打开一个文件,每次 t_lseek() 之后 t_write() 写入数据(t_lseek() 指定的offset是与写入数据的累计尺寸相一致的),t_close() 成功获取到一个tfs文件名。

再以 T_WRITE | T_READ 方式打开刚才的这个 tfs 文件,t_lseek(SET) 方式seek到文件结尾,再 t_write() 追加写入数据,之后 t_close() 失败,返回 -8013。利用 stat 命令查看刚才的文件,第二次的写入数据未被保存。

再看 dataserver.log,根据 filenumber 确定,刚才 t_close() 失败的原因是关闭请求消息中的 CRC 与 dataserver本地的CRC值不一致所致。

该问题在我的环境里必现,使用的版本是 http://code.taobao.org/svn/tfs/branches/dev_for_outer_users/ ,是在虚拟机里搭建的单机环境

@tfs-taobao

lanyuliuyun commented 8 years ago

分析了 dataserver 的代码之后,知道原因了,每次 t_open() 之后,初次写入数据,dataserver 会为当前的会话 new 一个 DataFile对象进行标识,其包含一个2MiB的buffer。若此时 seek 设置写入offset,再写入,此时写入的data前面会包含一些空洞(offset + size小于2MiB时)。t_close() 时,dataserver 会对 DataFile 的的buffer,从起始位置到数据结尾进行计算得到一个 CRC,拿这个 CRC 值与client提交的CRC值进行比较,此时就因CRC值不同而t_close() 失败了。

而刚才 DataFile 中计算CRC时,是将那些空洞里的数据算在内的,但该空洞中的数据是不确定的(new的原因),从而计算出的CRC值是无意义的,因此 t_close() 时 dataserver 必然出错。

只能说 tfs 太坑了!虽然提供了 lseek,但根本就不是常规 seek 的语义,形同虚设! 上传数据时,必须一次性全部写入,保证数据连续,不能后续重新打开后append !