Write error: Invalid argument, when file is opened with O_DIRECT

房东的猫 提交于 2020-06-18 08:32:29

问题


it is very important to me to write to a file with the O_DIRECT flag.

This is how I open the file:

//Open the file
int fd;
if((fd = open(inFilepath, O_WRONLY | O_CREAT |O_SYNC |O_DIRECT,S_IRUSR|S_IWUSR))<0) {
    //Error handling
    return;
}

I know about O_DIRECT's alignment restrictions. This is why I initialize my buffer with calloc:

char *buff = (char *) calloc((size_t) 1,sizeof(char));

if(write(fd,buff,(size_t)1)<1) {
    //Error logging
    free(buff);
    return -1;
}

And I get the write: Invalid argument error. I even tried to use more extreme measures such as memalign and posix_memalign, but had issues with them (memalign got stuck, and posix_memalign is missing for the ARM processor).

When I comment out the O_DIRECT flag, everything works as it should (but I/O is not direct, which is what I need).

Anyone has any insight as to why this is happening? If O_DIRECT was not implemented in Android, then it should've failed at open(), not at write(); so I must be doing something wrong!

Thanks -LD


回答1:


I solved it (with your guidance)- and wanted to post my solution in case anyone in the future has similar problems.

The trick was that with the O_DIRECT flag you need to align both the memory address and your buffer to the filesystem's block size (or at least, block size worked for me; sector didn't).

struct stat fstat;
stat(filepath, &fstat); 
int blksize = (int)fstat.st_blksize;
int align = blksize-1;

const char *buff = (char *) malloc((int)blksize+align);
buff = (char *)(((uintptr_t)buff+align)&~((uintptr_t)align));

if(write(fd,buff,(size_t)blksize)<1) { 
        //Error handling
        free((char *)buff);
        return -1;
}

I did two main things:

  1. Found the filesystem hosting my file's block size using stat() and accessing the st_blksize attribute.
  2. Allocated align more bytes than I need. I then added those extra align bytes to the pointer address so that masking off the bits to the lower block size alignment wouldn't leave me with less memory allocated than I wanted. Then of course you AND the bits with the mask (created by flipping the bits of align which is blksize-1), and voila- your buffer is blksize-aligned.

Also note that the amount you write also has to be aligned to block size (at least in my case).

-LD




回答2:


Calloc will not align the memory good enough in this case. Allocate more memory than you need, and round it up to the next 4k or so page. Also read the notes below in the manpage for open() with O_DIRECT.



来源:https://stackoverflow.com/questions/34182535/write-error-invalid-argument-when-file-is-opened-with-o-direct

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!