📄 extent40.c
字号:
reiser4_key_t key; uint64_t unit_size; uint64_t max_off; uint64_t ins_off; uint64_t uni_off; uint64_t blk_off; uint64_t total; uint64_t start; int64_t count; int64_t bytes; int64_t size; uint32_t unit_pos; uint32_t blksize; uint32_t width; uint32_t units; errno_t res; char *buff; aal_assert("umka-2357", hint != NULL); aal_assert("umka-2356", place != NULL); /* Correcting insert point, as it may point to -1 (create new item) and behind last unit (adding data at the end of item). */ if (place->pos.unit == MAX_UINT32) place->pos.unit = 0; hint->bytes = 0; buff = hint->specific; unit_pos = place->pos.unit; units = extent40_units(place); device = extent40_device(place); blksize = place_blksize(place); /* Get the offset range being handled: ins_off, max_off. */ ins_off = objcall(&hint->offset, get_offset); max_off = objcall(&hint->maxkey, get_offset); total = max_off - ins_off; count = total; if (hint->insert_flags & ET40_OVERWRITE) { /* If overwrite requires space, split the unit correctly. */ extent = extent40_body(place) + unit_pos; uni_off = extent40_offset(place, unit_pos); /* This loop checks if we insert some data inside extent and we should take into account possible holes. */ for ( ; count > 0 && unit_pos < units; count -= size, unit_pos++, extent++, ins_off += size, uni_off += unit_size) { start = et40_get_start(extent); width = et40_get_width(extent); unit_size = width * blksize; size = unit_size - (ins_off - uni_off); if (size > count) size = count; if (start != EXTENT_HOLE_UNIT || !buff) continue; /* Overwrite the hole with the data. (1) the whole hole gets overwritten; (2) a part of it, needs to be splitted; (3) a middle part, 2 splits are needed. */ aal_assert("vpf-1700", ins_off >= uni_off); if (ins_off >= uni_off + blksize) { /* Overwrite the tail. */ /* Add the unit after the current one. */ extent40_expand(place, unit_pos + 1, 1); /* Get the size of the current. */ unit_size = ins_off - uni_off; unit_size /= blksize; aal_assert("vpf-1699", width > unit_size); /* Reset widths of the current and the next. */ et40_set_width(extent, unit_size); et40_set_width(extent + 1, width - unit_size); et40_set_start(extent + 1, EXTENT_HOLE_UNIT); /* Recalc the unit size values. */ unit_size *= blksize; size = 0; } if (ins_off + size + blksize <= uni_off + unit_size) { /* Overwrite the head. */ /* Add the unit after the current one. */ extent40_expand(place, unit_pos + 1, 1); /* Get the size of the next. */ unit_size = ins_off + size - uni_off; unit_size = (unit_size + blksize - 1) / blksize; aal_assert("vpf-1701", width > unit_size); /* Reset widths of the current and the next. */ et40_set_width(extent, unit_size); et40_set_width(extent + 1, width - unit_size); et40_set_start(extent + 1, EXTENT_HOLE_UNIT); /* Recalc the unit size values. */ unit_size *= blksize; } if (!size) continue; et40_set_start(extent, EXTENT_UNALLOC_UNIT); /* Size bytes are to be written to this unit. */ bytes = extent40_alloc_block(place, hint->blocks, ins_off, size); if (bytes < 0) return bytes; hint->bytes += bytes; aal_assert("vpf-1703", bytes == width * blksize); } } else { int allocate = 0; /* Calculating width in blocks of new unit to be inserted. */ width = max_off - ins_off; width = (width + blksize - 1) / blksize; if (unit_pos && (hint->insert_flags & ET40_JOIN)) { /* Some units exist and new get merged with the last. */ /* Increment the width of the last unit. */ place->pos.unit--; unit_pos--; extent = extent40_body(place) + unit_pos; start = et40_get_start(extent); et40_inc_width(extent, width); allocate = (start == EXTENT_UNALLOC_UNIT); } else { /* First unit or cannot merge with the last one. */ extent = extent40_body(place) + unit_pos; /* If some data are being inserted, allocate some blocks for them later. */ if (buff) { et40_set_start(extent, EXTENT_UNALLOC_UNIT); allocate = 1; } else { et40_set_start(extent, EXTENT_HOLE_UNIT); } et40_set_width(extent, width); } if (allocate) { if ((bytes = extent40_alloc_block(place, hint->blocks, ins_off, count)) < 0) { return bytes; } hint->bytes += bytes; aal_assert("vpf-1703", bytes == width * blksize); } } /* Updating @key by unit key as it is changed. */ extent40_fetch_key(place, &key); extent = extent40_body(place) + place->pos.unit; uni_off = objcall(&key, get_offset); ins_off = objcall(&hint->offset, get_offset); count = total; /* Second stage -- writing data to allocated blocks. */ for ( ; count > 0; count -= size, ins_off += size) { blk_t blk; /* Calculating size to be written this time. */ size = blksize - (ins_off & (blksize - 1)); /* Block offset we will insert in. */ blk_off = ins_off - (ins_off & (blksize - 1)); if (size > count) size = count; /* Preparing key for getting data by it. */ objcall(&key, set_offset, blk_off); /* Checking if we write data inside item. */ aal_assert("vpf-1705", blk_off + size <= max_off); start = et40_get_start(extent); width = et40_get_width(extent); /* Nothing to be done if hole gets overwritten with hole. */ if (start == EXTENT_HOLE_UNIT && !buff) continue; /* Blocks must be allocated already. */ aal_assert("vpf-1706", start != EXTENT_HOLE_UNIT); blk = (blk_off - uni_off) / blksize; if (!(block = extent40_load_block(place, hint->blocks, &key, start, blk))) { return -EINVAL; } /* Writting data to @block. */ if (buff) { aal_memcpy(block->data + ins_off - blk_off, buff, size); buff += size; } else { /* Writting a hole. */ aal_memset(block->data + ins_off - blk_off, 0, size); } block->dirty = 1; if (blk == width) { extent++; uni_off += (width * blksize); } } if ((res = extent40_core->tree_ops.mpressure(place->node->tree))) return res; place_mkdirty(place); return total;}/* Calls @region_func for each block number extent points to. It is needed for calculating fragmentation, etc. */static errno_t extent40_layout(reiser4_place_t *place, region_func_t region_func, void *data){ extent40_t *extent; uint32_t i, units; errno_t res = 0; aal_assert("umka-1747", place != NULL); aal_assert("umka-1748", region_func != NULL); extent = extent40_body(place); units = extent40_units(place); for (i = 0; i < units; i++, extent++) { uint64_t start; uint64_t width; start = et40_get_start(extent); if (start == EXTENT_UNALLOC_UNIT || start == EXTENT_HOLE_UNIT) continue; width = et40_get_width(extent); if ((res = region_func(start, width, data))) return res; } return 0;}/* Estimates how many bytes may be shifted into neighbour item */static errno_t extent40_prep_shift(reiser4_place_t *src_place, reiser4_place_t *dst_place, shift_hint_t *hint){ int check_point; uint32_t units; aal_assert("umka-1705", hint != NULL); aal_assert("umka-1704", src_place != NULL); hint->units_number = 0; check_point = (src_place->pos.item == hint->pos.item && hint->pos.unit != MAX_UINT32); if (hint->control & SF_ALLOW_LEFT) { uint32_t left; /* If we have to take into account insert point. */ if (hint->control & SF_UPDATE_POINT && check_point) { left = hint->pos.unit * sizeof(extent40_t); if (hint->control & SF_HOLD_POS && hint->control & SF_MOVE_POINT) { units = extent40_units(src_place); if (units > hint->pos.unit) left += sizeof(extent40_t); } if (hint->units_bytes > left) hint->units_bytes = left; /* Units to be moved. */ units = hint->units_bytes / sizeof(extent40_t); if (hint->pos.unit <= units && (hint->control & SF_MOVE_POINT)) { hint->result |= SF_MOVE_POINT; hint->pos.unit = dst_place ? dst_place->len : 0; hint->pos.unit += hint->units_bytes; hint->pos.unit /= sizeof(extent40_t); if (hint->control & SF_HOLD_POS) hint->pos.unit--; } else { hint->pos.unit -= hint->units_bytes / sizeof(extent40_t); } } else { if (hint->units_bytes > src_place->len) hint->units_bytes = src_place->len; } } else { uint32_t right; /* The same check as abowe, but for right shift */ if (hint->control & SF_UPDATE_POINT && check_point) { units = extent40_units(src_place); /* Check is it is possible to move something into right neighbour item. */ if (hint->pos.unit < units) { units -= hint->pos.unit; units *= sizeof(extent40_t); right = units; if (hint->control & SF_HOLD_POS && !(hint->control & SF_MOVE_POINT)) { right -= sizeof(extent40_t); } if (hint->units_bytes > right) hint->units_bytes = right; if ((hint->control & SF_MOVE_POINT) && hint->units_bytes == units) { hint->result |= SF_MOVE_POINT; hint->pos.unit = 0; } } else { /* There is noning to move, update insert point, flags and out. */ if (hint->control & SF_MOVE_POINT) { hint->result |= SF_MOVE_POINT; hint->pos.unit = 0; } hint->units_bytes = 0; } } else { if (hint->units_bytes > src_place->len) hint->units_bytes = src_place->len; } } hint->units_bytes -= hint->units_bytes % sizeof(extent40_t); hint->units_number = hint->units_bytes / sizeof(extent40_t); return 0;}static errno_t extent40_shift_units(reiser4_place_t *src_place, reiser4_place_t *dst_place, shift_hint_t *hint){ uint32_t pos; aal_assert("umka-1708", hint != NULL); aal_assert("umka-1706", src_place != NULL); aal_assert("umka-1707", dst_place != NULL); if (hint->control & SF_ALLOW_LEFT) { pos = extent40_units(dst_place) - hint->units_number; /* Preparing space in @dst_place. */ extent40_expand(dst_place, pos, hint->units_number); /* Copying data from the @src_place to @dst_place. */ extent40_copy(dst_place, pos, src_place, 0, hint->units_number); /* Updating item's key by the first unit key. */ body40_get_key(src_place, hint->units_number, &src_place->key, extent40_offset); /* Removing units in @src_place. */ extent40_shrink(src_place, 0, hint->units_number); } else { /* Preparing space in @dst_place */ extent40_expand(dst_place, 0, hint->units_number); /* Copying data from the @src_place to @dst_place. */ pos = extent40_units(src_place) - hint->units_number; extent40_copy(dst_place, 0, src_place, pos, hint->units_number); /* Updating item's key by the first unit key. */ body40_get_key(src_place, pos, &dst_place->key, extent40_offset); /* Removing units in @src_place. */ extent40_shrink(src_place, pos, hint->units_number); } return 0;}#endifstatic item_balance_ops_t balance_ops = {#ifndef ENABLE_MINIMAL .merge = NULL, .update_key = NULL, .mergeable = extent40_mergeable, .prep_shift = extent40_prep_shift, .shift_units = extent40_shift_units, .maxreal_key = extent40_maxreal_key, .collision = NULL, .overhead = NULL,#endif .init = NULL, .units = extent40_units, .lookup = extent40_lookup, .fetch_key = extent40_fetch_key, .maxposs_key = extent40_maxposs_key};static item_object_ops_t object_ops = {#ifndef ENABLE_MINIMAL .remove_units = extent40_remove_units, .update_units = extent40_update_units, .prep_insert = extent40_prep_insert, .insert_units = extent40_insert_units, .prep_write = extent40_prep_write, .write_units = extent40_write_units, .trunc_units = extent40_trunc_units, .layout = extent40_layout, .size = extent40_size, .bytes = extent40_bytes,#endif .read_units = extent40_read_units, .fetch_units = extent40_fetch_units};#ifndef ENABLE_MINIMALstatic item_repair_ops_t repair_ops = { .check_layout = extent40_check_layout, .check_struct = extent40_check_struct, .prep_insert_raw = extent40_prep_insert_raw, .insert_raw = extent40_insert_raw, .pack = NULL, .unpack = NULL};static item_debug_ops_t debug_ops = { .print = extent40_print,};#endifreiser4_item_plug_t extent40_plug = { .p = { .id = {ITEM_EXTENT40_ID, EXTENT_ITEM, ITEM_PLUG_TYPE},#ifndef ENABLE_MINIMAL .label = "extent40", .desc = "Extent file body item plugin.",#endif }, .object = &object_ops, .balance = &balance_ops,#ifndef ENABLE_MINIMAL .repair = &repair_ops, .debug = &debug_ops,#endif};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -