1a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh#include <stdlib.h>
2a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh#include <stdio.h>
3a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh#include <sys/types.h>
4a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh#include <sys/ipc.h>
5a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh#include <sys/sem.h>
6a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh#include <signal.h>
7a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh#include <assert.h>
8a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh#include <fcntl.h>
9a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh#include <string.h>
10a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh#include <unistd.h>
11a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh#include <wait.h>
12a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh#include <sys/shm.h>
13a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh
14a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh/*
15a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh * Creates dirty data and issue sync at the end.
16a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh * Child creates enough dirty data, issues fsync. Parent synchronizes with
17a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh * child and soon as fsync is issued, dispatches KILL.
18a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh * If KILL was unsuccessful, a flag in shared memory is set.
19a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh * Parent verifies this flag to ensure test result.
20a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh */
21a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh
22a404bb0ab766a7ee63d6756e5f7e19a2185df162mblighunion semun {
23a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh	int val;
24a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh	struct semid_ds *buf;
25a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh	unsigned short  *array;
26a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh	struct seminfo  *__buf;
27a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh};
28a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh
29a404bb0ab766a7ee63d6756e5f7e19a2185df162mblighint main(int argc, char ** argv)
30a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh{
31a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh	int shm_id;
32a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh	char* shm_addr, *data_array;
33a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh	struct shmid_ds shm_desc;
34a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh	union semun data;
35a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh	struct sembuf op;
36a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh	int sem_id;
37a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh
38a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh	int status, pid, fd, len, loop;
39a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh	int count = 0, ret = 1, data_size;
40a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh	int *post_sync;
41a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh
42a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh	if (argc != 3) {
43a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh		printf("Usage : synctest <len> <loop> \n");
44a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh		exit(1);
45a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh	}
46a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh
47a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh	len = atoi(argv[1]);
48a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh	loop = atoi(argv[2]);
49a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh
50a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh	data_size = len * 1024 * 1024;
51a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh
52a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh	/* allocate a shared memory segment with size of 10 bytes. */
53a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh	shm_id = shmget(IPC_PRIVATE, 10, IPC_CREAT | IPC_EXCL | 0600);
54a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh	if (shm_id == -1) {
55a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh		perror("main : shmget \n");
56a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh		exit(1);
57a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh	}
58a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh
59a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh	/* attach the shared memory segment to our process's address space. */
60a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh	shm_addr = shmat(shm_id, NULL, 0);
61a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh	if (!shm_addr) { /* operation failed. */
62a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh		perror("main : shmat \n");
63a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh		goto early_out;
64a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh	}
65a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh
66a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh	post_sync = (int*) shm_addr;
67a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh	*post_sync = 0;
68a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh
69a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh	fd = open("testfile", O_RDWR|O_CREAT|O_APPEND|O_NONBLOCK);
70a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh	if (!fd) {
71a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh		perror("main : Failed to create data file \n");
72a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh		goto out;
73a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh	}
74a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh
75a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh	data_array = (char *)malloc(data_size * sizeof(char));
76a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh	if (!data_array) {
77a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh		perror("main : Not enough memory \n");
78a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh		goto out;
79a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh	}
80a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh
81a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh	op.sem_num = 0;
82a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh	sem_id = semget(IPC_PRIVATE, 1, IPC_CREAT);
83a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh
84a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh	if (sem_id < 0){
85a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh		perror("main : semget \n");
86a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh		goto out;
87a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh	}
88a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh
89a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh	data.val = 0;
90a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh	semctl(sem_id, 0, SETVAL, data);
91a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh
92a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh	pid = fork();
93a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh	if (pid < 0)
94a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh	{
95a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh		perror("main : fork failed \n");
96a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh		goto out;
97a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh	}
98a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh	if (!pid)
99a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh	{
100a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh		/* child process */
101a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh		while (count++ < loop) {
102a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh			write(fd, data_array, data_size * (sizeof(char)));
103a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh		}
104a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh
105a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh		printf("CHLD : start sync \n");
106a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh		/* increment sema */
107a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh		op.sem_op = 1;
108a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh		semop(sem_id, &op, 1);
109a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh
110a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh		/* wait for parent */
111a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh		op.sem_op = 0;
112a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh		semop(sem_id, &op, 1);
113a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh		fsync(fd);
114a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh		*post_sync = 1;
115a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh		return 0 ;
116a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh	} else {
117a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh		/* parent process */
118a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh		/* waiting for child to increment sema */
119a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh		op.sem_op = -1;
120a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh		semop(sem_id, &op, 1);
121a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh		/* some sleep so fsync gets started before we kill*/
122a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh		sleep(1);
123a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh
124a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh		ret = kill(pid, SIGKILL);
125a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh		if (ret) {
126a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh			perror("main : kill failed \n");
127a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh			goto out;
128a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh		}
129a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh
130a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh		printf("PAR : waiting\n");
131a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh		wait(&status);
132a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh	}
133a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh
134a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh	ret = *post_sync;
135a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh
136a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh	if (!ret)
137a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh		printf("PASS : sync interrupted \n");
138a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh	else
139a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh		printf("FAIL : sync not interrupted \n");
140a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh
141a404bb0ab766a7ee63d6756e5f7e19a2185df162mblighout:
142a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh	/* detach the shared memory segment from our process's address space. */
143a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh	if (shmdt(shm_addr) == -1) {
144a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh		perror("main : shmdt");
145a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh	}
146a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh
147a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh	close(fd);
148a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh	system("rm -f testfile \n");
149a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh
150a404bb0ab766a7ee63d6756e5f7e19a2185df162mblighearly_out:
151a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh
152a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh	/* de-allocate the shared memory segment. */
153a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh	if (shmctl(shm_id, IPC_RMID, &shm_desc) == -1) {
154a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh		perror("main : shmctl");
155a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh	}
156a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh
157a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh	return ret;
158a404bb0ab766a7ee63d6756e5f7e19a2185df162mbligh}
159