diff --git a/Cargo.lock b/Cargo.lock
index 01d223e832dd7a159e47ee373602994930bc1e42..3ae3a17190e7e72cdebce8dbd7b8855a8e44d937 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2,6 +2,21 @@
 # It is not intended for manual editing.
 version = 3
 
+[[package]]
+name = "addr2line"
+version = "0.19.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97"
+dependencies = [
+ "gimli",
+]
+
+[[package]]
+name = "adler"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
+
 [[package]]
 name = "aes"
 version = "0.7.5"
@@ -44,6 +59,21 @@ dependencies = [
  "winapi",
 ]
 
+[[package]]
+name = "backtrace"
+version = "0.3.67"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca"
+dependencies = [
+ "addr2line",
+ "cc",
+ "cfg-if",
+ "libc",
+ "miniz_oxide",
+ "object",
+ "rustc-demangle",
+]
+
 [[package]]
 name = "base64ct"
 version = "1.6.0"
@@ -80,6 +110,12 @@ version = "1.4.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
 
+[[package]]
+name = "cc"
+version = "1.0.79"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
+
 [[package]]
 name = "cfg-if"
 version = "1.0.0"
@@ -138,6 +174,28 @@ dependencies = [
  "termcolor",
 ]
 
+[[package]]
+name = "failure"
+version = "0.1.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86"
+dependencies = [
+ "backtrace",
+ "failure_derive",
+]
+
+[[package]]
+name = "failure_derive"
+version = "0.1.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "synstructure",
+]
+
 [[package]]
 name = "fuchsia-cprng"
 version = "0.1.1"
@@ -181,6 +239,12 @@ dependencies = [
  "wasi 0.11.0+wasi-snapshot-preview1",
 ]
 
+[[package]]
+name = "gimli"
+version = "0.27.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4"
+
 [[package]]
 name = "hermit-abi"
 version = "0.1.19"
@@ -217,12 +281,30 @@ version = "2.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
 
+[[package]]
+name = "miniz_oxide"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
+dependencies = [
+ "adler",
+]
+
 [[package]]
 name = "numtoa"
 version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef"
 
+[[package]]
+name = "object"
+version = "0.30.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439"
+dependencies = [
+ "memchr",
+]
+
 [[package]]
 name = "opaque-debug"
 version = "0.3.0"
@@ -342,6 +424,7 @@ dependencies = [
  "argon2",
  "base64ct",
  "env_logger",
+ "failure",
  "fuser",
  "getrandom",
  "libc",
@@ -371,6 +454,12 @@ version = "0.6.28"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
 
+[[package]]
+name = "rustc-demangle"
+version = "0.1.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d4a36c42d1873f9a77c53bde094f9664d9891bc604a45b4798fd2c389ed12e5b"
+
 [[package]]
 name = "seahash"
 version = "4.1.0"
@@ -400,6 +489,18 @@ dependencies = [
  "unicode-ident",
 ]
 
+[[package]]
+name = "synstructure"
+version = "0.12.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "unicode-xid",
+]
+
 [[package]]
 name = "termcolor"
 version = "1.2.0"
@@ -444,6 +545,12 @@ version = "1.0.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
 
+[[package]]
+name = "unicode-xid"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
+
 [[package]]
 name = "users"
 version = "0.11.0"
diff --git a/Cargo.toml b/Cargo.toml
index 4cbe883b4f7ad5889f59737dc81082f60552a716..cf56761a56116163179ec2a0b58fa8b691c02b0f 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -35,6 +35,7 @@ aes = { version = "=0.7.5", default-features = false }
 argon2 = { version = "0.3.4", default-features = false, features = ["alloc"] }
 base64ct = { version = "1", default-features = false }
 env_logger = { version = "0.9.0", optional = true }
+failure = "0.1.8"
 getrandom = { version = "0.2.5", optional = true }
 libc = "0.2"
 log = { version = "0.4.14", default-features = false, optional = true}
diff --git a/Makefile b/Makefile
index 0e233fd9744a52a0e5600703b9b8355c39f8adfe..222226946ab9b7ab9763bc118a0b2b1ea48c6df0 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,20 @@
+UNAME := $(shell uname)
+
+ifeq ($(UNAME),Darwin)
+	FUMOUNT=umount
+else ifeq ($(UNAME),FreeBSD)
+	FUMOUNT=sudo umount
+else
+	# Detect which version of the fusermount binary is available.
+	ifneq (, $(shell which fusermount3))
+		FUMOUNT=fusermount3 -u
+	else
+		FUMOUNT=fusermount -u
+	endif
+endif
+
 image.bin:
-	dd if=/dev/zero of=image.bin bs=1M count=1024
+	dd if=/dev/zero of=image.bin bs=1048576 count=1024
 	cargo build --release --bin redoxfs-mkfs
 	target/release/redoxfs-mkfs image.bin
 
@@ -10,12 +25,12 @@ mount: image.bin FORCE
 
 unmount: FORCE
 	sync
-	-fusermount -u image
+	-${FUMOUNT} image
 	rm -rf image
 
 clean: FORCE
 	sync
-	-fusermount -u image
+	-${FUMOUNT} image
 	rm -rf image image.bin
 	cargo clean
 
diff --git a/src/lib.rs b/src/lib.rs
index 03deee8a9f9f303b6ed41391ada827f4ca74d787..3e8b0f385a7341146eded7af08d35fdad4ecfc15 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -27,6 +27,7 @@ pub use self::mount::mount;
 pub use self::node::{Node, NodeLevel};
 pub use self::transaction::Transaction;
 pub use self::tree::{Tree, TreeData, TreeList, TreePtr};
+pub use self::unmount::unmount_path;
 
 mod allocator;
 #[cfg(feature = "std")]
@@ -42,6 +43,8 @@ mod mount;
 mod node;
 mod transaction;
 mod tree;
+#[cfg(feature = "std")]
+mod unmount;
 
 #[cfg(all(feature = "std", test))]
 mod tests;
diff --git a/src/tests.rs b/src/tests.rs
index eff15368a1ee3598c9e92a68f828a5ecefca98d5..2fd0ca619e32bc99944312ba870a77fa2f468d5b 100644
--- a/src/tests.rs
+++ b/src/tests.rs
@@ -3,7 +3,7 @@ use std::path::Path;
 use std::process::Command;
 use std::{fs, sync, thread, time};
 
-use crate::{DiskSparse, FileSystem};
+use crate::{unmount_path, DiskSparse, FileSystem};
 
 fn with_redoxfs<T, F>(callback: F) -> T
 where
@@ -43,17 +43,7 @@ where
                         panic!("sync failed");
                     }
 
-                    let status_res = if cfg!(target_os = "linux") {
-                        Command::new("fusermount")
-                            .arg("-u")
-                            .arg(mount_path)
-                            .status()
-                    } else {
-                        Command::new("umount").arg(mount_path).status()
-                    };
-
-                    let status = dbg!(status_res).unwrap();
-                    if !status.success() {
+                    if !unmount_path(mount_path).is_ok() {
                         panic!("umount failed");
                     }
                 }
diff --git a/src/unmount.rs b/src/unmount.rs
new file mode 100644
index 0000000000000000000000000000000000000000..2461a627bcb06ffe5e407105b14bc506af741cbb
--- /dev/null
+++ b/src/unmount.rs
@@ -0,0 +1,53 @@
+use failure::Error;
+
+use std::{
+    fs,
+    io::{self},
+    process::{Command, ExitStatus},
+};
+
+fn unmount_linux_path(mount_path: &str) -> io::Result<ExitStatus> {
+    // Different distributions can have various fusermount binaries. Try
+    // them all.
+    let commands = ["fusermount", "fusermount3"];
+
+    for command in commands {
+        let status = Command::new(command).arg("-u").arg(mount_path).status();
+        if status.is_ok() {
+            return status;
+        }
+        if let Err(ref e) = status {
+            if e.kind() == io::ErrorKind::NotFound {
+                continue;
+            }
+        }
+    }
+
+    // Unmounting failed since no suitable command was found
+    Err(std::io::Error::new(
+        io::ErrorKind::NotFound,
+        format!(
+            "Unable to locate any fusermount binaries. Tried {:?}. Is fuse installed?",
+            commands
+        ),
+    ))
+}
+
+pub fn unmount_path(mount_path: &str) -> Result<(), Error> {
+    if cfg!(target_os = "redox") {
+        fs::remove_file(format!(":{}", mount_path))?
+    } else {
+        let status_res = if cfg!(target_os = "linux") {
+            unmount_linux_path(mount_path)
+        } else {
+            Command::new("umount").arg(mount_path).status()
+        };
+
+        let status = status_res?;
+        if !status.success() {
+            return Err(io::Error::new(io::ErrorKind::Other, "redoxfs umount failed").into());
+        }
+    }
+
+    Ok(())
+}
diff --git a/test.sh b/test.sh
index e6ddec998d91229f88230dcc697c2d4316fd3e14..d75b3254d57b29e6d90d9e44483b6c7e60f882da 100755
--- a/test.sh
+++ b/test.sh
@@ -8,6 +8,7 @@ export RUST_LOG=info
 function cleanup {
     sync
     fusermount -u image || true
+    fusermount3 -u image || true
 }
 
 trap 'cleanup' ERR