📄 cde40_repair.c
字号:
cde_set_offset(place, 0, sizeof(cde40_t) + en_size(pol) * flags->count, pol); } /* There are some not correct units at the beginning, the correct unit number is the recovered count. */ real_count = flags->count; } else if (!tail && e_count > flags->count) { /* If there is enough space for another entry header (e_count > count), and nothing to remove at the end of the item, the last unit is correct (tail == 0), set @count unit offset to the item length to remove redundant item headers correctly later. */ if (hint->mode == RM_BUILD) { cde_set_offset(place, flags->count, place->len, pol); } } /* Fix the count before removing anything. */ if (real_count != cde_get_units(place)) { fsck_mess("Node (%llu), item (%u), [%s]: unit count " "(%u) is not correct. Should be (%u).%s", place_blknr(place), place->pos.item, print_key(cde40_core, &place->key), cde_get_units(place), real_count, hint->mode == RM_CHECK ? "" : " Fixed."); if (hint->mode == RM_CHECK) { res |= RE_FIXABLE; } else { cde_set_units(place, real_count); place_mkdirty(place); } } if (flags->count != real_count) { /* Estimated count is greater then the recovered count, in other words there are some last unit headers should be removed. */ fsck_mess("Node (%llu), item (%u), [%s]: entries [%u..%u] look " "corrupted. %s", place_blknr(place), place->pos.item, print_key(cde40_core, &place->key), flags->count, real_count - 1, hint->mode == RM_BUILD ? "Removed." : ""); if (hint->mode == RM_BUILD) { hint->len += cde40_cut(place, flags->count, real_count - flags->count, place->len); place_mkdirty(place); } else { res |= RE_FATAL; } } else if (tail) { /* Count of recovered units metches the estimated count but there are some btes at the end to be removed. */ fsck_mess("Node (%llu), item (%u), [%s]: %u redundant bytes at " "the end.%s", place_blknr(place), place->pos.item, print_key(cde40_core, &place->key), tail, hint->mode == RM_BUILD ? "Removed." : ""); if (hint->mode == RM_BUILD) hint->len += tail; } if (first) { /* Some first units should be removed. */ fsck_mess("Node (%llu), item (%u), [%s]: entries [%u..%u] look " "corrupted. %s", place_blknr(place), place->pos.item, print_key(cde40_core, &place->key), 0, first - 1, hint->mode == RM_BUILD ? "Removed." : ""); if (hint->mode == RM_BUILD) { hint->len += cde40_cut(place, 0, first, place->len); place_mkdirty(place); aal_memmove(flags->elem, flags->elem + first, flags->count - first); flags->count -= first; first = 0; } else { res |= RE_FATAL; } } /* Units before @first and after @count were handled, do not care about them anymore. Handle all not relable units between them. */ last = MAX_UINT32; for (; first < flags->count; first++) { if (last == MAX_UINT32) { /* Looking for the problem interval start. */ if (!aal_test_bit(flags->elem + first, R)) last = first - 1; continue; } /* Looking for the problem interval end. */ if (aal_test_bit(flags->elem + first, R)) { fsck_mess("Node (%llu), item (%u), [%s]: " "entries [%u..%u] look corrupted. %s", place_blknr(place), place->pos.item, print_key(cde40_core, &place->key), last, first - 1, hint->mode == RM_BUILD ? "Removed." : ""); if (hint->mode != RM_BUILD) { res |= RE_FATAL; last = MAX_UINT32; continue; } hint->len += cde40_cut(place, last, first - last, place->len); place_mkdirty(place); aal_memmove(flags->elem + last, flags->elem + first, flags->count - first); flags->count -= (first - last); first = last; last = MAX_UINT32; } } return res;}errno_t cde40_check_struct(reiser4_place_t *place, repair_hint_t *hint) { static reiser4_key_t pkey, ckey; struct entry_flags flags; uint32_t pol; errno_t res = 0; uint32_t i; aal_assert("vpf-267", place != NULL); aal_assert("vpf-1641", hint != NULL); pol = cde40_key_pol(place); if (place->len < en_len_min(1, pol)) { fsck_mess("Node (%llu), item (%u), [%s]: item length " "(%u) is too small to contain a valid item.", place_blknr(place), place->pos.item, print_key(cde40_core, &place->key), place->len); return RE_FATAL; } /* Try to recover even if item was shorten and not all entries exist. */ flags.count = (place->len - sizeof(cde40_t)) / (en_size(pol)); /* map consists of bit pairs - [not relable -R, relable - R] */ flags.elem = aal_calloc(flags.count, 0); res |= cde40_offsets_range_check(place, &flags, hint->mode); if (res) goto error; /* Filter units with relable offsets from others. */ res |= cde40_filter(place, &flags, hint); aal_free(flags.elem); if (repair_error_fatal(res)) return res; /* Structure is checked, check the unit keys and its order. FIXME-VITALY: just simple order check for now, the whole item is thrown away if smth wrong, to be improved later. */ for (i = 1; i <= flags.count; i++) { reiser4_key_t key; trans_hint_t trans; uint32_t offset; cde40_get_hash(place, i - 1, &key); offset = i == flags.count ? place->len - hint->len: cde_get_offset(place, i, pol); if (cde_get_offset(place, i - 1, pol) + ob_size(pol) == offset){ /* Check that [i-1] key is not hashed. */ if (!objcall(&key, hashed)) continue; /* Hashed, key is wrong, remove the entry. */ fsck_mess("Node (%llu), item (%u): wrong key " "[%s] of the unit (%u).%s", place_blknr(place), place->pos.item, print_inode(cde40_core, &key), i - 1, hint->mode == RM_BUILD ? " Removed." : ""); if (hint->mode != RM_BUILD) { res |= RE_FATAL; continue; } /* Remove the entry. */ trans.count = 1; if ((res |= cde40_delete(place, i - 1, &trans)) < 0) return res; hint->len += trans.len; flags.count--; i--; continue; } else { /* Check that [i-1] key is hashed. */ if (objcall(&key, hashed)) continue; /* Not hashed, key is wrong, remove the entry. */ fsck_mess("Node (%llu), item (%u): wrong key " "[%s] of the unit (%u).%s", place_blknr(place), place->pos.item, print_inode(cde40_core, &key), i - 1, hint->mode == RM_BUILD ? " Removed." : ""); if (hint->mode != RM_BUILD) { res |= RE_FATAL; continue; } /* Remove the entry. */ trans.count = 1; if ((res |= cde40_delete(place, i - 1, &trans)) < 0) return res; hint->len += trans.len; flags.count--; i--; continue; } } if (res & RE_FATAL) return res; aal_memset(&pkey, 0, sizeof(pkey)); aal_memset(&ckey, 0, sizeof(ckey)); cde40_get_hash(place, 0, &pkey); for (i = 1; i < flags.count; i++) { cde40_get_hash(place, i, &ckey); if (objcall(&pkey, compfull, &ckey) == 1) { fsck_mess("Node (%llu), item (%u), [%s]: wrong order " "of units [%d, %d]. The whole item is to be " "removed.",place_blknr(place),place->pos.item, print_key(cde40_core, &place->key), i - 1, i); return res | RE_FATAL; } pkey = ckey; } if (flags.count == 0) return res | RE_FATAL; cde40_get_hash(place, 0, &ckey); if (objcall(&ckey, compfull, &place->key)) { fsck_mess("Node (%llu), item (%u): the item key [%s] does " "not match the first unit key [%s].%s", place_blknr(place), place->pos.item, print_inode(cde40_core, &place->key), print_inode(cde40_core, &ckey), hint->mode == RM_BUILD ? " Fixed." : ""); res |= RE_FATAL; } return res; error: aal_free(flags.elem); return res;}static int cde40_comp_entry(reiser4_place_t *place1, uint32_t pos1, reiser4_place_t *place2, uint32_t pos2){ reiser4_key_t key1, key2; char *name1, *name2; int comp; cde40_get_hash(place1, pos1, &key1); cde40_get_hash(place2, pos2, &key2); /* Compare hashes. */ if ((comp = objcall(&key1, compfull, &key2))) return comp; /* If equal, and names are hashed, compare names. */ if (!objcall(&key1, hashed) || !objcall(&key2, hashed)) return 0; name1 = (char *)(cde40_objid(place1, pos1) + ob_size(cde40_key_pol(place1))); name2 = (char *)(cde40_objid(place2, pos2) + ob_size(cde40_key_pol(place2))); return aal_strcmp(name1, name2);}/* Estimate the space needed for the insertion of the not overlapped part of the item, overlapped part does not need any space. */errno_t cde40_prep_insert_raw(reiser4_place_t *place, trans_hint_t *trans) { uint32_t sunits, send; uint32_t offset, pol; reiser4_place_t *src; aal_assert("vpf-957", place != NULL); aal_assert("vpf-959", trans != NULL); src = (reiser4_place_t *)trans->specific; sunits = cde40_units(src); pol = cde40_key_pol(place); if (place->pos.unit != MAX_UINT32 && place->pos.unit != cde40_units(place)) { /* What is the last to be inserted? */ for (send = src->pos.unit; send < sunits; send++) { if (cde40_comp_entry(place, place->pos.unit, src, send) <= 0) break; } } else send = sunits; trans->bytes = 0; trans->count = send - src->pos.unit; offset = send == sunits ? src->len : cde_get_offset(src, send, pol); /* Len to be inserted is the size of header + item bodies. */ trans->len = trans->count * en_size(pol) + offset - cde_get_offset(src, src->pos.unit, pol); trans->overhead = cde40_overhead(); return 0;}int64_t cde40_insert_raw(reiser4_place_t *place, trans_hint_t *trans) { uint32_t dpos, dunits; uint32_t spos, sunits; reiser4_place_t *src; errno_t res; aal_assert("vpf-1370", place != NULL); aal_assert("vpf-1371", trans != NULL); src = (reiser4_place_t *)trans->specific; dpos = place->pos.unit; if (place->pos.unit == MAX_UINT32) place->pos.unit = 0; sunits = cde40_units(src); if (trans->count) { /* Expand @place & copy @trans->count units there from @src. */ if (dpos != MAX_UINT32) cde40_expand(place, dpos, trans->count, trans->len); else cde_set_units(place, 0); if ((res = cde40_copy(place, place->pos.unit, src, src->pos.unit, trans->count))) { return res; } spos = src->pos.unit + trans->count; place_mkdirty(place); } else { /* The first @place and @src entries match to each other. Get the very first that differ. */ dunits = cde40_units(place); for (dpos = place->pos.unit + 1, spos = src->pos.unit + 1; dpos < dunits; dpos++, spos++) { if (spos >= sunits) break; if (cde40_comp_entry(place, dpos, src, spos)) break; } } /* Update the item key. */ if (place->pos.unit == 0 && trans->count) aal_memcpy(&place->key, &trans->offset, sizeof(place->key)); if (spos == sunits) return cde40_maxposs_key(src, &trans->maxkey); return cde40_get_hash(src, spos, &trans->maxkey);}#define PRINT_NAME_LIMIT 38/* Prints cde item into passed @stream */void cde40_print(reiser4_place_t *place, aal_stream_t *stream, uint16_t options) { uint32_t namewidth = 0; uint64_t locality = 0; uint64_t objectid = 0; uint32_t i, j, count; char name[256]; uint32_t pol; aal_assert("umka-548", place != NULL); aal_assert("umka-549", stream != NULL); aal_stream_format(stream, "\nNR(%u) NAME%*s OFFSET HASH%*s " "SDKEY%*s\n", cde_get_units(place), PRINT_NAME_LIMIT - 5, " ", 29, " ", 13, " "); pol = cde40_key_pol(place); count = (place->len - sizeof(cde40_t)) / (en_size(pol)); if (count > cde_get_units(place)) count = cde_get_units(place); /* Loop though the all entries and print them to @stream. */ for (i = 0; i < count; i++) { void *entry = cde40_entry(place, i); uint64_t offset, haobj; void *objid; if (options != PO_UNIT_OFFSETS) { objid = cde40_objid(place, i); if (objid >= place->body + place->len || entry >= place->body + place->len) { aal_stream_format(stream, "Broken entry array " "detected.\n"); break; } cde40_get_name(place, i, name, sizeof(name)); /* Cutting name by PRINT_NAME_LIMIT symbols */ if (aal_strlen(name) > PRINT_NAME_LIMIT) { for (j = 0; j < 3; j++) name[PRINT_NAME_LIMIT - 3 + j] = '.'; name[PRINT_NAME_LIMIT - 3 + j] = '\0'; } /* Getting locality, objectid. */ locality = ob_get_locality(objid, pol); objectid = ob_get_objectid(objid, pol); namewidth = PRINT_NAME_LIMIT - aal_strlen(name); } offset = ha_get_offset(entry, pol); haobj = ha_get_objectid(entry, pol); /* Putting data to @stream. */ if (options != PO_UNIT_OFFSETS) { aal_stream_format(stream, "%*d %s%*s %*u %.16llx:%.16llx " "%.7llx:%.7llx\n", 3, i, name, namewidth, " ", 5, en_get_offset(entry, pol), haobj, offset, locality, objectid); } else { aal_stream_format(stream, "%*d %*u %.16llx:%.16llx\n", 3, i, 5, en_get_offset(entry, pol), haobj, offset); } }}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -