diff options
author | Arnd Bergmann <arnd@arndb.de> | 2011-01-04 16:52:47 +0100 |
---|---|---|
committer | Arnd Bergmann <arnd@arndb.de> | 2011-01-04 16:52:47 +0100 |
commit | c95ea1903edac9851a976a2bb0e35037b66020a5 (patch) | |
tree | 331e691135a6ff27d94ca83bd06ceb805ecb3cbb | |
parent | 5acb726787452d09e8fc562c563e4ec02e8f340c (diff) | |
download | flashbench-c95ea1903edac9851a976a2bb0e35037b66020a5.tar.gz |
flashbench: make code more modular
This makes it possible to call programs from
outside of vm.c, and moves all device access
to dev.c, as a step towards integrating the
flashbench front-end with the vm.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
-rw-r--r-- | Makefile | 4 | ||||
-rw-r--r-- | dev.c | 112 | ||||
-rw-r--r-- | dev.h | 25 | ||||
-rw-r--r-- | flashbench.c | 101 | ||||
-rw-r--r-- | vm.c | 91 | ||||
-rw-r--r-- | vm.h | 97 |
6 files changed, 243 insertions, 187 deletions
@@ -4,9 +4,9 @@ LDFLAGS := -lrt all: flashbench vm -flashbench: flashbench.c +flashbench: flashbench.o dev.o -vm: vm.c +vm: vm.o dev.o clean: rm flashbench vm @@ -0,0 +1,112 @@ +#define _GNU_SOURCE +#define _FILE_OFFSET_BITS 64 + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/time.h> +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <inttypes.h> +#include <time.h> +#include <errno.h> +#include <fcntl.h> +#include <limits.h> +#include <sched.h> +#include <string.h> +#include <getopt.h> +#include <stdbool.h> + +#include "dev.h" + +static inline long long time_to_ns(struct timespec *ts) +{ + return ts->tv_sec * 1000 * 1000 * 1000 + ts->tv_nsec; +} + +static long long get_ns(void) +{ + struct timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + return time_to_ns(&ts); +} + +long long time_read(struct device *dev, off_t pos, size_t size) +{ + static char readbuf[64 * 1024 * 1024] __attribute__((aligned(4096))); + long long now = get_ns(); + ssize_t ret; + + if (size > sizeof(readbuf)) + return -ENOMEM; + + do { + ret = pread(dev->fd, readbuf, size, pos % dev->size); + if (ret > 0) { + size -= ret; + pos += ret; + } + } while (ret > 0 || errno == -EAGAIN); + + if (ret) + return -errno; + + return get_ns() - now; +} + +long long time_write(struct device *dev, off_t pos, size_t size, enum writebuf which) +{ + static char writebuf[64 * 1024 * 1024] __attribute__((aligned(4096))); + long long now = get_ns(); + ssize_t ret; + + if (size > sizeof(writebuf)) + return -ENOMEM; + + do { + ret = pwrite(dev->fd, writebuf, size, pos % dev->size); + if (ret > 0) { + size -= ret; + pos += ret; + } + } while (ret > 0 || errno == -EAGAIN); + + if (ret) + return -errno; + + return get_ns() - now; +} + +static void set_rtprio(void) +{ + int ret; + struct sched_param p = { + .sched_priority = 10, + }; + ret = sched_setscheduler(0, SCHED_FIFO, &p); + if (ret) + perror("sched_setscheduler"); +} + + +int setup_dev(struct device *dev, const char *filename) +{ + set_rtprio(); + + dev->fd = open(filename, O_RDWR | O_DIRECT | O_SYNC | O_NOATIME); + if (dev->fd < 0) { + perror("open"); + return -errno; + } + + dev->size = lseek(dev->fd, 0, SEEK_END); + if (dev->size < 0) { + perror("seek"); + return -errno; + } + + return 0; +} + + + @@ -0,0 +1,25 @@ +#ifndef FLASHBENCH_DEV_H +#define FLASHBENCH_DEV_H + +#include <unistd.h> + +struct device { + void *readbuf; + void *writebuf[3]; + int fd; + ssize_t size; +}; + +enum writebuf { + WBUF_ZERO, + WBUF_ONE, + WBUF_RAND, +}; + +extern int setup_dev(struct device *dev, const char *filename); + +long long time_write(struct device *dev, off_t pos, size_t size, enum writebuf which); + +long long time_read(struct device *dev, off_t pos, size_t size); + +#endif /* FLASHBENCH_DEV_H */ diff --git a/flashbench.c b/flashbench.c index 26f39d7..7a9b6d9 100644 --- a/flashbench.c +++ b/flashbench.c @@ -8,35 +8,18 @@ #include <stdlib.h> #include <stdio.h> #include <inttypes.h> -#include <time.h> #include <errno.h> -#include <fcntl.h> #include <limits.h> -#include <sched.h> #include <string.h> #include <getopt.h> #include <stdbool.h> +#include "dev.h" + typedef long long ns_t; -struct device { - int fd; - ssize_t size; -}; #define returnif(x) do { typeof(x) __x = (x); if (__x < 0) return (__x); } while (0) -static inline ns_t time_to_ns(struct timespec *ts) -{ - return ts->tv_sec * 1000 * 1000 * 1000 + ts->tv_nsec; -} - -static ns_t get_ns(void) -{ - struct timespec ts; - clock_gettime(CLOCK_REALTIME, &ts); - return time_to_ns(&ts); -} - static ns_t ns_min(int count, ns_t data[]) { int i; @@ -134,54 +117,6 @@ static void regression(ns_t ns[], off_t bytes[], int count, ns_t *atime, float * *throughput = 1000.0 / slope; } -static ns_t time_read(struct device *dev, off_t pos, size_t size) -{ - static char readbuf[64 * 1024 * 1024] __attribute__((aligned(4096))); - ns_t now = get_ns(); - ssize_t ret; - - if (size > sizeof(readbuf)) - return -ENOMEM; - - do { - ret = pread(dev->fd, readbuf, size, pos % dev->size); - if (ret > 0) { - size -= ret; - pos += ret; - } - } while (ret > 0 || errno == -EAGAIN); - - if (ret) - return -errno; - - return get_ns() - now; -} - -#if 0 -static ns_t time_write(struct device *dev, off_t pos, size_t size) -{ - static char writebuf[64 * 1024 * 1024] __attribute__((aligned(4096))); - ns_t now = get_ns(); - ssize_t ret; - - if (size > sizeof(writebuf)) - return -ENOMEM; - - do { - ret = pwrite(dev->fd, writebuf, size, pos % dev->size); - if (ret > 0) { - size -= ret; - pos += ret; - } - } while (ret > 0 || errno == -EAGAIN); - - if (ret) - return -errno; - - return get_ns() - now; -} -#endif - static void flush_read_cache(struct device *dev) { off_t cache_size = 1024 * 1024; /* FIXME: use detected size */ @@ -476,17 +411,6 @@ static int try_read_alignments(struct device *dev, int tries, int blocksize) return 0; } -static void set_rtprio(void) -{ - int ret; - struct sched_param p = { - .sched_priority = 10, - }; - ret = sched_setscheduler(0, SCHED_FIFO, &p); - if (ret) - perror("sched_setscheduler"); -} - static void print_help(const char *name) { printf("%s [OPTION]... [DEVICE]\n", name); @@ -615,25 +539,6 @@ static int parse_arguments(int argc, char **argv, struct arguments *args) return 0; } -static int setup_dev(struct device *dev, struct arguments *args) -{ - set_rtprio(); - - dev->fd = open(args->dev, O_RDWR | O_DIRECT | O_SYNC | O_NOATIME); - if (dev->fd < 0) { - perror("open"); - return -errno; - } - - dev->size = lseek(dev->fd, 0, SEEK_END); - if (dev->size < 0) { - perror("seek"); - return -errno; - } - - return 0; -} - static FILE *open_output(const char *filename) { if (!filename || !strcmp(filename, "-")) @@ -651,7 +556,7 @@ int main(int argc, char **argv) returnif(parse_arguments(argc, argv, &args)); - returnif(setup_dev(&dev, &args)); + returnif(setup_dev(&dev, args.dev)); output = open_output(args.out); if (!output) { @@ -6,23 +6,7 @@ #include <sys/types.h> #include <stdlib.h> -struct device; - -typedef union result res_t; - -enum resulttype { - R_NONE, - R_ARRAY, - R_NS, - R_BYTE, - R_STRING, -}; - -union result { - res_t *_p; - long long l; - char s[8]; -} __attribute__((aligned(8))); +#include "vm.h" static inline res_t *res_ptr(res_t r) { @@ -41,72 +25,6 @@ static inline res_t to_res(res_t *_p, enum resulttype t) static const res_t res_null = { }; -struct operation { - enum opcode { - /* end of program marker */ - O_END = 0, - - /* basic operations */ - O_READ, - O_WRITE_ZERO, - O_WRITE_ONE, - O_WRITE_RAND, - O_ERASE, - - /* output */ - O_PRINT, - O_PRINTF, - O_FORMAT, - O_NEWLINE, - - /* group */ - O_SEQUENCE, - O_REPEAT, - - /* series */ - O_OFF_FIXED, - O_OFF_POW2, - O_OFF_LIN, - O_OFF_RAND, - O_LEN_POW2, - O_MAX_POW2, - O_MAX_LIN, - - /* reduce dimension */ - O_REDUCE, - - /* ignore result */ - O_DROP, - - /* end of list */ - O_MAX = O_DROP, - } code; - - /* number of indirect results, if any */ - unsigned int num; - - /* command code specific value */ - long long val; - - /* output string for O_PRINT */ - const char *string; - - /* aggregation of results from children */ - enum { - A_MINIMUM, - A_MAXIMUM, - A_AVERAGE, - A_TOTAL, - A_IGNORE, - } aggregate; - - /* dynamic result contents */ - res_t result; - unsigned int size_x; - unsigned int size_y; - enum resulttype r_type; -}; - struct syntax { enum opcode opcode; const char *name; @@ -122,11 +40,10 @@ struct syntax { }; static struct syntax syntax[]; -static int verbose = 0; -#define pr_debug(...) do { if (verbose) printf(__VA_ARGS__); } while(0) -#define return_err(...) do { printf(__VA_ARGS__); return NULL; } while(0) -static struct operation *call(struct operation *op, struct device *dev, +int verbose = 0; + +struct operation *call(struct operation *op, struct device *dev, off_t off, off_t max, size_t len) { struct operation *next; @@ -0,0 +1,97 @@ +#ifndef FLASHBENCH_VM_H +#define FLASHBENCH_VM_H + +#include <sys/types.h> + +typedef union result res_t; + +enum resulttype { + R_NONE, + R_ARRAY, + R_NS, + R_BYTE, + R_STRING, +}; + +union result { + res_t *_p; + long long l; + char s[8]; +} __attribute__((aligned(8))); + +struct device; + +struct operation { + enum opcode { + /* end of program marker */ + O_END = 0, + + /* basic operations */ + O_READ, + O_WRITE_ZERO, + O_WRITE_ONE, + O_WRITE_RAND, + O_ERASE, + + /* output */ + O_PRINT, + O_PRINTF, + O_FORMAT, + O_NEWLINE, + + /* group */ + O_SEQUENCE, + O_REPEAT, + + /* series */ + O_OFF_FIXED, + O_OFF_POW2, + O_OFF_LIN, + O_OFF_RAND, + O_LEN_POW2, + O_MAX_POW2, + O_MAX_LIN, + + /* reduce dimension */ + O_REDUCE, + + /* ignore result */ + O_DROP, + + /* end of list */ + O_MAX = O_DROP, + } code; + + /* number of indirect results, if any */ + unsigned int num; + + /* command code specific value */ + long long val; + + /* output string for O_PRINT */ + const char *string; + + /* aggregation of results from children */ + enum { + A_MINIMUM, + A_MAXIMUM, + A_AVERAGE, + A_TOTAL, + A_IGNORE, + } aggregate; + + /* dynamic result contents */ + res_t result; + unsigned int size_x; + unsigned int size_y; + enum resulttype r_type; +}; + +extern struct operation *call(struct operation *program, struct device *dev, + off_t off, off_t max, size_t len); + +extern int verbose; +#define pr_debug(...) do { if (verbose) printf(__VA_ARGS__); } while(0) +#define return_err(...) do { printf(__VA_ARGS__); return NULL; } while(0) + +#endif /* FLASHBENCH_VM_H */ |