Обнаружение конца ленты (ENOSPC )в многотомном режиме tar -с конвейерами для шифрования

Мне удалось решить эту проблему, выгрузив/занеся в черный список модуль ядра i2c _hid . Я не заметил потери функциональности после того, как (клавиатура и тачпад все еще работают ).

Я обнаружил, что патч совсем недавно был добавлен в ядро, которое отключает эти сообщения ядра. Я протестировал его, но обнаружил, что, хотя он и исправляет сообщения, по-прежнему наблюдается высокая загрузка ЦП (около 25% одного ядра )из-за постоянного срабатывания прерывания. Выгрузка модуля ядра остановила это.

3
06.10.2020, 02:34
2 ответа

Невозможно передать ошибки записи обратно через конвейер

И даже если бы это было возможно с помощью какого-то хака, каналы буферизируются и к тому времени, когда считыватель каналов попытается "сигнализировать" писателю каналов, последний мог уже записать данные который вызывает ошибку в дальнейшем, уже получил успешный статус (> 0 )и соответственно обновил свое состояние. Чтобы это сработало, процесс написания должен был вернуться в прошлое. Вдобавок ко всему, сам считыватель каналов может выполнять свою собственную буферизацию и сохранение состояния, что может привести к рассинхронизации.

Единственный выход tarсостоит в том, чтобы вызывать процедуры шифрования напрямую, вместо передачи данных по какому-либо каналу. Вместо того, чтобы изменять исходный код и перекомпилировать его, это можно было бы сделать, исправив его с помощью LD_PRELOADхака, который переопределяет write()библиотечную функцию и обрабатывает данные перед передачей их оригиналу write().

Как имитировать ENOSPCс помощью LD_PRELOADхака

Это приведет к сбою записи в fd 1 (stdout )с ENOSPC, как только он попытается записать в него более 40960 байт, после чего он сбрасывает счетчик и снова завершается успешно и т. д.

Если вы хотите, чтобы он работал с tar -cf filename,вместо tar -cf -вам, вероятно, следует изменить тест fd == 1на fd != 2.

$ cat <<'EOT' >enospc.c
#define _GNU_SOURCE
#include <unistd.h>
#include <dlfcn.h>
#include <err.h>
#include <errno.h>

#define MAX     40960

ssize_t write(int fd, const void *b, size_t z){
        ssize_t w;
        static typeof (write) *o_write;
        static size_t count;
        if(!o_write) o_write = dlsym(RTLD_NEXT, "write");
        if(fd == 1 && count + z > MAX){
                count = 0;
                errno = ENOSPC;
                return -1;
        }
        w = o_write(fd, b, z);
        if(w > 0) count += w;
        return w;
}
EOT

$ cc -Wall -shared enospc.c -o enospc.so -ldl

$ seq -f 'n foo%04g.tar' 1 10000 |
  LD_PRELOAD=./enospc.so tar -M -cf- /etc/X11 > foo0000.tar
tar: Removing leading `/' from member names
Prepare volume #2 for ‘-’ and hit return: Prepare volume #3 for ‘/tmp/foo0001.tar’ and hit return: Prepare volume #4 for ‘/tmp/foo0002.tar’ and hit return: Prepare volume #5 for ‘/tmp/foo0003.tar’ and hit return: Prepare volume #6 for ‘/tmp/foo0004.tar’ and hit return: Prepare volume #7 for ‘/tmp/foo0005.tar’ and hit return: Prepare volume #8 for ‘/tmp/foo0006.tar’ and hit return: Prepare volume #9 for ‘/tmp/foo0007.tar’ and hit return: $

$ ls foo000*
foo0000.tar  foo0002.tar  foo0004.tar  foo0006.tar  foo0008.tar
foo0001.tar  foo0003.tar  foo0005.tar  foo0007.tar
2
18.03.2021, 22:59

В вашем вопросе есть несколько проблем:

  • Правильный способ обнаружения ситуации с концом ленты — проверка записи (2 ), которая возвращает 0 без установки ошибки errno. Таким образом, правильная реализация tar, которая поддерживает многотомные ленточные архивы, проверяет запись (2 ), чтобы вернуть 0.

  • errno ENOSPC создается только при записи в обычный файл в файловой системе, поэтому этот errno не подходит для использования в качестве основы для многотомных -ленточных архивов.

  • Невозможно передать ошибку записи обратно через канал.

  • Команда tar UNIX не поддерживает многотомные -архивы томов

    .
  • gtar поддерживает запись многотомных -архивов, но не может их корректно прочитать с вероятностью прибл. 5%, потому что он не всегда может распознать последующий архив как правильный номер тома по порядку. Это вызвано конструктивным недостатком gtar, который нельзя исправить, не введя новый несовместимый многотомный формат -.

  • star пытается заблокировать память FIFO только в том случае, если она вызывается как root. Код ошибки, который он пишет в цитируемом вами сообщении, означает :не sueruser (root ). Вы запускаете этот звездный экземпляр в среде, где «root» имеет ограниченные права?

  • star не запускает программу сжатия, если вывод не является простым файлом, потому что вывод программы сжатия не блокируется, но блокировка вывода требуется для реализаций tar. Если вам нравится сжимать в таком случае, вызовите что-то вроде:star -c... | compress...

В общем, если вы действительно хотите зашифровать вывод программы tar, вам нужно будет направить вывод программы шифрования через программу, которая управляет многотомным выводом на ленту -.

Кстати, :не стесняйтесь присылать дополнительную информацию, чтобы получить более подробный ответ.

2
18.03.2021, 22:59

Теги

Похожие вопросы