26
1 Sistema de ficheros ext2 Ramírez Viera, Jesús Alberto Romero Santana, Samuel Llamadas al sistema read y write

1 Sistema de ficheros ext2 Ramírez Viera, Jesús Alberto Romero Santana, Samuel Llamadas al sistema read y write

Embed Size (px)

Citation preview

Page 1: 1 Sistema de ficheros ext2 Ramírez Viera, Jesús Alberto Romero Santana, Samuel Llamadas al sistema read y write

1

Sistema de ficheros ext2

Ramírez Viera, Jesús AlbertoRomero Santana, Samuel

Llamadas al sistema read y write

Page 2: 1 Sistema de ficheros ext2 Ramírez Viera, Jesús Alberto Romero Santana, Samuel Llamadas al sistema read y write

2

Llamada al sistema read Uso y parámetros La llamada al sistema read realiza la

lectura de datos desde un archivo Sus parámetros son:

Descriptor del fichero que se va a leer Buffer donde se almacenarán los datos Número de bytes a leer

Devuelve: Número de bytes que se consiguieron leer < 0 en caso de error

Page 3: 1 Sistema de ficheros ext2 Ramírez Viera, Jesús Alberto Romero Santana, Samuel Llamadas al sistema read y write

3

Esquema de funcionamiento del read

Sys_Read

Lock_kernel fget Locks_verify_area read fput unlock_kernel

fcheck Locks_mandatory_area

locks_remove_flock _fput remove_filp insert_file_free

Page 4: 1 Sistema de ficheros ext2 Ramírez Viera, Jesús Alberto Romero Santana, Samuel Llamadas al sistema read y write

4

Llamada al sistema read fs/read_write.c

asmlinkage ssize_t sys_read(unsigned int fd, char * buf, size_t count){

ssize_t ret;struct file * file;ssize_t (*read)(struct file *, char *, size_t, loff_t

*);

lock_kernel(); ret = -EBADF;file = fget(fd);

if (!file)goto bad_file;

if (!(file->f_mode & FMODE_READ))goto out;

Zona de exclusión mutua

Obtenemos la estructura file a través del descriptor de fichero

Si no existe estructura de fichero asociada, error

Verificamos modo de lectura

Page 5: 1 Sistema de ficheros ext2 Ramírez Viera, Jesús Alberto Romero Santana, Samuel Llamadas al sistema read y write

5

Llamada al sistema read fs/read_write.c

ret = locks_verify_area(FLOCK_VERIFY_READ, file->f_dentry->d_inode,file, file->f_pos, count);

if (ret)goto out;

ret = -EINVAL;

if (!file->f_op || !(read = .file->f_op->read))goto out;

ret = read(file, buf, count, &file->f_pos); out:

fput(file); bad_file:

unlock_kernel();return ret;

}

Dejamos el descriptor de

fichero

Comprueba si existe bloqueo

Si está bloqueada, sale (salta a out)

Efectuamos la lectura usando la función que acabamos de obtener

Page 6: 1 Sistema de ficheros ext2 Ramírez Viera, Jesús Alberto Romero Santana, Samuel Llamadas al sistema read y write

6

fget & fcheckinclude/linux/file.h

extern inline struct file * fget(unsigned int fd){ struct file * file = fcheck(fd);

if (file) file->f_count++; return file;}

extern inline struct file * fcheck(unsigned int fd){ struct file * file = NULL;

if (fd < current->files->max_fds) file = current->files->fd[fd]; return file;}

Comprueba que el descriptor es válido

(no se pasa del máximo)

Chequea el descriptor de fichero

Aumentamos el contador de accesos

Asigna la estructura file asociada al descriptor

Page 7: 1 Sistema de ficheros ext2 Ramírez Viera, Jesús Alberto Romero Santana, Samuel Llamadas al sistema read y write

7

fput include/linux/file.h

void fput(struct file *file){ int count = file->f_count-1;

if (!count) { locks_remove_flock(file); __fput(file); file->f_count = 0; remove_filp(file); insert_file_free(file); } else file->f_count = count;}

Disminuimos contador de accesos al fichero

Si ya no se va a realizar ninguna operación en el fichero, se libera de la

tabla de descriptores, para tener el descriptor de esa

entrada, libre.

Page 8: 1 Sistema de ficheros ext2 Ramírez Viera, Jesús Alberto Romero Santana, Samuel Llamadas al sistema read y write

8

locks_verify_area include/linux/fs.h

extern inline int locks_verify_area(int read_write, struct inode *inode, struct file *filp, loff_t offset, size_t count){

if (IS_MANDLOCK(inode) && (inode->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID)

return (locks_mandatory_area(read_write, inode, filp, offset, count));

return (0);} Intenta bloquear

¿Se cumplen las condiciones para poder realizar el bloqueo?

Page 9: 1 Sistema de ficheros ext2 Ramírez Viera, Jesús Alberto Romero Santana, Samuel Llamadas al sistema read y write

9

locks_mandatory_area include/linux/fs.h

int locks_mandatory_area(int read_write, struct inode *inode,struct file *filp, loff_t offset,size_t count){ struct file_lock *fl; struct file_lock tfl; memset(&tfl, 0, sizeof(tfl)); tfl.fl_file = filp; tfl.fl_flags = FL_POSIX | FL_ACCESS; tfl.fl_owner = current->files; tfl.fl_pid = current->pid; tfl.fl_type = (read_write == FLOCK_VERIFY_WRITE) ? F_WRLCK : F_RDLCK; tfl.fl_start = offset; tfl.fl_end = offset + count - 1;

Introducimos la información del nuevo

nodo

Reservamos memoria para el nuevo elemento de la lista de áreas bloqueadas

Page 10: 1 Sistema de ficheros ext2 Ramírez Viera, Jesús Alberto Romero Santana, Samuel Llamadas al sistema read y write

10

Locks_mandatory_area include/linux/fs.h

repeat:

for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) { if (!(fl->fl_flags & FL_POSIX)) continue; if (posix_locks_conflict(fl, &tfl)) {

... locks_insert_block(fl, &tfl); interruptible_sleep_on(&tfl.fl_wait); locks_delete_block(fl, &tfl);

...

Si existe conflicto del tipo escritura contra bloqueo de lectura o lectura/escritura contra bloqueo de escritura,ponemos nuestro inodo en espera, y esperamos por que las condiciones de

bloqueo desaparezcan

Page 11: 1 Sistema de ficheros ext2 Ramírez Viera, Jesús Alberto Romero Santana, Samuel Llamadas al sistema read y write

11

Estructuras include/linux/fs.hstruct file {

...struct file_operations *fop;...

}

struct file_operations {loff_t (*llseek) (struct file *, loff_t, int);ssize_t (*read) (struct file *, char *, size_t, loff_t *);ssize_t (*write) (struct file *, const char *, size_t,

loff_t *);int (*readdir) (struct file *, void *, filldir_t);...}

static struct file_operations ext2_file_operations = {// include/linux/file.c

ext2_file_lseek, /* lseek */generic_file_read, /* read */ext2_file_write, /* write */... }

Page 12: 1 Sistema de ficheros ext2 Ramírez Viera, Jesús Alberto Romero Santana, Samuel Llamadas al sistema read y write

12

Esquema Readpara el formato EXT2

generic_file_read

do_generic_file_read

page_hash _find_page Page_cache_alloc Page_cache_entry

add_to_page_cache readpage page_cache_release

generic_readpage

Page 13: 1 Sistema de ficheros ext2 Ramírez Viera, Jesús Alberto Romero Santana, Samuel Llamadas al sistema read y write

13

generic_file_read/mm/filemap.c

ssize_t generic_file_read(struct file * filp, char * buf, size_t count, loff_t *ppos){

ssize_t retval;retval = -EFAULT;if (access_ok(VERIFY_WRITE, buf, count)) {

retval = 0;if (count) {

read_descriptor_t desc; desc.written = 0; desc.count = count; desc.buf = buf; desc.error = 0; do_generic_file_read(filp, ppos, &desc,

file_read_actor);retval = desc.written;if (!retval)

retval = desc.error;}}

return retval;}

Introducimos la información pasada por parámetro, en la estructura que necesitará

do_generic_file_read

Número de bytes escritos, o error

Comprobamos el área de memoria donde se escribirá la información

Page 14: 1 Sistema de ficheros ext2 Ramírez Viera, Jesús Alberto Romero Santana, Samuel Llamadas al sistema read y write

14

do_generic_file_read mm/filemap.c

static void do_generic_file_read(struct file * filp, loff_t *ppos, read_descriptor_t * desc, read_actor_t actor){...

for (;;) {struct page *page, **hash;if (pos >= inode->i_size)

break;

hash = page_hash(inode, pos & PAGE_CACHE_MASK);page = __find_page(inode, pos &

PAGE_CACHE_MASK, *hash);...

Efectúa un bucle llamando a find_page, para buscar las páginas correspondientes a los datos a leer. Se busca en caché.

Page 15: 1 Sistema de ficheros ext2 Ramírez Viera, Jesús Alberto Romero Santana, Samuel Llamadas al sistema read y write

15

do_generic_file_read mm/filemap.c

no_cached_page:if (!page_cache) {

page_cache = page_cache_alloc();if (page_cache)

continue;desc->error = -ENOMEM;break;}

page = page_cache_entry(page_cache);page_cache = 0;add_to_page_cache(page, inode, pos & PAGE_CACHE_MASK,

hash);if (reada_ok && filp->f_ramax > MIN_READAHEAD)

filp->f_ramax = MIN_READAHEAD;{int error = inode->i_op->readpage(filp, page);if (!error)

goto found_page;desc->error = error;page_cache_release(page);break;}

Por último, leemos la página

Si hay error, borramos la página

de caché

Buscamos espacio para alojar en caché una nueva

página

Añadimos la página a la caché

Page 16: 1 Sistema de ficheros ext2 Ramírez Viera, Jesús Alberto Romero Santana, Samuel Llamadas al sistema read y write

16

generic_readpage fs/buffer.c

int generic_readpage(struct file * file, struct page * page){ atomic_inc(&page->count);

i = PAGE_SIZE >> inode->i_sb->s_blocksize_bits; block = page->offset >> inode->i_sb->s_blocksize_bits; p = nr; do { *p = inode->i_op->bmap(inode, block); i--; block++; p++; } while (i > 0);

...

return 0;}

No permite que la lectura se interrumpa por cualquier evento

Obtenemos número de bloques a leer

Vamos leyendo del inodo y dirección especificados

Page 17: 1 Sistema de ficheros ext2 Ramírez Viera, Jesús Alberto Romero Santana, Samuel Llamadas al sistema read y write

17

Estructuras de inodos mm/filemap.c

struct dentry {unsigned long d_time; /* used by d_revalidate */struct dentry_operations *d_op;struct super_block * d_sb; /* The root of the dentry

tree */ ...}struct inode_operations {

struct dentry * (*follow_link) (struct dentry *, struct dentry *, unsigned int);

int (*readpage) (struct file *, struct page *);int (*writepage) (struct file *, struct page *);

....};struct inode_operations ext2_file_inode_operations = {

generic_readpage,/* readpage */ext2_bmap, /* bmap */ext2_truncate, /* truncate */ext2_permission, /* permission */NULL /* smap */

...};

Page 18: 1 Sistema de ficheros ext2 Ramírez Viera, Jesús Alberto Romero Santana, Samuel Llamadas al sistema read y write

18

Llamada al sistema write · Uso y parámetros Sus parámetros son:

Descriptor del fichero que se va a escribir Buffer donde están los datos a escribir Número de bytes a escribir

Devuelve: Número de bytes que se consiguieron

escribir < 0 en caso de error

La llamada al sistema write realiza la escritura de datos desde un archivo

Page 19: 1 Sistema de ficheros ext2 Ramírez Viera, Jesús Alberto Romero Santana, Samuel Llamadas al sistema read y write

19

sys_write /fs/red_write.c

asmlinkage ssize_t sys_write(unsigned int fd, const char * buf, size_t count){

ssize_t ret;struct file * file;struct inode * inode;ssize_t (*write)(struct file *, const char *, size_t,

loff_t *);lock_kernel(); ret = -EBADF;file = fget(fd);if (!file)

goto bad_file;if (!(file->f_mode & FMODE_WRITE))

goto out;

Exclusión mutua

Tomamos descriptor

Comprobamos el permiso de escritura

Page 20: 1 Sistema de ficheros ext2 Ramírez Viera, Jesús Alberto Romero Santana, Samuel Llamadas al sistema read y write

20

sys_write/fs/red_write.c

inode = file->f_dentry->d_inode;ret = locks_verify_area(FLOCK_VERIFY_WRITE, inode, file,file->f_pos, count); if (ret)

goto out;ret = -EINVAL;if (!file->f_op || !(write = file->f_op->write))

goto out;

down(&inode->i_sem); ret = write(file, buf, count, &file->f_pos);up(&inode->i_sem);out:

fput(file); bad_file:

unlock_kernel();return ret;

}

Tomamos función para realizar escritura en EXT2

Controlamos el problema de los lectores / escritores

Liberamos descriptor

Realizamos escritura

La sección a escribir no está bloqueada

Page 21: 1 Sistema de ficheros ext2 Ramírez Viera, Jesús Alberto Romero Santana, Samuel Llamadas al sistema read y write

21

Ext2_file_write fs/ext2/file.c

static ssize_t ext2_file_write (struct file * filp, const char * buf,size_t count, loff_t *ppos)

{...if (!count)

return 0;

if (((signed) count) < 0)return -EINVAL;

write_error = buffercount = 0;

if (!inode) {printk("ext2_file_write: inode = NULL\n");return -EINVAL;

}sb = inode->i_sb;if (sb->s_flags & MS_RDONLY)

return -ENOSPC;

Comprobamos que existe un inodo asociado al fichero

Comprobamos que no es de solo lectura

Comprobamos valor del count (bytes a

escribir)

Page 22: 1 Sistema de ficheros ext2 Ramírez Viera, Jesús Alberto Romero Santana, Samuel Llamadas al sistema read y write

22

Ext2_file_write fs/ext2/file.c

if (!S_ISREG(inode->i_mode)) {ext2_warning (sb, "ext2_file_write", "mode =

%07o", inode->i_mode);return -EINVAL;

}remove_suid(inode);

if (filp->f_flags & O_APPEND)pos = inode->i_size;

else {pos = *ppos; if (pos != *ppos)

return -EINVAL;}

Borrar del inode setgid setuid

Comprobamos permiso de escritura

Flag de añadir al fichero

Escribimos en una posición determinada

Page 23: 1 Sistema de ficheros ext2 Ramírez Viera, Jesús Alberto Romero Santana, Samuel Llamadas al sistema read y write

23

Ext2_file_writefs/ext2/file.c

if (((unsigned) pos) >= 0x7FFFFFFFUL)return -EFBIG;

if (((unsigned) pos + count) > 0x7FFFFFFFUL) {

count = 0x7FFFFFFFL - pos;if (((signed) count) < 0)

return -EFBIG;

...

Se chequean el resto de parámetros

...

La posición a escribir no

sobrepasa el máximo

Los bytes a escribir no sobrepasan el

máximo

Page 24: 1 Sistema de ficheros ext2 Ramírez Viera, Jesús Alberto Romero Santana, Samuel Llamadas al sistema read y write

24

ext2_file_write fs/ext2/file.c

do {bh = ext2_getblk (inode, block, 1, &err);

if (!bh) {if (!written)

written = err;break; }

if (c > count)c = count;set_bit(BH_Lock, &bh->b_state);c -= copy_from_user (bh->b_data + offset, buf,

c);if (c != sb->s_blocksize) {

c = 0; unlock_buffer(bh);brelse(bh);if (!written)written = -EFAULT;}

mark_buffer_uptodate(bh, 1);unlock_buffer(bh);

Bucle de escritura mientras queden datos por escribir

Copia datos a la memoria intermedia.

Si hubo error, devuelve el número

de bytes

No se ha podido escribir nada

Obtenemos memoria intermedia donde se irá

copiando la información que después se escribirá

C indica los bytes q se copian en cada iteración. (Tamaño de bloque). La

última iteración puede ser diferente

Page 25: 1 Sistema de ficheros ext2 Ramírez Viera, Jesús Alberto Romero Santana, Samuel Llamadas al sistema read y write

25

ext2_file_write fs/ext2/file.c

mark_buffer_dirty(bh, 0);...pos += c;written += c;buf += c;count -= c;...block++;offset = 0;c = sb->s_blocksize;

} while (count);

Actualizamos contadores

Marca la memoria como modificada

Número de bloques copiados

Actualizamos c (bytes que se copian en cada

iteración)

Page 26: 1 Sistema de ficheros ext2 Ramírez Viera, Jesús Alberto Romero Santana, Samuel Llamadas al sistema read y write

26

ext2_file_write fs/ext2/file.c

if (pos > inode->i_size)inode->i_size = pos;

inode->i_ctime = inode->i_mtime = CURRENT_TIME;

*ppos = pos;mark_inode_dirty(inode);return written;

}

Si se aumentó el tamaño del fichero, se actualiza

Actualizamos información del inodo

Marcamos inodo como modificado