aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2011-01-04 18:54:17 +0100
committerArnd Bergmann <arnd@arndb.de>2011-01-04 18:54:17 +0100
commit0f6ead3914b5436785469e770a14fff753723f06 (patch)
tree42b2daea7753c15652f54523bd553d0356fdbb13
parentb0ec131ac68b16e35c7112c9ea686b608fb8983f (diff)
downloadflashbench-0f6ead3914b5436785469e770a14fff753723f06.tar.gz
flashbench: implement write opcodes in vm
This makes it possible to use three kinds of write operations, writing zero-, one- or somwhat random contents. Many media have different characteristics depending on the kind of content. Signed-off-by: Arnd Bergmann <arnd@arndb.de>
-rw-r--r--dev.c43
-rw-r--r--vm.c28
2 files changed, 55 insertions, 16 deletions
diff --git a/dev.c b/dev.c
index 6bd209d..c5c4088 100644
--- a/dev.c
+++ b/dev.c
@@ -19,6 +19,8 @@
#include "dev.h"
+#define MAX_BUFSIZE (64 * 1024 * 1024)
+
static inline long long time_to_ns(struct timespec *ts)
{
return ts->tv_sec * 1000 * 1000 * 1000 + ts->tv_nsec;
@@ -33,46 +35,49 @@ static long long get_ns(void)
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))
+ if (size > MAX_BUFSIZE)
return -ENOMEM;
do {
- ret = pread(dev->fd, readbuf, size, pos % dev->size);
+ ret = pread(dev->fd, dev->readbuf, size, pos % dev->size);
if (ret > 0) {
size -= ret;
pos += ret;
}
} while (ret > 0 || errno == -EAGAIN);
- if (ret)
- return -errno;
+ if (ret) {
+ fprintf(stderr, "fd %d buf %p size %ld pos %ld\n", dev->fd, dev->readbuf, size, pos % dev->size);
+ perror("time_read");
+ return 0;
+ }
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))
+ if (size > MAX_BUFSIZE)
return -ENOMEM;
do {
- ret = pwrite(dev->fd, writebuf, size, pos % dev->size);
+ ret = pwrite(dev->fd, dev->writebuf[which], size, pos % dev->size);
if (ret > 0) {
size -= ret;
pos += ret;
}
} while (ret > 0 || errno == -EAGAIN);
- if (ret)
- return -errno;
+ if (ret) {
+ perror("time_write");
+ return 0;
+ }
return get_ns() - now;
}
@@ -91,6 +96,7 @@ static void set_rtprio(void)
int setup_dev(struct device *dev, const char *filename)
{
+ int i, err;
set_rtprio();
dev->fd = open(filename, O_RDWR | O_DIRECT | O_SYNC | O_NOATIME);
@@ -105,8 +111,19 @@ int setup_dev(struct device *dev, const char *filename)
return -errno;
}
- return 0;
-}
-
+ err = posix_memalign(&dev->readbuf, 4096, MAX_BUFSIZE);
+ if (err) return -err;
+ err = posix_memalign(&dev->writebuf[WBUF_ZERO], 4096, MAX_BUFSIZE);
+ if (err) return -err;
+ err = posix_memalign(&dev->writebuf[WBUF_ONE], 4096, MAX_BUFSIZE);
+ if (err) return -err;
+ err = posix_memalign(&dev->writebuf[WBUF_RAND], 4096, MAX_BUFSIZE);
+ if (err) return -err;
+ memset(dev->writebuf[WBUF_ZERO], 0, MAX_BUFSIZE);
+ memset(dev->writebuf[WBUF_ONE], 0xff, MAX_BUFSIZE);
+ for (i = 0; i < MAX_BUFSIZE; i+=256)
+ memset(dev->writebuf[WBUF_RAND] + i, (i & 0xff), 256);
+ return 0;
+}
diff --git a/vm.c b/vm.c
index 36fb042..2bcf34c 100644
--- a/vm.c
+++ b/vm.c
@@ -168,6 +168,28 @@ static struct operation *do_read(struct operation *op, struct device *dev,
return op+1;
}
+static struct operation *do_write(struct operation *op, struct device *dev,
+ off_t off, off_t max, size_t len)
+{
+ enum writebuf writebuf;
+ switch (op->code) {
+ case O_WRITE_ZERO:
+ writebuf = WBUF_ZERO;
+ break;
+ case O_WRITE_ONE:
+ writebuf = WBUF_ONE;
+ break;
+ case O_WRITE_RAND:
+ writebuf = WBUF_RAND;
+ break;
+ default:
+ return NULL;
+ }
+ op->result.l = time_write(dev, off, len, writebuf);
+ op->r_type = R_NS;
+ return op+1;
+}
+
static struct operation *length_or_offs(struct operation *op, struct device *dev,
off_t off, off_t max, size_t len)
{
@@ -482,9 +504,9 @@ static struct operation *drop(struct operation *op, struct device *dev,
static struct syntax syntax[] = {
{ O_END, "END", nop, },
{ O_READ, "READ", do_read, },
- { O_WRITE_ZERO, "WRITE_ZERO", nop, },
- { O_WRITE_ONE, "WRITE_ONE", nop, },
- { O_WRITE_RAND, "WRITE_RAND", nop, },
+ { O_WRITE_ZERO, "WRITE_ZERO", do_write, },
+ { O_WRITE_ONE, "WRITE_ONE", do_write, },
+ { O_WRITE_RAND, "WRITE_RAND", do_write, },
{ O_ERASE, "ERASE", nop, },
{ O_LENGTH, "LENGTH", length_or_offs },
{ O_OFFSET, "OFFSET", length_or_offs, },