[Ocfs2-tools-devel] [Ocfs2-test-devel] [PATCH 3/6] New set of inline-data testing tools:Add single-node testing binary for directory

Tao Ma tao.ma at oracle.com
Sun Aug 31 23:09:58 PDT 2008



tristan.ye wrote:
> Still have sent this patch out before,
> 
> just enhance the orignal inline-dirs.c become work-load tunable,to
> perform a variety of test,such as stress test. also add concurrent r/w
> and multiple directories cases.
> 
> Signed-off-by: Tristan Ye <tristan.ye at oracle.com>
> ---
> 
> Index: ocfs2-test/programs/inline-data/single-inline-dirs.c
> ===================================================================
> --- ocfs2-test/programs/inline-data/single-inline-dirs.c	(revision 0)
> +++ ocfs2-test/programs/inline-data/single-inline-dirs.c	(revision 0)
> @@ -0,0 +1,1227 @@
> +/*
> + * Verify inline directory data.
> + *
> + * All tests read back the entire directory to verify correctness.
> + *
> + * XXX: This could easily be turned into an mpi program, where a
> + * second node does the verification step.
> + */
> +
> +#define _XOPEN_SOURCE 600
> +#define _GNU_SOURCE
> +
> +#include <asm/types.h>
> +#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>
> +#include <linux/types.h>
> +
> +
> +#define OCFS2_MAX_FILENAME_LEN		255
> +
> +/*
> + * OCFS2_DIR_PAD defines the directory entries boundaries
> + *
> + * NOTE: It must be a multiple of 4
> + */
> +#define OCFS2_DIR_PAD			4
> +#define OCFS2_DIR_ROUND			(OCFS2_DIR_PAD - 1)
> +#define OCFS2_DIR_MEMBER_LEN 		offsetof(struct ocfs2_dir_entry, name)
> +#define OCFS2_DIR_REC_LEN(name_len)	(((name_len) + OCFS2_DIR_MEMBER_LEN
> + \
> +                                          OCFS2_DIR_ROUND) & \
> +					 ~OCFS2_DIR_ROUND)
why need this? they are already defined in ocfs2_fs.h.
> +/*
> + * Quick reference table of namelen boundaries and their respective
> reclens.
> + *
> + * (name: 1  rec: 16)      (name: 5  rec: 20)      (name: 9  rec: 24)
> + * (name: 13  rec: 28)     (name: 17  rec: 32)     (name: 21  rec: 36)
> + * (name: 25  rec: 40)     (name: 29  rec: 44)     (name: 33  rec: 48)
> + * (name: 37  rec: 52)     (name: 41  rec: 56)     (name: 45  rec: 60)
> + * (name: 49  rec: 64)     (name: 53  rec: 68)     (name: 57  rec: 72)
> + * (name: 61  rec: 76)     (name: 65  rec: 80)     (name: 69  rec: 84)
> + * (name: 73  rec: 88)     (name: 77  rec: 92)     (name: 81  rec: 96)
> + * (name: 85  rec: 100)    (name: 89  rec: 104)    (name: 93  rec: 108)
> + * (name: 97  rec: 112)    (name: 101  rec: 116)   (name: 105  rec:
> 120)
> + * (name: 109  rec: 124)   (name: 113  rec: 128)   (name: 117  rec:
> 132)
> + * (name: 121  rec: 136)   (name: 125  rec: 140)   (name: 129  rec:
> 144)
> + * (name: 133  rec: 148)   (name: 137  rec: 152)   (name: 141  rec:
> 156)
> + * (name: 145  rec: 160)   (name: 149  rec: 164)   (name: 153  rec:
> 168)
> + * (name: 157  rec: 172)   (name: 161  rec: 176)   (name: 165  rec:
> 180)
> + * (name: 169  rec: 184)   (name: 173  rec: 188)   (name: 177  rec:
> 192)
> + * (name: 181  rec: 196)   (name: 185  rec: 200)   (name: 189  rec:
> 204)
> + * (name: 193  rec: 208)   (name: 197  rec: 212)   (name: 201  rec:
> 216)
> + * (name: 205  rec: 220)   (name: 209  rec: 224)   (name: 213  rec:
> 228)
> + * (name: 217  rec: 232)   (name: 221  rec: 236)   (name: 225  rec:
> 240)
> + * (name: 229  rec: 244)   (name: 233  rec: 248)   (name: 237  rec:
> 252)
> + * (name: 241  rec: 256)   (name: 245  rec: 260)   (name: 249  rec:
> 264)
> + * (name: 253  rec: 268)
> + */
also why you want this?

> +static int get_max_inlined_entries(int max_inline_size)
Please note that with Tiger's new xattr, max_inline_size may be changed.
so here the magic number(312 etc) may not be ok.
> +{
> +	unsigned int almost_full_entries;
> +
> +        /*
> +         * This will create enough entries to leave only 280 free
> +         * bytes in the directory.
> +         *
> +         * max_inline_size % 512 = 312    [always]
> +         * rec overhead for '.' and '..' = 32
> +         * So, 312 - 32 = 280.
> +         *
> +         */
> +	almost_full_entries = max_inline_size / 512;
> +	almost_full_entries *= 512;
> +	almost_full_entries /= 32;
> +
> +        /*
> +         * Now we add enough 32 byte entries to fill that remaining 280
> bytes:
> +         *
> +         * 280 / 32 = 8
> +         *
> +         * And we'll be left over with 24 bytes:
> +         *
> +         * 280 % 32 = 24
> +         *
> +         * Which can easily be overflowed by adding one more 32 byte
> entry.
> +         */
> +	almost_full_entries += 8;
> +        /*if user-specified operated_entries larger than this,decrease
> to a
> +          right inlined number
> +        */
> +	if (operated_entries > almost_full_entries)
> +		operated_entries = almost_full_entries - 1;
> +
> +	return almost_full_entries;
> +
> +}
> +static void get_directory_almost_full(int minus_this_many)
> +{
> +	int almost_full_entries;
> +
> +	almost_full_entries = get_max_inlined_entries(max_inline_size);
> +
> +	almost_full_entries -= minus_this_many;
> +
> +	/* Need up to 20 characters to get a 32 byte entry */
> +	create_files("filename-", almost_full_entries);
> +}
> +
> +static void random_unlink(int iters)
> +{
> +	int i, ret;
> +	struct my_dirent *dirent;
> +
> +	while (iters > 0) {
> +		i = get_rand(0, num_dirents - 1);
> +		dirent = &dirents[i];
> +
> +		if (is_dot_entry(dirent))
> +			continue;
> +		if (dirent->name_len == 0)
> +			continue;
> +
> +		ret = unlink_dirent(dirent);
> +		if (ret) {
> +			ret = errno;
> +			fprintf(stderr, "unlink failure %d: %s\n", ret,
> +				strerror(ret));
> +			exit(ret);
> +		}
> +
> +		dirent->name_len = 0;
> +		iters--;
> +	}
> +}
> +
> +static void random_fill_empty_entries(int iters)
> +{
> +	int i, ret, fd;
> +	struct my_dirent *dirent;
> +
> +	while (iters > 0) {
> +		i = get_rand(0, num_dirents - 1);
> +		dirent = &dirents[i];
> +
> +		if (is_dot_entry(dirent))
> +			continue;
> +		if (dirent->name_len > 0)
> +			continue;
> +
> +		//sprintf(path1, "%s%011d", "filename-", i);
> +		dirent->type = S_IFREG >> S_SHIFT;
> +		dirent->name_len = strlen(dirent->name);
> +		dirent->seen = 0;
> +		//strcpy(dirent->name, path1);
> +
> +		sprintf(path, "%s/%s", dir_name, dirent->name);
> +
> +		fd = open(path, FILE_BUFFERED_RW_FLAGS, FILE_MODE);
> +		if (fd == -1) {
> +			ret = errno;
> +			fprintf(stderr, "open failure %d: %s\n", ret, strerror(ret));
> +			exit(ret);
> +		}
> +
> +		close(fd);
> +		
> +		iters--;
> +	}
> +}
> +
> +static void random_rename_same_reclen(int iters)
> +{
> +	int i, ret;
> +	struct my_dirent *dirent;
> +
> +	while (iters > 0) {
> +		i = get_rand(0, num_dirents - 1);
> +		dirent = &dirents[i];
> +
> +		if (is_dot_entry(dirent))
> +			continue;
> +		if (dirent->name_len == 0)
> +			continue;
> +
> +		/*
> +		 * We already renamed this one
> +		 */
> +		/*
> +		if (dirent->name[0] == 'R')
> +			continue;
> +		*/
> +
> +		strcpy(path, dirent->name);
> +		path[0] = 'R';
> +		sprintf(path1, "%s/%s", dir_name, path);
> +		sprintf(path, "%s/%s", dir_name, dirent->name);
> +
> +		ret = rename(path, path1);
> +		if (ret) {
> +			ret = errno;
> +			fprintf(stderr, "rename failure %d: %s\n", ret,
> +				strerror(ret));
> +
> +			fprintf(stderr, "Failed rename from %s to %s\n",
> +				path, path1);
> +
> +			exit(ret);
> +		}
> +		dirent->name[0] = 'R';
> +		iters--;
> +	}
> +}
> +
> +static void random_deleting_rename(int iters)
> +{
> +	int i, j, ret;
> +	struct my_dirent *dirent1, *dirent2;
> +
> +	while (iters--) {
> +		i = get_rand(0, num_dirents - 1);
> +		j = get_rand(0, num_dirents - 1);
you can start from 2 instead of 0 so that you will not get '.' or '..' 
if I read your code correctly.
> +		dirent1 = &dirents[i];
> +		dirent2 = &dirents[j];
> +
> +		if (dirent1 == dirent2)
> +			continue;
> +		if (is_dot_entry(dirent1) || is_dot_entry(dirent2))
> +			continue;
> +		if (dirent1->name_len == 0 || dirent2->name_len == 0)
> +			continue;
> +
> +		sprintf(path, "%s/%s", dir_name, dirent1->name);
> +		sprintf(path1, "%s/%s", dir_name, dirent2->name);
> +
> +		ret = rename(path, path1);
> +		if (ret) {
> +			ret = errno;
> +			fprintf(stderr, "rename failure %d: %s\n", ret,
> +				strerror(ret));
> +
> +			fprintf(stderr, "Failed rename from %s to %s\n",
> +				path, path1);
> +
> +			exit(ret);
> +		}
> +		dirent2->type = dirent1->type;
> +		dirent1->name_len = 0;
> +	}
> +}
> +
btw, I have seen many functions quite similar with the previous patch, 
so is there any possibility that you can merge them together(I mean 
create another file and link it when you create your executives)?

Regards,
Tao



More information about the Ocfs2-tools-devel mailing list