1#![forbid(unsafe_code)]
49
50mod bitmap;
51pub mod resolve;
52pub mod resolver;
53
54pub use bitmap::SectorMarker;
55
56use bitmap::Bitmap;
57use disk_backend::Disk;
58use disk_backend::DiskError;
59use disk_backend::DiskIo;
60use disk_backend::UnmapBehavior;
61use guestmem::GuestMemory;
62use guestmem::MemoryWrite;
63use inspect::Inspect;
64use scsi_buffers::OwnedRequestBuffers;
65use scsi_buffers::RequestBuffers;
66use std::convert::Infallible;
67use std::future::Future;
68use std::pin::Pin;
69use thiserror::Error;
70
71#[derive(Inspect)]
73pub struct LayeredDisk {
74 #[inspect(iter_by_index)]
75 layers: Vec<Layer>,
76 read_only: bool,
77 is_fua_respected: bool,
78 sector_shift: u32,
79 disk_id: Option<[u8; 16]>,
80 physical_sector_size: u32,
81 unmap_behavior: UnmapBehavior,
82 optimal_unmap_sectors: u32,
83}
84
85#[derive(Inspect)]
86struct Layer {
87 backing: Box<dyn DynLayerIo>,
88 visible_sector_count: u64,
89 read_cache: bool,
90 write_through: bool,
91}
92
93pub struct DiskLayer(Box<dyn DynLayerAttach>);
95
96impl DiskLayer {
97 pub fn new<T: LayerAttach>(backing: T) -> Self {
99 Self(Box::new(backing))
100 }
101
102 pub fn from_disk(disk: Disk) -> Self {
105 Self::new(DiskAsLayer(disk))
106 }
107}
108
109#[derive(Clone)]
111#[expect(missing_docs)] pub struct DiskLayerMetadata {
113 pub disk_id: Option<[u8; 16]>,
114 pub sector_size: u32,
115 pub sector_count: u64,
116 pub physical_sector_size: u32,
117 pub unmap_behavior: UnmapBehavior,
118 pub optimal_unmap_sectors: u32,
119 pub read_only: bool,
120 pub can_read_cache: bool,
121 pub is_fua_respected: bool,
122}
123
124struct AttachedDiskLayer {
126 backing: Box<dyn DynLayerIo>,
127 meta: DiskLayerMetadata,
128}
129
130#[derive(Debug, Error)]
132pub enum InvalidLayer {
133 #[error("failed to attach layer")]
135 AttachFailed(#[source] anyhow::Error),
136 #[error("read caching was requested but is not supported")]
138 ReadCacheNotSupported,
139 #[error("sector size {0} is invalid")]
141 InvalidSectorSize(u32),
142 #[error("mismatched sector size {found}, expected {expected}")]
144 MismatchedSectorSize {
145 expected: u32,
147 found: u32,
149 },
150 #[error("nothing to write through")]
153 UselessWriteThrough,
154 #[error("read only layer in a writable disk")]
156 ReadOnly,
157}
158
159#[derive(Debug, Error)]
161pub enum InvalidLayeredDisk {
162 #[error("no layers were configured")]
164 NoLayers,
165 #[error("invalid layer {0}")]
167 Layer(usize, #[source] InvalidLayer),
168}
169
170pub struct LayerConfiguration<L = DiskLayer> {
172 pub layer: L,
174 pub write_through: bool,
176 pub read_cache: bool,
178}
179
180impl LayeredDisk {
181 pub async fn new(
186 read_only: bool,
187 layers: Vec<LayerConfiguration>,
188 ) -> Result<Self, InvalidLayeredDisk> {
189 if layers.is_empty() {
190 return Err(InvalidLayeredDisk::NoLayers);
191 }
192
193 let mut attached_layers: Vec<LayerConfiguration<AttachedDiskLayer>> = {
194 let mut attached_layers = Vec::new();
195
196 let mut lower_layer_metadata = None;
199 for (
200 i,
201 LayerConfiguration {
202 layer,
203 write_through,
204 read_cache,
205 },
206 ) in layers.into_iter().enumerate().rev()
207 {
208 let layer_error = |e| InvalidLayeredDisk::Layer(i, e);
209
210 let layer = layer
211 .0
212 .attach(lower_layer_metadata.take())
213 .await
214 .map_err(|e| layer_error(InvalidLayer::AttachFailed(e)))?;
215
216 let layer_meta = layer.meta.clone();
217
218 attached_layers.push(LayerConfiguration {
219 layer,
220 write_through,
221 read_cache,
222 });
223
224 if read_cache && !layer_meta.can_read_cache {
226 return Err(layer_error(InvalidLayer::ReadCacheNotSupported));
227 }
228 if !layer_meta.sector_size.is_power_of_two() {
229 return Err(layer_error(InvalidLayer::InvalidSectorSize(
230 layer_meta.sector_size,
231 )));
232 }
233 if layer_meta.sector_size != attached_layers[0].layer.meta.sector_size {
234 return Err(layer_error(InvalidLayer::MismatchedSectorSize {
236 expected: attached_layers[0].layer.meta.sector_size,
237 found: layer_meta.sector_size,
238 }));
239 }
240
241 lower_layer_metadata = Some(layer_meta);
242 }
243
244 attached_layers.reverse();
245 attached_layers
246 };
247
248 let mut last_write_through = true;
251 let mut is_fua_respected = true;
252 let mut optimal_unmap_sectors = 1;
253 let mut unmap_must_zero = false;
254 let mut disk_id = None;
255 let mut unmap_behavior = UnmapBehavior::Zeroes;
256 for (
257 i,
258 &LayerConfiguration {
259 ref layer,
260 write_through,
261 read_cache: _,
262 },
263 ) in attached_layers.iter().enumerate()
264 {
265 let layer_error = |e| InvalidLayeredDisk::Layer(i, e);
266
267 if last_write_through {
268 if layer.meta.read_only && !read_only {
269 return Err(layer_error(InvalidLayer::ReadOnly));
270 }
271 is_fua_respected &= layer.meta.is_fua_respected;
272 unmap_must_zero |= write_through;
282 unmap_behavior = match (unmap_behavior, layer.meta.unmap_behavior) {
283 (UnmapBehavior::Zeroes, UnmapBehavior::Zeroes) => UnmapBehavior::Zeroes,
284 _ if unmap_must_zero => UnmapBehavior::Ignored,
285 (UnmapBehavior::Ignored, _) => UnmapBehavior::Ignored,
286 (_, UnmapBehavior::Ignored) => UnmapBehavior::Ignored,
287 _ => UnmapBehavior::Unspecified,
288 };
289 optimal_unmap_sectors = optimal_unmap_sectors.max(layer.meta.optimal_unmap_sectors);
290 } else if write_through {
291 return Err(layer_error(InvalidLayer::UselessWriteThrough));
293 }
294 last_write_through = write_through;
295 if disk_id.is_none() {
296 disk_id = layer.meta.disk_id;
297 }
298 }
299
300 if last_write_through {
301 return Err(InvalidLayeredDisk::Layer(
302 attached_layers.len() - 1,
303 InvalidLayer::UselessWriteThrough,
304 ));
305 }
306
307 let sector_size = attached_layers[0].layer.meta.sector_size;
308 let physical_sector_size = attached_layers[0].layer.meta.physical_sector_size;
309
310 let mut last_sector_count = None;
311 let sector_counts_rev = attached_layers
312 .iter_mut()
313 .rev()
314 .map(|config| *last_sector_count.insert(config.layer.backing.sector_count()))
315 .collect::<Vec<_>>();
316
317 let mut visible_sector_count = !0;
318 let layers = attached_layers
319 .into_iter()
320 .zip(sector_counts_rev.into_iter().rev())
321 .map(|(config, sector_count)| {
322 let LayerConfiguration {
323 layer,
324 write_through,
325 read_cache,
326 } = config;
327 visible_sector_count = sector_count.min(visible_sector_count);
328 Layer {
329 backing: layer.backing,
330 visible_sector_count,
331 read_cache,
332 write_through,
333 }
334 })
335 .collect::<Vec<_>>();
336
337 Ok(Self {
338 is_fua_respected,
339 read_only,
340 sector_shift: sector_size.trailing_zeros(),
341 disk_id,
342 physical_sector_size,
343 unmap_behavior,
344 optimal_unmap_sectors,
345 layers,
346 })
347 }
348}
349
350trait DynLayerIo: Send + Sync + Inspect {
351 fn sector_count(&self) -> u64;
352
353 fn read<'a>(
354 &'a self,
355 buffers: &'a RequestBuffers<'_>,
356 sector: u64,
357 bitmap: SectorMarker<'a>,
358 ) -> Pin<Box<dyn 'a + Future<Output = Result<(), DiskError>> + Send>>;
359
360 fn write<'a>(
361 &'a self,
362 buffers: &'a RequestBuffers<'_>,
363 sector: u64,
364 fua: bool,
365 no_overwrite: bool,
366 ) -> Pin<Box<dyn 'a + Future<Output = Result<(), DiskError>> + Send>>;
367
368 fn sync_cache(&self) -> Pin<Box<dyn '_ + Future<Output = Result<(), DiskError>> + Send>>;
369
370 fn unmap(
371 &self,
372 sector: u64,
373 count: u64,
374 block_level_only: bool,
375 next_is_zero: bool,
376 ) -> Pin<Box<dyn '_ + Future<Output = Result<(), DiskError>> + Send>>;
377
378 fn wait_resize(&self, sector_count: u64) -> Pin<Box<dyn '_ + Future<Output = u64> + Send>>;
379}
380
381impl<T: LayerIo> DynLayerIo for T {
382 fn sector_count(&self) -> u64 {
383 self.sector_count()
384 }
385
386 fn read<'a>(
387 &'a self,
388 buffers: &'a RequestBuffers<'_>,
389 sector: u64,
390 bitmap: SectorMarker<'a>,
391 ) -> Pin<Box<dyn 'a + Future<Output = Result<(), DiskError>> + Send>> {
392 Box::pin(async move { self.read(buffers, sector, bitmap).await })
393 }
394
395 fn write<'a>(
396 &'a self,
397 buffers: &'a RequestBuffers<'_>,
398 sector: u64,
399 fua: bool,
400 no_overwrite: bool,
401 ) -> Pin<Box<dyn 'a + Future<Output = Result<(), DiskError>> + Send>> {
402 Box::pin(async move {
403 if no_overwrite {
404 self.write_no_overwrite()
405 .unwrap()
406 .write_no_overwrite(buffers, sector)
407 .await
408 } else {
409 self.write(buffers, sector, fua).await
410 }
411 })
412 }
413
414 fn sync_cache(&self) -> Pin<Box<dyn '_ + Future<Output = Result<(), DiskError>> + Send>> {
415 Box::pin(self.sync_cache())
416 }
417
418 fn unmap(
419 &self,
420 sector: u64,
421 count: u64,
422 block_level_only: bool,
423 next_is_zero: bool,
424 ) -> Pin<Box<dyn '_ + Future<Output = Result<(), DiskError>> + Send>> {
425 Box::pin(self.unmap(sector, count, block_level_only, next_is_zero))
426 }
427
428 fn wait_resize(&self, sector_count: u64) -> Pin<Box<dyn '_ + Future<Output = u64> + Send>> {
429 Box::pin(self.wait_resize(sector_count))
430 }
431}
432
433trait DynLayerAttach: Send + Sync {
434 fn attach(
435 self: Box<Self>,
436 lower_layer_metadata: Option<DiskLayerMetadata>,
437 ) -> Pin<Box<dyn Future<Output = anyhow::Result<AttachedDiskLayer>> + Send>>;
438}
439
440impl<T: LayerAttach> DynLayerAttach for T {
441 fn attach(
442 self: Box<Self>,
443 lower_layer_metadata: Option<DiskLayerMetadata>,
444 ) -> Pin<Box<dyn Future<Output = anyhow::Result<AttachedDiskLayer>> + Send>> {
445 Box::pin(async move {
446 Ok({
447 let backing = (*self)
448 .attach(lower_layer_metadata)
449 .await
450 .map_err(|e| anyhow::anyhow!(e.into()))?;
451 let can_read_cache = backing.write_no_overwrite().is_some();
452 AttachedDiskLayer {
453 meta: DiskLayerMetadata {
454 sector_count: LayerIo::sector_count(&backing),
455 disk_id: backing.disk_id(),
456 is_fua_respected: backing.is_fua_respected(),
457 sector_size: backing.sector_size(),
458 physical_sector_size: backing.physical_sector_size(),
459 unmap_behavior: backing.unmap_behavior(),
460 optimal_unmap_sectors: backing.optimal_unmap_sectors(),
461 read_only: backing.is_logically_read_only(),
462 can_read_cache,
463 },
464 backing: Box::new(backing),
465 }
466 })
467 })
468 }
469}
470
471pub trait LayerAttach: 'static + Send + Sync {
479 type Error: Into<Box<dyn std::error::Error + Send + Sync + 'static>>;
481 type Layer: LayerIo;
483
484 fn attach(
490 self,
491 lower_layer_metadata: Option<DiskLayerMetadata>,
492 ) -> impl Future<Output = Result<Self::Layer, Self::Error>> + Send;
493}
494
495impl<T: LayerIo> LayerAttach for T {
496 type Error = Infallible;
497 type Layer = Self;
498 async fn attach(
499 self,
500 _lower_layer_metadata: Option<DiskLayerMetadata>,
501 ) -> Result<Self, Infallible> {
502 Ok(self)
503 }
504}
505
506pub trait LayerIo: 'static + Send + Sync + Inspect {
522 fn layer_type(&self) -> &str;
526
527 fn sector_count(&self) -> u64;
532
533 fn sector_size(&self) -> u32;
537
538 fn disk_id(&self) -> Option<[u8; 16]>;
544
545 fn physical_sector_size(&self) -> u32;
549
550 fn is_fua_respected(&self) -> bool;
554
555 fn is_logically_read_only(&self) -> bool;
560
561 fn sync_cache(&self) -> impl Future<Output = Result<(), DiskError>> + Send;
563
564 fn read(
570 &self,
571 buffers: &RequestBuffers<'_>,
572 sector: u64,
573 marker: SectorMarker<'_>,
574 ) -> impl Future<Output = Result<(), DiskError>> + Send;
575
576 fn write(
582 &self,
583 buffers: &RequestBuffers<'_>,
584 sector: u64,
585 fua: bool,
586 ) -> impl Future<Output = Result<(), DiskError>> + Send;
587
588 fn unmap(
594 &self,
595 sector: u64,
596 count: u64,
597 block_level_only: bool,
598 next_is_zero: bool,
599 ) -> impl Future<Output = Result<(), DiskError>> + Send;
600
601 fn unmap_behavior(&self) -> UnmapBehavior;
603
604 fn optimal_unmap_sectors(&self) -> u32 {
606 1
607 }
608
609 fn write_no_overwrite(&self) -> Option<impl WriteNoOverwrite> {
611 None::<NoIdet>
612 }
613
614 fn wait_resize(&self, sector_count: u64) -> impl Future<Output = u64> + Send {
616 let _ = sector_count;
617 std::future::pending()
618 }
619}
620
621enum NoIdet {}
622
623pub trait WriteNoOverwrite: Send + Sync {
625 fn write_no_overwrite(
631 &self,
632 buffers: &RequestBuffers<'_>,
633 sector: u64,
634 ) -> impl Future<Output = Result<(), DiskError>> + Send;
635}
636
637impl<T: WriteNoOverwrite> WriteNoOverwrite for &T {
638 fn write_no_overwrite(
639 &self,
640 buffers: &RequestBuffers<'_>,
641 sector: u64,
642 ) -> impl Future<Output = Result<(), DiskError>> + Send {
643 (*self).write_no_overwrite(buffers, sector)
644 }
645}
646
647impl WriteNoOverwrite for NoIdet {
648 async fn write_no_overwrite(
649 &self,
650 _buffers: &RequestBuffers<'_>,
651 _sector: u64,
652 ) -> Result<(), DiskError> {
653 unreachable!()
654 }
655}
656
657impl DiskIo for LayeredDisk {
658 fn disk_type(&self) -> &str {
659 "layered"
660 }
661
662 fn sector_count(&self) -> u64 {
663 self.layers[0].backing.sector_count()
664 }
665
666 fn sector_size(&self) -> u32 {
667 1 << self.sector_shift
668 }
669
670 fn disk_id(&self) -> Option<[u8; 16]> {
671 self.disk_id
672 }
673
674 fn physical_sector_size(&self) -> u32 {
675 self.physical_sector_size
676 }
677
678 fn is_fua_respected(&self) -> bool {
679 self.is_fua_respected
680 }
681
682 fn is_read_only(&self) -> bool {
683 self.read_only
684 }
685
686 async fn read_vectored(
687 &self,
688 buffers: &RequestBuffers<'_>,
689 sector: u64,
690 ) -> Result<(), DiskError> {
691 let mut bounce_buffers = None::<(OwnedRequestBuffers, GuestMemory)>;
692 let sector_count = buffers.len() >> self.sector_shift;
693 let mut bitmap = Bitmap::new(sector, sector_count);
694 let mut bits_set = 0;
695 let mut populate_cache = Vec::new();
696 'done: for (i, layer) in self.layers.iter().enumerate() {
698 if bits_set == sector_count {
699 break;
700 }
701 for mut range in bitmap.unset_iter() {
702 let end = if i == 0 {
703 range.end_sector()
706 } else {
707 let end = range.end_sector().min(layer.visible_sector_count);
710 if range.start_sector() == end {
711 break 'done;
712 }
713 end
714 };
715
716 let sectors = end - range.start_sector();
717
718 let this_buffers = if let Some((bounce_buffers, mem)) = &bounce_buffers {
719 &bounce_buffers.buffer(mem)
720 } else {
721 buffers
722 };
723 let this_buffers = this_buffers.subrange(
724 range.start_sector_within_bitmap() << self.sector_shift,
725 (sectors as usize) << self.sector_shift,
726 );
727
728 layer
729 .backing
730 .read(&this_buffers, range.start_sector(), range.view(sectors))
731 .await?;
732
733 bits_set += range.set_count();
734
735 if range.set_count() as u64 != range.len() && layer.read_cache {
736 bounce_buffers.get_or_insert_with(|| {
739 let mem = GuestMemory::allocate(buffers.len());
740 let owned_buf = OwnedRequestBuffers::linear(0, buffers.len(), true);
741 (owned_buf, mem)
742 });
743
744 populate_cache.extend(range.unset_iter().map(|range| (layer, range)));
745 }
746 }
747 }
748 if bits_set != sector_count {
749 for range in bitmap.unset_iter() {
750 let len = (range.len() as usize) << self.sector_shift;
751 buffers
752 .subrange(range.start_sector_within_bitmap() << self.sector_shift, len)
753 .writer()
754 .zero(len)?;
755 }
756 }
757 if !populate_cache.is_empty() {
758 let (bounce_buffers, mem) = bounce_buffers.unwrap();
759 let bounce_buffers = bounce_buffers.buffer(&mem);
760 for &(layer, ref range) in &populate_cache {
761 assert!(layer.read_cache);
762 let offset = ((range.start - sector) as usize) << self.sector_shift;
763 let len = ((range.end - range.start) as usize) << self.sector_shift;
764 if let Err(err) = layer
765 .backing
766 .write(
767 &bounce_buffers.subrange(offset, len),
768 range.start,
769 false,
770 true,
771 )
772 .await
773 {
774 tracelimit::warn_ratelimited!(
775 error = &err as &dyn std::error::Error,
776 sector = range.start,
777 count = range.end - range.start,
778 "failed to populate read cache",
779 );
780 }
781 }
782 let mut mem = mem.into_inner_buf().ok().unwrap();
783 for (_, range) in populate_cache {
784 let offset = ((range.start - sector) as usize) << self.sector_shift;
788 let len = ((range.end - range.start) as usize) << self.sector_shift;
789 buffers
790 .subrange(offset, len)
791 .writer()
792 .write(&mem.as_bytes()[offset..][..len])?;
793 }
794 }
795 Ok(())
796 }
797
798 async fn write_vectored(
799 &self,
800 buffers: &RequestBuffers<'_>,
801 sector: u64,
802 fua: bool,
803 ) -> Result<(), DiskError> {
804 for layer in &self.layers {
805 layer.backing.write(buffers, sector, fua, false).await?;
806 if !layer.write_through {
807 break;
808 }
809 }
810 Ok(())
811 }
812
813 async fn sync_cache(&self) -> Result<(), DiskError> {
814 for layer in &self.layers {
815 layer.backing.sync_cache().await?;
816 if !layer.write_through {
817 break;
818 }
819 }
820 Ok(())
821 }
822
823 fn wait_resize(&self, sector_count: u64) -> impl Future<Output = u64> + Send {
824 self.layers[0].backing.wait_resize(sector_count)
825 }
826
827 async fn unmap(
828 &self,
829 sector_offset: u64,
830 sector_count: u64,
831 block_level_only: bool,
832 ) -> Result<(), DiskError> {
833 if self.unmap_behavior == UnmapBehavior::Ignored {
834 return Ok(());
835 }
836
837 for (layer, next_layer) in self
838 .layers
839 .iter()
840 .zip(self.layers.iter().map(Some).skip(1).chain([None]))
841 {
842 let next_is_zero = if let Some(next_layer) = next_layer {
843 sector_offset >= next_layer.visible_sector_count
849 } else {
850 true
851 };
852
853 layer
854 .backing
855 .unmap(sector_offset, sector_count, block_level_only, next_is_zero)
856 .await?;
857 if !layer.write_through {
858 break;
859 }
860 }
861 Ok(())
862 }
863
864 fn unmap_behavior(&self) -> UnmapBehavior {
865 self.unmap_behavior
866 }
867
868 fn optimal_unmap_sectors(&self) -> u32 {
869 self.optimal_unmap_sectors
870 }
871}
872
873#[derive(Inspect)]
875#[inspect(transparent)]
876struct DiskAsLayer(Disk);
877
878impl LayerIo for DiskAsLayer {
879 fn layer_type(&self) -> &str {
880 "disk"
881 }
882
883 fn sector_count(&self) -> u64 {
884 self.0.sector_count()
885 }
886
887 fn sector_size(&self) -> u32 {
888 self.0.sector_size()
889 }
890
891 fn disk_id(&self) -> Option<[u8; 16]> {
892 self.0.disk_id()
893 }
894
895 fn physical_sector_size(&self) -> u32 {
896 self.0.physical_sector_size()
897 }
898
899 fn is_fua_respected(&self) -> bool {
900 self.0.is_fua_respected()
901 }
902
903 fn is_logically_read_only(&self) -> bool {
904 self.0.is_read_only()
905 }
906
907 fn sync_cache(&self) -> impl Future<Output = Result<(), DiskError>> + Send {
908 self.0.sync_cache()
909 }
910
911 async fn read(
912 &self,
913 buffers: &RequestBuffers<'_>,
914 sector: u64,
915 mut bitmap: SectorMarker<'_>,
916 ) -> Result<(), DiskError> {
917 bitmap.set_all();
919 self.0.read_vectored(buffers, sector).await
920 }
921
922 async fn write(
923 &self,
924 buffers: &RequestBuffers<'_>,
925 sector: u64,
926 fua: bool,
927 ) -> Result<(), DiskError> {
928 self.0.write_vectored(buffers, sector, fua).await
929 }
930
931 fn unmap(
932 &self,
933 sector: u64,
934 count: u64,
935 block_level_only: bool,
936 _lower_is_zero: bool,
937 ) -> impl Future<Output = Result<(), DiskError>> + Send {
938 self.0.unmap(sector, count, block_level_only)
939 }
940
941 fn unmap_behavior(&self) -> UnmapBehavior {
942 self.0.unmap_behavior()
943 }
944}
945
946#[cfg(test)]
947mod tests {
948 use crate::DiskLayer;
949 use crate::LayerConfiguration;
950 use crate::LayerIo;
951 use crate::LayeredDisk;
952 use crate::SectorMarker;
953 use crate::WriteNoOverwrite;
954 use disk_backend::DiskIo;
955 use disk_backend::UnmapBehavior;
956 use guestmem::GuestMemory;
957 use guestmem::MemoryRead as _;
958 use guestmem::MemoryWrite;
959 use inspect::Inspect;
960 use pal_async::async_test;
961 use parking_lot::Mutex;
962 use scsi_buffers::OwnedRequestBuffers;
963 use std::collections::BTreeMap;
964 use std::collections::btree_map::Entry;
965 use std::sync::Arc;
966
967 #[derive(Inspect)]
968 #[inspect(skip)]
969 struct TestLayer {
970 sectors: Mutex<BTreeMap<u64, Data>>,
971 sector_count: u64,
972 }
973
974 impl TestLayer {
975 fn new(sector_count: u64) -> Self {
976 Self {
977 sectors: Mutex::new(BTreeMap::new()),
978 sector_count,
979 }
980 }
981 }
982
983 struct Data(Box<[u8]>);
984
985 impl LayerIo for Arc<TestLayer> {
986 fn layer_type(&self) -> &str {
987 "test"
988 }
989
990 fn sector_count(&self) -> u64 {
991 self.sector_count
992 }
993
994 fn sector_size(&self) -> u32 {
995 512
996 }
997
998 fn disk_id(&self) -> Option<[u8; 16]> {
999 None
1000 }
1001
1002 fn physical_sector_size(&self) -> u32 {
1003 512
1004 }
1005
1006 fn is_fua_respected(&self) -> bool {
1007 false
1008 }
1009
1010 fn is_logically_read_only(&self) -> bool {
1011 false
1012 }
1013
1014 async fn sync_cache(&self) -> Result<(), disk_backend::DiskError> {
1015 Ok(())
1016 }
1017
1018 async fn read(
1019 &self,
1020 buffers: &scsi_buffers::RequestBuffers<'_>,
1021 sector: u64,
1022 mut marker: SectorMarker<'_>,
1023 ) -> Result<(), disk_backend::DiskError> {
1024 let sector_count = buffers.len() / self.sector_size() as usize;
1025 let sectors = self.sectors.lock();
1026 for i in sector..sector + sector_count as u64 {
1027 let Some(data) = sectors.get(&i) else {
1028 continue;
1029 };
1030 let offset = ((i - sector) * self.sector_size() as u64) as usize;
1031 buffers
1032 .subrange(offset, self.sector_size() as usize)
1033 .writer()
1034 .write(&data.0)?;
1035 marker.set(i);
1036 }
1037 Ok(())
1038 }
1039
1040 async fn write(
1041 &self,
1042 buffers: &scsi_buffers::RequestBuffers<'_>,
1043 sector: u64,
1044 _fua: bool,
1045 ) -> Result<(), disk_backend::DiskError> {
1046 let sector_count = buffers.len() / self.sector_size() as usize;
1047 let mut sectors = self.sectors.lock();
1048 for i in sector..sector + sector_count as u64 {
1049 let offset = ((i - sector) * self.sector_size() as u64) as usize;
1050 let mut data = Data(vec![0; self.sector_size() as usize].into());
1051 buffers
1052 .subrange(offset, self.sector_size() as usize)
1053 .reader()
1054 .read(&mut data.0)?;
1055 sectors.insert(i, data);
1056 }
1057 Ok(())
1058 }
1059
1060 async fn unmap(
1061 &self,
1062 sector: u64,
1063 count: u64,
1064 _block_level_only: bool,
1065 next_is_zero: bool,
1066 ) -> Result<(), disk_backend::DiskError> {
1067 if !next_is_zero {
1068 return Ok(());
1069 }
1070 let mut sectors = self.sectors.lock();
1071 let mut next_sector = sector;
1072 let end = sector + count;
1073 while next_sector < end {
1074 let Some((§or, _)) = sectors.range_mut(next_sector..).next() else {
1075 break;
1076 };
1077 if sector >= end {
1078 break;
1079 }
1080 sectors.remove(§or);
1081 next_sector = sector + 1;
1082 }
1083 Ok(())
1084 }
1085
1086 fn unmap_behavior(&self) -> UnmapBehavior {
1087 UnmapBehavior::Unspecified
1088 }
1089
1090 fn write_no_overwrite(&self) -> Option<impl WriteNoOverwrite> {
1091 Some(self)
1092 }
1093 }
1094
1095 impl WriteNoOverwrite for Arc<TestLayer> {
1096 async fn write_no_overwrite(
1097 &self,
1098 buffers: &scsi_buffers::RequestBuffers<'_>,
1099 sector: u64,
1100 ) -> Result<(), disk_backend::DiskError> {
1101 let sector_count = buffers.len() / self.sector_size() as usize;
1102 let mut sectors = self.sectors.lock();
1103 for i in sector..sector + sector_count as u64 {
1104 let Entry::Vacant(entry) = sectors.entry(i) else {
1105 continue;
1106 };
1107 let offset = ((i - sector) * self.sector_size() as u64) as usize;
1108 let mut data = Data(vec![0; self.sector_size() as usize].into());
1109 buffers
1110 .subrange(offset, self.sector_size() as usize)
1111 .reader()
1112 .read(&mut data.0)?;
1113 entry.insert(data);
1114 }
1115 Ok(())
1116 }
1117 }
1118
1119 #[async_test]
1120 async fn test_read_cache() {
1121 const SIZE: u64 = 2048;
1122 let bottom = Arc::new(TestLayer::new(SIZE));
1123 let pattern = |i: u64| {
1124 let mut acc = (i + 1) * 3;
1125 Data(
1126 (0..512)
1127 .map(|_| {
1128 acc = acc.wrapping_mul(7);
1129 acc as u8
1130 })
1131 .collect::<Vec<_>>()
1132 .into(),
1133 )
1134 };
1135 bottom
1136 .sectors
1137 .lock()
1138 .extend((0..SIZE).map(|i| (i, pattern(i))));
1139
1140 let cache = Arc::new(TestLayer::new(SIZE));
1141 let cache_cfg = LayerConfiguration {
1142 layer: DiskLayer::new(cache.clone()),
1143 read_cache: true,
1144 write_through: false,
1145 };
1146 let bottom_cfg = LayerConfiguration {
1147 layer: DiskLayer::new(bottom),
1148 read_cache: false,
1149 write_through: false,
1150 };
1151 let disk = LayeredDisk::new(false, vec![cache_cfg, bottom_cfg])
1152 .await
1153 .unwrap();
1154
1155 let mut mem = GuestMemory::allocate(0x10000);
1156 let buffers = OwnedRequestBuffers::linear(0, 0x10000, true);
1157
1158 for i in [0, 2, 4, 6, 8, 0, 2, 4, 6, 8] {
1159 disk.read_vectored(&buffers.buffer(&mem).subrange(0, 512), i)
1160 .await
1161 .unwrap();
1162
1163 assert_eq!(mem.inner_buf_mut().unwrap()[..512], pattern(i).0[..]);
1164 }
1165
1166 assert_eq!(cache.sectors.lock().len(), 5);
1167
1168 mem.inner_buf_mut().unwrap().fill(0);
1169
1170 disk.read_vectored(&buffers.buffer(&mem).subrange(0, 15 * 512), 1)
1171 .await
1172 .unwrap();
1173
1174 assert_eq!(cache.sectors.lock().len(), 16);
1175
1176 for i in 0..15 {
1177 assert_eq!(
1178 mem.inner_buf_mut().unwrap()[i as usize * 512..][..512],
1179 pattern(i + 1).0[..],
1180 "{i}"
1181 );
1182 }
1183 }
1184}