summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorDaniel Verkamp <dverkamp@chromium.org>2019-11-08 10:11:16 -0800
committerCommit Bot <commit-bot@chromium.org>2019-11-18 09:30:58 +0000
commite73c80f355099a38293108baf0aed9666664a6e7 (patch)
treee325810bd77f52f6f525fe1255029e8d16e45982 /src
parent40a721b434f8bc59aac0010d5612ef3ac39f20c8 (diff)
downloadcrosvm-e73c80f355099a38293108baf0aed9666664a6e7.tar
crosvm-e73c80f355099a38293108baf0aed9666664a6e7.tar.gz
crosvm-e73c80f355099a38293108baf0aed9666664a6e7.tar.bz2
crosvm-e73c80f355099a38293108baf0aed9666664a6e7.tar.lz
crosvm-e73c80f355099a38293108baf0aed9666664a6e7.tar.xz
crosvm-e73c80f355099a38293108baf0aed9666664a6e7.tar.zst
crosvm-e73c80f355099a38293108baf0aed9666664a6e7.zip
devices: block: add option to control sparseness
Extend the --disk option and other related options to allow a particular
disk to have the sparse operations (virtio-blk's discard command)
enabled or disabled.

By default, the sparse flag will be enabled for virtio-blk devices,
matching current behavior.

BUG=chromium:858815
TEST=Run `crosvm with --rwdisk file.img,sparse=false` and try to discard

Change-Id: Ib72c949711fbe869a3f444d7f929a80d0e039f72
Signed-off-by: Daniel Verkamp <dverkamp@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/1906750
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Zach Reizner <zachr@chromium.org>
Diffstat (limited to 'src')
-rw-r--r--src/crosvm.rs1
-rw-r--r--src/linux.rs9
-rw-r--r--src/main.rs67
3 files changed, 66 insertions, 11 deletions
diff --git a/src/crosvm.rs b/src/crosvm.rs
index 649b0fe..c8b67bb 100644
--- a/src/crosvm.rs
+++ b/src/crosvm.rs
@@ -33,6 +33,7 @@ pub enum Executable {
 pub struct DiskOption {
     pub path: PathBuf,
     pub read_only: bool,
+    pub sparse: bool,
 }
 
 /// A bind mount for directories in the plugin process.
diff --git a/src/linux.rs b/src/linux.rs
index 1177377..25aba0f 100644
--- a/src/linux.rs
+++ b/src/linux.rs
@@ -358,8 +358,13 @@ fn create_block_device(
     flock(&raw_image, lock_op, true).map_err(Error::DiskImageLock)?;
 
     let disk_file = disk::create_disk_file(raw_image).map_err(Error::CreateDiskError)?;
-    let dev = virtio::Block::new(disk_file, disk.read_only, Some(disk_device_socket))
-        .map_err(Error::BlockDeviceNew)?;
+    let dev = virtio::Block::new(
+        disk_file,
+        disk.read_only,
+        disk.sparse,
+        Some(disk_device_socket),
+    )
+    .map_err(Error::BlockDeviceNew)?;
 
     Ok(VirtioDeviceStub {
         dev: Box::new(dev),
diff --git a/src/main.rs b/src/main.rs
index a864833..d6d82a5 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -299,11 +299,21 @@ fn set_argument(cfg: &mut Config, name: &str, value: Option<&str>) -> argument::
             cfg.syslog_tag = Some(value.unwrap().to_owned());
         }
         "root" | "rwroot" | "disk" | "rwdisk" | "qcow" | "rwqcow" => {
+            let param = value.unwrap();
+            let mut components = param.split(',');
             let read_only = !name.starts_with("rw");
-            let disk_path = PathBuf::from(value.unwrap());
+            let disk_path =
+                PathBuf::from(
+                    components
+                        .next()
+                        .ok_or_else(|| argument::Error::InvalidValue {
+                            value: param.to_owned(),
+                            expected: "missing disk path",
+                        })?,
+                );
             if !disk_path.exists() {
                 return Err(argument::Error::InvalidValue {
-                    value: value.unwrap().to_owned(),
+                    value: param.to_owned(),
                     expected: "this disk path does not exist",
                 });
             }
@@ -319,10 +329,42 @@ fn set_argument(cfg: &mut Config, name: &str, value: Option<&str>) -> argument::
                     if read_only { "ro" } else { "rw" }
                 ));
             }
-            cfg.disks.push(DiskOption {
+
+            let mut disk = DiskOption {
                 path: disk_path,
                 read_only,
-            });
+                sparse: true,
+            };
+
+            for opt in components {
+                let mut o = opt.splitn(2, '=');
+                let kind = o.next().ok_or_else(|| argument::Error::InvalidValue {
+                    value: opt.to_owned(),
+                    expected: "disk options must not be empty",
+                })?;
+                let value = o.next().ok_or_else(|| argument::Error::InvalidValue {
+                    value: opt.to_owned(),
+                    expected: "disk options must be of the form `kind=value`",
+                })?;
+
+                match kind {
+                    "sparse" => {
+                        let sparse = value.parse().map_err(|_| argument::Error::InvalidValue {
+                            value: value.to_owned(),
+                            expected: "`sparse` must be a boolean",
+                        })?;
+                        disk.sparse = sparse;
+                    }
+                    _ => {
+                        return Err(argument::Error::InvalidValue {
+                            value: kind.to_owned(),
+                            expected: "unrecognized disk option",
+                        });
+                    }
+                }
+            }
+
+            cfg.disks.push(disk);
         }
         "pmem-device" | "rw-pmem-device" => {
             let disk_path = PathBuf::from(value.unwrap());
@@ -336,6 +378,7 @@ fn set_argument(cfg: &mut Config, name: &str, value: Option<&str>) -> argument::
             cfg.pmem_devices.push(DiskOption {
                 path: disk_path,
                 read_only: !name.starts_with("rw"),
+                sparse: false,
             });
         }
         "host_ip" => {
@@ -726,12 +769,18 @@ fn run_vm(args: std::env::Args) -> std::result::Result<(), ()> {
                                 "Amount of guest memory in MiB. (default: 256)"),
           Argument::short_value('r',
                                 "root",
-                                "PATH",
-                                "Path to a root disk image. Like `--disk` but adds appropriate kernel command line option."),
-          Argument::value("rwroot", "PATH", "Path to a writable root disk image."),
-          Argument::short_value('d', "disk", "PATH", "Path to a disk image."),
+                                "PATH[,key=value[,key=value[,...]]",
+                                "Path to a root disk image followed by optional comma-separated options.
+                              Like `--disk` but adds appropriate kernel command line option.
+                              See --disk for valid options."),
+          Argument::value("rwroot", "PATH[,key=value[,key=value[,...]]", "Path to a writable root disk image followed by optional comma-separated options.
+                              See --disk for valid options."),
+          Argument::short_value('d', "disk", "PATH[,key=value[,key=value[,...]]", "Path to a disk image followed by optional comma-separated options.
+                              Valid keys:
+                              sparse=BOOL - Indicates whether the disk should support the discard operation (default: true)"),
           Argument::value("qcow", "PATH", "Path to a qcow2 disk image. (Deprecated; use --disk instead.)"),
-          Argument::value("rwdisk", "PATH", "Path to a writable disk image."),
+          Argument::value("rwdisk", "PATH[,key=value[,key=value[,...]]", "Path to a writable disk image followed by optional comma-separated options.
+                              See --disk for valid options."),
           Argument::value("rwqcow", "PATH", "Path to a writable qcow2 disk image. (Deprecated; use --rwdisk instead.)"),
           Argument::value("rw-pmem-device", "PATH", "Path to a writable disk image."),
           Argument::value("pmem-device", "PATH", "Path to a disk image."),