статистика файлов /sys

статистика файлов /sys

У меня есть скрипт bash, который используется rsyncдля резервного копирования файлов в Archlinux. Я заметил, что rsyncне удалось скопировать файл из /sys, хотя cpработало просто отлично:

# rsync /sys/class/net/enp3s1/address /tmp    
rsync: read errors mapping "/sys/class/net/enp3s1/address": No data available (61)
rsync: read errors mapping "/sys/class/net/enp3s1/address": No data available (61)
ERROR: address failed verification -- update discarded.
rsync error: some files/attrs were not transferred (see previous errors) (code 23) at main.c(1052) [sender=3.0.9]

# cp  /sys/class/net/enp3s1/address /tmp   ## this works

Интересно, почему происходит rsyncсбой, и можно ли скопировать файл с его помощью?

решение1

Во-первых /sys, этопсевдофайловая система. Если вы посмотрите, /proc/filesystemsто найдете список зарегистрированных файловых систем, где довольно много есть nodev впереди. Это указывает на то, что онипсевдофайловые системы. Это означает, что они существуют на работающем ядре как файловая система на базе ОЗУ. Кроме того, им не требуется блочное устройство.

$ cat /proc/filesystems
nodev   sysfs
nodev   rootfs
nodev   bdev
...

При загрузке ядро ​​монтирует эту систему и обновляет записи, когда это необходимо. Например, когда во время загрузки обнаруживается новое оборудование или udev.

Обычно /etc/mtabкрепление можно найти по:

sysfs /sys sysfs rw,noexec,nosuid,nodev 0 0

Для хорошей статьи по теме прочитайте Патрик Мохел – Файловая система sysfs.


статистика файлов /sys

Если вы зайдете в каталог /sysи сделаете , ls -lто заметите, что все файлы имеют один размер. Обычно 4096 байт. Об этом сообщает sysfs.

:/sys/devices/pci0000:00/0000:00:19.0/net/eth2$ ls -l
-r--r--r-- 1 root root 4096 Apr 24 20:09 addr_assign_type
-r--r--r-- 1 root root 4096 Apr 24 20:09 address
-r--r--r-- 1 root root 4096 Apr 24 20:09 addr_len
...

Далее вы можете сделать a statна файле и заметить еще одну отличительную особенность; он занимает 0 блоков. Также inode корня (stat /sys) равен 1. /stat/fsобычно имеет inode 2. и т.д.

rsync против cp

Самым простым объяснением сбоя синхронизации псевдофайлов с помощью rsync, пожалуй, является пример.

Допустим, у нас есть файл с именем address, который имеет размер 18 байт. Операция lsor statфайла сообщает о 4096 байтах.


rsync

  1. Открывает файловый дескриптор, fd.
  2. Использует fstat(fd) для получения такой информации, как размер.
  3. Установите для чтения размер байт, т.е. 4096. Это будетстрока 253кода, связанного@mattdm.read_size == 4096
    1. Спросите; прочитайте: 4096 байт.
    2. Считывается короткая строка, т.е. 18 байт.nread == 18
    3. read_size = read_size - nread (4096 - 18 = 4078)
    4. Спросить; прочитать: 4078 байт
    5. Прочитано 0 байт (так как при первом чтении были израсходованы все байты в файле).
    6. nread == 0,строка 255
    7. Невозможно прочитать 4096байты. Обнулить буфер.
    8. Ошибка установки ENODATA.
    9. Возвращаться.
  4. Сообщить об ошибке.
  5. Повторить попытку. (Цикл выше).
  6. Неудача.
  7. Сообщить об ошибке.
  8. ОТЛИЧНО.

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

ср

  1. Открывает файловый дескриптор, fd.
  2. Использует fstat(fd) для получения такой информации, как st_size (также использует lstat и stat).
  3. Проверьте, не является ли файл разреженным. То есть, файл имеет дыры и т.п.

    copy.c:1010
    /* Use a heuristic to determine whether SRC_NAME contains any sparse
     * blocks.  If the file has fewer blocks than would normally be
     * needed for a file of its size, then at least one of the blocks in
     * the file is a hole.  */
    sparse_src = is_probably_sparse (&src_open_sb);
    

    Поскольку statфайл отчетов не имеет блоков, он классифицируется как разреженный.

  4. Пытается прочитать файл методом экстента-копирования (более эффективный способ копирования)нормальный разреженные файлы) и терпит неудачу.

  5. Копия разреженной копией.
    1. Начинается с максимального размера чтения MAXINT.
      Обычно 18446744073709551615байты на 32-битной системе.
    2. Запрос; прочитать 4096 байт. (Размер буфера, выделенного в памяти из статистической информации.)
    3. Считывается короткая строка, т.е. 18 байт.
    4. Проверьте, нужно ли отверстие, нет.
    5. Записать буфер в цель.
    6. Вычтите 18 из максимального размера считывания.
    7. Спросите; прочитайте 4096 байт.
    8. 0 байт, так как все данные были израсходованы при первом чтении.
    9. Возвращение успеха.
  6. Все ОК. Обновите флаги для файла.
  7. ОТЛИЧНО.

решение2

Rsync имееткодкоторый специально проверяет, не обрезан ли файл во время чтения и выдает эту ошибку — ENODATA. Я не знаюпочемуфайлы в /sysведут себя таким образом, но поскольку это не настоящие файлы, я думаю, это не слишком удивительно. Кажется, нет способа указать rsync пропустить эту конкретную проверку.

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

решение3

Возможно, это связано, но вызовы расширенных атрибутов не будут работать в sysfs:

[root@hypervisor eth0]# адрес lsattr

lsattr: Неподходящий ioctl для устройства при чтении флагов по адресу

[root@hypervisor eth0]#

Если посмотреть на мой strace, то можно увидеть, что rsync пытается по умолчанию извлечь расширенные атрибуты:

22964 <... getxattr возобновлен>, 0x7fff42845110, 132) = -1 ENODATA (Нет доступных данных)

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

решение4

Rsync обычно считывает информацию из файла, переносит содержимое файла или дельты во временный файл в целевом каталоге, а затем после проверки данных файла переименовывает его в имя целевого файла.

Я считаю, что проблема с sysfs в том, что все файлы отображаются как 4k (одна страница памяти), хотя они могут содержать всего несколько байт. Чтобы избежать копирования потенциально поврежденного файла в место назначения, rsync отменяет копирование, когда обнаруживает несоответствие между метаданными файла и тем, что было фактически скопировано.

По крайней мере, в rsync v3.0.6 этого поведения можно избежать с помощью переключателя --inplace. Rsync все равно будет обнаруживать ошибки, но поскольку файлы назначения уже будут перезаписаны, то потенциально поврежденные файлы останутся там.

Обратите внимание, что побочным эффектом этого является то, что файлы в конечном итоге дополняются нулями до 4k, поскольку rsync считает, что файлы имеют такой размер. В большинстве случаев это не должно иметь значения, поскольку нулевые байты обычно игнорируются.

Связанный контент