vhdx/medium/policies.rs
1//! File access and log replay policies.
2
3use crate::error::Result;
4
5// Policies
6// ---------------------------------------------------------------------------
7
8/// Log replay policy controlling how pending logs are handled on open.
9///
10/// # Standard
11///
12/// MS-VHDX §2.3 + MS-VHDX-只读扩展标准 §4.
13#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
14pub enum LogReplayPolicy {
15 /// If a replayable log exists, `finish()` returns
16 /// [`crate::error::Error::LogReplayRequired`]. No implicit replay.
17 ///
18 /// Standard: MS-VHDX-只读扩展标准 §4.1
19 #[default]
20 Require,
21
22 /// Automatically replay the log during `finish()`.
23 /// On read-only open, replay is done in memory only.
24 ///
25 /// Standard: MS-VHDX-只读扩展标准 §4.2
26 Auto,
27
28 /// In-memory replay is allowed for read-only opens.
29 /// Not valid for read-write opens.
30 ///
31 /// Standard: MS-VHDX-只读扩展标准 §4.3
32 InMemoryOnReadOnly,
33
34 /// Open read-only without replaying the log.
35 /// Only structure-level reads are guaranteed consistent;
36 /// payload data-plane reads may be inconsistent.
37 ///
38 /// Standard: MS-VHDX-只读扩展标准 §4.4
39 ReadOnlyNoReplay,
40}
41
42/// BAT read semantics policy.
43///
44/// Controls whether effective data or raw data is preferred when resolving
45/// block reads. For differencing disks, child data is always preferred
46/// regardless of this setting.
47#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
48pub enum ReadSemanticsPolicy {
49 /// Prefer effective (possibly parent-assembled) data.
50 #[default]
51 EffectiveDataPreferred,
52 /// Prefer raw on-disk data.
53 RawDataPreferred,
54}
55
56/// Request passed to a parent resolver when a differencing disk needs parent data.
57pub struct ParentRequest<'a> {
58 pub locator: crate::metadata::ParentLocator<'a>,
59 pub expected_data_write_guid: crate::types::Guid,
60 pub child_logical_sector_size: u32,
61 pub child_virtual_disk_size: u64,
62}
63
64impl ParentRequest<'_> {
65 /// Parent locator metadata from the child disk.
66 #[must_use]
67 pub fn locator(&self) -> &crate::metadata::ParentLocator<'_> {
68 &self.locator
69 }
70
71 /// Logical sector size required by the child disk.
72 #[must_use]
73 pub fn child_logical_sector_size(&self) -> u32 {
74 self.child_logical_sector_size
75 }
76
77 /// Parent Data Write GUID expected by the child locator.
78 #[must_use]
79 pub fn expected_data_write_guid(&self) -> crate::types::Guid {
80 self.expected_data_write_guid
81 }
82
83 /// Virtual disk size required by the child disk.
84 #[must_use]
85 pub fn child_virtual_disk_size(&self) -> u64 {
86 self.child_virtual_disk_size
87 }
88}
89
90/// A resolved parent medium that can serve effective parent sectors.
91pub trait ParentMedium {
92 /// Parent Data Write GUID used for differencing linkage validation.
93 ///
94 /// # Errors
95 ///
96 /// Returns an error if the parent GUID cannot be read.
97 fn data_write_guid(&mut self) -> Result<crate::types::Guid>;
98
99 /// Parent logical sector size in bytes.
100 ///
101 /// # Errors
102 ///
103 /// Returns an error if the parent sector size cannot be read.
104 fn logical_sector_size(&mut self) -> Result<u32>;
105
106 /// Read one effective parent sector into `buf`.
107 ///
108 /// # Errors
109 ///
110 /// Returns an error if the requested parent sector cannot be read.
111 fn read_sector(&mut self, sector: u64, buf: &mut [u8]) -> Result<()>;
112}
113
114impl<T> ParentMedium for std::cell::RefCell<T>
115where
116 T: ParentMedium,
117{
118 fn data_write_guid(&mut self) -> Result<crate::types::Guid> {
119 self.borrow_mut().data_write_guid()
120 }
121
122 fn logical_sector_size(&mut self) -> Result<u32> {
123 self.borrow_mut().logical_sector_size()
124 }
125
126 fn read_sector(&mut self, sector: u64, buf: &mut [u8]) -> Result<()> {
127 self.borrow_mut().read_sector(sector, buf)
128 }
129}
130
131/// User-provided resolver for differencing disk parent media.
132pub trait ParentResolver {
133 /// Resolve the parent medium for a child request.
134 ///
135 /// # Errors
136 ///
137 /// Returns an error if the parent medium cannot be resolved.
138 fn resolve_parent(&mut self, request: ParentRequest<'_>) -> Result<Box<dyn ParentMedium>>;
139}