Home » OS » Linux » Linux O_DIRECTIO: what am I doing wrong?

Linux O_DIRECTIO: what am I doing wrong?

I’m trying to create a file using O_DIRECT (direct I/O) but am running into a problem.

If I run it as a normal user (me) I get error number 22 (invalid argument):

./dio
bytes_read= 4096
write failed: Invalid argument
bytes_read= 4096
write failed: Invalid argument
bytes_read= 4096
write failed: Invalid argument
bytes_read= 4096
write failed: Invalid argument
bytes_read= 4096
write failed: Invalid argument
bytes_read= 4096
write failed: Invalid argument
bytes_read= 4096
write failed: Invalid argument
bytes_read= 4096
write failed: Invalid argument
bytes_read= 4096
write failed: Invalid argument
bytes_read= 4096
write failed: Invalid argument
ls -l test.dat
-rw-r--r-- 1 jfroebe jfroebe 0 2007-05-10 15:22 test.dat

I understand that the data being written has to be aligned properly, which I believe I’m doing, but should it work when I run it as root?

sudo ./dio
Password:
bytes_read= 4096
bytes_written = 4096
bytes_read= 4096
bytes_written = 4096
bytes_read= 4096
bytes_written = 4096
bytes_read= 4096
bytes_written = 4096
bytes_read= 4096
bytes_written = 4096
bytes_read= 4096
bytes_written = 4096
bytes_read= 4096
bytes_written = 4096
bytes_read= 4096
bytes_written = 4096
bytes_read= 4096
bytes_written = 4096
bytes_read= 4096
bytes_written = 4096
ls -l test.dat
-rw-r--r-- 1 jfroebe jfroebe 40960 2007-05-10 15:18 test.dat

The program in question:


#include
#include
#include
#include
#include
#include

#include

#include
#include

#define _GNU_SOURCE
#define __USE_GNU

#include

int main(int argc, char **argv)
{
int test_fd;
int input_fd;
int bytes_read;
int bytes_written;
int nbytes;
int i;
int bufsize = getpagesize();
unsigned char buf[bufsize] __attribute__((aligned(4096))); // mem page size is 4096 bytes

input_fd = open(“/dev/zero”, O_RDONLY);
test_fd = open(“/home/jfroebe/build/test.dat”, O_CREAT|O_WRONLY|O_DIRECT, 0666);
//test_fd = open(“/home/jfroebe/build/test.dat”, O_CREAT|O_WRONLY|O_ASYNC, 0666);
//test_fd = open(“/home/jfroebe/build/test.dat”, O_CREAT|O_WRONLY|O_ASYNC|O_DIRECT, 0666);

if (test_fd < 0) { printf("couldn’t open/home/jfroebe/build/test.dat\n"); exit(1); } for (i=0; i < 10; i++) { bytes_read = read(input_fd, buf, bufsize); bytes_written = write(test_fd, buf, bufsize); printf("bytes_read= %d\n", bytes_read); if (errno == 0) { printf("bytes_written = %d\n", bytes_written); } else { fprintf(stderr, "write failed: %s\n", strerror(errno)); } } return 0; }[/c] UPDATE: Figured it out! I needed to allocate the memory with malloc() and do a little magic. FYI: the alignment is NOT necessary if and only if you are a superuser (root).


#include
#include
#include
#include
#include
#include

#include

#include
#include

#define _GNU_SOURCE
#define __USE_GNU

#define BUFFER_SIZE 1048576

#include

int main(int argc, char **argv)
{
int test_fd;
int input_fd;
int bytes_read;
int bytes_written;
int nbytes;
int i;
int pagesize = getpagesize();

char *realbuff = malloc(BUFFER_SIZE + pagesize);
char *alignedbuff = ((( (int unsigned)realbuff + pagesize – 1)/ pagesize) * pagesize);

input_fd = open(“/dev/zero”, O_RDONLY);
test_fd = open(“/home/jfroebe/build/test.dat”, O_CREAT|O_WRONLY|O_DIRECT, 0666);

if (test_fd < 0) { printf("couldn't open/home/jfroebe/build/test.dat\n"); exit(1); } for (i=0; i < 10; i++) { bytes_read = read(input_fd, alignedbuff, BUFFER_SIZE); bytes_written = write(test_fd, alignedbuff, BUFFER_SIZE); printf("bytes_read= %d\n", bytes_read); if (errno == 0) { printf("bytes_written = %d\n", bytes_written); } else { fprintf(stderr, "write failed (err %d): %s\n", errno, strerror(errno)); } } return 0; }[/c]

Share Button

Leave a Reply

Your email address will not be published. Required fields are marked *

*
*

Facebook login by WP-FB-AutoConnect