From: Edward Shishkin <edward.shishkin@gmail.com>
To: Reiserfs mailing list <reiserfs-devel@vger.kernel.org>
Cc: Bringfried Stecklum <stecklum@tls-tautenburg.de>
Subject: [patch] reiser4progs: Handle unprepped items by fsck
Date: Fri, 28 May 2010 13:10:12 +0200 [thread overview]
Message-ID: <4BFFA494.4060509@gmail.com> (raw)
[-- Attachment #1: Type: text/plain, Size: 314 bytes --]
Hello everyone. This patch fixes the problem (segmentation fault)
in fsck reported by Bringfried Stecklum and Jonáš Vidra:
http://marc.info/?l=reiserfs-devel&m=126936575206572&w=2
However, the source of the problem in the kernel (data loss by
cryptcompress file plugin) is not yet eliminated.
Thanks,
Edward.
[-- Attachment #2: reiser4progs-fsck-handle-unprepped-cluster.patch --]
[-- Type: text/x-patch, Size: 12273 bytes --]
. Handle orphan "unprepped" clusters;
. Don't repair the value of cluster shift in ctail item
in all circumstances. If cluster shift is wrong, then
remove the whole cluster.
Signed-off-by: Edward Shishkin <edward.shishkin@gmail.com>
---
plugin/object/ccreg40/ccreg40.c | 12 +-
plugin/object/ccreg40/ccreg40.h | 9 +
plugin/object/ccreg40/ccreg40_repair.c | 196 +++++++++++++++++----------------
3 files changed, 121 insertions(+), 96 deletions(-)
--- reiser4progs-1.0.7.orig/plugin/object/ccreg40/ccreg40.h
+++ reiser4progs-1.0.7/plugin/object/ccreg40/ccreg40.h
@@ -11,6 +11,12 @@
#include "reiser4/plugin.h"
#include "plugin/object/obj40/obj40.h"
+#define MIN_VALID_CLUSTER_SHIFT (0xc)
+#define MAX_VALID_CLUSTER_SHIFT (0x10)
+#define UNPREPPED_CLUSTER_SHIFT (0xff)
+
+#define ccreg40_cloff(off, size) ((off) & ((size) - 1))
+
#define ccreg40_clstart(off, size) ((off) & ~((size) - 1))
#define ccreg40_clnext(off, size) (ccreg40_clstart(off, size) + (size))
@@ -22,7 +28,8 @@ extern errno_t ccreg40_check_struct(reis
place_func_t func,
void *data, uint8_t mode);
-extern uint32_t ccreg40_get_cluster_size(reiser4_place_t *place);
+extern errno_t ccreg40_get_cluster_shift(reiser4_place_t *place,
+ uint8_t *shift);
extern errno_t ccreg40_set_cluster_size(reiser4_place_t *place,
uint32_t cluster);
--- reiser4progs-1.0.7.orig/plugin/object/ccreg40/ccreg40_repair.c
+++ reiser4progs-1.0.7/plugin/object/ccreg40/ccreg40_repair.c
@@ -25,80 +25,81 @@ typedef struct ccreg40_hint {
uint64_t seek; /* expected offset for lookup */
uint64_t found; /* what has been really found */
uint64_t maxreal; /* maximal (key) offset in the found item */
-
- /* Bytes all clusters takes on disk. */
- uint32_t bytes;
uint64_t sdsize;
+ /* The following two fields are to delete wrecks of a disk cluster */
+ uint64_t cut_from; /* offset to cut from */
+ uint32_t cut_size; /* how many bytes to cut */
+ uint32_t clsize;
+ /* Total number of units in a disk cluster */
+ uint32_t bytes;
uint32_t adler;
uint8_t mode;
-
- /* If a hole is detected. */
+ /* Indicates if cluster has a hole in key space */
uint8_t hole;
-
/* The cluster size & the buffer for the data. */
uint8_t data[64 * 1024];
- uint64_t clstart;
- uint32_t clsize;
} ccreg40_hint_t;
static errno_t ccreg40_check_item(reiser4_object_t *cc, void *data) {
ccreg40_hint_t *hint = (ccreg40_hint_t *)data;
- uint32_t clsize;
- errno_t res = 0;
-
+ uint8_t shift;
+ errno_t result;
+
hint->found = objcall(&cc->body.key, get_offset);
hint->maxreal = obj40_place_maxreal(&cc->body);
aal_assert("vpf-1871", hint->maxreal >= hint->found);
aal_assert("vpf-1872", hint->seek <= hint->found);
- /* Check the item plugin. */
+ /* check item plugin */
if (cc->body.plug != reiser4_psctail(cc)) {
- fsck_mess("The file [%s] (%s), node [%llu], item "
- "[%u]: item of the illegal plugin (%s) "
- "with the key of this object found.%s",
- print_inode(obj40_core, &cc->info.object),
- reiser4_psobj(cc)->p.label, place_blknr(&cc->body),
- cc->body.pos.item, cc->body.plug->p.label,
- hint->mode == RM_BUILD ? " Removed." : "");
-
- return hint->mode == RM_BUILD ? -ESTRUCT : RE_FATAL;
+ fsck_mess("Found item of illegal plugin (%s) "
+ "with the key of this object ",
+ cc->body.plug->p.label);
+ goto fatal;
}
-
- /* Check the shift. */
- clsize = ccreg40_get_cluster_size(&cc->body);
-
- if (hint->clsize != clsize) {
- fsck_mess("The file [%s] (%s), node [%llu], item [%u]: item "
- "of the wrong cluster size (%d) found, Should be "
- "(%d).%s", print_inode(obj40_core, &cc->info.object),
- reiser4_psobj(cc)->p.label, place_blknr(&cc->body),
- cc->body.pos.item, clsize, hint->clsize,
- hint->mode != RM_CHECK ? " Fixed." : "");
-
- /* Just fix the shift if wrong. */
- if (hint->mode == RM_CHECK) {
- res |= RE_FIXABLE;
- } else {
- ccreg40_set_cluster_size(&cc->body, hint->clsize);
- }
+ /* check cluster shift. */
+ result = ccreg40_get_cluster_shift(&cc->body, &shift);
+ if (result < 0)
+ return result;
+ if (shift == UNPREPPED_CLUSTER_SHIFT) {
+ fsck_mess("Found unprepped disk cluster ");
+ goto fatal;
+ }
+ if (shift < MIN_VALID_CLUSTER_SHIFT ||
+ shift > MAX_VALID_CLUSTER_SHIFT ||
+ shift != aal_log2(hint->clsize)) {
+ fsck_mess("Found item with wrong cluster shift %d, "
+ "should be %d", shift, aal_log2(hint->clsize));
+ goto fatal;
+ }
+ if (hint->seek &&
+ !ccreg40_clsame(hint->prev_found, hint->found, hint->clsize) &&
+ ccreg40_cloff(hint->found, hint->clsize) != 0){
+ fsck_mess("Found item of lenght (%llu) which has wrong "
+ "offset %llu, should be a multiple of logical "
+ "cluster size ",
+ hint->maxreal - hint->found + 1, hint->found);
+ goto fatal;
}
-
if (!ccreg40_clsame(hint->found, hint->maxreal, hint->clsize)) {
- /* The item covers the cluster border. Delete it. */
- fsck_mess("The file [%s] (%s), node [%llu], item [%u]: "
- "item of the lenght (%llu) found, it cannot "
- "contain data of 2 clusters.%s",
- print_inode(obj40_core, &cc->info.object),
- reiser4_psobj(cc)->p.label,
- place_blknr(&cc->body), cc->body.pos.item,
- hint->maxreal - hint->found + 1,
- hint->mode == RM_BUILD ? " Removed." : "");
-
- return hint->mode == RM_BUILD ? -ESTRUCT : RE_FATAL;
+ fsck_mess("Found item of length %llu and offset %llu, "
+ "which contains logical cluster boundary ",
+ hint->maxreal - hint->found + 1, hint->found);
+ goto fatal;
}
-
- return res;
+ return 0;
+ fatal:
+ fsck_mess("(file [%s] (%s), node [%llu], item [%u]). %s",
+ print_inode(obj40_core, &cc->info.object),
+ reiser4_psobj(cc)->p.label,
+ place_blknr(&cc->body),
+ cc->body.pos.item,
+ hint->mode == RM_BUILD ? " Removed." : "");
+ hint->cut_from = hint->found;
+ hint->cut_size = hint->maxreal - hint->found + 1;
+
+ return hint->mode == RM_BUILD ? -ESTRUCT : RE_FATAL;
}
static int64_t ccreg40_read_item(reiser4_place_t *place, ccreg40_hint_t *hint) {
@@ -133,23 +134,21 @@ static errno_t ccreg40_check_crc(ccreg40
return adler == disk ? 0 : RE_FATAL;
}
+/*
+ * Read a found item to the stream.
+ * Check a checksum, if the previous iteration completed a disk cluster.
+ */
static errno_t ccreg40_check_cluster(reiser4_object_t *cc,
ccreg40_hint_t *hint,
uint8_t mode)
{
- errno_t result;
+ errno_t result = 0;
errno_t res;
- int start;
- uint32_t lcl_size;
-
- result = 0;
- /* true, if the found item is the
- first one in the disk cluster */
- start = (ccreg40_clstart(hint->found, hint->clsize) == hint->found);
+ uint32_t lcl_bytes;
if ((cc->body.plug == NULL) ||
- (hint->seek && start) ||
- !ccreg40_clsame(hint->prev_found, hint->found, hint->clsize)) {
+ (hint->seek != 0 &&
+ !ccreg40_clsame(hint->prev_found, hint->found, hint->clsize))) {
/* Cluster is over */
if (hint->prev_found > hint->sdsize) {
@@ -158,31 +157,32 @@ static errno_t ccreg40_check_cluster(rei
result = RE_FATAL;
/* set offset of the cluster to be deleted. */
- hint->clstart = ccreg40_clstart(hint->prev_found,
- hint->clsize);
+ hint->cut_from = ccreg40_clstart(hint->prev_found,
+ hint->clsize);
fsck_mess("The file [%s] (%s): the cluster at [%llu] "
"offset %u bytes long is orphan.%s",
print_inode(obj40_core, &cc->info.object),
- reiser4_psobj(cc)->p.label, hint->clstart,
+ reiser4_psobj(cc)->p.label, hint->cut_from,
hint->clsize, hint->mode != RM_CHECK ?
" Removed." : "");
}
/**
- * If there still is a hole in the logical cluster,
- * then check a checksum (no hole means no checksum)
+ * If there still is a hole in the keyspace, then
+ * check a checksum (no such hole means that no
+ * checksum was appended)
*/
- else if (hint->hole && ccreg40_check_crc(hint)) {
+ else if (hint->bytes && hint->hole && ccreg40_check_crc(hint)) {
/* wrong checksum */
hint->bytes = 0;
result = RE_FATAL;
/* set offset of the cluster to be deleted. */
- hint->clstart = ccreg40_clstart(hint->prev_found,
- hint->clsize);
+ hint->cut_from = ccreg40_clstart(hint->prev_found,
+ hint->clsize);
fsck_mess("The file [%s] (%s): the cluster at [%llu] "
"offset %u bytes long is corrupted.%s",
print_inode(obj40_core, &cc->info.object),
- reiser4_psobj(cc)->p.label, hint->clstart,
+ reiser4_psobj(cc)->p.label, hint->cut_from,
hint->clsize, hint->mode != RM_CHECK ?
" Removed." : "");
}
@@ -192,16 +192,13 @@ static errno_t ccreg40_check_cluster(rei
hint->adler = 0;
if (!cc->body.plug)
+ /* finish with this object */
return result;
/* Update the cluster data. */
aal_memset(hint->data, 0, hint->clsize);
}
-
/* An item found. */
- aal_assert("edward-1",
- ccreg40_clstart(hint->found, hint->clsize) ==
- ccreg40_clstart(hint->maxreal, hint->clsize));
if ((res = ccreg40_read_item(&cc->body, hint)))
return res;
@@ -209,16 +206,19 @@ static errno_t ccreg40_check_cluster(rei
hint->prev_found = hint->found;
hint->bytes += objcall(&cc->body, object->bytes);
/**
- * Calculate a size of logical cluster
- * and figure out, if there is a hole
- * for the found items in the logical cluster.
+ * Calculate actual number of file's bytes in the
+ * logical cluster and figure out, if corresponding
+ * disk cluster has a hole in key space.
+ *
+ * We need this to figure out if disk cluster contains
+ * appended checksum.
*/
- lcl_size = 0;
+ lcl_bytes = 0;
if (ccreg40_clsame(hint->found, hint->sdsize - 1, hint->clsize))
- lcl_size = hint->sdsize % hint->clsize;
- if (lcl_size == 0)
- lcl_size = hint->clsize;
- hint->hole = (hint->bytes != lcl_size);
+ lcl_bytes = hint->sdsize % hint->clsize;
+ if (lcl_bytes == 0)
+ lcl_bytes = hint->clsize;
+ hint->hole = (hint->bytes != lcl_bytes);
return result;
}
@@ -256,8 +256,23 @@ errno_t ccreg40_check_struct(reiser4_obj
/* Get next item. */
lookup = obj40_check_item(cc, ccreg40_check_item, NULL, &hint);
- if (repair_error_fatal(lookup))
- return lookup;
+ if (repair_error_fatal(lookup)) {
+ if ((lookup & RE_FATAL) && mode == RM_BUILD) {
+ /*
+ * Delete item found in this iteration
+ */
+ res &= ~RE_FATAL;
+ res |= obj40_cut(cc, &trans, hint.cut_from,
+ hint.cut_size, NULL, NULL);
+ if (res < 0)
+ return res;
+ hint.seek = hint.maxreal + 1;
+ obj40_seek(cc, hint.seek);
+ continue;
+ }
+ else
+ return lookup;
+ }
else if (lookup == ABSENT)
cc->body.plug = NULL;
@@ -267,16 +282,17 @@ errno_t ccreg40_check_struct(reiser4_obj
"registered yet.", print_key(obj40_core,
&info->object));
}
-
+ /* check cluster found in previous iteration */
if ((res |= ccreg40_check_cluster(cc, &hint, mode)) < 0)
return res;
if (res & RE_FATAL) {
- /* Delete the whole cluster. */
-
+ /*
+ * Delete cluster found in previous iteration
+ */
if (mode == RM_BUILD) {
res &= ~RE_FATAL;
- res |= obj40_cut(cc, &trans, hint.clstart,
+ res |= obj40_cut(cc, &trans, hint.cut_from,
hint.clsize, NULL, NULL);
if (res < 0)
return res;
--- reiser4progs-1.0.7.orig/plugin/object/ccreg40/ccreg40.c
+++ reiser4progs-1.0.7/plugin/object/ccreg40/ccreg40.c
@@ -8,7 +8,7 @@
#include "ccreg40.h"
#include "plugin/object/obj40/obj40_repair.h"
-uint32_t ccreg40_get_cluster_size(reiser4_place_t *place) {
+errno_t ccreg40_get_cluster_shift(reiser4_place_t *place, uint8_t *shift) {
trans_hint_t hint;
ctail_hint_t chint;
@@ -17,10 +17,12 @@ uint32_t ccreg40_get_cluster_size(reiser
hint.specific = &chint;
hint.count = 1;
- if (objcall(place, object->fetch_units, &hint) != 1)
- return MAX_UINT32;
-
- return 1 << chint.shift;
+ if (objcall(place, object->fetch_units, &hint) != 1) {
+ aal_error("Can not extract cluster shift.");
+ return -EINVAL;
+ }
+ *shift = chint.shift;
+ return 0;
}
errno_t ccreg40_set_cluster_size(reiser4_place_t *place, uint32_t cluster) {
next reply other threads:[~2010-05-28 11:10 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-05-28 11:10 Edward Shishkin [this message]
[not found] ` <4C7BD349.5070005@tls-tautenburg.de>
[not found] ` <4C7BD64B.9070005@gmail.com>
[not found] ` <4C7BF309.8070906@tls-tautenburg.de>
[not found] ` <4C7C04FB.9070901@gmail.com>
[not found] ` <4D7CAE07.2090907@tls-tautenburg.de>
[not found] ` <4D7FECB3.4090804@gmail.com>
[not found] ` <4D8A771B.7080903@tls-tautenburg.de>
[not found] ` <4D8A7E79.90407@gmail.com>
[not found] ` <4D8A838C.5040702@tls-tautenburg.de>
[not found] ` <4D8A85D5.2010201@gmail.com>
[not found] ` <4D8A8893.9000802@tls-tautenburg.de>
[not found] ` <4D8A8C6D.7070906@gmail.com>
[not found] ` <4D8B5646.8020609@tls-tautenburg.de>
2011-03-24 21:42 ` search_one_bitmap_forward oops Edward Shishkin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4BFFA494.4060509@gmail.com \
--to=edward.shishkin@gmail.com \
--cc=reiserfs-devel@vger.kernel.org \
--cc=stecklum@tls-tautenburg.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.