Add file hashing helpers
authorJens Axboe <jens.axboe@oracle.com>
Sat, 1 Mar 2008 17:56:24 +0000 (18:56 +0100)
committerJens Axboe <jens.axboe@oracle.com>
Sat, 1 Mar 2008 17:56:24 +0000 (18:56 +0100)
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Makefile
filehash.c [new file with mode: 0644]
filehash.h [new file with mode: 0644]
init.c

index 7c79e91..1380c02 100644 (file)
--- 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 (file)
index 0000000..1bcfc6d
--- /dev/null
@@ -0,0 +1,107 @@
+#include <stdlib.h>
+#include <assert.h>
+
+#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 (file)
index 0000000..a89a91f
--- /dev/null
@@ -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 e53f103..4d336fa 100644 (file)
--- 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;
 }