Featured image of post linux 中u 盘的同步问题

linux 中u 盘的同步问题

linux 有很多不好用的地方

  • U 盘不能显示进度条

  • dd 命令制作的启动盘 meta data 不更新,导致无法继续写入

文韬大佬深耕内核多年,中断、文件系统、信号理解的都很深入。

问题背景

刘总反馈了一个 uos 上的使用体验问题:拷贝大文件到 u 盘时,虽然拷贝很快完成了,但是后面一直现在同步中,经常让人怀疑它是不是卡死了。而在 windows 上,虽然拷贝的进度条走得很慢,但是完成了就完成了,可以直接拔盘走人了,不会有“同步”的等待过程。

问题的原因(如果我理解错了,文管同事请指正)大概是:

  • 在 linux 上,copy 操作更多的是写入了内存的 page cache 里,而并没有真正完成落盘,而这一般是通过主动调用 fsync(2)之类的系统调用来完成的。
  • 比如在刘总的场景下, 如果电脑内存比较大(16G 以上),那拷贝一个 5G 的大文件,因为是从本地 nvme 读入到内存里,可能很快可以完成(几秒钟就 ok);但是当调用 fsync 将所有数据写入慢速 u 盘呢?如果 u 盘质量不太好,加上为了保持和 windows 的兼容所以 u 盘的文件系统一般是 exfat 或者 ntfs,可能速度只有 30-50M,那 5G 的数据可能需要超过 2 分钟。

在使用者来看,3s 就写完了,但是在“同步中”转了 2 分钟,确实让人恼火。

那这个问题可以被优化吗?如果是希望去掉同步过程,3s 就写完,那是不可能做到的。——u 盘就这么快,这是硬性的限制。

但如果是优化使用体验呢?那是有可能的,这其实也是刘总的核心诉求:不是要求更快,而是在进度的显示上更合理。——换而言之,不要 3s 就显示 100%了,对于用户而言不知道同步是什么含义,所以最好是落盘多少就显示多少进度,和 windows 一样。

所以问题的要点是:如何合理地获取、显示数据落盘的进度?

数据落盘进度

这并不是一个容易解决的问题。

内核的系统调用 fsync(2)是全部完成后返回,没有进度显示和反馈的。

——我之后可以研究一下,看是否有可能在 data 部分加一个进度统计;要做这也是一个工作量比较大的修改,而且不一定做得到。而且除了 data 之外,比如 ext4 还会涉及到 metadata 和 journal 的处理,exfat/ntfs-3g 因为是 fuse 实现,那更是完全走不同的路径,所以这个还需要更多的调研。

文管团队之前找到过在我看来很合理的统计方式:看 block 的流量统计。这是内核在 sysfs 导出的接口,通过观察有多少流量经过,我们就知道有多少数据被写下去了。

但是这个方式有一个问题:如果用户在同一个 u 盘上发起了多个拷贝操作,那这些流量会混在一起无法区分,没法统计单独一个操作的进度。——而且在 block 层面,目前而言无法做到区分它的数据来源。(这也是我可以 mark 一下的点,也许以后如果用 async-io+direct-io,我们有办法分开统计归属于各个 task 的流量,我之后会留意一下)

还有一个办法就是分段 copy+fsync,比如一个 5g 文件,按 256M 一段,分 20 段,一段一段 copy+fsync,完成一段就更新一段的进度。——但是这样据文管团队反应会损失不少的整体性能。(我没测试过,存疑)

我在这里提出一个折中的方案:

  • 考虑到大部分情况下,用户只会有一次拷贝操作,所以我建议保留基于 block 的统计。
  • 如果用户真的触发了多拷贝,再 fallback 到备选方式,比如现在的完成+同步。
  • 另外对于拷贝操作,可以考虑在进度里为“fsync”操作预留一些进度条,比如全部拷贝完成了也只是 80%,完成 fsync 才补上空余的 20%。

将来的展望

从内核方面,我会留意一下 block 的 task 流量统计,以及 fsync 的进度统计,以后说不定会有方案可以提供支撑。

另一方面,6.6 内核上 exfat 有了内核驱动,可以作为首选的 u 盘文件系统格式,可以避免现在的一些因为 fuse 实现而引起的问题;内核的 ntfs3 也是一个选项,还需要进一步评估。

另外值得一提的是,ntfs-3g 的 fsync 实现是很粗糙的,它实际上就是在用户空间调用了整个 disk 的 sync,类似于 fsync(“dev/sda1”)。——这种实现会有一些缺点,比如多任务下,一个小文件的 fsync,其实会要等待其它大任务的数据全部落盘才能返回,很蠢。

最后,我们目前对于 exfat 和 ntfs 的投入是非常小的(大概只有我稍微瞄过一眼),在现有的规划里似乎也没准备投入,所以其实这是一个需要评估的点:exfat 和 ntfs 对于我们有多重要?我们应该投入吗?是否需要增加一个专门的人深入来做?比如完善上游的 ntfs3 到一个稳定可用的程度?

——这也许是合理的,因为我们大概是全世界最关心内核 ntfs3 的公司之一了……

总结

总结如下:

  • 更多的不是性能优化问题,而是产品侧的进度显示策略问题。
  • 进度显示上有着技术难点,我建议是用 block 流量统计来处理通常的情况,再在多任务下 fallback 到 copy+fsync 的分段统计,同时给 fsync 阶段预留一定的进度。
  • 我会将相关的技术点加入我的 list,保持关注,希望以后可以有更好的选择。