Skip to content

Commit 0d082b2

Browse files
anpCQ Bot
authored andcommitted
[starnix] Use SNAPSHOT_MODIFIED in clone().
This allows us to avoid mutating the parent's memory manager when cloning to a new child. Change-Id: I6ae5394edec1b6ccb2b48f950f317090ca691ef3 Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/1192454 Commit-Queue: Auto-Submit <[email protected]> Fuchsia-Auto-Submit: Adam Perry <[email protected]> Reviewed-by: James Robinson <[email protected]>
1 parent 6bb505d commit 0d082b2

File tree

1 file changed

+14
-86
lines changed

1 file changed

+14
-86
lines changed

src/starnix/kernel/mm/memory_manager.rs

Lines changed: 14 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -3466,40 +3466,19 @@ impl MemoryManager {
34663466
where
34673467
L: LockBefore<MmDumpable>,
34683468
{
3469-
// TODO(https://fxbug.dev/42074633): When SNAPSHOT (or equivalent) is supported on pager-backed VMOs
3470-
// we can remove the hack below (which also won't be performant). For now, as a workaround,
3471-
// we use SNAPSHOT_AT_LEAST_ON_WRITE on both the child and the parent.
3472-
3473-
struct MemoryInfo {
3474-
memory: Arc<MemoryObject>,
3475-
size: u64,
3476-
3477-
// Indicates whether or not the memory object needs to be replaced on the parent as
3478-
// well.
3479-
needs_snapshot_on_parent: bool,
3480-
}
3481-
34823469
// Clones the `memory` and returns the `MemoryInfo` with the clone.
34833470
fn clone_memory(
34843471
memory: &Arc<MemoryObject>,
34853472
rights: zx::Rights,
3486-
) -> Result<MemoryInfo, Errno> {
3473+
) -> Result<Arc<MemoryObject>, Errno> {
34873474
let memory_info = memory.info()?;
34883475
let pager_backed = memory_info.flags.contains(zx::VmoInfoFlags::PAGER_BACKED);
34893476
Ok(if pager_backed && !rights.contains(zx::Rights::WRITE) {
3490-
MemoryInfo {
3491-
memory: memory.clone(),
3492-
size: memory_info.size_bytes,
3493-
needs_snapshot_on_parent: false,
3494-
}
3477+
memory.clone()
34953478
} else {
34963479
let mut cloned_memory = memory
34973480
.create_child(
3498-
if pager_backed {
3499-
zx::VmoChildOptions::SNAPSHOT_AT_LEAST_ON_WRITE
3500-
} else {
3501-
zx::VmoChildOptions::SNAPSHOT
3502-
} | zx::VmoChildOptions::RESIZABLE,
3481+
zx::VmoChildOptions::SNAPSHOT_MODIFIED | zx::VmoChildOptions::RESIZABLE,
35033482
0,
35043483
memory_info.size_bytes,
35053484
)
@@ -3509,54 +3488,28 @@ impl MemoryManager {
35093488
.replace_as_executable(&VMEX_RESOURCE)
35103489
.map_err(impossible_error)?;
35113490
}
3512-
MemoryInfo {
3513-
memory: Arc::new(cloned_memory),
3514-
size: memory_info.size_bytes,
3515-
needs_snapshot_on_parent: pager_backed,
3516-
}
3517-
})
3518-
}
3519-
3520-
fn snapshot_memory(
3521-
memory: &MemoryObject,
3522-
size: u64,
3523-
rights: zx::Rights,
3524-
) -> Result<Arc<MemoryObject>, Errno> {
3525-
let mut cloned_memory = memory
3526-
.create_child(
3527-
zx::VmoChildOptions::SNAPSHOT_AT_LEAST_ON_WRITE
3528-
| zx::VmoChildOptions::RESIZABLE,
3529-
0,
3530-
size,
3531-
)
3532-
.map_err(MemoryManager::get_errno_for_map_err)?;
35333491

3534-
if rights.contains(zx::Rights::EXECUTE) {
3535-
cloned_memory = cloned_memory
3536-
.replace_as_executable(&VMEX_RESOURCE)
3537-
.map_err(impossible_error)?;
3538-
}
3539-
Ok(Arc::new(cloned_memory))
3492+
Arc::new(cloned_memory)
3493+
})
35403494
}
35413495

35423496
// Hold the lock throughout the operation to uphold memory manager's invariants.
35433497
// See mm/README.md.
35443498
let state: &mut MemoryManagerState = &mut self.state.write();
35453499
let mut target_state = target.state.write();
3546-
let mut child_memorys = HashMap::<zx::Koid, MemoryInfo>::new();
3547-
let mut replaced_memorys = HashMap::<zx::Koid, Arc<MemoryObject>>::new();
3500+
let mut clone_cache = HashMap::<zx::Koid, Arc<MemoryObject>>::new();
35483501

35493502
#[cfg(feature = "alternate_anon_allocs")]
35503503
{
35513504
let backing_size = (state.user_vmar_info.base + state.user_vmar_info.len) as u64;
35523505
target_state.private_anonymous = state.private_anonymous.snapshot(backing_size)?;
35533506
}
35543507

3555-
for (range, mapping) in state.mappings.iter_mut() {
3508+
for (range, mapping) in state.mappings.iter() {
35563509
if mapping.flags.contains(MappingFlags::DONTFORK) {
35573510
continue;
35583511
}
3559-
match &mut mapping.backing {
3512+
match &mapping.backing {
35603513
MappingBacking::Memory(backing) => {
35613514
let memory_offset = backing.memory_offset + (range.start - backing.base) as u64;
35623515
let length = range.end - range.start;
@@ -3571,37 +3524,12 @@ impl MemoryManager {
35713524
create_anonymous_mapping_memory(length as u64)?
35723525
} else {
35733526
let basic_info = backing.memory.basic_info();
3574-
3575-
let MemoryInfo { memory, size: memory_size, needs_snapshot_on_parent } =
3576-
match child_memorys.entry(basic_info.koid) {
3577-
Entry::Occupied(o) => o.into_mut(),
3578-
Entry::Vacant(v) => {
3579-
v.insert(clone_memory(&backing.memory, basic_info.rights)?)
3580-
}
3581-
};
3582-
3583-
if *needs_snapshot_on_parent {
3584-
let replaced_memory = match replaced_memorys.entry(basic_info.koid) {
3585-
Entry::Occupied(o) => o.into_mut(),
3586-
Entry::Vacant(v) => v.insert(snapshot_memory(
3587-
&backing.memory,
3588-
*memory_size,
3589-
basic_info.rights,
3590-
)?),
3591-
};
3592-
map_in_vmar(
3593-
&state.user_vmar,
3594-
&state.user_vmar_info,
3595-
SelectedAddress::FixedOverwrite(range.start),
3596-
replaced_memory,
3597-
memory_offset,
3598-
length,
3599-
mapping.flags,
3600-
false,
3601-
)?;
3602-
3603-
backing.memory = replaced_memory.clone();
3604-
}
3527+
let memory = match clone_cache.entry(basic_info.koid) {
3528+
Entry::Occupied(o) => o.into_mut(),
3529+
Entry::Vacant(v) => {
3530+
v.insert(clone_memory(&backing.memory, basic_info.rights)?)
3531+
}
3532+
};
36053533
memory.clone()
36063534
};
36073535

0 commit comments

Comments
 (0)