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