diff --git a/store.go b/store.go index fc664bf3ee..c8fa753b34 100644 --- a/store.go +++ b/store.go @@ -572,30 +572,31 @@ type ContainerOptions struct { } type store struct { - lastLoaded time.Time - runRoot string - graphLock Locker - usernsLock Locker - graphRoot string - graphDriverName string - graphOptions []string - pullOptions map[string]string - uidMap []idtools.IDMap - gidMap []idtools.IDMap - autoUsernsUser string - additionalUIDs *idSet // Set by getAvailableIDs() - additionalGIDs *idSet // Set by getAvailableIDs() - autoNsMinSize uint32 - autoNsMaxSize uint32 - graphDriver drivers.Driver - layerStore rwLayerStore - roLayerStores []roLayerStore - imageStore rwImageStore - roImageStores []roImageStore - containerStore rwContainerStore - digestLockRoot string - disableVolatile bool - transientStore bool + lastLoaded time.Time + runRoot string + graphLock Locker + usernsLock Locker + graphRoot string + graphDriverName string + graphOptions []string + pullOptions map[string]string + uidMap []idtools.IDMap + gidMap []idtools.IDMap + autoUsernsUser string + additionalUIDs *idSet // Set by getAvailableIDs() + additionalGIDs *idSet // Set by getAvailableIDs() + autoNsMinSize uint32 + autoNsMaxSize uint32 + graphDriver drivers.Driver + layerStore rwLayerStore + containerLayerStore rwLayerStore // nil unless in transient-store mode + roLayerStores []roLayerStore + imageStore rwImageStore + roImageStores []roImageStore + containerStore rwContainerStore + digestLockRoot string + disableVolatile bool + transientStore bool } // GetStore attempts to find an already-created Store object matching the @@ -866,43 +867,68 @@ func (s *store) GraphDriver() (drivers.Driver, error) { if s.graphLock.TouchedSince(s.lastLoaded) { s.graphDriver = nil s.layerStore = nil + s.containerLayerStore = nil s.lastLoaded = time.Now() } return s.getGraphDriver() } -// getLayerStore obtains and returns a handle to the writeable layer store object -// used by the Store. -func (s *store) getLayerStore() (rwLayerStore, error) { +// getLayerStores obtains and returns a handle to the writeable layer store objects +// used by the Store. There are potentially two stores, the first always exist and +// is used for persistent layers (such as those related to images), and the second +// is transient. If transient mode is not enabled, then the second store is nil +// and the first one should be used. +func (s *store) getLayerStores() (rwLayerStore, rwLayerStore, error) { s.graphLock.Lock() defer s.graphLock.Unlock() if s.graphLock.TouchedSince(s.lastLoaded) { s.graphDriver = nil s.layerStore = nil + s.containerLayerStore = nil s.lastLoaded = time.Now() } if s.layerStore != nil { - return s.layerStore, nil + return s.layerStore, s.containerLayerStore, nil } driver, err := s.getGraphDriver() if err != nil { - return nil, err + return nil, nil, err } + driverPrefix := s.graphDriverName + "-" rlpath := filepath.Join(s.runRoot, driverPrefix+"layers") if err := os.MkdirAll(rlpath, 0700); err != nil { - return nil, err + return nil, nil, err } glpath := filepath.Join(s.graphRoot, driverPrefix+"layers") if err := os.MkdirAll(glpath, 0700); err != nil { - return nil, err + return nil, nil, err } rls, err := s.newLayerStore(rlpath, glpath, driver, false) if err != nil { - return nil, err + return nil, nil, err } + + var crls rwLayerStore + if s.transientStore { + rlpath := filepath.Join(s.runRoot, driverPrefix+"transientlayers") + if err := os.MkdirAll(rlpath, 0700); err != nil { + return nil, nil, err + } + glpath := filepath.Join(s.graphRoot, driverPrefix+"transientlayers") + if err := os.MkdirAll(glpath, 0700); err != nil { + return nil, nil, err + } + crls, err = s.newLayerStore(rlpath, glpath, driver, true) + if err != nil { + return nil, nil, err + } + } + s.layerStore = rls - return s.layerStore, nil + s.containerLayerStore = crls + + return s.layerStore, s.containerLayerStore, nil } // getROLayerStores obtains additional read/only layer store objects used by the @@ -933,10 +959,19 @@ func (s *store) getROLayerStores() ([]roLayerStore, error) { return s.roLayerStores, nil } +// Append but handle nil transient layer store +func appendLayerStores(rlstore rwLayerStore, crlstore rwLayerStore, rostores []roLayerStore) []roLayerStore { + if crlstore != nil { + return append([]roLayerStore{rlstore, crlstore}, rostores...) + } else { + return append([]roLayerStore{rlstore}, rostores...) + } +} + // allLayerStores returns a list of all layer store objects used by the Store. // This is a convenience method for read-only users of the Store. func (s *store) allLayerStores() ([]roLayerStore, error) { - primary, err := s.getLayerStore() + primary, containers, err := s.getLayerStores() if err != nil { return nil, fmt.Errorf("loading primary layer store data: %w", err) } @@ -944,7 +979,7 @@ func (s *store) allLayerStores() ([]roLayerStore, error) { if err != nil { return nil, fmt.Errorf("loading additional layer stores: %w", err) } - return append([]roLayerStore{primary}, additional...), nil + return appendLayerStores(primary, containers, additional), nil } // readAllLayerStores processes allLayerStores() in order: @@ -984,20 +1019,82 @@ func (s *store) readAllLayerStores(fn func(store roLayerStore) (bool, error)) (b return false, nil } -// writeToLayerStore is a helper for working with store.getLayerStore(): -// It locks the store for writing, checks for updates, and calls fn() +// writeToAllLayerStores is a helper for working with store.getLayerStores(): +// It locks both of the rw stores for writing in order, checks for updates +// and calls fn() on both. // It returns the return value of fn, or its own error initializing the store. -func (s *store) writeToLayerStore(fn func(store rwLayerStore) error) error { - store, err := s.getLayerStore() +func (s *store) writeToAllLayerStores(fn func(store rwLayerStore) error) error { + writeToALayerStore := func(store rwLayerStore) error { + if err := store.startWriting(); err != nil { + return err + } + defer store.stopWriting() + return fn(store) + } + + store, containerstore, err := s.getLayerStores() if err != nil { return err } - if err := store.startWriting(); err != nil { + err = writeToALayerStore(store) + if err != nil { return err } - defer store.stopWriting() - return fn(store) + + if containerstore != nil { + err = writeToALayerStore(store) + if err != nil { + return err + } + } + + return nil +} + +// writeToLayerStoreFor is a helper for working with store.getLayerStores(): +// It locks both of the rw stores for writing in order checking for updates, then +// checking that the id exists, and calls fn() on the found one. +// It returns the return value of fn, its own error initializing the store, or ErrLayerUnknown +// if no store had the layer +func (s *store) writeToLayerStoreFor(id string, fn func(store rwLayerStore) error) error { + store, containerstore, err := s.getLayerStores() + if err != nil { + return err + } + + foundLayer := false + + writeToALayerStore := func(store rwLayerStore) error { + if err := store.startWriting(); err != nil { + return err + } + defer store.stopWriting() + + if store.Exists(id) && !foundLayer { + foundLayer = true + return fn(store) + } + return nil + } + + err = writeToALayerStore(store) + if err != nil { + return err + } + + if !foundLayer && containerstore != nil { + err = writeToALayerStore(containerstore) + if err != nil { + return err + } + } + + if !foundLayer { + return ErrLayerUnknown + } + + return nil } // getImageStore obtains and returns a handle to the writable image store object @@ -1114,8 +1211,9 @@ func (s *store) writeToContainerStore(fn func(store rwContainerStore) error) err // writeToAllStores is a convenience helper for writing to all three stores: // It locks the stores for writing, checks for updates, and calls fn(). // It returns the return value of fn, or its own error initializing the stores. -func (s *store) writeToAllStores(fn func(rlstore rwLayerStore, ristore rwImageStore, rcstore rwContainerStore) error) error { - rlstore, err := s.getLayerStore() + +func (s *store) writeToAllStores(fn func(rlstore rwLayerStore, crlstore rwLayerStore, ristore rwImageStore, rcstore rwContainerStore) error) error { + rlstore, crlstore, err := s.getLayerStores() if err != nil { return err } @@ -1132,6 +1230,14 @@ func (s *store) writeToAllStores(fn func(rlstore rwLayerStore, ristore rwImageSt return err } defer rlstore.stopWriting() + + if crlstore != nil { + if err := crlstore.startWriting(); err != nil { + return err + } + defer crlstore.stopWriting() + } + if err := ristore.startWriting(); err != nil { return err } @@ -1141,7 +1247,7 @@ func (s *store) writeToAllStores(fn func(rlstore rwLayerStore, ristore rwImageSt } defer rcstore.stopWriting() - return fn(rlstore, ristore, rcstore) + return fn(rlstore, crlstore, ristore, rcstore) } func (s *store) canUseShifting(uidmap, gidmap []idtools.IDMap) bool { @@ -1159,7 +1265,8 @@ func (s *store) canUseShifting(uidmap, gidmap []idtools.IDMap) bool { func (s *store) PutLayer(id, parent string, names []string, mountLabel string, writeable bool, options *LayerOptions, diff io.Reader) (*Layer, int64, error) { var parentLayer *Layer - rlstore, err := s.getLayerStore() + // We always put layers to the persistent store (rlstore), as container layers are not put + rlstore, crlstore, err := s.getLayerStores() if err != nil { return nil, -1, err } @@ -1192,7 +1299,7 @@ func (s *store) PutLayer(id, parent string, names []string, mountLabel string, w gidMap := options.GIDMap if parent != "" { var ilayer *Layer - for _, l := range append([]roLayerStore{rlstore}, rlstores...) { + for _, l := range appendLayerStores(rlstore, crlstore, rlstores) { lstore := l if lstore != rlstore { if err := lstore.startReading(); err != nil { @@ -1414,7 +1521,7 @@ func (s *store) CreateContainer(id string, names []string, image, layer, metadat if options.HostGIDMapping { options.GIDMap = nil } - rlstore, err := s.getLayerStore() + rlstore, crlstore, err := s.getLayerStores() if err != nil { return nil, err } @@ -1517,10 +1624,14 @@ func (s *store) CreateContainer(id string, names []string, image, layer, metadat } } } else { - if err := rlstore.startWriting(); err != nil { - return nil, err + if crlstore == nil { + // No container layer store, use the regular one + if err := rlstore.startWriting(); err != nil { + return nil, err + } + defer rlstore.stopWriting() } - defer rlstore.stopWriting() + if !options.HostUIDMapping && len(options.UIDMap) == 0 { uidMap = s.uidMap } @@ -1528,6 +1639,16 @@ func (s *store) CreateContainer(id string, names []string, image, layer, metadat gidMap = s.gidMap } } + + if crlstore == nil { + crlstore = rlstore // Started writing above + } else { + if err := crlstore.startWriting(); err != nil { + return nil, err + } + defer crlstore.stopWriting() + } + var layerOptions *LayerOptions if s.canUseShifting(uidMap, gidMap) { layerOptions = &LayerOptions{ @@ -1567,7 +1688,7 @@ func (s *store) CreateContainer(id string, names []string, image, layer, metadat options.Flags[mountLabelFlag] = mountLabel } - clayer, err := rlstore.Create(layer, imageTopLayer, nil, mlabel, options.StorageOpt, layerOptions, true) + clayer, err := crlstore.Create(layer, imageTopLayer, nil, mlabel, options.StorageOpt, layerOptions, true) if err != nil { return nil, err } @@ -1584,7 +1705,7 @@ func (s *store) CreateContainer(id string, names []string, image, layer, metadat var err error container, err = rcstore.Create(id, names, imageID, layer, metadata, options) if err != nil || container == nil { - if err2 := rlstore.Delete(layer); err2 != nil { + if err2 := crlstore.Delete(layer); err2 != nil { if err == nil { err = fmt.Errorf("deleting layer %#v: %w", layer, err2) } else { @@ -1598,10 +1719,13 @@ func (s *store) CreateContainer(id string, names []string, image, layer, metadat } func (s *store) SetMetadata(id, metadata string) error { - return s.writeToAllStores(func(rlstore rwLayerStore, ristore rwImageStore, rcstore rwContainerStore) error { + return s.writeToAllStores(func(rlstore rwLayerStore, crlstore rwLayerStore, ristore rwImageStore, rcstore rwContainerStore) error { if rlstore.Exists(id) { return rlstore.SetMetadata(id, metadata) } + if crlstore != nil && crlstore.Exists(id) { + return crlstore.SetMetadata(id, metadata) + } if ristore.Exists(id) { return ristore.SetMetadata(id, metadata) } @@ -1769,7 +1893,7 @@ func (s *store) LayerBigData(id, key string) (io.ReadCloser, error) { // SetLayerBigData stores a (possibly large) chunk of named data // associated with a layer. func (s *store) SetLayerBigData(id, key string, data io.Reader) error { - return s.writeToLayerStore(func(store rwLayerStore) error { + return s.writeToLayerStoreFor(id, func(store rwLayerStore) error { return store.SetBigData(id, key, data) }) } @@ -2079,14 +2203,9 @@ func (s *store) RemoveNames(id string, names []string) error { func (s *store) updateNames(id string, names []string, op updateNameOperation) error { deduped := dedupeNames(names) - layerFound := false - if err := s.writeToLayerStore(func(rlstore rwLayerStore) error { - if !rlstore.Exists(id) { - return nil - } - layerFound = true + if err := s.writeToLayerStoreFor(id, func(rlstore rwLayerStore) error { return rlstore.updateNames(id, deduped, op) - }); err != nil || layerFound { + }); err != nil && err != ErrLayerUnknown { return err } @@ -2213,12 +2332,33 @@ func (s *store) Lookup(name string) (string, error) { } func (s *store) DeleteLayer(id string) error { - return s.writeToAllStores(func(rlstore rwLayerStore, ristore rwImageStore, rcstore rwContainerStore) error { + return s.writeToAllStores(func(rlstore rwLayerStore, crlstore rwLayerStore, ristore rwImageStore, rcstore rwContainerStore) error { + var lstore rwLayerStore if rlstore.Exists(id) { - if l, err := rlstore.Get(id); err != nil { - id = l.ID + lstore = rlstore + } else if crlstore != nil && crlstore.Exists(id) { + lstore = crlstore + } + if lstore == nil { + return ErrNotALayer + } + + if l, err := lstore.Get(id); err != nil { + id = l.ID + } + + layers, err := rlstore.Layers() + if err != nil { + return err + } + for _, layer := range layers { + if layer.Parent == id { + return fmt.Errorf("used by layer %v: %w", layer.ID, ErrLayerHasChildren) } - layers, err := rlstore.Layers() + } + + if crlstore != nil { + layers, err := crlstore.Layers() if err != nil { return err } @@ -2227,55 +2367,55 @@ func (s *store) DeleteLayer(id string) error { return fmt.Errorf("used by layer %v: %w", layer.ID, ErrLayerHasChildren) } } - images, err := ristore.Images() - if err != nil { - return err - } + } - for _, image := range images { - if image.TopLayer == id { - return fmt.Errorf("layer %v used by image %v: %w", id, image.ID, ErrLayerUsedByImage) - } - if stringutils.InSlice(image.MappedTopLayers, id) { - // No write access to the image store, fail before the layer is deleted - if _, ok := ristore.(*imageStore); !ok { - return fmt.Errorf("layer %v used by image %v: %w", id, image.ID, ErrLayerUsedByImage) - } - } - } - containers, err := rcstore.Containers() - if err != nil { - return err + images, err := ristore.Images() + if err != nil { + return err + } + + for _, image := range images { + if image.TopLayer == id { + return fmt.Errorf("layer %v used by image %v: %w", id, image.ID, ErrLayerUsedByImage) } - for _, container := range containers { - if container.LayerID == id { - return fmt.Errorf("layer %v used by container %v: %w", id, container.ID, ErrLayerUsedByContainer) + if stringutils.InSlice(image.MappedTopLayers, id) { + // No write access to the image store, fail before the layer is deleted + if _, ok := ristore.(*imageStore); !ok { + return fmt.Errorf("layer %v used by image %v: %w", id, image.ID, ErrLayerUsedByImage) } } - if err := rlstore.Delete(id); err != nil { - return fmt.Errorf("delete layer %v: %w", id, err) + } + containers, err := rcstore.Containers() + if err != nil { + return err + } + for _, container := range containers { + if container.LayerID == id { + return fmt.Errorf("layer %v used by container %v: %w", id, container.ID, ErrLayerUsedByContainer) } + } + if err := lstore.Delete(id); err != nil { + return fmt.Errorf("delete layer %v: %w", id, err) + } - // The check here is used to avoid iterating the images if we don't need to. - // There is already a check above for the imageStore to be writeable when the layer is part of MappedTopLayers. - if istore, ok := ristore.(*imageStore); ok { - for _, image := range images { - if stringutils.InSlice(image.MappedTopLayers, id) { - if err = istore.removeMappedTopLayer(image.ID, id); err != nil { - return fmt.Errorf("remove mapped top layer %v from image %v: %w", id, image.ID, err) - } + // The check here is used to avoid iterating the images if we don't need to. + // There is already a check above for the imageStore to be writeable when the layer is part of MappedTopLayers. + if istore, ok := ristore.(*imageStore); ok { + for _, image := range images { + if stringutils.InSlice(image.MappedTopLayers, id) { + if err = istore.removeMappedTopLayer(image.ID, id); err != nil { + return fmt.Errorf("remove mapped top layer %v from image %v: %w", id, image.ID, err) } } } - return nil } - return ErrNotALayer + return nil }) } func (s *store) DeleteImage(id string, commit bool) (layers []string, err error) { layersToRemove := []string{} - if err := s.writeToAllStores(func(rlstore rwLayerStore, ristore rwImageStore, rcstore rwContainerStore) error { + if err := s.writeToAllStores(func(rlstore rwLayerStore, crlstore rwLayerStore, ristore rwImageStore, rcstore rwContainerStore) error { if ristore.Exists(id) { image, err := ristore.Get(id) if err != nil { @@ -2305,6 +2445,15 @@ func (s *store) DeleteImage(id string, commit bool) (layers []string, err error) for _, layer := range layers { childrenByParent[layer.Parent] = append(childrenByParent[layer.Parent], layer.ID) } + if crlstore != nil { + layers, err := crlstore.Layers() + if err != nil { + return err + } + for _, layer := range layers { + childrenByParent[layer.Parent] = append(childrenByParent[layer.Parent], layer.ID) + } + } otherImagesTopLayers := make(map[string]struct{}) for _, img := range images { if img.ID != id { @@ -2336,6 +2485,12 @@ func (s *store) DeleteImage(id string, commit bool) (layers []string, err error) if l, err := rlstore.Get(layer); err == nil { parent = l.Parent } + if crlstore != nil { + if l, err := crlstore.Get(layer); err == nil { + parent = l.Parent + } + } + hasChildrenNotBeingRemoved := func() bool { layersToCheck := []string{layer} if layer == image.TopLayer { @@ -2365,9 +2520,14 @@ func (s *store) DeleteImage(id string, commit bool) (layers []string, err error) } if commit { for _, layer := range layersToRemove { - if err = rlstore.Delete(layer); err != nil { + if err = rlstore.Delete(layer); err != nil && err != ErrLayerUnknown { return err } + if crlstore != nil { + if err = crlstore.Delete(layer); err != nil && err != ErrLayerUnknown { + return err + } + } } } return nil @@ -2378,7 +2538,7 @@ func (s *store) DeleteImage(id string, commit bool) (layers []string, err error) } func (s *store) DeleteContainer(id string) error { - return s.writeToAllStores(func(rlstore rwLayerStore, ristore rwImageStore, rcstore rwContainerStore) error { + return s.writeToAllStores(func(rlstore rwLayerStore, crlstore rwLayerStore, ristore rwImageStore, rcstore rwContainerStore) error { if !rcstore.Exists(id) { return ErrNotAContainer } @@ -2398,6 +2558,13 @@ func (s *store) DeleteContainer(id string) error { wg.Done() }() } + if crlstore != nil && crlstore.Exists(container.LayerID) { + wg.Add(1) + go func() { + errChan <- crlstore.Delete(container.LayerID) + wg.Done() + }() + } wg.Add(1) go func() { errChan <- rcstore.Delete(id) @@ -2449,7 +2616,7 @@ func (s *store) DeleteContainer(id string) error { } func (s *store) Delete(id string) error { - return s.writeToAllStores(func(rlstore rwLayerStore, ristore rwImageStore, rcstore rwContainerStore) error { + return s.writeToAllStores(func(rlstore rwLayerStore, crlstore rwLayerStore, ristore rwImageStore, rcstore rwContainerStore) error { if rcstore.Exists(id) { if container, err := rcstore.Get(id); err == nil { if rlstore.Exists(container.LayerID) { @@ -2479,24 +2646,35 @@ func (s *store) Delete(id string) error { if rlstore.Exists(id) { return rlstore.Delete(id) } + if crlstore != nil && crlstore.Exists(id) { + return crlstore.Delete(id) + } return ErrLayerUnknown }) } func (s *store) Wipe() error { - return s.writeToAllStores(func(rlstore rwLayerStore, ristore rwImageStore, rcstore rwContainerStore) error { + return s.writeToAllStores(func(rlstore rwLayerStore, crlstore rwLayerStore, ristore rwImageStore, rcstore rwContainerStore) error { if err := rcstore.Wipe(); err != nil { return err } if err := ristore.Wipe(); err != nil { return err } - return rlstore.Wipe() + if err := rlstore.Wipe(); err != nil { + return err + } + if crlstore != nil { + if err := crlstore.Wipe(); err != nil { + return err + } + } + return nil }) } func (s *store) Status() ([][2]string, error) { - rlstore, err := s.getLayerStore() + rlstore, _, err := s.getLayerStores() if err != nil { return nil, err } @@ -2508,18 +2686,26 @@ func (s *store) Version() ([][2]string, error) { } func (s *store) mount(id string, options drivers.MountOpts) (string, error) { - rlstore, err := s.getLayerStore() + rlstore, crlstore, err := s.getLayerStores() if err != nil { return "", err } s.graphLock.Lock() defer s.graphLock.Unlock() + if err := rlstore.startWriting(); err != nil { return "", err } defer rlstore.stopWriting() + if crlstore != nil { + if err := crlstore.startWriting(); err != nil { + return "", err + } + defer crlstore.stopWriting() + } + modified, err := s.graphLock.Modified() if err != nil { return "", err @@ -2529,6 +2715,7 @@ func (s *store) mount(id string, options drivers.MountOpts) (string, error) { if modified { s.graphDriver = nil s.layerStore = nil + s.containerLayerStore = nil s.graphDriver, err = s.getGraphDriver() if err != nil { return "", err @@ -2543,6 +2730,9 @@ func (s *store) mount(id string, options drivers.MountOpts) (string, error) { if rlstore.Exists(id) { return rlstore.Mount(id, options) } + if crlstore != nil && crlstore.Exists(id) { + return crlstore.Mount(id, options) + } return "", ErrLayerUnknown } @@ -2590,7 +2780,7 @@ func (s *store) Mounted(id string) (int, error) { if layerID, err := s.ContainerLayerID(id); err == nil { id = layerID } - rlstore, err := s.getLayerStore() + rlstore, crlstore, err := s.getLayerStores() if err != nil { return 0, err } @@ -2599,7 +2789,22 @@ func (s *store) Mounted(id string) (int, error) { } defer rlstore.stopReading() - return rlstore.Mounted(id) + count, err := rlstore.Mounted(id) + if err == nil || err != ErrLayerUnknown { + return count, err + } + + if crlstore != nil { + if err := crlstore.startReading(); err != nil { + return 0, err + } + defer crlstore.stopReading() + + return crlstore.Mounted(id) + } + + return 0, ErrLayerUnknown + } func (s *store) UnmountImage(id string, force bool) (bool, error) { @@ -2615,14 +2820,12 @@ func (s *store) Unmount(id string, force bool) (bool, error) { id = layerID } var res bool - err := s.writeToLayerStore(func(rlstore rwLayerStore) error { - if rlstore.Exists(id) { - var err error - res, err = rlstore.Unmount(id, force) - return err - } - return ErrLayerUnknown + err := s.writeToLayerStoreFor(id, func(rlstore rwLayerStore) error { + var err error + res, err = rlstore.Unmount(id, force) + return err }) + return res, err } @@ -2676,6 +2879,7 @@ func (s *store) Diff(from, to string, options *DiffOptions) (io.ReadCloser, erro if modified { s.graphDriver = nil s.layerStore = nil + s.containerLayerStore = nil s.graphDriver, err = s.getGraphDriver() if err != nil { return nil, err @@ -2707,55 +2911,53 @@ func (s *store) Diff(from, to string, options *DiffOptions) (io.ReadCloser, erro } func (s *store) ApplyDiffFromStagingDirectory(to, stagingDirectory string, diffOutput *drivers.DriverWithDifferOutput, options *drivers.ApplyDiffOpts) error { - return s.writeToLayerStore(func(rlstore rwLayerStore) error { - if !rlstore.Exists(to) { - return ErrLayerUnknown - } + return s.writeToLayerStoreFor(to, func(rlstore rwLayerStore) error { return rlstore.ApplyDiffFromStagingDirectory(to, stagingDirectory, diffOutput, options) }) } func (s *store) CleanupStagingDirectory(stagingDirectory string) error { - return s.writeToLayerStore(func(rlstore rwLayerStore) error { + return s.writeToAllLayerStores(func(rlstore rwLayerStore) error { return rlstore.CleanupStagingDirectory(stagingDirectory) }) } func (s *store) ApplyDiffWithDiffer(to string, options *drivers.ApplyDiffOpts, differ drivers.Differ) (*drivers.DriverWithDifferOutput, error) { var res *drivers.DriverWithDifferOutput - err := s.writeToLayerStore(func(rlstore rwLayerStore) error { - if to != "" && !rlstore.Exists(to) { - return ErrLayerUnknown + found := false + err := s.writeToAllLayerStores(func(rlstore rwLayerStore) error { + // We check found here, so that if to == "" we only write to the first store + if (to == "" || rlstore.Exists(to)) && !found { + found = true + var err error + res, err = rlstore.ApplyDiffWithDiffer(to, options, differ) + return err } - var err error - res, err = rlstore.ApplyDiffWithDiffer(to, options, differ) - return err + return nil }) + + if !found { + return nil, ErrLayerUnknown + } return res, err } func (s *store) DifferTarget(id string) (string, error) { var res string - err := s.writeToLayerStore(func(rlstore rwLayerStore) error { - if rlstore.Exists(id) { - var err error - res, err = rlstore.DifferTarget(id) - return err - } - return ErrLayerUnknown + err := s.writeToLayerStoreFor(id, func(rlstore rwLayerStore) error { + var err error + res, err = rlstore.DifferTarget(id) + return err }) return res, err } func (s *store) ApplyDiff(to string, diff io.Reader) (int64, error) { var res int64 = -1 - err := s.writeToLayerStore(func(rlstore rwLayerStore) error { - if rlstore.Exists(to) { - var err error - res, err = rlstore.ApplyDiff(to, diff) - return err - } - return ErrLayerUnknown + err := s.writeToLayerStoreFor(to, func(rlstore rwLayerStore) error { + var err error + res, err = rlstore.ApplyDiff(to, diff) + return err }) return res, err } @@ -2811,7 +3013,7 @@ func (s *store) LayerSize(id string) (int64, error) { } func (s *store) LayerParentOwners(id string) ([]int, []int, error) { - rlstore, err := s.getLayerStore() + rlstore, crlstore, err := s.getLayerStores() if err != nil { return nil, nil, err } @@ -2822,11 +3024,22 @@ func (s *store) LayerParentOwners(id string) ([]int, []int, error) { if rlstore.Exists(id) { return rlstore.ParentOwners(id) } + + if crlstore != nil { + if err := crlstore.startReading(); err != nil { + return nil, nil, err + } + defer crlstore.stopReading() + if crlstore.Exists(id) { + return crlstore.ParentOwners(id) + } + } + return nil, nil, ErrLayerUnknown } func (s *store) ContainerParentOwners(id string) ([]int, []int, error) { - rlstore, err := s.getLayerStore() + rlstore, crlstore, err := s.getLayerStores() if err != nil { return nil, nil, err } @@ -2849,6 +3062,17 @@ func (s *store) ContainerParentOwners(id string) ([]int, []int, error) { if rlstore.Exists(container.LayerID) { return rlstore.ParentOwners(container.LayerID) } + + if crlstore != nil { + if err := crlstore.startReading(); err != nil { + return nil, nil, err + } + defer crlstore.stopReading() + if crlstore.Exists(container.LayerID) { + return crlstore.ParentOwners(container.LayerID) + } + } + return nil, nil, ErrLayerUnknown } @@ -2951,7 +3175,7 @@ func (al *additionalLayer) CompressedSize() int64 { } func (al *additionalLayer) PutAs(id, parent string, names []string) (*Layer, error) { - rlstore, err := al.s.getLayerStore() + rlstore, _, err := al.s.getLayerStores() if err != nil { return nil, err } @@ -3190,7 +3414,7 @@ func (s *store) FromContainerRunDirectory(id, file string) ([]byte, error) { func (s *store) Shutdown(force bool) ([]string, error) { mounted := []string{} - rlstore, err := s.getLayerStore() + rlstore, crlstore, err := s.getLayerStores() if err != nil { return mounted, err } @@ -3203,30 +3427,47 @@ func (s *store) Shutdown(force bool) ([]string, error) { } defer rlstore.stopWriting() - layers, err := rlstore.Layers() - if err != nil { - return mounted, err - } - for _, layer := range layers { - if layer.MountCount == 0 { - continue + unmountLayers := func(lstore rwLayerStore) error { + layers, err := lstore.Layers() + if err != nil { + return err } - mounted = append(mounted, layer.ID) - if force { - for layer.MountCount > 0 { - _, err2 := rlstore.Unmount(layer.ID, force) - if err2 != nil { - if err == nil { - err = err2 + for _, layer := range layers { + if layer.MountCount == 0 { + continue + } + mounted = append(mounted, layer.ID) + if force { + for layer.MountCount > 0 { + _, err2 := lstore.Unmount(layer.ID, force) + if err2 != nil { + if err == nil { + err = err2 + } + break } - break } } } + return nil + } + + err = unmountLayers(rlstore) + if err != nil { + return mounted, err + } + + if crlstore != nil { + err = unmountLayers(crlstore) + if err != nil { + return mounted, err + } } + if len(mounted) > 0 && err == nil { err = fmt.Errorf("a layer is mounted: %w", ErrLayerUsedByContainer) } + if err == nil { err = s.graphDriver.Cleanup() if err2 := s.graphLock.Touch(); err2 != nil {