Fix report when .fff files are not fully read

Two things could go wrong when .fff files are not fully read:

1. The constraint "assert(*read_all || errno == EIO);"
   could fail because, according to the manual,
   feof(3) does not set errno(3), but gettimeofday(2),
   which is called after fread(3), does.

2. The tail message "NOT fully read" was never issued because
   the test was "read_all", and variable read_all was a pointer.
   Thus, the test was always true.

The not-fully-read error message now adds the output of
strerror(3) to guide the diagnose of the failure.

These bugs must be rare because they have been lurking around for
more than two years according to git's log.
They were only found due to a bug report by John Lussmyer on
September 21st, 2013.
This commit is contained in:
Michel Machado
2013-09-23 10:30:36 -04:00
parent 532bad04d6
commit 05eceb342d

View File

@@ -25,8 +25,7 @@ static inline void update_dt(struct timeval *dt, const struct timeval *t1,
#define TOLERANCE 2
#define PRINT_STATUS(s) printf("%s%7" PRIu64 "/%9" PRIu64 "/%7" PRIu64 "/%7" \
PRIu64 "%s", (s), *ptr_ok, *ptr_corrupted, *ptr_changed, \
*ptr_overwritten, tail_msg)
PRIu64, (s), *ptr_ok, *ptr_corrupted, *ptr_changed, *ptr_overwritten)
#define BLANK " "
#define CLEAR ("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b" \
@@ -34,7 +33,7 @@ static inline void update_dt(struct timeval *dt, const struct timeval *t1,
static void validate_file(const char *path, int number,
uint64_t *ptr_ok, uint64_t *ptr_corrupted, uint64_t *ptr_changed,
uint64_t *ptr_overwritten, uint64_t *ptr_size, int *read_all,
uint64_t *ptr_overwritten, uint64_t *ptr_size, int *ptr_read_all,
struct timeval *ptr_dt, int progress)
{
char full_fn[PATH_MAX];
@@ -47,7 +46,7 @@ static void validate_file(const char *path, int number,
uint64_t offset, expected_offset;
struct drand48_data state;
long int rand_int;
char *tail_msg = "";
int final_errno;
struct timeval t1, t2;
/* Progress time. */
struct timeval pt1 = { .tv_sec = -1000, .tv_usec = 0 };
@@ -65,7 +64,7 @@ static void validate_file(const char *path, int number,
/* If the kernel follows our advice, f3read won't ever read from cache
* even when testing small memory cards without a remount, and
* we should have better reading speed measurement.
* we should have a better reading-speed measurement.
*/
assert(!fdatasync(fd));
assert(!posix_fadvise(fd, 0, 0, POSIX_FADV_DONTNEED));
@@ -77,6 +76,7 @@ static void validate_file(const char *path, int number,
ptr_end = sector + SECTOR_SIZE;
sectors_read = fread(sector, SECTOR_SIZE, 1, f);
final_errno = errno;
expected_offset = (uint64_t)number * GIGABYTES;
while (sectors_read > 0) {
assert(sectors_read == 1);
@@ -94,6 +94,7 @@ static void validate_file(const char *path, int number,
}
sectors_read = fread(sector, SECTOR_SIZE, 1, f);
final_errno = errno;
expected_offset += SECTOR_SIZE;
if (offset_match) {
@@ -122,15 +123,19 @@ static void validate_file(const char *path, int number,
assert(!gettimeofday(&t2, NULL));
update_dt(ptr_dt, &t1, &t2);
*read_all = feof(f);
assert(*read_all || errno == EIO);
*ptr_read_all = feof(f);
*ptr_size = ftell(f);
assert(*ptr_size >= 0);
fclose(f);
tail_msg = read_all ? "" : " - NOT fully read";
PRINT_STATUS(progress ? CLEAR : "");
if (!*ptr_read_all) {
assert(ferror(f));
printf(" - NOT fully read due to \"%s\"",
strerror(final_errno));
}
printf("\n");
fclose(f);
}
static void report(const char *prefix, uint64_t i)