是否存在调用fsync/刷新文件描述符对应父目录的方法?
fsync_parent(fd) equivalent to persist new file directory entries? Great question—this is such a common pitfall when you’re trying to guarantee full file persistence! Unfortunately, there’s no standard C function like fsync_parent(fd) that handles this in a single call. Let’s break down why, and what you can do instead:
Why fsync() alone isn’t enough
When you create a new file, the critical link between the filename and the file’s data (stored in the directory entry) lives in the parent directory’s metadata, not the file itself. Calling fsync() on the file’s file descriptor only flushes the file’s own data and metadata to disk—it doesn’t touch the parent directory’s records that prove the file exists. If the system crashes before the directory’s metadata is flushed, the file might be on disk but invisible to other processes (or lost entirely, depending on the filesystem).
The standard workaround
To ensure the new file is fully persistent, you need to explicitly sync the parent directory. Here’s how to do it:
- Get a file descriptor for the parent directory: You can open the directory with
open()(usingO_RDONLYis sufficient, since you only need to sync its metadata) or useopenat()if you’re working with relative paths or file descriptor-based path resolution. - Call
fsync()on the parent directory’s file descriptor: This flushes the directory’s metadata (including the new file entry) to disk. - Order matters: Always sync the file first, then close it (or at least finish all writes to it) before syncing the parent directory. Syncing the directory first could leave a directory entry pointing to an incomplete or corrupted file.
Example code
Here’s a quick snippet demonstrating the proper sequence:
#include <fcntl.h> #include <unistd.h> #include <stdio.h> #include <string.h> int main() { // Create and write to our new file int file_fd = open("my_persistent_file.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644); if (file_fd == -1) { perror("Failed to open file"); return 1; } const char* content = "This data should survive a crash!"; if (write(file_fd, content, strlen(content)) == -1) { perror("Failed to write to file"); close(file_fd); return 1; } // Sync the file's data/metadata first if (fsync(file_fd) == -1) { perror("Failed to fsync file"); close(file_fd); return 1; } close(file_fd); // Now sync the parent directory to persist the file entry int parent_dir_fd = open(".", O_RDONLY); if (parent_dir_fd == -1) { perror("Failed to open parent directory"); return 1; } if (fsync(parent_dir_fd) == -1) { perror("Failed to fsync parent directory"); close(parent_dir_fd); return 1; } close(parent_dir_fd); return 0; }
Notes on portability
Some operating systems have non-standard extensions (like Linux’s syncfs(), which syncs an entire filesystem), but these aren’t portable across all POSIX systems. The open-and-sync-parent-directory approach is the only standard, reliable way to ensure your new file’s entry is persisted.
内容的提问来源于stack exchange,提问作者Ari Sweedler

