En el lado de envío ( btrfs send)

En el lado de envío ( btrfs send)

Te lo explico en breve. Tengo dos subvolúmenes separados para películas y música, de los que estoy haciendo una copia de seguridad en otro disco con envío/recepción. Me gustaría fusionar los dos subvolúmenes en uno (con cp --reflink) y enviarlo a la unidad de respaldo clonando archivos vinculados de instantáneas existentes.

Intenté crearlo new_volume, luego cp -rx --reflink "music" "movies"ingresarlo y luego:

btrfs send \
    -c music-snapshot \
    -c movies-snapshot \
    new_volume-snapshot | btrfs receive /path/to/backup

pero se queja de que no se puede determinar el padre de new_volume(identificado por identificación):

ERROR: parent determination failed for <id_number>

Por supuesto music-snapshoty movies-snapshotexiste en la copia de seguridad. También intenté tomar una instantánea movies, new_volumeluego cp -rx --reflink "music"dentro de él, luego tomar una instantánea y enviarla con btrfs send -c music-snapshot -p movies-snapshot new_volume-snapshot, pero parece que -c music-snapshotno tiene ningún efecto, los datos se envían de todos modos.

¿Es posible lo que quiero hacer?

EDITAR: También intenté hacer esto:

btrfs sub snap -r movies movies-A
btrfs sub snap -r music music-A 
btrfs sub snap movies new_volume
btrfs sub snap -r new_volume new_volume-A

En este punto tengo:

movies-A
music-A
new_volume-A (exact clone of movies-A)

Entonces:

cp -rx --reflink music/* new_volume/
btrfs sub snap -r new_volume new_volume-B

Al final, con ambos movies-Ay music-Aexistiendo en destino, puedo hacer:

btrfs send \
    -p movies-A \
    new_volume-A | btrfs receive /backup/

y esto siempre funciona perfectamente (casi cero datos enviados). Pero...

btrfs send \
    -p new_volume-A \
    -c music-A \
    new_volume-B | btrfs receive /backup/

No sé cómo explicarlo: con "algunos archivos" musicfunciona, mientras que con otros sigue enviando datos porque ignora la fuente. Creo que de esta manera DEBERÍA funcionar definitivamente, pero no puedo reproducir de manera confiable ni el comportamiento de "trabajar" ni el de "no funcionar". Me tiendo a pensar que hay un error en alguna parte. ¿Alguien podría intentar esto?

Respuesta1

(DESCARGO DE RESPONSABILIDAD: el comentario de lgaudino sugiere que el enfoque propuesto para la fusión ya no funciona para btrfs-progs >=v5.14.2debido al cambiopropiedad btrfscomportamiento al cambiar el estado de solo lectura de una instantánea)

Lo que quieres se puede lograr, pero no directamente, porque btrfs send(y btrfs receive) son herramientas bastante simples,no hay forma de "fusionar" instantáneas en una proporcionando un padre secundariodesde el interior de las herramientas.

En el lado de envío ( btrfs send)

btrfs sendsalidassistema de archivosoperaciones de nivel (creación de directorio/archivo, transferencia de metadatos, transferencia de contenido de archivo, etc.) que pueden ser utilizadas en btrfs receiveel "lado receptor" para crear una instantánea equivalente en otro sistema de archivos btrfs. Estas operaciones se pueden ver realizando un "ejecución en seco" mediantebtrfs receive --dump.

Unincrementalenviar (p. ej. btrfs send -p <parent> <snapshot>) funciona exactamente igual en lo que a btrfs sendlo que respecta, excepto que solo se registran las operaciones del sistema de archivos necesarias para crear <snapshot>mediante modificación (agregar/eliminar directorios/archivos, actualizar metadatos) <parent>.

Tampoco se realiza ninguna verificación especial de la relación "padre-hijo". Suponiendo que el -pparámetro se utiliza para especificar el "padre", btrfs sendsimplemente genera los comandos necesarios para pasar de esa instantánea a otra (actuando como "secundario"). Esto funcionaría incluso si las dos instantáneas no tuvieran ninguna relación.

En el lado del envío, el único requisito btrfs sendes que todas las instantáneas seansolo lectura. Los subvolúmenes/instantáneas de solo lectura generalmente se generan mediante la -ropción enbtrfs subvolume snapshot -r <subvol> <snap>, a pesar debtrfs property set <snap> ro true/falseTambién se puede utilizar para cambiar la bandera después de la creación.

btrfs sendno tiene ninguna consideración por lo que está o no en el lado receptor, lo cual es inevitable ya que no hay comunicación bidireccional entre los lados, como en el rsynccaso de que btrfs send/receive ni siquiera se esté ejecutando al mismo tiempo y, en cambio, cada uno se ejecute en diferentes momentos. leer o escribir en un archivo.

Sólo puede haber un padre

Elpágina de manualy viejo)Preguntas frecuentes sobre wikislamentablemente son bastante confusos. el autor debtrfs-clone afirmaque btrfs envía y recibe solo puede considerar como máximounopadre para transferencias incrementales. El padre se puede especificar directamente -po indirectamente mediante una o varias -copciones:

btrfs-sendde btrfs-tools 4.13 selecciona el padre para un subvolumen S y un conjunto de fuentes de clonación dadas C_icomo esto:

  1. si -pse especifica la opción, úsela
  2. Si S no tiene parent_uuidun conjunto, o no se puede encontrar este uuid, abandone
  3. si hay C_icon C_i->uuid == S->parent_uuid(el subvolumen del cual S es un niño (instantánea), llamémoslo "mamá"), úsalo
  4. si ningún C_i tiene lo mismo parent_uuidque S, ríndete
  5. de todos los C_i que son hijos de "mamá", elige el que tenga la generación más cercana (en realidad, ctransid¿cuál es exactamente la diferencia entre "generación"?) y "mamá".

Tenga en cuenta quela wikies un poco engañoso, porque sugiere que -csin pes diferente de -ccon -p, aunque -pgeneralmente está implícito en el algoritmo anterior. La única excepción relevante es el envío de subvolúmenes que no tienen padre.

En resumen, sugiero especificar siempre explícitamente uno de los padres a través de -pe ignorar -c, btrfs receivesimplemente no existe el concepto de "dos padres".

En el lado receptor ( btrfs receive)

Elbtrfs-receiveLa página de manual describe el propósito del programa como:

Reciba un flujo de cambios y replique uno o más subvolúmenes que fueron generados previamente por btrfs send

<parent>En el caso de una transferencia completa, se crea un nuevo subvolumen; en el caso de una transferencia incremental, se crea una nueva instantánea de la instantánea (equivalente en el lado receptor) . En cualquier caso, el subvolumen/instantánea recién creado se muestra inicialmenteleer escribirpuede hasta que el "flujo de cambios" que emana btrfs sendse haya aplicado con éxito, luego se crea el subvolumen/instantáneasolo lectura.

Obviamente, no hay forma de implementar dos padres, ya que, para empezar, no hay copias de copia en escritura/reflink en el "flujo de cambios". La instantánea de <parent>simplemente proporciona la base sobre la cual se aplica el "flujo de cambios".

Pero, ¿cómo se asegura el lado receptor que su <parent>instantánea sea idéntica a la <parent>del lado emisor? Élnunca comprueba/compara el contenido realde las instantáneas/subvolúmenes, sino que utilizaUUIDmetadatos en relación con elinmutabilidadsuposición para la instantánea principal.

btrfs subvolume show <subvolume>proporciona resultados como:

/mnt/btrfs/subvolume
        Name:                   subvolume
        UUID:                   5e076a14-4e42-254d-ac8e-55bebea982d1
        Parent UUID:            -
        Received UUID:          -
        Creation time:          2018-01-01 12:34:56 +0000
        Subvolume ID:           79
        Generation:             2844
        Gen at creation:        2844
        Parent ID:              5
        Top level ID:           5
        Flags:                  -
        Snapshot(s):

Cada subvolumen/instantánea tiene tres ranuras UUID, de las cuales dos pueden estar vacías. Cada instantánea creada por btrfs subvolume snapshotsiempre tiene una Parent UUIDque identifica claramente a su padre y cada instantánea creada por btrfs receivesiempre tiene una Received UUIDentrada. Si fue una transferencia completa no tendrá ninguna Parent UUIDentrada, si fue una transferencia incremental tendrá tanto una Received UUIDentrada como una Parent UUIDentrada. El usuario no puede cambiar manualmente las entradas de UUID.

Estos ID son suficientes para btrfs receiveestablecer si posee una <parent>instantánea del "lado receptor" quedeberíaser completamente idéntica a la <parent>instantánea del "lado emisor", porque Received UUIDdebe ser equivalente al UUID del lado emisor, garantizando así que se creó a partir de él, y el estado de solo lectura de todas las instantáneas involucradas significa que nono debeMientras tanto se han producido cambios.

(Nota al margen: si bien solo un lado de los dos volúmenes principales contiene la entrada UUID recibido, btrfs send/receive parece ser lo suficientemente inteligente como para proporcionar estos metadatos en el "flujo de cambios", por lo que ambos lados/sistemas de archivos pueden actuar potencialmente como el lado "enviador" o "receptor", según las necesidades del usuario)

Cómo fusionar dos subvolúmenes/instantáneas (<v5.14.2)

Como hemos visto, la fusión es imposible con solo btrfs send/receivepero es bastante fácil de hacer manualmente, suponiendo que uno quiera combinar moviesy musicbajo un nuevo subvolumen unifiedy asumiendo que moviesy musictambién están completamente reflejados en el lado receptor:

  1. Cree un nuevo subvolumen (vacío) en el lado emisor:btrfs subvolume create unified
  2. Cámbielo a solo lectura:btrfs property set unified ro true
  3. Envíalo a la copia de seguridad:btrfs send /path/to/unified | btrfs receive /receiving/side/
  4. Desactivar solo lecturaa ambos lados, por ejemplo, btrfs property set /path/to/unified ro falsepara el lado emisor
  5. Manualmente --reflinkel contenido de musicy moviesaunified a ambos lados cp -a --reflink /path/to/music /path/to/movies /path/to/unified/
  6. Colocarambos ladosLas unifiedinstantáneas vuelven a ser de solo lectura.btrfs property set /path/to/unified ro true
  7. Cree una nueva instantánea de lectura y escritura unifiedpara interactuar, unifiedactuará como padre para futuras transferencias incrementales enambos lados.

En lugar de crear un subvolumen nuevo/vacío y enviarlo, también se podría haber comenzado en el paso 4 a partir de una instantánea musico preexistente movies. Desde el punto de vista de btrfs, lo único que importa es que los padres (futuros) de las dos partes estén conectados a través de un lado Received UUIDque apunta al otro y que ambos se lean solo en el momento de futuras transferencias.

Qué hacer para >= v5.14.2

Elsolución menos malaEs probable que siga el enfoque de la sección anterior pero, además, restablezca manualmente el Received UUIDvalor a través depython-btrfsdespués de que fue desarmado por btrfs-properties.

No haybiensolución utilizando sólo las btrfs-progsherramientas estándar. Lo más parecido a "una" solución puede ser explotar lahechoque la instantánea creada durante btrfs receivese pueda leer y escribir hasta que finalice la transferencia e intentar hacer nuestras --reflinkcopias antes de que la instantánea se configure como de solo lectura btrfs-receive. En otras palabras, explotar uncondición de carreraActualmente es la única forma de hacer esto solo con herramientas estándar btrfs-progs >=5.14.2.

Obviamente, lo que realmente se necesita es que alguien haga una solicitud de función con el proyecto btrfs para al menos permitir la fusión como era posible antes de 5.14.2 para las personas que saben lo que están haciendo.

De todos modos, una explotación de la condición de carrera probablemente se vería así: dado que todavía podemos cambiar el estado de solo lectura de una instantánea en el lado emisor, podríamos alterar dicha instantánea, por ejemplo

use moviesy vuelva a vincular la copia musicen él:

btrfs property set -f movies ro false
cp -a --reflink /path/to/music /path/to/movies/
btrfs property set -f /path/to/movies ro true   
btrfs subvolume snapshot /path/to/movies /path/to/unified_prep

Si es necesario, ahora podemos movernos por directorios y archivos internos unified_prep(pero dejar el directorio de música en paz), y cuando estémos listos:

btrfs subvolume snapshot -r /path/to/unified_prep /path/to/unified
btrfs send -p /path/to/movies /path/to/unified | btrfs receive /path/to/backups/

btrfs sendy btrfs receivedeberíanoseleccione el directorio de música adicional porque está presente tanto en movies(en el lado de envío) como unified(también en el lado del cliente). Ahora, IFF lo logramos cp -a --reflink /bkp/to/music /bkp/to/unified/en el lado receptor (!) mientras la nueva unifiedinstantánea aún se está transfiriendo y, por lo tanto, se puede leer y escribir, entonces tanto el unifiedsubvolumen del lado emisor como su instantánea del lado receptor deben ser idénticos y hemos fusionado exitosamente los subvolúmenes.

información relacionada