Различные результаты при работе внутри контейнера докеров

Я пытаюсь запустить некоторый код на основе этого примера libaio: https://oxnz.github.io/2016/10/13/linux-aio/#example-1

Я добавил флаг O_DIRECT в соответствии с документацией libaio. Кажется, он работает на моем настольном компьютере с Ubuntu 16.04 (привет записывается в /tmp/test).

Однако, когда я компилирую и запускаю один и тот же образец внутри контейнера докеров, в файл ничего не записывается. при запуске внутри gdb я вижу, что событие читается io_getevents и результат устанавливается равным -22 (EINVAL).

Любые идеи?

Это мой модифицированный код

#define _GNU_SOURCE

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <err.h>
#include <errno.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <libaio.h>

int main() {
    io_context_t ctx;
    struct iocb iocb;
    struct iocb * iocbs[1];
    struct io_event events[1];
    struct timespec timeout;
    int fd;

    fd = open("/tmp/test", O_WRONLY | O_CREAT | O_DIRECT) ;
    if (fd < 0) err(1, "open");

    memset(&ctx, 0, sizeof(ctx));
    if (io_setup(10, &ctx) != 0) err(1, "io_setup");

    const char *msg = "hello";
    io_prep_pwrite(&iocb, fd, (void *)msg, strlen(msg), 0);
    iocb.data = (void *)msg;

    iocbs[0] = &iocb;

    if (io_submit(ctx, 1, iocbs) != 1) {
        io_destroy(ctx);
        err(1, "io_submit");
    }

    while (1) {
        timeout.tv_sec = 0;
        timeout.tv_nsec = 500000000;
    int ret = io_getevents(ctx, 0, 1, events, &timeout);
        printf("ret=%d\n", ret);
    if (ret == 1) {
            close(fd);
            break;
        }
        printf("not done yet\n");
        sleep(1);
    }
    io_destroy(ctx);

    return 0;
}

person barisdad    schedule 05.07.2018    source источник
comment
Запуск программы внутри контейнера докеров напишет hello /tmp/test в пространстве имен MNT контейнера, а не хосту. Какие /tmp/test вы проверили?   -  person Joy Allen    schedule 06.07.2018
comment
Я проверил правильный. Файл существует, но он пустой.   -  person barisdad    schedule 06.07.2018
comment
Это может привести к сбою из-за дополнительных уровней устройства отображения между контейнером и хостом, налагающих более жесткие ограничения. Одна вещь, которую нужно исправить: для использования прямого ввода-вывода и ваш указатель памяти, и длина записываемого сообщения должны быть выровнены с размером блока базового устройства, который, вероятно, составляет либо 512 байт, либо 4096. Проще всего предположить. 4096 байт. Используйте posix_memalign, чтобы выделить память для сообщения, и запишите длину, кратную 4096 байтам. Если эта программа работала на хосте, она возвращалась к непрямому вводу-выводу.   -  person Mike Andrews    schedule 06.07.2018


Ответы (1)


Файловая система внутри контейнера, вероятно, будет отличаться от файловой системы хоста (в современных установках это может быть overlayfs, но в более старых системах это может быть aufs). Чтобы O_DIRECT работало в открытом режиме, устройство/файловая система должны как минимум "поддерживать" его (обратите внимание на пугающие кавычки), а файловая система вашего контейнера, скорее всего, этого не делает.

person Anon    schedule 12.01.2019