Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Doesn't link to libzutil on FreeBSD #65

Closed
asomers opened this issue Jul 27, 2021 · 0 comments · Fixed by #66
Closed

Doesn't link to libzutil on FreeBSD #65

asomers opened this issue Jul 27, 2021 · 0 comments · Fixed by #66

Comments

@asomers
Copy link
Contributor

asomers commented Jul 27, 2021

On FreeBSD, libzfs_core needs to link to libzutil. zfs-core-sys/build.rs does indeed specify that correctly. However, the resulting binaries don't end up linked to libzutil. It seems like rustc ignores the -l zutil option because the Rust code doesn't have direct references to libzutil, and Rust doesn't consider transitive linking dependencies. Probably related to bazelbuild/rules_rust#78 .

To demonstrate the problem:

cargo build --all-targets
> ldd target/debug/deps/basic-6af3a0e39594d1eb
target/debug/deps/basic-6af3a0e39594d1eb:
	libzfs_core.so.2 => /lib/libzfs_core.so.2 (0x801204000)
	libnvpair.so.2 => /lib/libnvpair.so.2 (0x80120d000)
	libthr.so.3 => /lib/libthr.so.3 (0x801227000)
	libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x801254000)
	libc.so.7 => /lib/libc.so.7 (0x80126f000)
	libm.so.5 => /lib/libm.so.5 (0x801690000)
# Notice no libzutil

However, apply this stupid little patch to the source tree, which calls a libzutil function that does literally nothing, and magically the binaries are all correctly linked:

diff --git a/zfs-core-sys/src/lib.rs b/zfs-core-sys/src/lib.rs
index 2d6a893..d1c85d1 100644
--- a/zfs-core-sys/src/lib.rs
+++ b/zfs-core-sys/src/lib.rs
@@ -6,3 +6,11 @@ extern crate nvpair_sys as nvpair;
 use nvpair::*;
 
 include!("bindings.rs");
+
+
+extern "C" {
+    /// This function does literally nothing on FreeBSD, but we must reference
+    /// it so the optimizer doesn't "helpfully" remove the linkage to
+    /// libzutil.so.
+    pub fn zfs_dev_flush(fd: i32) -> i32;
+}
diff --git a/zfs-core/src/lib.rs b/zfs-core/src/lib.rs
index e56222c..29f38c0 100644
--- a/zfs-core/src/lib.rs
+++ b/zfs-core/src/lib.rs
@@ -146,6 +146,7 @@ impl Zfs {
     /// Create a handle to the Zfs subsystem
     #[doc(alias = "libzfs_core_init")]
     pub fn new() -> io::Result<Self> {
+        unsafe { sys::zfs_dev_flush(0); }
         let v = unsafe { sys::libzfs_core_init() };
 
         if v != 0 {
> ldd target/debug/deps/basic-6af3a0e39594d1eb
target/debug/deps/basic-6af3a0e39594d1eb:
	libzutil.so.2 => /lib/libzutil.so.2 (0x801204000)
	libzfs_core.so.2 => /lib/libzfs_core.so.2 (0x801211000)
	libnvpair.so.2 => /lib/libnvpair.so.2 (0x80121a000)
	libthr.so.3 => /lib/libthr.so.3 (0x801234000)
	libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x801261000)
	libc.so.7 => /lib/libc.so.7 (0x80127c000)
	libm.so.5 => /lib/libm.so.5 (0x80169d000)
	libavl.so.2 => /lib/libavl.so.2 (0x8016d4000)
	libtpool.so.2 => /lib/libtpool.so.2 (0x8016d9000)
	libspl.so.2 => /lib/libspl.so.2 (0x8016df000)
bors bot added a commit that referenced this issue Aug 4, 2021
66: Fix linking to libzutil on FreeBSD r=jmesmon a=asomers

Rust needs to use -as-needed when linking to transitive dependencies.
At least, on some targets.  It's undocumented which targets require
that.  This option is not documented in the Cargo Book, only in the RFC
Book:
https://rust-lang.github.io/rfcs/2951-native-link-modifiers.html

Fixes #65

Co-authored-by: Alan Somers <[email protected]>
@bors bors bot closed this as completed in 70923d4 Aug 4, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant