(Como) excluir arquivos abertos no Linux e um sistema de arquivos FAT funciona?

4

Está claro para mim como a exclusão de arquivos abertos funciona em sistemas de arquivos que usam inodes - unlink () apenas diminui a contagem de links para zero e quando o último identificador de arquivo para o arquivo é fechado, o inode será removido. >

Mas como funciona ao usar um sistema de arquivos que não usa inodes, como o FAT32, com o Linux?

Alguns experimentos sugerem que a exclusão de arquivos abertos ainda é possível (diferentemente do Windows, onde a chamada de desconexão não seria bem-sucedida), mas o que acontece quando o sistema de arquivos é desimpedido sem limpeza?

Como o Linux marca os arquivos como desvinculados, quando o próprio sistema de arquivos não suporta tal operação? A entrada de diretório foi excluída, mas retida na memória (que garantiria a exclusão após a desmontagem em qualquer caso, mas deixaria o sistema de arquivos em um estado inconsistente) ou a exclusão somente será marcada na memória e gravada no momento em que a exclusão O último identificador de arquivo é fechado, evitando possíveis danos, mas restaurando os arquivos excluídos após uma desmontagem impura?

    
por lxgr 14.09.2012 / 08:41

1 resposta

2

Você está correto em sua suposição de que, enquanto todas as entradas de diretório são excluídas imediatamente após chamar unlink (), os blocos reais que compõem fisicamente o arquivo são apagados apenas disco quando nada está usando o inode mais. (Eu digo "diretório entradas " porque em vfat, um arquivo pode ter vários deles, por causa de como o suporte a nome de arquivo longo do vfat é implementado).

Neste contexto, por inode , refiro-me à estrutura na memória que o kernel do Linux usa para manipular arquivos. Ele é usado mesmo quando o sistema de arquivos não é "baseado em inode". No caso do vfat, o inode é simplesmente apoiado por alguns blocos no disco.

Observando o código-fonte do kernel do Linux, vemos que vfat_unlink , que implementa a chamada do sistema unlink() para vfat, faz aproximadamente o seguinte (extremamente simplificado para ilustração):

static int vfat_unlink(struct inode *dir, struct dentry *dentry)
{
        fat_remove_entries(dir, &sinfo);
        clear_nlink(inode);
}

Então o que acontece é:

  1. fat_remove_entries simplesmente remove a entrada do arquivo em seu diretório.
  2. clear_nlink define a contagem de links para o inode como 0 , o que significa que nenhum arquivo (ou seja, nenhuma entrada de diretório) aponta para esse inode mais.

Note que neste ponto, nem o inode nem sua representação física são tocados de qualquer forma (exceto pela diminuição da contagem de links), então ainda existe alegremente na memória e no disco, como se nada tivesse acontecido!

(A propósito, também é interessante notar que vfat_unlink sempre define a contagem de links para 0 ao invés de apenas decrementá-los usando drop_link . Isso deve indicar que sistemas de arquivos FAT não suportam hard links! E é mais uma indicação de que o próprio FAT não conhece nenhum conceito inode separado.)

Agora vamos dar uma olhada no que acontece quando o inode é despejado . evict_inode é chamado quando não queremos mais o inode na memória. No início, isso pode acontecer apenas quando nenhum processo contém qualquer descritor de arquivo aberto para esse inode (mas, em teoria, isso também pode acontecer em um momento posterior). A implementação do FAT para evict_inode parece (novamente simplificada) assim:

static void fat_evict_inode(struct inode *inode)
{
        truncate_inode_pages(&inode->i_data, 0);
        if (!inode->i_nlink) {
                inode->i_size = 0;
                fat_truncate_blocks(inode, 0);
        }
        invalidate_inode_buffers(inode);
        clear_inode(inode);
}

A mágica acontece exatamente dentro da if -clause: se a contagem de links do inode for 0, significa que nenhuma entrada de diretório está realmente apontando para ela. Por isso, definimos seu tamanho para 0 e, na verdade, o truncamos para 0 bytes, o que, na verdade, o exclui do disco, limpando os blocos dos quais foi feito.

Assim, a corrupção que você está experimentando em seus experimentos é facilmente explicada: assim como você suspeitava, a entrada de diretório já havia sido removida (por vfat_unlink ), mas como o inode ainda não foi removido, os blocos foram ainda intocado, e ainda estavam marcados no FAT (um acrônimo para File Allocation Table) como usado. No entanto, o fsck.vfat detecta que não existe mais nenhuma entrada de diretório que aponte para esses blocos, queixe e repare.

A propósito, CHKDSK não apenas limparia esses blocos marcando-os como livres, mas criaria novos arquivos no diretório raiz apontando para o primeiro bloco em cada cadeia, com nomes como FILE0001.CHK .

    
por 10.10.2012 / 23:26