From ee03583b589bf2a8cc76ba0188f3c35a478108fd Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Wed, 11 Jan 2023 21:34:33 -0700 Subject: [PATCH] Prevent drives from being opened more than once --- ahcid/src/scheme.rs | 34 +++++++++++++++++++++++++++++----- ided/src/scheme.rs | 34 +++++++++++++++++++++++++++++----- nvmed/src/scheme.rs | 31 +++++++++++++++++++++++++++++-- 3 files changed, 87 insertions(+), 12 deletions(-) diff --git a/ahcid/src/scheme.rs b/ahcid/src/scheme.rs index da51c0c301..77b36972a3 100644 --- a/ahcid/src/scheme.rs +++ b/ahcid/src/scheme.rs @@ -7,7 +7,7 @@ use std::io::SeekFrom; use std::io; use syscall::{ - Error, EACCES, EBADF, EINVAL, EISDIR, ENOENT, EOVERFLOW, Result, + Error, EACCES, EBADF, EINVAL, EISDIR, ENOENT, ENOLCK, EOVERFLOW, Result, Io, SchemeBlockMut, Stat, MODE_DIR, MODE_FILE, O_DIRECTORY, O_STAT, SEEK_CUR, SEEK_END, SEEK_SET}; @@ -124,9 +124,7 @@ impl DiskScheme { next_id: 0 } } -} -impl DiskScheme { pub fn irq(&mut self) -> bool { let is = self.hba_mem.is.read(); if is > 0 { @@ -145,6 +143,29 @@ impl DiskScheme { false } } + + // Checks if any conflicting handles already exist + fn check_locks(&self, disk_i: usize, part_i_opt: Option) -> Result<()> { + for (_, handle) in self.handles.iter() { + match handle { + Handle::Disk(i, _) => if disk_i == *i { + return Err(Error::new(ENOLCK)); + }, + Handle::Partition(i, p, _) => if disk_i == *i { + match part_i_opt { + Some(part_i) => if part_i == *p { + return Err(Error::new(ENOLCK)); + }, + None => { + return Err(Error::new(ENOLCK)); + } + } + }, + _ => (), + } + } + Ok(()) + } } impl SchemeBlockMut for DiskScheme { @@ -186,11 +207,12 @@ impl SchemeBlockMut for DiskScheme { if disk.pt.is_none() || disk.pt.as_ref().unwrap().partitions.get(p as usize).is_none() { return Err(Error::new(ENOENT)); } + + self.check_locks(i, Some(p))?; + let id = self.next_id; self.next_id += 1; - self.handles.insert(id, Handle::Partition(i, p, 0)); - Ok(Some(id)) } else { Err(Error::new(ENOENT)) @@ -199,6 +221,8 @@ impl SchemeBlockMut for DiskScheme { let i = path_str.parse::().or(Err(Error::new(ENOENT)))?; if self.disks.get(i).is_some() { + self.check_locks(i, None)?; + let id = self.next_id; self.next_id += 1; self.handles.insert(id, Handle::Disk(i, 0)); diff --git a/ided/src/scheme.rs b/ided/src/scheme.rs index e88fb46e0c..a5fe20b309 100644 --- a/ided/src/scheme.rs +++ b/ided/src/scheme.rs @@ -8,7 +8,7 @@ use std::io; use std::sync::{Arc, Mutex}; use syscall::{ - Error, EACCES, EBADF, EINVAL, EISDIR, ENOENT, EOVERFLOW, Result, + Error, EACCES, EBADF, EINVAL, EISDIR, ENOENT, ENOLCK, EOVERFLOW, Result, Io, SchemeBlockMut, Stat, MODE_DIR, MODE_FILE, O_DIRECTORY, O_STAT, SEEK_CUR, SEEK_END, SEEK_SET}; @@ -124,14 +124,35 @@ impl DiskScheme { next_id: 0 } } -} -impl DiskScheme { pub fn irq(&mut self, chan_i: usize) -> bool { let mut chan = self.chans[chan_i].lock().unwrap(); //TODO: check chan for irq true } + + // Checks if any conflicting handles already exist + fn check_locks(&self, disk_i: usize, part_i_opt: Option) -> Result<()> { + for (_, handle) in self.handles.iter() { + match handle { + Handle::Disk(i, _) => if disk_i == *i { + return Err(Error::new(ENOLCK)); + }, + Handle::Partition(i, p, _) => if disk_i == *i { + match part_i_opt { + Some(part_i) => if part_i == *p { + return Err(Error::new(ENOLCK)); + }, + None => { + return Err(Error::new(ENOLCK)); + } + } + }, + _ => (), + } + } + Ok(()) + } } impl SchemeBlockMut for DiskScheme { @@ -173,11 +194,12 @@ impl SchemeBlockMut for DiskScheme { if disk.pt.is_none() || disk.pt.as_ref().unwrap().partitions.get(p as usize).is_none() { return Err(Error::new(ENOENT)); } + + self.check_locks(i, Some(p))?; + let id = self.next_id; self.next_id += 1; - self.handles.insert(id, Handle::Partition(i, p, 0)); - Ok(Some(id)) } else { Err(Error::new(ENOENT)) @@ -186,6 +208,8 @@ impl SchemeBlockMut for DiskScheme { let i = path_str.parse::().or(Err(Error::new(ENOENT)))?; if self.disks.get(i).is_some() { + self.check_locks(i, None)?; + let id = self.next_id; self.next_id += 1; self.handles.insert(id, Handle::Disk(i, 0)); diff --git a/nvmed/src/scheme.rs b/nvmed/src/scheme.rs index 55a491ab7f..654044aba0 100644 --- a/nvmed/src/scheme.rs +++ b/nvmed/src/scheme.rs @@ -7,8 +7,8 @@ use std::sync::Arc; use std::{cmp, str}; use syscall::{ - Error, Io, Result, SchemeBlockMut, Stat, EACCES, EBADF, EINVAL, EISDIR, ENOENT, EOVERFLOW, - MODE_DIR, MODE_FILE, O_DIRECTORY, O_STAT, SEEK_CUR, SEEK_END, SEEK_SET, + Error, Io, Result, SchemeBlockMut, Stat, EACCES, EBADF, EINVAL, EISDIR, ENOENT, ENOLCK, + EOVERFLOW, MODE_DIR, MODE_FILE, O_DIRECTORY, O_STAT, SEEK_CUR, SEEK_END, SEEK_SET, }; use crate::nvme::{Nvme, NvmeNamespace}; @@ -157,6 +157,29 @@ impl DiskScheme { next_id: 0, } } + + // Checks if any conflicting handles already exist + fn check_locks(&self, disk_i: u32, part_i_opt: Option) -> Result<()> { + for (_, handle) in self.handles.iter() { + match handle { + Handle::Disk(i, _) => if disk_i == *i { + return Err(Error::new(ENOLCK)); + }, + Handle::Partition(i, p, _) => if disk_i == *i { + match part_i_opt { + Some(part_i) => if part_i == *p { + return Err(Error::new(ENOLCK)); + }, + None => { + return Err(Error::new(ENOLCK)); + } + } + }, + _ => (), + } + } + Ok(()) + } } impl SchemeBlockMut for DiskScheme { @@ -206,6 +229,8 @@ impl SchemeBlockMut for DiskScheme { .get(part_num as usize) .is_some() { + self.check_locks(nsid, Some(part_num))?; + let id = self.next_id; self.next_id += 1; self.handles @@ -221,6 +246,8 @@ impl SchemeBlockMut for DiskScheme { let nsid = path_str.parse::().or(Err(Error::new(ENOENT)))?; if self.disks.contains_key(&nsid) { + self.check_locks(nsid, None)?; + let id = self.next_id; self.next_id += 1; self.handles.insert(id, Handle::Disk(nsid, 0));