⬢ DragonFlyBSD Kernel Audit
DF-4528 / nvspam.c
← back to finding ↓ download raw
/* nvspam.c -- attach-race spammer: loop forever over all /dev/nvme[0-9]*,
 * issuing NVMEIOCGETLOG. Restarts on errors; designed to be running when a
 * controller (re)attaches so it races the admin thread's identify storm.
 * Reports STUCK (>3s) calls and a heartbeat. */
#include <sys/ioccom.h>
#include <sys/types.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <dirent.h>
#include <errno.h>
#include <time.h>

typedef struct { unsigned char pad[4096]; } nvme_admin_data_t;
typedef struct nvme_getlog_ioctl {
	uint8_t  lid, reserved01;
	uint16_t status;
	uint32_t ret_size, beg_offset;
	nvme_admin_data_t info;
} nvme_getlog_ioctl_t;
#define NVMEIOCGETLOG _IOWR('O', 0, struct nvme_getlog_ioctl)

static double
now(void)
{
	struct timespec ts;
	clock_gettime(CLOCK_MONOTONIC, &ts);
	return (double)ts.tv_sec + (double)ts.tv_nsec / 1e9;
}

int
main(int argc, char **argv)
{
	double last = now(), t0, t1, maxlat = 0;
	long n = 0, errs = 0, stuck = 0;

	setvbuf(stdout, NULL, _IOLBF, 0);
	for (;;) {
		DIR *d = opendir("/dev");
		struct dirent *de;
		char path[64];
		int fd = -1;

		if (d) {
			while ((de = readdir(d)) != NULL) {
				int v;
				if (sscanf(de->d_name, "nvme%d", &v) == 1) {
					snprintf(path, sizeof(path),
					    "/dev/%s", de->d_name);
					fd = open(path, O_RDONLY);
					if (fd >= 0)
						break;
				}
			}
			closedir(d);
		}
		if (fd < 0) {
			usleep(20000);
			continue;
		}
		for (;;) {
			nvme_getlog_ioctl_t ioc;
			memset(&ioc, 0, sizeof(ioc));
			ioc.lid = 1;
			ioc.ret_size = 4096;
			t0 = now();
			if (ioctl(fd, NVMEIOCGETLOG, &ioc) < 0) {
				errs++;
				close(fd);
				break;
			}
			t1 = now();
			if (t1 - t0 > maxlat)
				maxlat = t1 - t0;
			if (t1 - t0 > 3.0) {
				stuck++;
				printf("[%d] STUCK %.3fs (#%ld)\n",
				    getpid(), t1 - t0, n);
			}
			n++;
			if (t1 - last > 1.0) {
				printf("[%d] HB n=%ld errs=%ld maxlat=%.4f "
				    "stuck=%ld\n", getpid(), n, errs, maxlat,
				    stuck);
				last = t1;
			}
		}
	}
	return 0;
}