fix(windows): handle zfs volume paths (#3157)

* fix(windows): handle zfs volume paths

* fix(windows): address volume path review

* refactor(windows): share fallback path resolution

---------

Co-authored-by: houseme <housemecn@gmail.com>
This commit is contained in:
cxymds
2026-06-01 21:04:40 +08:00
committed by GitHub
parent e91e513ab3
commit 39a283fbce
4 changed files with 128 additions and 15 deletions
+17
View File
@@ -19,6 +19,23 @@ use std::{fmt::Display, path::Path};
use tracing::debug;
use url::{ParseError, Url};
#[cfg(windows)]
pub(crate) fn windows_fallback_local_path(
path: &str,
canonicalize_error: &std::io::Error,
context: &'static str,
) -> std::io::Result<std::path::PathBuf> {
let absolute = Path::new(path).absolutize()?.to_path_buf();
tracing::warn!(
path = %path,
canonicalize_error = %canonicalize_error,
resolved = ?absolute,
context = context,
"using windows fallback path resolution for local endpoint"
);
Ok(absolute)
}
/// enum for endpoint type.
#[derive(PartialEq, Eq, Debug)]
pub enum EndpointType {
+51 -11
View File
@@ -356,20 +356,60 @@ impl Debug for LocalDisk {
}
}
/// Resolve the local disk root path from an endpoint path.
///
/// Tries `canonicalize` first (fast path). On Windows, if canonicalization reports
/// `NotFound` for paths that may still be valid mount roots, falls back to
/// `absolutize` + metadata check to accept valid local directory roots that
/// don't support full canonicalization.
fn resolve_local_disk_root(ep_path: &str) -> Result<PathBuf> {
match rustfs_utils::canonicalize(ep_path) {
Ok(path) => Ok(path),
Err(err) => {
if err.kind() != ErrorKind::NotFound {
return Err(to_file_error(err).into());
}
#[cfg(windows)]
{
// On Windows, canonicalize can fail for ZFS volumes, junction points,
// subst drives, and other non-standard filesystem mounts. Try a fallback
// path resolution using absolutize + metadata check.
let absolute = match crate::disk::endpoint::windows_fallback_local_path(ep_path, &err, "local disk root") {
Ok(path) => path,
Err(_) => {
return Err(DiskError::VolumeNotFound);
}
};
match std::fs::metadata(&absolute) {
Ok(metadata) => {
if !metadata.is_dir() {
return Err(DiskError::DiskNotDir);
}
return Ok(absolute);
}
Err(meta_err) => {
if meta_err.kind() == ErrorKind::NotFound {
return Err(DiskError::VolumeNotFound);
}
return Err(to_file_error(meta_err).into());
}
}
}
#[cfg(not(windows))]
{
Err(DiskError::VolumeNotFound)
}
}
}
}
impl LocalDisk {
pub async fn new(ep: &Endpoint, cleanup: bool) -> Result<Self> {
debug!("Creating local disk");
// Use optimized path resolution instead of absolutize() for better performance
// Use dunce::canonicalize instead of std::fs::canonicalize to avoid UNC paths on Windows
let root = match rustfs_utils::canonicalize(ep.get_file_path()) {
Ok(path) => path,
Err(e) => {
if e.kind() == ErrorKind::NotFound {
return Err(DiskError::VolumeNotFound);
}
return Err(to_file_error(e).into());
}
};
let root = resolve_local_disk_root(&ep.get_file_path())?;
ensure_data_usage_layout(&root).await.map_err(DiskError::from)?;