Skip to main content

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}