1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225
|
/* Copyright (C) 2001-2005 by Hans Reiser, licensing governed by
reiser4progs/COPYING.
sdext_lt_repair.c -- large time stat data extension plugin recovery code. */
#ifndef ENABLE_MINIMAL
#include "sdext_plug.h"
#include <repair/plugin.h>
#include "sdext_plug.h"
#define PSET_MEMBER_LEN 14
char *pset_name[PSET_STORE_LAST] = {
[PSET_OBJ] = "object",
[PSET_DIR] = "directory",
[PSET_PERM] = "permission",
[PSET_POLICY] = "formatting",
[PSET_HASH] = "hash",
[PSET_FIBRE] = "fibration",
[PSET_STAT] = "statdata",
[PSET_DIRITEM] = "diritem",
[PSET_CRYPTO] = "crypto",
[PSET_DIGEST] = "digest",
[PSET_COMPRESS] = "compress",
[PSET_CMODE] = "compressMode",
[PSET_CLUSTER] = "cluster",
[PSET_CREATE] = "create",
};
errno_t sdext_plug_check_struct(stat_entity_t *stat, repair_hint_t *hint) {
reiser4_place_t *place;
uint64_t metmask = 0;
uint64_t rmmask = 0;
sdhint_plug_t plugh;
sdext_plug_t *ext;
uint16_t count, i;
int32_t remove;
uint32_t len;
int is_pset;
void *dst;
ext = (sdext_plug_t *)stat_body(stat);
count = sdext_plug_get_count(ext);
place = stat->place;
is_pset = stat->plug->p.id.id == SDEXT_PSET_ID;
if (count > PSET_STORE_LAST) {
fsck_mess("Node (%llu), item (%u), [%s]: does not "
"look like a valid SD %s set extention: "
"wrong member count detected (%u).",
place_blknr(place), place->pos.item,
print_key(sdext_pset_core, &place->key),
is_pset ? "plugin" : "heir", count);
return RE_FATAL;
}
len = sdext_plug_length(stat, NULL);
if (len == 0 || stat->offset + len > place->len) {
fsck_mess("Node (%llu), item (%u), [%s]: does not look like "
"a valid SD %s set extention: wrong member count "
"detected (%u).", place_blknr(place), place->pos.item,
print_key(sdext_pset_core, &place->key),
is_pset ? "plugin" : "heir", count);
return RE_FATAL;
}
aal_memset(&plugh, 0, sizeof(sdhint_plug_t));
remove = 0;
for (i = 0; i < count; i++) {
rid_t mem, id;
mem = sdext_plug_get_member(ext, i);
id = sdext_plug_get_pid(ext, i);
if (mem >= PSET_STORE_LAST) {
/* Unknown member. */
fsck_mess("Node (%llu), item (%u), [%s]: the slot (%u) "
"contains the invalid %s set member (%u).",
place_blknr(place), place->pos.item,
print_key(sdext_pset_core, &place->key),
i, is_pset ? "plugin" : "heir",mem);
rmmask |= (1 << i);
remove++;
} else if (metmask & (1 << mem)) {
/* Was met already. */
fsck_mess("Node (%llu), item (%u), [%s]: the slot (%u) "
"contains the %s set member (%s) that was met "
"already.",place_blknr(place),place->pos.item,
print_key(sdext_pset_core, &place->key), i,
is_pset ? "plugin" : "heir", pset_name[mem]);
rmmask |= (1 << i);
remove++;
} else {
metmask |= (1 << i);
/* Obtain the plugin. */
plugh.plug[mem] = sdext_pset_core->pset_ops.find(
mem, id, is_pset);
/* Check if the member is valid. */
if (plugh.plug[mem] == INVAL_PTR) {
fsck_mess("Node (%llu), item (%u), [%s]: the "
"slot (%u) contains the invalid %s "
"set member (%s), id (%u).",
place_blknr(place), place->pos.item,
print_key(sdext_pset_core, &place->key),
i, is_pset ? "plugin" : "heir",
pset_name[mem], id);
rmmask |= (1 << i);
remove++;
}
}
}
if (!rmmask)
return 0;
/* Some broken slots are found. */
if (hint->mode != RM_BUILD)
return RE_FATAL;
if (remove == count) {
fsck_mess("Node (%llu), item (%u), [%s]: no slot left. Does "
"not look like a valid (%s) statdata extention.",
place_blknr(place), place->pos.item,
print_key(sdext_pset_core, &place->key),
stat->plug->p.label);
return RE_FATAL;
}
/* Removing broken slots. */
fsck_mess("Node (%llu), item (%u), [%s]: removing broken slots.",
place_blknr(place), place->pos.item,
print_key(sdext_pset_core, &place->key));
dst = stat_body(stat) + sizeof(sdext_plug_t);
len -= sizeof(sdext_plug_t);
for (i = 0; i < count; i++, dst += sizeof(sdext_plug_slot_t)) {
len -= sizeof(sdext_plug_slot_t);
if (!(rmmask & (1 << i)))
continue;
aal_memmove(dst, dst + sizeof(sdext_plug_slot_t), len);
dst -= sizeof(sdext_plug_slot_t);
}
sdext_plug_set_count(ext, count - remove);
hint->len = remove * sizeof(sdext_plug_slot_t);
return 0;
}
void sdext_plug_print(stat_entity_t *stat,
aal_stream_t *stream,
uint16_t options)
{
reiser4_plug_t *plug;
sdext_plug_t *ext;
uint16_t count, i;
int is_pset;
aal_assert("vpf-1603", stat != NULL);
aal_assert("vpf-1604", stream != NULL);
ext = (sdext_plug_t *)stat_body(stat);
is_pset = stat->plug->p.id.id == SDEXT_PSET_ID;
if (sizeof(sdext_plug_t) + sizeof(sdext_plug_slot_t) >
stat->place->len - stat->offset)
{
aal_stream_format(stream, "No enough space (%u bytes) "
"for the %s set extention body.\n",
stat->place->len - stat->offset,
is_pset ? "plugin" : "heir");
return;
}
count = (stat->place->len - stat->offset - sizeof(sdext_plug_t)) /
sizeof(sdext_plug_slot_t);
if (count >= sdext_plug_get_count(ext)) {
count = sdext_plug_get_count(ext);
aal_stream_format(stream, "%sset count: \t%u\n",
is_pset ? "P" : "H", count);
} else {
aal_stream_format(stream, "%sset count: \t%u (fit to "
"place length %u)\n", is_pset ? "P" : "H",
sdext_plug_get_count(ext), count);
}
for (i = 0; i < count; i++) {
rid_t mem, id;
mem = sdext_plug_get_member(ext, i);
id = sdext_plug_get_pid(ext, i);
if (mem < (uint8_t)PSET_STORE_LAST) {
plug = sdext_pset_core->pset_ops.find(mem, id, is_pset);
aal_stream_format(stream, " %*s : id = %u",
PSET_MEMBER_LEN, pset_name[mem], id);
} else {
plug = NULL;
aal_stream_format(stream, "%*sUNKN(0x%x) : id = %u",
PSET_MEMBER_LEN - 5, "", mem, id);
}
if (plug && plug != INVAL_PTR)
aal_stream_format(stream, " (%s)\n", plug->label);
else
aal_stream_format(stream, "\n");
}
}
#endif
|