Skip to content

Commit

Permalink
DLPX-81971 zvols and zettacache device discovery leads to deadlock (o…
Browse files Browse the repository at this point in the history
  • Loading branch information
grwilson authored Jul 28, 2022
1 parent 00d402d commit 1dd2749
Showing 1 changed file with 42 additions and 17 deletions.
59 changes: 42 additions & 17 deletions cmd/zfs_object_agent/zettacache/src/open.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::collections::BTreeMap;
use std::collections::HashMap;
use std::collections::HashSet;
use std::fs::Metadata;
use std::os::unix::fs::FileTypeExt;
use std::path::Path;
use std::path::PathBuf;
Expand Down Expand Up @@ -61,16 +62,52 @@ impl DiscoveredDevice {
}
}

#[cfg(target_os = "linux")]
async fn check_zvol(meta: Metadata) -> Result<()> {
use std::os::unix::prelude::MetadataExt;

let major_id = fs::read_to_string("/sys/module/zfs/parameters/zvol_major")
.await?
.trim()
.parse::<u64>()
.unwrap();

if nix::sys::stat::major(meta.rdev()) == major_id {
return Err(anyhow!("zvol major number ({major_id}) detected, skipping"));
}
Ok(())
}

#[cfg(not(target_os = "linux"))]
async fn check_zvol(_meta: Metadata) -> Result<()> {
Ok(())
}

async fn from_path(path: PathBuf) -> Result<Self> {
match fs::metadata(&path).await {
Ok(meta) => {
if meta.is_dir() {
return Err(anyhow!("{path:?} is a directory"));
}

let file_type = meta.file_type();
if !file_type.is_block_device() && !file_type.is_file() {
return Err(anyhow!("{path:?} is not a file nor a block device"));
}

match DiscoveredDevice::check_zvol(meta).await {
Ok(_) => {}
Err(err) => return Err(anyhow!("{path:?}: {err}")),
}
}
Err(why) => {
return Err(anyhow!("{path:?} metadata() failed. error: {why:?}"));
}
}
let mut file = File::open(&path)
.await
.with_context(|| format!("open {path:?}"))?;

let filetype = file.metadata().await?.file_type();
if !filetype.is_block_device() && !filetype.is_file() {
return Err(anyhow!("{path:?} is not a file nor a block device"));
}

let mut buf = vec![0u8; SUPERBLOCK_SIZE];
file.read_exact(&mut buf)
.await
Expand All @@ -91,18 +128,6 @@ async fn discover_devices(
let mut canonical_entries = HashSet::new();
let mut dir = fs::read_dir(dir_path).await?;
while let Some(entry) = dir.next_entry().await? {
match entry.metadata().await {
Ok(meta) => {
if meta.is_dir() {
continue;
}
}
Err(why) => {
debug!("discovery: {entry:?}.metadata() failed. error: {why:?}");
continue;
}
}

// In certain directories under /dev we've come across device symlinks
// that resolve to the same device (e.g. /dev/disk/by-id on AWS). In
// order to avoid trying to open the same device twice, we always
Expand Down

0 comments on commit 1dd2749

Please sign in to comment.