int dm_array_get_value(struct dm_array_info *info, dm_block_t root, uint32_t index, void *value_le) { int r; struct dm_block *block; struct array_block *ab; size_t size_of_block; unsigned entry, max_entries; size_of_block = dm_bm_block_size(dm_tm_get_bm(info->btree_info.tm)); max_entries = calc_max_entries(info->value_type.size, size_of_block); r = lookup_ablock(info, root, index / max_entries, &block, &ab); if (r) return r; entry = index % max_entries; if (entry >= le32_to_cpu(ab->nr_entries)) r = -ENODATA; else memcpy(value_le, element_at(info, ab, entry), info->value_type.size); unlock_ablock(info, block); return r; }
static int walk_ablock(void *context, uint64_t *keys, void *leaf) { struct walk_info *wi = context; int r; unsigned i; __le64 block_le; unsigned nr_entries, max_entries; struct dm_block *block; struct array_block *ab; memcpy(&block_le, leaf, sizeof(block_le)); r = get_ablock(wi->info, le64_to_cpu(block_le), &block, &ab); if (r) return r; max_entries = le32_to_cpu(ab->max_entries); nr_entries = le32_to_cpu(ab->nr_entries); for (i = 0; i < nr_entries; i++) { r = wi->fn(wi->context, keys[0] * max_entries + i, element_at(wi->info, ab, i)); if (r) break; } unlock_ablock(wi->info, block); return r; }
/* * Utility function that calls one of the value_type methods on every value * in an array block. */ static void on_entries(struct dm_array_info *info, struct array_block *ab, void (*fn)(void *, const void *)) { unsigned i, nr_entries = le32_to_cpu(ab->nr_entries); for (i = 0; i < nr_entries; i++) fn(info->value_type.context, element_at(info, ab, i)); }
REAL matr_diag::at(size_t i, size_t j, size_t * next_j) const { bool zero = mask->get(j); if (zero) { if ( next_j ) *next_j = UINT_MAX; return REAL(0); } return element_at(i,j,next_j); };
ssize_t find_element(struct listy *ly, unsigned val) { if (element_at(ly, 0) == -1) return -1; // Zero-sized list ssize_t l = 1; ssize_t r; long long v = element_at(ly, l); while (v != -1 && v <= val) { if (v == val) { // We got lucky! return l; } l *= 2; v = element_at(ly, l); } r = l; l /= 2; while (l <= r) { ssize_t m = l+(r-l)/2; v = element_at(ly, m); if (v == -1) r = m-1; else if (v == val) return m; else if (v < val) l = m+1; else r = m-1; } return -1; }
/* * Remove some entries from the back of an array block. Every value * removed will be decremented. new_nr must be <= the current number of * entries. */ static void trim_ablock(struct dm_array_info *info, struct array_block *ab, unsigned new_nr) { unsigned i; uint32_t nr_entries; struct dm_btree_value_type *vt = &info->value_type; BUG_ON(new_nr > le32_to_cpu(ab->max_entries)); BUG_ON(new_nr > le32_to_cpu(ab->nr_entries)); nr_entries = le32_to_cpu(ab->nr_entries); for (i = nr_entries; i > new_nr; i--) if (vt->dec) vt->dec(vt->context, element_at(info, ab, i - 1)); ab->nr_entries = cpu_to_le32(new_nr); }
/* * Pad an array block out with a particular value. Every instance will * cause an increment of the value_type. new_nr must always be more than * the current number of entries. */ static void fill_ablock(struct dm_array_info *info, struct array_block *ab, const void *value, unsigned new_nr) { unsigned i; uint32_t nr_entries; struct dm_btree_value_type *vt = &info->value_type; BUG_ON(new_nr > le32_to_cpu(ab->max_entries)); BUG_ON(new_nr < le32_to_cpu(ab->nr_entries)); nr_entries = le32_to_cpu(ab->nr_entries); for (i = nr_entries; i < new_nr; i++) { if (vt->inc) vt->inc(vt->context, value); memcpy(element_at(info, ab, i), value, vt->size); } ab->nr_entries = cpu_to_le32(new_nr); }
static int array_set_value(struct dm_array_info *info, dm_block_t root, uint32_t index, const void *value, dm_block_t *new_root) { int r; struct dm_block *block; struct array_block *ab; size_t size_of_block; unsigned max_entries; unsigned entry; void *old_value; struct dm_btree_value_type *vt = &info->value_type; size_of_block = dm_bm_block_size(dm_tm_get_bm(info->btree_info.tm)); max_entries = calc_max_entries(info->value_type.size, size_of_block); r = shadow_ablock(info, &root, index / max_entries, &block, &ab); if (r) return r; *new_root = root; entry = index % max_entries; if (entry >= le32_to_cpu(ab->nr_entries)) { r = -ENODATA; goto out; } old_value = element_at(info, ab, entry); if (vt->dec && (!vt->equal || !vt->equal(vt->context, old_value, value))) { vt->dec(vt->context, old_value); if (vt->inc) vt->inc(vt->context, value); } memcpy(old_value, value, info->value_type.size); out: unlock_ablock(info, block); return r; }