aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKent Overstreet <kent.overstreet@linux.dev>2023-01-03 22:31:36 -0500
committerKent Overstreet <kent.overstreet@linux.dev>2023-02-21 01:03:08 -0500
commit28f703cc256fb6ae209aba1d1fe509d603de1735 (patch)
tree220fc0e14cd29a3b56fe18dc8594d7bb4fe66718
parentda6a35689518599b381c285cd9505ab8d58f7c73 (diff)
downloadbcachefs-tools-28f703cc256fb6ae209aba1d1fe509d603de1735.tar.gz
Rust now integrated into bcachefs binary
Rust is now required for building the bcachefs tool, and rust code is now fully integrated with the C codebase - meaning it is possible to call back and forth. The mount helper is now a subcommand, 'mount.bcachefs' is now a small shell wrapper that invokes 'bcachefs mount'. This will make it easier to start rewriting other subcommands in rust, and eventually the whole command line interface. Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
-rw-r--r--.gitignore4
-rw-r--r--Makefile43
-rw-r--r--bcachefs.c17
-rw-r--r--cmds.h1
-rwxr-xr-xmount.bcachefs4
-rw-r--r--rust-src/.gitignore (renamed from rust-src/mount/.gitignore)0
-rw-r--r--rust-src/Cargo.lock (renamed from rust-src/mount/Cargo.lock)2
-rw-r--r--rust-src/Cargo.toml (renamed from rust-src/mount/Cargo.toml)7
-rw-r--r--rust-src/README.md (renamed from rust-src/mount/README.md)0
-rw-r--r--rust-src/bch_bindgen/build.rs7
-rw-r--r--rust-src/default.nix (renamed from rust-src/mount/default.nix)0
-rw-r--r--rust-src/module.nix (renamed from rust-src/mount/module.nix)0
-rw-r--r--rust-src/mount/src/main.rs53
-rw-r--r--rust-src/rustfmt.toml (renamed from rust-src/mount/rustfmt.toml)0
-rw-r--r--rust-src/src/cmd_mount.rs (renamed from rust-src/mount/src/lib.rs)110
-rw-r--r--rust-src/src/filesystem.rs (renamed from rust-src/mount/src/filesystem.rs)0
-rw-r--r--rust-src/src/key.rs (renamed from rust-src/mount/src/key.rs)43
-rw-r--r--rust-src/src/lib.rs33
18 files changed, 151 insertions, 173 deletions
diff --git a/.gitignore b/.gitignore
index 7ba6add8..15accd00 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,8 +6,6 @@ bcachefs.5
*.so
*.d
*.a
-/rust-src/mount/result
-/rust-src/bch_bindgen/result
tags
TAGS
cscope*
@@ -21,6 +19,4 @@ tests/__pycache__/
!.travis.yml
!.editorconfig
-mount/target
-mount.bcachefs
bcachefs-principles-of-operation.*
diff --git a/Makefile b/Makefile
index bce10d5b..8846e127 100644
--- a/Makefile
+++ b/Makefile
@@ -90,10 +90,11 @@ else
endif
.PHONY: all
-all: bcachefs lib
+all: bcachefs
-.PHONY: lib
-lib: libbcachefs.so
+.PHONY: debug
+debug: CFLAGS+=-Werror -DCONFIG_BCACHEFS_DEBUG=y -DCONFIG_VALGRIND=y
+debug: bcachefs
.PHONY: tests
tests: tests/test_helper
@@ -123,30 +124,17 @@ OBJS=$(SRCS:.c=.o)
@echo " [CC] $@"
$(Q)$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<
-bcachefs: $(filter-out ./tests/%.o, $(OBJS))
+bcachefs: libbcachefs.a rust-src/target/release/libbcachefs_rust.a
@echo " [LD] $@"
- $(Q)$(CC) $(LDFLAGS) $+ $(LOADLIBES) $(LDLIBS) -o $@
-
-RUST_SRCS=$(shell find rust-src/ -type f -iname '*.rs')
-MOUNT_SRCS=$(filter %mount, $(RUST_SRCS))
-
-debug: CFLAGS+=-Werror -DCONFIG_BCACHEFS_DEBUG=y -DCONFIG_VALGRIND=y
-debug: bcachefs
-
-MOUNT_OBJ=$(filter-out ./bcachefs.o ./tests/%.o ./cmd_%.o , $(OBJS))
-libbcachefs.so: LDFLAGS+=-shared
-libbcachefs.so: $(MOUNT_OBJ)
- @echo " [CC] $@"
- $(Q)$(CC) $(LDFLAGS) $+ -o $@ $(LDLIBS)
-
-MOUNT_TOML=rust-src/mount/Cargo.toml
-mount.bcachefs: lib $(MOUNT_SRCS)
- LIBBCACHEFS_LIB=$(CURDIR) \
- LIBBCACHEFS_INCLUDE=$(CURDIR) \
- $(CARGO_BUILD) --manifest-path $(MOUNT_TOML)
+ $(Q)$(CC) $(LDFLAGS) -Wl,--whole-archive $+ $(LOADLIBES) -Wl,--no-whole-archive $(LDLIBS) -o $@
- ln -f rust-src/mount/target/$(CARGO_PROFILE)/bcachefs-mount $@
+libbcachefs.a: $(filter-out ./tests/%.o, $(OBJS))
+ @echo " [AR] $@"
+ $(Q)ar -rc $@ $+
+RUST_SRCS=$(shell find rust-src/ -type f -iname '*.rs')
+rust-src/target/release/libbcachefs_rust.a: libbcachefs.a $(RUST_SRCS)
+ $(CARGO_BUILD) --manifest-path rust-src/Cargo.toml
tests/test_helper: $(filter ./tests/%.o, $(OBJS))
@echo " [LD] $@"
@@ -166,15 +154,14 @@ cmd_version.o : .version
.PHONY: install
install: INITRAMFS_HOOK=$(INITRAMFS_DIR)/hooks/bcachefs
install: INITRAMFS_SCRIPT=$(INITRAMFS_DIR)/scripts/local-premount/bcachefs
-install: bcachefs lib
+install: bcachefs
$(INSTALL) -m0755 -D bcachefs -t $(DESTDIR)$(ROOT_SBINDIR)
$(INSTALL) -m0755 fsck.bcachefs $(DESTDIR)$(ROOT_SBINDIR)
$(INSTALL) -m0755 mkfs.bcachefs $(DESTDIR)$(ROOT_SBINDIR)
+ $(INSTALL) -m0755 mount.bcachefs $(DESTDIR)$(ROOT_SBINDIR)
$(INSTALL) -m0644 -D bcachefs.8 -t $(DESTDIR)$(PREFIX)/share/man/man8/
$(INSTALL) -m0755 -D initramfs/script $(DESTDIR)$(INITRAMFS_SCRIPT)
$(INSTALL) -m0755 -D initramfs/hook $(DESTDIR)$(INITRAMFS_HOOK)
- $(INSTALL) -m0755 -D mount.bcachefs.sh $(DESTDIR)$(ROOT_SBINDIR)
- $(INSTALL) -m0755 -D libbcachefs.so -t $(DESTDIR)$(PREFIX)/lib/
sed -i '/^# Note: make install replaces/,$$d' $(DESTDIR)$(INITRAMFS_HOOK)
echo "copy_exec $(ROOT_SBINDIR)/bcachefs /sbin/bcachefs" >> $(DESTDIR)$(INITRAMFS_HOOK)
@@ -182,7 +169,7 @@ install: bcachefs lib
.PHONY: clean
clean:
@echo "Cleaning all"
- $(Q)$(RM) bcachefs mount.bcachefs libbcachefs.so libbcachefs_mount.a tests/test_helper .version *.tar.xz $(OBJS) $(DEPS) $(DOCGENERATED)
+ $(Q)$(RM) bcachefs libbcachefs.a tests/test_helper .version *.tar.xz $(OBJS) $(DEPS) $(DOCGENERATED)
$(Q)$(RM) -rf rust-src/*/target
.PHONY: deb
diff --git a/bcachefs.c b/bcachefs.c
index 31d96287..1876823c 100644
--- a/bcachefs.c
+++ b/bcachefs.c
@@ -177,8 +177,21 @@ int main(int argc, char *argv[])
setvbuf(stdout, NULL, _IOLBF, 0);
- char *cmd = pop_cmd(&argc, argv);
- if (argc < 1) {
+ if (argc < 2) {
+ puts("missing command\n");
+ goto usage;
+ }
+
+ /* Rust commands first - rust can't handle us mutating argv */
+ char *cmd = argv[1];
+
+ if (!strcmp(cmd, "mount")) {
+ cmd_mount();
+ return 0;
+ }
+
+ cmd = pop_cmd(&argc, argv);
+ if (!cmd) {
puts("missing command\n");
goto usage;
}
diff --git a/cmds.h b/cmds.h
index c18a87fd..52b6e0bb 100644
--- a/cmds.h
+++ b/cmds.h
@@ -61,5 +61,6 @@ int cmd_subvolume_delete(int argc, char *argv[]);
int cmd_subvolume_snapshot(int argc, char *argv[]);
int cmd_fusemount(int argc, char *argv[]);
+void cmd_mount(void);
#endif /* _CMDS_H */
diff --git a/mount.bcachefs b/mount.bcachefs
new file mode 100755
index 00000000..59002328
--- /dev/null
+++ b/mount.bcachefs
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+SDIR="$(readlink -f "$0")"
+exec "${SDIR%/*}/bcachefs" mount "$@"
diff --git a/rust-src/mount/.gitignore b/rust-src/.gitignore
index 644cd426..644cd426 100644
--- a/rust-src/mount/.gitignore
+++ b/rust-src/.gitignore
diff --git a/rust-src/mount/Cargo.lock b/rust-src/Cargo.lock
index 0b193360..9e5fd2a5 100644
--- a/rust-src/mount/Cargo.lock
+++ b/rust-src/Cargo.lock
@@ -44,7 +44,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
-name = "bcachefs-mount"
+name = "bcachefs-rust"
version = "0.3.1"
dependencies = [
"anyhow",
diff --git a/rust-src/mount/Cargo.toml b/rust-src/Cargo.toml
index 40113945..64b195ca 100644
--- a/rust-src/mount/Cargo.toml
+++ b/rust-src/Cargo.toml
@@ -1,10 +1,11 @@
[package]
-name = "bcachefs-mount"
+name = "bcachefs-rust"
version = "0.3.1"
authors = ["Yuxuan Shui <yshuiv7@gmail.com>", "Kayla Firestack <dev@kaylafire.me>"]
edition = "2018"
-# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+[lib]
+crate-type = ["staticlib"]
[dependencies]
atty = "0.2.14"
@@ -23,5 +24,5 @@ parse-display = "0.1"
errno = "0.2"
either = "1.5"
rpassword = "4"
-bch_bindgen = { path = "../bch_bindgen" }
+bch_bindgen = { path = "bch_bindgen" }
byteorder = "1.3"
diff --git a/rust-src/mount/README.md b/rust-src/README.md
index e4700f6b..e4700f6b 100644
--- a/rust-src/mount/README.md
+++ b/rust-src/README.md
diff --git a/rust-src/bch_bindgen/build.rs b/rust-src/bch_bindgen/build.rs
index da1541b1..a2cb8957 100644
--- a/rust-src/bch_bindgen/build.rs
+++ b/rust-src/bch_bindgen/build.rs
@@ -7,13 +7,8 @@ fn main() {
let top_dir: PathBuf = std::env::var_os("CARGO_MANIFEST_DIR")
.expect("ENV Var 'CARGO_MANIFEST_DIR' Expected")
.into();
- let libbcachefs_inc_dir = std::env::var("LIBBCACHEFS_INCLUDE")
- .unwrap_or_else(|_| top_dir.join("libbcachefs").display().to_string());
- let libbcachefs_inc_dir = std::path::Path::new(&libbcachefs_inc_dir);
- println!("{}", libbcachefs_inc_dir.display());
- println!("cargo:rustc-link-lib=dylib=bcachefs");
- println!("cargo:rustc-link-search={}", env!("LIBBCACHEFS_LIB"));
+ let libbcachefs_inc_dir = std::path::Path::new("../..");
let _libbcachefs_dir = top_dir.join("libbcachefs").join("libbcachefs");
let bindings = bindgen::builder()
diff --git a/rust-src/mount/default.nix b/rust-src/default.nix
index 7cc4b956..7cc4b956 100644
--- a/rust-src/mount/default.nix
+++ b/rust-src/default.nix
diff --git a/rust-src/mount/module.nix b/rust-src/module.nix
index b62aa7dc..b62aa7dc 100644
--- a/rust-src/mount/module.nix
+++ b/rust-src/module.nix
diff --git a/rust-src/mount/src/main.rs b/rust-src/mount/src/main.rs
deleted file mode 100644
index 66ec8acc..00000000
--- a/rust-src/mount/src/main.rs
+++ /dev/null
@@ -1,53 +0,0 @@
-use bcachefs_mount::Cli;
-use bch_bindgen::{error, info};
-use clap::Parser;
-use colored::Colorize;
-
-fn main() {
- let opt = Cli::parse();
- bch_bindgen::log::set_verbose_level(opt.verbose + bch_bindgen::log::ERROR);
- colored::control::set_override(opt.colorize);
- if let Err(e) = crate::main_inner(opt) {
- error!("Fatal error: {}", e);
- }
-}
-
-pub fn main_inner(opt: Cli) -> anyhow::Result<()> {
- use bcachefs_mount::{filesystem, key};
- unsafe {
- libc::setvbuf(filesystem::stdout, std::ptr::null_mut(), libc::_IONBF, 0);
- // libc::fflush(filesystem::stdout);
- }
-
- let fss = filesystem::probe_filesystems()?;
- let fs = fss
- .get(&opt.uuid)
- .ok_or_else(|| anyhow::anyhow!("filesystem was not found"))?;
-
- info!("found filesystem {}", fs);
- if fs.encrypted() {
- let key = opt
- .key_location
- .0
- .ok_or_else(|| anyhow::anyhow!("no keyoption specified for locked filesystem"))?;
-
- key::prepare_key(&fs, key)?;
- }
-
- let mountpoint = opt
- .mountpoint
- .ok_or_else(|| anyhow::anyhow!("mountpoint option was not specified"))?;
-
- fs.mount(&mountpoint, &opt.options)?;
-
- Ok(())
-}
-
-#[cfg(test)]
-mod test {
- // use insta::assert_debug_snapshot;
- // #[test]
- // fn snapshot_testing() {
- // insta::assert_debug_snapshot!();
- // }
-}
diff --git a/rust-src/mount/rustfmt.toml b/rust-src/rustfmt.toml
index 42f2ad7c..42f2ad7c 100644
--- a/rust-src/mount/rustfmt.toml
+++ b/rust-src/rustfmt.toml
diff --git a/rust-src/mount/src/lib.rs b/rust-src/src/cmd_mount.rs
index 68acde03..7748b199 100644
--- a/rust-src/mount/src/lib.rs
+++ b/rust-src/src/cmd_mount.rs
@@ -1,66 +1,11 @@
-use anyhow::anyhow;
-use atty::Stream;
+use bch_bindgen::{error, info};
use clap::Parser;
+use colored::Colorize;
+use atty::Stream;
use uuid::Uuid;
-
-pub mod err {
- pub enum GError {
- Unknown {
- message: std::borrow::Cow<'static, String>,
- },
- }
- pub type GResult<T, E, OE> = ::core::result::Result<::core::result::Result<T, E>, OE>;
- pub type Result<T, E> = GResult<T, E, GError>;
-}
-
-#[macro_export]
-macro_rules! c_str {
- ($lit:expr) => {
- unsafe {
- std::ffi::CStr::from_ptr(concat!($lit, "\0").as_ptr() as *const std::os::raw::c_char)
- .to_bytes_with_nul()
- .as_ptr() as *const std::os::raw::c_char
- }
- };
-}
-
-#[derive(Debug)]
-struct ErrnoError(errno::Errno);
-impl std::fmt::Display for ErrnoError {
- fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
- self.0.fmt(f)
- }
-}
-impl std::error::Error for ErrnoError {}
-
-#[derive(Clone, Debug)]
-pub enum KeyLocation {
- Fail,
- Wait,
- Ask,
-}
-
-#[derive(Clone, Debug)]
-pub struct KeyLoc(pub Option<KeyLocation>);
-impl std::ops::Deref for KeyLoc {
- type Target = Option<KeyLocation>;
- fn deref(&self) -> &Self::Target {
- &self.0
- }
-}
-impl std::str::FromStr for KeyLoc {
- type Err = anyhow::Error;
- fn from_str(s: &str) -> anyhow::Result<Self> {
- // use anyhow::anyhow;
- match s {
- "" => Ok(KeyLoc(None)),
- "fail" => Ok(KeyLoc(Some(KeyLocation::Fail))),
- "wait" => Ok(KeyLoc(Some(KeyLocation::Wait))),
- "ask" => Ok(KeyLoc(Some(KeyLocation::Ask))),
- _ => Err(anyhow!("invalid password option")),
- }
- }
-}
+use crate::filesystem;
+use crate::key;
+use crate::key::KeyLoc;
fn parse_fstab_uuid(uuid_raw: &str) -> Result<Uuid, uuid::Error> {
let mut uuid = String::from(uuid_raw);
@@ -114,12 +59,41 @@ pub struct Cli {
pub verbose: u8,
}
-pub mod filesystem;
-pub mod key;
-// pub fn mnt_in_use()
+pub fn cmd_mount_inner(opt: Cli) -> anyhow::Result<()> {
+ unsafe {
+ libc::setvbuf(filesystem::stdout, std::ptr::null_mut(), libc::_IONBF, 0);
+ }
-#[test]
-fn verify_cli() {
- use clap::CommandFactory;
- Cli::command().debug_assert()
+ let fss = filesystem::probe_filesystems()?;
+ let fs = fss
+ .get(&opt.uuid)
+ .ok_or_else(|| anyhow::anyhow!("filesystem was not found"))?;
+
+ info!("found filesystem {}", fs);
+ if fs.encrypted() {
+ let key = opt
+ .key_location
+ .0
+ .ok_or_else(|| anyhow::anyhow!("no keyoption specified for locked filesystem"))?;
+
+ key::prepare_key(&fs, key)?;
+ }
+
+ let mountpoint = opt
+ .mountpoint
+ .ok_or_else(|| anyhow::anyhow!("mountpoint option was not specified"))?;
+
+ fs.mount(&mountpoint, &opt.options)?;
+
+ Ok(())
+}
+
+#[no_mangle]
+pub extern "C" fn cmd_mount() {
+ let opt = Cli::parse();
+ bch_bindgen::log::set_verbose_level(opt.verbose + bch_bindgen::log::ERROR);
+ colored::control::set_override(opt.colorize);
+ if let Err(e) = cmd_mount_inner(opt) {
+ error!("Fatal error: {}", e);
+ }
}
diff --git a/rust-src/mount/src/filesystem.rs b/rust-src/src/filesystem.rs
index 28a2ab9e..28a2ab9e 100644
--- a/rust-src/mount/src/filesystem.rs
+++ b/rust-src/src/filesystem.rs
diff --git a/rust-src/mount/src/key.rs b/rust-src/src/key.rs
index a49baa68..e2d0e4c0 100644
--- a/rust-src/mount/src/key.rs
+++ b/rust-src/src/key.rs
@@ -1,5 +1,36 @@
use bch_bindgen::info;
use colored::Colorize;
+use crate::c_str;
+use anyhow::anyhow;
+
+#[derive(Clone, Debug)]
+pub enum KeyLocation {
+ Fail,
+ Wait,
+ Ask,
+}
+
+#[derive(Clone, Debug)]
+pub struct KeyLoc(pub Option<KeyLocation>);
+impl std::ops::Deref for KeyLoc {
+ type Target = Option<KeyLocation>;
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+
+impl std::str::FromStr for KeyLoc {
+ type Err = anyhow::Error;
+ fn from_str(s: &str) -> anyhow::Result<Self> {
+ match s {
+ "" => Ok(KeyLoc(None)),
+ "fail" => Ok(KeyLoc(Some(KeyLocation::Fail))),
+ "wait" => Ok(KeyLoc(Some(KeyLocation::Wait))),
+ "ask" => Ok(KeyLoc(Some(KeyLocation::Ask))),
+ _ => Err(anyhow!("invalid password option")),
+ }
+ }
+}
fn check_for_key(key_name: &std::ffi::CStr) -> anyhow::Result<bool> {
use bch_bindgen::keyutils::{self, keyctl_search};
@@ -31,7 +62,6 @@ fn wait_for_key(uuid: &uuid::Uuid) -> anyhow::Result<()> {
const BCH_KEY_MAGIC: &str = "bch**key";
use crate::filesystem::FileSystem;
fn ask_for_key(fs: &FileSystem) -> anyhow::Result<()> {
- use anyhow::anyhow;
use bch_bindgen::bcachefs::{self, bch2_chacha_encrypt_key, bch_encrypted_key, bch_key};
use byteorder::{LittleEndian, ReadBytesExt};
use std::os::raw::c_char;
@@ -84,14 +114,11 @@ fn ask_for_key(fs: &FileSystem) -> anyhow::Result<()> {
}
}
-pub fn prepare_key(fs: &FileSystem, password: crate::KeyLocation) -> anyhow::Result<()> {
- use crate::KeyLocation::*;
- use anyhow::anyhow;
-
+pub fn prepare_key(fs: &FileSystem, password: KeyLocation) -> anyhow::Result<()> {
info!("checking if key exists for filesystem {}", fs.uuid());
match password {
- Fail => Err(anyhow!("no key available")),
- Wait => Ok(wait_for_key(fs.uuid())?),
- Ask => ask_for_key(fs),
+ KeyLocation::Fail => Err(anyhow!("no key available")),
+ KeyLocation::Wait => Ok(wait_for_key(fs.uuid())?),
+ KeyLocation::Ask => ask_for_key(fs),
}
}
diff --git a/rust-src/src/lib.rs b/rust-src/src/lib.rs
new file mode 100644
index 00000000..b2f0aaa7
--- /dev/null
+++ b/rust-src/src/lib.rs
@@ -0,0 +1,33 @@
+pub mod filesystem;
+pub mod key;
+pub mod cmd_mount;
+
+pub mod err {
+ pub enum GError {
+ Unknown {
+ message: std::borrow::Cow<'static, String>,
+ },
+ }
+ pub type GResult<T, E, OE> = ::core::result::Result<::core::result::Result<T, E>, OE>;
+ pub type Result<T, E> = GResult<T, E, GError>;
+}
+
+#[macro_export]
+macro_rules! c_str {
+ ($lit:expr) => {
+ unsafe {
+ std::ffi::CStr::from_ptr(concat!($lit, "\0").as_ptr() as *const std::os::raw::c_char)
+ .to_bytes_with_nul()
+ .as_ptr() as *const std::os::raw::c_char
+ }
+ };
+}
+
+#[derive(Debug)]
+struct ErrnoError(errno::Errno);
+impl std::fmt::Display for ErrnoError {
+ fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
+ self.0.fmt(f)
+ }
+}
+impl std::error::Error for ErrnoError {}