⬢ DragonFlyBSD Kernel Audit
DF-5820 / rename_stress.c
← back to finding ↓ download raw
/* DF-5820 stress: hammer out the nrename source-dirent lookup race.
 * The backend prints "xop_nrename: \"%s\" -> \"%s\"  ENOENT" and the
 * frontend masks it as success (hammer2_vnops.c:2165-2166).
 * Run N seconds of concurrent renames in a directory; afterwards report
 * whether any divergence markers can be observed via dmesg. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>

static const char *dir;
static volatile int stop;

static void *
renamer(void *arg)
{
	long id = (long)arg;
	char a[256], b[256];
	int i;

	for (i = 0; !stop; i++) {
		snprintf(a, sizeof(a), "%s/f%lda%d", dir, id, i % 40);
		snprintf(b, sizeof(b), "%s/f%ldb%d", dir, id, i % 40);
		rename(a, b);		/* ignore errors */
		if ((i % 4000) == 0)
			usleep(1000);
	}
	return (NULL);
}

int
main(int argc, char **argv)
{
	pthread_t th[4];
	int secs = argc > 2 ? atoi(argv[2]) : 20;
	long i;
	char p[256];

	dir = argv[1];
	for (i = 0; i < 4; i++)
		pthread_create(&th[i], NULL, renamer, (void *)i);
	sleep(secs);
	stop = 1;
	for (i = 0; i < 4; i++)
		pthread_join(th[i], NULL);
	/* cleanup */
	for (i = 0; i < 4; i++) {
		int j;
		for (j = 0; j < 40; j++) {
			snprintf(p, sizeof(p), "%s/f%lda%d", dir, i, j);
			unlink(p);
			snprintf(p, sizeof(p), "%s/f%ldb%d", dir, i, j);
			unlink(p);
		}
	}
	printf("stress done\n");
	return (0);
}