diff --git a/Cargo.lock b/Cargo.lock
index 320f5ad..1f68e68 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -393,6 +393,12 @@ version = "0.4.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
 
+[[package]]
+name = "linux-raw-sys"
+version = "0.6.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2a385b1be4e5c3e362ad2ffa73c392e53f031eaa5b7d648e64cd87f27f6063d7"
+
 [[package]]
 name = "log"
 version = "0.4.22"
@@ -1016,6 +1022,7 @@ dependencies = [
  "textwrap",
  "uu_ctrlaltdel",
  "uu_dmesg",
+ "uu_fsfreeze",
  "uu_last",
  "uu_lscpu",
  "uu_lsmem",
@@ -1047,6 +1054,17 @@ dependencies = [
  "uucore",
 ]
 
+[[package]]
+name = "uu_fsfreeze"
+version = "0.0.1"
+dependencies = [
+ "clap",
+ "linux-raw-sys 0.6.5",
+ "regex",
+ "sysinfo",
+ "uucore",
+]
+
 [[package]]
 name = "uu_last"
 version = "0.0.1"
diff --git a/Cargo.toml b/Cargo.toml
index 36510ca..0feea1d 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -26,6 +26,7 @@ default = ["feat_common_core"]
 uudoc = []
 
 feat_common_core = [
+  "fsfreeze",
   "mountpoint",
   "lscpu",
   "lsmem",
@@ -55,6 +56,7 @@ serde = { version = "1.0", features = ["derive"] }
 serde_json = "1.0.122"
 tabled = "0.17.0"
 dns-lookup = "2.0.4"
+linux-raw-sys = { version = "0.6.5", features = ["ioctl"] }
 
 [dependencies]
 clap = { workspace = true }
@@ -66,6 +68,7 @@ textwrap = { workspace = true }
 dns-lookup = { workspace = true }
 
 #
+fsfreeze = { optional = true, version = "0.0.1", package = "uu_fsfreeze", path = "src/uu/fsfreeze" }
 lscpu = { optional = true, version = "0.0.1", package = "uu_lscpu", path = "src/uu/lscpu" }
 lsmem = { optional = true, version = "0.0.1", package = "uu_lsmem", path = "src/uu/lsmem" }
 mountpoint = { optional = true, version = "0.0.1", package = "uu_mountpoint", path = "src/uu/mountpoint" }
diff --git a/README.md b/README.md
index 7b251d2..ff1162f 100644
--- a/README.md
+++ b/README.md
@@ -35,6 +35,7 @@ First, reimplement the most important tools from util-linux:
   Started
 - `fsck`: Checks and repairs filesystems.
 - `fsfreeze`: Freezes/unfreezes filesystems.
+  Done
 - `fstrim`: Discards unused blocks on filesystems.
 - `wipefs`: Wipes filesystem signatures.
 
diff --git a/src/uu/fsfreeze/Cargo.toml b/src/uu/fsfreeze/Cargo.toml
new file mode 100644
index 0000000..d96e2f0
--- /dev/null
+++ b/src/uu/fsfreeze/Cargo.toml
@@ -0,0 +1,18 @@
+[package]
+name = "uu_fsfreeze"
+version = "0.0.1"
+edition = "2021"
+
+[lib]
+path = "src/fsfreeze.rs"
+
+[[bin]]
+name = "fsfreeze"
+path = "src/main.rs"
+
+[dependencies]
+clap = { workspace = true }
+linux-raw-sys = { workspace = true }
+regex = { workspace = true }
+sysinfo = { workspace = true }
+uucore = { workspace = true }
diff --git a/src/uu/fsfreeze/fsfreeze.md b/src/uu/fsfreeze/fsfreeze.md
new file mode 100644
index 0000000..6728b4c
--- /dev/null
+++ b/src/uu/fsfreeze/fsfreeze.md
@@ -0,0 +1,7 @@
+# fsfreeze
+
+```
+fsfreeze <--freeze|--unfreeze> <MOUNTPOINT>
+```
+
+suspends or resumes modifications to a mounted filesystem
diff --git a/src/uu/fsfreeze/src/fsfreeze.rs b/src/uu/fsfreeze/src/fsfreeze.rs
new file mode 100644
index 0000000..820d9c2
--- /dev/null
+++ b/src/uu/fsfreeze/src/fsfreeze.rs
@@ -0,0 +1,85 @@
+// This file is part of the uutils util-linux package.
+//
+// For the full copyright and license information, please view the LICENSE
+// file that was distributed with this source code.
+
+use clap::{crate_version, Arg, ArgAction, ArgGroup, Command};
+#[cfg(target_os = "linux")]
+use std::{fs::File, io, os::fd::AsRawFd};
+#[cfg(target_os = "linux")]
+use uucore::{error::UIoError, libc};
+use uucore::{error::UResult, format_usage, help_about, help_usage};
+
+const ABOUT: &str = help_about!("fsfreeze.md");
+const USAGE: &str = help_usage!("fsfreeze.md");
+
+#[cfg(target_os = "linux")]
+#[uucore::main]
+pub fn uumain(args: impl uucore::Args) -> UResult<()> {
+    let matches: clap::ArgMatches = uu_app().try_get_matches_from(args)?;
+    let mountpoint = matches.get_one::<String>("mountpoint").unwrap();
+    let file = File::open(mountpoint)?;
+    let metadata = file.metadata()?;
+    if !metadata.is_dir() {
+        return Err(UIoError::new(io::ErrorKind::InvalidData, "not a directory"));
+    }
+
+    let (op_name, op_code) = if matches.get_flag("freeze") {
+        ("freeze", linux_raw_sys::ioctl::FIFREEZE)
+    } else {
+        ("unfreeze", linux_raw_sys::ioctl::FITHAW)
+    };
+
+    if unsafe { libc::ioctl(file.as_raw_fd(), op_code.into(), 0) } < 0 {
+        uucore::show_error!(
+            "failed to {} the filesystem: {}",
+            op_name,
+            UIoError::from(io::Error::last_os_error())
+        );
+    }
+    Ok(())
+}
+
+pub fn uu_app() -> Command {
+    Command::new(uucore::util_name())
+        .version(crate_version!())
+        .about(ABOUT)
+        .override_usage(format_usage(USAGE))
+        .infer_long_args(true)
+        .arg(
+            Arg::new("freeze")
+                .short('f')
+                .long("freeze")
+                .help("freeze the filesystem")
+                .action(ArgAction::SetTrue),
+        )
+        .arg(
+            Arg::new("unfreeze")
+                .short('u')
+                .long("unfreeze")
+                .help("unfreeze the filesystem")
+                .action(ArgAction::SetTrue),
+        )
+        .arg(
+            Arg::new("mountpoint")
+                .help("mountpoint of the filesystem")
+                .required(true)
+                .action(ArgAction::Set),
+        )
+        .group(
+            ArgGroup::new("action")
+                .required(true)
+                .args(["freeze", "unfreeze"]),
+        )
+}
+
+#[cfg(not(target_os = "linux"))]
+#[uucore::main]
+pub fn uumain(args: impl uucore::Args) -> UResult<()> {
+    let _matches: clap::ArgMatches = uu_app().try_get_matches_from(args)?;
+
+    Err(uucore::error::USimpleError::new(
+        1,
+        "`fsfreeze` is available only on Linux.",
+    ))
+}
diff --git a/src/uu/fsfreeze/src/main.rs b/src/uu/fsfreeze/src/main.rs
new file mode 100644
index 0000000..5ab60d7
--- /dev/null
+++ b/src/uu/fsfreeze/src/main.rs
@@ -0,0 +1 @@
+uucore::bin!(uu_fsfreeze);
diff --git a/tests/by-util/test_fsfreeze.rs b/tests/by-util/test_fsfreeze.rs
new file mode 100644
index 0000000..b55daa8
--- /dev/null
+++ b/tests/by-util/test_fsfreeze.rs
@@ -0,0 +1,62 @@
+// This file is part of the uutils util-linux package.
+//
+// For the full copyright and license information, please view the LICENSE
+// file that was distributed with this source code.
+
+use crate::common::util::TestScenario;
+
+#[test]
+fn test_invalid_arg() {
+    new_ucmd!().arg("--definitely-invalid").fails().code_is(1);
+}
+
+#[test]
+fn test_operations_mutually_exclusive() {
+    new_ucmd!()
+        .arg("--freeze")
+        .arg("--unfreeze")
+        .arg("/foo")
+        .fails()
+        .code_is(1)
+        .stderr_contains("the argument '--freeze' cannot be used with '--unfreeze'");
+}
+
+#[cfg(target_os = "linux")]
+mod linux {
+    use crate::common::util::TestScenario;
+
+    #[test]
+    fn test_fails_on_non_existing_path() {
+        new_ucmd!()
+            .arg("--unfreeze")
+            .arg("/non/existing")
+            .fails()
+            .code_is(1)
+            .stderr_contains("No such file or directory");
+    }
+
+    #[test]
+    fn test_fails_on_non_directory() {
+        new_ucmd!()
+            .arg("--unfreeze")
+            .arg("/dev/null")
+            .fails()
+            .code_is(1)
+            .stderr_contains("not a directory");
+    }
+}
+
+#[cfg(not(target_os = "linux"))]
+mod non_linux {
+    use crate::common::util::TestScenario;
+
+    #[test]
+    fn test_fails_on_unsupported_platforms() {
+        new_ucmd!()
+            .arg("--unfreeze")
+            .arg("/non/existing")
+            .fails()
+            .code_is(1)
+            .stderr_is("fsfreeze: `fsfreeze` is available only on Linux.\n");
+    }
+}
diff --git a/tests/tests.rs b/tests/tests.rs
index 4532383..824a096 100644
--- a/tests/tests.rs
+++ b/tests/tests.rs
@@ -36,3 +36,7 @@ mod test_last;
 #[cfg(feature = "dmesg")]
 #[path = "by-util/test_dmesg.rs"]
 mod test_dmesg;
+
+#[cfg(feature = "fsfreeze")]
+#[path = "by-util/test_fsfreeze.rs"]
+mod test_fsfreeze;