Restore error reporting for parity write

This commit is contained in:
Andrea Mazzoleni 2016-01-05 13:20:25 +01:00
parent fa635f72b8
commit 4191989fa7
3 changed files with 67 additions and 6 deletions

View file

@ -274,14 +274,20 @@ static struct snapraid_task* io_reader_step(struct snapraid_worker* worker)
*
* This is the synchronization point for workers with the io.
*/
static struct snapraid_task* io_writer_step(struct snapraid_worker* worker)
static struct snapraid_task* io_writer_step(struct snapraid_worker* worker, int state)
{
struct snapraid_io* io = worker->io;
struct snapraid_task* task = 0;
int error_index;
/* the synchronization is protected by the io mutex */
pthread_mutex_lock(&io->mutex);
/* counts the number of errors in the global state */
error_index = state - IO_WRITER_ERROR_BASE;
if (error_index >= 0 && error_index < IO_WRITER_ERROR_MAX)
++io->writer_error[error_index];
while (1) {
unsigned index;
@ -359,7 +365,7 @@ block_off_t io_read_next(struct snapraid_io* io, void*** buffer)
return blockcur_caller;
}
void io_write_next(struct snapraid_io* io, unsigned blockcur, int skip)
void io_write_next(struct snapraid_io* io, unsigned blockcur, int skip, int* writer_error)
{
unsigned i;
@ -373,6 +379,12 @@ void io_write_next(struct snapraid_io* io, unsigned blockcur, int skip)
/* the synchronization is protected by the io mutex */
pthread_mutex_lock(&io->mutex);
/* report errors */
for (i = 0; i < IO_WRITER_ERROR_MAX; ++i) {
writer_error[i] = io->writer_error[i];
io->writer_error[i] = 0;
}
if (skip) {
/* skip the next write */
io_writer_sched_empty(io, io->writer_index, blockcur);
@ -554,28 +566,35 @@ static void* io_reader_thread(void* arg)
return 0;
}
static void* io_writer_thread(void* arg)
{
struct snapraid_worker* worker = arg;
int latest_state = TASK_STATE_DONE;
while (1) {
struct snapraid_task* task;
/* get the new task */
task = io_writer_step(worker);
task = io_writer_step(worker, latest_state);
/* if no task, it means to exit */
if (!task)
break;
/* nothing more to do */
if (task->state == TASK_STATE_EMPTY)
if (task->state == TASK_STATE_EMPTY) {
latest_state = TASK_STATE_DONE;
continue;
}
assert(task->state == TASK_STATE_READY);
/* work on the assigned task */
worker->func(worker, task);
/* save the resulting state */
latest_state = task->state;
}
return 0;
@ -597,6 +616,10 @@ void io_start(struct snapraid_io* io,
io->reader_index = IO_MAX - 1;
io->writer_index = 0;
/* clear writer errors */
for (i = 0; i < IO_WRITER_ERROR_MAX; ++i)
io->writer_error[i] = 0;
/* setup the initial read pending tasks, except the latest one, */
/* the latest will be initialized at the fist io_read_next() call */
for (i = 0; i < IO_MAX - 1; ++i) {

View file

@ -120,6 +120,12 @@ struct snapraid_worker {
unsigned buffer_skew;
};
/**
* Number of error kind for writers.
*/
#define IO_WRITER_ERROR_BASE TASK_STATE_IOERROR_CONTINUE
#define IO_WRITER_ERROR_MAX (-IO_WRITER_ERROR_BASE)
/**
* Reader.
*
@ -258,6 +264,11 @@ struct snapraid_io {
* it's incremented, and a write_sched() signal is sent.
*/
unsigned writer_index;
/**
* Counts the error happening in the writers.
*/
int writer_error[IO_WRITER_ERROR_MAX];
};
/**
@ -343,7 +354,8 @@ void io_parity_write(struct snapraid_io* io, unsigned* levcur);
* \param io InputOutput context.
* \param blockcur The parity position to write.
* \param skip Skip the writes, in case parity doesn't need to be updated.
* \param writer_error Return the number of errors. Vector of IO_WRITER_ERROR_MAX elements.
*/
void io_write_next(struct snapraid_io* io, unsigned blockcur, int skip);
void io_write_next(struct snapraid_io* io, unsigned blockcur, int skip, int* writer_error);
#endif

View file

@ -747,6 +747,7 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
snapraid_info info;
int rehash;
void** buffer;
int writer_error[IO_WRITER_ERROR_MAX];
/* go to the next block */
blockcur = io_read_next(&io, &buffer);
@ -1193,7 +1194,32 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
}
/* write finished */
io_write_next(&io, blockcur, !parity_going_to_be_updated);
io_write_next(&io, blockcur, !parity_going_to_be_updated, writer_error);
/* handle errors reported */
for (j = 0; j < IO_WRITER_ERROR_MAX; ++j) {
if (writer_error[j]) {
switch (j + IO_WRITER_ERROR_BASE) {
case TASK_STATE_IOERROR_CONTINUE :
++io_error;
if (io_error >= state->opt.io_error_limit) {
log_fatal("DANGER! Unexpected input/output write error in a parity disk, it isn't possible to sync.\n");
log_fatal("Stopping at block %u\n", blockcur);
goto bail;
}
break;
case TASK_STATE_ERROR_CONTINUE :
++error;
break;
case TASK_STATE_IOERROR :
++io_error;
goto bail;
case TASK_STATE_ERROR :
++error;
goto bail;
}
}
}
/* mark the state as needing write */
state->need_write = 1;