/*
 * DF-2748 PoC: full-duplex journal ack-path death -> permanent
 * uninterruptible writer wedge (tsleep "jwrite", vfs_journal.c:547).
 *
 * Preconditions (set up by the harness before running this):
 *   mountctl -2 -w /root/j2.bin -o memfifo=65536 wedge:/tmp
 * The rthread fp_read()s the (empty) regular file target, gets EOF,
 * and exits immediately => xindex is frozen forever.  Once the 64KB
 * memfifo accumulates 64KB of un-acked stream bytes, journal_reserve()
 * sleeps uninterruptibly forever => writer wedged in-kernel, unkillable.
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <signal.h>
#include <sys/wait.h>

int
main(int ac, char **av)
{
	const char *dir = av[1];
	pid_t pids[2];
	int i, t;

	for (i = 0; i < 2; i++) {
		pid_t pid = fork();
		if (pid == 0) {
			char path[256], buf[4096];
			int n = 0, fd;

			setvbuf(stdout, NULL, _IONBF, 0);
			memset(buf, 'A' + i, sizeof(buf));
			for (;;) {
				snprintf(path, sizeof(path), "%s/w%d_%d", dir, i, n++);
				fd = open(path, O_CREAT|O_WRONLY|O_TRUNC, 0666);
				if (fd < 0) { perror("child open"); _exit(1); }
				printf("child %d: created+wrote file #%d\n", i, n);
				if (write(fd, buf, sizeof(buf)) != sizeof(buf)) {
					printf("child %d: write returned! errno=%d\n", i, errno);
					_exit(2);
				}
				close(fd);
				unlink(path);
			}
		}
		pids[i] = pid;
	}
	for (t = 1; t <= 12; t++) {
		int alivectl = 0;
		sleep(5);
		for (i = 0; i < 2; i++) {
			char cmd[160];
			int status;
			snprintf(cmd, sizeof(cmd),
				 "ps -o pid,state,wchan,comm -p %d | tail -1", pids[i]);
			printf("[t+%02ds] child %d: ", t * 5, i);
			fflush(stdout);
			if (system(cmd) == 0)
				alivectl++;
			if (waitpid(pids[i], &status, WNOHANG) > 0)
				printf("        child %d EXITED status=%d\n", i, status);
		}
		if (t == 3) {
			printf(">>> sending SIGKILL to both children\n");
			kill(pids[0], SIGKILL);
			kill(pids[1], SIGKILL);
		}
	}
	printf("RESULT: after 60s incl. SIGKILL: children still in kernel\n");
	return 0;
}
