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; enum allocation_event ev; 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 = sm_ll_inc(&smm->ll, i, &ev); 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; }
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; enum allocation_event ev; 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) return r; if (nr_blocks > DM_SM_METADATA_MAX_BLOCKS) nr_blocks = DM_SM_METADATA_MAX_BLOCKS; r = sm_ll_extend(&smm->ll, nr_blocks); if (r) return r; memcpy(&smm->sm, &ops, sizeof(smm->sm)); /* * 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 = sm_ll_inc(&smm->ll, i, &ev); 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_metadata_inc_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_INC, b); else { in(smm); r = sm_ll_inc(&smm->ll, b, &ev); r2 = out(smm); } return combine_errors(r, r2); }
static int commit_bop(struct sm_metadata *smm, struct block_op *op) { int r = 0; enum allocation_event ev; switch (op->type) { case BOP_INC: r = sm_ll_inc(&smm->ll, op->block, &ev); break; case BOP_DEC: r = sm_ll_dec(&smm->ll, op->block, &ev); break; } return r; }
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; enum allocation_event ev; struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm); smm->begin = superblock + 1; smm->recursion_count = 0; smm->allocated_this_transaction = 0; smm->nr_uncommitted = 0; memcpy(&smm->sm, &bootstrap_ops, sizeof(smm->sm)); r = sm_ll_new_metadata(&smm->ll, tm); if (r) return r; r = sm_ll_extend(&smm->ll, nr_blocks); if (r) return r; memcpy(&smm->sm, &ops, sizeof(smm->sm)); /* * 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 = sm_ll_inc(&smm->ll, i, &ev); if (r) return r; return sm_metadata_commit(sm); }