vmm: Add a "discard_writes=" to --pmem

This opens the backing file read-only, makes the pages in the mmap()
read-only and also makes the KVM mapping read-only. The file is also
mapped with MAP_PRIVATE to make the changes local to this process only.

This is functional alternative to having support for making a
virtio-pmem device readonly. Unfortunately there is no concept of
readonly virtio-pmem (or any type of NVDIMM/PMEM) in the Linux kernel so
to be able to have a block device that is appears readonly in the guest
requires significant specification and kernel changes.

Signed-off-by: Rob Bradford <robert.bradford@intel.com>
This commit is contained in:
Rob Bradford 2020-03-19 10:13:53 +00:00 committed by Sebastien Boeuf
parent d11a67b0fe
commit f7197e8415
4 changed files with 20 additions and 6 deletions

View File

@ -173,7 +173,7 @@ fn create_app<'a, 'b>(
.help( .help(
"Persistent memory parameters \ "Persistent memory parameters \
\"file=<backing_file_path>,size=<persistent_memory_size>,iommu=on|off,\ \"file=<backing_file_path>,size=<persistent_memory_size>,iommu=on|off,\
mergeable=on|off\"", mergeable=on|off,discard_writes=on|off,\"",
) )
.takes_value(true) .takes_value(true)
.min_values(1) .min_values(1)

View File

@ -410,6 +410,9 @@ components:
mergeable: mergeable:
type: boolean type: boolean
default: false default: false
discard_writes:
type: boolean
default: false
ConsoleConfig: ConsoleConfig:
required: required:

View File

@ -766,6 +766,8 @@ pub struct PmemConfig {
pub iommu: bool, pub iommu: bool,
#[serde(default)] #[serde(default)]
pub mergeable: bool, pub mergeable: bool,
#[serde(default)]
pub discard_writes: bool,
} }
impl PmemConfig { impl PmemConfig {
@ -777,6 +779,7 @@ impl PmemConfig {
let mut size_str: &str = ""; let mut size_str: &str = "";
let mut iommu_str: &str = ""; let mut iommu_str: &str = "";
let mut mergeable_str: &str = ""; let mut mergeable_str: &str = "";
let mut discard_writes_str: &str = "";
for param in params_list.iter() { for param in params_list.iter() {
if param.starts_with("file=") { if param.starts_with("file=") {
@ -787,6 +790,8 @@ impl PmemConfig {
iommu_str = &param[6..]; iommu_str = &param[6..];
} else if param.starts_with("mergeable=") { } else if param.starts_with("mergeable=") {
mergeable_str = &param[10..]; mergeable_str = &param[10..];
} else if param.starts_with("discard_writes=") {
discard_writes_str = &param[15..];
} }
} }
@ -799,6 +804,7 @@ impl PmemConfig {
size: parse_size(size_str)?, size: parse_size(size_str)?,
iommu: parse_on_off(iommu_str)?, iommu: parse_on_off(iommu_str)?,
mergeable: parse_on_off(mergeable_str)?, mergeable: parse_on_off(mergeable_str)?,
discard_writes: parse_on_off(discard_writes_str)?,
}) })
} }
} }

View File

@ -27,7 +27,7 @@ use arch::layout::{APIC_START, IOAPIC_SIZE, IOAPIC_START};
use devices::{ioapic, BusDevice, HotPlugNotificationFlags}; use devices::{ioapic, BusDevice, HotPlugNotificationFlags};
use kvm_ioctls::*; use kvm_ioctls::*;
use libc::TIOCGWINSZ; use libc::TIOCGWINSZ;
use libc::{MAP_NORESERVE, MAP_SHARED, O_RDONLY, O_TMPFILE, PROT_READ, PROT_WRITE}; use libc::{MAP_NORESERVE, MAP_PRIVATE, MAP_SHARED, O_TMPFILE, PROT_READ, PROT_WRITE};
#[cfg(feature = "pci_support")] #[cfg(feature = "pci_support")]
use pci::{ use pci::{
DeviceRelocation, PciBarRegionType, PciBus, PciConfigIo, PciConfigMmio, PciDevice, PciRoot, DeviceRelocation, PciBarRegionType, PciBus, PciConfigIo, PciConfigMmio, PciDevice, PciRoot,
@ -1392,7 +1392,7 @@ impl DeviceManager {
let file = OpenOptions::new() let file = OpenOptions::new()
.read(true) .read(true)
.write(true) .write(!pmem_cfg.discard_writes)
.custom_flags(custom_flags) .custom_flags(custom_flags)
.open(&pmem_cfg.file) .open(&pmem_cfg.file)
.map_err(DeviceManagerError::PmemFileOpen)?; .map_err(DeviceManagerError::PmemFileOpen)?;
@ -1406,12 +1406,17 @@ impl DeviceManager {
let mmap_region = MmapRegion::build( let mmap_region = MmapRegion::build(
Some(FileOffset::new(cloned_file, 0)), Some(FileOffset::new(cloned_file, 0)),
size as usize, size as usize,
if pmem_cfg.readonly { if pmem_cfg.discard_writes {
PROT_READ PROT_READ
} else { } else {
PROT_READ | PROT_WRITE PROT_READ | PROT_WRITE
}, },
MAP_NORESERVE | MAP_SHARED, MAP_NORESERVE
| if pmem_cfg.discard_writes {
MAP_PRIVATE
} else {
MAP_SHARED
},
) )
.map_err(DeviceManagerError::NewMmapRegion)?; .map_err(DeviceManagerError::NewMmapRegion)?;
let addr: u64 = mmap_region.as_ptr() as u64; let addr: u64 = mmap_region.as_ptr() as u64;
@ -1426,7 +1431,7 @@ impl DeviceManager {
size, size,
addr, addr,
pmem_cfg.mergeable, pmem_cfg.mergeable,
false, pmem_cfg.discard_writes,
) )
.map_err(DeviceManagerError::MemoryManager)?; .map_err(DeviceManagerError::MemoryManager)?;