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