Asynchronous I/O operation for VE (VE AIO) enables to develop VE programs which can do their own tasks during data transfer between VE and VH, and actual I/O.
Introduction
SX-Aurora TSUBASA provides VE AIO function that enables VE programs to do following:
- VE programs can request to read or write an ordinary file.
- VE programs can do their own tasks while data transfer between VE and VH, and actual I/O are done asynchronously.
The files must be opened without O_DIRECT flag. It cannot request to read or write an ordinary file opened with O_DIRECT flag. It cannot also request to read or write socket and pipe.
Prerequisite
To develop VE programs using VE AIO, please install libsysve-devel package, which has veaio.h header delcaring VE AIO API functions.
For example, execute the forllowing command as root.
# yum install libsysve-devel
If you execute a program using VE AIO only, no extra packages are required.
APIs of VE AIO
A VE program using VE AIO needs to include "veaio.h". In the header, the following API functions are declared.
Basic use of VE AIO read/write is following steps.
- Initialize VE AIO context.
- Start VE AIO read/write operation for VE AIO context.
- Do something with checking whether the VE AIO state is cpmpleted.
- If it is not completed after doing something, wait the completion of VE AIO operation.
- Release VE AIO context after VE AIO operation completes.
VE Code Using VE AIO
A simple program with VE AIO reading is following.
#include <stdio.h>
#include <stdint.h>
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <veaio.h>
#define BUF_SIZE (1024*1024)
ssize_t do_something_and_reading(int fd, uint64_t *rbuf,
size_t size) {
struct ve_aio_ctx *ctx;
int errnoval, ret, i;
ssize_t retval;
if (ctx == NULL) {
perror("ve_aio_init");
return -1;
}
if (ret == -1) {
perror("ve_aio_read");
retval = -1;
goto completed;
}
for (i = 0; i < 10; i++) {
if (ret == 0) {
goto completed;
} else if (ret == -1) {
perror("ve_aio_query");
retval = -1;
goto completed;
}
}
if (ret == -1) {
perror("ve_aio_wait");
retval = -1;
}
completed:
return retval;
}
int main (void) {
int i;
int fd;
int ret;
ssize_t retval;
uint64_t buf[BUF_SIZE];
uint64_t rbuf[BUF_SIZE];
fd = open("/tmp/test_file", O_RDWR|O_CREAT, S_IRWXU);
if (fd == -1) {
perror("open");
exit(1);
}
ret = ftruncate(fd, BUF_SIZE);
if (ret == -1) {
perror("ftruncate");
exit(1);
}
for (i = 0; i < BUF_SIZE/8; i++)
buf[i] = i;
ret = pwrite(fd, buf, BUF_SIZE, 0);
if (ret == -1) {
perror("pwrite");
exit(1);
}
retval = do_something_and_reading(fd, rbuf, BUF_SIZE);
if (retval != BUF_SIZE) {
fprintf(stderr, "do_something_and_reading fails: retval=%zd\n",
retval);
goto err;
}
for (i = 0; i < BUF_SIZE / 8; i++) {
if (buf[i] != rbuf[i]) {
fprintf(stderr, "diff buf[%d] = %lx, rbuf[%d] = %lx\n",
i, buf[i], i, rbuf[i]);
goto err;
}
}
printf("OK\n");
err:
close(fd);
return 0;
}
Compile and execute the VE program
Save the above code as simple_aio.c and compile it on VE side as shown below.
$ /opt/nec/ve/bin/ncc -o simple_aio simple_aio.c -lveio -pthread
Please note the VE AIO API functions are in libveio library. So, "-lveio -pthread" option is required.
Execute compiled VE program.