summary refs log tree commit diff
path: root/devices/src/virtio/block.rs
diff options
context:
space:
mode:
authorDaniel Verkamp <dverkamp@chromium.org>2018-08-09 16:27:44 -0700
committerchrome-bot <chrome-bot@chromium.org>2018-08-13 21:58:42 -0700
commit70589a0797115b3df7d42de132f0247ee7727f5d (patch)
tree6eff12da6d5ce2eab928f7a813e1ec13b9c6b43c /devices/src/virtio/block.rs
parent18fa20569fff7fffcc7e62a37b217be00830be13 (diff)
downloadcrosvm-70589a0797115b3df7d42de132f0247ee7727f5d.tar
crosvm-70589a0797115b3df7d42de132f0247ee7727f5d.tar.gz
crosvm-70589a0797115b3df7d42de132f0247ee7727f5d.tar.bz2
crosvm-70589a0797115b3df7d42de132f0247ee7727f5d.tar.lz
crosvm-70589a0797115b3df7d42de132f0247ee7727f5d.tar.xz
crosvm-70589a0797115b3df7d42de132f0247ee7727f5d.tar.zst
crosvm-70589a0797115b3df7d42de132f0247ee7727f5d.zip
devices: block: add support for read-only feature
The virtio block specification defines the VIRTIO_BLK_F_RO feature bit
to indicate read-only block devices.  Plumb the read-only status of
block devices from the crosvm frontend into the virtio block device and
populate the flag when appropriate.

BUG=chromium:872973
TEST=Verify lsblk output in guest has the correct RO values

Change-Id: I23af87cce8020641cd702adca6e8ff9fdd2b8220
Signed-off-by: Daniel Verkamp <dverkamp@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/1170306
Reviewed-by: Zach Reizner <zachr@chromium.org>
Diffstat (limited to 'devices/src/virtio/block.rs')
-rw-r--r--devices/src/virtio/block.rs28
1 files changed, 22 insertions, 6 deletions
diff --git a/devices/src/virtio/block.rs b/devices/src/virtio/block.rs
index 83616ce..ee4528b 100644
--- a/devices/src/virtio/block.rs
+++ b/devices/src/virtio/block.rs
@@ -28,6 +28,7 @@ const VIRTIO_BLK_S_OK: u8 = 0;
 const VIRTIO_BLK_S_IOERR: u8 = 1;
 const VIRTIO_BLK_S_UNSUPP: u8 = 2;
 
+const VIRTIO_BLK_F_RO: u32 = 5;
 const VIRTIO_BLK_F_FLUSH: u32 = 9;
 
 pub trait DiskFile: Read + Seek + Write {}
@@ -345,6 +346,7 @@ pub struct Block<T: DiskFile> {
     disk_image: Option<T>,
     config_space: Vec<u8>,
     avail_features: u64,
+    read_only: bool,
 }
 
 fn build_config_space(disk_size: u64) -> Vec<u8> {
@@ -363,7 +365,7 @@ impl<T: DiskFile> Block<T> {
     /// Create a new virtio block device that operates on the given file.
     ///
     /// The given file must be seekable and sizable.
-    pub fn new(mut disk_image: T) -> SysResult<Block<T>> {
+    pub fn new(mut disk_image: T, read_only: bool) -> SysResult<Block<T>> {
         let disk_size = disk_image.seek(SeekFrom::End(0))? as u64;
         if disk_size % SECTOR_SIZE != 0 {
             warn!("Disk size {} is not a multiple of sector size {}; \
@@ -373,12 +375,16 @@ impl<T: DiskFile> Block<T> {
         }
 
         let mut avail_features: u64 = 1 << VIRTIO_BLK_F_FLUSH;
+        if read_only {
+            avail_features |= 1 << VIRTIO_BLK_F_RO;
+        }
 
         Ok(Block {
                kill_evt: None,
                disk_image: Some(disk_image),
                config_space: build_config_space(disk_size),
                avail_features,
+               read_only,
            })
     }
 }
@@ -489,7 +495,7 @@ mod tests {
         let f = File::create(&path).unwrap();
         f.set_len(0x1000).unwrap();
 
-        let b = Block::new(f).unwrap();
+        let b = Block::new(f, true).unwrap();
         let mut num_sectors = [0u8; 4];
         b.read_config(0, &mut num_sectors);
         // size is 0x1000, so num_sectors is 8 (4096/512).
@@ -506,10 +512,20 @@ mod tests {
         let mut path = PathBuf::from(tempdir.as_path().unwrap());
         path.push("disk_image");
 
-        let f = File::create(&path).unwrap();
-        let b = Block::new(f).unwrap();
+        // read-write block device
+        {
+            let f = File::create(&path).unwrap();
+            let b = Block::new(f, false).unwrap();
+            // writable device should just set VIRTIO_BLK_F_FLUSH
+            assert_eq!(0x200, b.features(0));
+        }
 
-        // VIRTIO_BLK_F_FLUSH should always be set
-        assert_eq!(0x200, b.features(0));
+        // read-only block device
+        {
+            let f = File::create(&path).unwrap();
+            let b = Block::new(f, true).unwrap();
+            // read-only device should set VIRTIO_BLK_F_FLUSH and VIRTIO_BLK_F_RO
+            assert_eq!(0x220, b.features(0));
+        }
     }
 }