diff --git a/cmdline/elem.h b/cmdline/elem.h index c9a79d5a..fa6a95f4 100644 --- a/cmdline/elem.h +++ b/cmdline/elem.h @@ -914,28 +914,38 @@ struct snapraid_map* map_alloc(const char* name, unsigned position, block_off_t */ void map_free(struct snapraid_map* map); +/** + * Mask used to store additional information in the info bits. + * + * These bits reduce the granurality of the time in the memory representation. + */ +#define INFO_MASK 0x7 + /** * Makes an info. */ -static inline snapraid_info info_make(time_t last_access, int error, int rehash) +static inline snapraid_info info_make(time_t last_access, int error, int rehash, int justsynced) { /* clear the lowest bits as reserved for other information */ - snapraid_info info = last_access & ~0x3; + snapraid_info info = last_access & ~INFO_MASK; if (error != 0) info |= 0x1; if (rehash != 0) info |= 0x2; + if (justsynced != 0) + info |= 0x4; return info; } /** * Extracts the time information. * This is the last time when the block was know to be correct. + * The "scrubbed" info tells if the time is referreing at the latest sync or scrub. */ static inline time_t info_get_time(snapraid_info info) { - return info & ~0x3; + return info & ~INFO_MASK; } /** @@ -956,6 +966,15 @@ static inline int info_get_rehash(snapraid_info info) return (info & 0x2) != 0; } +/** + * Extracts the scrubbed information. + * Reports if the block address was never scrubbed. + */ +static inline int info_get_justsynced(snapraid_info info) +{ + return (info & 0x4) != 0; +} + /** * Marks the block address as with error. */ diff --git a/cmdline/scrub.c b/cmdline/scrub.c index 16aebb66..12745e5b 100644 --- a/cmdline/scrub.c +++ b/cmdline/scrub.c @@ -415,7 +415,7 @@ static int state_scrub_process(struct snapraid_state* state, struct snapraid_par } if (silent_error_on_this_block || io_error_on_this_block) { - /* set the error status keeping the existing time and hash */ + /* set the error status keeping other info */ info_set(&state->infoarr, i, info_set_bad(info)); } else if (error_on_this_block) { /* do nothing, as this is a generic error */ @@ -432,7 +432,7 @@ static int state_scrub_process(struct snapraid_state* state, struct snapraid_par /* update the time info of the block */ /* and clear any other flag */ - info_set(&state->infoarr, i, info_make(now, 0, 0)); + info_set(&state->infoarr, i, info_make(now, 0, 0, 0)); } /* mark the state as needing write */ diff --git a/cmdline/state.c b/cmdline/state.c index f0b19a8e..bfafbc90 100644 --- a/cmdline/state.c +++ b/cmdline/state.c @@ -1639,6 +1639,7 @@ static void state_read_text(struct snapraid_state* state, const char* path, STRE snapraid_info info; int rehash; int bad; + int justsynced; uint32_t t; ret = sgetu32(f, &v_pos); @@ -1675,6 +1676,7 @@ static void state_read_text(struct snapraid_state* state, const char* path, STRE /* read extra tags if present */ rehash = 0; bad = 0; + justsynced = 0; c = sgetc(f); while (c == ' ') { ret = sgettok(f, buffer, sizeof(buffer)); @@ -1696,6 +1698,8 @@ static void state_read_text(struct snapraid_state* state, const char* path, STRE exit(EXIT_FAILURE); /* LCOV_EXCL_STOP */ } + } else if (strcmp(buffer, "justsynced") == 0) { + justsynced = 1; } else { /* LCOV_EXCL_START */ log_fatal("Invalid 'inf' specification '%s' in '%s' at line %u\n", buffer, path, line); @@ -1707,7 +1711,7 @@ static void state_read_text(struct snapraid_state* state, const char* path, STRE } sungetc(c, f); - info = info_make(t, bad, rehash); + info = info_make(t, bad, rehash, justsynced); /* insert the info in the array */ info_set(&state->infoarr, v_pos, info); @@ -2518,7 +2522,7 @@ static void state_read_text(struct snapraid_state* state, const char* path, STRE if (!info) { /* LCOV_EXCL_START */ /* set a fake info block */ - info = info_make(save_time, 0, 0); + info = info_make(save_time, 0, 0, 0); /* insert the info in the array */ info_set(&state->infoarr, b, info); @@ -2896,6 +2900,9 @@ static void state_write_text(struct snapraid_state* state, STREAM* f) if (info_get_rehash(info)) { sputsl(" rehash", f); } + if (info_get_justsynced(info)) { + sputsl(" justsynced", f); + } sputeol(f); if (serror(f)) { /* LCOV_EXCL_START */ @@ -3306,8 +3313,9 @@ static void state_read_binary(struct snapraid_state* state, const char* path, ST v_pos = 0; while (v_pos < blockmax) { - int rehash; int bad; + int rehash; + int justsynced; uint32_t t; uint32_t flag; uint32_t v_count; @@ -3350,6 +3358,7 @@ static void state_read_binary(struct snapraid_state* state, const char* path, ST /* analyze the flags */ bad = (flag & 2) != 0; rehash = (flag & 4) != 0; + justsynced = (flag & 8) != 0; if (rehash && state->prevhash == HASH_UNDEFINED) { /* LCOV_EXCL_START */ @@ -3359,7 +3368,7 @@ static void state_read_binary(struct snapraid_state* state, const char* path, ST /* LCOV_EXCL_STOP */ } - info = info_make(t + v_oldest, bad, rehash); + info = info_make(t + v_oldest, bad, rehash, justsynced); } else { info = 0; } @@ -4328,6 +4337,8 @@ static void state_write_binary(struct snapraid_state* state, STREAM* f) flag |= 2; if (info_get_rehash(info)) flag |= 4; + if (info_get_justsynced(info)) + flag |= 8; sputb32(flag, f); t = info_get_time(info) - info_oldest; diff --git a/cmdline/sync.c b/cmdline/sync.c index 0a48b2d0..05613e3f 100644 --- a/cmdline/sync.c +++ b/cmdline/sync.c @@ -1020,7 +1020,7 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari } /* we update the info block only if we really have updated the parity */ - /* because otherwise the time info would be misleading as we didn't */ + /* because otherwise the time/justsynced info would be misleading as we didn't */ /* wrote the parity at this time */ /* we also update the info block only if no silent error was found */ /* because has no sense to refresh the time for data that we know bad */ @@ -1039,7 +1039,7 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari /* update the time info of the block */ /* we are also clearing any previous bad and rehash flag */ - info_set(&state->infoarr, i, info_make(now, 0, 0)); + info_set(&state->infoarr, i, info_make(now, 0, 0, 1)); } }