📄 node40.c
字号:
nh_dec_free_space(entity, len); if (insert) { /* Setting up the fields of new item. */ ih_set_flags(ih, 0, entity->keypol); ih_set_offset(ih, offset, entity->keypol); /* Setting up node header. */ nh_inc_num_items(entity, count); nh_dec_free_space(entity, headers); } node40_mkdirty(entity); return 0;}/* General node40 cutting function. It is used from shift, remove, etc. It removes an amount of items specified by @count and shrinks node. */errno_t node40_shrink(reiser4_node_t *entity, pos_t *pos, uint32_t len, uint32_t count){ uint32_t size; void *cur, *end; void *src, *dst; uint32_t headers; uint32_t i, items; aal_assert("umka-1800", count > 0); aal_assert("umka-1799", pos != NULL); aal_assert("umka-1798", entity != NULL); items = nh_get_num_items(entity); end = node40_ih_at(entity, items - 1); if (pos->unit == MAX_UINT32) { headers = count * ih_size(entity->keypol); /* Moving item header and bodies if it is needed. */ if (pos->item + count < items) { /* Moving item bodies */ dst = node40_ib_at(entity, pos->item); src = dst + len; /* Remove operation in broken nodes cannot rely on free_space, do not use node40_size here. */ size = end - src; aal_memmove(dst, src, size); /* Moving item headers. */ src = node40_ih_at(entity, items - 1); dst = src + headers; size = (items - (pos->item + count)) * ih_size(entity->keypol); aal_memmove(dst, src, size); /* Updating item offsets. */ cur = node40_ih_at(entity, pos->item); for (i = pos->item; i < items - count; i++) { ih_dec_offset(cur, len, entity->keypol); cur -= ih_size(entity->keypol); } } /* Updating node header */ nh_dec_num_items(entity, count); nh_inc_free_space(entity, (len + headers)); } else { void *ih; uint32_t ilen; ih = node40_ih_at(entity, pos->item); ilen = node40_len_by_ih(entity, ih, pos, items); /* Moving item bodies */ src = node40_ib_at(entity, pos->item) + ilen; /* Remove operation in broken nodes cannot rely on free_space, use len instead. */ dst = src - len; size = end - src; aal_memmove(dst, src, size); /* Updating header offsets */ cur = ih - ih_size(entity->keypol); while (cur >= end) { ih_dec_offset(cur, len, entity->keypol); cur -= ih_size(entity->keypol); } /* Updating node header and item header */ nh_inc_free_space(entity, len); } nh_dec_free_space_start(entity, len); node40_mkdirty(entity); return 0;}/* Makes copy of @count items from @src_entity to @dst_entity */errno_t node40_copy(reiser4_node_t *dst_entity, pos_t *dst_pos, reiser4_node_t *src_entity, pos_t *src_pos, uint32_t count){ void *body; uint32_t pol; uint32_t size; void *ih, *end; void *src, *dst; uint32_t items; uint32_t fss, i; uint32_t offset; uint32_t headers; pol = dst_entity->keypol; headers = count * ih_size(pol); items = nh_get_num_items(dst_entity); fss = nh_get_free_space_start(dst_entity); size = node40_size(src_entity, src_pos, count); /* Copying item bodies from src node to dst one. */ src = node40_ib_at(src_entity, src_pos->item); if (dst_pos->item < items - count) { body = node40_ib_at(dst_entity, dst_pos->item); } else { body = dst_entity->block->data + fss - size; } aal_memcpy(body, src, size); /* Copying item headers from src node to dst one. */ src = node40_ih_at(src_entity, src_pos->item + count - 1); dst = node40_ih_at(dst_entity, dst_pos->item + count - 1); aal_memcpy(dst, src, headers); /* Updating item headers in dst node. */ end = node40_ih_at(dst_entity, items - 1); ih = dst + (ih_size(pol) * (count - 1)); offset = (body - dst_entity->block->data); for (i = 0; i < count; i++) { uint32_t old; old = ih_get_offset(ih, pol); ih_set_offset(ih, offset, pol); if (ih == end) { offset += fss - ih_get_offset(ih, pol); } else { offset += ih_get_offset((ih - ih_size(pol)), pol) - old; } ih -= ih_size(pol); } node40_mkdirty(dst_entity); return 0;}/* Mode modifying fucntion. */int64_t node40_modify(reiser4_node_t *entity, pos_t *pos, trans_hint_t *hint, modify_func_t modify_func){ void *ih; int64_t res; uint32_t pol; uint32_t len; int64_t write; reiser4_place_t place; len = hint->len + hint->overhead; /* Expand node if @len greater than zero. */ if ((res = node40_expand(entity, pos, len, 1))) { aal_error("Can't expand node for insert one " "more item/unit."); return res; } pol = entity->keypol; ih = node40_ih_at(entity, pos->item); /* Updating item header if we want to insert new item. */ if (pos->unit == MAX_UINT32) { ih_set_pid(ih, hint->plug->p.id.id, pol); aal_memcpy(ih, hint->offset.body, key_size(pol)); } /* Preparing place for calling item plugin with them. */ if (node40_fetch(entity, pos, &place)) return -EINVAL; /* Inserting units into @place. */ if ((write = modify_func(&place, hint)) < 0) { aal_error("Can't insert unit to node %llu, item %u.", entity->block->nr, place.pos.item); return write; } /* Updating item's key if we insert new item or if we insert unit into leftmost postion. */ if (pos->unit == 0) aal_memcpy(ih, place.key.body, key_size(pol)); return write;}static errno_t node40_insert(reiser4_node_t *entity, pos_t *pos, trans_hint_t *hint){ modify_func_t ins_func; aal_assert("umka-2448", pos != NULL); aal_assert("umka-1814", hint != NULL); aal_assert("umka-818", entity != NULL); ins_func = hint->plug->object->insert_units; return node40_modify(entity, pos, hint, ins_func);}static int64_t node40_write(reiser4_node_t *entity, pos_t *pos, trans_hint_t *hint){ modify_func_t write_func; aal_assert("umka-2449", pos != NULL); aal_assert("umka-2450", hint != NULL); aal_assert("umka-2451", entity != NULL); write_func = hint->plug->object->write_units; return node40_modify(entity, pos, hint, write_func);}/* Truncates node at @pos. Needed for tail conversion. */static int64_t node40_trunc(reiser4_node_t *entity, pos_t *pos, trans_hint_t *hint){ void *ih; uint32_t pol; uint32_t len; int64_t count; reiser4_place_t place; aal_assert("umka-2462", pos != NULL); aal_assert("umka-2463", entity != NULL); pol = entity->keypol; /* Getting item at @pos */ if (node40_fetch(entity, pos, &place)) return -EINVAL; /* Truncating item. */ count = objcall(&place, object->trunc_units, hint); if (count < 0) return count; len = hint->overhead + hint->len; /* Shrinking node and and update key. */ if (len > 0) { errno_t res; uint32_t number; number = count; place.pos.unit = 0; if (len >= place.len) { /* It seems that len cannot be > than place.len now. */ number = 1; place.pos.unit = MAX_UINT32; len = place.len; } if ((res = node40_shrink(entity, &place.pos, len, number))) { return res; } if (len < place.len) { ih = node40_ih_at(entity, place.pos.item); aal_memcpy(ih, place.key.body, key_size(pol)); } } else { ih = node40_ih_at(entity, place.pos.item); aal_memcpy(ih, place.key.body, key_size(pol)); } return count;}/* This function removes item/unit from the node at specified @pos */errno_t node40_remove(reiser4_node_t *entity, pos_t *pos, trans_hint_t *hint) { reiser4_place_t place; uint32_t count; uint32_t units; uint32_t len; errno_t res; aal_assert("umka-987", pos != NULL); aal_assert("umka-986", entity != NULL); /* Check if we remove some number of whole items, or units inside particular item. */ if (pos->unit == MAX_UINT32) { pos_t walk; /* Calculating amount of bytes removed item occupie. Node will be shrinked by this value. */ len = node40_size(entity, pos, hint->count); count = hint->count; if (hint->region_func) { POS_INIT(&walk, pos->item, MAX_UINT32); /* Calling layout function with @hint->region_func for each removed item in order to let higher levels know that some region is released. */ for (; walk.item < pos->item + count; walk.item++) { if (node40_fetch(entity, &walk, &place)) return -EINVAL; /* Not for nodeprt items. */ if (place.plug->p.id.group == PTR_ITEM) continue; /* Only if item has a block layout. */ if (!place.plug->object->layout) continue; objcall(&place, object->layout, hint->region_func, hint->data); } } } else { /* Here we init @count (number of items to be removed) to 1, as here are possible only two cases: (1) Remove item as it get empty (the case when @count is needed). (2) Shrink item at @place.pos.item by @len and @count is ignored. */ if (node40_fetch(entity, pos, &place)) return -EINVAL; units = objcall(&place, balance->units); count = 1; if (place.plug->object->remove_units) { /* Removing units from the item pointed by @pos. */ if ((res = objcall(&place, object->remove_units, hint))) return res; } /* Check if item is empty. If so, we remove it too. */ if ((len = hint->len + hint->overhead) >= place.len || units == hint->count) { /* Forcing node40_shrink() to remove whole item, as we have removed all units from it.*/ len = place.len; pos->unit = MAX_UINT32; } else { uint32_t pol = entity->keypol; /* Updating items key if leftmost unit was changed and item will not be removed as it is not yet empty. */ if (pos->unit == 0) { void *ih = node40_ih_at(entity, pos->item); aal_memcpy(ih, place.key.body, key_size(pol)); } } } /* Shrinking node by @hint->len. Item @place.pos will be removed if place.pos points to whole item (unit is MAX_UINT32). */ return node40_shrink(entity, pos, len, count);}/* Fuses two mergeable items if they lie in the same node side by side. This is needed for fsck if it discovered, that two items are mergeable and lie in the same node (due to some corruption or fail) it will merge them. */static errno_t node40_merge(reiser4_node_t *entity, pos_t *left_pos, pos_t *right_pos){ errno_t res; uint32_t pol; int32_t delta; uint32_t items; void *left, *right; reiser4_place_t left_place; reiser4_place_t right_place; aal_assert("umka-2682", entity != NULL); aal_assert("umka-2683", left_pos != NULL); aal_assert("umka-2684", right_pos != NULL);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -