Home | History | Annotate | Download | only in src
      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