2

after a lot of testing and digging around the BTRFS man pages i need help from some Linux / BTRFS folks.

I have a java application that writes data files to disk using the java MappedByteBuffer utility. This is application uses a byte buffer of ~16000 bytes when writing to disk. When a new file is being written to it creates a temp file of the buffer size and due to the java implementation of mem-mapped files the code does not explicitly close the file. Instead we call Linux's drop_caches to force unused memory maps to flush to disk.

  • On EXT4 these files are automatically closed and the filesize is adjusted correctly.
  • On BTRFS these files stay the ~16000 bytes and are missing some data (possibly paging issues)
  • On BTRFS when i delete these files and the software re-runs and creates the files again the same issue occurs each time AND the modified dates are from when the files were originally created

Server info: We are running on the latest centos 7.2 and are up to date with patches

  • OS Centos 7 x64 (Kernel 3.10.0-514.10.2.el7.x86_64)
  • btrfs-progs v4.4.1
  • Java 1.8.0_111

Testing performed

  • We have a replica server running on Ext4 and this issue is not happening

  • We are currently using COW and compression so i tried disabling them both, rebooting, deleting the old data and restarting the software. The issue still occurred

  • I have also tried disabling space_cache, recovery and i also tried setting commit=5 with flushoncommit ...this also didnt help the non closing files / the incorrect modified dates
NickGDev
  • 56
  • 4

1 Answers1

1

and due to the java implementation of mem-mapped files the code does not explicitly close the file.

That does not make much sense. file-backed memory mappings do not require their file descriptors to be kept open. So you absolutely can close the file after creating the mapped buffer.

Instead we call Linux's drop_caches to force unused memory maps to flush to disk.

That is massive overkill.

  1. use MappedByteBuffer::force to sync changes to disk
  2. rename tempfile
  3. fsync the directory necessary after renames for crash-durability (see references below).


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

the8472
  • 40,999
  • 5
  • 70
  • 122
  • 1
    Is it guaranteed that we can open directories as `ByteChannel`? – Holger Mar 25 '17 at 10:42
  • 1
    @Holger it's not guaranteed by the docs yet but it's required by unix semantics and when the ability was removed in the JDK9 development cycle there were complaints and thus the removal was reverted, so it'll probably be in the future. See https://bugs.openjdk.java.net/browse/JDK-8080629 – the8472 Mar 25 '17 at 15:15
  • @the8472 thanks for the detailed reply! The force option was something we considered but due to it's synchronous nature we decided not to implement it. I fully in agree the frequent drop_caches is overkill and we're working towards a better solution. – NickGDev Mar 27 '17 at 09:49
  • i suppose my main question is with BTRFS on Centos 7, does BTRFS handle memory mapped files differently from ext4 or is this a bug? (issues: files not closing correctly and old modified dates used when file is recreated) – NickGDev Mar 27 '17 at 09:53