Considérez un périphérique de bloc brut de 100 Mo comme exemple simple. Soit 204800 blocs de 512 octets chacun pour un total de 102760448 octets.
Le défi est de décaler les premiers 98 Mo (blocs 200704) de sorte qu'il y ait un écart de 2 Mo (4096 blocs) devant lui. Pour le faire sur place, rien n'est écrit dans un secteur qui n'a pas été lu. Une façon d'y parvenir consiste à introduire un tampon:
$ dd if=/dev/sdj2 count=200704 | mbuffer -s 512 -b 4096 -P 100 | dd of=/dev/sdj2 seek=4096
On s'attend à ce mbuffer
qu'il stocke 4096 blocs avant de transmettre quoi que ce soit à l'écrivain, garantissant ainsi que rien n'est écrit dans une zone qui n'a pas été lue et que l'écrivain accuse un retard sur le lecteur par la taille du tampon. Le tampon doit permettre au lecteur et à l'écrivain de fonctionner aussi rapidement que possible dans ces constriants.
Cependant, cela ne semble pas fonctionner de manière fiable. J'ai essayé d'utiliser de vrais appareils mais ça ne marche jamais sur eux, alors que les expériences avec un fichier fonctionnaient sur ma box 64 bits mais pas sur ma box 32 bits.
Tout d'abord, quelques préparatifs:
$ dd if=/dev/sdj2 count=200704 | md5sum
0f0727f6644dac7a6ec60ea98ffc6da9
$ dd if=/dev/sdj2 count=200704 of=testfile
Cela ne fonctionne pas:
$ dd if=/dev/sdj2 count=200704 | mbuffer -s 512 -b 4096 -P 100 -H | dd of=/dev/sdj2 seek=4096
summary: 98.0 MiByte in 4.4sec - average of 22.0 MiB/s
md5 hash: 3cbf1ca59a250d19573285458e320ade
Cela fonctionne sur un système 64 bits mais pas sur un système 32 bits:
$ dd if=testfile count=200704 | mbuffer -s 512 -b 4096 -P 100 -H | dd of=testfile seek=4096 conv=notrunc
summary: 98.0 MiByte in 0.9sec - average of 111 MiB/s
md5 hash: 0f0727f6644dac7a6ec60ea98ffc6da9
Comment cela peut-il être fait de manière fiable?
Remarques
J'ai lu d'autres questions sur la mise en mémoire tampon et regardé pv
, buffer
et mbuffer
. Je ne pouvais que faire fonctionner ce dernier avec la taille de tampon requise.
L'utilisation du stockage intermédiate est une solution évidente au problème qui fonctionne toujours, mais ce n'est pas pratique quand une capacité de réserve suffisante n'est pas disponible.
Testez les plates-formes exécutant Arch Linux avec la mbuffer
version 20140302.
la source
mbuffer
du tout? Pourquoi ne pas plutôt fairedd
lire le contenu entier du périphérique de bloc en une seule fois en utilisantdd bs=102760448
? Bien sûr, d'une manière ou d'une autre, il est mis en mémoire tampon dans la RAM.mbuffer
devrait en fait forcer le seconddd
à prendre du retard pour le premier et vous n'avez besoin que de suffisamment de RAM pour tamponner la taille du décalage. Dommagedd
ne prend pas en charge la lecture et l'écriture des blocs dans l'ordre inverse car cela éliminerait le problème!-H
argument active cette fonctionnalité).Réponses:
Sans tampon, vous pouvez revenir en arrière, un bloc à la fois.
Veuillez noter que cet exemple est dangereux en raison du manque de vérification des erreurs.
Il est également lent en raison de la quantité d'
dd
appels. Si vous avez de la mémoire disponible, vous pouvez utiliser une taille de bloc plus grande.Avec un tampon, méfiez - vous des pièges . Il ne suffit pas de garantir un pré-remplissage à 100%. Ce dont vous avez besoin, c'est d'un remplissage minimum tout au long du processus. Le tampon ne doit jamais descendre en dessous
2M
car sinon vous aurez à nouveau écrasé vos données encore à lire.Donc, en théorie, vous pouvez vous passer de tout type de tampon et simplement enchaîner
dd
:En pratique, cela ne fonctionne pas de manière fiable car il n'y a aucune garantie que le premier
dd
parvienne à continuer à lire les données, tandis que le dernierdd
(avec2M
"tampon" entre les deux) écrit déjà.Vous pouvez augmenter considérablement vos chances en augmentant considérablement la taille du tampon intermédiaire, mais ce n'est pas fiable.
Malheureusement, je ne connais pas un bon programme tampon avec une propriété de remplissage minimum. Vous en avez besoin d'un qui arrête la sortie tant qu'il reste moins que votre marge de sécurité dans le tampon.
la source
dd
l'utiliser. Je pense, cependant, que la vraie solution n'est pas d'utiliser,dd
mais plutôt d'opter pour quelque chose qui est conçu pour fonctionner à l'envers commeddrescue
. J'ai décrit un moyen de le faire dans une réponse.ddrescue
ici. Pas s'il s'attend à fonctionner sur différents appareils et que vous devez l'inciter à accepter vos arguments. Il pourrait ne pas avoir la propriété "minimum buffer fill" en interne non plus (car avec différents appareils, ce n'est pas nécessaire), donc encore une fois, cela pourrait corrompre vos données. Vous devez vérifier dans le code source s'il est réellement conçu pour votre cas d'utilisation.Vous lisez 4096 blocs, puis écrivez ces blocs 4096 dans les blocs 4096 suivants du disque, écrasant ainsi les deuxièmes blocs 4096 avant de pouvoir les lire. Vous devez lire 8129 blocs pour obtenir ces seconds 4096 avant de commencer toute écriture, puis vous devez uniquement écrire 4096 blocs avant de lire le 4096 suivant.
Vous n'avez pas mentionné de quel type de système de fichiers il s'agit. Si elle est ext [234] et que vous disposez d'une version récente de e2fsprogs, vous pouvez l'utiliser
e2image -ra -O 512 /dev/sdj2
. Cela a également l'avantage supplémentaire d'être suffisamment intelligent pour ignorer l'espace libre dans le volume.la source
ext4
que pour la copie de périphérique de bloc, tout système de fichiers ne devrait pas être pertinent.dd
ne fait pas.Une solution fiable requiert que vous vous assuriez que rien n'écrit dans une zone qui n'a peut-être pas été lue et que la seule véritable façon d'y parvenir est d'effectuer la copie dans le sens inverse.
L'
ddrescue
outil peut fonctionner en sens inverse mais il refuse de fonctionner avec l'entrée et la sortie identiques. Cependant, il est possible de le tromper en dupliquant le nœud du périphérique.J'ai effectué quelques expériences rapides et cela semble fonctionner. La ligne de commande est:
Les arguments sont
-f
est nécessaire pour le forcer à écrire sur un périphérique de sortie existant-R
lui dit de travailler dans le sens inverse-s
lui indique la quantité d'entrée à copier (j'ai utilisé les
suffixe pour spécifier le nombre de secteurs)-o
lui dit de rechercher vers l'avant dans le périphérique de sortie avant d'écrire (spécifié à nouveau dans les secteurs avec les
suffixe)/dev/sdj11
est le périphérique bloc à lire/dev/sdj11_copy
est le périphérique de bloc pour écrireJ'ai créé
/dev/sdj11_copy
avecmknod
pour correspondre aux paramètres de/dev/sdj11
.Je n'ai fait que des tests très rapides, mais cela semble fonctionner correctement pour copier un périphérique brut. Cela ne fonctionne pas sur un fichier (je ne pouvais pas l'amener à aller au-delà des fichiers étant les mêmes)
Cela ne répond pas à ma question initiale qui demandait comment y parvenir,
dd
mais je pense qu'après avoir lu les autres réponses, la réponse est quedd
cela ne peut pas être fait.la source
ddrescue
découvre un mauvais bloc dans ce scénario? S'il saute vers une autre zone du disque (pour éviter les blocs défectueux) et continue de copier à partir de là, il écraserait à nouveau les parties non encore copiées de vos données. S'il ne s'attend pas à travailler avec le même appareil, il n'a aucune raison de prendre des mesures spéciales pour éviter divers cas possibles de corruption de données.ddrescue
options pour limiter ses tentatives de récupération de données incorrectes, mais je n'ai pas cherché à les utiliser.