1. Qué puede quedar a medias tras un fallo
En el tema 32 comprobamos que escribir puede fallar incluso después de una previsión favorable. Ahora distinguiremos lo que aceptó el kernel de lo que alcanzó almacenamiento estable y de las relaciones internas que el sistema de archivos debe mantener.
Consistencia estructural: coherencia entre directorios, inodos, mapas de asignación y otros metadatos. Durabilidad: permanencia de cambios frente al tipo de fallo considerado. Atomicidad de aplicación: que una actualización lógica no quede expuesta como una mezcla incompleta.
Un archivo puede pertenecer a un sistema estructuralmente correcto y contener la versión antigua. También puede guardar bytes nuevos sin que todas las relaciones de una actualización lógica se hayan completado. Estas propiedades deben analizarse por separado.
2. Una creación cambia más que el contenido
Crear /datos/nuevo:
asignar un inodo
asignar bloques cuando sean necesarios
registrar sus referencias y tamaños
añadir la entrada del directorio
actualizar mapas y contadores pertinentes
Si las estructuras se persistieran por separado sin coordinación:
un mapa podría marcar libre un bloque ya referenciado
un directorio podría apuntar a un inodo incorrecto
podrían quedar objetos asignados sin nombres accesiblesEl orden real y los detalles dependen del formato y de sus optimizaciones. El ejemplo muestra por qué una única llamada de usuario puede requerir varias actualizaciones de estructuras internas.
Un cierre inesperado del proceso no equivale a un corte de energía del equipo: el kernel puede seguir escribiendo páginas pendientes. Por eso matar un programa o ejecutar _exit no constituye una prueba de pérdida de la caché del sistema.
3. De write a la confirmación del almacenamiento
write devuelve el progreso aceptado por esa operación, no una certificación universal de que sobrevivirá al apagado. La escritura puede completarse más tarde y producir errores diferidos. Véase write(2).
El dispositivo y su controlador deben respetar las operaciones de flush y las garantías de orden requeridas. Una caché que confirma datos que luego pierde, o un fallo físico, puede exceder las hipótesis del protocolo. No se corrige eso interpretando cualquier retorno de write como «guardado seguro».
4. Qué registra un journal
Un journal conserva registros de una transacción interna antes de completar su propagación a las ubicaciones finales. No es necesariamente un archivo de texto con intenciones de alto nivel: incluye información que permite recuperar actualizaciones del formato.
En el modelo clásico de ext4/JBD2, un registro de commit válido y persistido distingue una transacción recuperable de un conjunto incompleto. Más tarde se copian los cambios a sus ubicaciones definitivas, operación que llamaremos checkpoint.
Preparar registros → persistir transacción → commit válido
↓
copiar a ubicaciones finales
↓
liberar espacio del journal
Fallo antes de commit válido: no aplicar una transacción incompleta.
Fallo después de commit: el replay puede completar lo comprometido.El motor real maneja secuencias, integridad, revocaciones y optimizaciones adicionales, como fast commits en configuraciones compatibles. El mecanismo se describe en la documentación del journal de ext4.
5. Replay y comprobación completa son trabajos diferentes
El replay usa registros válidos del journal para completar cambios comprometidos. No intenta reconstruir por adivinación cualquier sector ilegible ni restaurar todas las versiones históricas de documentos.
Una comprobación completa recorre estructuras y contrasta sus relaciones. Puede detectar errores que no se resuelven únicamente reproduciendo el diario. Tener journal reduce la necesidad de ciertos recorridos tras una interrupción ordinaria, pero no elimina todas las revisiones o reparaciones.
Después de una recuperación puede haber un sistema estructuralmente consistente sin las últimas modificaciones que una aplicación no sincronizó. Asimismo, checksums de metadatos o del journal no deben interpretarse como verificación integral de todos los datos de usuario.
6. Los modos data=writeback, ordered y journal de ext4
| Modo | Qué pasa por el journal | Relación relevante con datos |
|---|---|---|
| data=writeback | Metadatos. | No impone el mismo orden de los datos asociados antes del commit de metadatos. |
| data=ordered | Metadatos. | Los datos asociados que requiere ese orden se escriben antes de comprometer sus metadatos. |
| data=journal | Datos y metadatos. | Los datos pasan también por el diario antes de su ubicación final. |
ordered es el modo habitual por defecto de ext4. El orden reduce determinadas exposiciones de datos incompletos ligados a metadatos nuevos, pero no hace atómica cualquier sobrescritura de un archivo existente ni todas las escrituras de una aplicación.
journal suele introducir más escritura y tiene interacciones con opciones como delayed allocation y E/S directa. No se comparan prestaciones sin declarar carga, formato y opciones. Véase la guía de administración de ext4.
El laboratorio no cambia el modo de montaje de un volumen del equipo. El simulador separa garantías de orden en una creación simplificada; no pretende reproducir todas las decisiones del controlador real.
7. El journal no es una transacción de aplicación
Actualizar dos archivos y luego borrar un tercero es una operación lógica para una aplicación. El sistema de archivos puede agrupar o dividir las modificaciones en transacciones internas diferentes. Una transacción del diario no equivale automáticamente a la transacción del negocio.
Aplicación:
actualizar saldo.txt
actualizar movimientos.txt
Tras un fallo, las estructuras del sistema pueden ser correctas,
pero la aplicación todavía debe saber si ambos cambios corresponden
a la misma operación lógica y cómo confirmar o recuperar su estado.Copias de seguridad, logs de aplicación, bases de datos y protocolos de publicación resuelven objetivos distintos. Journaling tampoco protege frente a borrar el archivo correcto por error ni reemplaza una copia externa de los datos.
8. fsync, directorios y límites del cierre
fsync solicita completar la transferencia de cambios del archivo y los metadatos necesarios según su contrato. Para hacer durable una creación o un cambio de nombre, puede ser necesario sincronizar también el directorio que contiene la entrada.
fdatasync puede evitar sincronizar metadatos que no son necesarios para recuperar los datos. No omite los metadatos imprescindibles para leerlos correctamente, como una ampliación del tamaño. Véase fsync(2).
crear nombre nuevo → escribir comprobando progreso
→ fsync del archivo
→ fsync del directorio
→ cerrar comprobando erroresclose libera la referencia y puede informar fallos diferidos; su éxito no sustituye la sincronización requerida por el protocolo. En Linux no se repite close a ciegas tras un error, pues el número de descriptor puede haberse reutilizado. Véase close(2).
Para reemplazar una versión publicada se necesita otro diseño que coordine temporal, sincronización y rename. La atomicidad de sustitución del nombre no implica por sí sola persistencia tras un corte; el tema 35 desarrollará ese patrón con detalle. Véase rename(2).
9. fsck y el verificador específico del formato
fsck es una interfaz que selecciona o coordina verificadores del tipo correspondiente. e2fsck se encarga de la familia ext2/ext3/ext4. No se ejecuta un reparador de formato basándose únicamente en el nombre de una carpeta.
$ findmnt --target ruta-existente --output TARGET,SOURCE,FSTYPE,OPTIONS
$ fsck -N -t ext4 imagen-propia.img
$ e2fsck -fn imagen-propia.img-N de fsck muestra lo que ejecutaría sin realizar la comprobación. La última orden solo corresponde a una imagen propia identificada y desmontada. Sin un destino explícito, fsck puede consultar la configuración del sistema; los ejemplos no lo invocan de esa manera. Véase fsck(8).
El chequeo contrasta referencias de bloques, estructura y conectividad de directorios, contadores de enlaces y mapas de asignación, entre otras relaciones. Reubicar un objeto recuperado en lost+found no reconstruye necesariamente su nombre anterior ni valida el significado de sus bytes.
10. Comprobar sin reparar y reparar una copia
| Opción de e2fsck | Intención en este tema |
|---|---|
| -n | Abrir en lectura y responder no a correcciones, sin añadir opciones que cambien ese contrato. |
| -f | Forzar el recorrido aunque el estado inicial parezca limpio. |
| -p | Aplicar reparaciones automáticas que la herramienta considere apropiadas; puede detenerse con errores no resueltos. |
| -y | Afirmar a las preguntas de reparación; no es el modo usado por el laboratorio. |
Las revisiones del tema se realizan con la imagen desmontada y sin procesos que la utilicen. Incluso una comprobación de lectura de un sistema activo puede dar resultados inválidos por cambios concurrentes. No se usa -n como justificación para diagnosticar con confianza una estructura que se está modificando.
Antes de una reparación real se preservan los datos y se identifica si hay errores físicos o de lectura. Reparar cambia estructuras y puede descartar relaciones que no puede recuperar. La referencia de opciones y estados es e2fsck(8).
Montar ext4 con ro puede reproducir el journal y producir escrituras de recuperación según su estado. ro,noload evita cargar el journal, pero puede exponer una vista inconsistente: no se presenta como reparación ni como receta general de rescate. Véase ext4(5).
11. Interpretar el estado de salida como combinación de bits
| Valor | Condición informada |
|---|---|
| 0 | Sin errores informados. |
| 1 | Errores corregidos. |
| 2 | El sistema debe reiniciarse según el verificador. |
| 4 | Errores sin corregir. |
| 8 | Error operativo. |
| 16 | Error de uso o sintaxis. |
| 32 | Cancelación por el usuario. |
| 128 | Error de biblioteca compartida. |
Los valores pueden combinarse: 3 tiene los bits 1 y 2; 5 tiene correcciones y errores pendientes. Un script que considera cualquier estado distinto de cero como «no hizo nada» pierde información. Tampoco debe tratar 1 y 4 como éxitos equivalentes.
if e2fsck -fn "$COPIA33"; then
RC33=0
else
RC33=$?
fi
./interpretar-fsck "$RC33"El decodificador no ordena un reinicio ni ejecuta reparaciones: solo describe el código suministrado. El contexto de la operación y sus mensajes siguen siendo necesarios.
12. Programa en C: observar los puntos de confirmación
Guarda guardar-comprobando.c. Crea registro.txt nuevo en un directorio propio, escribe el mismo contenido en dos modos y comprueba cada operación. solo-write no solicita fsync; sincronizar solicita confirmación del archivo y del directorio.
#define _POSIX_C_SOURCE 200809L
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
static int sincronizar(int fd)
{
int r;
do { r = fsync(fd); } while (r == -1 && errno == EINTR);
return r;
}
int main(int argc, char **argv)
{
if (argc != 3 || (strcmp(argv[2], "solo-write") && strcmp(argv[2], "sincronizar"))) {
fprintf(stderr, "Uso: %s directorio-propio solo-write|sincronizar\n", argv[0]);
return 2;
}
int base = open(argv[1], O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC);
if (base == -1) { perror("open directorio"); return 1; }
int fd = openat(base, "registro.txt", O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC, 0600);
int resultado = 1;
if (fd == -1) { perror("openat nuevo"); goto fin; }
const char contenido[] = "version=33\n";
size_t hechos = 0, total = sizeof contenido - 1;
while (hechos < total) {
ssize_t n = write(fd, contenido + hechos, total - hechos);
if (n == -1 && errno == EINTR) continue;
if (n <= 0) {
if (n == -1) perror("write");
else fprintf(stderr, "write no avanzó\n");
goto fin;
}
hechos += (size_t)n;
}
printf("WRITE_ACEPTADOS=%zu\n", hechos);
if (!strcmp(argv[2], "sincronizar")) {
if (sincronizar(fd) == -1) { perror("fsync archivo"); goto fin; }
puts("FSYNC_ARCHIVO=OK");
if (sincronizar(base) == -1) { perror("fsync directorio"); goto fin; }
puts("FSYNC_DIRECTORIO=OK");
} else {
puts("SIN_SOLICITUD_EXPLICITA_DE_FSYNC");
}
resultado = 0;
fin:
if (fd != -1 && close(fd) == -1) { perror("close archivo"); resultado = 1; }
if (close(base) == -1) { perror("close directorio"); resultado = 1; }
return resultado;
}Ambos modos pueden producir el mismo contenido visible al leer inmediatamente. Esa observación no demuestra que tengan la misma garantía frente a un apagado. El estado cero significa que las operaciones de ese modo finalizaron correctamente, no que solo-write haya prometido durabilidad.
Un fallo puede dejar el archivo creado o parcial. No hay reversión automática ni reemplazo de una versión anterior: O_EXCL exige un nombre nuevo. La base y sus componentes previos deben ser de confianza.
13. Programa en C: decodificar la revisión
Guarda interpretar-fsck.c. Valida un entero decimal de 0 a 255 y presenta todas las condiciones conocidas. El bit 64 no está definido en la tabla usada y se informa explícitamente si aparece.
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
if (argc != 2 || !argv[1][0]) {
fprintf(stderr, "Uso: %s codigo-0-a-255\n", argv[0]); return 2;
}
for (const char *p = argv[1]; *p; ++p) {
if (*p < '0' || *p > '9') {
fprintf(stderr, "Se requiere un entero decimal sin signo\n"); return 2;
}
}
errno = 0;
unsigned long valor = strtoul(argv[1], NULL, 10);
if (errno == ERANGE || valor > 255) {
fprintf(stderr, "Código fuera de rango\n"); return 2;
}
unsigned int c = (unsigned int)valor;
const unsigned int bits[] = {1, 2, 4, 8, 16, 32, 128};
const char *textos[] = {
"errores corregidos", "se requiere reinicio",
"errores sin corregir", "error operativo",
"uso o sintaxis incorrectos", "cancelado por el usuario",
"error de biblioteca compartida"
};
printf("CODIGO=%u\n", c);
if (!c) puts("SIN_ERRORES_INFORMADOS");
for (size_t i = 0; i < sizeof bits / sizeof bits[0]; ++i)
if (c & bits[i]) printf("BIT_%u=%s\n", bits[i], textos[i]);
unsigned int desconocidos = c & ~191u;
if (desconocidos) printf("BITS_NO_CONTEMPLADOS=%u\n", desconocidos);
if (desconocidos || (c & (4u | 8u | 16u | 32u | 128u)))
puts("DICTAMEN=NO_TRATAR_COMO_REVISION_CORRECTA");
else if (c & 2u)
puts("DICTAMEN=REQUIERE_REINICIO_SEGUN_HERRAMIENTA");
else if (c & 1u)
puts("DICTAMEN=CORREGIDO");
else
puts("DICTAMEN=SIN_ERRORES_INFORMADOS");
/* Cero indica que este decodificador pudo interpretar la entrada. */
return 0;
}El retorno del propio decodificador es cero para una entrada válida y 2 para entrada incorrecta. No propaga el estado del verificador como su retorno: sus líneas describen el código que recibió.
14. Laboratorio de imagen y copia con una inconsistencia conocida
Usa Bash en Linux, GNU coreutils, un compilador C, Python 3 y e2fsprogs. Este laboratorio no necesita montar la imagen ni usar sudo. Reserva espacio para dos imágenes de 64 MiB y los registros. Todas las alteraciones se limitan a una copia nueva de un archivo propio.
$ LAB33=$(mktemp -d "$HOME/tema33.XXXXXX")
$ cd -- "$LAB33"
$ cc -std=c11 -Wall -Wextra -Wpedantic -O2 guardar-comprobando.c -o guardar-comprobando
$ cc -std=c11 -Wall -Wextra -Wpedantic -O2 interpretar-fsck.c -o interpretar-fsck
$ mkdir solo-write sincronizado
$ ./guardar-comprobando solo-write solo-write
$ ./guardar-comprobando sincronizado sincronizar
$ ./interpretar-fsck 3
$ ./interpretar-fsck 5Crear una imagen con un archivo inicial
$ mkdir semilla
$ printf 'datos de prueba\n' > semilla/dato.txt
$ IMG33="$LAB33/original.img"
$ COPIA33="$LAB33/copia.img"
$ dd if=/dev/zero of="$IMG33" bs=1M count=64 conv=excl status=progress
$ test -f "$IMG33" && test ! -L "$IMG33"
$ mkfs.ext4 -F -L CURSO33 -d "$LAB33/semilla" "$IMG33"
$ dumpe2fs -h "$IMG33"
$ e2fsck -fn "$IMG33"
$ sha256sum -- "$IMG33" > "$LAB33/original.sha256"-d incorpora la semilla al crear el formato; no exige montar. -F solo se aplica al archivo nuevo verificado, nunca a un disco o partición. Véanse mke2fs(8) y dumpe2fs(8).
Alterar solo el contador de enlaces de la copia
$ test ! -e "$COPIA33"
$ cp --reflink=never -- "$IMG33" "$COPIA33"
$ test -f "$COPIA33" && test ! -L "$COPIA33"
$ debugfs -w -R 'set_inode_field /dato.txt links_count 7' "$COPIA33"
$ if e2fsck -fn "$COPIA33"; then RC33=0; else RC33=$?; fi
$ ./interpretar-fsck "$RC33"Continúa cada etapa solo si sus comprobaciones fueron satisfactorias. El archivo tiene una referencia de directorio, pero se fuerza el contador a 7. e2fsck debe detectar esa discordancia y, con -n, no corregirla: se espera el bit 4. debugfs -w modifica la copia directamente; la herramienta se describe en debugfs(8).
Corregir la copia y volver a consultar
$ if e2fsck -fp "$COPIA33"; then RC33=0; else RC33=$?; fi
$ ./interpretar-fsck "$RC33"
$ e2fsck -fn "$COPIA33"
$ debugfs -R 'cat /dato.txt' "$COPIA33"
$ sha256sum -c "$LAB33/original.sha256"Se mantiene -f al reparar: la alteración directa puede dejar la marca de sistema limpio y -p sin revisión forzada podría omitir el recorrido. Para esta alteración se espera una corrección con estado 1 y una revisión posterior con estado 0. Si quedan errores, se detiene el ensayo para analizar el registro; no se añade -y por rutina. El original debe mantener la misma huella.
Este caso prueba detección y reparación de una relación de metadatos. No reproduce la cronología de un apagado, no prueba replay del journal y no demuestra que cualquier daño conserve el contenido del archivo.
15. Verificador reproducible y observación de llamadas
Guarda verificar-tema33.py. Crea otro conjunto de casos nuevos, conserva salidas de las herramientas y comprueba la secuencia de estados 0 → 4 → 1 → 0. No toca las imágenes del ejercicio manual.
import hashlib
import os
from pathlib import Path
import shutil
import subprocess
import tempfile
base = Path(tempfile.mkdtemp(prefix="casos33-", dir=".")).resolve()
guardar = Path("guardar-comprobando").resolve(strict=True)
interpretar = Path("interpretar-fsck").resolve(strict=True)
def ejecutar(args, esperados=(0,), log=None):
p = subprocess.run(list(map(str, args)), capture_output=True, text=True, timeout=60)
if log:
(base / log).write_text(p.stdout + p.stderr)
assert p.returncode in esperados, (args, p.returncode, p.stdout, p.stderr)
return p
def sha(ruta):
h = hashlib.sha256()
with ruta.open("rb") as f:
for bloque in iter(lambda: f.read(1024 * 1024), b""):
h.update(bloque)
return h.hexdigest()
for modo in ("solo-write", "sincronizar"):
d = base / modo
d.mkdir(mode=0o700)
p = ejecutar([guardar, d, modo])
assert (d / "registro.txt").read_bytes() == b"version=33\n"
assert ("FSYNC_ARCHIVO=OK" in p.stdout) == (modo == "sincronizar")
ejecutar([guardar, d, modo], (1,))
for entrada in ("-1", "+1", "256", "1x", "9" * 40):
ejecutar([interpretar, entrada], (2,))
for codigo in (0, 1, 2, 3, 4, 5, 8, 16, 32, 64, 128, 255):
p = ejecutar([interpretar, codigo])
assert f"CODIGO={codigo}" in p.stdout
assert "BIT_1=" in ejecutar([interpretar, 3]).stdout
assert "BIT_2=" in ejecutar([interpretar, 3]).stdout
semilla = base / "semilla"
semilla.mkdir()
(semilla / "dato.txt").write_bytes(b"datos de prueba\n")
original, copia = base / "original.img", base / "copia.img"
fd = os.open(original, os.O_WRONLY | os.O_CREAT | os.O_EXCL, 0o600)
try:
os.ftruncate(fd, 64 * 1024 * 1024)
finally:
os.close(fd)
ejecutar(["mkfs.ext4", "-F", "-L", "CURSO33", "-d", semilla, original], log="mkfs.txt")
huella = sha(original)
ejecutar(["e2fsck", "-fn", original], log="original-fsck.txt")
assert sha(original) == huella
shutil.copyfile(original, copia)
# Solo se altera esta copia regular nueva, nunca un dispositivo ni un montaje.
assert copia.is_file() and not copia.is_symlink()
ejecutar(["debugfs", "-w", "-R",
"set_inode_field /dato.txt links_count 7", copia], log="alteracion.txt")
ejecutar(["e2fsck", "-fn", copia], (4,), log="copia-antes.txt")
ejecutar(["e2fsck", "-fp", copia], (1,), log="reparacion.txt")
ejecutar(["e2fsck", "-fn", copia], log="copia-despues.txt")
p = ejecutar(["debugfs", "-R", "cat /dato.txt", copia])
assert p.stdout == "datos de prueba\n"
assert sha(original) == huella, "El original debe permanecer idéntico"
print("Correctos: programas, estados 0/4/1/0, contenido y original conservado")
print("Registros e imágenes del laboratorio:", base)$ python3 verificar-tema33.pyOpcionalmente, strace permite comprobar que el modo sincronizar solicita dos fsync. Usa otros directorios nuevos, porque el programa no sobrescribe registro.txt.
$ mkdir traza-write traza-sync
$ strace -o "$LAB33/write.trace" -e trace=openat,write,fsync,close ./guardar-comprobando traza-write solo-write
$ strace -o "$LAB33/sync.trace" -e trace=openat,write,fsync,close ./guardar-comprobando traza-sync sincronizarLa traza confirma solicitudes y retornos, no observa por sí sola qué sobreviviría a una pérdida eléctrica. No se reinicia la máquina, no se corta energía y no se fuerzan fallos sobre sistemas montados para esta lección.
16. Simuladores de commit y estados de revisión
Interrumpir una creación en distintos puntos
Modelo clásico y simplificado de creación de un archivo con bloques nuevos. Parte de un estado consistente y supone registros válidos, almacenamiento que respeta flush y ausencia de daño físico. No representa sobrescrituras de datos existentes ni el agrupamiento real de transacciones.
Commit, checkpoint y recuperación
| Etapa alcanzada | Qué quedó preparado |
|---|
Un código puede contener varias condiciones
El panel interpreta un código suministrado; no ejecuta herramientas ni determina si una imagen está montada. No decide reparaciones basándose solo en el número.
Bits del estado de fsck
| Bit | Condición | Presente |
|---|
Compara 1, 3, 4 y 5. Después prueba 64: se informa un bit fuera de la tabla en vez de declararlo limpio. En el diario compara un corte antes y después de commit, y distingue datos de metadatos en writeback.
17. Diagnóstico y resumen
| Observación | Interpretación que conviene evitar | Qué comprobar |
|---|---|---|
| El volumen vuelve a montar tras replay. | «Todos mis últimos cambios están guardados». | Qué sincronizó la aplicación y qué datos verifica. |
| e2fsck devuelve 1. | «No pudo trabajar porque no devolvió cero». | Las correcciones realizadas y la revisión posterior. |
| e2fsck devuelve 5. | «Todo está corregido». | También está presente el bit de errores pendientes. |
| Hay EIO o sectores ilegibles. | «Repetir reparaciones resolverá el soporte físico». | Estado del almacenamiento y preservación de una copia antes de escribir más. |
| El contenido se lee bien inmediatamente. | «La lectura prueba durabilidad frente a un corte». | Protocolo de sincronización y alcance del ensayo. |
- Consistencia estructural, durabilidad y atomicidad lógica son garantías distintas.
- El journal diferencia transacciones incompletas y comprometidas; checkpoint propaga lo comprometido.
- Los modos de ext4 cambian la relación entre datos y diario.
- ordered no convierte cualquier actualización de aplicación en una transacción atómica.
- fsync, sincronización del directorio y tratamiento de errores forman parte del protocolo.
- fsck selecciona verificadores; e2fsck entiende estructuras de la familia ext.
- La revisión se realiza con el objeto del ensayo identificado y desmontado.
- Los estados pueden combinar bits; se conserva el código real y el registro.
- Una reparación de copia no equivale a recuperar versiones históricas ni a reparar hardware.
18. Preguntas de repaso y práctica
1. ¿Un sistema consistente tiene siempre la última versión del documento?
No. Puede tener relaciones internas correctas y conservar una versión antigua de los datos.
2. ¿write exitoso significa que el dato sobrevivirá a un corte?
No por sí solo. Informa progreso aceptado, con las garantías de esa operación.
3. ¿Matar un proceso equivale a apagar el equipo?
No. El kernel y sus cachés siguen funcionando y pueden persistir cambios pendientes.
4. ¿El journal es solo un texto de intenciones?
No. Registra información transaccional del formato que permite recuperar actualizaciones bajo su protocolo.
5. ¿Commit y checkpoint son el mismo punto?
No. Commit identifica una transacción comprometida; checkpoint propaga los cambios a las ubicaciones finales.
6. ¿Se reproduce cualquier transacción que tenga algunos registros?
No. El modelo requiere una transacción válida y comprometida; no se aplica un conjunto incompleto como si fuera completo.
7. ¿Qué orden distingue a data=ordered?
Ordena los datos asociados requeridos antes de comprometer los metadatos correspondientes; no journaliza todos los datos de usuario.
8. ¿data=writeback ofrece el mismo orden de datos?
No. El modo no impone esa misma precedencia antes del commit de metadatos.
9. ¿data=journal elimina la necesidad de fsync?
No. El modo de diario no sustituye una solicitud de confirmación de persistencia cuando el protocolo de aplicación la necesita.
10. ¿Una transacción del journal es una transacción de la aplicación?
No necesariamente. Los límites internos no tienen por qué coincidir con una actualización lógica de varios archivos.
11. ¿fsync del archivo cubre necesariamente el nombre recién creado?
No. La entrada de directorio puede requerir sincronizar también su directorio.
12. ¿close es un reemplazo de fsync?
No. Puede informar errores y libera la referencia, pero no sustituye el protocolo de sincronización.
13. ¿fsck es el formato ext4?
No. Es una interfaz para seleccionar o coordinar verificadores; e2fsck es el específico usado aquí para ext.
14. ¿Qué indican -f y -n en la comprobación del laboratorio?
-f fuerza la revisión y -n evita aplicar las correcciones propuestas en el contrato utilizado.
15. ¿Un chequeo de lectura sobre un sistema activo da siempre resultados válidos?
No. Los cambios concurrentes pueden invalidar sus conclusiones; el ensayo usa imágenes desmontadas.
16. ¿Qué expresa un estado 3?
Combina 1 y 2: errores corregidos y condición de reinicio informada por la herramienta.
17. ¿Qué expresa un estado 5?
Combina correcciones con errores sin corregir; no se considera una revisión completamente resuelta.
18. ¿Qué cambia debugfs en el ejercicio?
Solo el contador de enlaces del archivo conocido en una copia regular nueva. El original se verifica por huella.
19. ¿La secuencia 0/4/1/0 demuestra replay después de un corte?
No. Demuestra detección, corrección y nueva revisión de una discordancia introducida de forma controlada.
20. ¿Journaling reemplaza una copia de seguridad?
No. No conserva necesariamente versiones anteriores ni protege de todo borrado, corrupción o fallo físico.
Para practicar
- Separa tres ejemplos de consistencia, durabilidad y atomicidad lógica.
- Dibuja las relaciones de una creación que deben mantenerse coherentes.
- Compara un corte antes de commit con uno durante checkpoint en el simulador.
- Analiza por qué escribir dos archivos no se transforma automáticamente en una transacción única.
- Compara los dos modos de guardar-comprobando mediante strace.
- Ejecuta el laboratorio y conserva las salidas de revisión y reparación.
- Comprueba que original.img conserva su huella mientras se altera y repara copia.img.
- Decodifica manualmente 0, 1, 3, 5, 12 y 128.
- Explica por qué no se sustituye todo estado distinto de cero por un mismo mensaje.
- Describe qué información falta para decidir una reparación cuando solo conoces el código.
- Distingue qué comprueba el verificador y qué no prueba sobre pérdida eléctrica.
- Plantea cómo anunciaría una aplicación que una escritura quedó pendiente de confirmación.
En el tema 34 estudiaremos copy-on-write y snapshots. En el tema 35 volveremos a C para construir un protocolo de actualización mediante temporal, fsync, rename y sincronización del directorio.