DF-4714 / trigger_a.c
/* * DF-4714 trigger (scenario A - clean silent-data-loss oracle, no panic). * * ONE 16KB write() at volume sectors [128,160) - a single data block on * subdisk s1 (ordinal 1). Preconditions: s0 (the stripe's parity subdisk) * administratively DOWN, s1 in state sd_reborn (both states arise * naturally from drive flaps; here placed via 'vinum setstate -f'). * * bre5() marks the down parity subdisk at vinumraid5.c:363-364 * (m.badsdno = psdno). In the write loop, s1 (reborn) makes * checksdstate() return REQUEST_OK (reborn is writable), and the * second-bad-subdisk guard at :404 only fires when s != 0 -- so * m.badsdno is silently OVERWRITTEN with the data subdisk (:420). * The XFR_PARITYLESS_WRITE conversion at :443 never happens; instead * the degraded path runs: the data block (flagged XFR_BAD_SUBDISK) is * never written, parity is recomputed from the other column plus the * user's new data and written to the DOWN parity subdisk, and the * write() returns SUCCESS. The user's 16KB is gone. * * buggy kernel: write OK, readback returns the OLD bytes (loss). * fixed kernel: write fails EIO (refusal at the :404 guard). */ #include <fcntl.h> #include <stdio.h> #include <string.h> #include <unistd.h> #define VOL "/dev/vinum/vol/rv" #define OFF (128 * 512) #define LEN (32 * 512) unsigned char wbuf[LEN], rbuf[LEN]; int main(void) { int fd, rc, i; memset(wbuf, 0xBB, LEN); memset(rbuf, 0, LEN); fd = open(VOL, O_RDWR); if (fd < 0) { perror("open"); return 2; } if (lseek(fd, OFF, SEEK_SET) < 0) { perror("lseek"); return 2; } rc = write(fd, wbuf, LEN); if (rc != LEN) { perror("write"); printf("DF-4714-A RESULT: write FAILED (correct behavior on a fixed kernel)\n"); return 0; } printf("DF-4714-A: write OK (16KB accepted with parity sd DOWN + data sd REBORN)\n"); sleep(1); if (lseek(fd, OFF, SEEK_SET) < 0) { perror("lseek2"); return 2; } rc = read(fd, rbuf, LEN); if (rc != LEN) { perror("read"); printf("DF-4714-A RESULT: read FAILED\n"); return 0; } for (i = 0; i < LEN; i++) if (rbuf[i] != 0xBB) { printf("DF-4714-A RESULT: *** SILENT DATA LOSS (readback %02x != %02x) ***\n", rbuf[i], 0xBB); return 1; } printf("DF-4714-A RESULT: readback matches (no loss)\n"); return 0; } |