f3probe: more than 45% speed-up with limbo drives

Skip the second test of a block if the first time test reads
something really different from what was written.
This commit is contained in:
Michel Machado 2014-08-19 19:23:26 -04:00
parent 6a63a5fff4
commit 185145f5a1

View File

@ -508,12 +508,6 @@ static inline int equal_blk(const char *b1, const char *b2)
return !memcmp(b1, b2, BLOCK_SIZE); return !memcmp(b1, b2, BLOCK_SIZE);
} }
static inline void *align_512(void *p)
{
uintptr_t ip = (uintptr_t)p;
return (void *)( (ip + 511) & ~511 );
}
/* Minimum size of the memory chunk used to build flash drives. /* Minimum size of the memory chunk used to build flash drives.
* It must be a power of two. * It must be a power of two.
*/ */
@ -550,7 +544,23 @@ static int search_wrap(struct device *dev,
return false; return false;
} }
/* XXX Should test if block if fully damaged, if so, avoid retrying. */ /* Return true if @b1 and b2 are at most @tolerance_byte bytes different. */
static int similar_blk(const char *b1, const char *b2, int tolerance_byte)
{
int i;
for (i = 0; i < BLOCK_SIZE; i++) {
if (*b1 != *b2) {
tolerance_byte--;
if (tolerance_byte <= 0)
return false;
}
b1++;
b2++;
}
return true;
}
/* Return true if the block @pos is damaged. */ /* Return true if the block @pos is damaged. */
static int test_block(struct device *dev, static int test_block(struct device *dev,
const char *stamp_blk, char *probe_blk, uint64_t pos) const char *stamp_blk, char *probe_blk, uint64_t pos)
@ -564,19 +574,29 @@ static int test_block(struct device *dev,
if (dev_reset(dev) && dev_reset(dev)) if (dev_reset(dev) && dev_reset(dev))
return true; return true;
/* Test block. */ /*
* Test block.
*/
if (dev_read_block(dev, probe_blk, pos) && if (dev_read_block(dev, probe_blk, pos) &&
dev_read_block(dev, probe_blk, pos)) dev_read_block(dev, probe_blk, pos))
return true; return true;
if (!equal_blk(stamp_blk, probe_blk)) {
/* The probe block seems to be damaged. if (equal_blk(stamp_blk, probe_blk))
* Trying a second time... return false;
*/
return dev_write_and_reset(dev, stamp_blk, pos) || /* Save time with certainly damaged blocks. */
dev_read_block(dev, probe_blk, pos) || if (!similar_blk(stamp_blk, probe_blk, 8)) {
!equal_blk(stamp_blk, probe_blk); /* The probe block is damaged. */
return true;
} }
return false;
/* The probe block seems to be damaged.
* Trying a second time...
*/
return dev_write_and_reset(dev, stamp_blk, pos) ||
dev_read_block(dev, probe_blk, pos) ||
!equal_blk(stamp_blk, probe_blk);
} }
/* Caller must guarantee that the left bock is good, and written. */ /* Caller must guarantee that the left bock is good, and written. */
@ -644,6 +664,12 @@ static int ceiling_log2(uint64_t x)
return ilog2(clp2(x)); return ilog2(clp2(x));
} }
static inline void *align_512(void *p)
{
uintptr_t ip = (uintptr_t)p;
return (void *)( (ip + 511) & ~511 );
}
/* XXX Properly handle read and write errors. */ /* XXX Properly handle read and write errors. */
void probe_device(struct device *dev, uint64_t *preal_size_byte, void probe_device(struct device *dev, uint64_t *preal_size_byte,
uint64_t *pannounced_size_byte, int *pwrap) uint64_t *pannounced_size_byte, int *pwrap)