[Ocfs2-test-devel] [PATCH 3/4] Ocfs2-test: Add generic dir operation funcs for libocfs2test.

Tristan Ye tristan.ye at oracle.com
Tue Mar 24 05:24:07 PDT 2009


Provide generic utility fuctions on dir operations for ocfs2-tests.

Signed-off-by: Tristan Ye <tristan.ye at oracle.com>
---
 programs/libocfs2test/dir_ops.c |  345 +++++++++++++++++++++++++++++++++++++++
 programs/libocfs2test/dir_ops.h |   85 ++++++++++
 2 files changed, 430 insertions(+), 0 deletions(-)
 create mode 100644 programs/libocfs2test/dir_ops.c
 create mode 100644 programs/libocfs2test/dir_ops.h

diff --git a/programs/libocfs2test/dir_ops.c b/programs/libocfs2test/dir_ops.c
new file mode 100644
index 0000000..5857231
--- /dev/null
+++ b/programs/libocfs2test/dir_ops.c
@@ -0,0 +1,345 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * dir_ops.c
+ *
+ * Provide generic utility fuctions on dir operations for ocfs2-tests
+ *
+ * Copyright (C) 2008 Oracle.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#include "dir_ops.h"
+
+extern unsigned long num_dirents;
+extern struct my_dirent *dirents;
+
+extern int is_dot_entry(struct my_dirent *dirent)
+{
+	if (dirent->name_len == 1 && dirent->name[0] == '.')
+		return 1;
+	if (dirent->name_len == 2 && dirent->name[0] == '.'
+	    && dirent->name[1] == '.')
+		return 1;
+
+	return 0;
+}
+
+extern int unlink_dirent(char *dirname, struct my_dirent *dirent)
+{
+	char path[PATH_MAX];
+
+	dirent->name_len = 0;
+	dirent->seen = 0;
+	sprintf(path, "%s/%s", dirname, dirent->name);
+
+	return unlink(path);
+}
+
+extern int create_and_prep_dir(char *dirname)
+{
+	int ret;
+	struct my_dirent *dirent;
+	
+	memset(dirents, 0, sizeof(struct my_dirent) * MAX_DIRENTS);
+	
+	dirent = &dirents[0];
+	dirent->type = S_IFDIR >> S_SHIFT;
+	dirent->name_len = 1;
+	strcpy(dirent->name, ".");
+	
+	dirent = &dirents[1];
+	dirent->type = S_IFDIR >> S_SHIFT;
+	dirent->name_len = 2;
+	strcpy(dirent->name, "..");
+	
+	num_dirents = 2;
+	ret = mkdir(dirname, FILE_MODE);
+	if (ret) {
+	        ret = errno;
+	        fprintf(stderr, "mkdir failure %d: %s\n", ret, strerror(ret));
+		return ret;
+	}
+	
+	return 0;
+}
+
+extern int destroy_dir(char *dirname)
+{
+	int ret, i;
+	struct my_dirent *dirent;
+
+	for (i = 0; i < num_dirents; i++) {
+		dirent = &dirents[i];
+
+		if (dirent->name_len == 0)
+			continue;
+
+		if (!is_dot_entry(dirent)) {
+			ret = unlink_dirent(dirname, dirent);
+			if (ret < 0) {
+				ret = errno;
+				fprintf(stderr, "unlink failure %d: %s\n", ret,
+					strerror(ret));
+				return ret;
+			}
+
+			dirent->name_len = 0;
+		}
+
+        }
+
+	ret = rmdir(dirname);
+	if (ret) {
+		ret = errno;
+		fprintf(stderr, "rmdir failure %d: %s\n", ret,
+			strerror(ret));
+		return ret;
+	}
+	
+	num_dirents = 0;
+	
+	return 0;
+}
+
+extern struct my_dirent *find_my_dirent(char *name)
+{
+	int i, len;
+	struct my_dirent *my_dirent;
+
+	len = strlen(name);
+
+	for (i = 0; i < num_dirents; i++) {
+		my_dirent = &dirents[i];
+
+		if (my_dirent->name_len == 0)
+			continue;
+
+		if (my_dirent->name_len == len &&
+		    strcmp(my_dirent->name, name) == 0)
+			return my_dirent;
+	}
+
+	return NULL;
+}
+
+
+extern int create_file(char *filename, char *dirname)
+{
+	int ret, fd;
+	struct my_dirent *dirent;
+	char path[PATH_MAX];
+	
+	dirent = &dirents[num_dirents];
+	num_dirents++;
+	
+	dirent->type = S_IFREG >> S_SHIFT;
+	dirent->name_len = strlen(filename);
+	dirent->seen = 0;
+	strcpy(dirent->name, filename);
+	
+	sprintf(path, "%s/%s", dirname, dirent->name);
+	
+	fd = open(path, FILE_BUFFERED_RW_FLAGS, FILE_MODE);
+	if (fd < 0) {
+	        ret = errno;
+	        fprintf(stderr, "Create file %s failure %d: %s\n", path, ret,
+			strerror(ret));
+		return ret;
+	}
+	
+	close(fd);
+	
+	return 0;
+}
+
+extern int create_files(char *prefix, unsigned long num, char *dirname)
+{
+        int i, ret;
+	char dirent_nam[OCFS2_MAX_FILENAME_LEN];
+	char path[PATH_MAX];
+
+        for (i = 0; i < num; i++) {
+		if (!prefix) {
+			get_rand_nam(dirent_nam, 3, OCFS2_MAX_FILENAME_LEN/4);
+			ret = create_file(dirent_nam, dirname);
+		} else {
+                	snprintf(path, PATH_MAX, "%s%011d", prefix, i);
+			ret = create_file(path, dirname);
+		}
+
+		if (ret < 0)
+			return ret;
+        }
+
+	return 0;
+}
+
+extern int is_dir_empty(char *name)
+{
+	DIR *dir;
+	int ret, entries = 0;
+	struct dirent *dirent;
+	
+	dir = opendir(name);
+	if (dir < 0) {
+		ret = errno;
+		fprintf(stderr, "dir open failure %d: %s\n", ret,
+			strerror(ret));
+	}
+
+	dirent = readdir(dir);
+	while (dirent) {
+		entries++;
+		dirent = readdir(dir);
+		if ( entries > 2)
+			break;
+	}
+
+	closedir(dir);
+
+	if (entries == 2)
+		return 1;
+	else
+		return 0;
+}
+
+/*
+ *
+ */
+extern int build_dir_tree(char *dirname, unsigned long entries,
+		    unsigned long depth, int is_random)
+{
+	unsigned long i, dir_dirents, file_dirents;
+	char fullpath[PATH_MAX];
+	char dirent[OCFS2_MAX_FILENAME_LEN];
+	unsigned long layer = depth;
+
+	int fd, ret;
+
+	ret = mkdir(dirname, FILE_MODE);
+	if (ret < 0) {
+		ret = errno;
+		fprintf(stderr, "mkdir failure %d: %s\n", ret,
+			strerror(ret));
+		return ret;
+	}
+
+	if (layer == 0)
+		return;
+
+	if (is_random)
+		dir_dirents = get_rand(1, entries - 1);
+	else
+		dir_dirents = entries / 2;
+
+	file_dirents = entries - dir_dirents;
+
+	for (i = 0; i < file_dirents; i++) {
+		if (is_random) {
+			get_rand_nam(dirent, 1, OCFS2_MAX_FILENAME_LEN - 20);
+			snprintf(fullpath, PATH_MAX, "%s/%s%ld%ld",
+				 dirname, dirent, layer, i);
+		} else 
+			snprintf(fullpath, PATH_MAX, "%s/%s%ld%ld",
+				 dirname, "F", layer, i);
+		if (strlen(fullpath) > PATH_MAX)
+			return;
+		fd = open(fullpath, FILE_BUFFERED_RW_FLAGS, FILE_MODE);
+		if (fd < 0) {
+			ret = errno;
+			fprintf(stderr, "create file failure %d: %s,"
+				"filename = %s\n", ret, strerror(ret),
+				fullpath);
+			return ret;
+		}
+
+		close(fd);
+	}
+
+	for (i = 0; i < dir_dirents; i++) {
+		if (is_random) {
+			get_rand_nam(dirent, 1, OCFS2_MAX_FILENAME_LEN - 20);
+			snprintf(fullpath, PATH_MAX, "%s/%s%ld%ld",
+				 dirname, dirent, layer, i);
+		} else
+			snprintf(fullpath, PATH_MAX, "%s/%s%ld%ld",
+				 dirname, "D", layer, i);
+		if (strlen(fullpath) > PATH_MAX)
+			return;
+
+		build_dir_tree(fullpath, entries, layer - 1, is_random);
+	}
+
+	return 0;
+}
+
+extern int set_semvalue(int sem_id)
+{
+        union semun sem_union;
+
+        sem_union.val = 1;
+        if (semctl(sem_id, 0, SETVAL, sem_union) == -1) {
+                perror("semctl");
+                return -1;
+        }
+
+        return 0;
+}
+
+extern 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;
+}
+
+extern 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;
+}
+
+extern int get_max_inlined_entries(int max_inline_size)
+{
+        unsigned int almost_full_entries;
+	
+	/*
+		Borrowed from mark's inline-dirs test to measure
+		how to fill up the inlined directory.
+	*/
+	almost_full_entries = max_inline_size / 512;
+	almost_full_entries *= 512;
+	almost_full_entries /= 32;
+
+	almost_full_entries += 8;
+
+
+	return almost_full_entries;
+}
+
diff --git a/programs/libocfs2test/dir_ops.h b/programs/libocfs2test/dir_ops.h
new file mode 100644
index 0000000..a20c181
--- /dev/null
+++ b/programs/libocfs2test/dir_ops.h
@@ -0,0 +1,85 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * dir_ops.h
+ *
+ * Copyright (C) 2008 Oracle.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+#ifndef DIR_OPS_H
+#define DIR_OPS_H
+
+#define _XOPEN_SOURCE 600
+#define _GNU_SOURCE
+#define _LARGEFILE64_SOURCE
+
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/vfs.h>
+#include <sys/shm.h>
+#include <sys/sem.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <limits.h>
+
+#include <ocfs2/ocfs2.h>
+
+#include <dirent.h>
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+
+#include <signal.h>
+#include <sys/wait.h>
+#include <inttypes.h>
+
+#define OCFS2_MAX_FILENAME_LEN          255
+#define MAX_DIRENTS                     40000
+
+#define FILE_BUFFERED_RW_FLAGS  (O_CREAT|O_RDWR|O_TRUNC)
+#define FILE_MODE               (S_IRUSR|S_IWUSR|S_IXUSR|S_IROTH|\
+                                 S_IWOTH|S_IXOTH|S_IRGRP|S_IWGRP|S_IXGRP)
+
+struct my_dirent {
+	unsigned int    type;
+	unsigned int    name_len;
+	unsigned int    seen;
+	char            name[OCFS2_MAX_FILENAME_LEN];
+};
+
+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 */
+};
+
+int is_dot_entry(struct my_dirent *dirent);
+int unlink_dirent(char *dirname, struct my_dirent *dirent);
+int create_and_prep_dir(char *dirname);
+int destroy_dir(char *dirname);
+struct my_dirent *find_my_dirent(char *name);
+int create_file(char *filename, char *dirname);
+int create_files(char *prefix, unsigned long num, char *dirname);
+int is_dir_empty(char *name);
+int build_dir_tree(char *dirname, unsigned long entries, unsigned long depth,
+		   int is_random);
+int set_semvalue(int sem_id);
+int semaphore_p(int sem_id);
+int semaphore_v(int sem_id);
+int get_max_inlined_entries(int max_inline_size);
+
+#endif
-- 
1.5.5




More information about the Ocfs2-test-devel mailing list