From 9a5f30cd32d7766cf2e82332ac4c70b4e5db3f3d Mon Sep 17 00:00:00 2001 From: Andrea Mazzoleni Date: Thu, 27 Aug 2015 18:02:12 +0200 Subject: [PATCH] Add a new justsynced info bit to position The value 0 means that the block is scrubbed, and it allows an easy conversion of past content files. Note that past versions ignore this info when using binary content files, then we don't increase the version of the format. --- cmdline/elem.h | 25 ++++++++++++++++++++++--- cmdline/scrub.c | 4 ++-- cmdline/state.c | 19 +++++++++++++++---- cmdline/sync.c | 4 ++-- 4 files changed, 41 insertions(+), 11 deletions(-) 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)); } }