Skip to content

Commit

Permalink
Various tidying up for freebsd support
Browse files Browse the repository at this point in the history
  • Loading branch information
anacrolix committed Mar 3, 2024
1 parent 475e2f3 commit d58af58
Show file tree
Hide file tree
Showing 8 changed files with 46 additions and 11 deletions.
8 changes: 7 additions & 1 deletion README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,13 @@ Efficiently removing data, and creating read snapshots requires hole punching, a

== Supported systems

macOS, Linux and Windows are supported. FreeBSD doesn't work yet, unfortunately file cloning and open file description locking is missing, but there are fallbacks that can be used. Solaris requires a small amount of work to complete the implementation. On systems where block cloning is not supported (ext4 on Linux, and NTFS on Windows are notable examples), the implementation falls back to file region locking (except for FreeBSD which will have to fall back to whole-file locking).
macOS, Linux and Windows.

FreeBSD 14+. Unfortunately file cloning and open file description locking are missing. The implementation falls back on flock(2) and has to separate write and read files.

Solaris requires a small amount of work to complete the implementation.

On filesystems where block cloning is not supported (ext4 on Linux, and NTFS on Windows are notable examples), the implementation falls back to file region locking unless that is also not available (FreeBSD).

== anacrolix/squirrel

Expand Down
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,13 @@ Efficiently removing data, and creating read snapshots requires hole punching, a

## Supported systems

macOS, Linux and Windows are supported. FreeBSD doesn’t work yet, unfortunately file cloning and open file description locking is missing, but there are fallbacks that can be used. Solaris requires a small amount of work to complete the implementation. On systems where block cloning is not supported (ext4 on Linux, and NTFS on Windows are notable examples), the implementation falls back to file region locking (except for FreeBSD which will have to fall back to whole-file locking).
macOS, Linux and Windows.

FreeBSD 14+. Unfortunately file cloning and open file description locking are missing. The implementation falls back on flock(2) and has to separate write and read files.

Solaris requires a small amount of work to complete the implementation.

On filesystems where block cloning is not supported (ext4 on Linux, and NTFS on Windows are notable examples), the implementation falls back to file region locking unless that is also not available (FreeBSD).

## anacrolix/squirrel

Expand Down
8 changes: 6 additions & 2 deletions src/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,14 @@ pub(crate) fn emulate_freebsd() -> bool {
use once_cell::sync::OnceCell;
static CELL: OnceCell<bool> = OnceCell::new();
*CELL.get_or_init(|| {
!matches!(
let emulate = !matches!(
std::env::var("POSSUM_EMULATE_FREEBSD"),
Err(std::env::VarError::NotPresent)
)
);
if emulate {
super::error!("emulating freebsd");
}
emulate
})
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/exclusive_file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ use crate::FileId;

#[derive(Debug)]
enum LockLevel {
// On systems that don't implement flock, downgrades never occur.
#[allow(dead_code)]
Shared,
Exclusive,
}
Expand Down
22 changes: 19 additions & 3 deletions src/handle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ pub struct Handle {
pub(crate) instance_limits: Limits,
deleted_values: Option<DeletedValuesSender>,
_value_puncher: Option<std::thread::JoinHandle<()>>,
pub(crate) value_puncher_done: Arc<Mutex<std::sync::mpsc::Receiver<()>>>,
value_puncher_done: ValuePuncherDone,
}

/// 4 bytes stored in the database header https://sqlite.org/fileformat2.html#database_header.
Expand Down Expand Up @@ -108,7 +108,7 @@ impl Handle {
Self::init_sqlite_conn(&mut conn)?;
let (deleted_values, receiver) = std::sync::mpsc::sync_channel(10);
let (value_puncher_done_sender, value_puncher_done) = std::sync::mpsc::sync_channel(0);
let value_puncher_done = Arc::new(Mutex::new(value_puncher_done));
let value_puncher_done = ValuePuncherDone(Arc::new(Mutex::new(value_puncher_done)));
let handle = Self {
conn: Mutex::new(conn),
exclusive_files: Default::default(),
Expand Down Expand Up @@ -350,7 +350,6 @@ impl Handle {
file_id,
file_offset,
length,
..
} = &v;
let value_length = length;
let msg = format!(
Expand Down Expand Up @@ -390,6 +389,11 @@ impl Handle {
}
}
}

/// Returns something that can be used to test if the value puncher routine for this Handle has returned.
pub fn get_value_puncher_done(&self) -> ValuePuncherDone {
ValuePuncherDone(Arc::clone(&self.value_puncher_done.0))
}
}

use item::Item;
Expand All @@ -407,3 +411,15 @@ impl Drop for Handle {
// }
}
}

#[derive(Debug)]
pub struct ValuePuncherDone(Arc<Mutex<std::sync::mpsc::Receiver<()>>>);

impl ValuePuncherDone {
pub fn wait(&self) {
assert!(matches!(
self.0.lock().unwrap().recv(),
Err(std::sync::mpsc::RecvError)
))
}
}
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -816,6 +816,7 @@ impl<'a> Reader<'a> {
if flocking() {
// Possibly we want to block if we're flocking.
assert!(file.flock(LockShared)?);
return Ok(());
}
for extent in read_extents {
assert!(file.lock_segment(LockSharedNonblock, Some(extent.len), extent.offset)?);
Expand Down
4 changes: 2 additions & 2 deletions src/sys/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pub use flock::*;
pub(crate) use pathconf::*;
pub use punchfile::*;

use crate::env::flocking;
use crate::env::{emulate_freebsd, flocking};

cfg_if! {
if #[cfg(windows)] {
Expand Down Expand Up @@ -88,7 +88,7 @@ impl FileSystemFlags for UnixFilesystemFlags {
// AFAIK there's no way to check if a filesystem supports block cloning on non-Windows
// platforms, and even then it depends on where you're copying to/from, sometimes even on
// the same filesystem.
if flocking() {
if emulate_freebsd() {
Some(false)
} else {
None
Expand Down
4 changes: 2 additions & 2 deletions src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,10 @@ fn test_replace_keys() -> Result<()> {
);

let dir = handle.dir.clone();
let values_punched = Arc::clone(&handle.value_puncher_done);
let values_punched = handle.get_value_puncher_done();
drop(handle);
// Wait for it to recv, which should be a disconnect when the value_puncher hangs up.
values_punched.lock().unwrap().recv();
values_punched.wait();

let entries = dir.walk_dir()?;
let values_files: Vec<_> = entries
Expand Down

0 comments on commit d58af58

Please sign in to comment.