Skip to content

Commit

Permalink
store: get exclusive access to store with Diff/Changes
Browse files Browse the repository at this point in the history
when NaiveDiff is used, the Diff/Changes operations can trigger the
mount of the layer.  Prevent that multiple processes step on each
other and one of them performs an unmount while the other one is still
accessing the mount.

Closes: containers#2033

Signed-off-by: Giuseppe Scrivano <[email protected]>
  • Loading branch information
giuseppe committed Jul 17, 2024
1 parent 82ac2b8 commit d6e52a8
Showing 1 changed file with 56 additions and 22 deletions.
78 changes: 56 additions & 22 deletions store.go
Original file line number Diff line number Diff line change
Expand Up @@ -2930,15 +2930,40 @@ func (s *store) Unmount(id string, force bool) (bool, error) {
}

func (s *store) Changes(from, to string) ([]archive.Change, error) {
if res, done, err := readAllLayerStores(s, func(store roLayerStore) ([]archive.Change, bool, error) {
if store.Exists(to) {
res, err := store.Changes(from, to)
return res, true, err
}
return nil, false, nil
}); done {
// NaiveDiff could cause mounts to happen without a lock, so be safe
// and treat the .Diff operation as a Mount.
// We need to make sure the home mount is present when the Mount is done, which happens by possibly reinitializing the graph driver
// in startUsingGraphDriver().
if err := s.startUsingGraphDriver(); err != nil {
return nil, err
}
defer s.stopUsingGraphDriver()

rlstore, lstores, err := s.bothLayerStoreKindsLocked()
if err != nil {
return nil, err
}
if err := rlstore.startWriting(); err != nil {
return nil, err
}
if rlstore.Exists(to) {
res, err := rlstore.Changes(from, to)
rlstore.stopWriting()
return res, err
}
rlstore.stopWriting()

for _, s := range lstores {
store := s
if err := store.startReading(); err != nil {
return nil, err
}
exists := store.Exists(to)
store.stopReading()
if exists {
return nil, fmt.Errorf("mounting read/only store images is not allowed: %w", ErrLayerUnknown)
}
}
return nil, ErrLayerUnknown
}

Expand Down Expand Up @@ -2968,30 +2993,39 @@ func (s *store) Diff(from, to string, options *DiffOptions) (io.ReadCloser, erro
}
defer s.stopUsingGraphDriver()

layerStores, err := s.allLayerStoresLocked()
rlstore, lstores, err := s.bothLayerStoreKindsLocked()
if err != nil {
return nil, err
}

for _, s := range layerStores {
if err := rlstore.startWriting(); err != nil {
return nil, err
}
if rlstore.Exists(to) {
rc, err := rlstore.Diff(from, to, options)
if rc != nil && err == nil {
wrapped := ioutils.NewReadCloserWrapper(rc, func() error {
err := rc.Close()
rlstore.stopWriting()
return err
})
return wrapped, nil
}
rlstore.stopWriting()
return rc, err
}
rlstore.stopWriting()

for _, s := range lstores {
store := s
if err := store.startReading(); err != nil {
return nil, err
}
if store.Exists(to) {
rc, err := store.Diff(from, to, options)
if rc != nil && err == nil {
wrapped := ioutils.NewReadCloserWrapper(rc, func() error {
err := rc.Close()
store.stopReading()
return err
})
return wrapped, nil
}
store.stopReading()
return rc, err
}
exists := store.Exists(to)
store.stopReading()
if exists {
return nil, fmt.Errorf("mounting read/only store images is not allowed: %w", ErrLayerUnknown)
}
}
return nil, ErrLayerUnknown
}
Expand Down

0 comments on commit d6e52a8

Please sign in to comment.