Skip to content

Commit df0f057

Browse files
5ec1cffbackslashxx
authored andcommitted
magic_mount: supports whiteout
1 parent 78ce6de commit df0f057

File tree

1 file changed

+39
-23
lines changed

1 file changed

+39
-23
lines changed

userspace/ksud/src/magic_mount.rs

Lines changed: 39 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::defs::{KSU_MOUNT_SOURCE, MODULE_DIR, SKIP_MOUNT_FILE_NAME, TEMP_DIR};
2-
use crate::magic_mount::NodeFileType::{Directory, RegularFile, Symlink};
2+
use crate::magic_mount::NodeFileType::{Directory, RegularFile, Symlink, Whiteout};
33
use crate::restorecon::{lgetfilecon, lsetfilecon};
44
use anyhow::{bail, Context, Result};
55
use extattr::lgetxattr;
@@ -14,7 +14,7 @@ use std::collections::hash_map::Entry;
1414
use std::collections::HashMap;
1515
use std::fs;
1616
use std::fs::{create_dir, create_dir_all, read_dir, DirEntry, FileType};
17-
use std::os::unix::fs::symlink;
17+
use std::os::unix::fs::{symlink, FileTypeExt};
1818
use std::path::{Path, PathBuf};
1919

2020
const REPLACE_DIR_XATTR: &str = "trusted.overlay.opaque";
@@ -24,6 +24,7 @@ enum NodeFileType {
2424
RegularFile,
2525
Directory,
2626
Symlink,
27+
Whiteout,
2728
}
2829

2930
impl NodeFileType {
@@ -63,13 +64,9 @@ impl Node {
6364
}
6465
}
6566

66-
let file_type = entry.file_type()?;
67-
6867
let node = match self.children.entry(name.clone()) {
6968
Entry::Occupied(o) => Some(o.into_mut()),
70-
Entry::Vacant(v) => {
71-
Self::new_module(&name, file_type, &path).map(|it| v.insert(it))
72-
}
69+
Entry::Vacant(v) => Self::new_module(&name, &entry, &path).map(|it| v.insert(it)),
7370
};
7471

7572
if let Some(node) = node {
@@ -96,18 +93,30 @@ impl Node {
9693

9794
fn new_module<T: ToString, P: AsRef<Path>>(
9895
name: T,
99-
file_type: FileType,
96+
entry: &DirEntry,
10097
module_path: P,
10198
) -> Option<Self> {
102-
let file_type = NodeFileType::from_file_type(file_type)?;
99+
if let Ok(metadata) = entry.metadata() {
100+
let file_type = if metadata.file_type().is_char_device()
101+
&& metadata.dev() == 0
102+
&& metadata.ino() == 0
103+
{
104+
Some(Whiteout)
105+
} else {
106+
NodeFileType::from_file_type(metadata.file_type())
107+
};
108+
if let Some(file_type) = file_type {
109+
return Some(Node {
110+
name: name.to_string(),
111+
file_type,
112+
children: Default::default(),
113+
module_path: Some(PathBuf::from(module_path.as_ref())),
114+
replace: false,
115+
});
116+
}
117+
}
103118

104-
Some(Node {
105-
name: name.to_string(),
106-
file_type,
107-
children: Default::default(),
108-
module_path: Some(PathBuf::from(module_path.as_ref())),
109-
replace: false,
110-
})
119+
None
111120
}
112121
}
113122

@@ -251,13 +260,19 @@ fn do_magic_mount<P: AsRef<Path>, WP: AsRef<Path>>(
251260
if !has_tmpfs {
252261
for (name, node) in &current.children {
253262
let real_path = path.join(name);
254-
let need = if node.file_type == Symlink || !real_path.exists() {
255-
true
256-
} else {
257-
let file_type = real_path.metadata()?.file_type();
258-
let file_type =
259-
NodeFileType::from_file_type(file_type).unwrap_or(RegularFile);
260-
file_type != node.file_type || file_type == Symlink
263+
let need = match node.file_type {
264+
Symlink => true,
265+
Whiteout => real_path.exists(),
266+
_ => {
267+
if let Ok(metadata) = real_path.metadata() {
268+
let file_type = NodeFileType::from_file_type(metadata.file_type())
269+
.unwrap_or(Whiteout);
270+
file_type != node.file_type || file_type == Symlink
271+
} else {
272+
// real path not exists
273+
true
274+
}
275+
}
261276
};
262277
if need {
263278
create_tmpfs = need;
@@ -333,6 +348,7 @@ fn do_magic_mount<P: AsRef<Path>, WP: AsRef<Path>>(
333348
move_mount(&work_dir_path, &path)?;
334349
}
335350
}
351+
Whiteout => {}
336352
}
337353

338354
Ok(())

0 commit comments

Comments
 (0)