block.rs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. mod mbr;
  2. use super::{
  3. constants::ENOENT,
  4. mem::{paging::Page, AsMemoryBlock as _},
  5. vfs::DevId,
  6. };
  7. use crate::kernel::constants::{EEXIST, EINVAL};
  8. use crate::{
  9. io::{Buffer, FillResult},
  10. prelude::*,
  11. };
  12. use alloc::{
  13. collections::btree_map::{BTreeMap, Entry},
  14. sync::Arc,
  15. };
  16. use core::cmp::Ordering;
  17. use mbr::MBRPartTable;
  18. pub fn make_device(major: u32, minor: u32) -> DevId {
  19. (major << 8) & 0xff00u32 | minor & 0xffu32
  20. }
  21. pub struct Partition {
  22. pub lba_offset: u64,
  23. pub sector_count: u64,
  24. }
  25. pub trait PartTable {
  26. fn partitions(&self) -> impl Iterator<Item = Partition> + use<'_, Self>;
  27. }
  28. pub trait BlockRequestQueue: Send + Sync {
  29. /// Maximum number of sectors that can be read in one request
  30. fn max_request_pages(&self) -> u64;
  31. fn submit(&self, req: BlockDeviceRequest) -> KResult<()>;
  32. }
  33. enum BlockDeviceType {
  34. Disk {
  35. queue: Arc<dyn BlockRequestQueue>,
  36. },
  37. Partition {
  38. disk_dev: DevId,
  39. lba_offset: u64,
  40. queue: Arc<dyn BlockRequestQueue>,
  41. },
  42. }
  43. pub struct BlockDevice {
  44. /// Unique device identifier, major and minor numbers
  45. devid: DevId,
  46. /// Total size of the device in sectors (512 bytes each)
  47. sector_count: u64,
  48. dev_type: BlockDeviceType,
  49. }
  50. impl PartialEq for BlockDevice {
  51. fn eq(&self, other: &Self) -> bool {
  52. self.devid == other.devid
  53. }
  54. }
  55. impl PartialOrd for BlockDevice {
  56. fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
  57. Some(self.devid.cmp(&other.devid))
  58. }
  59. }
  60. impl Eq for BlockDevice {}
  61. impl Ord for BlockDevice {
  62. fn cmp(&self, other: &Self) -> Ordering {
  63. self.devid.cmp(&other.devid)
  64. }
  65. }
  66. static BLOCK_DEVICE_LIST: Spin<BTreeMap<DevId, Arc<BlockDevice>>> = Spin::new(BTreeMap::new());
  67. impl BlockDevice {
  68. pub fn register_disk(
  69. devid: DevId,
  70. size: u64,
  71. queue: Arc<dyn BlockRequestQueue>,
  72. ) -> KResult<Arc<Self>> {
  73. let device = Arc::new(Self {
  74. devid,
  75. sector_count: size,
  76. dev_type: BlockDeviceType::Disk { queue },
  77. });
  78. match BLOCK_DEVICE_LIST.lock().entry(devid) {
  79. Entry::Vacant(entry) => Ok(entry.insert(device).clone()),
  80. Entry::Occupied(_) => Err(EEXIST),
  81. }
  82. }
  83. pub fn get(devid: DevId) -> KResult<Arc<Self>> {
  84. BLOCK_DEVICE_LIST.lock().get(&devid).cloned().ok_or(ENOENT)
  85. }
  86. }
  87. impl BlockDevice {
  88. pub fn devid(&self) -> DevId {
  89. self.devid
  90. }
  91. fn queue(&self) -> &Arc<dyn BlockRequestQueue> {
  92. match &self.dev_type {
  93. BlockDeviceType::Disk { queue } => queue,
  94. BlockDeviceType::Partition { queue, .. } => queue,
  95. }
  96. }
  97. pub fn register_partition(&self, idx: usize, offset: u64, size: u64) -> KResult<Arc<Self>> {
  98. let queue = match &self.dev_type {
  99. BlockDeviceType::Disk { queue } => queue.clone(),
  100. BlockDeviceType::Partition { .. } => return Err(EINVAL),
  101. };
  102. let device = Arc::new(BlockDevice {
  103. devid: make_device(self.devid >> 8, (self.devid & 0xff) + idx as u32 + 1),
  104. sector_count: size,
  105. dev_type: BlockDeviceType::Partition {
  106. disk_dev: self.devid,
  107. lba_offset: offset,
  108. queue,
  109. },
  110. });
  111. match BLOCK_DEVICE_LIST.lock().entry(device.devid()) {
  112. Entry::Vacant(entry) => Ok(entry.insert(device).clone()),
  113. Entry::Occupied(_) => Err(EEXIST),
  114. }
  115. }
  116. pub async fn partprobe(&self) -> KResult<()> {
  117. match self.dev_type {
  118. BlockDeviceType::Partition { .. } => Err(EINVAL),
  119. BlockDeviceType::Disk { .. } => {
  120. if let Ok(mbr_table) = MBRPartTable::from_disk(self).await {
  121. for (idx, partition) in mbr_table.partitions().enumerate() {
  122. self.register_partition(idx, partition.lba_offset, partition.sector_count)?;
  123. }
  124. }
  125. Ok(())
  126. }
  127. }
  128. }
  129. /// No extra overhead, send the request directly to the queue
  130. /// If any of the parameters does not meet the requirement, the operation will fail
  131. ///
  132. /// # Requirements
  133. /// - `req.count` must not exceed the disk size and maximum request size
  134. /// - `req.sector` must be within the disk size
  135. /// - `req.buffer` must be enough to hold the data
  136. ///
  137. pub fn commit_request(&self, mut req: BlockDeviceRequest) -> KResult<()> {
  138. // Verify the request parameters.
  139. match &mut req {
  140. BlockDeviceRequest::Read { sector, count, .. } => {
  141. if *sector + *count > self.sector_count {
  142. return Err(EINVAL);
  143. }
  144. if let BlockDeviceType::Partition { lba_offset, .. } = &self.dev_type {
  145. // Adjust the sector for partition offset.
  146. *sector += lba_offset;
  147. }
  148. }
  149. BlockDeviceRequest::Write { sector, count, .. } => {
  150. if *sector + *count > self.sector_count {
  151. return Err(EINVAL);
  152. }
  153. if let BlockDeviceType::Partition { lba_offset, .. } = &self.dev_type {
  154. // Adjust the sector for partition offset.
  155. *sector += lba_offset;
  156. }
  157. }
  158. }
  159. self.queue().submit(req)
  160. }
  161. /// Read some from the block device, may involve some copy and fragmentation
  162. ///
  163. /// Further optimization may be needed, including caching, read-ahead and reordering
  164. ///
  165. /// # Arguments
  166. /// `offset` - offset in bytes
  167. ///
  168. pub fn read_some(&self, offset: usize, buffer: &mut dyn Buffer) -> KResult<FillResult> {
  169. let mut sector_start = offset as u64 / 512;
  170. let mut first_sector_offset = offset as u64 % 512;
  171. let mut sector_count = (first_sector_offset + buffer.total() as u64 + 511) / 512;
  172. let mut nfilled = 0;
  173. 'outer: while sector_count != 0 {
  174. let pages: &[Page];
  175. let page: Option<Page>;
  176. let page_vec: Option<Vec<Page>>;
  177. let nread;
  178. match sector_count {
  179. count if count <= 8 => {
  180. nread = count;
  181. let _page = Page::alloc();
  182. page = Some(_page);
  183. pages = core::slice::from_ref(page.as_ref().unwrap());
  184. }
  185. count if count <= 16 => {
  186. nread = count;
  187. let _pages = Page::alloc_order(1);
  188. page = Some(_pages);
  189. pages = core::slice::from_ref(page.as_ref().unwrap());
  190. }
  191. count => {
  192. nread = count.min(self.queue().max_request_pages());
  193. let npages = (nread + 15) / 16;
  194. let mut _page_vec = Vec::with_capacity(npages as usize);
  195. for _ in 0..npages {
  196. _page_vec.push(Page::alloc_order(1));
  197. }
  198. page_vec = Some(_page_vec);
  199. pages = page_vec.as_ref().unwrap().as_slice();
  200. }
  201. }
  202. let req = BlockDeviceRequest::Read {
  203. sector: sector_start,
  204. count: nread,
  205. buffer: &pages,
  206. };
  207. self.commit_request(req)?;
  208. for page in pages.iter() {
  209. // SAFETY: We are the only owner of the page so no one could be mutating it.
  210. let data = unsafe { &page.as_memblk().as_bytes()[first_sector_offset as usize..] };
  211. first_sector_offset = 0;
  212. match buffer.fill(data)? {
  213. FillResult::Done(n) => nfilled += n,
  214. FillResult::Partial(n) => {
  215. nfilled += n;
  216. break 'outer;
  217. }
  218. FillResult::Full => {
  219. break 'outer;
  220. }
  221. }
  222. }
  223. sector_start += nread;
  224. sector_count -= nread;
  225. }
  226. if nfilled == buffer.total() {
  227. Ok(FillResult::Done(nfilled))
  228. } else {
  229. Ok(FillResult::Partial(nfilled))
  230. }
  231. }
  232. /// Write some data to the block device, may involve some copy and fragmentation
  233. ///
  234. /// # Arguments
  235. /// `offset` - offset in bytes
  236. /// `data` - data to write
  237. ///
  238. pub fn write_some(&self, offset: usize, data: &[u8]) -> KResult<usize> {
  239. let mut sector_start = offset as u64 / 512;
  240. let mut first_sector_offset = offset as u64 % 512;
  241. let mut remaining_data = data;
  242. let mut nwritten = 0;
  243. while !remaining_data.is_empty() {
  244. let pages: &[Page];
  245. let page: Option<Page>;
  246. let page_vec: Option<Vec<Page>>;
  247. // Calculate sectors needed for this write
  248. let write_end = first_sector_offset + remaining_data.len() as u64;
  249. let sector_count = ((write_end + 511) / 512).min(self.queue().max_request_pages());
  250. match sector_count {
  251. count if count <= 8 => {
  252. let _page = Page::alloc();
  253. page = Some(_page);
  254. pages = core::slice::from_ref(page.as_ref().unwrap());
  255. }
  256. count if count <= 16 => {
  257. let _pages = Page::alloc_order(1);
  258. page = Some(_pages);
  259. pages = core::slice::from_ref(page.as_ref().unwrap());
  260. }
  261. count => {
  262. let npages = (count + 15) / 16;
  263. let mut _page_vec = Vec::with_capacity(npages as usize);
  264. for _ in 0..npages {
  265. _page_vec.push(Page::alloc_order(1));
  266. }
  267. page_vec = Some(_page_vec);
  268. pages = page_vec.as_ref().unwrap().as_slice();
  269. }
  270. }
  271. if first_sector_offset != 0 || remaining_data.len() < (sector_count * 512) as usize {
  272. let read_req = BlockDeviceRequest::Read {
  273. sector: sector_start,
  274. count: sector_count,
  275. buffer: pages,
  276. };
  277. self.commit_request(read_req)?;
  278. }
  279. let mut data_offset = 0;
  280. let mut page_offset = first_sector_offset as usize;
  281. for page in pages.iter() {
  282. // SAFETY: We own the page and can modify it
  283. let page_data = unsafe {
  284. let memblk = page.as_memblk();
  285. core::slice::from_raw_parts_mut(memblk.addr().get() as *mut u8, memblk.len())
  286. };
  287. let copy_len =
  288. (remaining_data.len() - data_offset).min(page_data.len() - page_offset);
  289. if copy_len == 0 {
  290. break;
  291. }
  292. page_data[page_offset..page_offset + copy_len]
  293. .copy_from_slice(&remaining_data[data_offset..data_offset + copy_len]);
  294. data_offset += copy_len;
  295. page_offset = 0; // Only first page has offset
  296. if data_offset >= remaining_data.len() {
  297. break;
  298. }
  299. }
  300. let write_req = BlockDeviceRequest::Write {
  301. sector: sector_start,
  302. count: sector_count,
  303. buffer: pages,
  304. };
  305. self.commit_request(write_req)?;
  306. let bytes_written = data_offset;
  307. nwritten += bytes_written;
  308. remaining_data = &remaining_data[bytes_written..];
  309. sector_start += sector_count;
  310. first_sector_offset = 0;
  311. }
  312. Ok(nwritten)
  313. }
  314. }
  315. pub enum BlockDeviceRequest<'lt> {
  316. Read {
  317. /// Sector to read from, in 512-byte blocks
  318. sector: u64,
  319. /// Number of sectors to read
  320. count: u64,
  321. /// Buffer pages to read into
  322. buffer: &'lt [Page],
  323. },
  324. Write {
  325. /// Sector to write to, in 512-byte blocks
  326. sector: u64,
  327. /// Number of sectors to write
  328. count: u64,
  329. /// Buffer pages to write from
  330. buffer: &'lt [Page],
  331. },
  332. }