More precise disk usage time

When we wait, we now count the time for all the waiting disks,
and not only for the first one that finish.
This commit is contained in:
Andrea Mazzoleni 2016-01-20 21:30:00 +01:00
parent f61f9192b0
commit e2c4399e28
7 changed files with 149 additions and 73 deletions

View file

@ -23,6 +23,7 @@
#include "parity.h"
#include "handle.h"
#include "io.h"
#include "raid/raid.h"
/****************************************************************************/
/* dry */
@ -179,6 +180,8 @@ static int state_dry_process(struct snapraid_state* state, struct snapraid_parit
unsigned error;
unsigned io_error;
unsigned l;
unsigned* waiting_map;
unsigned waiting_mac;
handle = handle_mapping(state, &diskmax);
@ -188,6 +191,8 @@ static int state_dry_process(struct snapraid_state* state, struct snapraid_parit
/* initialize the io threads */
io_init(&io, state, state->opt.io_cache, buffermax, dry_data_reader, handle, diskmax, dry_parity_reader, 0, parity_handle, state->level);
waiting_map = malloc_nofail((diskmax + RAID_PARITY_MAX) * sizeof(unsigned));
error = 0;
io_error = 0;
@ -222,7 +227,10 @@ static int state_dry_process(struct snapraid_state* state, struct snapraid_parit
state_usage_cpu(state);
/* get the next task */
task = io_data_read(&io, &diskcur);
task = io_data_read(&io, &diskcur, waiting_map, &waiting_mac);
/* until now is disk */
state_usage_disk(state, handle, waiting_map, waiting_mac);
/* get the task results */
disk = task->disk;
@ -233,9 +241,6 @@ static int state_dry_process(struct snapraid_state* state, struct snapraid_parit
if (!disk)
continue;
/* until now is disk */
state_usage_disk(state, disk);
/* if the block is not used */
if (!block_has_file(block))
continue;
@ -285,10 +290,10 @@ static int state_dry_process(struct snapraid_state* state, struct snapraid_parit
struct snapraid_task* task;
unsigned levcur;
task = io_parity_read(&io, &levcur);
task = io_parity_read(&io, &levcur, waiting_map, &waiting_mac);
/* until now is parity */
state_usage_parity(state, levcur);
state_usage_parity(state, waiting_map, waiting_mac);
/* handle error conditions */
if (task->state == TASK_STATE_IOERROR) {
@ -370,6 +375,7 @@ bail:
log_fatal("DANGER! Unexpected input/output errors!\n");
free(handle);
free(waiting_map);
io_done(&io);
if (error + io_error != 0)

View file

@ -485,8 +485,16 @@ void io_write_next(struct snapraid_io* io, unsigned blockcur, int skip, int* wri
#endif
}
static struct snapraid_task* io_task_read(struct snapraid_io* io, unsigned base, unsigned count, unsigned* pos)
static struct snapraid_task* io_task_read(struct snapraid_io* io, unsigned base, unsigned count, unsigned* pos, unsigned* waiting_map, unsigned* waiting_mac)
{
unsigned waiting_cycle;
/* count the waiting cycle */
waiting_cycle = 0;
/* clear the waiting indexes */
*waiting_mac = 0;
/* the synchronization is protected by the io mutex */
pthread_mutex_lock(&io->mutex);
@ -512,6 +520,12 @@ static struct snapraid_task* io_task_read(struct snapraid_io* io, unsigned base,
if (base <= i && i < base + count) {
struct snapraid_worker* worker;
/* if it's the first cycle */
if (waiting_cycle == 0) {
/* store the waiting indexes */
waiting_map[(*waiting_mac)++] = i - base;
}
worker = &io->reader_map[i];
/* if the worker has finished this index */
@ -529,6 +543,10 @@ static struct snapraid_task* io_task_read(struct snapraid_io* io, unsigned base,
/* return the position */
*pos = i - base;
/* on the first cycle, no one is waiting */
if (waiting_cycle == 0)
*waiting_mac = 0;
return task;
}
}
@ -537,23 +555,34 @@ static struct snapraid_task* io_task_read(struct snapraid_io* io, unsigned base,
let = &io->reader_list[i + 1];
}
/* if not worker is ready, wait for an event */
/* if no worker is ready, wait for an event */
pthread_cond_wait(&io->read_done, &io->mutex);
/* count the cycles */
++waiting_cycle;
}
}
struct snapraid_task* io_data_read(struct snapraid_io* io, unsigned* pos)
struct snapraid_task* io_data_read(struct snapraid_io* io, unsigned* pos, unsigned* waiting_map, unsigned* waiting_mac)
{
return io_task_read(io, io->data_base, io->data_count, pos);
return io_task_read(io, io->data_base, io->data_count, pos, waiting_map, waiting_mac);
}
struct snapraid_task* io_parity_read(struct snapraid_io* io, unsigned* pos)
struct snapraid_task* io_parity_read(struct snapraid_io* io, unsigned* pos, unsigned* waiting_map, unsigned* waiting_mac)
{
return io_task_read(io, io->parity_base, io->parity_count, pos);
return io_task_read(io, io->parity_base, io->parity_count, pos, waiting_map, waiting_mac);
}
void io_parity_write(struct snapraid_io* io, unsigned* pos)
void io_parity_write(struct snapraid_io* io, unsigned* pos, unsigned* waiting_map, unsigned* waiting_mac)
{
unsigned waiting_cycle;
/* count the waiting cycle */
waiting_cycle = 0;
/* clear the waiting indexes */
*waiting_mac = 0;
/* the synchronization is protected by the io mutex */
pthread_mutex_lock(&io->mutex);
@ -578,6 +607,12 @@ void io_parity_write(struct snapraid_io* io, unsigned* pos)
if (i == io->writer_max)
break;
/* if it's the first cycle */
if (waiting_cycle == 0) {
/* store the waiting indexes */
waiting_map[(*waiting_mac)++] = i;
}
worker = &io->writer_map[i];
/* the two indexes cannot be equal */
@ -594,6 +629,10 @@ void io_parity_write(struct snapraid_io* io, unsigned* pos)
/* return the position */
*pos = i;
/* on the first cycle, no one is waiting */
if (waiting_cycle == 0)
*waiting_mac = 0;
return;
}
@ -601,8 +640,11 @@ void io_parity_write(struct snapraid_io* io, unsigned* pos)
let = &io->writer_list[i + 1];
}
/* if not worker is ready, wait for an event */
/* if no worker is ready, wait for an event */
pthread_cond_wait(&io->write_done, &io->mutex);
/* count the cycles */
++waiting_cycle;
}
}

View file

@ -329,7 +329,7 @@ block_off_t io_read_next(struct snapraid_io* io, void*** buffer);
* \param pos The position of the data block in the ::handle_map vector.
* \return The completed task.
*/
struct snapraid_task* io_data_read(struct snapraid_io* io, unsigned* diskcur);
struct snapraid_task* io_data_read(struct snapraid_io* io, unsigned* diskcur, unsigned* waiting_map, unsigned* waiting_mac);
/**
* Read a parity block.
@ -340,7 +340,7 @@ struct snapraid_task* io_data_read(struct snapraid_io* io, unsigned* diskcur);
* \param pos The position of the parity block in the ::parity_handle_map vector.
* \return The completed task.
*/
struct snapraid_task* io_parity_read(struct snapraid_io* io, unsigned* levcur);
struct snapraid_task* io_parity_read(struct snapraid_io* io, unsigned* levcur, unsigned* waiting_map, unsigned* waiting_mac);
/**
* Write of a parity block.
@ -350,7 +350,7 @@ struct snapraid_task* io_parity_read(struct snapraid_io* io, unsigned* levcur);
* \param io InputOutput context.
* \param pos The position of the parity block in the ::parity_handle_map vector.
*/
void io_parity_write(struct snapraid_io* io, unsigned* levcur);
void io_parity_write(struct snapraid_io* io, unsigned* levcur, unsigned* waiting_map, unsigned* waiting_mac);
/**
* Next write position.

View file

@ -264,6 +264,8 @@ static int state_scrub_process(struct snapraid_state* state, struct snapraid_par
unsigned silent_error;
unsigned io_error;
unsigned l;
unsigned* waiting_map;
unsigned waiting_mac;
/* maps the disks to handles */
handle = handle_mapping(state, &diskmax);
@ -277,6 +279,8 @@ static int state_scrub_process(struct snapraid_state* state, struct snapraid_par
/* initialize the io threads */
io_init(&io, state, state->opt.io_cache, buffermax, scrub_data_reader, handle, diskmax, scrub_parity_reader, 0, parity_handle, state->level);
waiting_map = malloc_nofail((diskmax + RAID_PARITY_MAX) * sizeof(unsigned));
error = 0;
silent_error = 0;
io_error = 0;
@ -362,7 +366,10 @@ static int state_scrub_process(struct snapraid_state* state, struct snapraid_par
state_usage_cpu(state);
/* get the next task */
task = io_data_read(&io, &diskcur);
task = io_data_read(&io, &diskcur, waiting_map, &waiting_mac);
/* until now is disk */
state_usage_disk(state, handle, waiting_map, waiting_mac);
/* get the task results */
disk = task->disk;
@ -378,9 +385,6 @@ static int state_scrub_process(struct snapraid_state* state, struct snapraid_par
if (!disk)
continue;
/* until now is disk */
state_usage_disk(state, disk);
/* if the block is unsynced, errors are expected */
if (block_has_invalid_parity(block)) {
/* report that the block and the file are not synced */
@ -485,10 +489,10 @@ static int state_scrub_process(struct snapraid_state* state, struct snapraid_par
struct snapraid_task* task;
unsigned levcur;
task = io_parity_read(&io, &levcur);
task = io_parity_read(&io, &levcur, waiting_map, &waiting_mac);
/* until now is parity */
state_usage_parity(state, levcur);
state_usage_parity(state, waiting_map, waiting_mac);
/* handle error conditions */
if (task->state == TASK_STATE_IOERROR) {
@ -670,6 +674,7 @@ bail:
free(handle);
free(rehandle_alloc);
free(waiting_map);
io_done(&io);
if (state->opt.expect_recoverable) {

View file

@ -24,6 +24,7 @@
#include "support.h"
#include "parity.h"
#include "stream.h"
#include "handle.h"
#include "raid/raid.h"
#include "raid/cpu.h"
@ -4032,6 +4033,58 @@ int state_progress(struct snapraid_state* state, block_off_t blockpos, block_off
return 0;
}
void state_usage_waste(struct snapraid_state* state)
{
uint64_t now = tick();
state->tick_last = now;
}
void state_usage_cpu(struct snapraid_state* state)
{
uint64_t now = tick();
uint64_t delta = now - state->tick_last;
/* increment the time spent in computations */
state->tick_cpu += delta;
state->tick_last = now;
}
void state_usage_disk(struct snapraid_state* state, struct snapraid_handle* handle_map, unsigned* waiting_map, unsigned waiting_mac)
{
uint64_t now = tick();
uint64_t delta = now - state->tick_last;
unsigned i;
/* increment the time spent in the data disks */
for (i = 0; i < waiting_mac; ++i) {
struct snapraid_disk* disk = handle_map[waiting_map[i]].disk;
if (!disk)
continue;
disk->tick += delta;
}
state->tick_io += delta;
state->tick_last = now;
}
void state_usage_parity(struct snapraid_state* state, unsigned* waiting_map, unsigned waiting_mac)
{
uint64_t now = tick();
uint64_t delta = now - state->tick_last;
unsigned i;
/* increment the time spent in the parity disk */
for (i = 0; i < waiting_mac; ++i)
state->parity[waiting_map[i]].tick += delta;
state->tick_io += delta;
state->tick_last = now;
}
void state_usage_print(struct snapraid_state* state)
{
uint64_t tick_total;

View file

@ -20,6 +20,8 @@
#include "elem.h"
struct snapraid_handle;
/****************************************************************************/
/* parity level */
@ -333,58 +335,22 @@ void state_progress_restart(struct snapraid_state* state);
/**
* Set the usage time as wasted one not counted.
*/
static inline void state_usage_waste(struct snapraid_state* state)
{
uint64_t now = tick();
state->tick_last = now;
}
void state_usage_waste(struct snapraid_state* state);
/**
* Set the usage time for CPU.
*/
static inline void state_usage_cpu(struct snapraid_state* state)
{
uint64_t now = tick();
uint64_t delta = now - state->tick_last;
/* increment the time spent in computations */
state->tick_cpu += delta;
state->tick_last = now;
}
void state_usage_cpu(struct snapraid_state* state);
/**
* Set the usage time for data disk.
* Set the usage time for a set of data disks.
*/
static inline void state_usage_disk(struct snapraid_state* state, struct snapraid_disk* disk)
{
uint64_t now = tick();
uint64_t delta = now - state->tick_last;
/* increment the time spent in the data disk */
disk->tick += delta;
state->tick_io += delta;
state->tick_last = now;
}
void state_usage_disk(struct snapraid_state* state, struct snapraid_handle* handle_map, unsigned* waiting_map, unsigned waiting_mac);
/**
* Set the usage time for parity disk.
* Set the usage time for a set of parity disk.
*/
static inline void state_usage_parity(struct snapraid_state* state, unsigned level)
{
uint64_t now = tick();
uint64_t delta = now - state->tick_last;
assert(level < LEV_MAX);
/* increment the time spent in the parity disk */
state->parity[level].tick += delta;
state->tick_io += delta;
state->tick_last = now;
}
void state_usage_parity(struct snapraid_state* state, unsigned* waiting_map, unsigned waiting_mac);
/**
* Print the stats of the usage time.

View file

@ -244,7 +244,7 @@ static int state_hash_process(struct snapraid_state* state, block_off_t blocksta
}
/* until now is disk */
state_usage_disk(state, disk);
state_usage_disk(state, handle, &j, 1);
countsize += read_size;
@ -681,6 +681,8 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
struct failed_struct* failed;
int* failed_map;
unsigned l;
unsigned* waiting_map;
unsigned waiting_mac;
/* the sync process assumes that all the hashes are correct */
/* including the ones from CHG and DELETED blocks */
@ -711,6 +713,7 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
failed = malloc_nofail(diskmax * sizeof(struct failed_struct));
failed_map = malloc_nofail(diskmax * sizeof(unsigned));
waiting_map = malloc_nofail((diskmax + RAID_PARITY_MAX) * sizeof(unsigned));
error = 0;
silent_error = 0;
@ -814,7 +817,10 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
/* until now is CPU */
state_usage_cpu(state);
task = io_data_read(&io, &diskcur);
task = io_data_read(&io, &diskcur, waiting_map, &waiting_mac);
/* until now is disk */
state_usage_disk(state, handle, waiting_map, waiting_mac);
/* get the results */
disk = task->disk;
@ -830,9 +836,6 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
if (!disk)
continue;
/* until now is disk */
state_usage_disk(state, disk);
/* get the state of the block */
block_state = block_state_get(block);
@ -1065,7 +1068,7 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
}
/* until now is parity */
state_usage_parity(state, l);
state_usage_parity(state, &l, 1);
}
/* if no error in parity read */
@ -1196,10 +1199,10 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
for (l = 0; l < state->level; ++l) {
unsigned levcur;
io_parity_write(&io, &levcur);
io_parity_write(&io, &levcur, waiting_map, &waiting_mac);
/* until now is parity */
state_usage_parity(state, levcur);
state_usage_parity(state, waiting_map, waiting_mac);
}
/* write finished */
@ -1362,6 +1365,7 @@ bail:
free(rehandle_alloc);
free(failed);
free(failed_map);
free(waiting_map);
io_done(&io);
if (state->opt.expect_recoverable) {