[Ocfs2-test-devel] [PATCH 3/4] Ocfs2-test: Add generic dir operation funcs for libocfs2test.
Sunil Mushran
sunil.mushran at oracle.com
Tue Mar 31 16:51:30 PDT 2009
The num_dirents is not efficient. As in, unlink does not
make the space available for reuse. Now I understand we
don't want to go overboard considering this is just for
testing. But you could very easily use lists instead of arrays.
See stringlist in debugs.ocfs2/utils.c as an example.
Tristan Ye wrote:
> 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
>
More information about the Ocfs2-test-devel
mailing list