Por que o rsync não copia arquivos de / sys no Linux?

12

Eu tenho um script bash que usa rsync para arquivos de backup no Archlinux. Percebi que rsync falhou ao copiar um arquivo de /sys , enquanto cp funcionou bem:

# 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

Pergunto-me por que rsync falha e é possível copiar o arquivo com ele?

    
por Eugene Yarmash 24.04.2013 / 18:35

4 respostas

12

O Rsync tem código que verifica especificamente se um arquivo é truncado durante a leitura e apresenta este erro - ENODATA . Eu não sei porque os arquivos em /sys têm esse comportamento, mas como eles não são arquivos reais, eu acho que não é muito surpreendente. Não parece haver uma maneira de dizer ao rsync para pular essa verificação em particular.

Eu acho que você provavelmente está melhor em não rsyncing /sys e usar scripts específicos para escolher as informações específicas que você deseja (como o endereço da placa de rede).

    
por 24.04.2013 / 20:20
11

Primeiro, /sys é um pseudo sistema de arquivos . Se você olhar para /proc/filesystems , você encontrará uma lista de sistemas de arquivos registrados, onde alguns têm nodev em frente. Isso indica que eles são pseudo filesystems . Isso significa que eles existem em um kernel em execução como um sistema de arquivos baseado em RAM. Além disso, eles não exigem um dispositivo de bloco.

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

Na inicialização, o kernel monta este sistema e atualiza as entradas quando adequado. Por exemplo. quando novo hardware é encontrado durante a inicialização ou por udev .

Em /etc/mtab , você geralmente encontra a montagem por:

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

Para um bom artigo sobre o assunto, leia Patric Mochel's - O sistema de arquivos sysfs .

stat dos arquivos / sys

Se você entrar em um diretório em /sys e fizer um ls -l , perceberá que todos os arquivos têm um tamanho. Normalmente, 4096 bytes. Isso é relatado por 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
...

Além disso, você pode fazer um stat em um arquivo e observar outro recurso distinto; ocupa 0 blocos. Também inode da raiz (stat / sys) é 1. /stat/fs tipicamente tem inode 2. etc.

rsync vs. cp

A explicação mais fácil para a falha do rsync de sincronizar pseudo-arquivos é talvez pelo exemplo.

Digamos que tenhamos um arquivo chamado address , que é 18 bytes. Um ls ou stat do arquivo relata 4096 bytes.

rsync

  1. Abre o descritor de arquivos, fd.
  2. Usa fstat (fd) para obter informações como tamanho.
  3. Prepare-se para ler bytes de tamanho, ou seja, 4096. Isso seria linha 253 do código vinculado por @mattdm . %código%
    1. Pergunte; leia: 4096 bytes.
    2. Uma string curta é lida, isto é, 18 bytes. %código%
    3. read_size == 4096
    4. Pergunte; ler: 4078 bytes
    5. 0 bytes lidos (como primeira leitura consumiu todos os bytes no arquivo).
    6. nread == 18 , linha 255
    7. Não é possível ler read_size = read_size - nread (4096 - 18 = 4078) bytes. Zero out buffer.
    8. Definir erro nread == 0 .
    9. Retornar.
  4. Comunicar erro.
  5. Tente novamente. (Acima do loop).
  6. Falha.
  7. Comunicar erro.
  8. FINA.

Durante este processo, ele lê o arquivo inteiro. Mas sem tamanho disponível não pode validar o resultado - assim, a falha é apenas a opção.

cp

  1. Abre o descritor de arquivos, fd.
  2. Usa fstat (fd) para obter informações como st_size (também usa lstat e stat).
  3. Verifique se é provável que o arquivo seja escasso. Esse é o arquivo tem furos etc.

    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);
    

    Como o arquivo de relatórios 4096 tem blocos zero, ele é classificado como esparso.

  4. Tenta ler o arquivo por cópia de extensão (uma maneira mais eficiente de copiar normal arquivos esparsos) e falha.

  5. Copiar por cópia esparsa.
    1. Começa com o tamanho máximo de leitura de MAXINT.
      tipicamente ENODATA bytes em um sistema de 32 bits.
    2. Pergunte; leia 4096 bytes. (Tamanho do buffer alocado na memória a partir de informações estatísticas).
    3. Uma string curta é lida, isto é, 18 bytes.
    4. Verifique se um buraco é necessário, não.
    5. Escreve o buffer para o destino.
    6. Subtraia 18 do tamanho máximo de leitura.
    7. Pergunte; leia 4096 bytes.
    8. 0 bytes como todos consumidos na primeira leitura.
    9. Retornar o sucesso.
  6. Tudo OK. Atualizar sinalizadores para arquivo.
  7. FINA.
por 25.04.2013 / 02:23
2

Pode estar relacionado, mas as chamadas de atributo estendido falharão no sysfs:

[root@hypervisor eth0]# lsattr address

lsattr: Inappropriate ioctl for device While reading flags on address

[root@hypervisor eth0]#

Olhando para o meu strace, parece que o rsync tenta extrair atributos estendidos por padrão:

22964 <... getxattr resumed> , 0x7fff42845110, 132) = -1 ENODATA (No data available)

Eu tentei encontrar um sinalizador para dar ao rsync para ver se ignorar os atributos estendidos resolve o problema, mas não conseguiu encontrar nada ( --xattrs os transforma no destino).

    
por 24.04.2013 / 19:55
0

O Rsync normalmente lê as informações do arquivo, transfere o conteúdo do arquivo ou delta para um arquivo temporário no diretório de destino, depois de verificar os dados do arquivo, ele renomeia o nome do arquivo de destino.

Eu acredito que o problema com o sysfs é que todos os arquivos são exibidos como 4k (uma página de memória), mas eles podem conter apenas alguns bytes. Para evitar a cópia de um arquivo potencialmente corrompido para o destino, o rsync cancela a cópia quando vê uma incompatibilidade entre os metadados do arquivo e o que foi realmente copiado.

Pelo menos no rsync v3.0.6, esse comportamento pode ser evitado usando a opção --inplace . O Rsync ainda detectará erros, mas como os arquivos de destino já foram sobrescritos, isso deixará os arquivos potencialmente corrompidos lá.

Note que um efeito colateral disso é que os arquivos acabam sendo preenchidos com zero para 4k, já que este é o tamanho que o rsync acha que os arquivos são. Não deve fazer diferença na maioria dos casos, pois os bytes nulos são geralmente ignorados.

    
por 23.02.2018 / 06:16