2

在对 BTRFS 手册页进行了大量测试和挖掘之后,我需要一些 Linux / BTRFS 人员的帮助。

我有一个 java 应用程序,它使用 java MappedByteBuffer 实用程序将数据文件写入磁盘。这是应用程序在写入磁盘时使用约 16000 字节的字节缓冲区。当一个新文件被写入时,它会创建一个缓冲区大小的临时文件,并且由于 mem 映射文件的 java 实现,代码不会显式关闭文件。相反,我们调用 Linux 的 drop_caches 来强制未使用的内存映射刷新到磁盘。

  • 在 EXT4 上,这些文件会自动关闭并正确调整文件大小。
  • 在 BTRFS 上,这些文件保持约 16000 字节,并且丢失了一些数据(可能是分页问题)
  • 在 BTRFS 上,当我删除这些文件并且软件重新运行并再次创建文件时,每次都会出现相同的问题,并且修改的日期来自最初创建文件的时间

服务器信息: 我们在最新的 centos 7.2 上运行,并且是最新的补丁

  • 操作系统 Centos 7 x64(内核 3.10.0-514.10.2.el7.x86_64)
  • btrfs-progs v4.4.1
  • Java 1.8.0_111

进行的测试

  • 我们有一个在 Ext4 上运行的副本服务器,这个问题没有发生

  • 我们目前正在使用 COW 和压缩,所以我尝试禁用它们,重新启动,删除旧数据并重新启动软件。问题依旧出现

  • 我还尝试禁用space_cache,恢复,我还尝试使用flushoncommit设置commit = 5 ...这也无助于非关闭文件/不正确的修改日期
4

1 回答 1

1

并且由于 mem 映射文件的 java 实现,代码不会显式关闭文件。

这没有多大意义。文件支持的内存映射不要求它们的文件描述符保持打开状态。因此,您绝对可以在创建映射缓冲区后关闭文件。

相反,我们调用 Linux 的 drop_caches 来强制未使用的内存映射刷新到磁盘。

这是巨大的矫枉过正。

  1. 使用MappedByteBuffer::force将更改同步到磁盘
  2. 重命名临时文件
  3. fsync 重命名后必要的目录以实现崩溃持久性(请参阅下面的参考资料)。


try(FileChannel dir = FileChannel.open(Paths.get("/path/directory"), StandardOpenOptions.READ)) {
  dir.force(true);
}

于 2017-03-24T18:54:43.467 回答