Skip to content

Commit c343a1d

Browse files
committed
Add fsfreeze_thaw_cycle()
As SIGTERM signals are intercepted by SignalTerminationGuard, we just call `FIFREEZE` and `FITHAW` one after the other without doing a complicated dance like in ostree.
1 parent 82247d2 commit c343a1d

File tree

2 files changed

+51
-0
lines changed

2 files changed

+51
-0
lines changed

src/freezethaw.rs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
use rustix::fd::AsFd;
2+
use rustix::ffi as c;
3+
use rustix::io::Errno;
4+
use rustix::ioctl::opcode;
5+
use rustix::{io, ioctl};
6+
7+
use crate::util::SignalTerminationGuard;
8+
9+
fn ioctl_fifreeze<Fd: AsFd>(fd: Fd) -> io::Result<()> {
10+
// SAFETY: `FIFREEZE` is a no-argument opcode.
11+
// `FIFREEZE` is defined as `_IOWR('X', 119, int)`.
12+
unsafe {
13+
let ctl = ioctl::NoArg::<{ opcode::read_write::<c::c_int>(b'X', 119) }>::new();
14+
ioctl::ioctl(fd, ctl)
15+
}
16+
}
17+
18+
fn ioctl_fithaw<Fd: AsFd>(fd: Fd) -> io::Result<()> {
19+
// SAFETY: `FITHAW` is a no-argument opcode.
20+
// `FITHAW` is defined as `_IOWR('X', 120, int)`.
21+
unsafe {
22+
let ctl = ioctl::NoArg::<{ opcode::read_write::<c::c_int>(b'X', 120) }>::new();
23+
ioctl::ioctl(fd, ctl)
24+
}
25+
}
26+
27+
/// syncfs() doesn't flush the journal on XFS,
28+
/// and since GRUB2 can't read the XFS journal, the system
29+
/// could fail to boot.
30+
///
31+
/// http://marc.info/?l=linux-fsdevel&m=149520244919284&w=2
32+
/// https://github.com/ostreedev/ostree/pull/1049
33+
///
34+
/// This function always call syncfs() first, then calls
35+
/// `ioctl(FIFREEZE)` and `ioctl(FITHAW)`, ignoring `EOPNOTSUPP` and `EPERM`
36+
pub(crate) fn fsfreeze_thaw_cycle<Fd: AsFd>(fd: Fd) -> anyhow::Result<()> {
37+
rustix::fs::syncfs(&fd)?;
38+
39+
let _guard = SignalTerminationGuard::new()?;
40+
41+
let freeze = ioctl_fifreeze(&fd);
42+
match freeze {
43+
// Ignore permissions errors (tests)
44+
Err(Errno::PERM) => Ok(()),
45+
// Ignore unsupported FS
46+
Err(Errno::NOTSUP) => Ok(()),
47+
Ok(()) => Ok(ioctl_fithaw(fd)?),
48+
_ => Ok(freeze?),
49+
}
50+
}

src/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ mod efi;
3333
mod failpoints;
3434
mod filesystem;
3535
mod filetree;
36+
mod freezethaw;
3637
#[cfg(any(
3738
target_arch = "x86_64",
3839
target_arch = "aarch64",

0 commit comments

Comments
 (0)