DF-3178 / statfs_probe.c
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 | /* * DF-3178 statfs probe — figure out which syscall df(1) wedges on against * the census-lie hpfs mount. Each probe is wrapped in alarm(10) so the * process survives to tell which one timed out. * * Build: cc -O2 -o statfs_probe statfs_probe.c */ #include <sys/mount.h> #include <errno.h> #include <fcntl.h> #include <err.h> #include <signal.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> static sig_atomic_t timed_out; static void alarm_handler(int sig __unused) { timed_out = 1; } static void probe(const char *name, void (*fn)(void), void (*cleanup)(void)) { timed_out = 0; fflush(stdout); printf("%-22s ... ", name); fflush(stdout); alarm(10); fn(); alarm(0); if (timed_out) { printf("TIMEOUT (kernel wedged in this syscall)\n"); if (cleanup) cleanup(); } else { printf("returned\n"); } fflush(stdout); } static const char *P; static void do_statfs(void) { struct statfs sb; if (statfs(P, &sb) < 0) printf("errno=%d ", errno); else printf("f_blocks=%llu f_bsize=%lu f_bfree=%llu ", (unsigned long long)sb.f_blocks, (unsigned long)sb.f_bsize, (unsigned long long)sb.f_bfree); } static void do_getfsstat(void) { struct statfs *sfs; int i, n = getfsstat(NULL, 0, MNT_NOWAIT); if (n < 0) { printf("errno=%d ", errno); return; } sfs = calloc(n, sizeof(*sfs)); n = getfsstat(sfs, n * sizeof(*sfs), MNT_NOWAIT); printf("%d mounts ", n); for (i = 0; i < n; i++) if (strcmp(sfs[i].f_fstypename, "hpfs") == 0) printf("[hpfs: f_blocks=%llu mntfrom=%s] ", (unsigned long long)sfs[i].f_blocks, sfs[i].f_mntfromname); free(sfs); } static void do_open(void) { int fd = open(P, O_RDONLY); if (fd < 0) printf("errno=%d ", errno); else { printf("open OK "); close(fd); } } static void do_close_sync(void) { sync(); } int main(int argc, char **argv) { if (argc != 2) { fprintf(stderr, "usage: %s <path>\n", argv[0]); return 2; } P = argv[1]; signal(SIGALRM, alarm_handler); printf("pid=%d path=%s\n", getpid(), P); probe("open(mnt)", do_open, NULL); probe("statfs(mnt)", do_statfs, NULL); probe("getfsstat", do_getfsstat, NULL); printf("ALL DONE\n"); return 0; } |