From f1d4094566f7ac14b33b39f15407c6659c64ea4f Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Tue, 31 Mar 2015 00:25:37 +0100 Subject: allocate small block using block use bitmaps to find free entries. --- content/fs_backing_store.c | 81 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 69 insertions(+), 12 deletions(-) (limited to 'content/fs_backing_store.c') diff --git a/content/fs_backing_store.c b/content/fs_backing_store.c index 548a5efe5..089e1cccc 100644 --- a/content/fs_backing_store.c +++ b/content/fs_backing_store.c @@ -100,7 +100,6 @@ /** length in bytes of a block files use map */ #define BLOCK_USE_MAP_SIZE (1 << (BLOCK_ENTRY_COUNT - 3)) - /** * The type used to store index values refering to store entries. Care * must be taken with this type as it is used to build address to @@ -204,6 +203,14 @@ struct block_file { uint8_t use_map[BLOCK_USE_MAP_SIZE]; }; +/** + * log2 of block size. + */ +static const unsigned int log2_block_size[ENTRY_ELEM_COUNT] = { + BLOCK_DATA_SIZE, /**< Data block size */ + BLOCK_META_SIZE /**< Metadata block size */ +}; + /** * Parameters controlling the backing store. */ @@ -831,6 +838,36 @@ get_store_entry(struct store_state *state, nsurl *url, struct store_entry **bse) return NSERROR_OK; } +/** + * Find next available small block. + */ +static block_index_t alloc_block(struct store_state *state, int elem_idx) +{ + int bf; + int idx; + int bit; + uint8_t *map; + + for (bf = 0; bf < BLOCK_FILE_COUNT; bf++) { + map = &state->blocks[elem_idx][bf].use_map[0]; + + for (idx = 0; idx < BLOCK_USE_MAP_SIZE; idx++) { + if (*(map + idx) != 0xff) { + /* located an unused block */ + for (bit = 0; bit < 8;bit++) { + if (((*(map + idx)) & (1U << bit)) == 0) { + /* mark block as used */ + *(map + idx) |= 1U << bit; + state->blocks_dirty = true; + return (((bf * BLOCK_USE_MAP_SIZE) + idx) * 8) + bit; + } + } + } + } + } + + return 0; +} /** * Set a backing store entry in the entry table from a url. @@ -931,6 +968,11 @@ set_store_entry(struct store_state *state, elem->size = datalen; state->total_alloc += elem->size; + /* if the elemnt will fit in a small block attempt to allocate one */ + if (elem->size <= (1U << log2_block_size[elem_idx])) { + elem->block = alloc_block(state, elem_idx); + } + /* ensure control maintinance scheduled. */ state->entries_dirty = true; guit->browser->schedule(CONTROL_MAINT_TIME, control_maintinance, state); @@ -1134,6 +1176,8 @@ read_blocks(struct store_state *state) return ret; } + LOG(("Initialising block use map from %s", fname)); + fd = open(fname, O_RDWR); free(fname); if (fd != -1) { @@ -1153,6 +1197,7 @@ read_blocks(struct store_state *state) close(fd); } else { + LOG(("Initialising block use map to defaults")); /* ensure block 0 (invalid sentinal) is skipped */ state->blocks[ENTRY_ELEM_DATA][0].use_map[0] = 1; state->blocks[ENTRY_ELEM_META][0].use_map[0] = 1; @@ -1458,11 +1503,23 @@ initialise(const struct llcache_store_parameters *parameters) static nserror finalise(void) { + int bf; /* block file index */ + if (storestate != NULL) { guit->browser->schedule(-1, control_maintinance, storestate); write_entries(storestate); write_blocks(storestate); + /* ensure all block files are closed */ + for (bf = 0; bf < BLOCK_FILE_COUNT; bf++) { + if (storestate->blocks[ENTRY_ELEM_DATA][bf].fd != -1) { + close(storestate->blocks[ENTRY_ELEM_DATA][bf].fd); + } + if (storestate->blocks[ENTRY_ELEM_META][bf].fd != -1) { + close(storestate->blocks[ENTRY_ELEM_META][bf].fd); + } + } + /* avoid division by zero */ if (storestate->miss_count == 0) { storestate->miss_count = 1; @@ -1494,7 +1551,7 @@ static nserror store_write_block(struct store_state *state, { block_index_t bf = (bse->elem[elem_idx].block >> BLOCK_ENTRY_COUNT) & ((1 << BLOCK_FILE_COUNT) - 1); /* block file block resides in */ - block_index_t bi = bse->elem[elem_idx].block & ((1 << BLOCK_ENTRY_COUNT) -1); /* block index in file */ + block_index_t bi = bse->elem[elem_idx].block & ((1U << BLOCK_ENTRY_COUNT) -1); /* block index in file */ ssize_t wr; off_t offst; @@ -1507,17 +1564,17 @@ static nserror store_write_block(struct store_state *state, return NSERROR_SAVE_FAILED; } - if (elem_idx == ENTRY_ELEM_META) { - offst = bi << BLOCK_META_SIZE; - } else { - offst = bi << BLOCK_DATA_SIZE; - } + offst = bi << log2_block_size[elem_idx]; wr = pwrite(state->blocks[elem_idx][bf].fd, bse->elem[elem_idx].data, bse->elem[elem_idx].size, offst); + LOG(("Wrote %d of %d bytes from %p at 0x%x block %d", + wr, bse->elem[elem_idx].size, bse->elem[elem_idx].data, + offst, bse->elem[elem_idx].block)); + if (wr != bse->elem[elem_idx].size) { return NSERROR_SAVE_FAILED; } @@ -1655,17 +1712,17 @@ static nserror store_read_block(struct store_state *state, return NSERROR_SAVE_FAILED; } - if (elem_idx == ENTRY_ELEM_META) { - offst = bi << BLOCK_META_SIZE; - } else { - offst = bi << BLOCK_DATA_SIZE; - } + offst = bi << log2_block_size[elem_idx]; rd = pread(state->blocks[elem_idx][bf].fd, bse->elem[elem_idx].data, bse->elem[elem_idx].size, offst); + LOG(("Read %d of %d bytes into %p from 0x%x block %d", + rd, bse->elem[elem_idx].size, bse->elem[elem_idx].data, + offst, bse->elem[elem_idx].block)); + if (rd != bse->elem[elem_idx].size) { return NSERROR_SAVE_FAILED; } -- cgit v1.2.3