Skip to content

Commit 86d0231

Browse files
mike-sulricardosalveti
authored andcommitted
base: docker-moby: patch to fsync layer metadata
Fsync `link` and `lower` layer files just after write to make sure their content is stored on a persistent storage. It helps to overcome the issue that occurs when image layers download/extraction is interrupted by a power cut. Docker daemon can recover if the interrupted layer is "broken", but it cannot recover if there are two or more lower to the interrupted layers are "broken". The given fix makes sure that the lower layers that are fully downloaded and extracted are consistent even if the current top layer is broken. Signed-off-by: Mike Sul <[email protected]>
1 parent d2edd3d commit 86d0231

2 files changed

Lines changed: 76 additions & 0 deletions

File tree

meta-lmp-base/recipes-containers/docker/docker-moby.bb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ SRC_URI = "\
5050
file://increase_containerd_timeouts.patch \
5151
file://dockerd-daemon-reload-image-store-on-a-hup-signal.patch \
5252
file://0001-registry-increase-TLS-and-connection-timeouts.patch \
53+
file://0001-overlay2-fsync-layer-metadata-files.patch \
5354
"
5455

5556
require recipes-containers/docker/docker.inc
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
From 14cb4453d05cd2a66efecbd1288bd2c7a7ff19a6 Mon Sep 17 00:00:00 2001
2+
From: Mike Sul <[email protected]>
3+
Date: Mon, 18 Oct 2021 12:19:14 +0300
4+
Subject: [PATCH] overlay2: fsync layer metadata files
5+
6+
Fsync `link` and `lower` layer files just after write to make sure their
7+
content is actually stored on a persistent storage. It helps to overcome
8+
the issue that occurs when image layers download/extraction is
9+
interrupted by a power cut.
10+
Docker daemon can recover if there the interrupted layer is "broken",
11+
but it cannot recover if there are two or more lower to the interrupted
12+
layers are "broken". The given fix makes sure that the lower layers that
13+
are fully downloaded and extracted are consistent even if the current
14+
top layer is broken.
15+
16+
Signed-off-by: Mike Sul <[email protected]>
17+
---
18+
daemon/graphdriver/overlay2/overlay.go | 30 ++++++++++++++++++++++++++
19+
1 file changed, 30 insertions(+)
20+
21+
diff --git a/src/import/daemon/graphdriver/overlay2/overlay.go b/src/import/daemon/graphdriver/overlay2/overlay.go
22+
index 36a921a018..6127f64936 100644
23+
--- a/src/import/daemon/graphdriver/overlay2/overlay.go
24+
+++ b/src/import/daemon/graphdriver/overlay2/overlay.go
25+
@@ -387,6 +387,7 @@ func (d *Driver) create(id, parent string, opts *graphdriver.CreateOpts) (retErr
26+
if err := ioutil.WriteFile(path.Join(dir, "link"), []byte(lid), 0644); err != nil {
27+
return err
28+
}
29+
+ fsync(path.Join(dir, "link"))
30+
31+
// if no parent directory, done
32+
if parent == "" {
33+
@@ -409,6 +410,7 @@ func (d *Driver) create(id, parent string, opts *graphdriver.CreateOpts) (retErr
34+
if err := ioutil.WriteFile(path.Join(dir, lowerFile), []byte(lower), 0666); err != nil {
35+
return err
36+
}
37+
+ fsync(path.Join(dir, lowerFile))
38+
}
39+
40+
return nil
41+
@@ -736,3 +738,31 @@ func (d *Driver) Diff(id, parent string) (io.ReadCloser, error) {
42+
func (d *Driver) Changes(id, parent string) ([]archive.Change, error) {
43+
return d.naiveDiff.Changes(id, parent)
44+
}
45+
+
46+
+
47+
+// Foundries.io patch to fsync changes
48+
+func fsync(path string) {
49+
+ f, err := os.Open(path)
50+
+ if err != nil {
51+
+ logger.Warnf(">>> FIO: failed to open file for fsyncing; file: %s, err: %s", path, err.Error())
52+
+ return
53+
+ }
54+
+ if f == nil {
55+
+ logger.Warnf(">>> FIO: failed to open file for fsyncing; file: %s, err: nil file descriptor", path)
56+
+ return
57+
+ }
58+
+
59+
+ defer func() {
60+
+ err := f.Close()
61+
+ if err != nil {
62+
+ logger.Warnf(">>> FIO: failed to close a file opened for fsyncing; file: %s, err: %s", path, err.Error())
63+
+ }
64+
+ }()
65+
+
66+
+ err = f.Sync()
67+
+ if err == nil {
68+
+ logger.Infof(">>> FIO: fsync %s", path)
69+
+ } else {
70+
+ logger.Infof(">>> FIO: failed to fsync %s, err: %s", path, err.Error())
71+
+ }
72+
+}
73+
--
74+
2.17.1
75+

0 commit comments

Comments
 (0)