/* * Read metadata block from disk, possibly create it if it does not exist and * and open flags allow */ static int read_meta(TEE_Result *errno, struct sql_fs_fd *fdp) { size_t msize = meta_size(); size_t out_size = sizeof(fdp->meta); uint8_t *meta = NULL; int rc = -1; *errno = TEE_ERROR_GENERIC; meta = malloc(msize); if (!meta) { *errno = TEE_ERROR_OUT_OF_MEMORY; goto exit; } rc = tee_fs_rpc_lseek(OPTEE_MSG_RPC_CMD_SQL_FS, fdp->fd, 0, TEE_FS_SEEK_SET); if (rc < 0) goto exit; rc = sql_fs_read_rpc(fdp->fd, meta, msize); if (rc < 0) { /* Read error */ goto exit; } else if (rc == 0) { /* No meta data on disk yet */ if (!(fdp->flags & TEE_FS_O_CREATE)) goto exit; rc = create_meta(errno, fdp); } else if (rc == (int)msize) { #ifdef CFG_ENC_FS TEE_Result res; res = tee_fs_decrypt_file(META_FILE, meta, msize, (uint8_t *)&fdp->meta, &out_size, fdp->encrypted_fek); if (res != TEE_SUCCESS) { *errno = res; rc = -1; goto exit; } #else memcpy((uint8_t *)&fdp->meta, meta + tee_fs_get_header_size(META_FILE), out_size); #endif rc = 0; } else { /* Unexpected data length */ rc = -1; } exit: free(meta); return rc; }
unsigned long get_data_segment_free_space_size(){ metadata_t *head = NULL; int i = 0; unsigned long result = 0; for (i = 0; i < ARRAY_SIZE; i++) { head = freelist_arr[i]; while (head != NULL) { result += meta_size(head); head = head->next; } } return result; }
/* Given a position in the user data, return the offset in the DB file */ static tee_fs_off_t pos_to_raw(tee_fs_off_t pos) { tee_fs_off_t res; if (pos < 0) return -1; res = meta_size() + block_num(pos) * block_size_raw(); if (pos % BLOCK_SIZE) { res += block_header_size(); res += pos % BLOCK_SIZE; } return res; }
void add_node(metadata_t *node) { int idx = array_idx(meta_size(node)); if (!freelist_arr[idx]) { freelist_arr[idx] = node; node->prev = NULL; node->next = NULL; } else { node->prev = NULL; node->next = freelist_arr[idx]; freelist_arr[idx]->prev = node; freelist_arr[idx] = node; } }
static int write_meta(TEE_Result *errno, struct sql_fs_fd *fdp) { int fd = fdp->fd; size_t ct_size = meta_size(); uint8_t *ct; int rc = -1; *errno = TEE_ERROR_GENERIC; ct = malloc(ct_size); if (!ct) { *errno = TEE_ERROR_OUT_OF_MEMORY; goto exit; } rc = tee_fs_rpc_lseek(OPTEE_MSG_RPC_CMD_SQL_FS, fd, 0, TEE_FS_SEEK_SET); if (rc < 0) goto exit; #ifdef CFG_ENC_FS { TEE_Result res; res = tee_fs_encrypt_file(META_FILE, (const uint8_t *)&fdp->meta, sizeof(fdp->meta), ct, &ct_size, fdp->encrypted_fek); if (res != TEE_SUCCESS) { *errno = res; rc = -1; goto exit; } } #else copy_data(META_FILE, ct, (const uint8_t *)&fdp->meta, sizeof(fdp->meta)); #endif rc = sql_fs_write_rpc(fdp->fd, ct, ct_size); if (rc != (int)ct_size) rc = -1; else rc = 0; exit: free(ct); return rc; }
/* Given a position in the DB file, return the offset in the user data */ static tee_fs_off_t raw_to_pos(tee_fs_off_t raw_pos) { tee_fs_off_t pos = raw_pos; ssize_t n = block_num_raw(raw_pos); if (n < 0) return -1; pos -= meta_size(); pos -= block_header_size(); if (pos < 0) return -1; return (n * BLOCK_SIZE) + (pos % BLOCK_SIZE); }
void* dmalloc(size_t numbytes, int flag) { if(!is_init) { //Initialize through sbrk call first time if(!dmalloc_init()) { return NULL; } } assert(numbytes > 0); /* Your code goes here */ size_t space = ALIGN(numbytes); // go over the linked list, find the first fit //metadata_t* flpt = freelist; metadata_t* flpt = find_fit(space, flag); if (!flpt) { //return NULL; if (!(flpt = extend_heap(space))) { printf("extend heap failed! \n"); return NULL; } } size_t rest = meta_size(flpt) - space; delete_node(flpt); if (rest < ALIGN(META_SIZE + FOOTER_SIZE + 1)) { set_alloc(flpt); set_alloc((metadata_t *)(to_footer(to_block(flpt)))); } else { rest = rest - META_SIZE - FOOTER_SIZE; set_size(flpt, space); set_alloc(flpt); set_size((metadata_t *)(to_footer(to_block(flpt))), space); set_alloc((metadata_t *)(to_footer(to_block(flpt)))); metadata_t* newmt = (metadata_t *)((void *)flpt + META_SIZE + space + FOOTER_SIZE); set_size(newmt, rest); set_free(newmt); set_size((metadata_t *)to_footer(to_block(newmt)), rest); set_free((metadata_t *)to_footer(to_block(newmt))); add_node(newmt); } void * result = to_block(flpt); assert(result != NULL); if (!result) { int a = 1; } return result; }
metadata_t * find_fit(size_t space, int flag) { int idx = array_idx(space); metadata_t *flpt = NULL; if (flag == FF) { while (idx < ARRAY_SIZE) { flpt = freelist_arr[idx]; while (flpt) { if (meta_size(flpt) < space) { flpt = flpt->next; } else { return flpt; } } idx++; } return NULL; } else if (flag == BF) { size_t redundant = ~(size_t)0x00; metadata_t *result = NULL; while (idx < ARRAY_SIZE && result == NULL) { flpt = freelist_arr[idx]; while (flpt) { if (meta_size(flpt) == space) { return flpt; } else if (meta_size(flpt) > space && redundant > meta_size(flpt) - space) { result = flpt; redundant = meta_size(flpt) - space; } flpt = flpt->next; } idx++; } return result; } else if (flag == WF) { metadata_t *result = NULL; int i = ARRAY_SIZE - 1; for (; i >= idx && !result; i--) { flpt = freelist_arr[i]; while (flpt && !result) { if (meta_size(flpt) >= space) { result = flpt; } flpt = flpt->next; } } return result; } return NULL; }
bool dmalloc_init() { /* Two choices: * 1. Append prologue and epilogue blocks to the start and the end of the freelist * 2. Initialize freelist pointers to NULL * * Note: We provide the code for 2. Using 1 will help you to tackle the * corner cases succinctly. */ is_init = true; size_t max_bytes = ALIGN(MAX_HEAP_SIZE); int i = 0; for (i = 0; i < ARRAY_SIZE; i++) { freelist_arr[i] = NULL; } metadata_t *fl = (metadata_t*) sbrk(max_bytes); // returns heap_region, which is initialized to freelist heap_begin = fl; /* Q: Why casting is used? i.e., why (void*)-1? */ if (fl == (void *)-1) return false; //prologue block footer_t* prologue = (footer_t *)fl; set_size((metadata_t *)prologue, 0); set_alloc((metadata_t *)prologue); //epilogue block metadata_t* epilogue = (metadata_t *)((void *)fl + max_bytes - META_SIZE); set_size(epilogue, 0); set_alloc(epilogue); //freelist fl = (metadata_t *)((void *)fl + FOOTER_SIZE); set_size(fl, max_bytes - 2 * META_SIZE - 2 * FOOTER_SIZE); set_free(fl); set_size((metadata_t *)to_footer(to_block(fl)), meta_size(fl)); set_free((metadata_t *)to_footer(to_block(fl))); fl->next = NULL; fl->prev = NULL; add_node(fl); return true; }
void delete_node(metadata_t *node) { size_t space = meta_size(node); int idx = array_idx(space); if (!node->prev && !node->next) { freelist_arr[idx] = NULL; } else if (!node->prev) { freelist_arr[idx] = node->next; node->next = NULL; freelist_arr[idx]->prev = NULL; } else if (!node->next) { node->prev->next = NULL; node->prev = NULL; } else { node->prev->next = node->next; node->next->prev = node->prev; node->prev = NULL; node->next = NULL; } }
/* Return the position of a block in the DB file */ static ssize_t block_pos_raw(size_t block_num) { return meta_size() + block_num * block_size_raw(); }
/* Return the block number from a position in the DB file */ static ssize_t block_num_raw(tee_fs_off_t raw_pos) { return (raw_pos - meta_size()) / block_size_raw(); }
inline size_t block_size(void *bp) { return meta_size(to_meta(bp)); }
inline void set_footer_size(metadata_t *mt, size_t s) { footer_t* ft = (footer_t *) ((void *)(mt) + META_SIZE + meta_size(mt) + FOOTER_SIZE); ft->size = s; }