Como eu crio uma pequena imagem de disco com grandes partições?

6

Estou construindo uma imagem de disco para um sistema embarcado (para ser colocado em um cartão SD de 4GB). Eu quero que o sistema tenha duas partições. Uma partição 'Root' (200Mb) e 'Data' (800Mb).

Eu crio um arquivo vazio de 1GB com dd. Então eu uso parted para configurar as partições. Eu os monto cada um em um dispositivo de loop e os formato; ext2 para 'Root' ext4 para 'Data'. Adicione meu sistema de arquivos raiz à partição 'Root' e deixe 'Data' vazio.

Aqui é onde está o problema. Agora estou com uma imagem de 1 GB, com apenas 200 MB de dados. Eu não deveria, em teoria, ser capaz de truncar a imagem para baixo para dizer .. 201MB e ainda ter o sistema de arquivos montável? Infelizmente, não encontrei este o caso.

Eu me lembro no passado de ter usado um ambiente de criação da Freescale que costumava criar imagens de 30Mb, que teriam partições para utilizar um cartão SD inteiro de 4GB. Infelizmente, neste momento, não consigo descobrir como eles estavam fazendo isso.

Eu li o formato em disco para o sistema de arquivos ext, e se não houver dados em nada além do primeiro super bloco (exceto para super blocos de backup e tabelas de bloco não utilizadas), pensei que poderia truncar lá.

Infelizmente, quando faço isso, o sistema de montagem enlouquece. Eu posso então executar o FSCK, restaurar os superblocos e bloquear tabelas e montá-lo sem problemas. Eu só não acho que isso seja necessário.

Talvez um sistema de arquivos diferente possa funcionar? Alguma idéia?

obrigado,

editar

alterou a partição para ler o sistema de arquivos. A partição ainda está lá e não muda, mas o sistema de arquivos está sendo destruído depois de truncar a imagem.

editar

Encontrei o caso quando trunco o arquivo para um tamanho maior que o primeiro conjunto de superblocos de partição de dados e tabelas inode / block, (em algum lugar no intervalo de blocos de dados) o sistema de arquivos se torna desmontável sem fazer um fsck para restaurar o resto dos super blocos e tabelas de bloco / inode

    
por AllenKll 16.07.2015 / 22:57

4 respostas

4

Primeiramente, escrever uma imagem esparsa em um disco não resultará em nada além do tamanho total do arquivo de imagem - furos e tudo - cobrindo o disco. Isso ocorre porque manipulação de arquivos esparsos é uma qualidade do sistema de arquivos - e um dispositivo bruto (como aquele no qual você escreve a imagem) não tem essa coisa ainda . Um arquivo esparso pode ser armazenado com segurança em um meio controlado por um sistema de arquivos que entende arquivos esparsos (como um dispositivo ext4) mas como Assim que você escrever, ele irá envolver tudo o que você pretende. E o que você deve fazer é:

  1. Basta armazená-lo em um fs que compreenda arquivos esparsos até estar preparado para escrevê-lo.

  2. Faça duas camadas de profundidade ...

    • Ou seja, escreva sua imagem principal em um arquivo, crie outra imagem parent com um fs que entenda arquivos esparsos e copie sua imagem para o pai imagem e ...

    • Quando chegar a hora de escrever a imagem, primeiro escreva sua imagem principal e escreva sua imagem principal.

Veja como fazer 2:

  • Crie um arquivo esparso de 1 GB ...

    dd bs=1kx1k seek=1k of=img </dev/null
    
  • Escreva duas partições ext4 em sua tabela de partições: 1 200MB, 2 800MB ...

    printf '%b\n\n\n\n' n '+200M\nn\n' 'w\n\c' | fdisk img
    
  • Crie dois ext4 sistemas de arquivos em um dispositivo de loop de -P artitioned e coloque uma cópia do segundo no primeiro ...

    sudo sh -c '
        for p in "$(losetup --show -Pf img)p"*        ### the for loop will iterate
        do    mkfs.ext4 "$p"                          ### over fdisks two partitions
              mkdir -p ./mnt/"${p##*/}"               ### and mkfs, then mount each
              mount "$p" ./mnt/"${p##*/}"             ### on dirs created for them
        done; sync; cd ./mnt/*/                       ### next we cp a sparse image
        cp --sparse=always "$p" ./part2               ### of part2 onto part1
        dd bs=1kx1k count=175 </dev/zero >./zero_fill ### fill out part1 w/ zeroes
        sync; cd ..; ls -Rhls .                       ### sync, and list contents
        umount */; losetup -d "${p%p*}"               ### last umount, destroy
        rm -rf loop*p[12]/ '                          ### loop devs and mount dirs
    
    mke2fs 1.42.12 (29-Aug-2014)
    Discarding device blocks: done
    Creating filesystem with 204800 1k blocks and 51200 inodes
    Filesystem UUID: 2f8ae02f-4422-4456-9a8b-8056a40fab32
    Superblock backups stored on blocks:
        8193, 24577, 40961, 57345, 73729
    
    Allocating group tables: done
    Writing inode tables: done
    Creating journal (4096 blocks): done
    Writing superblocks and filesystem accounting information: done
    
    mke2fs 1.42.12 (29-Aug-2014)
    Discarding device blocks: done
    Creating filesystem with 210688 4k blocks and 52752 inodes
    Filesystem UUID: fa14171c-f591-4067-a39a-e5d0dac1b806
    Superblock backups stored on blocks:
        32768, 98304, 163840
    
    Allocating group tables: done
    Writing inode tables: done
    Creating journal (4096 blocks): done
    Writing superblocks and filesystem accounting information: done
    
    175+0 records in
    175+0 records out
    183500800 bytes (184 MB) copied, 0.365576 s, 502 MB/s
    ./:
    total 1.0K
    1.0K drwxr-xr-x 3 root root 1.0K Jul 16 20:49 loop0p1
       0 drwxr-xr-x 2 root root   40 Jul 16 20:42 loop0p2
    
    ./loop0p1:
    total 176M
     12K drwx------ 2 root root  12K Jul 16 20:49 lost+found
     79K -rw-r----- 1 root root 823M Jul 16 20:49 part2
    176M -rw-r--r-- 1 root root 175M Jul 16 20:49 zero_fill
    
    ./loop0p1/lost+found:
    total 0
    
    ./loop0p2:
    total 0
    
  • Agora, esse é um bom resultado - principalmente de mkfs.ext4 -, mas observe especialmente os ls bits na parte inferior. ls -s mostrará o real -s ize de um arquivo no disco - e ele sempre é exibido na primeira coluna.

  • Agora, basicamente, podemos reduzir nossa imagem apenas para a primeira partição ...

    fdisk -l img
    
    Disk img: 1 GiB, 1073741824 bytes, 2097152 sectors
    Units: sectors of 1 * 512 = 512 bytes
    Sector size (logical/physical): 512 bytes / 512 bytes
    I/O size (minimum/optimal): 512 bytes / 512 bytes
    Disklabel type: dos
    Disk identifier: 0xc455ed35
    
    Device Boot  Start     End Sectors  Size Id Type
    img1          2048  411647  409600  200M 83 Linux
    img2        411648 2097151 1685504  823M 83 Linux
    
  • fdisk nos informa que há 411647 +1 512 setores de bytes na primeira partição de img ...

    dd seek=411648 of=img </dev/null
    
  • Isso trunca o arquivo img para apenas sua primeira partição. Vêem?

    ls -hls img
    
    181M -rw-r--r-- 1 mikeserv mikeserv 201M Jul 16 21:37 img
    
  • ... mas ainda podemos montar essa partição ...

    sudo mount "$(sudo losetup -Pf --show img)p"*1 ./mnt
    
  • ... e aqui está o seu conteúdo ...

    ls -hls ./mnt
    
    total 176M
     12K drwx------ 2 root root  12K Jul 16 21:34 lost+found
     79K -rw-r----- 1 root root 823M Jul 16 21:34 part2
    176M -rw-r--r-- 1 root root 175M Jul 16 21:34 zero_fill
    
  • E podemos acrescentar a imagem armazenada da segunda partição à primeira ...

    sudo sh -c '
        dd seek=411648 if=./mnt/part2 of=img
        umount ./mnt; losetup -D
        mount "$(losetup -Pf --show img)p"*2 ./mnt
        ls ./mnt; umount ./mnt; losetup -D'
    
    1685504+0 records in
    1685504+0 records out
    862978048 bytes (863 MB) copied, 1.96805 s, 438 MB/s
    lost+found
    
  • Agora que cresceu nosso arquivo img : não é mais esparso ...

    ls -hls img
    
    1004M -rw-r--r-- 1 mikeserv mikeserv 1.0G Jul 16 21:58 img
    
  • ... mas remover isso é tão simples na segunda vez como foi o primeiro, claro ...

    dd seek=411648 of=img </dev/null
    ls -hls img
    
    181M -rw-r--r-- 1 mikeserv mikeserv 201M Jul 16 22:01 img
    
por 17.07.2015 / 01:01
6

A maneira mais fácil de fazer isso é criar seu arquivo de apoio como um arquivo esparso; isto é, faça 1GB com truncate -s 1G disk.img em vez de dd if=/dev/zero bs=1048576 count=1024 of=disk.img (ou qualquer outro). Bem, truncate também é muito mais rápido.

Se você fizer um ls -l no arquivo, ele será exibido como 1 GB, mas esse é apenas o tamanho aparente. du disk.img dará o tamanho real.

(Nota - você precisará ter sua imagem em um sistema de arquivos que suporte arquivos esparsos. Todos os Unix comuns fazem. Ext2 / 3/4 todos fazem. FAT32 não. HFS + também não.)

NOTA: Os arquivos esparsos ainda são, logicamente, o tamanho total. Apenas as seções nunca gravadas não são fisicamente armazenadas no disco. Na maior parte, a parte não armazenada é ocultada dos programas. Alguns utilitários têm suporte para isso, no entanto. (Por exemplo, dd conv=sparse , cp --sparse=auto/always , etc.). Um stick USB real não pode ser escasso. E se você usar dd conv=sparse para escrevê-lo, provavelmente será muito mais rápido, mas você deixará todos os dados antes, em vez dos blocos cheios de NULs (0x00) esperados. Deve funcionar bem (como seu espaço livre), mas deixará dados antigos no pen drive USB - possivelmente uma preocupação de segurança.

    
por 16.07.2015 / 23:20
0

Você está querendo criar esta imagem com 800MB de espaço, para poder copiar para cartões SD. Mas não querendo perder espaço ao armazenar a imagem. Em caso afirmativo, sugiro a compactação, como bzip . Isso dependerá de blocos não utilizados sendo inicializados para zero.

    
por 16.07.2015 / 23:47
-1

Espero que eu entenda a pergunta corretamente:

Para reduzir um sistema de arquivos e partição. Use gparted .

    
por 16.07.2015 / 23:22