Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TDB-184 : Broken fsync error handling #410

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

george-lorch
Copy link
Contributor

  • Factored out i/o error reporting to be common and try to obtain actual
    filename from descriptor.
  • Fixed ENOSPC reporting to use common i/o reporting.
  • Fixed fsync retry logic to retry EINTR, EIO, and ENOLCK based on InnoDB code
    and upstream mysql issues 34823 and 90296. Retry will print message every 100
    attempts in a loop.
  • Touched up 'slow fsync' tracking and reporting to use new i/o error reporting.
  • Fixed close retry logic to be same as fsync.

@george-lorch
Copy link
Contributor Author

@@ -72,67 +72,98 @@ void toku_fs_get_write_info(time_t *enospc_last_time, uint64_t *enospc_current,
*enospc_total = toku_write_enospc_total;
}


void report_io_problem(int fd, const char *fmt, ...) __attribute__((format(printf, 2, 3)));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cannot attach attribute to definition to save a declaration (in front?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ohh, good catch, I forgot attribute could be used like that.

va_list ap;
va_start(ap, fmt);

const int tstr_length = 26;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

static constexpr

buf);
#endif
fflush(stderr);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

va_end

report_io_problem(
fd, "Failed write of [%" PRIu64 "] bytes.", (uint64_t)len);
int out_of_disk_space = 1;
assert(!out_of_disk_space); // Give an error message that might
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huh. bool at least?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was original FT code and I saw no reason to change it, funky as it is.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh, and static constexpr yada yada if you decide to touch it

report_io_problem(fd,
"Write of [%" PRIu64
"] bytes interrupted. Retrying.",
(uint64_t)len);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

C++ style cast

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

similar, slightly modified FT code, but yeah

case ENOSPC: {
if (toku_assert_on_write_enospc) {
report_io_problem(
fd, "Failed write of [%" PRIu64 "] bytes.", (uint64_t)len);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

C++ style cast

// be useful if this is the only one
// that survives.
} else {
toku_sync_fetch_and_add(&toku_write_enospc_total, 1);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be too much work to convert to std::atomic?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably not as these are pretty local to file.cc

// fallthrough
case EINTR:
// fallthrough
case EIO:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But the issue being fixed here is that EIO must fail at once, exactly the opposite of EINTR/ENOLCK

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is not what I came to understand about EIO, which could be incorrect. https://stackoverflow.com/questions/42434872/writing-programs-to-cope-with-i-o-errors-causing-lost-writes-on-linux

Otherwise, what is the point of this exercise at all where FT would generally assert on all errors that were not EINTR or ENOSPC.

Copy link
Contributor

@laurynas-biveinis laurynas-biveinis Apr 11, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's what I was referring to with my comment on the TDB issue: "I didn't realise that was a release-build assert too - in which case the bug is not nearly as serious"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, yeah, the discussion meanders around from retry indefinitely, to retry exactly once, to fail immediately as the write is lost forever. So yeah, now I think the original suggestion reported in 90296 is correct, abort immediately as a write is lost.

}

if (r == -1) {
int what_errno = get_error_errno();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly duplicated code with the above

- Factored out i/o error reporting to be common and try to obtain actual
  filename from descriptor.
- Factored out write, close and fsync error handling into a common function that
  handles special cases sch as ENOLCK, EINTR, ENOSPC, and EIO. See upstream
  MySQL issues 34823 and 90296 for details on ENOLCK and EIO.
- Fixed write, close, and fsync retry logic to use new common handler.
- Touched up 'slow fsync' tracking and reporting to use new i/o error reporting.
- Converted metric trackers to std::atomic where appropriate.
- Various bits of code reformatting and conversions to std::atomic and
  constexpr, #include style fixes.
@george-lorch
Copy link
Contributor Author

OK, I reworked it a bit more and factored out the write error handing as well as it wasn't really doing what the function names might indicate. Here is a new set of jenkins runs. Please take another look and approach it as if it were a new review and not just the items commented.

https://jenkins.percona.com/view/TokuDB/job/PerconaFT-param/123/
https://jenkins.percona.com/view/PS%205.6/job/percona-server-5.6-param/2151/
https://jenkins.percona.com/view/5.7/job/mysql-5.7-param/1772/

Copy link
Contributor

@laurynas-biveinis laurynas-biveinis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks much better now!

va_list ap;
va_start(ap, fmt);

constexpr int tstr_length = 26;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

static constexpr (but only if there are other comments to address)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants