Skip to content

Commit 3506110

Browse files
committed
Move locking into block device
1 parent dad2fa1 commit 3506110

File tree

5 files changed

+30
-34
lines changed

5 files changed

+30
-34
lines changed

lib/io/src/block/file.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -77,12 +77,12 @@ impl File {
7777

7878
impl Block for File {
7979
#[cfg(unix)]
80-
fn read_exact_at(&mut self, buf: &mut [u8], offset: u64) -> Result<()> {
80+
fn read_exact_at(&self, buf: &mut [u8], offset: u64) -> Result<()> {
8181
self.file.read_exact_at(buf, offset)
8282
}
8383

8484
#[cfg(windows)]
85-
fn read_exact_at(&mut self, mut buf: &mut [u8], mut offset: u64) -> Result<()> {
85+
fn read_exact_at(&self, mut buf: &mut [u8], mut offset: u64) -> Result<()> {
8686
while !buf.is_empty() {
8787
match self.file.seek_read(buf, offset) {
8888
Ok(0) => {
@@ -103,12 +103,12 @@ impl Block for File {
103103
}
104104

105105
#[cfg(unix)]
106-
fn write_all_at(&mut self, buf: &[u8], offset: u64) -> Result<()> {
106+
fn write_all_at(&self, buf: &[u8], offset: u64) -> Result<()> {
107107
self.file.write_all_at(buf, offset)
108108
}
109109

110110
#[cfg(windows)]
111-
fn write_all_at(&mut self, mut buf: &[u8], mut offset: u64) -> Result<()> {
111+
fn write_all_at(&self, mut buf: &[u8], mut offset: u64) -> Result<()> {
112112
while !buf.is_empty() {
113113
match self.file.seek_write(buf, offset) {
114114
Ok(0) => {
@@ -125,7 +125,7 @@ impl Block for File {
125125
Ok(())
126126
}
127127

128-
fn flush(&mut self) -> Result<()> {
128+
fn flush(&self) -> Result<()> {
129129
self.file.sync_data()
130130
}
131131

lib/io/src/block/mod.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,31 +35,31 @@ pub trait Block {
3535
/// Reads the exact number of byte required to fill buf from the given offset.
3636
///
3737
/// Caller must ensure `offset` and buffer size is aligned to `blksize` queried by `capability`.
38-
fn read_exact_at(&mut self, buf: &mut [u8], offset: u64) -> Result<()>;
38+
fn read_exact_at(&self, buf: &mut [u8], offset: u64) -> Result<()>;
3939

4040
/// Attempts to write an entire buffer starting from a given offset.
4141
///
4242
/// Caller must ensure `offset` and buffer size is aligned to `blksize` queried by `capability`.
43-
fn write_all_at(&mut self, buf: &[u8], offset: u64) -> Result<()>;
43+
fn write_all_at(&self, buf: &[u8], offset: u64) -> Result<()>;
4444

4545
/// Attempts to write zero to a given offset.
4646
///
4747
/// Caller must ensure `offset` and `len` is aligned to `blksize` queried by `capability`.
48-
fn write_zero_at(&mut self, offset: u64, len: usize) -> Result<()> {
48+
fn write_zero_at(&self, offset: u64, len: usize) -> Result<()> {
4949
let buf = vec![0; len];
5050
self.write_all_at(&buf, offset)
5151
}
5252

5353
/// Discard contents at the given offset.
5454
///
5555
/// Caller must ensure `offset` and `len` is aligned to `blksize` queried by `capability`.
56-
fn discard(&mut self, offset: u64, len: usize) -> Result<()> {
56+
fn discard(&self, offset: u64, len: usize) -> Result<()> {
5757
let _ = (offset, len);
5858
Ok(())
5959
}
6060

6161
/// Flush this block device.
62-
fn flush(&mut self) -> Result<()> {
62+
fn flush(&self) -> Result<()> {
6363
Ok(())
6464
}
6565

lib/io/src/block/shadow.rs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,28 @@
11
use super::{Block, Capability};
22
use fnv::FnvHashMap;
33
use std::io::Result;
4+
use std::sync::RwLock;
45

56
/// A shadow block device that captures all write requests to the underlying block device.
67
///
78
/// All modified data will be kept in memory and not forwarded to the underlying block device.
89
pub struct Shadow<T> {
9-
overlay: FnvHashMap<u64, Box<[u8]>>,
10+
overlay: RwLock<FnvHashMap<u64, Box<[u8]>>>,
1011
block: T,
1112
}
1213

1314
impl<T> Shadow<T> {
1415
/// Construct a new `Shadow`.
1516
pub fn new(block: T) -> Self {
16-
Shadow { block, overlay: FnvHashMap::default() }
17+
Shadow { block, overlay: RwLock::new(FnvHashMap::default()) }
1718
}
1819
}
1920

2021
impl<T: Block> Block for Shadow<T> {
21-
fn read_exact_at(&mut self, buf: &mut [u8], mut offset: u64) -> Result<()> {
22+
fn read_exact_at(&self, buf: &mut [u8], mut offset: u64) -> Result<()> {
23+
let overlay = self.overlay.read().unwrap();
2224
for chunk in buf.chunks_mut(512) {
23-
match self.overlay.get(&offset) {
25+
match overlay.get(&offset) {
2426
None => self.block.read_exact_at(chunk, offset)?,
2527
Some(v) => chunk.copy_from_slice(v),
2628
}
@@ -29,15 +31,16 @@ impl<T: Block> Block for Shadow<T> {
2931
Ok(())
3032
}
3133

32-
fn write_all_at(&mut self, buf: &[u8], mut offset: u64) -> Result<()> {
34+
fn write_all_at(&self, buf: &[u8], mut offset: u64) -> Result<()> {
35+
let mut overlay = self.overlay.write().unwrap();
3336
for chunk in buf.chunks(512) {
34-
self.overlay.insert(offset, chunk.to_owned().into_boxed_slice());
37+
overlay.insert(offset, chunk.to_owned().into_boxed_slice());
3538
offset += 512
3639
}
3740
Ok(())
3841
}
3942

40-
fn flush(&mut self) -> Result<()> {
43+
fn flush(&self) -> Result<()> {
4144
Ok(())
4245
}
4346

lib/io/src/hw/virtio/block.rs

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use super::{Device, DeviceId, Queue};
22
use crate::block::Block as BlockDevice;
33
use crate::{IrqPin, RuntimeContext};
4-
use parking_lot::Mutex;
54
use std::sync::Arc;
65

76
#[allow(dead_code)]
@@ -28,7 +27,7 @@ pub struct Block {
2827
}
2928

3029
struct Inner {
31-
file: Mutex<Box<dyn BlockDevice + Send>>,
30+
file: Box<dyn BlockDevice + Send + Sync>,
3231
irq: Box<dyn IrqPin>,
3332
}
3433

@@ -37,13 +36,13 @@ impl Block {
3736
pub fn new(
3837
ctx: Arc<dyn RuntimeContext>,
3938
irq: Box<dyn IrqPin>,
40-
file: Box<dyn BlockDevice + Send>,
39+
file: Box<dyn BlockDevice + Send + Sync>,
4140
) -> Block {
4241
let len = file.len();
4342
if len % 512 != 0 {
4443
panic!("Size of block device must be multiple of 512 bytes");
4544
}
46-
let inner = Arc::new(Inner { file: Mutex::new(file), irq });
45+
let inner = Arc::new(Inner { file, irq });
4746
Block { status: 0, config: (len / 512).to_le_bytes(), ctx, inner }
4847
}
4948

@@ -64,11 +63,8 @@ impl Block {
6463
let mut io_buffer = Vec::with_capacity(writer.len());
6564
unsafe { io_buffer.set_len(io_buffer.capacity() - 1) };
6665

67-
{
68-
let mut file = inner.file.lock();
69-
(*file).read_exact_at(&mut io_buffer, header.sector * 512).unwrap();
70-
trace!(target: "VirtioBlk", "read {} bytes from sector {:x}", io_buffer.len(), header.sector);
71-
}
66+
inner.file.read_exact_at(&mut io_buffer, header.sector * 512).unwrap();
67+
trace!(target: "VirtioBlk", "read {} bytes from sector {:x}", io_buffer.len(), header.sector);
7268

7369
io_buffer.push(0);
7470
writer.write_all(&io_buffer).await.unwrap();
@@ -78,13 +74,10 @@ impl Block {
7874
unsafe { io_buffer.set_len(io_buffer.capacity()) };
7975
reader.read_exact(&mut io_buffer).await.unwrap();
8076

81-
{
82-
let mut file = inner.file.lock();
83-
file.write_all_at(&io_buffer, header.sector * 512).unwrap();
84-
// We must make sure the data has been flushed into the disk before returning
85-
file.flush().unwrap();
86-
trace!(target: "VirtioBlk", "write {} bytes from sector {:x}", io_buffer.len(), header.sector);
87-
}
77+
inner.file.write_all_at(&io_buffer, header.sector * 512).unwrap();
78+
// We must make sure the data has been flushed into the disk before returning
79+
inner.file.flush().unwrap();
80+
trace!(target: "VirtioBlk", "write {} bytes from sector {:x}", io_buffer.len(), header.sector);
8881

8982
writer.write_all(&[0]).await.unwrap();
9083
}

lib/io/src/system/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ impl IoSystem {
194194
.open(&config.config.path)
195195
.unwrap();
196196
let file = crate::block::File::new(file).unwrap();
197-
let file: Box<dyn crate::block::Block + Send> = if config.config.shadow {
197+
let file: Box<dyn crate::block::Block + Send + Sync> = if config.config.shadow {
198198
Box::new(crate::block::Shadow::new(file))
199199
} else {
200200
Box::new(file)

0 commit comments

Comments
 (0)