Flush data to instance disk using BLKFLSBUF

Previously, we used fsync which works only for file descriptors that
are not by page cache. Since the instance disk is directly opened as a
block device, fsync didn't work. Fixing the issue by using BLKFLSBUF
instead.

Bug: 208639280
Test: atest MicrodroidTestApp
Change-Id: I782bc9d1d59d302fedecc72f471abde601162830
diff --git a/microdroid_manager/src/instance.rs b/microdroid_manager/src/instance.rs
index f3bbf16..4d65421 100644
--- a/microdroid_manager/src/instance.rs
+++ b/microdroid_manager/src/instance.rs
@@ -33,6 +33,8 @@
 //! The payload of a partition is encrypted/signed by a key that is unique to the loader and to the
 //! VM as well. Failing to decrypt/authenticate a partition by a loader stops the boot process.
 
+use crate::ioutil;
+
 use android_security_dice::aidl::android::security::dice::IDiceNode::IDiceNode;
 use anyhow::{anyhow, bail, Context, Result};
 use binder::wait_for_interface;
@@ -180,7 +182,7 @@
 
         // Persist the encrypted payload data
         self.file.write_all(&data)?;
-        self.file.flush()?;
+        ioutil::blkflsbuf(&mut self.file)?;
 
         Ok(())
     }
diff --git a/microdroid_manager/src/ioutil.rs b/microdroid_manager/src/ioutil.rs
index 8ab2413..8ac3712 100644
--- a/microdroid_manager/src/ioutil.rs
+++ b/microdroid_manager/src/ioutil.rs
@@ -14,11 +14,13 @@
 
 //! IO utilities
 
-use anyhow::{anyhow, Result};
+use anyhow::{anyhow, bail, Result};
 use log::debug;
 use std::fmt::Debug;
 use std::fs::File;
 use std::io;
+use std::os::unix::fs::FileTypeExt;
+use std::os::unix::io::AsRawFd;
 use std::path::Path;
 use std::thread;
 use std::time::{Duration, Instant};
@@ -45,6 +47,20 @@
     }
 }
 
+// From include/uapi/linux/fs.h
+const BLK: u8 = 0x12;
+const BLKFLSBUF: u8 = 97;
+nix::ioctl_none!(_blkflsbuf, BLK, BLKFLSBUF);
+
+pub fn blkflsbuf(f: &mut File) -> Result<()> {
+    if !f.metadata()?.file_type().is_block_device() {
+        bail!("{:?} is not a block device", f.as_raw_fd());
+    }
+    // SAFETY: The file is kept open until the end of this function.
+    unsafe { _blkflsbuf(f.as_raw_fd()) }?;
+    Ok(())
+}
+
 #[cfg(test)]
 mod tests {
     use super::*;