From 2dd5cf430edaae01594d566c9f27d780c3ffb4ef Mon Sep 17 00:00:00 2001 From: Matias Linares Date: Sun, 26 Apr 2015 21:43:42 -0300 Subject: Initial commit --- block_walker.c | 368 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 368 insertions(+) create mode 100644 block_walker.c (limited to 'block_walker.c') diff --git a/block_walker.c b/block_walker.c new file mode 100644 index 0000000..b4c2682 --- /dev/null +++ b/block_walker.c @@ -0,0 +1,368 @@ +#include +#include +#include +#include +#include +#include + +#include "block_walker.h" +#include "defs.h" + +struct _block_walker { + const char *fib; + const char *fbb; + const char *ipool; + const char *bpool; + + uint16_t *indblock_mem; + + GList *block_list; + GList *indirect_list; +}PACKED; + +uint16_t allocate_block(bwalker *bw); +int free_block(bwalker *bw, uint16_t block); + +/* Auxiliares */ +uint16_t allocate_block(bwalker *bw) +{ + uint16_t result = 0; + uint16_t i = 0; + + assert (bw != NULL); + /* Solo queremos desde el segundo inodo para + * que tengamos como error el 0 */ + for(i = 1; i < BLOCKPOOL_BLOCKS; i++) + if(GET_BIT(bw->fbb, i) == 0) + { + /* cambiamos el bitmap */ + SET_BIT_1((char*)bw->fbb, i); + result = i; + break; + } + /* Tiene que estar seteado a 1 */ + assert(GET_BIT(bw->fbb, i) == 1); + + return (result); +} + +int free_block(bwalker *bw, uint16_t block) +{ + char *block_mem = NULL; + assert (bw != NULL); + + block_mem = (char *) bw->bpool + (block * BLOCK_SIZE); + + /* Chequeamos error */ + if (GET_BIT(bw->fbb, block) == 0) + return -1; + + SET_BIT_0((char *)bw->fbb, block); + + return (0); +} + + +/* Creacion y destruccion */ + +bwalker *bwalker_create(const char *base_mem, size_t size, uint16_t *indirect_mem) +{ + bwalker *bw = NULL; + unsigned int i = 0; + uint16_t *indirect_ptr; + uint16_t indirect_num = 0; + + bw = calloc(1, sizeof(struct _block_walker)); + + assert (bw != NULL); + bw->fbb = (char *)base_mem + FBB_OFFSET; + bw->fib = (char *)base_mem + FIB_OFFSET; + bw->ipool = (char *)base_mem + INODEPOOL_OFFSET; + bw->bpool = (char *)base_mem + BLOCKPOOL_OFFSET; + + bw->indblock_mem = indirect_mem; + bw->block_list = NULL; + bw->indirect_list = NULL; + + if (size == 0) + { + /* No hay bloques, no hay nada, + * retornamos aqui */ + return (bw); + } + /* Deberia tener al menos un bloque indirecto. */ + assert ((*indirect_mem) != 0); + + indirect_num = *indirect_mem; + bw->indirect_list = g_list_append (bw->indirect_list, + GUINT_TO_POINTER(indirect_num)); + assert(indirect_num == GPOINTER_TO_UINT(bw->indirect_list->data)); + + indirect_ptr = (uint16_t *) bw->bpool + (BLOCK_SIZE*indirect_num); + + + while (size > 0) + { + /* Empezamos a meterles bloques */ + for(i = 0; i < 255 && size>0; i++) + { + if (indirect_ptr[i] != 0){ + bw->block_list = g_list_append (bw->block_list, + GUINT_TO_POINTER(indirect_ptr[i])); + } + if(indirect_ptr[i]==0){ + break; + } + + if(size > BLOCK_SIZE){ + size -= BLOCK_SIZE; + }else{ + size = 0; + } + } + + if(size != 0 && size>0) + + if(indirect_ptr[255] != 0) + + { + bw->indirect_list = g_list_append (bw->indirect_list, + GUINT_TO_POINTER(indirect_ptr[255])); + indirect_ptr = (uint16_t *) bw->bpool + (BLOCK_SIZE*indirect_ptr[255]); + } + } + + + /*assert (g_list_length(bw->indirect_list) > 0);*/ + + /*assert (*indirect_mem == GPOINTER_TO_UINT(g_list_first(bw->indirect_list)->data));*/ + /*assert (g_list_length(bw->indirect_list) > 0); + assert (g_list_length(bw->block_list) > 0);*/ + + return (bw); +} + +void bwalker_destroy (bwalker *bw) +{ + assert (bw != NULL); + + if(bw->block_list != NULL) + g_list_free(g_list_first(bw->block_list)); + if(bw->indirect_list != NULL) + g_list_free(g_list_first(bw->indirect_list)); + + free(bw); + bw = NULL; +} + +uint16_t bwalker_direct_length(bwalker *bw) +{ + assert(bw != NULL); + return ((uint16_t) g_list_length(bw->block_list)); +} + +uint16_t bwalker_indirect_length(bwalker *bw) +{ + assert(bw != NULL); + return ((uint16_t) g_list_length(bw->indirect_list)); +} + +uint16_t bwalker_allocate_block(bwalker *bw) +{ + uint16_t block = 0; + uint16_t indirect_block = 0; + uint16_t *buf; + uint16_t i =0 ; + bool no_first_indblock = false; + bool indblk_alloc = false; + assert (bw != NULL); + + no_first_indblock = (g_list_length(bw->indirect_list) == 0); + + if(no_first_indblock) + goto ALLOCATE_INDBLK; + + indirect_block = bwalker_last_indirect(bw); + /* Esto tiene que ser distinto de 0 si o si */ + buf = (uint16_t *) bw->bpool + (indirect_block * BLOCK_SIZE); + for(i = 0; i < 255; i++){ + if(buf[i] == 0) + goto ALLOCATE_BLOCK; + } + /* Si llegamos aca, aloca un indirecto y encima _no_ es el primero :B */ + +ALLOCATE_INDBLK: + indirect_block = allocate_block (bw); + assert(indirect_block != 0); + + if(!indirect_block) + goto ENOBLK; + if(no_first_indblock) + *(bw->indblock_mem) = indirect_block; + else + { + assert(buf != NULL); + assert(&(buf[255]) == &(buf[i])); + assert(i == 255); + buf[i] = indirect_block; + } + bw->indirect_list = g_list_append(bw->indirect_list, GUINT_TO_POINTER(indirect_block)); + i = 0; + indblk_alloc = true; + +ALLOCATE_BLOCK: + buf = (uint16_t *) bw->bpool + (indirect_block * BLOCK_SIZE); + block = allocate_block (bw); + if(!block) + { + if(indblk_alloc) + { + free_block(bw,indirect_block); + bw->indirect_list = g_list_remove(bw->indirect_list, GUINT_TO_POINTER(indirect_block)); + if(no_first_indblock) + *bw->indblock_mem = 0; + } + goto ENOBLK; + } + buf[i] = block; + + bw->block_list = g_list_append(bw->block_list, GUINT_TO_POINTER(block)); + + assert(block != 0); + return block; + +ENOBLK: + return 0; +} + +void bwalker_free_block(bwalker *bw) +{ + uint16_t list_length_b, list_length_i; + uint16_t *buf = NULL; + uint16_t block = 0; + uint16_t i = 0; + GList *auxlist = NULL; + assert(bw != NULL); + + if(g_list_length(bw->block_list) == 0) + return; + + list_length_b=g_list_length(bw->block_list); + list_length_i=g_list_length(bw->indirect_list); + /* Aca tenemos que ver si necesitamos deallocar un + * bloque indirecto. */ + auxlist = g_list_last(bw->indirect_list); + block = (uint16_t) auxlist->data; + buf = (uint16_t *) bw->bpool + (block*BLOCK_SIZE); + if(!buf[1]) + { + /* Dealocamos solamente un bloque. */ + for(i=1; buf[i]; i++) + ; + block = buf[i-1]; + free_block(bw, block); + /*no se actualiza la lista. mirenlo a ver que onda, + * me parecio que era asi, pero no me hace caso*/ + bw->block_list=g_list_remove(bw->block_list, g_list_last(bw->block_list)->data); + + buf[i-1] = 0; + + } + else + { + free_block(bw, buf[0]); + bw->block_list=g_list_remove(bw->block_list, g_list_last(bw->block_list)->data); + + buf[0] = 0; + + + if((auxlist = g_list_previous(auxlist))) + { + block = (uint16_t) auxlist->data; + buf = (uint16_t *) bw->bpool + + (block*BLOCK_SIZE); + free_block(bw, buf[255]); + /*el indirecto == buf[255]???*/ + bw->indirect_list=g_list_remove(bw->indirect_list, g_list_last(bw->indirect_list)->data); + + buf[255] = 0; + } + else + { + free_block(bw, *bw->indblock_mem); + bw->indirect_list=g_list_remove(bw->indirect_list, bw->indblock_mem); + + *bw->indblock_mem = 0; + } + + } + +} + +uint16_t bwalker_next(bwalker *bw) +{ + uint16_t result = 0; + + assert (bw != NULL); + if(g_list_length(bw->block_list) == 0) + return 0; + + + if(g_list_length(bw->block_list) == 1){ + return (uint16_t)GPOINTER_TO_UINT(bw->block_list->data); + } + if(bw->block_list!=g_list_last(bw->block_list)){ + assert(*(bw->indblock_mem)!=GPOINTER_TO_UINT(bw->block_list->data)); + result = (uint16_t)GPOINTER_TO_UINT(bw->block_list->data); + bw->block_list = g_list_next(bw->block_list); + } + return (result); +} + +uint16_t bwalker_prev(bwalker *bw) +{ + uint16_t result = 0; + + assert (bw != NULL); + + if (bw->block_list != g_list_first(bw->block_list)) + { + result = GPOINTER_TO_UINT(bw->block_list->data); + bw->block_list = g_list_previous(bw->block_list); + } + + return (result); +} + +uint16_t bwalker_last_indirect (bwalker *bw) +{ + uint16_t result = 0; + assert(bw != NULL); + assert(g_list_length(bw->indirect_list) > 0); + if(g_list_last(bw->indirect_list)) + { + result = (uint16_t) + GPOINTER_TO_UINT(g_list_last(bw->indirect_list)->data); + } + + return result; +} + +uint16_t bwalker_last_block (bwalker *bw) +{ + uint16_t result = 0; + assert (bw != NULL); + if(g_list_last(bw->block_list)) + result = GPOINTER_TO_UINT(g_list_last(bw->block_list)->data); + return result; +} + +uint16_t bwalker_block_is_last(bwalker *bw) +{ + assert(bw != NULL); + return (bw->block_list == g_list_last(bw->block_list)); +} +void bwalker_set_first(bwalker *bw) +{ + bw->block_list=g_list_first(bw->block_list); +} -- cgit v1.2.3-70-g09d2