Está en la página 1de 103

Diseño de Sistemas

Operativos

Implementaciones de
Sistemas de Ficheros

(Superbloque)

EMILIO GONZÁLEZ DÍAZ


IGNACIO SOLINIS CAMALICH
¿Qué es un Sistema de Ficheros?
 Es el método mediante el cual se almacena
la información en el disco duro.
 Almacena y Gestiona los datos que los
usuarios tienen guardados en los
dispositivos de almacenaje.
 Asegura que los datos que se obtienen son
idénticos a los que se almacenaron
originalmente.
 Crea y gestiona información sobre los
ficheros y sobre sí mismo.

2
Historia de los SF en Linux
 La primera versión del sistema de ficheros
de Linux estaba basada en el sistema de
ficheros de Minix. Muy limitado.
 Más tarde entró en escena el sistema de
ficheros extendido (Extfs). Resultados
insatisfactorios de rendimiento.
 Por esto, en 1994 surgió el segundo sistema
de ficheros extendido (Ext2fs). Alta eficiencia
y robustez.

3
Historia de los SF en Linux
 Durante los últimos años, el Ext2 ha sido el sistema
de ficheros más extendido entre los sistemas Linux.
 Linux se usa cada vez más en entornos servidor,
llevando a Ext2 al límite de sus posibilidades.
 Los requisitos más comunes de hoy en día son:
• Necesidad de recuperación rápida de caídas del sistema
• Rendimiento alto en operaciones de Entrada / Salida (I/O)
• Necesidad de almacenar Terabytes de información

4
Historia de los SF en Linux
 Para solventar estas carencias, aparecen entre
otros, los sistemas de ficheros Ext3, ReiserFS, XFS
y JFS.
 Además de cumplir con los requisitos especificados
más arriba, todos ellos soportan el sistema
“Journaling”.
 Un sistema de ficheros Journaling
• Simplifica los reinicios
• Reduce problemas derivados de la fragmentación
• Acelera las operaciones de E/S

5
El sistema de ficheros en Linux
 Los sistemas de
ficheros se crean en
particiones.
 Los sistemas basados
en Unix utilizan un
sistema jerarquizado
compuesto por:
• Ficheros
• Directorios, los cuales
pueden contener tanto
ficheros como directorios

6
El sistema de ficheros en Linux
 Los sistemas de ficheros se montan
mediante el comando “mount”.
 Mount se ejecuta automáticamente en
el proceso de arranque del sistema.
 El listado de sistemas de ficheros a
montar se almacena en el fichero
/etc/fstab (filesystem table)

7
El sistema de ficheros en Linux
 El listado de los sistemas de ficheros
montados en el sistema se almacena en
el fichero /etc/mtab (mount table)
 Los sistemas de ficheros se desmontan
automáticamente con el apagado del
sistema.

8
Criterios de Selección
 ESTABILIDAD Y FIABILIDAD – Con respecto a la
pérdida de datos
 CAPACIDAD (“lo capaz que es”) – Requisitos de
rendimiento
 CAPACIDAD (“la capacidad que tiene”) – Los límites del
sistema de ficheros
 MANTENIMIENTO – El tipo de mantenimiento que
necesita
 AFINAMIENTO (tuning) – Facilidad de configuración y
afinamiento del sistema
 SOPORTE – Por parte del grupo de desarrollo

9
Sistema Virtual de Archivos (VFS)
 Los distintos SO suelen usar su propio
Sistema de Ficheros

 Esto complica la compartición de datos en un


disco duro entre distintos SO

 Linux ofrece soporte para distintos Sistemas


de Ficheros como EXT2, Minix, FAT…

10
Sistema Virtual de Archivos (VFS)
 Los procesos necesitan
de un acceso uniforme a
los datos, sin
preocuparse de qué
Sistema de Ficheros se
trata
 El VFS es la interfaz
entre las llamadas al
sistema y la gestión de
archivos
 Las llamadas se dirigen
al VFS, que redirige la
petición al módulo que
gestiona el archivo

11
Segundo sistema de ficheros
extendido (Ext2)

12
Definición de conceptos
 Un BLOQUE lógico es la unidad más pequeña de
almacenamiento (se mide en bytes)
 Un VOLUMEN lógico es una PARTICIÓN de disco.
 Las particiones están divididas en bloques.
 La Asignación de bloques es un método donde el
sistema de ficheros asigna un bloque cada vez.
 Un puntero a cada bloque se mantiene y almacena
en el sistema.

13
Definición de conceptos
 La FRAGMENTACIÓN INTERNA ocurre cuando un
fichero no ocupa por completo un bloque.
 Ej. Si tenemos un fichero de 10K y un tamaño de
bloque de 8K, el sistema de ficheros asignará dos
bloques para alojar el fichero, pero 6K del segundo
bloque se desaprovecharán. Nótese que a mayor
tamaño de bloque mayor será el espacio
desperdiciado.
 La FRAGMENTACIÓN EXTERNA ocurre cuando los
bloques lógicos no se encuentran contiguos. Este
tipo de fragmentación produce un bajo rendimiento.

14
Definición de conceptos
 Un Extent es un conjunto de bloques contiguos.
 Cada Extent se describe como una tripleta
• Offset del fichero, que nos dice a qué bloque
lógico corresponde dentro del fichero.
• El número del primer bloque del extent.
• El tamaño del extent (medido en bloques).

15
Definición de conceptos
 Los extent se asignan y se monitorizan como una
unidad independiente (forman un todo) por lo que un
único puntero monitorizará un grupo de bloques.
 La técnica de asignación de extents es un método
más eficiente para ficheros grandes que la técnica
de asignación de bloques.

16
Ejemplo del uso de
extents:
 El fichero requiere 18 bloques
 El sistema de ficheros realiza
una asignación de:
• 1 extent de 8 bloques.
• 2 extent de 5 bloques.

17
Definición de conceptos
 Lista de Control de Acceso (Access Control List –
ACL): Especifica los derechos de acceso para
cualquier usuario específico o combinación de
usuarios.
 Los METADATOS son las estructuras de datos
internas del sistema de ficheros
 Los metadatos incluyen:
• La fecha y hora.
• Información sobre el propietario.
• La lista de control de acceso (ACL).
• El tamaño del fichero…

18
Definición de conceptos
 Un I-NODE almacena toda la información sobre un
fichero excepto la información del fichero
propiamente dicha (es un Metadato).
 Un i-node consume también bloques.
 Un i-node contiene:
• Los permisos del fichero.
• El tipo del fichero.
• El número de links (enlaces) al fichero.

19
Definición de conceptos
 Cada i-node tiene un número único que los
identifica.
 Un DIRECTORIO es un tipo específico de fichero
que contiene punteros a otros ficheros.
 El i-node de un fichero directorio simplemente
contiene el número identificador de los i-nodes que
contiene además de los permisos, etc.

20
Características del Ext2
 Ext2 está presente sobre un dispositivo físico
(disquete, disco duro...)
 Seleccionar el tamaño de bloque en la creación del
sistema de ficheros (desde 1.024 a 4096 bytes).
Esto dependerá del tamaño medio esperado de los
ficheros.
 En la creación del sistema de ficheros también se
puede elegir el número de inodes que se van a
permitir para una partición.

21
Características del Ext2
 El sistema de ficheros coloca los bloques de disco
en grupos.
 Cada bloque incluye bloques de datos e i-nodes
almacenados en pistas adyacentes.
 Gracias a esta estructura, ficheros almacenados en
un único grupo de bloques pueden ser accedidos en
un menor tiempo promedio de búsqueda en disco.

22
Características del Ext2
 El sistema de ficheros preasigna bloques de datos
en disco a ficheros regulares antes de ser usados.
 Cuando el fichero aumenta de tamaño, varios
bloques ya están reservados en posiciones
adyacentes (reduce la fragmentación externa).
 Soporta chequeos automáticos de consistencia en el
inicio del sistema (e2fsck).

23
Características del Ext2

 Borrado Lógico. Permite a los usuarios la


recuperación sencilla, si es necesario, del contenido
de un fichero previamente eliminado.

 Compatibilidad tanto con el SVR4 (Unix System V


Release 4) y con la semántica BSD.

24
Estructura Física de un SF EXT2

 Está formado por una colección de bloques


secuenciales
 El sector de boot contiene el código necesario
para cargar el núcleo en el arranque del sistema.
 El sistema de ficheros es manejado globalmente
como una serie de Grupos de Bloques (GB)
25
Estructura Física de un SF EXT2

 Los GB ayudan a mantener la información relacionada


físicamente cercana en el disco, simplificando las tareas de
gestión.
 Todos los grupos de bloques tienen el mismo tamaño y están
colocados de manera secuencial.
 De esta manera se reduce la fragmentación externa.

26
Estructura Física de un SF EXT2

Cada GB se descompone a su vez en distintos elementos:


 Una copia del superbloque
 Una copia de la tabla de descriptores de grupo
 Un bloque de bitmap para los bloques
 Un bloque de bitmap para los i-nodos
 Una tabla de i-nodos
 Bloques de datos

27
El Superbloque
 Contiene las informaciones de control del sistema de
archivos
 Se sitúa al principio del sistema de archivos en
disco. Se encuentra en el offset fijo 1024 del disco y
ocupa 1024 bytes
 El superbloque contiene una descripción del tamaño
y forma del sistema de archivos
 Existe una copia del mismo en cada GB
DISCO
SECTOR BOOT SUPERBLOQUE

0 1024 2048
28
Estructura del superbloque
 Es almacenado en una estructura
denominada ext2_super_block, definida en
el archivo <linux/ext2_fs.h>
 Hay tres tipos de información almacenada en
la estructura del superbloque:
• Parámetros fijos
• Parámetros del sistema modificables
• Información sobre el estado del sistema de
ficheros

29
Parámetros fijos del superbloque
Tipo Campo Descripción
_u32 s_blocks_count Número total de bloques
_u32 s_inodes_count Número total de i-nodos
_u32 s_log_block_size Tamaño lógico de los bloques en bytes (0 -> 1KB, 1 -> 2KB, 2 -> 4KB...)
_u32 s_first_data_block Número del primer bloque útil de datos. Define el bloque que ocupará el
superbloque.
_u32 s_blocks_per_group Número de bloques por grupo.
_u32 s_inodes_per_group Número de i-nodos por grupo
_u32 s_creator_os Identificador del sistema operativo bajo el cual se ha creado el sistema de
archivos. Los valores 0, 1 y 2 representan a los sistemas LINUX, HURD y
MASIX respectivamente.
_u32 s_log_frag_size Tamaño lógico de los fragmentos en bytes. Debe ser igual al tamaño de
bloque, ya que la opción de la fragmentación en bloque no está aún
implementada.
_u32 s_frags_per_group Número de fragmentos por grupo
_u16 s_magic Firma del sistema de archivos. Ext2 es 0xEF53.

30
Parámetros modificables

 Existen parámetros que pueden ser modificados por


el usuario durante el funcionamiento del SF

_u32 s_r_blocks_count Número de bloques reservados al superusuario. Permiten almacenar bloques al


superusuario cuando los demás no tienen bloques disponibles.
_u16 s_def_resuid Identificador del usuario que puede usar los bloques reservados al superusuario
de modo predeterminado
_u16 s_def_resgid Identificador del grupo que puede usar los bloques reservados al superusuario
de modo predeterminado

31
Parámetros de Información sobre el
estado del sistema de ficheros
 El sistema va modificando sus valores en función del
estado en que se encuentre
_u32 s_free_blocks_count Número de bloques libres
_u32 s_free_inodes_count Número de i-nodos libres
_u32 s_mtime Fecha del último montaje del sistema de archivos
_u32 s_wtime Fecha de la última escritura del superbloque
_u16 s_mnt_count Número de montajes del sistema de archivos
_s16 s_max_mnt_count Número máximo de montajes. Cuando s_mnt_count es igual a este valor,
se muestra el mensaje de aviso «maximal mount count reached, running
e2fsck is recommended».
_u16 s_state Estado del sistema de archivos. Si el valor es 0, el sistema está montado
o fue incorrectamente desmontado, si es 1 el sistema está desmontado
correctamente y si es 2, existen errores.
_u16 s_errors Define qué comportamiento que debe tener del sistema de archivos en
caso de errores

32
Estructura del descriptor de grupo
 Cada grupo de bloques, contiene una copia del
superbloque, así como una copia de descriptores de
grupos
 Estos descriptores contienen las coordenadas de las
estructuras de control presentes en cada grupo
 Los descriptores de grupo se colocan todos juntos,
formando así la tabla de descriptores de grupo
 En el fichero de cabecera linux/ext2_fs.h se encuentra
la definición de la estructura ext2_group_desc, que
define el descriptor de grupo

33
Estructura del descriptor de grupo
_u32 bg_block_bitmap Dirección del bloque de bitmap para los bloques de este grupo
_u32 bg_inode_bitmap Dirección del bloque de bitmap para los i-nodos de este grupo
_u32 bg_inode_table Dirección del primer bloque de la tabla de i-nodos en este grupo
_u16 bg_free_blocks_count Número de bloques libres en este grupo
_u16 bg_free_inodes_count Número de i-nodos libres en este grupo
_u16 bg_used_dirs_count Número de directorios asignados en este grupo
_u16 bg_pad No utilizado
_u32[2] bg_reserved Campo reservado para futura extensión

34
Estructura del descriptor de grupo
 Todos estos elementos son creados en el momento de
creación del sistema de ficheros
 bg_block_bitmap y bg_inode_bitmap contienen el
número de bloque del bitmap de asignación de bloques y
del bitmap de asignación de i-nodos respectivamente
 Los campos bg_free_blocks_count,
bg_free_inodes_count y bg_used_dirs_count
mantienen información estadística sobre el uso de estos
recursos en el GB

35
Tratamiento de errores en EXT2
 EXT2 no realiza un tratamiento del error propiamente dicho

 Cualquier error ha de ser identificado por el kernel, quien debe lanzar


programas de chequeo como e2fsck, debugfs ó EXT2ED

 Estos programas consultan s_state (bit limpio), que está a 0 con el


sistema montado y a 1 cuando se desmonta

 Un error común es el apagado del sistema sin desmontar los SF


montados
• Causa que el s_state sea 0 en el próximo arranque -> el kernel lanza fsck

 s_errors define el comportamiento del sistema en caso de darse un


error:
• 1 -> se ignora el error
• 2 -> el kernel remontará como sólo lectura
• 3 -> se entra en un kernel panic

36
Tratamiento de errores en EXT2
 Un error común es el apagado del sistema sin
desmontar los SF montados
• Causa que el s_state sea 0 en el próximo arranque ->
el kernel lanza fsck
 El chequeo es necesario, ya que se podían
estar realizando escrituras en disco en el
momento del apagado
• Metadatos o datos de usuario
 s_mnt_count, s_max_mnt_count, s_lastcheck
y s_checkinterval, son campos que pueden
comprobar estos programas, para lanzar
revisiones automáticas
37
Operaciones vinculadas al SF
 Las operaciones sobre el superbloque para EXT2 se implementan en
el archivo fuente fs/ext2/super.c
 El VFS realiza la correspondencia entre las funciones llamadas por
procesos y la específica para ese SF. P. ej.: ext2_write_inode ->
write_inode
 El siguiente array de punteros a funciones, indica esta
correspondencia

static struct super_operations ext2_sops = {


ext2_read_inode,
NULL,
ext2_write_inode,
ext2_put_inode,
ext2_put_super,
ext2_write_super,
ext2_statfs,
ext2_remount
};

38
EXT2_PUT_SUPER
 ¿Para qué sirve?
• Implementa put_super para el SF EXT2
• Llamada por el VFS
• Se utiliza cuando un SF se desmonta

 Modo de funcionamiento
• Marca los bloques modificados para actualizarlos a disco
desde la memoria intermedia (mark_buffer_dirty)
• Libera memorias intermedias y punteros, tanto usadas por
descriptores como por los mapas de bits (de i-nodos y
bloques)
• Libera memoria intermedia que contiene al superbloque
• La función usada para liberar memoria es brelse y para
liberar punteros kfree_s
39
EXT2_PUT_SUPER
void ext2_put_super (struct super_block *sb)
{
int db_count;
int i;

/* Se indica que hay que actualizar el SB en disco */


if (!(sb->s_flags & MS_RDONLY)) {
sb->u.ext2_sb.s_es->s_state = sb->u.ext2_sb.s_mount_state;
mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1);
}

/* Libera las memorias que contienen los descriptores del FS */


db_count = sb->u.ext2_sb.s_db_per_group;
for (i = 0; i < db_count; i++)
if (sb->u.ext2_sb.s_group_desc[i])
brelse (sb->u.ext2_sb.s_group_desc[i]);

/* Libera los punteros a esas memorias */


kfree_s (sb->u.ext2_sb.s_group_desc,
db_count * sizeof (struct buffer_head *));

40
EXT2_PUT_SUPER
/* Libera las memorias asociadas a los bitmaps de i-nodos */
for (i = 0; i < EXT2_MAX_GROUP_LOADED; i++)
if (sb->u.ext2_sb.s_inode_bitmap[i])
brelse (sb->u.ext2_sb.s_inode_bitmap[i]);

/* Libera las memorias asociadas a los bitmaps de bloques */


for (i = 0; i < EXT2_MAX_GROUP_LOADED; i++)
if (sb->u.ext2_sb.s_block_bitmap[i])
brelse (sb->u.ext2_sb.s_block_bitmap[i]);

/* Libera la memoria que contiene el superbloque */


brelse (sb->u.ext2_sb.s_sbh);

return;
}

41
EXT2_PARSE_OPTIONS
 ¿Para qué sirve?

• Hace un análisis de las opciones de montaje pasadas por parámetro

 Modo de funcionamiento
• Comprueba si se han pasado opciones
• Comprueba cada una de las opciones pasadas por parámetro
• Devuelve:
• 1 si es correcto
• 0 en caso contrario

42
EXT2_SETUP_SUPER
 ¿Para qué sirve?
• Inicializa el descriptor del SB a partir del SB del disco
• Se llama cuando se (re)monta el SF

 Modo de funcionamiento
• Comprueba que la versión del SB no es mayor que la máxima
• Comprueba que la última vez se desmontó adecuadamente
• Si no, se recomienda ejecutar e2fsck
• Se incrementa el número de veces que ha sido montado el SF
• Se actualiza la fecha de modificación
• Se indica la necesidad de actualización a disco

43
EXT2_SETUP_SUPER
static void ext2_setup_super (struct super_block * sb,
struct ext2_super_block * es)
{
/* Si la versión de SB > máxima versión permitida: error */
if (es->s_rev_level > EXT2_MAX_SUPP_REV) {
printk ("EXT2-fs warning: revision level too high,
forcing read/only mode\n");
sb->s_flags |= MS_RDONLY;
}

/* Si es escribible */
if (!(sb->s_flags & MS_RDONLY)) {
/* Adecuadamente desmontado la última vez? */
if (!(sb->u.ext2_sb.s_mount_state & EXT2_VALID_FS))
printk ("EXT2-fs warning: mounting unchecked fs,
running e2fsck is recommended\n");

/* Se indica que el sistema ha sido montado */


es->s_state &= ~EXT2_VALID_FS;

44
EXT2_SETUP_SUPER
/* Se incrementa el nº de veces que se ha montado el FS */
if (!es->s_max_mnt_count)
es->s_max_mnt_count = EXT2_DFL_MAX_MNT_COUNT;
es->s_mnt_count++;

/* Se actualiza la fecha de modificación */


es->s_mtime = CURRENT_TIME;

/* Se indica que hay que actualizar en disco */


mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1);
sb->s_dirt = 1;

/* Opciones de depuración y chequeo */


if (test_opt (sb, DEBUG))
printk ("[EXT II FS %s, %s, bs=%lu, fs=%lu,
gc=%lu, bpg=%lu, ipg=%lu, mo=%04lx]\n",
EXT2FS_VERSION, EXT2FS_DATE,
sb->s_blocksize,sb->u.ext2_sb.s_mount_opt);
}
}

45
EXT2_CHECK_DESCRIPTORS
 ¿Para qué sirve?
• Comprueba los descriptores de grupo leídos del disco

 Modo de funcionamiento:
• Comprueba, para cada descriptor:
• Bloques de bitmap (i-nodo y bloque)
• Tabla de i-nodos
• Están contenidos en el grupo
• Devuelve:
• 1 si no hay errores
• 0 si hay algún error

46
EXT2_CHECK_DESCRIPTORS
static int ext2_check_descriptors (struct super_block * sb)
{
int i;
int desc_block = 0;
unsigned long block = sb->u.ext2_sb.s_es->s_first_data_block;
struct ext2_group_desc * gdp = NULL;

ext2_debug ("Checking group descriptors");

/* Se recorren todos los descriptores de grupos */


for (i = 0; i < sb->u.ext2_sb.s_groups_count; i++)
{
/* Se selecciona un descriptor de Grupo de Bloques */
if ((i % EXT2_DESC_PER_BLOCK(sb)) == 0)
gdp = (struct ext2_group_desc *)
sb->u.ext2_sb.s_group_desc[desc_block++]->b_data;

47
EXT2_CHECK_DESCRIPTORS
/* ¿Bitmap de bloque contenido en el grupo? */
if (gdp->bg_block_bitmap < block ||
gdp->bg_block_bitmap >= block +
EXT2_BLOCKS_PER_GROUP(sb)){
ext2_error (sb, "ext2_check_descriptors",
"Block bitmap for group %d“ " not in group (block
%lu)!", i, (unsigned long) gdp->bg_block_bitmap);

return 0;
}
/* ¿Bitmap de i-nodo contenido en el grupo? */
if (gdp->bg_inode_bitmap < block ||
gdp->bg_inode_bitmap >= block +
EXT2_BLOCKS_PER_GROUP(sb)){
ext2_error (sb, "ext2_check_descriptors",
"Inode bitmap for group %d"
" not in group (block %lu)!",i, (unsigned long)
gdp->bg_inode_bitmap);

return 0;
}

48
EXT2_CHECK_DESCRIPTORS
/* tabla de i-nodos está contenida en el grupo? */
if (gdp->bg_inode_table < block ||
gdp->bg_inode_table + sb->u.ext2_sb.s_itb_per_group >=
block + EXT2_BLOCKS_PER_GROUP(sb))
{
ext2_error (sb, "ext2_check_descriptors",
"Inode table for group %d"
" not in group (block %lu)!",
i, (unsigned long) gdp->bg_inode_table);
return 0;
}
block += EXT2_BLOCKS_PER_GROUP(sb);
gdp++;
}

/* Si no hubo errores, se devuelve 1 */


return 1;
}

49
EXT2_READ_SUPER
 ¿Para qué sirve?
• Lee del disco el SB del SF a montar
• Se llama al montar un SF
• Devuelve un puntero al contenido del SB o NULL
 Modo de funcionamiento
• Comprobamos las opciones de montaje (parse_options)
• Se lee el SB desde el disco y se guarda en memoria
• Se comprueba su validez (s_magic) y otras características
• Comprobamos si el modo (lect/esc) esta permitido
• Inicializa y comprueba el tamaño del bloque
• Incorrecto: se libera y se lee de nuevo el SB
• Inicializa algunos campos del SB
• Comprobamos que se va a montar un EXT2 (número mágico)

50
EXT2_READ_SUPER
 Modo de funcionamiento (II)
• Comprobamos la correctitud de los cálculos:
• Tamaño de Bloque
• Tamaño de Fragmento
• Bloques por grupo
• Fragmentos por grupo
• I-nodo por grupo
• Leemos y Comprobamos los descriptores de grupo
• Usamos la función ext2_check_descriptors
• Inicializamos algunos campos con sus valores por defecto
• Intentamos leer el nodo raiz en s_mounted
• Se inicializa el SB llamando a ext2_setup_super

51
EXT2_READ_SUPER
struct super_block * ext2_read_super (struct super_block * sb,
void * data, int silent) {

struct buffer_head * bh;


struct ext2_super_block * es;
unsigned long sb_block = 1;
unsigned short resuid = resgid = EXT2_DEF_RESUID;
unsigned long logic_sb_block = 1;
kdev_t dev = sb->s_dev;
int db_count, i, j;

sb->u.ext2_sb.s_mount_opt = 0;
set_opt (sb->u.ext2_sb.s_mount_opt, CHECK_NORMAL);

/* Se analizan las opciones de montaje: parse_options */


if (!parse_options ((char *) data, &sb_block, &resuid, &resgid,
&sb->u.ext2_sb.s_mount_opt)) {
sb->s_dev = 0;
return NULL;
}

52
EXT2_READ_SUPER
MOD_INC_USE_COUNT;
lock_super (sb);
set_blocksize (dev, BLOCK_SIZE);

/* Se lee el superbloque desde el disco */


if (!(bh = bread (dev, sb_block, BLOCK_SIZE))) {
sb->s_dev = 0;
unlock_super (sb);
printk ("EXT2-fs: unable to read superblock\n");
MOD_DEC_USE_COUNT;
return NULL;
}

/* Se guarda el SB en “es”  SB de disco


y en “sb->u.ext2_sb.s_es”  SB en memoria*/
es = (struct ext2_super_block *) bh->b_data;
sb->u.ext2_sb.s_es = es;
sb->s_magic = es->s_magic;

53
EXT2_READ_SUPER
/* Se verifica la validez del superbloque */
if (sb->s_magic != EXT2_SUPER_MAGIC) {
if (!silent)
printk ("VFS: Can't find an ext2 filesystem on dev "
"%s.\n", kdevname(dev));
failed_mount:
sb->s_dev = 0;
unlock_super (sb);
if (bh) brelse(bh);
MOD_DEC_USE_COUNT;
return NULL;
}

/* Se verifican las características opcionales del SB */


if (es->s_rev_level > EXT2_GOOD_OLD_REV) {
if (es->s_feature_incompat & ~EXT2_FEATURE_INCOMPAT_SUPP) {
printk("EXT2-fs: %s: couldn't mount because of "
"unsupported optional features.\n",kdevname(dev));
goto failed_mount;
}

54
EXT2_READ_SUPER
/* Se verifica si el modo (lect/esc) está soportado */
if (!(sb->s_flags & MS_RDONLY) &&
(es->s_feature_ro_compat &EXT2_FEURE_RO_COMPAT_SUPP))
{
printk("EXT2-fs: %s: couldn't mount RDWR because of "
"unsupported optional features.\n",
kdevname(dev));
goto failed_mount;
}
}
/* Inicializa el tamaño de los bloques */
/* Realiza la correspondencia: 0 -> 1KB; 1 -> 2KB; 2 -> 4KB. Log10
(s_log_block_size) */
sb->s_blocksize_bits = sb->u.ext2_sb.s_es->s_log_block_size +10;
sb->s_blocksize = 1 << sb->s_blocksize_bits;

/* Se comprueba que es un tamaño correcto. Si no es de tamaño BLOCK_SIZE se


libera y se vuelve a leer el superbloque */
if (sb->s_blocksize != BLOCK_SIZE &&
(sb->s_blocksize == 1024 || sb->s_blocksize == 2048 ||
sb->s_blocksize == 4096)) {
unsigned long offset;

55
EXT2_READ_SUPER
/* Libera las memorias intermedias que contienen los
descriptores del sistema de archivos */
brelse (bh);
set_blocksize (dev, sb->s_blocksize);
logic_sb_block = (sb_block*BLOCK_SIZE) / sb->s_blocksize;
offset = (sb_block*BLOCK_SIZE) % sb->s_blocksize;

/* Se vuelve a leer el superbloque */


bh = bread (dev, logic_sb_block, sb->s_blocksize);
if(!bh) {
printk("EXT2-fs: Couldn't read superblock on "
"2nd try.\n");
goto failed_mount;
}

/* Se vuelve a asignar el superbloque a las variables */


es = (struct ext2_super_block *) (((char *)bh->b_data)+
offset);
sb->u.ext2_sb.s_es = es;

56
EXT2_READ_SUPER
/* Se comprueba la validez del superbloque */
if (es->s_magic != EXT2_SUPER_MAGIC) {
printk ("EXT2-fs: Magic mismatch, very weird !\n");
goto failed_mount;
}
}

/* ¿Están soportadas las características de esta revisión? */


if (es->s_rev_level == EXT2_GOOD_OLD_REV) {
sb->u.ext2_sb.s_inode_size = EXT2_GOOD_OLD_INODE_SIZE;
sb->u.ext2_sb.s_first_ino = EXT2_GOOD_OLD_FIRST_INO;
} else {
sb->u.ext2_sb.s_inode_size = es->s_inode_size;
sb->u.ext2_sb.s_first_ino = es->s_first_ino;
if (sb->u.ext2_sb.s_inode_size != EXT2_GOOD_OLD_INODE_SIZE)
{
printk ("EXT2-fs: unsupported inode size: %d\n",
sb->u.ext2_sb.s_inode_size);
goto failed_mount;
}
}

57
EXT2_READ_SUPER
/* Se inician distintos campos del SB realizando ciertos
cálculos sobre el SB leído de disco (es) */

/* Si no es un SF ext2 (número mágico)  error */


if (sb->s_magic != EXT2_SUPER_MAGIC) {
if (!silent)
printk ("VFS: Can't find an ext2 filesystem on dev "
"%s.\n",
kdevname(dev));
goto failed_mount;
}

/* Se comprueban si los cálculos realizados son correctos */

58
EXT2_READ_SUPER
/* Se leen los descriptores de grupo */
for (i = 0; i < db_count; i++) {
sb->u.ext2_sb.s_group_desc[i] = bread(dev,logic_sb_block+ i+1,
sb->s_blocksize);

/* Si se produce un error se liberan los leídos */


if (!sb->u.ext2_sb.s_group_desc[i]) {
for (j = 0; j < i; j++)
brelse (sb->u.ext2_sb.s_group_desc[j]);
kfree_s (sb->u.ext2_sb.s_group_desc,
db_count * sizeof (struct buffer_head *));
printk ("EXT2-fs: unable to read group descriptors\n");
goto failed_mount;
}
}

59
EXT2_READ_SUPER
/* Se chequean los descriptores de grupos. Si se produce un fallo
se liberan los asignados*/
if (!ext2_check_descriptors (sb)) {
for (j = 0; j < db_count; j++)
brelse (sb->u.ext2_sb.s_group_desc[j]);
kfree_s (sb->u.ext2_sb.s_group_desc,
db_count * sizeof (struct buffer_head *));
printk ("EXT2-fs: group descriptors corrupted !\n");
goto failed_mount;
}

/* ... Se realizan algunas inicializaciones a valores por defecto


... */

60
EXT2_READ_SUPER
/* Se intenta leer el nodo raíz en s_mounted. En caso de error
se liberan los descriptores asociados */
if (!(sb->s_mounted = iget (sb, EXT2_ROOT_INO))) {
sb->s_dev = 0;
for (i = 0; i < db_count; i++)
if (sb->u.ext2_sb.s_group_desc[i])
brelse (sb->u.ext2_sb.s_group_desc[i]);
kfree_s (sb->u.ext2_sb.s_group_desc,
db_count * sizeof (struct buffer_head *));
brelse (bh);
printk ("EXT2-fs: get root inode failed\n");
return NULL;
}

/* Se completa la inicialización del SB llamando a setup */

ext2_setup_super (sb, es);


return sb;
}

61
EXT2_REMOUNT
 ¿Para qué sirve?
• Montamos de nuevo el SF de nuevo
• Sólo reconfigura el SF, no lo lee de disco de nuevo

 Modo de funcionamiento
• Comprobamos las opciones de montaje
(parse_options)
• Actualizamos algunos campos del descriptor
• Inicializamos el SB (ext2_setup_super)

62
EXT2_REMOUNT
int ext2_remount (struct super_block *sb, int *flags, char *data)
{
struct ext2_super_block * es;
unsigned short resuid = sb->u.ext2_sb.s_resuid;
unsigned short resgid = sb->u.ext2_sb.s_resgid;
unsigned long new_mount_opt;
unsigned long tmp;

/* Comprobamos las nuevas opciones de montaje */


new_mount_opt = EXT2_MOUNT_CHECK_NORMAL;
if (!parse_options (data, &tmp, &resuid, &resgid,
&new_mount_opt))
return -EINVAL;

/* Se actualizan algunos campos */


sb->u.ext2_sb.s_mount_opt = new_mount_opt;
sb->u.ext2_sb.s_resuid = resuid;
sb->u.ext2_sb.s_resgid = resgid;
es = sb->u.ext2_sb.s_es;

63
EXT2_REMOUNT
/* Sistema en modo lec y ya lo estaba, retornamos */
if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
return 0;

/* Sistema en modo lectura y estaba en modo lect/esc */


if (*flags & MS_RDONLY) {
/* comprueba si ya se ha realizado  termina */
if (es->s_state & EXT2_VALID_FS ||
!(sb->u.ext2_sb.s_mount_state & EXT2_VALID_FS))
return 0;
/* marcamos el flag de sólo lectura y remarcar la
partición como válida. */
es->s_state = sb->u.ext2_sb.s_mount_state;
es->s_mtime = CURRENT_TIME;
mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1);
sb->s_dirt = 1;

/* Se actualiza el superbloque en disco */


ext2_commit_super (sb, es);
}

64
EXT2_REMOUNT
else {
/* Si se va a remontar un sistema que estaba en modo sólo
lectura en modo lect/esc se actualiza en disco el flag
de validez, que puede haber cambiado (e2fsck) */

sb->u.ext2_sb.s_mount_state = es->s_state;
sb->s_flags &= ~MS_RDONLY;

/* Se completa la inicialización del superbloque */


ext2_setup_super (sb, es);
}
return 0;
}

65
EXT2_COMMIT_SUPER
 ¿Para qué sirve?
• Marca la memoria intermedia que contiene el
SB como modificada.
• Esta memoria será actualizada a disco en la
siguiente escritura en disco del buffer caché.

 Modo de funcionamiento
• Guarda la hora en la que se modifica
• Llama a mark_buffer_dirty

66
EXT2_COMMIT_SUPER
static void ext2_commit_super (struct super_block *sb,
struct ext2_super_block *es)
{
es->s_wtime = CURRENT_TIME;
mark_buffer_dirty(sb->u.ext2_sb.s_sbh, 1);
sb->s_dirt = 0;
}

67
EXT2_WRITE_SUPER
 ¿Para qué sirve?
• Se usa para actualizar algunos campos como:
• Fecha de última modificación del SB (s_mtime)
• Estado del SF (s_state)
 Modo de funcionamiento
• Se comprueba si es posible escribir
• Se actualizan los campos (s_mtime, s_state)
• Se llama a ext2_commit_super para escribir en la
memoria intermedia.

68
EXT2_WRITE_SUPER
void ext2_write_super (struct super_block * sb)
{
struct ext2_super_block * es;

/* Si se puede escribir */
if (!(sb->s_flags & MS_RDONLY)) {
es = sb->u.ext2_sb.s_es;

/* Se actualiza s_state: SF montado */


if (es->s_state & EXT2_VALID_FS) {
es->s_state &= ~EXT2_VALID_FS;

/* Se actualiza s_mtime: fecha de última modif del SB) */


es->s_mtime = CURRENT_TIME;
}

/* Se indica que se ha de actualizar el SB */


ext2_commit_super (sb, es);
}
sb->s_dirt = 0;
}

69
EXT2_INIT_FS
 ¿Para qué sirve?
• Devuelve la identificación del SF tipo EXT2

 Modo de funcionamiento
• Llama a la función register_filesystem

70
EXT2_INIT_FS
int init_ext2_fs(void)
{
return register_filesystem(&ext2_fs_type);
}

/* Valores de un FS ext2 */
static struct file_system_type ext2_fs_type = {
ext2_read_super, "ext2", 1, NULL
};

71
EXT2_STATFS
 ¿Para qué sirve?
• Devuelve información estadística del SF

 Modo de funcionamiento
• Cálculo del tamaño de las cabeceras de un GB
• Cálculo de varias estadísticas:
• Número mágico
• Tamaño de bloque
• Número de bloque
• Número de bloques libres …
• Se vuelcan los datos en el buffer pasado como
argumento

72
EXT2_STATFS
void ext2_statfs (struct super_block *sb, struct statfs *buf,
int bufsiz)
{
unsigned long overhead;
unsigned long overhead_per_group;
struct statfs tmp;

/* Tamaño de las cabeceras de un GB */


if (test_opt (sb, MINIX_DF))
overhead = 0;
else {
overhead_per_group = 1 + /* super block */
sb->u.ext2_sb.s_db_per_group + /* descriptors */
1 + /* block bitmap */
1 + /* inode bitmap */
sb->u.ext2_sb.s_itb_per_group; /* inode table */

overhead = sb->u.ext2_sb.s_es->s_first_data_block +
sb->u.ext2_sb.s_groups_count *
overhead_per_group;
}

73
EXT2_STATFS
/* Se calculan estadísticas a partir del “sb” */
tmp.f_type = EXT2_SUPER_MAGIC;
tmp.f_bsize = sb->s_blocksize;
/* Bloques de datos (no metadatos) */
tmp.f_blocks = sb->u.ext2_sb.s_es->s_blocks_count - overhead;
tmp.f_bfree = ext2_count_free_blocks (sb);
/* Los bloques disponibles; no contamos con los reservados para el
superusuario */
tmp.f_bavail = tmp.f_bfree –
sb->u.ext2_sb.s_es->s_r_blocks_count;

if (tmp.f_bfree < sb->u.ext2_sb.s_es->s_r_blocks_count)


tmp.f_bavail = 0;

tmp.f_files = sb->u.ext2_sb.s_es->s_inodes_count;
tmp.f_ffree = ext2_count_free_inodes (sb);
tmp.f_namelen = EXT2_NAME_LEN;

/* Se vuelca tmp en el buffer (como salida) */


memcpy_tofs(buf, &tmp, bufsiz);
}

74
Tercer sistema de ficheros
extendido (Ext3)

75
Características del Ext3
 Este nuevo sistema de ficheros ha sido diseñado
con dos conceptos en mente:
• Que sea todo lo compatible posible con el Ext2:
• Está totalmente basado en el Ext2, por lo que las
estructuras de disco son esencialmente idénticas.
• Que sea un sistema de ficheros Journaling:
• Se puede crear un sistema Journal Ext3 a partir de un
sistema de ficheros Ext2 (remontándolo).
 Nos centraremos en la característica Journal.

76
Sistema Journal para el Ext3
 En un sistema de ficheros Ext2 las modificaciones
de los bloques del sistema de ficheros se realizan en
la memoria dinámica.
 Se mantienen durante un tiempo antes de ser
volcados en el disco.
 Un evento dramático, como un fallo en la corriente
del sistema, puede hacer que el sistema se quede
en un estado de inconsistencias.

77
Sistema Journal para el Ext3
 Para sobreponerse a este problema, cada sistema
tradicional del Unix es chequeado antes de ser
montado.
 Si no es ha sido desmontado correctamente, en
programa específico ejecuta un exhaustivo chequeo
(que consume mucho tiempo) y corrige todas las
posibles inconsistencias que encuentre en el
sistema de ficheros a nivel de metadatos.

78
Sistema Journal para el Ext3
 En el Ext2 el estado se almacena en el campo
s_mount_state de la superbloque del disco.
 La utilidad e2fsck en invocada por el script de arranque
para chequear el valor almacenado en este campo.
 Si no es igual a EXT2_VALID_FS, el sistema de fichero
no se desmontó correctamente
• e2fsck comienza a chequear todas las estructuras de datos
del SF.
 Claramente, el tiempo dedicado al chequeo depende:
• Del número de ficheros y directorios a examinar.
• Del tamaño del disco.
 Hoy en día un simple chequeo de consistencia puede
llevar horas.
79
Sistema Journal para el Ext3
 La idea del Journaling Ext3 es realizar cualquier
cambio de alto nivel en el sistema de ficheros en
dos pasos.
1. Una copia de los bloques que serán escritos se
almacena un Journal (diario).
2. Cuando la escritura en Journal se completa, los
bloques se escriben en el sistema de ficheros.
 Cuando se completa la operación de escritura al
sistema de ficheros la copia de los bloques en el
Journal se descartan.
80
Sistema Journal para el Ext3
 Mientras se recupera de un fallo en el sistema, el
programa e2fsck distingue dos casos:
1. El fallo en el sistema ocurrió antes de que se
realizara un commit en el Journal. Las copias
de los bloques relativos a los cambios se han
perdido del Journal, o están incompletos; en
ambos casos el e2fsck los ignora.
2. El fallo en el sistema ocurrió después de que
se realizara el commit en el Journal. La copia
de los bloques son válidos y el e2fsck los
escribe en el sistema de ficheros.
81
Sistema Journal para el Ext3
 En el primero de los casos, los cambios sobre el
sistema de ficheros se han perdido, pero el estado
del mismo es consistente.
 En el segundo de los casos, el e2fsck aplica todos
los cambios previstos sobre el sistema de ficheros,
arreglando cualquier inconsistencia.

82
Sistema Journal para el Ext3
 Existen dos tipos de bloques:
• Los que contienen metadatos del sistema.
• Los que contienen los datos en sí.
 Los registros log de los metadatos son suficientes
para recuperar la consistencia del SF.
 El Ext3 puede configurarse para que realice un
seguimiento:
• Tanto en los operaciones que afectan a los
metadatos.
• Como en aquellas que afectan a los datos de un
fichero.
83
Sistema Journal para el Ext3
 Estos son los diferentes modos de Journal:
Journal:
• Todos los cambios en los datos y metadatos
del sistema de ficheros se registran en el
Journal.
• Este modo minimiza la posibilidad de perdida de
las actualizaciones hechos sobre cada fichero,
pero requiere muchos accesos adicionales a
disco.
• Este es el método más seguro pero el más lento
de los modos Journaling.
84
Sistema Journal para el Ext3
Ordered:
• Solo los cambios en los metadatos del sistema
de ficheros se almacenan el Journal.
• El Ext3 agrupa los metadatos y sus bloques de
datos relacionados de manera que los bloques
de datos sean escritos en disco antes que los
metadatos.
• De esta manera, la posibilidad de tener datos
corruptos en un fichero se reducen. Este es el
método por defecto del Ext3.

85
Sistema Journal para el Ext3
Writeback:
• Sólo los cambios en los metadatos del sistema
de ficheros se almacenan en el Journal.
• Este es el método más rápido, pero el más
inseguro.
 El modo Journaling se especifica en una opción del
comando de montaje del sistema.
#mount -t ext3 -o data=writeback /dev/hda1 /jdisk

86
Sistema Journal para el Ext3
 El Journal del Ext3 normalmente se almacena en el
fichero oculto llamado .journal que se encuentra en
el directorio root del sistema de ficheros.
 Capa del dispositivo de bloque Journaling, JBD:
• El Ext3 no maneja el fichero journal por si mismo,
si no que utiliza una capa superior del kernel
llamada dispositivo de bloque Journaling, o JBD.
• El Ext3 invoca a las rutinas del JBC para
asegurarse que las sucesivas operaciones no
corrompan las estructuras de datos en caso de
fallo en el sistema.
87
Sistema de ficheros ReiserFS
 ReiserFS fue diseñado originalmente por Hans
Reiser.
 La primera versión se lanzó a mediados de los 90,
llegando a formar parte del núcleo en la versión
2.4.1 del mismo (ReiserFS v3.5).
 La versión 3.6 es el sistema de ficheros por defecto
de las distribuciones SUSE, GENTOO y LINDOWS.
 La versión actual de prueba (testing) es la v4.

88
Las características del ReiserFS
 Rápido, pero eficiente en la gestión del espacio.
• 10 veces más rápido que el Ext2
• Sin penalización para ficheros pequeños
 Fiable.
• Soporte Journaling
 Compatible con la semántica de UNIX, pero
extensible a través de un sofisticado sistema de
Plugins.

89
Las características del ReiserFS
 En esencia, el ReiserFS en un sistema Journaling
que trata a toda la partición del disco como si fuera
una única tabla de una base de datos.
 Los directorios, ficheros y metadatos se organizan
en una eficiente estructura de datos llamada
“árbol balanceado”.
 Esto difiere bastante de la manera tradicional de
trabajar de otros sistemas de ficheros.

90
Las características del ReiserFS
 Ofrece grandes mejoras de velocidad en muchas
aplicaciones, especialmente aquellas que utilizan
gran cantidad de ficheros pequeños.
 La apertura de un fichero requiere que:
• El sistema localice el fichero.
• El sistema necesita examinar los metadatos para saber si
el usuario tiene los permisos de accesos necesarios.
• El sistema pierde más tiempo decidiendo si permite el
acceso al fichero que el tiempo que finalmente se tarda en
obtener la información del mismo.

91
Las características del ReiserFS
 ReiserFS utiliza los árboles balanceados (Árboles B*):
• Para el proceso de la localización de los ficheros.
• Para la obtención de la información de los metadatos (y
otro tipo de información adicional).
• Para ficheros extremadamente pequeños, toda la
información del fichero puede físicamente almacenarse
cerca de los metadatos, de manera que ambos pueden ser
accedidos simultáneamente.

92
Las características del ReiserFS

 Los nodos hojas (leaf nodes), almacenan los datos en


sí, y no tienen hijos.
 Los nodos que contienen información se dice que están
formateados.
 Sólo los nodos hoja pueden estar no formateados.

93
Las características del ReiserFS
 Los punteros se almacenan en nodos formateados
por lo que los nodos intermedios (internal nodes)
necesariamente tienen que estar formateados.
 El nodo raíz es de donde nace el árbol.
 Si una aplicación necesita abrir ficheros muy
pequeños rápidamente, este planteamiento mejora
el rendimiento significativamente.

94
Las características del ReiserFS
 Los árboles balanceados no sólo almacenan metadatos,
sino que también almacenan los datos en sí.
 En un sistema tradicional como el Ext2, el espacio se
reparte en bloques de tamaño desde 1024 a 4096 bytes.
 Si el tamaño de un fichero no es múltiplo del tamaño de
bloque habrá cierto espacio que se desperdiciará
(fragmentación interna).
 Ej. supongamos un tamaño de bloque de 1024 bytes y un espacio
requerido de 8195 bytes.

95
Las características del ReiserFS
 ReiserFS no utiliza el enfoque clásico de bloques a la
hora dividir el espacio de disco.

 Se apoya en la estructura arbórea para mantener un


seguimiento de los bytes asignados.

 En ficheros pequeños, esto puede ahorrar como ya


hemos dicho mucho espacio de almacenamiento.

96
Las características del ReiserFS
 Los ficheros tienden a colocarse cercanos unos de
otros por lo que el sistema es capaz de abrir y leer
muchos ficheros pequeños con un único acceso al disco.
 Esto conlleva un ahorro de tiempo al disminuir el tiempo
de búsqueda de la cabeza lectora del disco.

97
Las características del ReiserFS

 Para almacenar grandes ficheros, ReiserFS versión 3

utiliza el método BLOB (Binary Large OBject) que

desbalanceaba el árbol reduciendo así el rendimiento.

98
Las características del ReiserFS

 Se almacenan en los nodos hoja punteros a nodos que


contienen el fichero en su conjunto.

 Este método desbalancea al árbol.

99
Las características del ReiserFS

 En la versión 4 de ReiserFS se intenta solucionar este problema


haciendo que todos los punteros a ficheros se almacenen en el mismo
nivel.
 Los nodos Twig, son los padres de los nodos hojas.
 Los nodos Branch son nodos internos que no son Twig.
 De esta manera se mantiene al árbol balanceado.

100
Las características del ReiserFS
 Otra característica destacable del ReiserFS es la
utilización de Plugins.
 Los Plugins permiten la adaptación del sistema de
ficheros a nuevas características sin la necesidad de
formateo.
 Trabajan de forma independiente sobre el núcleo del
sistema de ficheros.

101
Las características del ReiserFS
 Todas las operaciones se implementan en Plugins.
 Permite que se modifique la funcionalidad del sistema de
ficheros sin necesidad de modificar el núcleo.
 Por encima de todo, ReiserFS es un verdadero sistema
de ficheros Journaling como el XFS, el Ext3 y el JFS.

102
Fin
103

También podría gustarte