Skip to content
This repository has been archived by the owner on Aug 13, 2019. It is now read-only.

fix wal panic when page flush fails. #582

Merged

Conversation

krasi-georgiev
Copy link
Contributor

@krasi-georgiev krasi-georgiev commented Apr 15, 2019

fixes: prometheus/prometheus#3283

New records should be added to the page only when the last flush
succeeded. Otherwise the page would be full and panics when trying to
add a new record.

to replicate the bug:

dd if=/dev/zero of=tmp/data.img bs=1M count=20 // create a 20mb disk image
mkfs.ext4 /tmp/data.img
mkdir /tmp/prometheus/
sudo mount -t ext4 -o loop /tmp/data.img /tmp/prometheus/
GO111MODULE=on go run cmd/prometheus/main.go   --config.file=.local/simpleMany.yaml --storage.tsdb.path=/tmp/prometheus   --storage.tsdb.wal-segment-size=1MB

before the fix this will panic when the disk image is full because it is trying to add more records to the page when it is already full.

At the moment can't think of simple test to test for this, but will add it to https://github.com/prometheus/tsdb/issues/579 if we figure out how to inject file system faults.

Signed-off-by: Krasi Georgiev kgeorgie@redhat.com

New records should be added to the page only when the last flush
succeeded. Otherwise the page would be full and panics when trying to
add a new record.

Signed-off-by: Krasi Georgiev <kgeorgie@redhat.com>
Copy link
Contributor

@bwplotka bwplotka left a comment

Choose a reason for hiding this comment

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

I think it makes sense, but not fully approving, as it's the first time I see this code. Some suggestions though. Let me know if I need to really really dive into this flow.

wal/wal.go Outdated Show resolved Hide resolved
wal/wal.go Outdated Show resolved Hide resolved
@@ -429,7 +429,6 @@ func (w *WAL) flushPage(clear bool) error {
// No more data will fit into the page. Enqueue and clear it.
if clear {
p.alloc = pageSize // Write till end of page.
w.pageCompletions.Inc()
}
n, err := w.segment.Write(p.buf[p.flushed:p.alloc])
if err != nil {
Copy link
Contributor

Choose a reason for hiding this comment

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

Line 437: What if the clear is true, and we do Write and n is not actually p.alloc? I think we would then drop some bytes, right? Now is the question if the implementation of segment.Write does partial writes in any case (n). Worth to check?

Copy link
Contributor

@bwplotka bwplotka Apr 27, 2019

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think we would then drop some bytes, right?

Not sure what you mean by this. Can you add more details.

n, err := w.segment.Write(p.buf[p.flushed:p.alloc])
	if err != nil {
		return err
	}
	p.flushed += n

When Write returns an error tsdb will exit(leaving the WAL in corrupted state) and will run a repair on the next start up.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ping @bwplotka

Signed-off-by: Krasi Georgiev <kgeorgie@redhat.com>
Copy link
Collaborator

@gouthamve gouthamve left a comment

Choose a reason for hiding this comment

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

LGTM!

@krasi-georgiev
Copy link
Contributor Author

merging as is.
@bwplotka if you still think there is a problem please let me know and I will open another PR.

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

Successfully merging this pull request may close these issues.

Prometheus 2.0.0-beta5 doesn't recover nicely when running out of disk space
3 participants