Skip to content

Commit 4468055

Browse files
acatangiuiulianbarbu
authored andcommitted
devices: block: activate through an activation event
Postpone block external events registration to device activation time. This makes the block device unaware of external events prior to its activation. During creation register a dedicated activation event which will notify the device when it's time to register the other external events sources. This activation event is unregistered after successful device activation. Signed-off-by: Adrian Catangiu <acatan@amazon.com>
1 parent 6b2c817 commit 4468055

File tree

5 files changed

+192
-50
lines changed

5 files changed

+192
-50
lines changed

src/devices/src/virtio/block/device.rs

Lines changed: 41 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use virtio_gen::virtio_blk::*;
2121
use vm_memory::{Bytes, GuestMemoryMmap};
2222

2323
use super::{
24-
super::{ActivateResult, Queue, VirtioDevice, TYPE_BLOCK, VIRTIO_MMIO_INT_VRING},
24+
super::{ActivateResult, DeviceState, Queue, VirtioDevice, TYPE_BLOCK, VIRTIO_MMIO_INT_VRING},
2525
request::*,
2626
Error, CONFIG_SPACE_SIZE, QUEUE_SIZES, SECTOR_SHIFT, SECTOR_SIZE,
2727
};
@@ -88,15 +88,15 @@ pub struct Block {
8888
avail_features: u64,
8989
acked_features: u64,
9090
config_space: Vec<u8>,
91+
pub(crate) activate_evt: EventFd,
9192

9293
// Transport related fields.
9394
queues: Vec<Queue>,
9495
interrupt_status: Arc<AtomicUsize>,
9596
interrupt_evt: EventFd,
9697
pub(crate) queue_evts: [EventFd; 1],
97-
mem: GuestMemoryMmap,
9898

99-
device_activated: bool,
99+
pub(crate) device_state: DeviceState,
100100

101101
// Implementation specific fields.
102102
pub(crate) rate_limiter: RateLimiter,
@@ -107,7 +107,6 @@ impl Block {
107107
///
108108
/// The given file must be seekable and sizable.
109109
pub fn new(
110-
mem: GuestMemoryMmap,
111110
mut disk_image: File,
112111
is_disk_read_only: bool,
113112
rate_limiter: RateLimiter,
@@ -132,12 +131,12 @@ impl Block {
132131
acked_features: 0u64,
133132
config_space: build_config_space(disk_size),
134133
rate_limiter,
135-
mem,
136134
interrupt_status: Arc::new(AtomicUsize::new(0)),
137135
interrupt_evt: EventFd::new(libc::EFD_NONBLOCK)?,
138136
queue_evts,
139137
queues,
140-
device_activated: false,
138+
device_state: DeviceState::Inactive,
139+
activate_evt: EventFd::new(libc::EFD_NONBLOCK)?,
141140
})
142141
}
143142

@@ -161,11 +160,16 @@ impl Block {
161160
}
162161

163162
pub(crate) fn process_queue(&mut self, queue_index: usize) -> bool {
163+
let mem = match self.device_state {
164+
DeviceState::Activated(ref mem) => mem,
165+
// This should never happen, it's been already validated in the event handler.
166+
DeviceState::Inactive => unreachable!(),
167+
};
164168
let queue = &mut self.queues[queue_index];
165169
let mut used_any = false;
166-
while let Some(head) = queue.pop(&self.mem) {
170+
while let Some(head) = queue.pop(mem) {
167171
let len;
168-
match Request::parse(&head, &self.mem) {
172+
match Request::parse(&head, mem) {
169173
Ok(request) => {
170174
// If limiter.consume() fails it means there is no more TokenType::Ops
171175
// budget and rate limiting is in effect.
@@ -196,7 +200,7 @@ impl Block {
196200
let status = match request.execute(
197201
&mut self.disk_image,
198202
self.disk_nsectors,
199-
&self.mem,
203+
mem,
200204
&self.disk_image_id,
201205
) {
202206
Ok(l) => {
@@ -212,15 +216,15 @@ impl Block {
212216
};
213217
// We use unwrap because the request parsing process already checked that the
214218
// status_addr was valid.
215-
self.mem.write_obj(status, request.status_addr).unwrap();
219+
mem.write_obj(status, request.status_addr).unwrap();
216220
}
217221
Err(e) => {
218222
error!("Failed to parse available descriptor chain: {:?}", e);
219223
METRICS.block.execute_fails.inc();
220224
len = 0;
221225
}
222226
}
223-
queue.add_used(&self.mem, head.index, len);
227+
queue.add_used(mem, head.index, len);
224228
used_any = true;
225229
}
226230

@@ -318,17 +322,24 @@ impl VirtioDevice for Block {
318322
}
319323

320324
fn is_activated(&self) -> bool {
321-
self.device_activated
325+
match self.device_state {
326+
DeviceState::Inactive => false,
327+
DeviceState::Activated(_) => true,
328+
}
322329
}
323330

324-
fn activate(&mut self, _: GuestMemoryMmap) -> ActivateResult {
325-
self.device_activated = true;
331+
fn activate(&mut self, mem: GuestMemoryMmap) -> ActivateResult {
332+
if self.activate_evt.write(1).is_err() {
333+
error!("Block: Cannot write to activate_evt");
334+
return Err(super::super::ActivateError::BadActivate);
335+
}
336+
self.device_state = DeviceState::Activated(mem);
326337
Ok(())
327338
}
328339
}
329340

330341
#[cfg(test)]
331-
mod tests {
342+
pub(crate) mod tests {
332343
use std::fs::metadata;
333344
use std::os::unix::io::AsRawFd;
334345
use std::thread;
@@ -352,7 +363,7 @@ mod tests {
352363
}
353364

354365
impl Block {
355-
fn set_queue(&mut self, idx: usize, q: Queue) {
366+
pub(crate) fn set_queue(&mut self, idx: usize, q: Queue) {
356367
self.queues[idx] = q;
357368
}
358369

@@ -366,7 +377,7 @@ mod tests {
366377
}
367378

368379
/// Create a default Block instance to be used in tests.
369-
fn default_block() -> Block {
380+
pub fn default_block() -> Block {
370381
// Create backing file.
371382
let f = TempFile::new().unwrap();
372383
let block_file = f.into_file();
@@ -375,12 +386,14 @@ mod tests {
375386
// Rate limiting is enabled but with a high operation rate (10 million ops/s).
376387
let rate_limiter = RateLimiter::new(0, None, 0, 100_000, None, 10).unwrap();
377388

378-
let mem = GuestMemoryMmap::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
389+
Block::new(block_file, true, rate_limiter).unwrap()
390+
}
379391

380-
Block::new(mem, block_file, true, rate_limiter).unwrap()
392+
pub fn default_mem() -> GuestMemoryMmap {
393+
GuestMemoryMmap::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap()
381394
}
382395

383-
fn initialize_virtqueue(vq: &VirtQueue) {
396+
pub fn initialize_virtqueue(vq: &VirtQueue) {
384397
let request_type_desc: usize = 0;
385398
let data_desc: usize = 1;
386399
let status_desc: usize = 2;
@@ -496,7 +509,7 @@ mod tests {
496509
#[test]
497510
fn test_invalid_request() {
498511
let mut block = default_block();
499-
let mem = block.mem.clone();
512+
let mem = default_mem();
500513
let vq = VirtQueue::new(GuestAddress(0), &mem, 16);
501514
block.set_queue(0, vq.create_queue());
502515
block.activate(mem.clone()).unwrap();
@@ -521,7 +534,7 @@ mod tests {
521534
#[test]
522535
fn test_request_execute_failures() {
523536
let mut block = default_block();
524-
let mem = block.mem.clone();
537+
let mem = default_mem();
525538
let vq = VirtQueue::new(GuestAddress(0), &mem, 16);
526539
block.set_queue(0, vq.create_queue());
527540
block.activate(mem.clone()).unwrap();
@@ -579,7 +592,7 @@ mod tests {
579592
#[test]
580593
fn test_unsupported_request_type() {
581594
let mut block = default_block();
582-
let mem = block.mem.clone();
595+
let mem = default_mem();
583596
let vq = VirtQueue::new(GuestAddress(0), &mem, 16);
584597
block.set_queue(0, vq.create_queue());
585598
block.activate(mem.clone()).unwrap();
@@ -609,7 +622,7 @@ mod tests {
609622
#[test]
610623
fn test_read_write() {
611624
let mut block = default_block();
612-
let mem = block.mem.clone();
625+
let mem = default_mem();
613626
let vq = VirtQueue::new(GuestAddress(0), &mem, 16);
614627
block.set_queue(0, vq.create_queue());
615628
block.activate(mem.clone()).unwrap();
@@ -668,7 +681,7 @@ mod tests {
668681
#[test]
669682
fn test_flush() {
670683
let mut block = default_block();
671-
let mem = block.mem.clone();
684+
let mem = default_mem();
672685
let vq = VirtQueue::new(GuestAddress(0), &mem, 16);
673686
block.set_queue(0, vq.create_queue());
674687
block.activate(mem.clone()).unwrap();
@@ -711,7 +724,7 @@ mod tests {
711724
#[test]
712725
fn test_get_device_id() {
713726
let mut block = default_block();
714-
let mem = block.mem.clone();
727+
let mem = default_mem();
715728
let vq = VirtQueue::new(GuestAddress(0), &mem, 16);
716729
block.set_queue(0, vq.create_queue());
717730
block.activate(mem.clone()).unwrap();
@@ -777,7 +790,7 @@ mod tests {
777790
#[test]
778791
fn test_bandwidth_rate_limiter() {
779792
let mut block = default_block();
780-
let mem = block.mem.clone();
793+
let mem = default_mem();
781794
let vq = VirtQueue::new(GuestAddress(0), &mem, 16);
782795
block.set_queue(0, vq.create_queue());
783796
block.activate(mem.clone()).unwrap();
@@ -842,7 +855,7 @@ mod tests {
842855
#[test]
843856
fn test_ops_rate_limiter() {
844857
let mut block = default_block();
845-
let mem = block.mem.clone();
858+
let mem = default_mem();
846859
let vq = VirtQueue::new(GuestAddress(0), &mem, 16);
847860
block.set_queue(0, vq.create_queue());
848861
block.activate(mem.clone()).unwrap();

0 commit comments

Comments
 (0)