Skip to content

Commit 6b74e51

Browse files
committed
virtio-blk: reuse request fields for discard range
Store the validated discard byte offset and length in the existing Request fields instead of carrying a separate discard range. Signed-off-by: Jonas Savulionis <jonas@esnet.lt>
1 parent 560d2f8 commit 6b74e51

2 files changed

Lines changed: 27 additions & 21 deletions

File tree

src/vmm/src/devices/virtio/block/virtio/io/sync_io.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ pub(super) fn discard_file(file: &File, range: (u64, u64)) -> Result<u32, std::i
4343
if len == 0 {
4444
return Ok(0);
4545
}
46+
let discarded = u32::try_from(len).map_err(|_| {
47+
std::io::Error::new(std::io::ErrorKind::InvalidInput, "discard length overflow")
48+
})?;
4649

4750
if file_type.is_block_device() {
4851
let mut range = [offset, len];
@@ -73,7 +76,7 @@ pub(super) fn discard_file(file: &File, range: (u64, u64)) -> Result<u32, std::i
7376
}
7477
}
7578

76-
Ok(u32::try_from(len).unwrap_or(u32::MAX))
79+
Ok(discarded)
7780
}
7881

7982
impl SyncFileEngine {

src/vmm/src/devices/virtio/block/virtio/request.rs

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use std::mem::size_of;
1010

1111
use vm_memory::GuestMemoryError;
1212

13-
use super::{MAX_DISCARD_SECTORS, SECTOR_SHIFT, SECTOR_SIZE, VirtioBlockError, io as block_io};
13+
use super::{io as block_io, VirtioBlockError, MAX_DISCARD_SECTORS, SECTOR_SHIFT, SECTOR_SIZE};
1414
use crate::devices::virtio::block::virtio::device::DiskProperties;
1515
use crate::devices::virtio::block::virtio::metrics::BlockDeviceMetrics;
1616
pub use crate::devices::virtio::generated::virtio_blk::{
@@ -19,7 +19,7 @@ pub use crate::devices::virtio::generated::virtio_blk::{
1919
VIRTIO_BLK_T_OUT,
2020
};
2121
use crate::devices::virtio::queue::DescriptorChain;
22-
use crate::logger::{IncMetric, error};
22+
use crate::logger::{error, IncMetric};
2323
use crate::rate_limiter::{RateLimiter, TokenType};
2424
use crate::vstate::memory::{Address, ByteValued, Bytes, GuestAddress, GuestMemoryMmap};
2525

@@ -263,7 +263,6 @@ pub struct Request {
263263
pub status_addr: GuestAddress,
264264
sector: u64,
265265
data_addr: GuestAddress,
266-
discard_range: Option<(u64, u64)>,
267266
}
268267

269268
impl Request {
@@ -282,7 +281,6 @@ impl Request {
282281
r#type: RequestType::from(request_header.request_type),
283282
sector: request_header.sector,
284283
data_addr: GuestAddress(0),
285-
discard_range: None,
286284
data_len: 0,
287285
status_addr: GuestAddress(0),
288286
};
@@ -390,7 +388,10 @@ impl Request {
390388
let byte_len = u64::from(range.num_sectors)
391389
.checked_mul(u64::from(SECTOR_SIZE))
392390
.ok_or(VirtioBlockError::InvalidDataLength)?;
393-
self.discard_range = Some((byte_offset, byte_len));
391+
let byte_len = u32::try_from(byte_len).map_err(|_| VirtioBlockError::InvalidDataLength)?;
392+
393+
self.sector = byte_offset;
394+
self.data_len = byte_len;
394395

395396
Ok(())
396397
}
@@ -457,11 +458,8 @@ impl Request {
457458
));
458459
}
459460

460-
disk.file_engine.discard(
461-
self.discard_range
462-
.expect("discard request missing validated range"),
463-
pending,
464-
)
461+
disk.file_engine
462+
.discard((self.sector, u64::from(self.data_len)), pending)
465463
}
466464
RequestType::Flush => disk.file_engine.flush(pending),
467465
RequestType::GetDeviceID => {
@@ -502,7 +500,7 @@ mod tests {
502500

503501
use super::*;
504502
use crate::devices::virtio::queue::{Queue, VIRTQ_DESC_F_NEXT, VIRTQ_DESC_F_WRITE};
505-
use crate::devices::virtio::test_utils::{VirtQueue, default_mem};
503+
use crate::devices::virtio::test_utils::{default_mem, VirtQueue};
506504
use crate::vstate::memory::{Address, GuestAddress, GuestMemory};
507505

508506
const NUM_DISK_SECTORS: u64 = 1024;
@@ -586,9 +584,17 @@ mod tests {
586584
request.r#type,
587585
RequestType::from(expected_header.request_type)
588586
);
589-
assert_eq!(request.sector, expected_header.sector);
587+
if request.r#type == RequestType::Discard {
588+
let range: DiscardWriteZeroes = memory
589+
.read_obj(GuestAddress(self.data_desc.addr.get()))
590+
.unwrap();
591+
assert_eq!(request.sector, range.sector * u64::from(SECTOR_SIZE));
592+
assert_eq!(request.data_len, range.num_sectors * SECTOR_SIZE);
593+
} else {
594+
assert_eq!(request.sector, expected_header.sector);
595+
}
590596

591-
if check_data {
597+
if check_data && request.r#type != RequestType::Discard {
592598
assert_eq!(request.data_addr.raw_value(), self.data_desc.addr.get());
593599
assert_eq!(request.data_len, self.data_desc.len.get());
594600
}
@@ -909,8 +915,8 @@ mod tests {
909915
}
910916

911917
#[allow(clippy::let_with_type_underscore)]
912-
fn random_request_parse()
913-
-> impl Strategy<Value = (Result<Request, VirtioBlockError>, GuestMemoryMmap, Queue)> {
918+
fn random_request_parse(
919+
) -> impl Strategy<Value = (Result<Request, VirtioBlockError>, GuestMemoryMmap, Queue)> {
914920
// In this strategy we are going to generate random Requests/Errors and map them
915921
// to an input descriptor chain.
916922
//
@@ -999,7 +1005,6 @@ mod tests {
9991005
status_addr,
10001006
sector: sector & (NUM_DISK_SECTORS - sectors_len),
10011007
data_addr,
1002-
discard_range: None,
10031008
};
10041009
let mut request_header = RequestHeader::new(virtio_request_id, request.sector);
10051010

@@ -1031,10 +1036,8 @@ mod tests {
10311036
request.data_addr,
10321037
)
10331038
.unwrap();
1034-
request.discard_range = Some((
1035-
discard_sector * u64::from(SECTOR_SIZE),
1036-
u64::from(SECTOR_SIZE),
1037-
));
1039+
request.sector = discard_sector * u64::from(SECTOR_SIZE);
1040+
request.data_len = SECTOR_SIZE;
10381041
}
10391042
}
10401043

0 commit comments

Comments
 (0)