don't create src dir on readonly bind mount (#3084)

This commit is contained in:
Aiden McClelland
2025-12-19 23:26:15 -07:00
committed by GitHub
parent 2d0251e585
commit 5446c89bc0
5 changed files with 16 additions and 10 deletions

View File

@@ -8,6 +8,7 @@ use sha2::Sha256;
use ts_rs::TS;
use super::FileSystem;
use crate::disk::mount::filesystem::MountType;
use crate::prelude::*;
use crate::util::io::create_file;
@@ -48,7 +49,7 @@ impl<Src: AsRef<Path> + Send + Sync> FileSystem for Bind<Src> {
fn extra_args(&self) -> impl IntoIterator<Item = impl AsRef<std::ffi::OsStr>> {
["--bind"]
}
async fn pre_mount(&self, mountpoint: &Path) -> Result<(), Error> {
async fn pre_mount(&self, mountpoint: &Path, mount_type: MountType) -> Result<(), Error> {
let from_meta = tokio::fs::metadata(&self.src).await.ok();
let to_meta = tokio::fs::metadata(&mountpoint).await.ok();
if matches!(self.filetype, FileType::File)
@@ -58,7 +59,7 @@ impl<Src: AsRef<Path> + Send + Sync> FileSystem for Bind<Src> {
if to_meta.as_ref().map_or(false, |m| m.is_dir()) {
tokio::fs::remove_dir(mountpoint).await?;
}
if from_meta.is_none() {
if from_meta.is_none() && mount_type == MountType::ReadWrite {
create_file(self.src.as_ref()).await?.sync_all().await?;
}
if to_meta.is_none() {
@@ -68,7 +69,7 @@ impl<Src: AsRef<Path> + Send + Sync> FileSystem for Bind<Src> {
if to_meta.as_ref().map_or(false, |m| m.is_file()) {
tokio::fs::remove_file(mountpoint).await?;
}
if from_meta.is_none() {
if from_meta.is_none() && mount_type == MountType::ReadWrite {
tokio::fs::create_dir_all(self.src.as_ref()).await?;
}
if to_meta.is_none() {

View File

@@ -49,7 +49,7 @@ impl<EncryptedDir: AsRef<Path> + Send + Sync, Key: AsRef<str> + Send + Sync> Fil
mountpoint: P,
mount_type: super::MountType,
) -> Result<(), Error> {
self.pre_mount(mountpoint.as_ref()).await?;
self.pre_mount(mountpoint.as_ref(), mount_type).await?;
Command::new("mount")
.args(
default_mount_command(self, mountpoint, mount_type)

View File

@@ -14,6 +14,7 @@ use tokio::process::Command;
use ts_rs::TS;
use super::FileSystem;
use crate::disk::mount::filesystem::MountType;
use crate::prelude::*;
use crate::util::{FromStrParser, Invoke};
@@ -110,8 +111,8 @@ impl<Fs: FileSystem> FileSystem for IdMapped<Fs> {
async fn source(&self) -> Result<Option<impl AsRef<Path>>, Error> {
self.filesystem.source().await
}
async fn pre_mount(&self, mountpoint: &Path) -> Result<(), Error> {
self.filesystem.pre_mount(mountpoint).await?;
async fn pre_mount(&self, mountpoint: &Path, mount_type: MountType) -> Result<(), Error> {
self.filesystem.pre_mount(mountpoint, mount_type).await?;
let info = tokio::fs::metadata(mountpoint).await?;
for i in &self.idmap {
let uid_in_range = i.from_id <= info.uid() && i.from_id + i.range > info.uid();

View File

@@ -69,7 +69,7 @@ pub(self) async fn default_mount_impl(
mountpoint: impl AsRef<Path> + Send,
mount_type: MountType,
) -> Result<(), Error> {
fs.pre_mount(mountpoint.as_ref()).await?;
fs.pre_mount(mountpoint.as_ref(), mount_type).await?;
Command::from(default_mount_command(fs, mountpoint, mount_type).await?)
.capture(false)
.invoke(ErrorKind::Filesystem)
@@ -91,7 +91,11 @@ pub trait FileSystem: Send + Sync {
fn source(&self) -> impl Future<Output = Result<Option<impl AsRef<Path>>, Error>> + Send {
async { Ok(None::<&Path>) }
}
fn pre_mount(&self, mountpoint: &Path) -> impl Future<Output = Result<(), Error>> + Send {
fn pre_mount(
&self,
mountpoint: &Path,
#[allow(unused_variables)] mount_type: MountType,
) -> impl Future<Output = Result<(), Error>> + Send {
async move {
tokio::fs::create_dir_all(mountpoint).await?;
Ok(())

View File

@@ -6,7 +6,7 @@ use digest::generic_array::GenericArray;
use digest::{Digest, OutputSizeUser};
use sha2::Sha256;
use crate::disk::mount::filesystem::{FileSystem, ReadWrite};
use crate::disk::mount::filesystem::{FileSystem, MountType, ReadWrite};
use crate::disk::mount::guard::{GenericMountGuard, MountGuard};
use crate::prelude::*;
use crate::util::io::TmpDir;
@@ -38,7 +38,7 @@ impl<P0: AsRef<Path> + Send + Sync, P1: AsRef<Path> + Send + Sync, P2: AsRef<Pat
Box::new(lazy_format!("workdir={}", self.work.as_ref().display())),
]
}
async fn pre_mount(&self, mountpoint: &Path) -> Result<(), Error> {
async fn pre_mount(&self, mountpoint: &Path, _: MountType) -> Result<(), Error> {
tokio::fs::create_dir_all(self.upper.as_ref()).await?;
tokio::fs::create_dir_all(self.work.as_ref()).await?;
tokio::fs::create_dir_all(mountpoint).await?;