1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
| #define _GNU_SOURCE #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <sys/stat.h> #include <string.h> #include <errno.h> #include <time.h> #include <sys/syscall.h> #include <linux/fs.h>
double time_diff_ms(struct timespec start, struct timespec end) { return ((end.tv_sec - start.tv_sec) * 1000.0) + ((end.tv_nsec - start.tv_nsec) / 1000000.0); }
int my_syncfs(int fd) { #ifdef SYS_syncfs return syscall(SYS_syncfs, fd); #else fprintf(stderr, "syncfs system call not available on this system.\n"); return -1; #endif }
int main() { const char *file1_name = "/tmp/sync_test_file1.txt"; const char *file2_name = "/home/user/sync_test_file2.txt"; int fd1, fd2; struct timespec start, end; double elapsed_time;
printf("--- Demonstrating sync and syncfs ---\n"); printf("PID: %d\n", getpid());
printf("\n1. Creating and writing test files...\n");
fd1 = open(file1_name, O_CREAT | O_WRONLY | O_TRUNC, 0644); if (fd1 == -1) { perror("open file1"); printf("Skipping file2 due to open error.\n"); fd2 = -1; } else { printf("Opened %s\n", file1_name); if (write(fd1, "Data for file 1 on root/tmp filesystem.\n", 40) != 40) { perror("write file1"); } }
fd2 = open(file2_name, O_CREAT | O_WRONLY | O_TRUNC, 0644); if (fd2 == -1) { perror("open file2"); printf("Skipping operations on file2.\n"); } else { printf("Opened %s\n", file2_name); if (write(fd2, "Data for file 2 on home filesystem.\n", 37) != 37) { perror("write file2"); } }
printf("\nData written to files. It's likely in the page cache now.\n");
printf("\n2. --- Demonstrating syncfs ---\n"); if (fd1 != -1) { printf("Calling syncfs() on the filesystem containing %s...\n", file1_name); clock_gettime(CLOCK_MONOTONIC, &start); if (my_syncfs(fd1) == -1) { perror("syncfs fd1"); printf("This might be because syncfs is not supported or fd is invalid.\n"); } else { clock_gettime(CLOCK_MONOTONIC, &end); elapsed_time = time_diff_ms(start, end); printf("syncfs(fd1) completed in %.2f ms.\n", elapsed_time); printf("This synced only the filesystem containing %s.\n", file1_name); } }
if (fd2 != -1) { printf("Calling syncfs() on the filesystem containing %s...\n", file2_name); clock_gettime(CLOCK_MONOTONIC, &start); if (my_syncfs(fd2) == -1) { perror("syncfs fd2"); } else { clock_gettime(CLOCK_MONOTONIC, &end); elapsed_time = time_diff_ms(start, end); printf("syncfs(fd2) completed in %.2f ms.\n", elapsed_time); printf("This synced only the filesystem containing %s.\n", file2_name); } }
printf("\n3. --- Demonstrating sync ---\n"); printf("Calling sync() to flush ALL filesystems...\n"); clock_gettime(CLOCK_MONOTONIC, &start); sync(); clock_gettime(CLOCK_MONOTONIC, &end); elapsed_time = time_diff_ms(start, end); printf("sync() completed in %.2f ms.\n", elapsed_time); printf("This synced data for ALL mounted filesystems on the system.\n");
if (fd1 != -1) close(fd1); if (fd2 != -1) close(fd2);
printf("\n4. --- Cleaning up ---\n"); if (fd1 != -1) { if (unlink(file1_name) == 0) { printf("Deleted %s\n", file1_name); } else { perror("unlink file1"); } } if (fd2 != -1) { if (unlink(file2_name) == 0) { printf("Deleted %s\n", file2_name); } else { perror("unlink file2"); } }
printf("\n--- Summary ---\n"); printf("1. sync(): Flushes dirty data for ALL mounted filesystems. No return value.\n"); printf("2. syncfs(fd): Flushes dirty data for ONLY the filesystem containing the file referred to by 'fd'. Returns 0 on success.\n"); printf("3. syncfs is more targeted and usually faster than sync.\n"); printf("4. Use sync() before system shutdown. Use syncfs() or fsync() for specific data safety in applications.\n");
return 0; }
|