Use a single scheduling point for sync

This commit is contained in:
Andrea Mazzoleni 2016-01-31 18:55:09 +01:00
parent d2bad33af8
commit 541665db46
3 changed files with 56 additions and 3 deletions

View file

@ -489,7 +489,7 @@ static void io_write_next_outside(struct snapraid_io* io)
*
* It must be called inside the lock.
*/
static void io_write_next_inside(struct snapraid_io* io, unsigned blockcur, int skip, int* writer_error)
static void io_write_next_inside(struct snapraid_io* io, block_off_t blockcur, int skip, int* writer_error)
{
unsigned i;
@ -537,6 +537,38 @@ void io_write_next(struct snapraid_io* io, unsigned blockcur, int skip, int* wri
#endif
}
block_off_t io_write_and_read_next(struct snapraid_io* io, block_off_t blockcur, int skip, int* writer_error, void*** buffer)
{
block_off_t blockcur_schedule;
block_off_t blockcur_caller;
io_write_next_outside(io);
blockcur_schedule = io_read_next_outside(io);
/* the synchronization is protected by the io mutex */
pthread_mutex_lock(&io->mutex);
io_write_next_inside(io, blockcur, skip, writer_error);
blockcur_caller = io_read_next_inside(io, blockcur_schedule, buffer);
#ifndef CHECKER
/* without the thread checker unlock before signaling, */
/* this reduces the number of context switches */
pthread_mutex_unlock(&io->mutex);
#endif
/* signal all the workers that there is a new pending task */
pthread_cond_broadcast(&io->write_sched);
pthread_cond_broadcast(&io->read_sched);
#ifdef CHECKER
pthread_mutex_unlock(&io->mutex);
#endif
return blockcur_caller;
}
void io_refresh(struct snapraid_io* io)
{
unsigned i;

View file

@ -365,6 +365,14 @@ void io_parity_write(struct snapraid_io* io, unsigned* levcur, unsigned* waiting
*/
void io_write_next(struct snapraid_io* io, block_off_t blockcur, int skip, int* writer_error);
/**
* Next write and read position.
*
* It's a combination of io_write_next() and io_read_next() that
* locks only one time the scheduling mutex.
*/
block_off_t io_write_and_read_next(struct snapraid_io* io, block_off_t blockcur, int skip, int* writer_error, void*** buffer);
/**
* Refresh the number of cached blocks for all data and parity disks.
*/

View file

@ -686,6 +686,8 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
unsigned l;
unsigned* waiting_map;
unsigned waiting_mac;
block_off_t blocknext;
void** buffernext;
/* the sync process assumes that all the hashes are correct */
/* including the ones from CHG and DELETED blocks */
@ -754,6 +756,10 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
if (!state_progress_begin(state, blockstart, blockmax, countmax))
goto end;
/* scheduling helper */
buffernext = 0;
blocknext = 0;
while (1) {
unsigned failed_count;
int error_on_this_block;
@ -768,7 +774,14 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
int writer_error[IO_WRITER_ERROR_MAX];
/* go to the next block */
blockcur = io_read_next(&io, &buffer);
if (buffernext != 0) {
/* if already computed, use it */
buffer = buffernext;
blockcur = blocknext;
} else {
/* otherwise do it now */
blockcur = io_read_next(&io, &buffer);
}
if (blockcur >= blockmax)
break;
@ -1227,7 +1240,7 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
}
/* write finished */
io_write_next(&io, blockcur, !parity_going_to_be_updated, writer_error);
blocknext = io_write_and_read_next(&io, blockcur, !parity_going_to_be_updated, writer_error, &buffernext);
/* handle errors reported */
for (j = 0; j < IO_WRITER_ERROR_MAX; ++j) {