O losetup pode ser eficiente com arquivos esparsos?

1

Então minha configuração é assim.

$ truncate -s 1T volume
$ losetup -f --show volume
/dev/loop0
$ mkfs.ext4 /dev/loop0
$ ls -sh volume
1.1G volume
$ mount /dev/loop0 /mnt/loop

Agora eu tenho um volume de 1,1 TB, como esperado. A sobrecarga do ext4 expandiu o arquivo esparso para 1.1G, mas tudo bem. Agora para adicionar um arquivo.

$ dd if=/dev/urandom of=/mnt/loop/file bs=1M count=10240
$ ls -sh volume
12G volume

Legal, agora não quero o arquivo.

$ rm /mnt/loop/file
$ ls -sh volume
12G volume

O espaço livre ainda ocupa espaço, como esperado, e $ fallocate -d volume libera 1 gb.

A minha pergunta é: como posso zerar o espaço livre aqui sem expandir o volume para o tamanho total? $ dd if=/dev/zero expandirá para o tamanho total e, com conv=sparse , criará um arquivo esparso inútil dentro do volume.

TL; DR: Existe uma maneira de fazer com que losetup ignore gravações de blocos nulos em setores nulos, enquanto permite tudo mais?

    
por Daffy 23.08.2018 / 02:43

2 respostas

2

Para descartar automaticamente os blocos de dados quando eles não forem mais usados, use mount -o discard ... . Ou você pode executar manualmente fstrim .

Este recurso foi aparentemente adicionado ao dispositivo de loop no Linux 3.2. link

No caso geral, não é garantido que mount -o discard seja eficaz, porque alguns tipos de dispositivos podem ignorar as solicitações de descarte quando estiverem ocupadas. Isso não seria uma preocupação para o tamanho do seu arquivo esparso.

Neste caso geral - por ex. se você também quiser enviar solicitações de descarte para um dispositivo físico subjacente - o método mais robusto é executar fstrim em intervalos regulares.

    
por 23.08.2018 / 09:48
0

Não é uma solução usando ferramentas embutidas, mas eu peguei um script python para fazer o que eu quero. Aqui está, se ajudar alguém. Ainda procurando uma solução incorporada, se houver uma.

#!/usr/bin/python3.6
import os
import time
import sys

if len(sys.argv) != 2:
    print('''Usage: {} <file>

Fills a file/device with zeros, with efficiencies for sparse files.'''.format(sys.argv[0]))
    exit(1)

f = open(sys.argv[1], 'rb+', 0)

bs = 1024*1024 # block size
zb = b'
#!/usr/bin/python3.6
import os
import time
import sys

if len(sys.argv) != 2:
    print('''Usage: {} <file>

Fills a file/device with zeros, with efficiencies for sparse files.'''.format(sys.argv[0]))
    exit(1)

f = open(sys.argv[1], 'rb+', 0)

bs = 1024*1024 # block size
zb = b'%pre%'*bs  # a full block of zeros

lasttime = round(time.time())
block = f.read(bs)
while len(block) == bs:

    # IFF a block contains non-zero characters, zero it
    if block != zb:
        f.seek(-bs, os.SEEK_CUR)
        f.write(zb)
    block = f.read(bs)

    # Print the processed bytes every second
    # Could add a MB/s or % completed, but too lazy
    if round(time.time()) != lasttime:
        print(f.tell())
        lasttime = round(time.time())

# Hit EOF, might have missed bytes at the end
# Zero last block unconditionally, too lazy to check if its required
f.seek(-bs, os.SEEK_CUR)
f.write(zb)
f.close()
'*bs # a full block of zeros lasttime = round(time.time()) block = f.read(bs) while len(block) == bs: # IFF a block contains non-zero characters, zero it if block != zb: f.seek(-bs, os.SEEK_CUR) f.write(zb) block = f.read(bs) # Print the processed bytes every second # Could add a MB/s or % completed, but too lazy if round(time.time()) != lasttime: print(f.tell()) lasttime = round(time.time()) # Hit EOF, might have missed bytes at the end # Zero last block unconditionally, too lazy to check if its required f.seek(-bs, os.SEEK_CUR) f.write(zb) f.close()
    
por 23.08.2018 / 06:50