diff --git a/src/libprobe.c b/src/libprobe.c index 45156ad..2ce6bae 100644 --- a/src/libprobe.c +++ b/src/libprobe.c @@ -197,10 +197,15 @@ struct def_x_block { uint64_t expected_offset; }; +struct x_block_found { + enum block_state state; + uint64_t found_offset; +}; + static int find_first_x_block(struct device *dev, const struct def_x_block x_blocks[], uint32_t n_blocks, uint64_t bs_set, uint32_t *pfirst_x_block_idx, - enum block_state *pstate, struct rdwr_info *rwi, + struct x_block_found *xbf, struct rdwr_info *rwi, progress_cb cb, unsigned int indent) { const unsigned int block_order = dev_get_block_order(dev); @@ -230,7 +235,8 @@ static int find_first_x_block(struct device *dev, if (in_bs_set(bs_set, bs)) { /* Found the first x_block. */ *pfirst_x_block_idx = i; - *pstate = bs; + xbf->state = bs; + xbf->found_offset = found_offset; end_measurement(&rwi->randr_fw); return false; } @@ -242,13 +248,46 @@ static int find_first_x_block(struct device *dev, return false; } +static bool is_block_from_cache(const struct rdwr_info *rwi, uint64_t block) +{ + if (rwi->cache_size_block == 0) + return false; + assert(block < rwi->cache_pos + rwi->cache_size_block); + return block >= rwi->cache_pos; +} + +static void cb_bad_block_info(const progress_cb cb, const unsigned int indent, + const struct def_x_block *x_block, const struct x_block_found *xbf, + const struct device *dev, const struct rdwr_info *rwi) +{ + if (xbf->state == bs_overwritten) { + const unsigned int block_order = dev_get_block_order(dev); + const unsigned int block_size = dev_get_block_size(dev); + const uint64_t found_block = xbf->found_offset >> block_order; + + assert((xbf->found_offset & (block_size - 1)) == 0); + + if (is_block_from_cache(rwi, found_block)) { + cb(indent, "INFO: Block %" PRIu64 " comes from the cache block %" PRIu64 "\n", + x_block->pos, found_block); + } else { + cb(indent, "INFO: Block %" PRIu64 " overwrites block %" PRIu64 "\n", + found_block, x_block->pos); + } + return; + } + + cb(indent, "INFO: Block %" PRIu64 " is %s\n", + x_block->pos, block_state_to_str(xbf->state)); +} + static int find_first_bad_block(struct device *dev, const uint64_t pos[], uint32_t n_pos, bool *pany_bad, uint64_t *pbad_pos, struct rdwr_info *rwi, progress_cb cb, unsigned int indent) { const unsigned int block_order = dev_get_block_order(dev); struct def_x_block x_blocks[n_pos]; - enum block_state bs; + struct x_block_found xbf; uint32_t i; for (i = 0; i < n_pos; i++) { @@ -258,13 +297,12 @@ static int find_first_bad_block(struct device *dev, const uint64_t pos[], if (find_first_x_block(dev, x_blocks, n_pos, neg_bs_set(bs_to_set(bs_good)), - &i, &bs, rwi, cb, indent)) + &i, &xbf, rwi, cb, indent)) return true; *pany_bad = i < n_pos; if (*pany_bad) { *pbad_pos = x_blocks[i].pos; - cb(indent, "INFO: Block %" PRIu64 " is %s!\n", - *pbad_pos, block_state_to_str(bs)); + cb_bad_block_info(cb, indent, &x_blocks[i], &xbf, dev, rwi); } return false; } @@ -629,7 +667,7 @@ static int find_wrap(struct device *dev, unsigned int block_order; uint64_t expected_offset, high_bit; uint32_t i; - enum block_state bs; + struct x_block_found xbf; cb(indent, "## Find module\n"); @@ -681,13 +719,14 @@ static int find_wrap(struct device *dev, assert(high_bit + good_block >= *pright_pos); if (find_first_x_block(dev, x_blocks, n_samples, - bss_to_set(bss, DIM(bss)), &i, &bs, rwi, + bss_to_set(bss, DIM(bss)), &i, &xbf, rwi, cb, indent + 1)) return true; if (i < n_samples) { *pright_pos = x_blocks[i].pos - good_block; /* = high_bit */ cb(indent + 1, "INFO: Block %" PRIu64 " overwrites %s block %" PRIu64 "\n", - x_blocks[i].pos, block_state_to_str(bs), good_block); + x_blocks[i].pos, block_state_to_str(xbf.state), + good_block); } return false; }