[Ocfs2-test-devel] [PATCH 2/2] Ocfs2-test: Add semaphore to protect file_writes and log_writes.

Tristan Ye tristan.ye at oracle.com
Thu Dec 3 02:47:48 PST 2009


File writes and log writes together should be finished like a transaction,
we therefore use sem to guarantee the atomicity of such ops. and we also
want the crash will be right after a successful write or reflink.

Signed-off-by: Tristan Ye <tristan.ye at oracle.com>
---
 programs/reflink_tests/reflink_test.c       |   78 +++++++++++++++++++++++----
 programs/reflink_tests/reflink_test.h       |   15 +++++
 programs/reflink_tests/reflink_test_utils.c |   57 +++++++++++++++++++
 3 files changed, 140 insertions(+), 10 deletions(-)

diff --git a/programs/reflink_tests/reflink_test.c b/programs/reflink_tests/reflink_test.c
index 41bd544..9c95a24 100755
--- a/programs/reflink_tests/reflink_test.c
+++ b/programs/reflink_tests/reflink_test.c
@@ -1807,6 +1807,23 @@ static int destructive_test(void)
 
 	pid_t pid;
 
+	int sem_id;
+	key_t sem_key = IPC_PRIVATE;
+
+	/*get and init semaphore*/
+	sem_id = semget(sem_key, 1, 0766 | IPC_CREAT);
+	if (sem_id < 0) {
+		sem_id = errno;
+		fprintf(stderr, "semget failed, %s.\n", strerror(sem_id));
+		return -1;
+	}
+
+	ret = set_semvalue(sem_id, 1);
+	if (ret < 0) {
+		fprintf(stderr, "Set semaphore value failed!\n");
+		return ret;
+	}
+
 	while (align_filesz < file_size)
 		align_filesz += CHUNK_SIZE;
 
@@ -1876,6 +1893,11 @@ static int destructive_test(void)
 
 			for (j = 0; j < chunk_no; j++) {
 
+				if (semaphore_p(sem_id) < 0) {
+					ret = -1;
+					goto child_bail;
+				}
+
 				memset(log_rec, 0, sizeof(log_rec));
 				prep_rand_dest_write_unit(&dwu, get_rand(0,
 							  chunk_no - 1));
@@ -1886,22 +1908,38 @@ static int destructive_test(void)
 
 				ret = do_write_chunk(fd, &dwu);
 				if (ret)
-					return -1;
+					goto child_bail;
 				write(sockfd, log_rec, strlen(log_rec) + 1);
 
+				if (semaphore_v(sem_id) < 0) {
+					ret = -1;
+					goto child_bail;
+				}
+
 				if (get_rand(0, 1)) {
+					
+					if (semaphore_p(sem_id) < 0) {
+						ret = -1;
+						goto child_bail;
+					}
+
 					snprintf(dest, PATH_MAX,
 						 "%s_target_%d_%d",
 						 orig_path, getpid(), j);
-					ret = reflink(orig_path, dest, 1);
-					should_exit(ret);
 					memset(log_rec, 0, sizeof(log_rec));
 					snprintf(log_rec, sizeof(log_rec),
 						 "Reflink:\t%s\t->\t%s\n",
 						 orig_path, dest);
+					ret = reflink(orig_path, dest, 1);
+					if (ret)
+						goto child_bail;
 					write(sockfd, log_rec,
 					      strlen(log_rec) + 1);
-
+					
+					if (semaphore_v(sem_id) < 0) {
+						ret = -1;
+						goto child_bail;
+					}
 				}
 
 				/*
@@ -1909,21 +1947,38 @@ static int destructive_test(void)
 				*/
 
 				if ((j > 1) && (j < chunk_no - 1)) {
-					if (get_rand(1, chunk_no) == chunk_no / 2)
+					if (get_rand(1, chunk_no) == chunk_no / 2) {
+
+						if (semaphore_p(sem_id) < 0) {
+							ret = -1;
+							goto child_bail;
+						}
+
 						system("echo b>/proc/sysrq-trigger");
-				} else if (j == chunk_no - 1)
+					}
+				} else if (j == chunk_no - 1) {
+
+						if (semaphore_p(sem_id) < 0) {
+							ret = -1;
+							goto child_bail;
+						}
+
 						system("echo b>/proc/sysrq-trigger");
+				}
 
 				usleep(10000);
 			}
-
-			if (!fd)
+child_bail:
+			if (fd)
 				close(fd);
 
-			if (!sockfd)
+			if (sockfd)
 				close(sockfd);
 
-			exit(0);
+			if (sem_id)
+				semaphore_close(sem_id);
+
+			exit(ret);
 		}
 
 		if (pid > 0)
@@ -1960,6 +2015,9 @@ static int destructive_test(void)
 	if (sockfd)
 		close(sockfd);
 
+	if (sem_id)
+		semaphore_close(sem_id);
+
 	return 0;
 }
 
diff --git a/programs/reflink_tests/reflink_test.h b/programs/reflink_tests/reflink_test.h
index 6b12e84..3db48f1 100755
--- a/programs/reflink_tests/reflink_test.h
+++ b/programs/reflink_tests/reflink_test.h
@@ -34,6 +34,7 @@
 #include <inttypes.h>
 #include <linux/types.h>
 #include <sys/time.h>
+#include <sys/sem.h>
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -105,6 +106,13 @@ struct dest_logs {
 	unsigned long index;
 };
 
+union semun {
+	int val;                    /* value for SETVAL */
+	struct semid_ds *buf;       /* buffer for IPC_STAT, IPC_SET */
+	unsigned short int *array;  /* array for GETALL, SETALL */
+	struct seminfo *__buf;      /* buffer for IPC_INFO */
+};
+
 char rand_char(void);
 unsigned long get_rand(unsigned long min, unsigned long max);
 int get_rand_buf(char *buf, unsigned long size);
@@ -165,4 +173,11 @@ long get_verify_logs_num(char *log);
 int verify_dest_file(char *log, struct dest_logs d_log, unsigned long chunk_no);
 int verify_dest_files(char *log, char *orig, unsigned long chunk_no);
 uint32_t crc32_checksum(uint32_t crc, char *p, size_t len);
+
+/* Add utils for semaphore ops */
+int set_semvalue(int sem_id, int val);
+int semaphore_close(int sem_id);
+int semaphore_p(int sem_id);
+int semaphore_v(int sem_id);
+
 #endif
diff --git a/programs/reflink_tests/reflink_test_utils.c b/programs/reflink_tests/reflink_test_utils.c
index 4f314d0..925cb41 100755
--- a/programs/reflink_tests/reflink_test_utils.c
+++ b/programs/reflink_tests/reflink_test_utils.c
@@ -1768,3 +1768,60 @@ bail:
 
 	return ret;
 }
+
+int set_semvalue(int sem_id, int val)
+{
+	union semun sem_union;
+
+	sem_union.val = val;
+	if (semctl(sem_id, 0, SETVAL, sem_union) == -1) {
+		perror("semctl");
+		return -1;
+	}
+
+	return 0;
+}
+
+int semaphore_close(int sem_id)
+{
+	int ret = 0;
+
+	ret = semctl(sem_id, 1, IPC_RMID);
+	if (ret < 0) {
+		ret = errno;
+		fprintf(stderr, "semctl failed, %s.\n", strerror(ret));
+		return -1;
+	}
+
+	return ret;
+}
+
+int semaphore_p(int sem_id)
+{
+	struct sembuf sem_b;
+
+	sem_b.sem_num = 0;
+	sem_b.sem_op = -1; /* P() */
+	sem_b.sem_flg = SEM_UNDO;
+	if (semop(sem_id, &sem_b, 1) == -1) {
+		fprintf(stderr, "semaphore_p failed\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+int semaphore_v(int sem_id)
+{
+	struct sembuf sem_b;
+
+	sem_b.sem_num = 0;
+	sem_b.sem_op = 1; /* V() */
+	sem_b.sem_flg = SEM_UNDO;
+	if (semop(sem_id, &sem_b, 1) == -1) {
+		fprintf(stderr, "semaphore_v failed\n");
+		return -1;
+	}
+
+	return 0;
+}
-- 
1.5.5




More information about the Ocfs2-test-devel mailing list