The following changes since commit 36bb0880c7f7f48abb86e3a16d3168343dda9b75: Fix disk utils being updated too often (2015-01-07 15:04:39 -0700) are available in the git repository at: git://git.kernel.dk/fio.git master for you to fetch changes up to f9a33cc03d70ff34b740629cbde4cef22a120338: client: take better care to return failure from fio_handle_clients() (2015-01-13 21:47:43 -0700) ---------------------------------------------------------------- Jens Axboe (4): filelock: fix segfault on some use cases of log file locking axmap: random maps are private, don't get them from smalloc smalloc: limit to 1 pool, and bump size to 16MB client: take better care to return failure from fio_handle_clients() Yoshinori Sato (1): mmap backend invalidate fix client.c | 8 ++- engines/mmap.c | 25 ++++---- filelock.c | 174 ++++++++++++++++++++++++++++++++++++++++++-------------- lib/axmap.c | 17 +++--- smalloc.c | 4 +- 5 files changed, 158 insertions(+), 70 deletions(-) --- Diff of recent changes: diff --git a/client.c b/client.c index 74c9c76..760ec85 100644 --- a/client.c +++ b/client.c @@ -62,6 +62,8 @@ static struct json_object *root = NULL; static struct json_array *clients_array = NULL; static struct json_array *du_array = NULL; +static int error_clients; + #define FIO_CLIENT_HASH_BITS 7 #define FIO_CLIENT_HASH_SZ (1 << FIO_CLIENT_HASH_BITS) #define FIO_CLIENT_HASH_MASK (FIO_CLIENT_HASH_SZ - 1) @@ -176,6 +178,9 @@ void fio_put_client(struct fio_client *client) if (!client->did_stat) sum_stat_clients--; + if (client->error) + error_clients++; + free(client); } @@ -1616,6 +1621,7 @@ static int fio_check_clients_timed_out(void) else log_err("fio: client %s timed out\n", client->hostname); + client->error = ETIMEDOUT; remove_client(client); ret = 1; } @@ -1709,5 +1715,5 @@ int fio_handle_clients(struct client_ops *ops) fio_client_json_fini(); free(pfds); - return retval; + return retval || error_clients; } diff --git a/engines/mmap.c b/engines/mmap.c index 8bcd42c..69add78 100644 --- a/engines/mmap.c +++ b/engines/mmap.c @@ -62,6 +62,16 @@ static int fio_mmap_file(struct thread_data *td, struct fio_file *f, goto err; } } + if (posix_madvise(fmd->mmap_ptr, length, POSIX_MADV_DONTNEED) < 0) { + td_verror(td, errno, "madvise"); + goto err; + } + +#ifdef FIO_MADV_FREE + if (f->filetype == FIO_TYPE_BD) + (void) posix_madvise(fmd->mmap_ptr, fmd->mmap_sz, FIO_MADV_FREE); +#endif + err: if (td->error && fmd->mmap_ptr) @@ -252,20 +262,6 @@ static int fio_mmapio_close_file(struct thread_data *td, struct fio_file *f) return generic_close_file(td, f); } -static int fio_mmapio_invalidate(struct thread_data *td, struct fio_file *f) -{ - struct fio_mmap_data *fmd = FILE_ENG_DATA(f); - int ret; - - ret = posix_madvise(fmd->mmap_ptr, fmd->mmap_sz, POSIX_MADV_DONTNEED); -#ifdef FIO_MADV_FREE - if (f->filetype == FIO_TYPE_BD) - (void) posix_madvise(fmd->mmap_ptr, fmd->mmap_sz, FIO_MADV_FREE); -#endif - - return ret; -} - static struct ioengine_ops ioengine = { .name = "mmap", .version = FIO_IOOPS_VERSION, @@ -274,7 +270,6 @@ static struct ioengine_ops ioengine = { .queue = fio_mmapio_queue, .open_file = fio_mmapio_open_file, .close_file = fio_mmapio_close_file, - .invalidate = fio_mmapio_invalidate, .get_file_size = generic_get_file_size, .flags = FIO_SYNCIO | FIO_NOEXTEND, }; diff --git a/filelock.c b/filelock.c index 18e8875..17b5a85 100644 --- a/filelock.c +++ b/filelock.c @@ -5,6 +5,7 @@ */ #include <inttypes.h> #include <string.h> +#include <unistd.h> #include <assert.h> #include "flist.h" @@ -20,36 +21,99 @@ struct fio_filelock { struct flist_head list; unsigned int references; }; + +#define MAX_FILELOCKS 128 -static struct flist_head *filelock_list; -static struct fio_mutex *filelock_lock; +static struct filelock_data { + struct flist_head list; + struct fio_mutex lock; + + struct flist_head free_list; + struct fio_filelock ffs[MAX_FILELOCKS]; +} *fld; + +static void put_filelock(struct fio_filelock *ff) +{ + flist_add(&ff->list, &fld->free_list); +} + +static struct fio_filelock *__get_filelock(void) +{ + struct fio_filelock *ff; + + if (flist_empty(&fld->free_list)) + return NULL; + + ff = flist_first_entry(&fld->free_list, struct fio_filelock, list); + flist_del_init(&ff->list); + return ff; +} + +static struct fio_filelock *get_filelock(int trylock, int *retry) +{ + struct fio_filelock *ff; + + do { + ff = __get_filelock(); + if (ff || trylock) + break; + + fio_mutex_up(&fld->lock); + usleep(1000); + fio_mutex_down(&fld->lock); + *retry = 1; + } while (1); + + return ff; +} int fio_filelock_init(void) { - filelock_list = smalloc(sizeof(*filelock_list)); - if (!filelock_list) - return 1; + int i; - INIT_FLIST_HEAD(filelock_list); - filelock_lock = fio_mutex_init(FIO_MUTEX_UNLOCKED); - if (!filelock_lock) { - sfree(filelock_list); + fld = smalloc(sizeof(*fld)); + if (!fld) return 1; + + INIT_FLIST_HEAD(&fld->list); + INIT_FLIST_HEAD(&fld->free_list); + + if (__fio_mutex_init(&fld->lock, FIO_MUTEX_UNLOCKED)) + goto err; + + for (i = 0; i < MAX_FILELOCKS; i++) { + struct fio_filelock *ff = &fld->ffs[i]; + + if (__fio_mutex_init(&ff->lock, FIO_MUTEX_UNLOCKED)) + goto err; + flist_add_tail(&ff->list, &fld->free_list); } return 0; +err: + fio_filelock_exit(); + return 1; } void fio_filelock_exit(void) { - if (!filelock_list) + if (!fld) return; - assert(flist_empty(filelock_list)); - sfree(filelock_list); - filelock_list = NULL; - fio_mutex_remove(filelock_lock); - filelock_lock = NULL; + assert(flist_empty(&fld->list)); + fio_mutex_remove(&fld->lock); + + while (!flist_empty(&fld->free_list)) { + struct fio_filelock *ff; + + ff = flist_first_entry(&fld->free_list, struct fio_filelock, list); + + flist_del_init(&ff->list); + fio_mutex_remove(&ff->lock); + } + + sfree(fld); + fld = NULL; } static struct fio_filelock *fio_hash_find(uint32_t hash) @@ -57,7 +121,7 @@ static struct fio_filelock *fio_hash_find(uint32_t hash) struct flist_head *entry; struct fio_filelock *ff; - flist_for_each(entry, filelock_list) { + flist_for_each(entry, &fld->list) { ff = flist_entry(entry, struct fio_filelock, list); if (ff->hash == hash) return ff; @@ -66,38 +130,68 @@ static struct fio_filelock *fio_hash_find(uint32_t hash) return NULL; } -static struct fio_filelock *fio_hash_get(uint32_t hash) +static struct fio_filelock *fio_hash_get(uint32_t hash, int trylock) { struct fio_filelock *ff; ff = fio_hash_find(hash); if (!ff) { - ff = smalloc(sizeof(*ff)); + int retry = 0; + + ff = get_filelock(trylock, &retry); + if (!ff) + return NULL; + + /* + * If we dropped the main lock, re-lookup the hash in case + * someone else added it meanwhile. If it's now there, + * just return that. + */ + if (retry) { + struct fio_filelock *__ff; + + __ff = fio_hash_find(hash); + if (__ff) { + put_filelock(ff); + return __ff; + } + } + ff->hash = hash; - __fio_mutex_init(&ff->lock, FIO_MUTEX_UNLOCKED); ff->references = 0; - flist_add(&ff->list, filelock_list); + flist_add(&ff->list, &fld->list); } return ff; } -int fio_trylock_file(const char *fname) +static int __fio_lock_file(const char *fname, int trylock) { struct fio_filelock *ff; uint32_t hash; hash = jhash(fname, strlen(fname), 0); - fio_mutex_down(filelock_lock); - ff = fio_hash_get(hash); - ff->references++; - fio_mutex_up(filelock_lock); + fio_mutex_down(&fld->lock); + ff = fio_hash_get(hash, trylock); + if (ff) + ff->references++; + fio_mutex_up(&fld->lock); + + if (!ff) { + assert(!trylock); + return 1; + } + + if (!trylock) { + fio_mutex_down(&ff->lock); + return 0; + } if (!fio_mutex_down_trylock(&ff->lock)) return 0; - fio_mutex_down(filelock_lock); + fio_mutex_down(&fld->lock); /* * If we raced and the only reference to the lock is us, we can @@ -108,7 +202,7 @@ int fio_trylock_file(const char *fname) ff = NULL; } - fio_mutex_up(filelock_lock); + fio_mutex_up(&fld->lock); if (ff) { fio_mutex_down(&ff->lock); @@ -118,19 +212,14 @@ int fio_trylock_file(const char *fname) return 1; } -void fio_lock_file(const char *fname) +int fio_trylock_file(const char *fname) { - struct fio_filelock *ff; - uint32_t hash; - - hash = jhash(fname, strlen(fname), 0); - - fio_mutex_down(filelock_lock); - ff = fio_hash_get(hash); - ff->references++; - fio_mutex_up(filelock_lock); + return __fio_lock_file(fname, 1); +} - fio_mutex_down(&ff->lock); +void fio_lock_file(const char *fname) +{ + __fio_lock_file(fname, 0); } void fio_unlock_file(const char *fname) @@ -140,19 +229,18 @@ void fio_unlock_file(const char *fname) hash = jhash(fname, strlen(fname), 0); - fio_mutex_down(filelock_lock); + fio_mutex_down(&fld->lock); ff = fio_hash_find(hash); if (ff) { int refs = --ff->references; fio_mutex_up(&ff->lock); if (!refs) { - flist_del(&ff->list); - __fio_mutex_remove(&ff->lock); - sfree(ff); + flist_del_init(&ff->list); + put_filelock(ff); } } else log_err("fio: file not found for unlocking\n"); - fio_mutex_up(filelock_lock); + fio_mutex_up(&fld->lock); } diff --git a/lib/axmap.c b/lib/axmap.c index 68096d8..164300f 100644 --- a/lib/axmap.c +++ b/lib/axmap.c @@ -22,7 +22,6 @@ #include "../arch/arch.h" #include "axmap.h" -#include "../smalloc.h" #include "../minmax.h" #if BITS_PER_LONG == 64 @@ -80,10 +79,10 @@ void axmap_free(struct axmap *axmap) return; for (i = 0; i < axmap->nr_levels; i++) - sfree(axmap->levels[i].map); + free(axmap->levels[i].map); - sfree(axmap->levels); - sfree(axmap); + free(axmap->levels); + free(axmap); } struct axmap *axmap_new(unsigned long nr_bits) @@ -91,7 +90,7 @@ struct axmap *axmap_new(unsigned long nr_bits) struct axmap *axmap; unsigned int i, levels; - axmap = smalloc(sizeof(*axmap)); + axmap = malloc(sizeof(*axmap)); if (!axmap) return NULL; @@ -103,7 +102,7 @@ struct axmap *axmap_new(unsigned long nr_bits) } axmap->nr_levels = levels; - axmap->levels = smalloc(axmap->nr_levels * sizeof(struct axmap_level)); + axmap->levels = malloc(axmap->nr_levels * sizeof(struct axmap_level)); axmap->nr_bits = nr_bits; for (i = 0; i < axmap->nr_levels; i++) { @@ -111,7 +110,7 @@ struct axmap *axmap_new(unsigned long nr_bits) al->level = i; al->map_size = (nr_bits + BLOCKS_PER_UNIT - 1) >> UNIT_SHIFT; - al->map = smalloc(al->map_size * sizeof(unsigned long)); + al->map = malloc(al->map_size * sizeof(unsigned long)); if (!al->map) goto err; @@ -123,9 +122,9 @@ struct axmap *axmap_new(unsigned long nr_bits) err: for (i = 0; i < axmap->nr_levels; i++) if (axmap->levels[i].map) - sfree(axmap->levels[i].map); + free(axmap->levels[i].map); - sfree(axmap->levels); + free(axmap->levels); return NULL; } diff --git a/smalloc.c b/smalloc.c index 1ba9353..67cb7cc 100644 --- a/smalloc.c +++ b/smalloc.c @@ -25,8 +25,8 @@ #define SMALLOC_BPI (sizeof(unsigned int) * 8) #define SMALLOC_BPL (SMALLOC_BPB * SMALLOC_BPI) -#define INITIAL_SIZE 8192*1024 /* new pool size */ -#define MAX_POOLS 128 /* maximum number of pools to setup */ +#define INITIAL_SIZE 16*1024*1024 /* new pool size */ +#define MAX_POOLS 1 /* maximum number of pools to setup */ #define SMALLOC_PRE_RED 0xdeadbeefU #define SMALLOC_POST_RED 0x5aa55aa5U -- To unsubscribe from this list: send the line "unsubscribe fio" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html