From 2f9ade3cb72218eb260f4f5e6914218bdcaa2bcc Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 20 Oct 2006 11:25:52 +0200 Subject: [PATCH] [PATCH] Split out the memory handling from fio.c In the process also fix some bugs in the memory pinning. Signed-off-by: Jens Axboe --- Makefile | 4 ++- fio.c | 96 +++++-------------------------------------------- fio.h | 8 +++++ memory.c | 108 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 127 insertions(+), 89 deletions(-) create mode 100644 memory.c diff --git a/Makefile b/Makefile index a3e215e2..111d5cd4 100644 --- a/Makefile +++ b/Makefile @@ -2,6 +2,8 @@ CC = gcc CFLAGS = -W -Wall -O2 -g -D_GNU_SOURCE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 PROGS = fio SCRIPTS = fio_generate_plots +OBJS = fio.o ioengines.o init.o stat.o log.o time.o md5.o crc32.o \ + filesetup.o eta.o verify.o memory.o INSTALL = install prefix = /usr/local @@ -15,7 +17,7 @@ CFLAGS += '-D_INST_PREFIX="$(FIO_INST_DIR)"' all: depend $(PROGS) $(SCRIPTS) $(MAKE) -C engines -fio: fio.o ioengines.o init.o stat.o log.o time.o md5.o crc32.o filesetup.o eta.o verify.o +fio: $(OBJS) $(CC) $(CFLAGS) -o $@ $(filter %.o,$^) -lpthread -lm -ldl clean: diff --git a/fio.c b/fio.c index 624c9598..8d2a8e5f 100644 --- a/fio.c +++ b/fio.c @@ -45,8 +45,6 @@ int shm_id = 0; int temp_stall_ts; char *fio_inst_prefix = _INST_PREFIX; -extern unsigned long long mlock_size; - #define should_fsync(td) ((td_write(td) || td_rw(td)) && (!(td)->odirect || (td)->override_sync)) static volatile int startup_sem; @@ -237,8 +235,6 @@ static int check_min_rate(struct thread_data *td, struct timeval *now) rate = (td->this_io_bytes[ddir] - td->rate_bytes) / spent; if (rate < td->ratemin) { fprintf(f_out, "%s: min rate %d not met, got %ldKiB/sec\n", td->name, td->ratemin, rate); - if (rate_quit) - terminate_threads(td->groupid); return 1; } } @@ -753,6 +749,8 @@ static void do_io(struct thread_data *td) rate_throttle(td, usec, icd.bytes_done[td->ddir]); if (check_min_rate(td, &e)) { + if (rate_quit) + terminate_threads(td->groupid); td_verror(td, ENOMEM); break; } @@ -800,19 +798,7 @@ static void cleanup_io_u(struct thread_data *td) free(io_u); } - if (td->mem_type == MEM_MALLOC) - free(td->orig_buffer); - else if (td->mem_type == MEM_SHM) { - struct shmid_ds sbuf; - - shmdt(td->orig_buffer); - shmctl(td->shm_id, IPC_RMID, &sbuf); - } else if (td->mem_type == MEM_MMAP) - munmap(td->orig_buffer, td->orig_buffer_size); - else - log_err("Bad memory type %d\n", td->mem_type); - - td->orig_buffer = NULL; + free_io_mem(td); } static int init_io_u(struct thread_data *td) @@ -831,32 +817,8 @@ static int init_io_u(struct thread_data *td) td->orig_buffer_size = td->max_bs * max_units + MASK; - if (td->mem_type == MEM_MALLOC) - td->orig_buffer = malloc(td->orig_buffer_size); - else if (td->mem_type == MEM_SHM) { - td->shm_id = shmget(IPC_PRIVATE, td->orig_buffer_size, IPC_CREAT | 0600); - if (td->shm_id < 0) { - td_verror(td, errno); - perror("shmget"); - return 1; - } - - td->orig_buffer = shmat(td->shm_id, NULL, 0); - if (td->orig_buffer == (void *) -1) { - td_verror(td, errno); - perror("shmat"); - td->orig_buffer = NULL; - return 1; - } - } else if (td->mem_type == MEM_MMAP) { - td->orig_buffer = mmap(NULL, td->orig_buffer_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | OS_MAP_ANON, 0, 0); - if (td->orig_buffer == MAP_FAILED) { - td_verror(td, errno); - perror("mmap"); - td->orig_buffer = NULL; - return 1; - } - } + if (allocate_io_mem(td)) + return 1; p = ALIGN(td->orig_buffer); for (i = 0; i < max_units; i++) { @@ -1126,48 +1088,6 @@ static void reap_threads(int *nr_running, int *t_rate, int *m_rate) terminate_threads(TERMINATE_ALL); } -static void fio_unpin_memory(void *pinned) -{ - if (pinned) { - if (munlock(pinned, mlock_size) < 0) - perror("munlock"); - munmap(pinned, mlock_size); - } -} - -static void *fio_pin_memory(void) -{ - unsigned long long phys_mem; - void *ptr; - - if (!mlock_size) - return NULL; - - /* - * Don't allow mlock of more than real_mem-128MB - */ - phys_mem = os_phys_mem(); - if (phys_mem) { - if ((mlock_size + 128 * 1024 * 1024) > phys_mem) { - mlock_size = phys_mem - 128 * 1024 * 1024; - fprintf(f_out, "fio: limiting mlocked memory to %lluMiB\n", mlock_size >> 20); - } - } - - ptr = mmap(NULL, mlock_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | OS_MAP_ANON, 0, 0); - if (!ptr) { - perror("malloc locked mem"); - return NULL; - } - if (mlock(ptr, mlock_size) < 0) { - munmap(ptr, mlock_size); - perror("mlock"); - return NULL; - } - - return ptr; -} - /* * Main function for kicking off and reaping jobs, as needed. */ @@ -1176,9 +1096,9 @@ static void run_threads(void) struct thread_data *td; unsigned long spent; int i, todo, nr_running, m_rate, t_rate, nr_started; - void *mlocked_mem; - mlocked_mem = fio_pin_memory(); + if (fio_pin_memory()) + return; if (!terse_output) { printf("Starting %d thread%s\n", thread_number, thread_number > 1 ? "s" : ""); @@ -1336,7 +1256,7 @@ static void run_threads(void) } update_io_ticks(); - fio_unpin_memory(mlocked_mem); + fio_unpin_memory(); } int main(int argc, char *argv[]) diff --git a/fio.h b/fio.h index 4af6a743..b9ae15bf 100644 --- a/fio.h +++ b/fio.h @@ -479,6 +479,14 @@ extern void populate_verify_io_u(struct thread_data *, struct io_u *); extern int get_next_verify(struct thread_data *td, struct io_u *); extern int do_io_u_verify(struct thread_data *, struct io_u **); +/* + * Memory helpers + */ +extern int fio_pin_memory(void); +extern void fio_unpin_memory(void); +extern int allocate_io_mem(struct thread_data *); +extern void free_io_mem(struct thread_data *); + /* * This is a pretty crappy semaphore implementation, but with the use that fio * has (just signalling start/go conditions), it doesn't have to be better. diff --git a/memory.c b/memory.c new file mode 100644 index 00000000..d8924a85 --- /dev/null +++ b/memory.c @@ -0,0 +1,108 @@ +/* + * Memory helpers + */ +#include +#include +#include + +#include "fio.h" +#include "os.h" + +extern unsigned long long mlock_size; +static void *pinned_mem; + +void fio_unpin_memory(void) +{ + if (pinned_mem) { + if (munlock(pinned_mem, mlock_size) < 0) + perror("munlock"); + munmap(pinned_mem, mlock_size); + pinned_mem = NULL; + } +} + +int fio_pin_memory(void) +{ + unsigned long long phys_mem; + + if (!mlock_size) + return 0; + + /* + * Don't allow mlock of more than real_mem-128MB + */ + phys_mem = os_phys_mem(); + if (phys_mem) { + if ((mlock_size + 128 * 1024 * 1024) > phys_mem) { + mlock_size = phys_mem - 128 * 1024 * 1024; + fprintf(f_out, "fio: limiting mlocked memory to %lluMiB\n", mlock_size >> 20); + } + } + + pinned_mem = mmap(NULL, mlock_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | OS_MAP_ANON, 0, 0); + if (pinned_mem == MAP_FAILED) { + perror("malloc locked mem"); + pinned_mem = NULL; + return 1; + } + if (mlock(pinned_mem, mlock_size) < 0) { + perror("mlock"); + munmap(pinned_mem, mlock_size); + pinned_mem = NULL; + return 1; + } + + return 0; +} + +/* + * Setup the buffer area we need for io. + */ +int allocate_io_mem(struct thread_data *td) +{ + if (td->mem_type == MEM_MALLOC) + td->orig_buffer = malloc(td->orig_buffer_size); + else if (td->mem_type == MEM_SHM) { + td->shm_id = shmget(IPC_PRIVATE, td->orig_buffer_size, IPC_CREAT | 0600); + if (td->shm_id < 0) { + td_verror(td, errno); + perror("shmget"); + return 1; + } + + td->orig_buffer = shmat(td->shm_id, NULL, 0); + if (td->orig_buffer == (void *) -1) { + td_verror(td, errno); + perror("shmat"); + td->orig_buffer = NULL; + return 1; + } + } else if (td->mem_type == MEM_MMAP) { + td->orig_buffer = mmap(NULL, td->orig_buffer_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | OS_MAP_ANON, 0, 0); + if (td->orig_buffer == MAP_FAILED) { + td_verror(td, errno); + perror("mmap"); + td->orig_buffer = NULL; + return 1; + } + } + + return 0; +} + +void free_io_mem(struct thread_data *td) +{ + if (td->mem_type == MEM_MALLOC) + free(td->orig_buffer); + else if (td->mem_type == MEM_SHM) { + struct shmid_ds sbuf; + + shmdt(td->orig_buffer); + shmctl(td->shm_id, IPC_RMID, &sbuf); + } else if (td->mem_type == MEM_MMAP) + munmap(td->orig_buffer, td->orig_buffer_size); + else + log_err("Bad memory type %d\n", td->mem_type); + + td->orig_buffer = NULL; +} -- 2.25.1