composepost: Fix race condition in timestamp checking

`syncfs()` isn't going to do anything on e.g. `tmpfs` and even
if it did wouldn't fix any race conditions because that's about
synchronizing in memory changes to disk, but won't change
what system calls return.

Some investigation turned up
https://stackoverflow.com/questions/14392975/timestamp-accuracy-on-ext4-sub-millsecond
and `current_fs_time` is now:
https://www.kernel.org/doc/html/v5.12/core-api/timekeeping.html

Basically there's a "coarse" time that might only update once every 10ms
for example.

Let's just sleep 100ms for now.

I think we should be using the inode versions, but we can investigate
that separately.
This commit is contained in:
Colin Walters 2021-04-30 12:44:30 -04:00
parent a42fcd06c7
commit 12cc4e5f5b

View File

@ -1171,25 +1171,21 @@ OSTREE_VERSION='33.4'
rootfs.new_file(&binpath, 0o755).unwrap(); rootfs.new_file(&binpath, 0o755).unwrap();
let fpath = format!("{}/{}", PREFIX, fname); let fpath = format!("{}/{}", PREFIX, fname);
rootfs.new_file(&fpath, 0o755).unwrap(); rootfs.new_file(&fpath, 0o755).unwrap();
rootfs.syncfs().unwrap();
let before_meta = rootfs.metadata(fpath).unwrap(); let before_meta = rootfs.metadata(fpath).unwrap();
metas.push(before_meta); metas.push(before_meta);
} }
// File timestamps may not increment faster than e.g. 10ms. Really
// what we should be doing is using inode versions.
std::thread::sleep(std::time::Duration::from_millis(100));
tweak_selinux_timestamps(&rootfs, gio::NONE_CANCELLABLE).unwrap(); tweak_selinux_timestamps(&rootfs, gio::NONE_CANCELLABLE).unwrap();
rootfs.syncfs().unwrap();
for (fname, before_meta) in files.iter().zip(metas.iter()) { for (fname, before_meta) in files.iter().zip(metas.iter()) {
let fpath = format!("{}/{}", PREFIX, fname); let fpath = format!("{}/{}", PREFIX, fname);
let after = rootfs.metadata(&fpath).unwrap(); let after = rootfs.metadata(&fpath).unwrap();
assert!( if before_meta.stat().st_mtime == after.stat().st_mtime {
before_meta.stat().st_atime != after.stat().st_atime assert_ne!(before_meta.stat().st_mtime_nsec, after.stat().st_mtime_nsec);
|| before_meta.stat().st_atime_nsec != after.stat().st_atime_nsec }
);
assert!(
before_meta.stat().st_mtime != after.stat().st_mtime
|| before_meta.stat().st_mtime_nsec != after.stat().st_mtime_nsec
);
} }
} }