Skip to content

Commit

Permalink
Merge branch 'main' into feature/keep-dirty-memory-bitmaps-until-snap…
Browse files Browse the repository at this point in the history
…shot-is-made
  • Loading branch information
JonathanWoollett-Light committed Jan 19, 2024
2 parents be5e263 + 256e402 commit 11a2a5f
Show file tree
Hide file tree
Showing 8 changed files with 269 additions and 117 deletions.
34 changes: 34 additions & 0 deletions src/jailer/src/resource_limits.rs
Expand Up @@ -187,4 +187,38 @@ mod tests {
assert_eq!(rlim.rlim_cur, new_limit);
assert_eq!(rlim.rlim_max, new_limit);
}

#[test]
fn test_install() {
// Setup the resource limits
let mut rlimits = ResourceLimits::default();
let new_file_size_limit = 2097151;
let new_no_file_limit = 100;
rlimits.set_file_size(new_file_size_limit);
rlimits.set_no_file(new_no_file_limit);

// Install the new limits to file size and
// the number of file descriptors
rlimits.install().unwrap();

// Verify the new limit for file size
let file_size_resource = Resource::RlimitFsize;
let mut file_size_limit: libc::rlimit = libc::rlimit {
rlim_cur: 0,
rlim_max: 0,
};
unsafe { libc::getrlimit(file_size_resource.into(), &mut file_size_limit) };
assert_eq!(file_size_limit.rlim_cur, new_file_size_limit);
assert_eq!(file_size_limit.rlim_max, new_file_size_limit);

// Verify the new limit for the number of file descriptors
let file_descriptor_resource = Resource::RlimitNoFile;
let mut file_descriptor_limit: libc::rlimit = libc::rlimit {
rlim_cur: 0,
rlim_max: 0,
};
unsafe { libc::getrlimit(file_descriptor_resource.into(), &mut file_descriptor_limit) };
assert_eq!(file_descriptor_limit.rlim_cur, new_no_file_limit);
assert_eq!(file_descriptor_limit.rlim_max, new_no_file_limit);
}
}
28 changes: 23 additions & 5 deletions src/vmm/src/arch/aarch64/vcpu.rs
Expand Up @@ -153,12 +153,30 @@ pub fn get_registers(
/// Returns all registers ids, including core and system
pub fn get_all_registers_ids(vcpufd: &VcpuFd) -> Result<Vec<u64>, VcpuError> {
// Call KVM_GET_REG_LIST to get all registers available to the guest. For ArmV8 there are
// less than 500 registers.
// less than 500 registers expected, resize to the reported size when necessary.
let mut reg_list = RegList::new(500).map_err(VcpuError::Fam)?;
vcpufd
.get_reg_list(&mut reg_list)
.map_err(VcpuError::GetRegList)?;
Ok(reg_list.as_slice().to_vec())

match vcpufd.get_reg_list(&mut reg_list) {
Ok(_) => Ok(reg_list.as_slice().to_vec()),
Err(e) => match e.errno() {
libc::E2BIG => {
// resize and retry.
let size: usize = reg_list
.as_fam_struct_ref()
.n
.try_into()
// Safe to unwrap as Firecracker only targets 64-bit machines.
.unwrap();
reg_list = RegList::new(size).map_err(VcpuError::Fam)?;
vcpufd
.get_reg_list(&mut reg_list)
.map_err(VcpuError::GetRegList)?;

Ok(reg_list.as_slice().to_vec())
}
_ => Err(VcpuError::GetRegList(e)),
},
}
}

/// Set the state of the system registers.
Expand Down
63 changes: 42 additions & 21 deletions src/vmm/src/devices/virtio/balloon/event_handler.rs
@@ -1,8 +1,6 @@
// Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

use std::os::unix::io::AsRawFd;

use event_manager::{EventOps, Events, MutEventSubscriber};
use utils::epoll::EventSet;

Expand All @@ -12,25 +10,51 @@ use crate::devices::virtio::device::VirtioDevice;
use crate::logger::{error, warn};

impl Balloon {
const PROCESS_ACTIVATE: u32 = 0;
const PROCESS_VIRTQ_INFLATE: u32 = 1;
const PROCESS_VIRTQ_DEFLATE: u32 = 2;
const PROCESS_VIRTQ_STATS: u32 = 3;
const PROCESS_STATS_TIMER: u32 = 4;

fn register_runtime_events(&self, ops: &mut EventOps) {
if let Err(err) = ops.add(Events::new(&self.queue_evts[INFLATE_INDEX], EventSet::IN)) {
if let Err(err) = ops.add(Events::with_data(
&self.queue_evts[INFLATE_INDEX],
Self::PROCESS_VIRTQ_INFLATE,
EventSet::IN,
)) {
error!("Failed to register inflate queue event: {}", err);
}
if let Err(err) = ops.add(Events::new(&self.queue_evts[DEFLATE_INDEX], EventSet::IN)) {
if let Err(err) = ops.add(Events::with_data(
&self.queue_evts[DEFLATE_INDEX],
Self::PROCESS_VIRTQ_DEFLATE,
EventSet::IN,
)) {
error!("Failed to register deflate queue event: {}", err);
}
if self.stats_enabled() {
if let Err(err) = ops.add(Events::new(&self.queue_evts[STATS_INDEX], EventSet::IN)) {
if let Err(err) = ops.add(Events::with_data(
&self.queue_evts[STATS_INDEX],
Self::PROCESS_VIRTQ_STATS,
EventSet::IN,
)) {
error!("Failed to register stats queue event: {}", err);
}
if let Err(err) = ops.add(Events::new(&self.stats_timer, EventSet::IN)) {
if let Err(err) = ops.add(Events::with_data(
&self.stats_timer,
Self::PROCESS_STATS_TIMER,
EventSet::IN,
)) {
error!("Failed to register stats timerfd event: {}", err);
}
}
}

fn register_activate_event(&self, ops: &mut EventOps) {
if let Err(err) = ops.add(Events::new(&self.activate_evt, EventSet::IN)) {
if let Err(err) = ops.add(Events::with_data(
&self.activate_evt,
Self::PROCESS_ACTIVATE,
EventSet::IN,
)) {
error!("Failed to register activate event: {}", err);
}
}
Expand All @@ -40,15 +64,19 @@ impl Balloon {
error!("Failed to consume balloon activate event: {:?}", err);
}
self.register_runtime_events(ops);
if let Err(err) = ops.remove(Events::new(&self.activate_evt, EventSet::IN)) {
if let Err(err) = ops.remove(Events::with_data(
&self.activate_evt,
Self::PROCESS_ACTIVATE,
EventSet::IN,
)) {
error!("Failed to un-register activate event: {}", err);
}
}
}

impl MutEventSubscriber for Balloon {
fn process(&mut self, event: Events, ops: &mut EventOps) {
let source = event.fd();
let source = event.data();
let event_set = event.event_set();
let supported_events = EventSet::IN;

Expand All @@ -61,27 +89,20 @@ impl MutEventSubscriber for Balloon {
}

if self.is_activated() {
let virtq_inflate_ev_fd = self.queue_evts[INFLATE_INDEX].as_raw_fd();
let virtq_deflate_ev_fd = self.queue_evts[DEFLATE_INDEX].as_raw_fd();
let virtq_stats_ev_fd = self.queue_evts[STATS_INDEX].as_raw_fd();
let stats_timer_fd = self.stats_timer.as_raw_fd();
let activate_fd = self.activate_evt.as_raw_fd();

// Looks better than C style if/else if/else.
match source {
_ if source == virtq_inflate_ev_fd => self
Self::PROCESS_ACTIVATE => self.process_activate_event(ops),
Self::PROCESS_VIRTQ_INFLATE => self
.process_inflate_queue_event()
.unwrap_or_else(report_balloon_event_fail),
_ if source == virtq_deflate_ev_fd => self
Self::PROCESS_VIRTQ_DEFLATE => self
.process_deflate_queue_event()
.unwrap_or_else(report_balloon_event_fail),
_ if source == virtq_stats_ev_fd => self
Self::PROCESS_VIRTQ_STATS => self
.process_stats_queue_event()
.unwrap_or_else(report_balloon_event_fail),
_ if source == stats_timer_fd => self
Self::PROCESS_STATS_TIMER => self
.process_stats_timer_event()
.unwrap_or_else(report_balloon_event_fail),
_ if activate_fd == source => self.process_activate_event(ops),
_ => {
warn!("Balloon: Spurious event received: {:?}", source);
}
Expand Down
70 changes: 46 additions & 24 deletions src/vmm/src/devices/virtio/net/event_handler.rs
@@ -1,8 +1,6 @@
// Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

use std::os::unix::io::AsRawFd;

use event_manager::{EventOps, Events, MutEventSubscriber};
use utils::epoll::EventSet;

Expand All @@ -12,29 +10,57 @@ use crate::devices::virtio::net::{RX_INDEX, TX_INDEX};
use crate::logger::{error, warn, IncMetric};

impl Net {
const PROCESS_ACTIVATE: u32 = 0;
const PROCESS_VIRTQ_RX: u32 = 1;
const PROCESS_VIRTQ_TX: u32 = 2;
const PROCESS_TAP_RX: u32 = 3;
const PROCESS_RX_RATE_LIMITER: u32 = 4;
const PROCESS_TX_RATE_LIMITER: u32 = 5;

fn register_runtime_events(&self, ops: &mut EventOps) {
if let Err(err) = ops.add(Events::new(&self.queue_evts[RX_INDEX], EventSet::IN)) {
if let Err(err) = ops.add(Events::with_data(
&self.queue_evts[RX_INDEX],
Self::PROCESS_VIRTQ_RX,
EventSet::IN,
)) {
error!("Failed to register rx queue event: {}", err);
}
if let Err(err) = ops.add(Events::new(&self.queue_evts[TX_INDEX], EventSet::IN)) {
if let Err(err) = ops.add(Events::with_data(
&self.queue_evts[TX_INDEX],
Self::PROCESS_VIRTQ_TX,
EventSet::IN,
)) {
error!("Failed to register tx queue event: {}", err);
}
if let Err(err) = ops.add(Events::new(&self.rx_rate_limiter, EventSet::IN)) {
if let Err(err) = ops.add(Events::with_data(
&self.rx_rate_limiter,
Self::PROCESS_RX_RATE_LIMITER,
EventSet::IN,
)) {
error!("Failed to register rx queue event: {}", err);
}
if let Err(err) = ops.add(Events::new(&self.tx_rate_limiter, EventSet::IN)) {
if let Err(err) = ops.add(Events::with_data(
&self.tx_rate_limiter,
Self::PROCESS_TX_RATE_LIMITER,
EventSet::IN,
)) {
error!("Failed to register tx queue event: {}", err);
}
if let Err(err) = ops.add(Events::new(
if let Err(err) = ops.add(Events::with_data(
&self.tap,
Self::PROCESS_TAP_RX,
EventSet::IN | EventSet::EDGE_TRIGGERED,
)) {
error!("Failed to register tap event: {}", err);
}
}

fn register_activate_event(&self, ops: &mut EventOps) {
if let Err(err) = ops.add(Events::new(&self.activate_evt, EventSet::IN)) {
if let Err(err) = ops.add(Events::with_data(
&self.activate_evt,
Self::PROCESS_ACTIVATE,
EventSet::IN,
)) {
error!("Failed to register activate event: {}", err);
}
}
Expand All @@ -44,15 +70,19 @@ impl Net {
error!("Failed to consume net activate event: {:?}", err);
}
self.register_runtime_events(ops);
if let Err(err) = ops.remove(Events::new(&self.activate_evt, EventSet::IN)) {
if let Err(err) = ops.remove(Events::with_data(
&self.activate_evt,
Self::PROCESS_ACTIVATE,
EventSet::IN,
)) {
error!("Failed to un-register activate event: {}", err);
}
}
}

impl MutEventSubscriber for Net {
fn process(&mut self, event: Events, ops: &mut EventOps) {
let source = event.fd();
let source = event.data();
let event_set = event.event_set();

// TODO: also check for errors. Pending high level discussions on how we want
Expand All @@ -67,21 +97,13 @@ impl MutEventSubscriber for Net {
}

if self.is_activated() {
let virtq_rx_ev_fd = self.queue_evts[RX_INDEX].as_raw_fd();
let virtq_tx_ev_fd = self.queue_evts[TX_INDEX].as_raw_fd();
let rx_rate_limiter_fd = self.rx_rate_limiter.as_raw_fd();
let tx_rate_limiter_fd = self.tx_rate_limiter.as_raw_fd();
let tap_fd = self.tap.as_raw_fd();
let activate_fd = self.activate_evt.as_raw_fd();

// Looks better than C style if/else if/else.
match source {
_ if source == virtq_rx_ev_fd => self.process_rx_queue_event(),
_ if source == tap_fd => self.process_tap_rx_event(),
_ if source == virtq_tx_ev_fd => self.process_tx_queue_event(),
_ if source == rx_rate_limiter_fd => self.process_rx_rate_limiter_event(),
_ if source == tx_rate_limiter_fd => self.process_tx_rate_limiter_event(),
_ if activate_fd == source => self.process_activate_event(ops),
Self::PROCESS_ACTIVATE => self.process_activate_event(ops),
Self::PROCESS_VIRTQ_RX => self.process_rx_queue_event(),
Self::PROCESS_VIRTQ_TX => self.process_tx_queue_event(),
Self::PROCESS_TAP_RX => self.process_tap_rx_event(),
Self::PROCESS_RX_RATE_LIMITER => self.process_rx_rate_limiter_event(),
Self::PROCESS_TX_RATE_LIMITER => self.process_tx_rate_limiter_event(),
_ => {
warn!("Net: Spurious event received: {:?}", source);
self.metrics.event_fails.inc();
Expand Down

0 comments on commit 11a2a5f

Please sign in to comment.