Commit fff75eb2 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'errseq-v4.17' of git://git.kernel.org/pub/scm/linux/kernel/git/jlayton/linux

Pull errseq infrastructure fix from Jeff Layton:
 "The PostgreSQL developers recently had a spirited discussion about the
  writeback error handling in Linux, and reached out to us about a
  behavoir change to the code that bit them when the errseq_t changes
  were merged.

  When we changed to using errseq_t for tracking writeback errors, we
  lost the ability for an application to see a writeback error that
  occurred before the open on which the fsync was issued. This was
  problematic for PostgreSQL which offloads fsync calls to a completely
  separate process from the DB writers.

  This patch restores that ability. If the errseq_t value in the inode
  does not have the SEEN flag set, then we just return 0 for the sample.
  That ensures that any recorded error is always delivered at least
  once.

  Note that we might still lose the error if the inode gets evicted from
  the cache before anything can reopen it, but that was the case before
  errseq_t was merged. At LSF/MM we had some discussion about keeping
  inodes with unreported writeback errors around in the cache for longer
  (possibly indefinitely), but that's really a separate problem"

* tag 'errseq-v4.17' of git://git.kernel.org/pub/scm/linux/kernel/git/jlayton/linux:
  errseq: Always report a writeback error once
parents 8188fc8b b4678df1
...@@ -111,27 +111,22 @@ EXPORT_SYMBOL(errseq_set); ...@@ -111,27 +111,22 @@ EXPORT_SYMBOL(errseq_set);
* errseq_sample() - Grab current errseq_t value. * errseq_sample() - Grab current errseq_t value.
* @eseq: Pointer to errseq_t to be sampled. * @eseq: Pointer to errseq_t to be sampled.
* *
* This function allows callers to sample an errseq_t value, marking it as * This function allows callers to initialise their errseq_t variable.
* "seen" if required. * If the error has been "seen", new callers will not see an old error.
* If there is an unseen error in @eseq, the caller of this function will
* see it the next time it checks for an error.
* *
* Context: Any context.
* Return: The current errseq value. * Return: The current errseq value.
*/ */
errseq_t errseq_sample(errseq_t *eseq) errseq_t errseq_sample(errseq_t *eseq)
{ {
errseq_t old = READ_ONCE(*eseq); errseq_t old = READ_ONCE(*eseq);
errseq_t new = old;
/* /* If nobody has seen this error yet, then we can be the first. */
* For the common case of no errors ever having been set, we can skip if (!(old & ERRSEQ_SEEN))
* marking the SEEN bit. Once an error has been set, the value will old = 0;
* never go back to zero. return old;
*/
if (old != 0) {
new |= ERRSEQ_SEEN;
if (old != new)
cmpxchg(eseq, old, new);
}
return new;
} }
EXPORT_SYMBOL(errseq_sample); EXPORT_SYMBOL(errseq_sample);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment