-
Notifications
You must be signed in to change notification settings - Fork 77
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
install-to-disk: Check for mounts before install #805
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,6 +12,7 @@ use crate::task::Task; | |
|
||
#[derive(Deserialize, Debug)] | ||
#[serde(rename_all = "kebab-case")] | ||
#[allow(dead_code)] | ||
pub(crate) struct Filesystem { | ||
// Note if you add an entry to this list, you need to change the --output invocation below too | ||
pub(crate) source: String, | ||
|
@@ -21,14 +22,15 @@ pub(crate) struct Filesystem { | |
pub(crate) fstype: String, | ||
pub(crate) options: String, | ||
pub(crate) uuid: Option<String>, | ||
pub(crate) children: Option<Vec<Filesystem>>, | ||
} | ||
|
||
#[derive(Deserialize, Debug)] | ||
pub(crate) struct Findmnt { | ||
pub(crate) filesystems: Vec<Filesystem>, | ||
} | ||
|
||
fn run_findmnt(args: &[&str], path: &str) -> Result<Filesystem> { | ||
fn run_findmnt(args: &[&str], path: &str) -> Result<Findmnt> { | ||
let o: Findmnt = Command::new("findmnt") | ||
.args([ | ||
"-J", | ||
|
@@ -40,6 +42,12 @@ fn run_findmnt(args: &[&str], path: &str) -> Result<Filesystem> { | |
.arg(path) | ||
.log_debug() | ||
.run_and_parse_json()?; | ||
Ok(o) | ||
} | ||
|
||
// Retrieve a mounted filesystem from a device given a matching path | ||
fn findmnt_filesystem(args: &[&str], path: &str) -> Result<Filesystem> { | ||
let o = run_findmnt(args, path)?; | ||
o.filesystems | ||
.into_iter() | ||
.next() | ||
|
@@ -50,13 +58,42 @@ fn run_findmnt(args: &[&str], path: &str) -> Result<Filesystem> { | |
/// Inspect a target which must be a mountpoint root - it is an error | ||
/// if the target is not the mount root. | ||
pub(crate) fn inspect_filesystem(path: &Utf8Path) -> Result<Filesystem> { | ||
run_findmnt(&["--mountpoint"], path.as_str()) | ||
findmnt_filesystem(&["--mountpoint"], path.as_str()) | ||
} | ||
|
||
#[context("Inspecting filesystem by UUID {uuid}")] | ||
/// Inspect a filesystem by partition UUID | ||
pub(crate) fn inspect_filesystem_by_uuid(uuid: &str) -> Result<Filesystem> { | ||
run_findmnt(&["--source"], &(format!("UUID={uuid}"))) | ||
findmnt_filesystem(&["--source"], &(format!("UUID={uuid}"))) | ||
} | ||
|
||
// Check if a specified device contains an already mounted filesystem | ||
pub(crate) fn is_mounted_in_pid1_mountns(path: String) -> Result<bool> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's make this take There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Updated, will resolve when pushed |
||
let o = run_findmnt(&["-N"], "1")?; | ||
for fs in o.filesystems.iter() { | ||
if is_source_mounted(&path, fs)? { | ||
return Ok(true); | ||
} | ||
} | ||
|
||
Ok(false) | ||
Comment on lines
+73
to
+79
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is all fine but with the below change could be condensed to something like Or:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Updated, will resolve when pushed |
||
} | ||
|
||
// Recursively check a given filesystem to see if it contains an already mounted source | ||
pub(crate) fn is_source_mounted(path: &String, mounted_fs: &Filesystem) -> Result<bool> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Updated, will resolve when pushed |
||
if mounted_fs.source.contains(path) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A bit uncertain about Just thinking through this...what is probably cleaner actually is to do a set-intersection; on the calling side loop through all children of the device. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure I follow what you're saying, my understanding is that we want to see if Are you saying that this should only fail if the device alone is mounted? As in it shouldn't be checking the partitions of the device? That's the reasoning behind the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think what I mean is doing the check like this:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Or maybe cleaner actually, make There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So instead of looping through the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That was my original thought a couple of weeks ago when I first looked at this, I ended up going with parsing the For the code block you noted above, should mount checking be within the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Eh nevermind, no need to bikeshed this one fully, I think it's fine as is. Let's just do the minor tweaks and get it in! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Copy that, will push as soon as I run through my testing |
||
return Ok(true); | ||
} | ||
|
||
if let Some(ref children) = mounted_fs.children { | ||
for child in children { | ||
if is_source_mounted(path, child)? { | ||
return Ok(true); | ||
} | ||
} | ||
} | ||
|
||
Ok(false) | ||
} | ||
|
||
/// Mount a device to the target path. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"already mounted filesystem in the root mount namespace" or so.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated, will resolve when pushed