Commit Graph

53 Commits

Author SHA1 Message Date
Miloslav Trmač a02dbdbfa1 Only touch lock files after successful JSON writes
AtomicWriteFile truly is atomic, it only changes the file
on success. So there's no point notifying other processes about
a changed file if we failed, they are going to see the same JSON data.

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2022-10-01 02:46:52 +02:00
Miloslav Trmač d1de06c839 Be explicit about how we ignore errors using trucindex.TruncIndex
This does not change behavior, it just makes it clearer
what is going on.

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2022-10-01 02:46:52 +02:00
Daniel J Walsh c9c7d28334
Fix accessing containers and image locks
Match containers and image lock to the new layer lock method.
in https://github.com/containers/storage/pull/1351

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2022-09-28 05:45:56 -04:00
Miloslav Trmač 4b28197720 Use os.ReadFile instead of ioutil.ReadFile
Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2022-09-12 16:30:43 +02:00
Nalin Dahyabhai 47c94cab85 Image.recomputeDigests(): don't call digest.Validate() twice
Don't call Validate() on a digest a second time if it returns an error
the first time, when it's easy to just remember the error it returned
the first time.

Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2022-07-25 10:56:24 -04:00
Daniel J Walsh 3f8c0dc0de
Wrap errors properly with fmt.Errorf
Also returned errors should not begine with a capatalized errors.

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2022-07-12 13:26:10 -04:00
Sascha Grunert 3455d12729
Switch to golang native error wrapping
We now use the golang error wrapping format specifier `%w` instead of the
deprecated github.com/pkg/errors package.

Signed-off-by: Sascha Grunert <sgrunert@redhat.com>
2022-07-07 13:22:46 +02:00
Aditya R 4c37491c64
store: add independent AddNames and RemoveNames for images,layers,containers
Adds AddNames and RemoveNames so operations which are invoked in parallel
manner can use it without destroying names from storage.

For instance

We are deleting names which were already written in store.
This creates faulty behavior when builds are invoked in parallel manner, as
this removes names for other builds.

To fix this behavior we must append to already written names and
override if needed. But this should be optional and not break public API

Following patch will be used by parallel operations at podman or buildah end, directly or indirectly.

Signed-off-by: Aditya R <arajan@redhat.com>
2022-03-01 01:33:35 +05:30
Miloslav Trmač 281a1c57b2 Fix an ignored error return value.
The "if err == nil" is always true, because
there are no prior assignments to err; but it
creates a new scope, making the "err = r.Save()"
call write to an ignored variable.

Remove the unnecessary condition to avoid that.

(Note that the code still continues on after a failure
to save, i.e. it returns a reference to a created in-memory-only
container along with the error value.)

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2022-02-22 19:39:11 +01:00
Giuseppe Scrivano abb54202ce
store: ReloadIfChanged propagates errors from Modified()
Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
2021-05-27 14:55:42 +02:00
Giuseppe Scrivano 0f5231b7bb
store: new method ROFileBasedStore.ReloadIfChanged()
add a new method to reload the store information from the hard disk if
has changed.

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
2021-05-13 09:05:42 +02:00
Nalin Dahyabhai 5ef1e9d68b Use json-iterator instead of encoding/json
Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2021-05-06 12:24:24 -04:00
Giuseppe Scrivano a8da4fdb58
store: support mapped layers deletion
currently it is not possible to delete a mapped layer as it is always
referenced by the image.

Change it allow deleting the mapping if it is not used by any
container or other layers.

It will be useful in CRI-O as a lot of thrown away containers will be
created and the mapped images would keep growing without a way of
cleaning them up.

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
2020-08-05 13:33:43 +02:00
Sascha Grunert fd72b45a3f
Enable golint linter and fix lints
Signed-off-by: Sascha Grunert <sgrunert@suse.com>
2020-01-28 15:59:15 +01:00
Sascha Grunert ecb04cf484
Add names-history support
This commit adds a new `NamesHistory` field to the `images.json`, which
is basically a deduped list of names the image had in the past. The
first entry of the list is the latest history entry.

The main use case for this feature is to tell the end-user which
names/tags an image had in the past if it does not contain any `names`
any more.

Detailed use case:
1. Pulling `image:v1` into the local registry: `names: [ "image:v1" ]`
2. Pushing a new image as `image:v1` into the remote registry
3. Pulling `image:v1` again into the local registry:
    - first image: `names: [ "image:v1" ]`
    - previous v1 image: `names: [], names-history: [ "image:v1" ]`
4. An consumer of the storage API can now process the image name and
   still display `image` as REPOSITORY, like:
   * Before:
   ```
   > podman images
   REPOSITORY      TAG      IMAGE ID       CREATED          SIZE
   image           v1       25b62d1b654a   13 seconds ago   2.07 kB
   <none>          <none>   b134eff7b955   17 seconds ago   2.07 kB
   ```
   * After:
   ```
   > podman images
   REPOSITORY      TAG      IMAGE ID       CREATED          SIZE
   image           v1       25b62d1b654a   13 seconds ago   2.07 kB
   image           <none>   b134eff7b955   17 seconds ago   2.07 kB
   ```
5. Since the `NamesHistory` is a slice we would be able to tell the
   end-user which names an image ID had before.

The change should be backwards compatible with previous versions of
containers/storage.

Signed-off-by: Sascha Grunert <sgrunert@suse.com>
2019-11-11 10:21:14 +01:00
Valentin Rothberg a427596d18 wrap ID or digest to ErrImageUnkown errors
Wrap the ID or the digest to ErrImageUnknown errors to avoid ambiguity
which image is unknown.  Consumers of the storage library may have
multiple subsequent calls to the storage API where it can be unclear
which image is unknown.  Wrapping the ID and digest attempts to avoid
this ambiguity.

Related-to:    github.com/containers/libpod/issues/2979
Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
2019-09-11 10:03:08 +02:00
Nalin Dahyabhai 47335895e5 locking: take read locks on read-only stores
Use RLock() to lock stores that we know are read-only, and panic in
Lock() if we know that we're not a read-write lock.

Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2019-07-02 11:14:03 -04:00
Nalin Dahyabhai d60a53b30b
Merge pull request #347 from vrothberg/recursive-locks
lockfile: add RecursiveLock() API
2019-05-31 10:10:21 -04:00
Valentin Rothberg 237602b4b8 lockfile: add RecursiveLock() API
Add a RecursiveLock() API to allow for recursive acquisitions of a
writer lock within the same process space.  This is yet another
requirement for the copy-detection mechanism in containers/image where
multiple goroutines can be pulling the same blob.  Having a recursive
lock avoids a complex synchronization mechanism as the commit order is
determinted by the corresponding index in the image.

Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
2019-05-22 17:05:38 +02:00
Nalin Dahyabhai 31e71c482e Let consumers know when Layers and Images came from read-only stores
Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2019-05-16 17:24:27 -04:00
Nalin Dahyabhai b41a2a8b83 Drop our dependency on github.com/containers/image
Drop our dependency on the image library's manifest package by requiring
that callers pass its Digest() function to us as a callback.  This makes
our CLI test/diagnostic tool calculate digests of s1 manifests
incorrectly, but that's not something that we were testing.

Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2019-03-06 15:06:34 -05:00
Nalin Dahyabhai 29cfb6e219 imageStore: remove compatibity hacks for adding digests
Remove compatibility hacks for older versions which didn't track size or
digest information for big data items, hopefully without any impact.

Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2019-03-06 15:03:26 -05:00
Nalin Dahyabhai 1194eb9848 layers/images: don't try to clean up with just a read-only lock
Don't attempt to remove conflicting names or finish layer cleanups if we
only have a read-only lock on layer or image stores, since doing either
means we'd have to modify the list of layers or images, and our lock
that we've obtained doesn't allow us to do that.

Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2019-02-26 14:19:53 -05:00
Nalin Dahyabhai 45b0aa27aa Locker.Locked(): clarify that we're checking for write locks
Clarify that Locker.Locked() checks if we have a write lock, since
that's what we care about whenever we check it.

Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2019-02-26 14:19:50 -05:00
Valentin Rothberg f58686dcce lockfile: implement reader-writer locks
Implement reader-writer locks to allow allow multiple readers to hold
the lock in parallel.

* The locks are still based on fcntl(2).

* Changing the lock from a reader to a writer and vice versa will block
  on the syscall.

* A writer lock can be held only by one process.  To protect against
  concurrent accesses by gourtines within the same process space, use a
  writer mutex.

* Extend the Locker interface with the `RLock()` method to acquire a
  reader lock.  If the lock is set to be read-only, all calls to
  `Lock()` will be redirected to `RLock()`.  A reader lock is only
  released via fcntl(2) when all gourtines within the same process space
  have unlocked it.  This is done via an internal counter which is
  protected (among other things) by an internal state mutex.

* Panic on violations of the lock protocol, namely when calling
  `Unlock()` on an unlocked lock.  This helps detecting violations in
  the code but also protects the storage from corruption.  Doing this
  has revealed some bugs fixed in ealier commits.

Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
2019-02-15 09:49:44 +01:00
Nalin Dahyabhai 6b2ee7f61c images: always set Digest if we have digests
Make sure that an Image that has at least one digest always has a
populated Digest field.

Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2019-02-07 14:07:16 -05:00
Nalin Dahyabhai ccf8bef6fa Teach images to hold multiple manifests
Change how we compute digests for BigData items with names that start
with "manifest" so that we use the image library's manifest.Digest()
function, which knows how to preprocess schema1 manifests to get the
right value, instead of just trying to finesse it.

Track the digests of multiple manifest-named items for images.

Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2019-02-07 10:27:36 -05:00
Nalin Dahyabhai c8dc9b79a8 Remove mapped layers first
When removing an image, remove the image's mapped top layers before the
image's "main" top layer, in case the graph driver is hiding a
dependency between the mapped layers and the "real" one (as it's allowed
to do).

Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2019-01-17 14:30:04 -05:00
Zac Medico c7ba5749d4
Add lock sanity checks to Save() methods
I have experienced "layer not known" corruption triggered by concurrent
buildah/skopeo processes, and hopefully lock sanity checks will help to
prevent this kind of problem.

Signed-off-by: Zac Medico <zmedico@gmail.com>
2018-08-24 20:31:47 -07:00
Nalin Dahyabhai 6cb6f31c03 Add mapped top layers to images
Allow images to have multiple top layers which should only differ by
which UID/GID mappings are used in them, to make creating multiple
containres which use the same mappings faster.

Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2018-05-30 13:46:08 -04:00
Nalin Dahyabhai 16e7f5fb57 Only try to copy new layers/images/containers if we create them
When creating new Layers, Images, or Containers, only try to copy the
newly-created results if we actually created them.

Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2018-05-07 10:35:28 -04:00
Nalin Dahyabhai 363b02079c Always return deep-copied layer/image/container info
Always copy slices and maps in Layer, Image, and Container structures
before handing them back to callers so that, even if they modify them
directly, they won't accidentally mess with our in-memory copies of
those fields in the copies of the structures that we're using.

Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2018-03-07 17:07:38 -05:00
Nalin Dahyabhai 1824cf917a Add explicitly-settable digest values for images
Add explicitly-settable digest values for images that are treated mostly
like the implicit digests that we track for manifests, for the sake of
v1 images which have manifests that need to be preprocessed before being
digested to produce an image's digest value.  We'll still have the
digest of the unprocessed manifest, but that shouldn't hurt.

Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2017-12-11 16:16:46 -05:00
Nalin Dahyabhai 2a564455fd Add a notion of image "digests" based on their "manifest" data
Add a "digest" of an image that is equal to the digest of its big data
item named "manifest", if it has one, that we can index and use for
locating images.

Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2017-11-16 11:52:25 -05:00
Nalin Dahyabhai eace836c44 Track the digests of "big data" items
Teach image and container store types to also track the digests of "big
data" items that we have them store.

Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2017-10-02 17:50:00 -04:00
Daniel J Walsh 232429cdea Merge pull request #107 from nalind/preallocate-slices
Preallocate some slices that we build up
2017-09-30 07:07:48 -04:00
Nalin Dahyabhai 2f258f168e Initialize Flags and BigDataSizes maps
When we read itms from disk, if maps in the structures are empty, they
won't be allocated as part of the decoding process.  When we
subsequently go to read or write something from such a map, make sure
it's been initialized.

Add some validation of names that we convert to file names, and of
digest values, so that we can be more precise about the error code we
return when there's a problem with the values.

Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2017-09-29 17:58:47 -04:00
Nalin Dahyabhai 84922714d2 Merge pull request #108 from nalind/layerless-images
Stop rejecting creation of images with no layers
2017-09-29 16:16:54 -04:00
Nalin Dahyabhai 7ccd1bdeb2 Stop rejecting creation of images with no layers
We need to be able to create images which consist of just a list of
manifests, and those don't contain layers, so relax CreateImage()'s
requirement that a layer be specified.

Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2017-09-29 15:01:26 -04:00
Nalin Dahyabhai 1289ff09a7 Preallocate some slices that we build up
Take a guess at the final size of some slices that we build up item by
item, and try to allocate enough capacity for them before starting to
build them.  It's probably not a big speedup, though.

Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2017-09-29 15:00:59 -04:00
Nalin Dahyabhai a546c6d7a4 Also dedupe layer/image/container names at create
We already deduplicated names in Store.SetNames(), but we weren't also
doing that when creating layers, images, and containers, or in the
individual store SetNames() methods.

Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2017-09-29 15:00:09 -04:00
Nalin Dahyabhai 6986edce00 Create errors using "errors"
Use the standard library's "errors" package to create errors so that
backtraces in wrapped errors terminate at the point where the error was
first wrapped, and not at the line where we created the error, which
isn't as useful for troubleshooting.

Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2017-09-01 17:04:56 -04:00
Nalin Dahyabhai a4c52f3316 Allow setting the creation-date on images
Add a field to ImageOptions that allows a caller to specify a date of
creation when calling CreateImage(), if there's a value in the image
metadata that would be more useful than the default (which is "now" at
the time CreateImage() is called).

Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2017-06-20 11:59:28 -04:00
Daniel J Walsh 8358b1ea98 Merge pull request #66 from runcom/memory-hungry-not
layers|containers: do not allocate slices at every delete
2017-06-19 11:50:32 -04:00
Antonio Murdaca 10844b724d
layers|containers: do not allocate slices at every delete
When Delete:ing a layer or a container the code was always allocating a
new slice just to remove an element from the original slice.
Profiling cri-o with c/storage showed that doing it at every delete is
pretty expensive:

```
         .          .    309:   newContainers := []Container{}
         .          .    310:   for _, candidate := range r.containers
{
         .          .    311:           if candidate.ID != id {
  528.17kB   528.17kB    312:                   newContainers =
append(newContainers, candidate)
         .          .    313:           }
         .          .    314:   }

         .          .    552:           newLayers := []Layer{}
         .          .    553:           for _, candidate := range
r.layers {
         .          .    554:                   if candidate.ID != id {
    1.03MB     1.03MB    555:                           newLayers =
append(newLayers, candidate)
         .          .    556:                   }
         .          .    557:           }
         .          .    558:           r.layers = newLayers
```

This patch just filters out the element to remove from the original
slice w/o allocating a new slice. After this patch, no memory overhead
anymore is shown in the profiler.

Signed-off-by: Antonio Murdaca <runcom@redhat.com>
2017-06-19 17:08:40 +02:00
Nalin Dahyabhai 0200465c0b Track creation dates for layers/images/containers
Add a Created field to Layer, Image, and Container structures that we
intialize when creating one of them.

Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2017-06-16 10:12:55 -04:00
Nalin Dahyabhai a9b1fe6241 Add read-only layer/image/container stores
Implement read-only versions of layer and image store interfaces which
allocate read-only locks and which return errors whenever a write
function is called (which should only be possible after a type
assertion, since they're not part of the read-only interfaces).

Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2017-06-12 16:31:19 -04:00
Nalin Dahyabhai 198f752fb5 Split layer and image stores into RO and RW kinds
Split the LayerStore and ImageStore interfaces into read-only and
write-only subset interfaces, and make the proper stores into unions of
the read-only and write-only method sets.

Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2017-06-12 10:44:36 -04:00
Dan Walsh 162e676330 Add read-only locks
We need to be able to acquire locks on storage areas which aren't
mounted read-write, which return errors when we attempt to open a file
in the mode where we can take write locks on them.  This patch adds a
read-only lock type for use in those cases.

A given file can be opened for read-locking or write-locking, but not
both.  Our Locker interface gains an IsReadWrite() method to let callers
tell the difference.

Based on patches by Dan Walsh <dwalsh@redhat.com>
Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2017-06-12 10:40:39 -04:00
Dan Walsh 35dc8dbc67 Uneccessary Touch functions.
We don't need these Touch calls, since the Save function will handle it.

Signed-off-by: Dan Walsh <dwalsh@redhat.com>
2017-06-07 16:58:11 -04:00