From: Jens Axboe Date: Sat, 1 Mar 2008 17:56:24 +0000 (+0100) Subject: Add file hashing helpers X-Git-Tag: fio-1.20-rc1~13 X-Git-Url: https://git.kernel.dk/?p=fio.git;a=commitdiff_plain;h=380065aa652b87093d6bbd240e70db30bd6f193d;hp=2e5cdb118aeb26cb469a50f746b632676306f698;ds=sidebyside Add file hashing helpers Signed-off-by: Jens Axboe --- diff --git a/Makefile b/Makefile index 7c79e910..1380c02c 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ PROGS = fio SCRIPTS = fio_generate_plots OBJS = gettime.o fio.o ioengines.o init.o stat.o log.o time.o filesetup.o \ eta.o verify.o memory.o io_u.o parse.o mutex.o sem.o options.o \ - rbtree.o diskutil.o fifo.o blktrace.o smalloc.o + rbtree.o diskutil.o fifo.o blktrace.o smalloc.o filehash.o OBJS += crc/crc7.o OBJS += crc/crc16.o diff --git a/filehash.c b/filehash.c new file mode 100644 index 00000000..1bcfc6de --- /dev/null +++ b/filehash.c @@ -0,0 +1,107 @@ +#include +#include + +#include "fio.h" +#include "list.h" +#include "crc/crc16.h" + +#define HASH_BUCKETS 512 +#define HASH_MASK (HASH_BUCKETS - 1) + +unsigned int file_hash_size = HASH_BUCKETS * sizeof(struct list_head); + +static struct list_head *file_hash; +static struct fio_mutex *hash_lock; + +static void dump_hash(void) +{ + struct list_head *n; + unsigned int i; + + for (i = 0; i < HASH_BUCKETS; i++) { + list_for_each(n, &file_hash[i]) { + struct fio_file *f; + + f = list_entry(n, struct fio_file, hash_list); + printf("%d: %s\n", i, f->file_name); + } + } +} + +static unsigned short hash(const char *name) +{ + return crc16((const unsigned char *) name, strlen(name)) & HASH_MASK; +} + +void remove_file_hash(struct fio_file *f) +{ + fio_mutex_down(hash_lock); + + if (f->flags & FIO_FILE_HASHED) { + assert(!list_empty(&f->hash_list)); + list_del_init(&f->hash_list); + f->flags &= ~FIO_FILE_HASHED; + } + + fio_mutex_up(hash_lock); +} + +static struct fio_file *__lookup_file_hash(const char *name) +{ + struct list_head *bucket = &file_hash[hash(name)]; + struct list_head *n; + + list_for_each(n, bucket) { + struct fio_file *f = list_entry(n, struct fio_file, hash_list); + + if (!strcmp(f->file_name, name)) { + assert(f->fd != -1); + return f; + } + } + + dump_hash(); + return NULL; +} + +struct fio_file *lookup_file_hash(const char *name) +{ + struct fio_file *f; + + fio_mutex_down(hash_lock); + f = __lookup_file_hash(name); + fio_mutex_up(hash_lock); + return f; +} + +struct fio_file *add_file_hash(struct fio_file *f) +{ + struct fio_file *alias; + + if (f->flags & FIO_FILE_HASHED) + return NULL; + + INIT_LIST_HEAD(&f->hash_list); + + fio_mutex_down(hash_lock); + + alias = __lookup_file_hash(f->file_name); + if (!alias) { + f->flags |= FIO_FILE_HASHED; + list_add_tail(&f->hash_list, &file_hash[hash(f->file_name)]); + } + + fio_mutex_up(hash_lock); + return alias; +} + +void file_hash_init(void *ptr) +{ + unsigned int i; + + file_hash = ptr; + for (i = 0; i < HASH_BUCKETS; i++) + INIT_LIST_HEAD(&file_hash[i]); + + hash_lock = fio_mutex_init(1); +} diff --git a/filehash.h b/filehash.h new file mode 100644 index 00000000..a89a91f8 --- /dev/null +++ b/filehash.h @@ -0,0 +1,11 @@ +#ifndef FIO_FILE_HASH_H +#define FIO_FILE_HASH_H + +extern unsigned int file_hash_size; + +extern void file_hash_init(void *); +extern struct fio_file *lookup_file_hash(const char *); +extern struct fio_file *add_file_hash(struct fio_file *); +extern void remove_file_hash(struct fio_file *); + +#endif diff --git a/init.c b/init.c index e53f103f..4d336fa3 100644 --- a/init.c +++ b/init.c @@ -17,6 +17,7 @@ #include "fio.h" #include "parse.h" #include "smalloc.h" +#include "filehash.h" static char fio_version_string[] = "fio 1.19"; @@ -750,10 +751,13 @@ static void free_shm(void) /* * The thread area is shared between the main process and the job * threads/processes. So setup a shared memory segment that will hold - * all the job info. + * all the job info. We use the end of the region for keeping track of + * open files across jobs, for file sharing. */ static int setup_thread_area(void) { + void *hash; + /* * 1024 is too much on some machines, scale max_jobs if * we get a failure that looks like too large a shm segment @@ -761,6 +765,8 @@ static int setup_thread_area(void) do { size_t size = max_jobs * sizeof(struct thread_data); + size += file_hash_size; + shm_id = shmget(0, size, IPC_CREAT | 0600); if (shm_id != -1) break; @@ -782,6 +788,8 @@ static int setup_thread_area(void) } memset(threads, 0, max_jobs * sizeof(struct thread_data)); + hash = (void *) threads + max_jobs * sizeof(struct thread_data); + file_hash_init(hash); atexit(free_shm); return 0; }