nvme: better prp list
This commit is contained in:
parent
0be9d86344
commit
f79cae5368
@ -93,28 +93,49 @@ pub struct QueuePair {
|
|||||||
inner: IrqSafeSpinlock<Inner>,
|
inner: IrqSafeSpinlock<Inner>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum PrpList {
|
pub struct PrpList {
|
||||||
None,
|
prp1: PhysicalRegionPage,
|
||||||
One(PhysicalAddress),
|
prp2: PhysicalRegionPage,
|
||||||
Two(PhysicalAddress, PhysicalAddress),
|
list: Option<PageBox<[PhysicalAddress]>>,
|
||||||
List(PhysicalAddress, PageBox<[PhysicalAddress]>),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PrpList {
|
impl PrpList {
|
||||||
|
pub const fn empty() -> Self {
|
||||||
|
Self {
|
||||||
|
prp1: PhysicalRegionPage::null(),
|
||||||
|
prp2: PhysicalRegionPage::null(),
|
||||||
|
list: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn from_buffer(base: PhysicalAddress, size: usize) -> Result<Self, NvmeError> {
|
pub fn from_buffer(base: PhysicalAddress, size: usize) -> Result<Self, NvmeError> {
|
||||||
// TODO hardcoded page size
|
// TODO hardcoded page size
|
||||||
if base.into_u64() % 0x1000 != 0 {
|
if base.into_u64() % 0x1000 != 0 {
|
||||||
todo!();
|
todo!();
|
||||||
}
|
}
|
||||||
|
|
||||||
match size {
|
match size {
|
||||||
0 => Ok(Self::None),
|
0 => Ok(Self::empty()),
|
||||||
_ if size <= 0x1000 => Ok(Self::One(base)),
|
_ if size <= 0x1000 => Ok(Self {
|
||||||
_ if size <= 0x2000 => Ok(Self::Two(base, base.add(0x1000))),
|
prp1: PhysicalRegionPage::with_addr(base),
|
||||||
|
prp2: PhysicalRegionPage::null(),
|
||||||
|
list: None,
|
||||||
|
}),
|
||||||
|
_ if size <= 0x2000 => Ok(Self {
|
||||||
|
prp1: PhysicalRegionPage::with_addr(base),
|
||||||
|
prp2: PhysicalRegionPage::with_addr(base.add(0x1000)),
|
||||||
|
list: None,
|
||||||
|
}),
|
||||||
_ => {
|
_ => {
|
||||||
let count = (size + 0xFFF) / 0x1000;
|
let count = (size + 0xFFF) / 0x1000;
|
||||||
let list = PageBox::new_slice_with(|i| base.add((i + 1) * 0x1000), count - 1)
|
let list = PageBox::new_slice_with(|i| base.add((i + 1) * 0x1000), count - 1)
|
||||||
.map_err(NvmeError::MemoryError)?;
|
.map_err(NvmeError::MemoryError)?;
|
||||||
Ok(Self::List(base, list))
|
|
||||||
|
Ok(Self {
|
||||||
|
prp1: PhysicalRegionPage::with_addr(base),
|
||||||
|
prp2: PhysicalRegionPage::with_addr(unsafe { list.as_physical_address() }),
|
||||||
|
list: Some(list),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -339,25 +360,8 @@ impl QueuePair {
|
|||||||
let mut inner = self.inner.lock();
|
let mut inner = self.inner.lock();
|
||||||
let mut sqe = SubmissionQueueEntry::zeroed();
|
let mut sqe = SubmissionQueueEntry::zeroed();
|
||||||
|
|
||||||
match ranges {
|
sqe.data_pointer[0] = ranges.prp1;
|
||||||
PrpList::None => {
|
sqe.data_pointer[1] = ranges.prp2;
|
||||||
sqe.data_pointer[0] = PhysicalRegionPage::null();
|
|
||||||
sqe.data_pointer[1] = PhysicalRegionPage::null();
|
|
||||||
}
|
|
||||||
&PrpList::One(buf0) => {
|
|
||||||
sqe.data_pointer[0] = PhysicalRegionPage::with_addr(buf0);
|
|
||||||
sqe.data_pointer[1] = PhysicalRegionPage::null();
|
|
||||||
}
|
|
||||||
&PrpList::Two(buf0, buf1) => {
|
|
||||||
sqe.data_pointer[0] = PhysicalRegionPage::with_addr(buf0);
|
|
||||||
sqe.data_pointer[1] = PhysicalRegionPage::with_addr(buf1);
|
|
||||||
}
|
|
||||||
PrpList::List(buf0, list) => {
|
|
||||||
sqe.data_pointer[0] = PhysicalRegionPage::with_addr(*buf0);
|
|
||||||
sqe.data_pointer[1] =
|
|
||||||
PhysicalRegionPage::with_addr(unsafe { list.as_physical_address() });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd.fill_sqe(&mut sqe);
|
cmd.fill_sqe(&mut sqe);
|
||||||
|
|
||||||
@ -374,7 +378,7 @@ impl QueuePair {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn request_no_data<C: Command>(&self, req: C) -> Result<(), NvmeError> {
|
pub async fn request_no_data<C: Command>(&self, req: C) -> Result<(), NvmeError> {
|
||||||
let list = PrpList::None;
|
let list = PrpList::empty();
|
||||||
let command_id = self.submit(req, &list, true)?;
|
let command_id = self.submit(req, &list, true)?;
|
||||||
self.wait_for_completion(command_id, ())
|
self.wait_for_completion(command_id, ())
|
||||||
.await
|
.await
|
||||||
@ -399,8 +403,6 @@ impl QueuePair {
|
|||||||
let mut inner = self.inner.lock();
|
let mut inner = self.inner.lock();
|
||||||
let mut n = 0;
|
let mut n = 0;
|
||||||
|
|
||||||
let mut completion_list = Vec::new();
|
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let (cmp, expected_phase) = inner.cq.at_head(n);
|
let (cmp, expected_phase) = inner.cq.at_head(n);
|
||||||
let cmp_phase = cmp.phase();
|
let cmp_phase = cmp.phase();
|
||||||
@ -411,29 +413,24 @@ impl QueuePair {
|
|||||||
|
|
||||||
n += 1;
|
n += 1;
|
||||||
|
|
||||||
|
let command_id = cmp.command_id();
|
||||||
let sub_queue_id = cmp.sub_queue_id();
|
let sub_queue_id = cmp.sub_queue_id();
|
||||||
// TODO allow several sqs receive completions through one cq?
|
// TODO allow several sqs receive completions through one cq?
|
||||||
assert_eq!(sub_queue_id, self.id);
|
debug_assert_eq!(sub_queue_id, self.id);
|
||||||
|
|
||||||
let sub_queue_head = cmp.sub_queue_head();
|
let sub_queue_head = cmp.sub_queue_head();
|
||||||
let cmp = *cmp;
|
let cmp = *cmp;
|
||||||
inner.sq.take_until(sub_queue_head);
|
inner.sq.take_until(sub_queue_head);
|
||||||
|
|
||||||
completion_list.push(cmp);
|
if inner.pending.remove(&command_id) {
|
||||||
|
inner.completed.insert(command_id, cmp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if n != 0 {
|
if n != 0 {
|
||||||
inner.cq.take(n);
|
inner.cq.take(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
for cmp in completion_list {
|
|
||||||
let command_id = cmp.command_id();
|
|
||||||
|
|
||||||
if inner.pending.remove(&command_id) {
|
|
||||||
inner.completed.insert(command_id, cmp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if n != 0 {
|
if n != 0 {
|
||||||
self.completion_notify.wake_all();
|
self.completion_notify.wake_all();
|
||||||
}
|
}
|
||||||
|
@ -29,36 +29,11 @@ impl RegularNode {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn read(&self, mut pos: u64, buffer: &mut [u8]) -> Result<usize, Error> {
|
async fn read(&self, pos: u64, buffer: &mut [u8]) -> Result<usize, Error> {
|
||||||
let holder = self.inode.get().await?;
|
let holder = self.inode.get().await?;
|
||||||
let inode = holder.read();
|
let inode = holder.read();
|
||||||
|
|
||||||
if pos >= inode.size(&self.fs) {
|
self.fs.read_inode_data(&inode, pos, buffer).await
|
||||||
return Ok(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut offset = 0;
|
|
||||||
let mut remaining = core::cmp::min(buffer.len(), (inode.size(&self.fs) - pos) as usize);
|
|
||||||
|
|
||||||
while remaining != 0 {
|
|
||||||
let block_index = pos / self.fs.block_size as u64;
|
|
||||||
let block_offset = (pos % self.fs.block_size as u64) as usize;
|
|
||||||
let amount = core::cmp::min(self.fs.block_size - block_offset, remaining);
|
|
||||||
|
|
||||||
self.fs
|
|
||||||
.with_inode_block(&inode, block_index as u32, |block| {
|
|
||||||
buffer[offset..offset + amount]
|
|
||||||
.copy_from_slice(&block[block_offset..block_offset + amount]);
|
|
||||||
Ok(())
|
|
||||||
})
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
pos += amount as u64;
|
|
||||||
offset += amount;
|
|
||||||
remaining -= amount;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(offset)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn write(&self, mut pos: u64, buffer: &[u8]) -> Result<usize, Error> {
|
async fn write(&self, mut pos: u64, buffer: &[u8]) -> Result<usize, Error> {
|
||||||
|
@ -439,6 +439,41 @@ impl Ext2Fs {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn read_inode_data(
|
||||||
|
&self,
|
||||||
|
inode: &Inode,
|
||||||
|
mut pos: u64,
|
||||||
|
buffer: &mut [u8],
|
||||||
|
) -> Result<usize, Error> {
|
||||||
|
let size = inode.size(self);
|
||||||
|
|
||||||
|
if pos >= size {
|
||||||
|
return Ok(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut offset = 0;
|
||||||
|
let mut remaining = buffer.len().min((size - pos) as usize);
|
||||||
|
|
||||||
|
while remaining != 0 {
|
||||||
|
let block_index = pos / self.block_size as u64;
|
||||||
|
let block_offset = (pos % self.block_size as u64) as usize;
|
||||||
|
let amount = remaining.min(self.block_size - block_offset);
|
||||||
|
|
||||||
|
self.with_inode_block(&inode, block_index as u32, |block| {
|
||||||
|
buffer[offset..offset + amount]
|
||||||
|
.copy_from_slice(&block[block_offset..block_offset + amount]);
|
||||||
|
Ok(())
|
||||||
|
})
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
pos += amount as u64;
|
||||||
|
offset += amount;
|
||||||
|
remaining -= amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(offset)
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn flush_inode_cache(&self) -> Result<(), Error> {
|
pub async fn flush_inode_cache(&self) -> Result<(), Error> {
|
||||||
log::info!("Flushing inode cache");
|
log::info!("Flushing inode cache");
|
||||||
self.inode_cache.get().flush().await
|
self.inode_cache.get().flush().await
|
||||||
|
@ -33,11 +33,12 @@ impl SymlinkNode {
|
|||||||
let inode = inode.read();
|
let inode = inode.read();
|
||||||
|
|
||||||
let len = inode.size(&self.fs) as usize;
|
let len = inode.size(&self.fs) as usize;
|
||||||
if len >= self.fs.block_size {
|
if len > self.fs.block_size {
|
||||||
todo!()
|
log::warn!("ext2: symlink size > block size");
|
||||||
|
return Err(Error::InvalidFile);
|
||||||
}
|
}
|
||||||
if buf.len() < len {
|
if buf.len() < len {
|
||||||
todo!();
|
return Err(Error::BufferTooSmall);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut write = self.cache.write();
|
let mut write = self.cache.write();
|
||||||
|
@ -435,11 +435,13 @@ impl Thread {
|
|||||||
///
|
///
|
||||||
/// Will panic if no current thread is present. For try-style getter, see
|
/// Will panic if no current thread is present. For try-style getter, see
|
||||||
/// [Thread::get_current].
|
/// [Thread::get_current].
|
||||||
|
#[inline]
|
||||||
pub fn current() -> CurrentThread {
|
pub fn current() -> CurrentThread {
|
||||||
Self::get_current().unwrap()
|
Self::get_current().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the current thread on the CPU, if any is present
|
/// Returns the current thread on the CPU, if any is present
|
||||||
|
#[inline]
|
||||||
pub fn get_current() -> Option<CurrentThread> {
|
pub fn get_current() -> Option<CurrentThread> {
|
||||||
// IrqGuard is held throughout
|
// IrqGuard is held throughout
|
||||||
let cpu = CpuImpl::<CpuQueue>::local();
|
let cpu = CpuImpl::<CpuQueue>::local();
|
||||||
@ -449,6 +451,7 @@ impl Thread {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a thread for given `id`, if such exists
|
/// Returns a thread for given `id`, if such exists
|
||||||
|
#[inline]
|
||||||
pub fn get(id: ThreadId) -> Option<Arc<Thread>> {
|
pub fn get(id: ThreadId) -> Option<Arc<Thread>> {
|
||||||
THREADS.read().get(id).cloned()
|
THREADS.read().get(id).cloned()
|
||||||
}
|
}
|
||||||
|
@ -151,6 +151,7 @@ impl Device for LocalApic {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl LocalApicInterface for LocalApic {
|
impl LocalApicInterface for LocalApic {
|
||||||
|
#[inline]
|
||||||
fn clear_interrupt(&self) {
|
fn clear_interrupt(&self) {
|
||||||
self.regs.EndOfInterrupt.set(0);
|
self.regs.EndOfInterrupt.set(0);
|
||||||
}
|
}
|
||||||
|
@ -140,11 +140,15 @@ impl log::Log for RingLoggerSink {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl log::Log for KernelLoggerSink {
|
impl log::Log for KernelLoggerSink {
|
||||||
fn enabled(&self, _metadata: &log::Metadata) -> bool {
|
fn enabled(&self, metadata: &log::Metadata) -> bool {
|
||||||
true
|
metadata.target() != "io"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn log(&self, record: &log::Record) {
|
fn log(&self, record: &log::Record) {
|
||||||
|
if !self.enabled(record.metadata()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if RING_AVAILABLE.load(Ordering::Acquire) {
|
if RING_AVAILABLE.load(Ordering::Acquire) {
|
||||||
RING_LOGGER_SINK.log(record);
|
RING_LOGGER_SINK.log(record);
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ use std::{
|
|||||||
use sysutils::Input;
|
use sysutils::Input;
|
||||||
|
|
||||||
fn cat_file(stdout: &mut Stdout, path: &str) -> io::Result<()> {
|
fn cat_file(stdout: &mut Stdout, path: &str) -> io::Result<()> {
|
||||||
let mut buf = [0; 4096];
|
let mut buf = [0; 512];
|
||||||
let mut reader = Input::open_str(path)?;
|
let mut reader = Input::open_str(path)?;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
@ -88,7 +88,7 @@ fn run<I: Read + Seek, O: Write>(
|
|||||||
let mut offset = 0;
|
let mut offset = 0;
|
||||||
let mut bytes_read = 0;
|
let mut bytes_read = 0;
|
||||||
|
|
||||||
// input.seek(SeekFrom::Start(src_position * src_block_size))?;
|
input.seek(SeekFrom::Start(src_position * src_block_size))?;
|
||||||
|
|
||||||
let mut total_delta = Duration::ZERO;
|
let mut total_delta = Duration::ZERO;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user