/*
 * DF-2799 — unprivileged side of the deadlock: hammer
 * `sysctl jail.list` (world-readable, no privileges required).
 * Each read takes its CPU's gd_sysctllock SHARED across the handler and
 * then blocks on jail_lock while the root churner holds it.
 *
 * Runs for <secs> seconds (or forever if 0).
 */
#include <sys/sysctl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>

static time_t t0;

int
main(int argc, char **argv)
{
	int secs = argc > 1 ? atoi(argv[1]) : 60;
	static char buf[1 << 19];
	long n = 0, errs = 0;

	t0 = time(NULL);
	for (;;) {
		size_t len = sizeof(buf);
		if (sysctlbyname("jail.list", buf, &len, NULL, 0) < 0)
			errs++;
		n++;
		if ((n % 4096) == 0) {
			printf("reader: %ld reads, %ld errors, %lds\n",
			       n, errs, (long)(time(NULL) - t0));
			fflush(stdout);
			if (secs && time(NULL) - t0 > secs)
				break;
		}
	}
	printf("reader: finished %ld reads %ld errors\n", n, errs);
	return (0);
}
