📄 node40_repair.c
字号:
/* Copyright 2001-2005 by Hans Reiser, licensing governed by reiser4progs/COPYING. node40_repair.c -- reiser4 node with short keys. */#ifndef ENABLE_MINIMAL#include "node40.h"#include <repair/plugin.h>#define MIN_ITEM_LEN 1static void node40_set_offset_at(reiser4_node_t *node, int pos, uint16_t offset){ if (pos > nh_get_num_items(node)) return; if (nh_get_num_items(node) == pos) { nh_set_free_space_start(node, offset); } else { ih_set_offset(node40_ih_at(node, pos), offset, node->keypol); }}static errno_t node40_region_delete(reiser4_node_t *node, uint16_t start_pos, uint16_t end_pos) { uint32_t count; uint32_t len; pos_t pos; uint16_t i; void *ih; aal_assert("vpf-201", node != NULL); aal_assert("vpf-202", node->block != NULL); aal_assert("vpf-213", start_pos <= end_pos); aal_assert("vpf-214", end_pos <= nh_get_num_items(node)); ih = node40_ih_at(node, start_pos); for (i = start_pos; i < end_pos; i++) { ih_set_offset(ih, ih_get_offset(ih + ih_size(node->keypol), node->keypol) + 1, node->keypol); ih -= ih_size(node->keypol); } pos.unit = MAX_UINT32; pos.item = start_pos - 1; count = end_pos - pos.item; len = node40_size(node, &pos, count); return node40_shrink((reiser4_node_t *)node, &pos, len, count);}/* Count is valid if: free_space_start + free_space == block_size - count * ih size */static int node40_count_valid(reiser4_node_t *node) { uint32_t count; count = nh_get_num_items(node); if (count > node->block->size / ih_size(node->keypol)) return 0; if (nh_get_free_space_start(node) > node->block->size) return 0; if (nh_get_free_space(node) > node->block->size) return 0; return (nh_get_free_space_start(node) + nh_get_free_space(node) + count * ih_size(node->keypol) == node->block->size);}/* Look through ih array looking for the last valid item location. This will be the last valid item. */static uint32_t node40_estimate_count(reiser4_node_t *node) { uint32_t offset, left, right; uint32_t count, last, i; count = nh_get_num_items(node); left = sizeof(node40_header_t); right = node->block->size - ih_size(node->keypol) - MIN_ITEM_LEN; last = 0; for (i = 0 ; ; i++, left += MIN_ITEM_LEN, right -= ih_size(node->keypol)) { if (left > right) break; offset = ih_get_offset(node40_ih_at(node, i), node->keypol); if (offset >= left && offset <= right) { last = i; left = offset; } } return last + 1;}static errno_t node40_space_check(reiser4_node_t *node, uint32_t offset, uint8_t mode){ errno_t res = 0; uint32_t space; space = nh_get_free_space_start(node); /* Last relable position is not free space spart. Correct it. */ if (offset != space) { /* There is left region with broken offsets, remove it. */ fsck_mess("Node (%llu): Free space start (%u) is wrong. " "Should be (%u). %s", node->block->nr, space, offset, mode == RM_BUILD ? "Fixed." : ""); if (mode == RM_BUILD) { nh_set_free_space(node, nh_get_free_space(node) + space - offset); nh_set_free_space_start(node, offset); node40_mkdirty(node); } else { res |= RE_FATAL; } } space = node->block->size - nh_get_free_space_start(node) - ih_size(node->keypol) * nh_get_num_items(node); if (space != nh_get_free_space(node)) { /* Free space is wrong. */ fsck_mess("Node (%llu): the free space (%u) is wrong. " "Should be (%u). %s", node->block->nr, nh_get_free_space(node), space, mode == RM_CHECK ? "" : "Fixed."); if (mode == RM_CHECK) { res |= RE_FIXABLE; } else { nh_set_free_space(node, space); node40_mkdirty(node); } } return res;}/* Count of items is correct. Free space fields and item locations should be * checked/recovered if broken. */static errno_t node40_ih_array_check(reiser4_node_t *node, uint8_t mode) { uint32_t right, left, offset; uint32_t last_pos, count, i; errno_t res = 0; bool_t relable; blk_t blk; aal_assert("vpf-208", node != NULL); aal_assert("vpf-209", node->block != NULL); blk = node->block->nr; offset = 0; last_pos = 0; count = nh_get_num_items(node); left = sizeof(node40_header_t); right = node->block->size - count * ih_size(node->keypol); for(i = 0; i <= count; i++, left += MIN_ITEM_LEN) { offset = (i == count) ? nh_get_free_space_start(node) : ih_get_offset(node40_ih_at(node, i), node->keypol); if (i == 0) { if (offset == left) continue; fsck_mess("Node (%llu), item (0): Offset (%u) is " "wrong. Should be (%u). %s", blk, offset, left, mode == RM_BUILD ? "Fixed." : ""); if (mode != RM_BUILD) { res |= RE_FATAL; continue; } ih_set_offset(node40_ih_at(node, 0), left, node->keypol); node40_mkdirty(node); continue; } relable = offset >= left && offset + (count - i) * MIN_ITEM_LEN <= right; if (!relable) { /* fsck_mess("Node (%llu), item (%u): Offset (%u) " "is wrong.", blk, i, offset); */ res |= (mode == RM_BUILD ? 0 : RE_FATAL); if (count != i) continue; } /* i-th offset is ok or i == count. Removed broken items. */ if ((last_pos != i - 1) || !relable) { uint32_t delta; fsck_mess("Node (%llu): Region of items [%d-%d] with " "wrong offsets %s removed.", blk, last_pos, i - 1, mode == RM_BUILD ? "is" : "should be"); if (mode == RM_BUILD) { delta = i - last_pos; count -= delta; right += delta * ih_size(node->keypol); if (node40_region_delete(node, last_pos + 1, i)) return -EINVAL; i = last_pos; } /* DO not correct the left limit in the CHECK mode,leave it the same last_relable_offset + n * MIN_ITEM_SIZE. However, correct it for the i == count to check free space correctly. */ if (mode == RM_BUILD || !relable) { left = ih_get_offset(node40_ih_at(node, last_pos), node->keypol); } } else { /* Set the last correct offset and the keft limit. */ last_pos = i; left = (i == count) ? nh_get_free_space_start(node) : ih_get_offset(node40_ih_at(node, i), node->keypol); } } left -= (i - last_pos) * MIN_ITEM_LEN; res |= node40_space_check(node, left, mode); return res;}/* Checks the count of items written in node_header. If it is wrong, it tries to estimate it on the base of free_space fields and recover if REBUILD mode. Returns FATAL otherwise. */static errno_t node40_count_check(reiser4_node_t *node, uint8_t mode) { uint32_t num, count; blk_t blk; aal_assert("vpf-802", node != NULL); aal_assert("vpf-803", node->block != NULL); blk = node->block->nr; /* Check the count of items. */ if (node40_count_valid(node)) return 0; /* Count is probably is not valid. Estimate the count. */ num = node40_estimate_count(node); count = nh_get_num_items(node); if (num >= count) return 0; fsck_mess("Node (%llu): Count of items (%u) is wrong. " "Only (%u) items found.%s", blk, count, num, mode == RM_BUILD ? " Fixed." : ""); /* Recover is impossible. */ if (mode != RM_BUILD) return RE_FATAL; nh_set_num_items(node, num); node40_mkdirty(node); return 0;}static errno_t node40_iplug_check(reiser4_node_t *node, uint8_t mode) { uint32_t count, len; uint16_t pid; errno_t res; pos_t pos; void *ih; count = nh_get_num_items(node); ih = node40_ih_at(node, 0); pos.unit = MAX_UINT32; res = 0; for (pos.item = 0; pos.item < count; pos.item++, ih -= ih_size(node->keypol)) { pid = ih_get_pid(ih, node->keypol); if (!node40_core->factory_ops.ifind(ITEM_PLUG_TYPE, pid)) { fsck_mess("Node (%llu), item (%u): the item of unknown " "plugin id (0x%x) is found.%s", node->block->nr, pos.item, pid, mode == RM_BUILD ? " Removed." : ""); if (mode != RM_BUILD) { res |= RE_FATAL; continue; } /* Item plugin cannot be found, remove it. */ len = node40_size(node, &pos, 1); if ((res = node40_shrink(node, &pos, len, 1))) return res; } } return res;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -