static int sm_metadata_new_block_(struct dm_space_map *sm, dm_block_t *b) { int r, r2 = 0; enum allocation_event ev; struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm); r = sm_ll_find_free_block(&smm->old_ll, smm->begin, smm->old_ll.nr_blocks, b); if (r) return r; smm->begin = *b + 1; if (recursing(smm)) r = add_bop(smm, BOP_INC, *b); else { in(smm); r = sm_ll_inc(&smm->ll, *b, &ev); r2 = out(smm); } if (!r) smm->allocated_this_transaction++; return combine_errors(r, r2); }
static int sm_metadata_extend(struct dm_space_map *sm, dm_block_t extra_blocks) { int r, i; struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm); dm_block_t old_len = smm->ll.nr_blocks; /* * Flick into a mode where all blocks get allocated in the new area. */ smm->begin = old_len; memcpy(sm, &bootstrap_ops, sizeof(*sm)); /* * Extend. */ r = sm_ll_extend(&smm->ll, extra_blocks); if (r) goto out; /* * We repeatedly increment then commit until the commit doesn't * allocate any new blocks. */ do { for (i = old_len; !r && i < smm->begin; i++) r = add_bop(smm, BOP_INC, i); if (r) goto out; old_len = smm->begin; r = apply_bops(smm); if (r) { DMERR("%s: apply_bops failed", __func__); goto out; } r = sm_ll_commit(&smm->ll); if (r) goto out; } while (old_len != smm->begin); out: /* * Switch back to normal behaviour. */ memcpy(sm, &ops, sizeof(*sm)); return r; }
static int sm_metadata_dec_block(struct dm_space_map *sm, dm_block_t b) { int r, r2 = 0; enum allocation_event ev; struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm); if (recursing(smm)) r = add_bop(smm, BOP_DEC, b); else { in(smm); r = sm_ll_dec(&smm->ll, b, &ev); r2 = out(smm); } return combine_errors(r, r2); }
int dm_sm_metadata_create(struct dm_space_map *sm, struct dm_transaction_manager *tm, dm_block_t nr_blocks, dm_block_t superblock) { int r; dm_block_t i; struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm); smm->begin = superblock + 1; smm->recursion_count = 0; smm->allocated_this_transaction = 0; brb_init(&smm->uncommitted); threshold_init(&smm->threshold); memcpy(&smm->sm, &bootstrap_ops, sizeof(smm->sm)); r = sm_ll_new_metadata(&smm->ll, tm); if (!r) { if (nr_blocks > DM_SM_METADATA_MAX_BLOCKS) nr_blocks = DM_SM_METADATA_MAX_BLOCKS; r = sm_ll_extend(&smm->ll, nr_blocks); } memcpy(&smm->sm, &ops, sizeof(smm->sm)); if (r) return r; /* * Now we need to update the newly created data structures with the * allocated blocks that they were built from. */ for (i = superblock; !r && i < smm->begin; i++) r = add_bop(smm, BOP_INC, i); if (r) return r; r = apply_bops(smm); if (r) { DMERR("%s: apply_bops failed", __func__); return r; } return sm_metadata_commit(sm); }
static int sm_bootstrap_dec_block(struct dm_space_map *sm, dm_block_t b) { struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm); return add_bop(smm, BOP_DEC, b); }