storage: Use DiskWrapper::pt in nvmed and virtio-blkd
This commit is contained in:
@@ -8,8 +8,7 @@ use partitionlib::{LogicalBlockSize, PartitionTable};
|
||||
/// `read_fn` will be called with a block number to be read, and a buffer to be filled.
|
||||
/// `read_fn` must return a full block of data.
|
||||
/// Result will be the number of bytes read.
|
||||
// FIXME make private once nvmed uses the DiskWrapper defined in this crate
|
||||
pub fn block_read(
|
||||
fn block_read(
|
||||
offset: u64,
|
||||
blksize: u32,
|
||||
buf: &mut [u8],
|
||||
@@ -67,9 +66,10 @@ pub struct DiskWrapper {
|
||||
}
|
||||
|
||||
impl DiskWrapper {
|
||||
fn pt(disk: &mut dyn Disk) -> Option<PartitionTable> {
|
||||
pub fn pt(disk: &mut dyn Disk) -> Option<PartitionTable> {
|
||||
let bs = match disk.block_length() {
|
||||
Ok(512) => LogicalBlockSize::Lb512,
|
||||
Ok(4096) => LogicalBlockSize::Lb4096,
|
||||
_ => return None,
|
||||
};
|
||||
struct Device<'a> {
|
||||
|
||||
+24
-90
@@ -1,11 +1,11 @@
|
||||
use std::collections::BTreeMap;
|
||||
use std::convert::{TryFrom, TryInto};
|
||||
use std::fmt::Write;
|
||||
use std::io;
|
||||
use std::io::prelude::*;
|
||||
use std::str;
|
||||
use std::sync::Arc;
|
||||
use std::{cmp, str};
|
||||
|
||||
use driver_block::Disk;
|
||||
use partitionlib::PartitionTable;
|
||||
use redox_scheme::{CallerCtx, OpenResult, SchemeBlock};
|
||||
use syscall::schemev2::NewFdFlags;
|
||||
use syscall::{
|
||||
@@ -15,14 +15,32 @@ use syscall::{
|
||||
|
||||
use crate::nvme::{Nvme, NvmeNamespace};
|
||||
|
||||
use partitionlib::{LogicalBlockSize, PartitionTable};
|
||||
|
||||
enum Handle {
|
||||
List(Vec<u8>), // entries
|
||||
Disk(u32), // disk num
|
||||
Partition(u32, u32), // disk num, part num
|
||||
}
|
||||
|
||||
struct NamespaceAndNvme<'a>(&'a Nvme, NvmeNamespace);
|
||||
|
||||
impl Disk for NamespaceAndNvme<'_> {
|
||||
fn block_length(&mut self) -> syscall::error::Result<u32> {
|
||||
Ok(self.1.block_size.try_into().unwrap())
|
||||
}
|
||||
|
||||
fn size(&mut self) -> u64 {
|
||||
self.1.blocks * self.1.block_size
|
||||
}
|
||||
|
||||
fn read(&mut self, block: u64, buffer: &mut [u8]) -> syscall::Result<Option<usize>> {
|
||||
self.0.namespace_read(self.1, block, buffer)
|
||||
}
|
||||
|
||||
fn write(&mut self, block: u64, buffer: &[u8]) -> syscall::Result<Option<usize>> {
|
||||
self.0.namespace_write(self.1, block, buffer)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct DiskWrapper {
|
||||
inner: NvmeNamespace,
|
||||
pt: Option<PartitionTable>,
|
||||
@@ -36,91 +54,7 @@ impl AsRef<NvmeNamespace> for DiskWrapper {
|
||||
|
||||
impl DiskWrapper {
|
||||
fn pt(disk: NvmeNamespace, nvme: &Nvme) -> Option<PartitionTable> {
|
||||
let bs = match disk.block_size {
|
||||
512 => LogicalBlockSize::Lb512,
|
||||
4096 => LogicalBlockSize::Lb4096,
|
||||
_ => return None,
|
||||
};
|
||||
struct Device<'a> {
|
||||
disk: NvmeNamespace,
|
||||
nvme: &'a Nvme,
|
||||
offset: u64,
|
||||
}
|
||||
|
||||
impl<'a> Seek for Device<'a> {
|
||||
fn seek(&mut self, from: io::SeekFrom) -> io::Result<u64> {
|
||||
let size_u = self.disk.blocks * self.disk.block_size;
|
||||
let size = i64::try_from(size_u).or(Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
"Disk larger than 2^63 - 1 bytes",
|
||||
)))?;
|
||||
|
||||
self.offset = match from {
|
||||
io::SeekFrom::Start(new_pos) => cmp::min(size_u, new_pos),
|
||||
io::SeekFrom::Current(new_pos) => {
|
||||
cmp::max(0, cmp::min(size, self.offset as i64 + new_pos)) as u64
|
||||
}
|
||||
io::SeekFrom::End(new_pos) => {
|
||||
cmp::max(0, cmp::min(size + new_pos, size)) as u64
|
||||
}
|
||||
};
|
||||
|
||||
Ok(self.offset)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Read for Device<'a> {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
let blksize = self.disk.block_size;
|
||||
let size_in_blocks = self.disk.blocks;
|
||||
|
||||
let disk = self.disk;
|
||||
let nvme = &mut self.nvme;
|
||||
|
||||
let read_block = |block: u64, block_bytes: &mut [u8]| {
|
||||
if block >= size_in_blocks {
|
||||
return Err(io::Error::from_raw_os_error(syscall::EOVERFLOW));
|
||||
}
|
||||
loop {
|
||||
match nvme
|
||||
.namespace_read(disk, block, block_bytes)
|
||||
.map_err(|err| io::Error::from_raw_os_error(err.errno))?
|
||||
{
|
||||
Some(bytes) => {
|
||||
assert_eq!(bytes, block_bytes.len());
|
||||
assert_eq!(bytes, blksize as usize);
|
||||
return Ok(());
|
||||
}
|
||||
None => {
|
||||
std::thread::yield_now();
|
||||
continue;
|
||||
} // TODO: Does this driver have (internal) error handling at all?
|
||||
}
|
||||
}
|
||||
};
|
||||
let bytes_read = driver_block::block_read(
|
||||
self.offset,
|
||||
blksize
|
||||
.try_into()
|
||||
.expect("Unreasonable block size above 2^32 bytes"),
|
||||
buf,
|
||||
read_block,
|
||||
)?;
|
||||
self.offset += bytes_read as u64;
|
||||
Ok(bytes_read)
|
||||
}
|
||||
}
|
||||
|
||||
partitionlib::get_partitions(
|
||||
&mut Device {
|
||||
disk,
|
||||
nvme,
|
||||
offset: 0,
|
||||
},
|
||||
bs,
|
||||
)
|
||||
.ok()
|
||||
.flatten()
|
||||
driver_block::DiskWrapper::pt(&mut NamespaceAndNvme(nvme, disk))
|
||||
}
|
||||
fn new(inner: NvmeNamespace, nvme: &Nvme) -> Self {
|
||||
Self {
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
use std::collections::BTreeMap;
|
||||
use std::io::Read;
|
||||
use std::io::Result as IoResult;
|
||||
use std::io::Seek;
|
||||
|
||||
use std::fmt::Write;
|
||||
use std::sync::Arc;
|
||||
|
||||
use common::dma::Dma;
|
||||
use partitionlib::LogicalBlockSize;
|
||||
use driver_block::DiskWrapper;
|
||||
use partitionlib::PartitionTable;
|
||||
|
||||
use redox_scheme::CallerCtx;
|
||||
@@ -121,85 +118,31 @@ impl<'a> DiskScheme<'a> {
|
||||
part_table: None,
|
||||
};
|
||||
|
||||
struct VirtioShim<'a, 'b> {
|
||||
scheme: &'b DiskScheme<'a>,
|
||||
offset: u64,
|
||||
}
|
||||
|
||||
impl<'a, 'b> Read for VirtioShim<'a, 'b> {
|
||||
fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> {
|
||||
let read_block =
|
||||
|block: u64, block_bytes: &mut [u8]| -> Result<(), std::io::Error> {
|
||||
let req = Dma::new(BlockVirtRequest {
|
||||
ty: BlockRequestTy::In,
|
||||
reserved: 0,
|
||||
sector: block,
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let result = Dma::new([0u8; 512]).unwrap();
|
||||
let status = Dma::new(u8::MAX).unwrap();
|
||||
|
||||
let chain = ChainBuilder::new()
|
||||
.chain(Buffer::new(&req))
|
||||
.chain(Buffer::new(&result).flags(DescriptorFlags::WRITE_ONLY))
|
||||
.chain(Buffer::new(&status).flags(DescriptorFlags::WRITE_ONLY))
|
||||
.build();
|
||||
|
||||
futures::executor::block_on(self.scheme.queue.send(chain));
|
||||
assert_eq!(*status, 0);
|
||||
|
||||
let size = core::cmp::min(block_bytes.len(), result.len());
|
||||
block_bytes[..size].copy_from_slice(&result.as_slice()[..size]);
|
||||
Ok(())
|
||||
};
|
||||
|
||||
let bytes_read =
|
||||
driver_block::block_read(self.offset, 512, buf, read_block).unwrap();
|
||||
self.offset += bytes_read as u64;
|
||||
Ok(bytes_read)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'b> Seek for VirtioShim<'a, 'b> {
|
||||
fn seek(&mut self, from: std::io::SeekFrom) -> IoResult<u64> {
|
||||
let size_u = self.scheme.cfg.capacity() * self.scheme.cfg.block_size() as u64;
|
||||
let size = i64::try_from(size_u).or(Err(std::io::Error::new(
|
||||
std::io::ErrorKind::Other,
|
||||
"Disk larger than 2^63 - 1 bytes",
|
||||
)))?;
|
||||
|
||||
self.offset = match from {
|
||||
std::io::SeekFrom::Start(new_pos) => std::cmp::min(size_u, new_pos),
|
||||
std::io::SeekFrom::Current(new_pos) => {
|
||||
std::cmp::max(0, std::cmp::min(size, self.offset as i64 + new_pos)) as u64
|
||||
}
|
||||
std::io::SeekFrom::End(new_pos) => {
|
||||
std::cmp::max(0, std::cmp::min(size + new_pos, size)) as u64
|
||||
}
|
||||
};
|
||||
|
||||
Ok(self.offset)
|
||||
}
|
||||
}
|
||||
|
||||
let mut shim = VirtioShim {
|
||||
scheme: &this,
|
||||
offset: 0,
|
||||
};
|
||||
|
||||
//driver_block::DiskWrapper::new(disk)
|
||||
|
||||
// FIXME use DiskWrapper instead
|
||||
let part_table = partitionlib::get_partitions(&mut shim, LogicalBlockSize::Lb512)
|
||||
.ok()
|
||||
.flatten();
|
||||
|
||||
this.part_table = part_table;
|
||||
this.part_table = DiskWrapper::pt(&mut this);
|
||||
this
|
||||
}
|
||||
}
|
||||
|
||||
impl driver_block::Disk for DiskScheme<'_> {
|
||||
fn block_length(&mut self) -> syscall::error::Result<u32> {
|
||||
Ok(self.cfg.block_size())
|
||||
}
|
||||
|
||||
fn size(&mut self) -> u64 {
|
||||
self.cfg.capacity() * self.cfg.block_size() as u64
|
||||
}
|
||||
|
||||
fn read(&mut self, block: u64, buffer: &mut [u8]) -> syscall::Result<Option<usize>> {
|
||||
Ok(Some(futures::executor::block_on(
|
||||
self.queue.read(block, buffer),
|
||||
)))
|
||||
}
|
||||
|
||||
fn write(&mut self, _block: u64, _buffer: &[u8]) -> syscall::Result<Option<usize>> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> SchemeBlock for DiskScheme<'a> {
|
||||
fn xopen(
|
||||
&mut self,
|
||||
|
||||
Reference in New Issue
Block a user