aboutsummaryrefslogtreecommitdiff
path: root/block_walker.c
diff options
context:
space:
mode:
Diffstat (limited to 'block_walker.c')
-rw-r--r--block_walker.c368
1 files changed, 368 insertions, 0 deletions
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 <assert.h>
+#include <glib.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <time.h>
+
+#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);
+}