Eu preciso reduzir um grande volume ext4, e gostaria de fazê-lo com o menor tempo de inatividade possível. Com os testes que fiz até agora, parece que pode ser desmontado para redimensionar por até uma semana. Existe alguma maneira de desfragmentar o sistema de arquivos on-line antecipadamente, para que as resizefs não precisem mover tantos blocos ao redor?
Atualização:
Levou algum tempo para chegar a esse ponto, movi alguns dados de TB em preparação para o psiquiatra, e experimentei usar as informações na resposta abaixo. Eu finalmente criei a seguinte linha de comando que poderia ser útil para outras pessoas em uma situação similar com apenas pequenas modificações. Observe também que ele deve ser executado como raiz para que os comandos filefrag e e4defrag funcionem corretamente - isso não afetará a propriedade do arquivo. Ele também funciona adequadamente em arquivos com vários hard-links, o que eu tenho muito.
find -type f -print0 | xargs -0 filefrag -v | grep '\.\.[34][0-9]\{9\}.*eof' -A 1 | awk '/extents found/ {match($0, /^(.*): [0-9]+ extents found/, res); print res[1]}' | xargs -n 1 -d '\n' e4defrag
Uma explicação rápida para facilitar a modificação / uso de outras pessoas:
O primeiro comando 'find' constrói a lista de arquivos para trabalhar. Possivelmente redundante agora ou poderia ser feito de uma maneira melhor, mas durante o teste eu tinha outros filtros lá e deixei-o como um local prático para modificar o escopo do resto do comando.
Em seguida, passe cada arquivo por meio de 'filefrag -v' para obter uma lista de todos os blocos físicos usados por cada arquivo.
O grep procura o último bloco usado por cada arquivo (linha que termina em 'eof'), e onde esse bloco é um número de 10 dígitos começando com 3 ou 4. No meu caso, o novo tamanho do sistema de arquivos será 2980024320 longo para que seja feito um trabalho suficientemente bom apenas de trabalhar em arquivos que estão na área do disco a ser removido. Ter o grep também inclui a seguinte linha (o '-A 1') também inclui o nome do arquivo na saída da próxima seção. É aqui que qualquer outra pessoa que faça isso terá que modificar o comando, dependendo do tamanho do sistema de arquivos. Também poderia provavelmente ser feito de uma maneira muito melhor, mas isso está funcionando para mim agora e eu sou preguiçoso.
O awk extrai apenas os nomes dos arquivos de todos os outros tipos de lixo que o grep deixou na saída do arquivo.
E finalmente e4defrag é chamado - não me importo com a contagem real de fragmentos, mas tem o efeito colateral de mover os blocos físicos (esperançosamente para uma parte inicial da unidade) e funciona contra arquivos com vários hard-links sem esforço extra.
Se você quiser apenas saber quais arquivos ele desfragmentaria sem realmente mover nenhum dado, apenas deixe a última parte do comando desligada.
find -type f -print0 | xargs -0 filefrag -v | grep '\.\.[34][0-9]\{9\}.*eof' -A 1 | awk '/extents found/ {match($0, /^(.*): [0-9]+ extents found/, res); print res[1]}'