Para hacer el dump, es decir, para mandar la copia de seguridad de Kfs al servidor de fichero, tenemos que ir enviando bloque a bloque la partición que Kfs esta usando.
El procedimiento de conseguir los bloques de disco uno a uno y mandarlos es secuencial. Lo primero que se hace es establecer el tamaño de la partición que se va a mandar y dividir eso entre el tamaño de bloque que esta usando Kfs. Una vez hecho esto ya sabemos cuantos bloques tendremos que mandar al servidor de backups para completar la copia de seguridad.
Los problemas vienen a la hora de hacer un servicio de backups que no interrumpa el servicio de Kfs. Para no interrumpirlo se debe dejar que mientras se están mandando uno a uno todos los bloques de la partición de Kfs al servidor, otras aplicaciones puedan pedir a dicho Kfs ficheros y este se los debe servir sin notarse demasiado que se esta haciendo un backup.
Con el planteamiento anterior, aparecen problemas de incoherencia temporal del backup al dejar escribir bloques mientras se están mandando a copiar. Por ejemplo, si tenemos una partición con 10000 bloques , el proceso de dump esta mandando el 4000 y en ese momento se escribe el 5000. La copia final no tendrá el estado que tenia cuando se inicio el backup, sino que estará modificada en algunos bloques. Eso es la incoherencia temporal de los backups.
Para resolver el problema se ha implementado el servicio de backups en Kfs de tal forma que se deja leer en cualquier bloque en cualquier instante de tiempo durante el backup. En cuanto a la escritura, se sigue el criterio de dejar solamente escribir los bloques que ya han sido mandados al servidor de backups y que por tanto ya han sido copiados. En el ejemplo anterior la petición de escritura del bloque 5000 no seria atendida ya que el proceso de dump va por el bloque 4000.
Para resolver ese problema ha habido que modificar la estructura de datos IOBUF, que es como se le llama a los bloques del dispositivo de almacenamiento (disco duro) , cuando están en memoria. Dicha estructura de datos estaba definida de la siguiente forma:
struct Iobuf
{
QLock;
Device dev;
Iobuf *next; /* for hash */
Iobuf *fore; /* for lru */
Iobuf *back; /* for lru */
char *iobuf; /* only active while locked */
char *xiobuf; /* "real" buffer pointer */
long addr;
int flags;
};
En el campo flags , tenemos un numero entero que nos da información a cerca del Iobuf, como por ejemplo, si esta modificado, si se pidió para escritura, si se pidió para lectura, etc...
Los flags permitidos son:
enum //POSIBLES FLAGS DE IOBUF
{
Bread = (1<<0), /* read the block if miss */
Bprobe = (1<<1), /* return null if miss */
Bmod = (1<<2), /* set modified bit in buffer */
Bimm = (1<<3), /* set immediate bit in buffer */
Bres = (1<<4), /* reserved, never renammed */
};
La modificación que se ha implantado es que los Iobuf tienen otro posible valor en su campo flags. Ese flags ha sido llamado Bdump, nos indica si esta activo, que todavía dicho Iobuf no se ha copiado y si esta desactivado se considera que el bloque al que corresponde el Iobuf ya fue copiado.
El nuevo flag introducido solo es considerado por el servicio de backups dentro de Kfs, es decir que si no hay un proceso de Dump en curso, el flag de Bdump no se considera.
Durante el proceso de Dump, se traen bloques de disco a memoria, al hacerlo tenemos que comprobar si se debe activar, en el Iobuf correspondiente al bloque, el flag de BDUMP.
Al traer un bloque a memoria se le puede poner o no la marca de Bdump, dependiendo de si su numero de bloque es mayor o menor que el del ultimo que se ha copiado. Si es menor no se le pone la marca de Bdump porque ya esta copiado y si es mayor si ha de ponérsele para indicar que todavía no le ha llegado su turno para ser copiado.
Durante un proceso de Dump, Kfs puede recibir una petición de escritura de un bloque de datos. Esta operación no se tratara si el bloque que se quiere escribir ya fue mandado al servidor de backups, sin embargo, si dicho bloque todavía no ha sido copiado necesitamos hacer que se copia de forma rápida para que la petición de escritura de ese bloque no se demore demasiado.
Este problema puede suponer mucho tiempo de espera y por lo tanto causar grandes demoras en el servicio. Por ejemplo, si tenemos una partición de 1000 bloques y vamos copiando el 10. Entonces en ese momento llega una petición de escritura del bloque 999, la cual se quedara parada hasta que el servicio de backups llegue a mandar dicho bloque al servidor de backups.
Como se observa en el ejemplo anterior, es necesario eliminar ese problema para mejorar infinitamente el servicio. Por este hecho, se ha implementado un mecanismo basado en que si un bloque es pedido para escritura y todavía no forma parte de los bloques copiados al backup en curso, se le debe dar prioridad y mandar a copiar en el backup para que inmediatamente despues cualquier aplicacion pueda escribir o modificar ese bloque.
El mecanismo de copiar bloques requeridos para escritura, los cuales todavía no hayan sido copiados al backup, se le ha llamado mecanismo de urgencia. En ese mecanismo tenemos una estructura de datos que es una cola. En ella se van guardando los números de bloques que se piden para escritura y que todavía no se han copiado. Tenemos un proceso que continuamente esta mirando si hay bloques en la cola, en caso de que haya deben ser copiados al backup lo mas rápido posible, con prioridad sobre los que se están copiando en el curso normal de backup del sistema de ficheros. De esta forma la espera comentada en el ejemplo anterior es reducida a valores ínfimos. Véase Figura
y apartado 4.3.1
En cuanto a la parte de restore. El proceso es mucho mas sencillo y por tanto también su implementación en Kfs.
Ahora pasamos a detallar cada uno de los servicios de backups: Dump y Restore.