Search code examples
clinuxio

What does "O_DIRECT 512-byte aligned" mean?


O_DIRECT mode introduces further requirements of all read and write operations to have their file offset, memory buffer and size be aligned to 512 bytes.

What deos this exactly mean?

For example,

struct iocb cb;
char data[4096];
cb.aio_buf = (uint64_t)data;
cb.aio_offset = 512;
cb.aio_nbytes = 4096;

Does this mean the data size should be 512*n ? and the offset should be 512 * n?

I changed 4096 to 7777 and offset to 333, and it seems working fine.


Solution

  • Offset, buffer address, size must be aligned 512 bytes, otherwise it will report Invalid argument (errno=-22)

    Below are test cases

    #define _GNU_SOURCE
    #include <stdio.h>
    #include <unistd.h>
    #include <string.h>
    #include <fcntl.h>
    #include <stdint.h>
    #include <errno.h>
    #include <linux/aio_abi.h>
    #include <syscall.h>
    
    #define align(p, a) (((long)(p) + (a - 1)) & ~(a - 1))
    
    static inline int io_setup(unsigned nr_events, aio_context_t *ctx_idp)
    {
        return syscall(__NR_io_setup, nr_events, ctx_idp);
    }
    
    static inline int io_destroy(aio_context_t ctx)
    {
        return syscall(__NR_io_destroy, ctx);
    }
    
    static inline int io_submit(aio_context_t ctx, long nr, struct iocb **iocbpp)
    {
        return syscall(__NR_io_submit, ctx, nr, iocbpp);
    }
    
    static inline int io_getevents(aio_context_t ctx, long min_nr, long nr,
                                   struct io_event *events, struct timespec *timeout)
    {
        return syscall(__NR_io_getevents, ctx, min_nr, nr, events, timeout);
    }
    
    
    int main(int argc, char *argv[])
    {
        int fd, rc;
        char data[8192];
    
        aio_context_t ctx = 0;
        struct io_event events;
        struct iocb cb;
        struct iocb *cblist[] = {&cb};
    
        fd = open("a.txt", O_CREAT | O_RDWR | O_DIRECT, 0666);
    
        if (fd < 0)
            return -1;
    
        rc = io_setup(1, &ctx);
        memset(&cb, 0, sizeof(cb));
        cb.aio_buf = align(data, 512);
        cb.aio_offset = 512;
        cb.aio_nbytes = 4096;
        cb.aio_fildes = fd;
        cb.aio_lio_opcode = IOCB_CMD_PWRITE;
    
        rc = io_submit(ctx, 1, cblist);
    
        if (rc < 0) {
            printf("io_submit: error=%d\n", rc);
            goto error_exit;
        }
    
        rc = io_getevents(ctx, 1, 1, &events, NULL);
    
        if (rc != 1) {
            fprintf(stderr, "io_getevents failed: %s.\n", strerror(errno));
            goto error_exit;
        }
    
        if (events.res < 0)
            printf("write error: %s (%lld)\n", strerror(-events.res), events.res);
        else
            printf("write result: %lld\n", events.res);
    
        rc = io_destroy(ctx);
    
    error_exit:
        close(fd);
        return 0;
    }