mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-26 10:51:54 -04:00
Preliminary usage graph
This commit is contained in:
parent
3e2420489a
commit
846c02e2c1
7 changed files with 217 additions and 45 deletions
|
|
@ -608,7 +608,7 @@ static void printl(const char* str, size_t pad)
|
|||
len = strlen(str);
|
||||
|
||||
while (len < pad) {
|
||||
printf(" ");
|
||||
putchar(' ');
|
||||
++len;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -225,8 +225,8 @@ static int state_dry_process(struct snapraid_state* state, struct snapraid_parit
|
|||
struct snapraid_disk* disk;
|
||||
unsigned diskcur;
|
||||
|
||||
/* until now is CPU */
|
||||
state_usage_cpu(state);
|
||||
/* until now is misc */
|
||||
state_usage_misc(state);
|
||||
|
||||
/* get the next task */
|
||||
task = io_data_read(&io, &diskcur, waiting_map, &waiting_mac);
|
||||
|
|
@ -284,8 +284,8 @@ static int state_dry_process(struct snapraid_state* state, struct snapraid_parit
|
|||
countsize += read_size;
|
||||
}
|
||||
|
||||
/* until now is CPU */
|
||||
state_usage_cpu(state);
|
||||
/* until now is misc */
|
||||
state_usage_misc(state);
|
||||
|
||||
/* read the parity */
|
||||
for (l = 0; l < state->level; ++l) {
|
||||
|
|
|
|||
|
|
@ -31,6 +31,11 @@
|
|||
/****************************************************************************/
|
||||
/* snapraid */
|
||||
|
||||
/**
|
||||
* Number of measures of the operation progress.
|
||||
*/
|
||||
#define PROGRESS_MAX 100
|
||||
|
||||
/**
|
||||
* Max UUID length.
|
||||
*/
|
||||
|
|
@ -328,10 +333,12 @@ struct snapraid_disk {
|
|||
char uuid[UUID_MAX]; /**< UUID of the disk. */
|
||||
|
||||
uint64_t device; /**< Device identifier. */
|
||||
uint64_t tick; /**< Usage time of the disk. */
|
||||
block_off_t total_blocks; /**< Number of total blocks. */
|
||||
block_off_t free_blocks; /**< Number of free blocks at the last sync. */
|
||||
|
||||
uint64_t tick; /**< Usage time. */
|
||||
uint64_t progress_tick[PROGRESS_MAX]; /**< Last ticks of progress. */
|
||||
|
||||
/**
|
||||
* First free searching block.
|
||||
* Note that it doesn't necessarily point at the first free block,
|
||||
|
|
@ -423,10 +430,8 @@ struct snapraid_parity {
|
|||
int skip_access; /**< If the disk is inaccessible and it should be skipped. */
|
||||
int is_excluded; /**< If the parity is excluded by disk filter. */
|
||||
|
||||
/**
|
||||
* Cumulative time used for parity disks.
|
||||
*/
|
||||
uint64_t tick;
|
||||
uint64_t tick; /**< Usage time. */
|
||||
uint64_t progress_tick[PROGRESS_MAX]; /**< Last cpu ticks of progress. */
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -364,8 +364,8 @@ static int state_scrub_process(struct snapraid_state* state, struct snapraid_par
|
|||
/* if not, silent errors are assumed as expected error */
|
||||
file_is_unsynced = 0;
|
||||
|
||||
/* until now is CPU */
|
||||
state_usage_cpu(state);
|
||||
/* until now is misc */
|
||||
state_usage_misc(state);
|
||||
|
||||
/* get the next task */
|
||||
task = io_data_read(&io, &diskcur, waiting_map, &waiting_mac);
|
||||
|
|
@ -456,6 +456,9 @@ static int state_scrub_process(struct snapraid_state* state, struct snapraid_par
|
|||
memhash(state->hash, state->hashseed, hash, buffer[diskcur], read_size);
|
||||
}
|
||||
|
||||
/* until now is hash */
|
||||
state_usage_hash(state);
|
||||
|
||||
if (block_has_updated_hash(block)) {
|
||||
/* compare the hash */
|
||||
if (memcmp(hash, block->hash, HASH_SIZE) != 0) {
|
||||
|
|
@ -483,8 +486,8 @@ static int state_scrub_process(struct snapraid_state* state, struct snapraid_par
|
|||
for (; l < LEV_MAX; ++l)
|
||||
buffer_recov[l] = 0;
|
||||
|
||||
/* until now is CPU */
|
||||
state_usage_cpu(state);
|
||||
/* until now is misc */
|
||||
state_usage_misc(state);
|
||||
|
||||
/* read the parity */
|
||||
for (l = 0; l < state->level; ++l) {
|
||||
|
|
@ -563,6 +566,9 @@ static int state_scrub_process(struct snapraid_state* state, struct snapraid_par
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* until now is raid */
|
||||
state_usage_raid(state);
|
||||
}
|
||||
|
||||
if (silent_error_on_this_block || io_error_on_this_block) {
|
||||
|
|
@ -606,8 +612,8 @@ static int state_scrub_process(struct snapraid_state* state, struct snapraid_par
|
|||
) {
|
||||
autosavedone = 0; /* restart the counter */
|
||||
|
||||
/* until now is CPU */
|
||||
state_usage_cpu(state);
|
||||
/* until now is misc */
|
||||
state_usage_misc(state);
|
||||
|
||||
state_progress_stop(state);
|
||||
|
||||
|
|
|
|||
162
cmdline/state.c
162
cmdline/state.c
|
|
@ -159,7 +159,9 @@ void state_init(struct snapraid_state* state)
|
|||
state->parity[l].is_excluded = 0;
|
||||
}
|
||||
state->tick_io = 0;
|
||||
state->tick_cpu = 0;
|
||||
state->tick_misc = 0;
|
||||
state->tick_raid = 0;
|
||||
state->tick_hash = 0;
|
||||
state->tick_last = tick();
|
||||
state->share[0] = 0;
|
||||
state->pool[0] = 0;
|
||||
|
|
@ -3908,6 +3910,8 @@ int state_progress(struct snapraid_state* state, block_off_t blockpos, block_off
|
|||
{
|
||||
time_t now;
|
||||
int pred;
|
||||
tommy_node* i;
|
||||
unsigned l;
|
||||
|
||||
now = time(0);
|
||||
|
||||
|
|
@ -3920,16 +3924,16 @@ int state_progress(struct snapraid_state* state, block_off_t blockpos, block_off
|
|||
if (state->progress_tick == 0
|
||||
|| state->progress_time[pred] != now
|
||||
) {
|
||||
uint64_t tick_total;
|
||||
uint64_t tick_cpu;
|
||||
uint64_t tick_total;
|
||||
time_t elapsed;
|
||||
unsigned out_perc = 0;
|
||||
unsigned out_speed = 0;
|
||||
unsigned out_cpu = 0;
|
||||
unsigned out_eta = 0;
|
||||
|
||||
tick_total = state->tick_cpu + state->tick_io;
|
||||
tick_cpu = state->tick_cpu;
|
||||
tick_cpu = state->tick_misc + state->tick_raid + state->tick_hash;
|
||||
tick_total = tick_cpu + state->tick_io;
|
||||
elapsed = now - state->progress_whole_start - state->progress_wasted;
|
||||
|
||||
/* completion percentage */
|
||||
|
|
@ -3946,8 +3950,10 @@ int state_progress(struct snapraid_state* state, block_off_t blockpos, block_off
|
|||
time_t delta_time;
|
||||
block_off_t delta_pos;
|
||||
data_off_t delta_size;
|
||||
uint64_t delta_tick_total;
|
||||
uint64_t delta_tick_cpu;
|
||||
uint64_t delta_tick_total;
|
||||
uint64_t oldest_tick_cpu;
|
||||
uint64_t oldest_tick_total;
|
||||
|
||||
/* number of past measures */
|
||||
past = state->progress_tick;
|
||||
|
|
@ -3968,11 +3974,16 @@ int state_progress(struct snapraid_state* state, block_off_t blockpos, block_off
|
|||
oldest -= PROGRESS_MAX;
|
||||
}
|
||||
|
||||
oldest_tick_cpu = state->progress_tick_misc[oldest]
|
||||
+ state->progress_tick_raid[oldest]
|
||||
+ state->progress_tick_hash[oldest];
|
||||
oldest_tick_total = oldest_tick_cpu + state->progress_tick_io[oldest];
|
||||
|
||||
delta_time = now - state->progress_time[oldest];
|
||||
delta_pos = countpos - state->progress_pos[oldest];
|
||||
delta_size = countsize - state->progress_size[oldest];
|
||||
delta_tick_total = tick_total - state->progress_tick_total[oldest];
|
||||
delta_tick_cpu = tick_cpu - state->progress_tick_cpu[oldest];
|
||||
delta_tick_cpu = tick_cpu - oldest_tick_cpu;
|
||||
delta_tick_total = tick_total - oldest_tick_total;
|
||||
|
||||
/* estimate the speed in MB/s */
|
||||
if (delta_time != 0)
|
||||
|
|
@ -3991,6 +4002,11 @@ int state_progress(struct snapraid_state* state, block_off_t blockpos, block_off
|
|||
log_tag("run:pos:%u:%u:%" PRIu64 ":%u:%u:%u:%u:%" PRIu64 "\n", blockpos, countpos, countsize, out_perc, out_eta, out_speed, out_cpu, (uint64_t)elapsed);
|
||||
log_flush();
|
||||
} else {
|
||||
if (msg_level >= MSG_VERBOSE) {
|
||||
printf("\n\n");
|
||||
state_usage_graph(state);
|
||||
}
|
||||
|
||||
msg_bar("%u%%, %u MB", out_perc, (unsigned)(countsize / MEGA));
|
||||
if (out_speed)
|
||||
msg_bar(", %u MB/s", out_speed);
|
||||
|
|
@ -4005,8 +4021,16 @@ int state_progress(struct snapraid_state* state, block_off_t blockpos, block_off
|
|||
state->progress_time[state->progress_ptr] = now;
|
||||
state->progress_pos[state->progress_ptr] = countpos;
|
||||
state->progress_size[state->progress_ptr] = countsize;
|
||||
state->progress_tick_cpu[state->progress_ptr] = tick_cpu;
|
||||
state->progress_tick_total[state->progress_ptr] = tick_total;
|
||||
state->progress_tick_misc[state->progress_ptr] = state->tick_misc;
|
||||
state->progress_tick_raid[state->progress_ptr] = state->tick_raid;
|
||||
state->progress_tick_hash[state->progress_ptr] = state->tick_hash;
|
||||
state->progress_tick_io[state->progress_ptr] = state->tick_io;
|
||||
for (i = state->disklist; i != 0; i = i->next) {
|
||||
struct snapraid_disk* disk = i->data;
|
||||
disk->progress_tick[state->progress_ptr] = disk->tick;
|
||||
}
|
||||
for (l = 0; l < state->level; ++l)
|
||||
state->parity[l].progress_tick[state->progress_ptr] = state->parity[l].tick;
|
||||
|
||||
/* next position */
|
||||
++state->progress_ptr;
|
||||
|
|
@ -4040,13 +4064,35 @@ void state_usage_waste(struct snapraid_state* state)
|
|||
state->tick_last = now;
|
||||
}
|
||||
|
||||
void state_usage_cpu(struct snapraid_state* state)
|
||||
void state_usage_misc(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_misc += delta;
|
||||
|
||||
state->tick_last = now;
|
||||
}
|
||||
|
||||
void state_usage_raid(struct snapraid_state* state)
|
||||
{
|
||||
uint64_t now = tick();
|
||||
uint64_t delta = now - state->tick_last;
|
||||
|
||||
/* increment the time spent in computations */
|
||||
state->tick_raid += delta;
|
||||
|
||||
state->tick_last = now;
|
||||
}
|
||||
|
||||
void state_usage_hash(struct snapraid_state* state)
|
||||
{
|
||||
uint64_t now = tick();
|
||||
uint64_t delta = now - state->tick_last;
|
||||
|
||||
/* increment the time spent in computations */
|
||||
state->tick_hash += delta;
|
||||
|
||||
state->tick_last = now;
|
||||
}
|
||||
|
|
@ -4085,6 +4131,100 @@ void state_usage_parity(struct snapraid_state* state, unsigned* waiting_map, uns
|
|||
state->tick_last = now;
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a repeated char.
|
||||
*/
|
||||
static void printc(char c, size_t pad)
|
||||
{
|
||||
while (pad) {
|
||||
putchar(c);
|
||||
--pad;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a string with space padding.
|
||||
*/
|
||||
static void printr(const char* str, size_t pad)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
len = strlen(str);
|
||||
|
||||
while (len < pad) {
|
||||
putchar(' ');
|
||||
++len;
|
||||
}
|
||||
|
||||
printf("%s", str);
|
||||
}
|
||||
|
||||
#define USAGE_COLUMN 60
|
||||
|
||||
void state_usage_graph(struct snapraid_state* state)
|
||||
{
|
||||
uint64_t tick_total;
|
||||
tommy_node* i;
|
||||
unsigned l;
|
||||
size_t pad;
|
||||
|
||||
tick_total = state->tick_misc + state->tick_raid + state->tick_hash + state->tick_io;
|
||||
if (!tick_total)
|
||||
return;
|
||||
|
||||
pad = 4;
|
||||
for (i = state->disklist; i != 0; i = i->next) {
|
||||
struct snapraid_disk* disk = i->data;
|
||||
size_t len = strlen(disk->name);
|
||||
if (pad < len)
|
||||
pad = len;
|
||||
}
|
||||
for (l = 0; l < state->level; ++l) {
|
||||
size_t len = strlen(lev_config_name(l));
|
||||
if (pad < len)
|
||||
pad = len;
|
||||
}
|
||||
|
||||
/* extra space */
|
||||
pad += 1;
|
||||
|
||||
/* here we don't use msg_progress() because it doesn't allow partial output */
|
||||
for (i = state->disklist; i != 0; i = i->next) {
|
||||
struct snapraid_disk* disk = i->data;
|
||||
printr(disk->name, pad);
|
||||
printf("%3" PRIu64 "%% | ", disk->tick * 100 / tick_total);
|
||||
printc('*', disk->tick * USAGE_COLUMN / tick_total);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
for (l = 0; l < state->level; ++l) {
|
||||
printr(lev_config_name(l), pad);
|
||||
printf("%3" PRIu64 "%% | ", state->parity[l].tick * 100 / tick_total);
|
||||
printc('*', state->parity[l].tick * USAGE_COLUMN / tick_total);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
printr("raid", pad);
|
||||
printf("%3" PRIu64 "%% | ", state->tick_raid * 100 / tick_total);
|
||||
printc('*', state->tick_raid * USAGE_COLUMN / tick_total);
|
||||
printf("\n");
|
||||
|
||||
printr("hash", pad);
|
||||
printf("%3" PRIu64 "%% | ", state->tick_hash * 100 / tick_total);
|
||||
printc('*', state->tick_hash * USAGE_COLUMN / tick_total);
|
||||
printf("\n");
|
||||
|
||||
printr("misc", pad);
|
||||
printf("%3" PRIu64 "%% | ", state->tick_misc * 100 / tick_total);
|
||||
printc('*', state->tick_misc * USAGE_COLUMN / tick_total);
|
||||
printf("\n");
|
||||
|
||||
printr("", pad);
|
||||
printf(" +-");
|
||||
printc('-', USAGE_COLUMN);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
void state_usage_print(struct snapraid_state* state)
|
||||
{
|
||||
uint64_t tick_total;
|
||||
|
|
|
|||
|
|
@ -119,11 +119,6 @@ struct snapraid_option {
|
|||
int auto_conf; /**< Allow to run without configuration file. */
|
||||
};
|
||||
|
||||
/**
|
||||
* Number of measures of the operation progress.
|
||||
*/
|
||||
#define PROGRESS_MAX 100
|
||||
|
||||
struct snapraid_state {
|
||||
struct snapraid_option opt; /**< Setup options. */
|
||||
int filter_hidden; /**< Filter out hidden files. */
|
||||
|
|
@ -158,7 +153,9 @@ struct snapraid_state {
|
|||
/**
|
||||
* Cumulative time used for computations.
|
||||
*/
|
||||
uint64_t tick_cpu;
|
||||
uint64_t tick_misc;
|
||||
uint64_t tick_raid;
|
||||
uint64_t tick_hash;
|
||||
|
||||
/**
|
||||
* Cumulative time used for all io operations of disks.
|
||||
|
|
@ -179,8 +176,10 @@ struct snapraid_state {
|
|||
time_t progress_time[PROGRESS_MAX]; /**< Last times of progress. */
|
||||
block_off_t progress_pos[PROGRESS_MAX]; /**< Last positions of progress. */
|
||||
data_off_t progress_size[PROGRESS_MAX]; /**< Last sizes of progress. */
|
||||
uint64_t progress_tick_cpu[PROGRESS_MAX]; /**< Last cpu ticks of progress. */
|
||||
uint64_t progress_tick_total[PROGRESS_MAX]; /**< Last total ticks of progress. */
|
||||
uint64_t progress_tick_misc[PROGRESS_MAX]; /**< Last cpu ticks of progress. */
|
||||
uint64_t progress_tick_raid[PROGRESS_MAX]; /**< Last raid ticks of progress. */
|
||||
uint64_t progress_tick_hash[PROGRESS_MAX]; /**< Last hash ticks of progress. */
|
||||
uint64_t progress_tick_io[PROGRESS_MAX]; /**< Last io ticks of progress. */
|
||||
|
||||
int progress_ptr; /**< Pointer to the next position to fill. Rolling over. */
|
||||
int progress_tick; /**< Number of measures done. */
|
||||
|
|
@ -340,7 +339,9 @@ void state_usage_waste(struct snapraid_state* state);
|
|||
/**
|
||||
* Set the usage time for CPU.
|
||||
*/
|
||||
void state_usage_cpu(struct snapraid_state* state);
|
||||
void state_usage_misc(struct snapraid_state* state);
|
||||
void state_usage_raid(struct snapraid_state* state);
|
||||
void state_usage_hash(struct snapraid_state* state);
|
||||
|
||||
/**
|
||||
* Set the usage time for a set of data disks.
|
||||
|
|
@ -357,6 +358,11 @@ void state_usage_parity(struct snapraid_state* state, unsigned* waiting_map, uns
|
|||
*/
|
||||
void state_usage_print(struct snapraid_state* state);
|
||||
|
||||
/**
|
||||
* Print a graph of usage time.
|
||||
*/
|
||||
void state_usage_graph(struct snapraid_state* state);
|
||||
|
||||
/**
|
||||
* Check the file-system on all disks.
|
||||
* On error it aborts.
|
||||
|
|
|
|||
|
|
@ -124,8 +124,8 @@ static int state_hash_process(struct snapraid_state* state, block_off_t blocksta
|
|||
/* if we have to use the old hash */
|
||||
rehash = info_get_rehash(info);
|
||||
|
||||
/* until now is CPU */
|
||||
state_usage_cpu(state);
|
||||
/* until now is misc */
|
||||
state_usage_misc(state);
|
||||
|
||||
/* if the file is different than the current one, close it */
|
||||
if (handle[j].file != 0 && handle[j].file != file) {
|
||||
|
|
@ -255,6 +255,9 @@ static int state_hash_process(struct snapraid_state* state, block_off_t blocksta
|
|||
memhash(state->hash, state->hashseed, hash, buffer, read_size);
|
||||
}
|
||||
|
||||
/* until now is hash */
|
||||
state_usage_hash(state);
|
||||
|
||||
if (block_state == BLOCK_STATE_REP) {
|
||||
/* compare the hash */
|
||||
if (memcmp(hash, block->hash, HASH_SIZE) != 0) {
|
||||
|
|
@ -817,8 +820,8 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
|
|||
block_off_t file_pos;
|
||||
unsigned diskcur;
|
||||
|
||||
/* until now is CPU */
|
||||
state_usage_cpu(state);
|
||||
/* until now is misc */
|
||||
state_usage_misc(state);
|
||||
|
||||
task = io_data_read(&io, &diskcur, waiting_map, &waiting_mac);
|
||||
|
||||
|
|
@ -917,6 +920,9 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
|
|||
memhash(state->hash, state->hashseed, hash, buffer[diskcur], read_size);
|
||||
}
|
||||
|
||||
/* until now is hash */
|
||||
state_usage_hash(state);
|
||||
|
||||
if (block_has_updated_hash(block)) {
|
||||
/* compare the hash */
|
||||
if (memcmp(hash, block->hash, HASH_SIZE) != 0) {
|
||||
|
|
@ -1035,8 +1041,8 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
|
|||
|
||||
/* if we have something to recover and enough parity */
|
||||
if (something_to_recover && j == failed_count) {
|
||||
/* until now is CPU */
|
||||
state_usage_cpu(state);
|
||||
/* until now is misc */
|
||||
state_usage_misc(state);
|
||||
|
||||
/* read the parity */
|
||||
/* we are sure that parity exists because */
|
||||
|
|
@ -1082,6 +1088,9 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
|
|||
/* only 'fix' supports the most advanced fixing */
|
||||
raid_rec(failed_mac, failed_map, diskmax, state->level, state->block_size, buffer);
|
||||
|
||||
/* until now is raid */
|
||||
state_usage_raid(state);
|
||||
|
||||
/* check the result and prepare the data */
|
||||
for (j = 0; j < failed_count; ++j) {
|
||||
unsigned char hash[HASH_SIZE];
|
||||
|
|
@ -1099,6 +1108,9 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
|
|||
memhash(state->hash, state->hashseed, hash, block_buffer, size);
|
||||
}
|
||||
|
||||
/* until now is hash */
|
||||
state_usage_hash(state);
|
||||
|
||||
/* if the hash doesn't match */
|
||||
if (memcmp(hash, failed[j].block->hash, HASH_SIZE) != 0) {
|
||||
/* we have not recovered */
|
||||
|
|
@ -1132,6 +1144,9 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
|
|||
/* compute the parity */
|
||||
raid_gen(diskmax, state->level, state->block_size, buffer);
|
||||
|
||||
/* until now is raid */
|
||||
state_usage_raid(state);
|
||||
|
||||
/* mark that the parity is going to be written */
|
||||
parity_going_to_be_updated = 1;
|
||||
}
|
||||
|
|
@ -1196,7 +1211,7 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
|
|||
/* Note that the calls to io_parity_write() are mandatory */
|
||||
/* even if the parity doesn't need to be updated */
|
||||
/* This because we want to keep track of the time usage */
|
||||
state_usage_cpu(state);
|
||||
state_usage_misc(state);
|
||||
|
||||
/* write the parity */
|
||||
for (l = 0; l < state->level; ++l) {
|
||||
|
|
@ -1258,8 +1273,8 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
|
|||
) {
|
||||
autosavedone = 0; /* restart the counter */
|
||||
|
||||
/* until now is CPU */
|
||||
state_usage_cpu(state);
|
||||
/* until now is misc */
|
||||
state_usage_misc(state);
|
||||
|
||||
state_progress_stop(state);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue