static int push_frame(struct del_stack *s, dm_block_t b, unsigned level) { int r; uint32_t ref_count; if (s->top >= MAX_SPINE_DEPTH - 1) { DMERR("btree deletion stack out of memory"); return -ENOMEM; } r = dm_tm_ref(s->tm, b, &ref_count); if (r) return r; if (ref_count > 1) /* * This is a shared node, so we can just decrement it's * reference counter and leave the children. */ dm_tm_dec(s->tm, b); else { uint32_t flags; struct frame *f = s->spine + ++s->top; r = dm_tm_read_lock(s->tm, b, &btree_node_validator, &f->b); if (r) { s->top--; return r; } f->n = dm_block_data(f->b); f->level = level; f->nr_children = le32_to_cpu(f->n->header.nr_entries); f->current_child = 0; flags = le32_to_cpu(f->n->header.flags); if (flags & INTERNAL_NODE || is_internal_level(s->info, f)) prefetch_children(s, f); } return 0; }
static void block_dec(void *context, const void *value) { int r; uint64_t b; __le64 block_le; uint32_t ref_count; struct dm_block *block; struct array_block *ab; struct dm_array_info *info = context; memcpy(&block_le, value, sizeof(block_le)); b = le64_to_cpu(block_le); r = dm_tm_ref(info->btree_info.tm, b, &ref_count); if (r) { DMERR_LIMIT("couldn't get reference count for block %llu", (unsigned long long) b); return; } if (ref_count == 1) { /* * We're about to drop the last reference to this ablock. * So we need to decrement the ref count of the contents. */ r = get_ablock(info, b, &block, &ab); if (r) { DMERR_LIMIT("couldn't get array block %llu", (unsigned long long) b); return; } dec_ablock_entries(info, ab); unlock_ablock(info, block); } dm_tm_dec(info->btree_info.tm, b); }