#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); }