title: file mapping vs file system synchronization
body: <p>I have a file with some data, which is also memory-mapped. So that I have both file descriptor and the pointer to the mapped pages. Mostly the data is only read from the mapping, but eventually it's also modified. </p>
  
  <p>The modification consists of modifying some data within the file (sort of headers update), plus appending some new data (i.e. writing post the current end of the file).</p>
  
  <p>This data structure is accessed from different threads, and to prevent collisions I synchronize access to it (mutex and friends).</p>
  
  <p>During the modification I use both the file mapping and the file descriptor. Headers are updated implicitly by modifying the mapped memory, whereas the new data is written to the file by the appropriate API (<code>WriteFile</code> on windows, <code>write</code> on posix). Worth to note that the new data and the headers belong to different pages.</p>
  
  <p>Since the modification changes the file size, the memory mapping is re-initialized after every such a modification. That is, it's unmapped, and then mapped again (with the new size).</p>
  
  <p>I realize that writes to the mapped memory are "asynchronous" wrt file system, and order is not guaranteed, but I thought there was no problem because I explicitly close the file mapping, which should (IMHO) act as a sort of a flushing point.</p>
  
  <p>Now this works without problem on windows, but on linux (android to be exact) eventually the mapped data turns-out to be inconsistent temporarily (i.e. data is ok when retrying). Seems like it doesn't reflect the newly-appended data.</p>
  
  <p>Do I have to call some synchronization API to ensure the data if flushed properly? If so, which one should I use: <code>sync</code>, <code>msync</code>, <code>syncfs</code> or something different?</p>
  
  <p>Thanks in advance.</p>
  
  <p><strong>EDIT:</strong></p>
  
  <p>This is a pseudo-code that illustrates the scenario I'm dealing with.
  (The real code is more complex of course)</p>
  
  <pre><code>struct CompressedGrid
  {
      mutex m_Lock;
      int m_FileHandle;    
      void* m_pMappedMemory;
  
      Hdr* get_Hdr() { return /* the mapped memory with some offset*/; }
  
      void SaveGridCell(int idx, const Cell&amp; cCompressed)
      {
          AutoLock scope(m_Lock);
  
          // Write to mapped memory
          get_Hdr()-&gt;m_pCellOffset[Idx] = /* current end of file */;
  
          // Append the data
          lseek64(m_FileHandle, 0, FILE_END);
          write(m_FileHandle, cCompressed.pPtr, cCompressed.nSize);
  
          // re-map
          munmap(...);
          m_pMappedMemory = mmap(...); // specify the new file size of course
      }
  
      bool DecodeGridCell(int idx, Cell&amp; cRaw)
      {
          AutoLock scope(m_Lock);
  
          uint64_t nOffs = get_Hdr()-&gt;m_pCellOffset[Idx] = /* ;
          if (!nOffs)
              return false; // unavail
  
          const uint8_t* p = m_pMappedMemory + nOffs;
  
          cRaw.DecodeFrom(p); // This is where the problem appears!
  
          return true;
      }
  </code></pre>