Created
December 24, 2013 13:31
-
-
Save adolgarev/8113387 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define _XOPEN_SOURCE 600 | |
#define _GNU_SOURCE | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <unistd.h> | |
#include <inttypes.h> | |
#include <fcntl.h> | |
#include <errno.h> | |
#include <libaio.h> | |
#include <sys/ioctl.h> | |
#include <linux/fs.h> | |
#include <time.h> | |
#include "log.h" | |
#define EVENTS_DEV 100 | |
typedef struct dev_s_ { | |
uint64_t dev_siz; | |
int fd; | |
} dev_s; | |
static uint64_t blk_get_size(const char *file); | |
static int io_submit_one(dev_s *devp, io_context_t ioctx, void *buffer, long sz, size_t len); | |
//------------------------------------------------------------------- | |
int main(int argc, const char* argv[]) { | |
int ret = 0; | |
int nr = (argc - 1) * EVENTS_DEV; | |
dev_s devs[argc-1]; | |
dev_s *devp; | |
int i; | |
void *buffer = NULL; | |
size_t len; | |
struct io_event events[nr]; | |
long sz; | |
if (argc < 2) { | |
log_err("./prog dev1 dev2..."); | |
goto err_end; | |
} | |
srand(time(NULL)); | |
{ | |
sz = sysconf(_SC_PAGESIZE); | |
len = sz * 1; | |
ret = posix_memalign(&buffer, sz, len); | |
switch (ret) { | |
case EINVAL: | |
log_err("posix_memalign: The alignment argument was not a power of two, or was not a multiple of sizeof(void *)."); | |
goto err_end; | |
case ENOMEM: | |
log_err("posix_memalign: There was insufficient memory to fulfill the allocation request."); | |
goto err_end; | |
case 0: | |
break; | |
default: | |
log_err("posix_memalign"); | |
goto err_end; | |
} | |
} | |
io_context_t ioctx; | |
memset(&ioctx, 0, sizeof(ioctx)); | |
if (io_setup(nr, &ioctx)) { | |
log_err("io_setup"); | |
goto err_end; | |
} | |
for (devp = devs; devp < devs + argc-1; devp++) { | |
const char *name = argv[devp - devs + 1]; | |
if ((devp->fd = open(name, O_RDWR | O_DIRECT | O_SYNC | O_LARGEFILE)) == -1) { | |
log_syserr("open %s", name); | |
goto err_end; | |
} | |
log_debug("opened %s", name); | |
if ((devp->dev_siz = blk_get_size(name)) == -1) | |
goto err_end; | |
for (i = 0; i < EVENTS_DEV; i++) { | |
if (io_submit_one(devp, ioctx, buffer, sz, len)) | |
goto err_end; | |
} | |
} | |
for (i = 0; i < 1000000; ) { | |
int num; | |
struct io_event *ep; | |
if ((num = io_getevents(ioctx, 1, nr, events, NULL)) < 1) { | |
log_err("io_getevents"); | |
goto err_end; | |
} | |
for (ep = events; ep < events + num; ep++) { | |
if (ep->res < len) | |
log_err("res is only %ld bytes instead of %lu", ep->res, len); | |
if (io_submit_one(ep->data, ioctx, buffer, sz, len)) | |
goto err_end; | |
} | |
i += num; | |
} | |
for (devp = devs; devp < devs + argc-1; devp++) | |
close(devp->fd); | |
io_destroy(ioctx); | |
free(buffer); | |
return 0; | |
err_end: | |
io_destroy(ioctx); | |
free(buffer); | |
return 1; | |
} | |
//------------------------------------------------------------------- | |
uint64_t blk_get_size(const char *file) { | |
int d = -1; | |
uint64_t oct = 0LL; | |
if ((d = open(file, O_RDONLY)) == -1) { | |
log_syserr("open"); | |
goto err_end; | |
} | |
if (ioctl(d, BLKGETSIZE64, &oct)) { | |
log_syserr("ioctl"); | |
goto err_end; | |
} | |
return oct; | |
err_end: | |
if (d != -1) | |
close(d); | |
return -1; | |
} | |
//------------------------------------------------------------------- | |
int io_submit_one(dev_s *devp, io_context_t ioctx, void *buffer, long sz, size_t len) { | |
int ret; | |
struct iocb iocb; | |
struct iocb* iocbs = &iocb; | |
long long int off; | |
off = (rand() % devp->dev_siz) / sz * sz; | |
if (rand() % 100 < 50) | |
io_prep_pread(&iocb, devp->fd, buffer, len, off); | |
else | |
io_prep_pwrite(&iocb, devp->fd, buffer, len, off); | |
iocb.data = devp; | |
ret = io_submit(ioctx, 1, &iocbs); | |
switch (ret) { | |
case -EAGAIN: | |
log_err("io_submit: EAGAIN"); | |
break; | |
case -EBADF: | |
log_err("io_submit: EBADF"); | |
break; | |
case -EFAULT: | |
log_err("io_submit: EFAULT"); | |
break; | |
case -EINVAL: | |
log_err("io_submit: EINVAL"); | |
break; | |
case -ENOSYS: | |
log_err("io_submit: ENOSYS"); | |
break; | |
default: | |
if (ret < 0) | |
log_err("io_submit"); | |
break; | |
} | |
if (ret != 1) | |
goto err_end; | |
return 0; | |
err_end: | |
return 1; | |
} | |
//------------------------------------------------------------------- |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment