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 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