DF-5071 / df5071_trigger.c
/* DF-5071 trigger: drive the amr parked-bio sink. * * shutdown <ctldev> - ioctl 71: amr_pci_shutdown/amr_rescan_drives analog * online <ctldev> - ioctl 73: amr_startup analog * poke <ctldev> - ioctl 72: drain the parked bios (external completion) * wedge <rawdev> - pread @2M: normal bio (parks forever when shut down) * wedgehold <rawdev> <secs> - open the RAW device NOW (before shutdown), * sleep, then pread @2M: models an fd that was open * before the controller went away โ amrd_open's gate * never sees it and amrd_strategy has no gate. * freshopen <rawdev> - plain open(): amrd_open's ENXIO gate (contrast arm) */ #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <errno.h> #include <string.h> #include <sys/ioctl.h> #define DF5071_CTL_SHUTDOWN _IOW('D', 71, int) #define DF5071_CTL_POKE _IOW('D', 72, int) #define DF5071_CTL_ONLINE _IOW('D', 73, int) int main(int argc, char **argv) { char buf[512]; ssize_t r; int fd, secs; if (argc < 3) { fprintf(stderr, "usage: %s shutdown|online|poke <ctldev>\n" " %s wedge <rawdev>\n" " %s wedgehold <rawdev> <secs>\n" " %s freshopen <rawdev>\n", argv[0], argv[0], argv[0], argv[0]); exit(2); } if (strcmp(argv[1], "shutdown") == 0 || strcmp(argv[1], "online") == 0 || strcmp(argv[1], "poke") == 0) { unsigned long cmd = strcmp(argv[1], "shutdown") == 0 ? DF5071_CTL_SHUTDOWN : strcmp(argv[1], "online") == 0 ? DF5071_CTL_ONLINE : DF5071_CTL_POKE; fd = open(argv[2], O_RDWR); if (fd < 0) { perror("open ctl"); exit(1); } if (ioctl(fd, cmd, &(int){0}) < 0) { perror("ioctl"); exit(1); } fprintf(stderr, "%s: ioctl ok\n", argv[1]); return (0); } if (strcmp(argv[1], "freshopen") == 0) { fd = open(argv[2], O_RDONLY); fprintf(stderr, "freshopen: open(%s) fd=%d errno=%d(%s) โ " "amrd_open refuses once SHUTDOWN is set\n", argv[2], fd, fd < 0 ? errno : 0, fd < 0 ? strerror(errno) : "ok"); if (fd >= 0) close(fd); return (0); } if (strcmp(argv[1], "wedgehold") == 0) { secs = argc > 3 ? atoi(argv[3]) : 6; fd = open(argv[2], O_RDONLY); if (fd < 0) { perror("wedgehold open"); exit(1); } fprintf(stderr, "wedgehold: fd=%d open BEFORE shutdown; " "sleeping %ds then pread@2M\n", fd, secs); sleep(secs); r = pread(fd, buf, sizeof(buf), 2UL << 20); fprintf(stderr, "wedgehold: pread@2M r=%zd errno=%d(%s) โ " "returned only when the bio was completed externally\n", r, r < 0 ? errno : 0, r < 0 ? strerror(errno) : "ok"); return (0); } /* plain wedge: fresh open + pread (fine while online) */ fd = open(argv[2], O_RDONLY); if (fd < 0) { perror("open"); exit(1); } r = pread(fd, buf, sizeof(buf), 2UL << 20); fprintf(stderr, "%s: pread@%lu r=%zd errno=%d(%s)\n", argv[1], 2UL << 20, r, r < 0 ? errno : 0, r < 0 ? strerror(errno) : "ok"); return (0); } |