-
Notifications
You must be signed in to change notification settings - Fork 193
blockdev: handle ZFS dataset sources in list_dev_by_dir #2138
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
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 | ||||
|---|---|---|---|---|---|---|
|
|
@@ -382,10 +382,39 @@ pub fn list_dev(dev: &Utf8Path) -> Result<Device> { | |||||
| .ok_or_else(|| anyhow!("no device output from lsblk for {dev}")) | ||||||
| } | ||||||
|
|
||||||
| #[context("Finding block device for ZFS dataset {dataset}")] | ||||||
| fn list_dev_for_zfs_dataset(dataset: &str) -> Result<Device> { | ||||||
| let dataset = dataset.strip_prefix("ZFS=").unwrap_or(dataset); | ||||||
| let pool = dataset | ||||||
| .split('/') | ||||||
| .next() | ||||||
| .ok_or_else(|| anyhow!("Invalid ZFS dataset: {dataset}"))?; | ||||||
|
|
||||||
| let output = Command::new("zpool") | ||||||
| .args(["list", "-H", "-v", "-P", pool]) | ||||||
| .run_get_string() | ||||||
| .with_context(|| format!("Querying ZFS pool {pool}"))?; | ||||||
|
|
||||||
| for line in output.lines() { | ||||||
| if line.starts_with('\t') || line.starts_with(' ') { | ||||||
| let dev_path = line.trim_start().split('\t').next().unwrap_or("").trim(); | ||||||
| if dev_path.starts_with('/') { | ||||||
| return list_dev(Utf8Path::new(dev_path)); | ||||||
| } | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| anyhow::bail!("Could not find a block device backing ZFS pool {pool}") | ||||||
| } | ||||||
|
|
||||||
| /// List the device containing the filesystem mounted at the given directory. | ||||||
| pub fn list_dev_by_dir(dir: &Dir) -> Result<Device> { | ||||||
| let fsinfo = bootc_mount::inspect_filesystem_of_dir(dir)?; | ||||||
| list_dev(&Utf8PathBuf::from(&fsinfo.source)) | ||||||
| let source = &fsinfo.source; | ||||||
| if fsinfo.fstype == "zfs" || (!source.starts_with('/') && source.contains('/')) { | ||||||
|
Contributor
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. The heuristic
Suggested change
|
||||||
| return list_dev_for_zfs_dataset(source); | ||||||
| } | ||||||
| list_dev(&Utf8PathBuf::from(source)) | ||||||
| } | ||||||
|
|
||||||
| pub struct LoopbackDevice { | ||||||
|
|
||||||
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.
The
split('/').next()call on a string will always returnSome(even for an empty string), making theok_or_elseblock unreachable. Furthermore, if thedatasetstring is empty or only contains theZFS=prefix,poolwill be an empty string, which will cause thezpoolcommand to fail later. It's safer to filter out empty strings to ensure a valid pool name is extracted.