size_t block_store_write(block_store_t *const bs, const size_t block_id, const void *buffer, const size_t nbytes, const size_t offset) { if (bs && bs->fbm && bs->data_blocks && BLOCKID_VALID(block_id) && buffer && nbytes && (nbytes + offset <= BLOCK_SIZE)) { size_t total_offset = offset + (BLOCK_SIZE * (block_id - FBM_SIZE)); memcpy((void *)(bs->data_blocks + total_offset), buffer, nbytes); block_store_errno = bitmap_test(bs->fbm, block_id) ? BS_OK : BS_FBM_REQUEST_MISMATCH; return nbytes; } block_store_errno = BS_FATAL; return 0; }
// Need to refactor this for V3. Have this switch on FILE_BASED and have it either do // block_mem_write or block_file_write (both with same params) which then handles everything // (same for read) size_t block_store_write(block_store_t *const bs, const size_t block_id, const void *buffer, const size_t nbytes, const size_t offset) { if (bs && BLOCKID_VALID(block_id) && buffer && nbytes && (nbytes + offset <= BLOCK_SIZE)) { // Not going to forbid writing of not-in-use blocks (but we'll log it via errno) bitmap_set(bs->dbm, block_id); FLAG_SET(bs, DIRTY); memcpy((void *)(bs->data_blocks + BLOCK_OFFSET_POSITION(block_id, offset)), buffer, nbytes); bs_errno = bitmap_test(bs->fbm, block_id) ? BS_OK : BS_REQUEST_MISMATCH; return nbytes; } bs_errno = BS_PARAM; return 0; }
size_t block_store_release(block_store_t *const bs, const size_t block_id) { if (bs && bs->fbm && BLOCKID_VALID(block_id)) { // we could clear the dirty bit, since the info is no longer in use but... // We'll keep it. Could be useful. Doesn't really hurt anything. // Keeps it more true to a standard block device. // You could also use this function to format the specified block for security reasons bitmap_reset(bs->fbm, block_id); block_store_errno = BS_OK; return block_id; } block_store_errno = BS_PARAM; return 0; }
size_t block_store_read(const block_store_t *const bs, const size_t block_id, void *buffer, const size_t nbytes, const size_t offset) { if (bs && BLOCKID_VALID(block_id) && buffer && nbytes && (nbytes + offset <= BLOCK_SIZE)) { // Not going to forbid reading of not-in-use blocks (but we'll log it via the errno) memcpy(buffer, bs->data_blocks + BLOCK_OFFSET_POSITION(block_id, offset), nbytes); bs_errno = bitmap_test(bs->fbm, block_id) ? BS_OK : BS_REQUEST_MISMATCH; return nbytes; } // technically we return BS_PARAM even if the internal structure of the BS object is busted // Which, in reality, would be more of a BS_INTERNAL or a BS_FATAL... but it'll add another branch to everything // And technically the bs is a parameter... bs_errno = BS_PARAM; return 0; }
bool block_store_request(block_store_t *const bs, const size_t block_id) { if (bs && BLOCKID_VALID(block_id)) { if (!bitmap_test(bs->fbm, block_id)) { bitmap_set(bs->fbm, block_id); bitmap_set(bs->dbm, FBM_BLOCK_CHANGE_LOCATION(block_id)); // Set that FBM block as changed FLAG_SET(bs, DIRTY); bs_errno = BS_OK; return true; } else { bs_errno = BS_IN_USE; return false; } } bs_errno = BS_PARAM; return false; }