Skip to content

Instantly share code, notes, and snippets.

@joanbm
Created January 1, 2025 15:58
Show Gist options
  • Save joanbm/159759c075b04a679593ee5473456da0 to your computer and use it in GitHub Desktop.
Save joanbm/159759c075b04a679593ee5473456da0 to your computer and use it in GitHub Desktop.
Shows that on an unclean shutdown of ext4 (default settings, kernel 6.12.7), files may get a suffix of NUL bytes - see https://github.com/fish-shell/fish-shell/issues/10300
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <linux/reboot.h>
#define NUM_FILES 200000
#define BUFFER_SIZE 100
void quit_on_error(const char *message) {
perror(message);
exit(EXIT_FAILURE);
}
void create_file_with_content(const char *filename, char c, size_t size) {
int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (fd < 0) quit_on_error("Failed to create file");
char buffer[BUFFER_SIZE];
memset(buffer, c, BUFFER_SIZE);
size_t remaining = size;
while (remaining > 0) {
size_t to_write = remaining > BUFFER_SIZE ? BUFFER_SIZE : remaining;
if (write(fd, buffer, to_write) != to_write) quit_on_error("Failed to write to file");
remaining -= to_write;
}
close(fd);
}
int main() {
char filename[64];
for (int i = 0; i < NUM_FILES; i++) {
snprintf(filename, sizeof(filename), "file_%06d", i);
create_file_with_content(filename, 'A', 5000);
}
int fd = open(".", O_RDONLY);
if (fd < 0) quit_on_error("Failed to open directory for sync");
if (syscall(SYS_syncfs, fd) < 0) quit_on_error("Failed to sync filesystem");
close(fd);
for (int i = 0; i < NUM_FILES; i++) {
snprintf(filename, sizeof(filename), "file_%06d", i);
int fd = open(filename, O_WRONLY | O_APPEND, 0644);
if (fd < 0) quit_on_error("Failed to open file");
for (int i = 0; i < 100; i++) {
if (write(fd, "xyzzyxyzzyxyzzyxyzzy", 20) != 20) quit_on_error("Failed to append to file");
}
close(fd);
}
if (syscall(SYS_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART) < 0)
quit_on_error("Failed to uncleanly reboot system. Please run as root in a VM.");
return 0;
}
@joanbm
Copy link
Author

joanbm commented Jan 1, 2025

My qemu command line: qemu-system-x86_64 -nodefaults -enable-kvm -cpu host -smp 2 -m 4096 -vga virtio -nic user -serial mon:stdio -drive file=ArchFsCrash.qcow2,if=virtio,cache=directsync

This creates a lot of files and then uncleanly restarts the system. After the system comes up, take a look at the file sizes to locate which files were being written when the system was restarted and then look for signs of corruption. If all files are in the 'old' or 'new' state, then you need to tune the number and size of the files.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment