summaryrefslogtreecommitdiff
path: root/libpod
diff options
context:
space:
mode:
Diffstat (limited to 'libpod')
-rw-r--r--libpod/config/config.go19
-rw-r--r--libpod/container_internal.go5
-rw-r--r--libpod/image/image.go130
3 files changed, 59 insertions, 95 deletions
diff --git a/libpod/config/config.go b/libpod/config/config.go
index 5b4b57f3a..f1fa70fbc 100644
--- a/libpod/config/config.go
+++ b/libpod/config/config.go
@@ -469,6 +469,9 @@ func NewConfig(userConfigPath string) (*Config, error) {
if defaultConfig, err := defaultConfigFromMemory(); err != nil {
return nil, errors.Wrapf(err, "error generating default config from memory")
} else {
+ // Check if we need to switch to cgroupfs and logger=file on rootless.
+ defaultConfig.checkCgroupsAndLogger()
+
if err := config.mergeConfig(defaultConfig); err != nil {
return nil, errors.Wrapf(err, "error merging default config from memory")
}
@@ -487,9 +490,6 @@ func NewConfig(userConfigPath string) (*Config, error) {
return nil, errors.Wrapf(define.ErrInvalidArg, "volume path must be an absolute path - instead got %q", config.VolumePath)
}
- // Check if we need to switch to cgroupfs on rootless.
- config.checkCgroupsAndAdjustConfig()
-
return config, nil
}
@@ -524,11 +524,13 @@ func systemConfigs() ([]string, error) {
return configs, nil
}
-// checkCgroupsAndAdjustConfig checks if we're running rootless with the systemd
+// checkCgroupsAndLogger checks if we're running rootless with the systemd
// cgroup manager. In case the user session isn't available, we're switching the
-// cgroup manager to cgroupfs. Note, this only applies to rootless.
-func (c *Config) checkCgroupsAndAdjustConfig() {
- if !rootless.IsRootless() || c.CgroupManager != define.SystemdCgroupsManager {
+// cgroup manager to cgroupfs and the events logger backend to 'file'.
+// Note, this only applies to rootless.
+func (c *Config) checkCgroupsAndLogger() {
+ if !rootless.IsRootless() || (c.CgroupManager !=
+ define.SystemdCgroupsManager && c.EventsLogger == "file") {
return
}
@@ -543,7 +545,8 @@ func (c *Config) checkCgroupsAndAdjustConfig() {
logrus.Warningf("The cgroups manager is set to systemd but there is no systemd user session available")
logrus.Warningf("For using systemd, you may need to login using an user session")
logrus.Warningf("Alternatively, you can enable lingering with: `loginctl enable-linger %d` (possibly as root)", rootless.GetRootlessUID())
- logrus.Warningf("Falling back to --cgroup-manager=cgroupfs")
+ logrus.Warningf("Falling back to --cgroup-manager=cgroupfs and --events-backend=file")
c.CgroupManager = define.CgroupfsCgroupsManager
+ c.EventsLogger = "file"
}
}
diff --git a/libpod/container_internal.go b/libpod/container_internal.go
index 028d7601d..4ff1913b5 100644
--- a/libpod/container_internal.go
+++ b/libpod/container_internal.go
@@ -652,6 +652,11 @@ func (c *Container) removeConmonFiles() error {
return errors.Wrapf(err, "error removing container %s ctl file", c.ID())
}
+ winszFile := filepath.Join(c.bundlePath(), "winsz")
+ if err := os.Remove(winszFile); err != nil && !os.IsNotExist(err) {
+ return errors.Wrapf(err, "error removing container %s winsz file", c.ID())
+ }
+
oomFile := filepath.Join(c.bundlePath(), "oom")
if err := os.Remove(oomFile); err != nil && !os.IsNotExist(err) {
return errors.Wrapf(err, "error removing container %s OOM file", c.ID())
diff --git a/libpod/image/image.go b/libpod/image/image.go
index c912ac2ca..75ac85311 100644
--- a/libpod/image/image.go
+++ b/libpod/image/image.go
@@ -765,109 +765,65 @@ func (i *Image) History(ctx context.Context) ([]*History, error) {
return nil, err
}
- // Use our layers list to find images that use any of them (or no
- // layer, since every base layer is derived from an empty layer) as its
- // topmost layer.
- interestingLayers := make(map[string]bool)
- var layer *storage.Layer
- if i.TopLayer() != "" {
- if layer, err = i.imageruntime.store.Layer(i.TopLayer()); err != nil {
- return nil, err
- }
+ // Build a mapping from top-layer to image ID.
+ images, err := i.imageruntime.GetImages()
+ if err != nil {
+ return nil, err
}
- interestingLayers[""] = true
- for layer != nil {
- interestingLayers[layer.ID] = true
- if layer.Parent == "" {
- break
+ topLayerMap := make(map[string]string)
+ for _, image := range images {
+ if _, exists := topLayerMap[image.TopLayer()]; !exists {
+ topLayerMap[image.TopLayer()] = image.ID()
}
- layer, err = i.imageruntime.store.Layer(layer.Parent)
+ }
+
+ var allHistory []*History
+ var layer *storage.Layer
+
+ // Check if we have an actual top layer to prevent lookup errors.
+ if i.TopLayer() != "" {
+ layer, err = i.imageruntime.store.Layer(i.TopLayer())
if err != nil {
return nil, err
}
}
- // Get the IDs of the images that share some of our layers. Hopefully
- // this step means that we'll be able to avoid reading the
- // configuration of every single image in local storage later on.
- images, err := i.imageruntime.GetImages()
- if err != nil {
- return nil, errors.Wrapf(err, "error getting images from store")
- }
- interestingImages := make([]*Image, 0, len(images))
- for i := range images {
- if interestingLayers[images[i].TopLayer()] {
- interestingImages = append(interestingImages, images[i])
- }
- }
+ // Iterate in reverse order over the history entries, and lookup the
+ // corresponding image ID, size and get the next later if needed.
+ numHistories := len(oci.History) - 1
+ for x := numHistories; x >= 0; x-- {
+ var size int64
- // Build a list of image IDs that correspond to our history entries.
- historyImages := make([]*Image, len(oci.History))
- if len(oci.History) > 0 {
- // The starting image shares its whole history with itself.
- historyImages[len(historyImages)-1] = i
- for i := range interestingImages {
- image, err := images[i].ociv1Image(ctx)
- if err != nil {
- return nil, errors.Wrapf(err, "error getting image configuration for image %q", images[i].ID())
+ id := "<missing>"
+ if x == numHistories {
+ id = i.ID()
+ } else if layer != nil {
+ if !oci.History[x].EmptyLayer {
+ size = layer.UncompressedSize
}
- // If the candidate has a longer history or no history
- // at all, then it doesn't share the portion of our
- // history that we're interested in matching with other
- // images.
- if len(image.History) == 0 || len(image.History) > len(historyImages) {
- continue
- }
- // If we don't include all of the layers that the
- // candidate image does (i.e., our rootfs didn't look
- // like its rootfs at any point), then it can't be part
- // of our history.
- if len(image.RootFS.DiffIDs) > len(oci.RootFS.DiffIDs) {
- continue
- }
- candidateLayersAreUsed := true
- for i := range image.RootFS.DiffIDs {
- if image.RootFS.DiffIDs[i] != oci.RootFS.DiffIDs[i] {
- candidateLayersAreUsed = false
- break
- }
- }
- if !candidateLayersAreUsed {
- continue
- }
- // If the candidate's entire history is an initial
- // portion of our history, then we're based on it,
- // either directly or indirectly.
- sharedHistory := historiesMatch(oci.History, image.History)
- if sharedHistory == len(image.History) {
- historyImages[sharedHistory-1] = images[i]
+ if imageID, exists := topLayerMap[layer.ID]; exists {
+ id = imageID
+ // Delete the entry to avoid reusing it for following history items.
+ delete(topLayerMap, layer.ID)
}
}
- }
- var (
- size int64
- sizeCount = 1
- allHistory []*History
- )
-
- for i := len(oci.History) - 1; i >= 0; i-- {
- imageID := "<missing>"
- if historyImages[i] != nil {
- imageID = historyImages[i].ID()
- }
- if !oci.History[i].EmptyLayer {
- size = img.LayerInfos()[len(img.LayerInfos())-sizeCount].Size
- sizeCount++
- }
allHistory = append(allHistory, &History{
- ID: imageID,
- Created: oci.History[i].Created,
- CreatedBy: oci.History[i].CreatedBy,
+ ID: id,
+ Created: oci.History[x].Created,
+ CreatedBy: oci.History[x].CreatedBy,
Size: size,
- Comment: oci.History[i].Comment,
+ Comment: oci.History[x].Comment,
})
+
+ if layer != nil && layer.Parent != "" && !oci.History[x].EmptyLayer {
+ layer, err = i.imageruntime.store.Layer(layer.Parent)
+ if err != nil {
+ return nil, err
+ }
+ }
}
+
return allHistory, nil
}