Skip to content

Commit

Permalink
Do some work on freebsd support
Browse files Browse the repository at this point in the history
Unfortunately there's a bunch of system calls missing.
  • Loading branch information
anacrolix committed Feb 28, 2024
1 parent 5f115f7 commit 13aee01
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 2 deletions.
4 changes: 2 additions & 2 deletions README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ Efficiently removing data, and creating read snapshots requires hole punching, a

== Supported systems

macOS, Linux and Windows are supported. BSD should work. 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.
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).

== anacrolix/squirrel

I previously wrote https://github.com/anacrolix/squirrel[anacrolix/squirrel], which can fit the role of both in-memory or disk caching due to SQLite's VFS. However, it's written in Go and so is less accessible from other languages. Using SQLite for value storage means large streaming writes are exclusive, even within a single transaction. Value data is serialized to the blob format, potentially across multiple linked pages, and copied multiple times as items are evicted and moved around. Direct file I/O isn't available with SQLite, and the size of values must be known before they can be written, which can mean copying streams to temporary files before they can be written into the SQLite file.
I previously wrote https://github.com/anacrolix/squirrel[anacrolix/squirrel], which can fit the role of both in-memory or disk caching due to SQLite's VFS. However, it's written in Go and so is less accessible from other languages. Using SQLite for value storage means large streaming writes are exclusive, even within a single transaction. Value data is serialized to the blob format, potentially across multiple linked pages, and copied multiple times as items are evicted and moved around. Direct file I/O isn't available with SQLite, and the size of values must be known before they can be written, which can mean copying streams to temporary files before they can be written into the SQLite file.
10 changes: 10 additions & 0 deletions src/sys/clonefile/sys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,16 @@ pub fn fclonefile_noflags(src_file: &File, dst_path: &Path) -> PubResult<()> {
if rv == -1 {
return Err(last_errno());
}
} else if #[cfg(target_os = "freebsd")] {
// Looks like the syscall isn't ready yet.
// https://github.com/openzfs/zfs/pull/13392#issue-1221750354
let dst_file = File::create(dst_path)?;
let src_fd = src_file.as_raw_fd();
let dst_fd = dst_file.as_raw_fd();
let rv = libc::fclonefile(src_fd, dst_fd);
if rv == -1 {
return Err(last_errno());
}
} else {
// assert!(dst_path.is_absolute());
let dst_buf = CPathBuf::try_from(dst_path).unwrap();
Expand Down
35 changes: 35 additions & 0 deletions src/sys/punchfile/freebsd.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use std::{io, mem};
use std::io::Error;

use super::*;

pub fn punchfile(file: &File, offset: u64, length: u64) -> io::Result<()> {
// TODO: On solaris we want fcntl(F_FREESP);
let rqsr = libc::spacectl_range {
r_offset: offset.try_into().unwrap(),
r_len: length.try_into().unwrap(),
};
let mut rmsr: libc::spacectl_range = unsafe { mem::zeroed() };
let rv = unsafe {
libc::fspacectl(
file.as_fd().as_raw_fd(),
libc::SPACECTL_DEALLOC,
&rqsr,
0,
&mut rmsr,
)
};
if rv == -1 {
return Err(Error::last_os_error());
}
if rmsr.r_len != 0 {
warn!(
req_off = rqsr.r_offset,
req_len = rqsr.r_len,
unproc_off = rmsr.r_offset,
unproc_len = rmsr.r_len,
"spacectl dealloc returned unprocessed part"
);
}
Ok(())
}
4 changes: 4 additions & 0 deletions src/sys/punchfile/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ cfg_if! {
} else if #[cfg(windows)] {
mod windows;
pub use self::windows::*;
} else if #[cfg(target_os = "freebsd")] {
mod freebsd;
pub use freebsd::*;
} else {
// Looks like FreeBSD has fspacectl()
mod macos;
pub use macos::*;
}
Expand Down

0 comments on commit 13aee01

Please sign in to comment.