Commit Graph

228 Commits

Author SHA1 Message Date
Miloslav Trmač fbfe821818 Use io.SeekStart instead of hard-coding 0.
Should not change behavior.

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2025-05-14 20:53:29 +02:00
Giuseppe Scrivano 289948adad chunked: use temporary file for tar-split data
Replace the in-memory buffer with a O_TMPFILE file.  This reduces the
memory requirements for a partial pull since the tar-split data can be
written to disk.

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
2025-04-29 12:26:57 +02:00
openshift-merge-bot[bot] 427a733a40 Merge pull request #2306 from kolyshkin/modernize
Use `slices` and `maps` more where appropriate
2025-04-01 22:00:08 +00:00
openshift-merge-bot[bot] 1c7103f4f0 Merge pull request #2305 from kolyshkin/for-range
Use for range over integers
2025-04-01 21:57:19 +00:00
Kir Kolyshkin 41542bfd7b Use for range over integers
This form is available since Go 1.22 (see
https://tip.golang.org/ref/spec#For_range) and will probably be seen
more and more in the new code.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-03-31 15:39:12 -07:00
Kir Kolyshkin b15d254157 Use any instead of interface{}
It's available since Go 1.18 (see https://pkg.go.dev/builtin#any).

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-03-31 15:37:25 -07:00
Kir Kolyshkin 58e13450ca layers: use slices.Sort
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-03-31 14:40:17 -07:00
Giuseppe Scrivano 0759d0c77d layers: write read only layers to imagestore
when an imagestore is used, a R/O layer must be written to the
layers.json under the imagestore, not graphroot.

The lock on the imagestore is already taken through the
multipleLockFile{} mechanism in place.

Closes: https://github.com/containers/storage/issues/2257

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
2025-02-20 09:24:55 +01:00
Sascha Grunert ed080a1b61 Remove hashicorp dependencies
The dependencies are licensed under MPL-2.0 which is not allowed in the
CNCF.

https://github.com/cncf/foundation/blob/main/license-exceptions

https://github.com/cncf/foundation/blob/main/allowed-third-party-license-policy.md#cncf-allowlist-license-policy

Signed-off-by: Sascha Grunert <sgrunert@redhat.com>
2025-02-03 09:52:24 +01:00
Giuseppe Scrivano dddc41bb19 store: new function Dedup()
expose a new API to deduplicate files in the images.

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
2024-12-09 16:41:59 +01:00
Paul Holzinger e95ec138a1 store: correctly remove incomplete layers on load.
In go one should never modify a slice while also iterating over it at
the same time. This causes weird side effects as the underlying array
elements are shifted around without the range loop index knowing.
So if you delete a element the loop will then actually skip the next one
and theoretically access out of bounds on the last element which does
not panic but rather return the default zero type, nil here which then
causes the panic on layer.Flags == nil.

Here is a simple example to show the behavior:
func main() {
	slice := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
	for _, num := range slice {
		if num == 5 {
			slice = slices.DeleteFunc(slice, func(n int) bool {
				return n == 5
			})
		}
		fmt.Println(num)
	}
}

The loop will not print 6, but then as last number it prints 0 (the
default zero type for an int).

Fixes #2184

Signed-off-by: Paul Holzinger <pholzing@redhat.com>
2024-12-03 15:11:25 +01:00
Jan Rodák c78d40a402 Refactor of copying maps
Removes the duplicate copy*Map function using the general function newMapFrom.
Reduces the allocation of empty maps using the copyMapPrefferingNil function.
This change may affect the behavior so that instead of an empty allocated map, a nil will be returned.

Signed-off-by: Jan Rodák <hony.com@seznam.cz>
2024-10-25 10:24:48 +02:00
Jan Rodák c1905bba73 Refactor operations with slices
Removes duplicate copy*Slice functions using a generic copy function
or replaces them with the slices.Clone function.
Also simplifies the stringSliceWithoutValue function.
These changes should not change the behavior.

Signed-off-by: Jan Rodák <hony.com@seznam.cz>
2024-10-25 10:23:12 +02:00
Miloslav Trmač 8df9d1d7d6 Use the correct Go doc list syntax
Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2024-10-16 00:34:54 +02:00
Miloslav Trmač e652ec86b3 Explicitly differentiate between empty and missing tar-split
Empty tar-split shouldn't ever happen, but being precise
here doesn't hurt.

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2024-10-14 20:10:07 +02:00
Miloslav Trmač 9fdbfc818c Don't set UncompressedSize on chunked pull
The current value obtained by summing the sizes of regular file contents
does not match the size of the uncompressed layer tarball.

We don't have a convenient source to compute the correct size
for estargz without pulling the full layer and defeating the point;
so we must allow for the size being unknown.

For recent zstd:chunked images, we have the full tar-split,
so we can compute the correct size; that will happen in
the following commits.

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2024-10-14 20:10:07 +02:00
Jan Rodák 0ce45449a5 Revert the use of the slices.Clone function
because it does not return nil when the slice length is 0.
This behavior caused the slices.Clone function to allocate
a unnecessary amount of memory when the slice length is 0,
and the c/common tests failed.

Signed-off-by: Jan Rodák <hony.com@seznam.cz>
2024-10-08 14:26:51 +02:00
Giuseppe Scrivano b5c36c473d drivers: drop unused args from ApplyDiffWithDiffer
Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
2024-09-19 09:33:27 +02:00
Giuseppe Scrivano 108ca3fa3f chunked: fix reuse of the layers cache
the global singleton was never updated, causing the cache to be always
recreated for each layer.

It is not possible to keep the layersCache mutex for the entire load()
since it calls into some store APIs causing a deadlock since
findDigestInternal() is already called while some store locks are
held.

Another benefit is that now only one goroutine can run load()
preventing multiple calls to load() to happen in parallel doing the
same work.

Closes: https://github.com/containers/storage/issues/2023

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
2024-09-19 09:33:27 +02:00
Miloslav Trmač 92e1bd58a3 Avoid unnecessary manually-coded loops
Use the "slices", "maps" standard library packages, or other
readily-available features.

Should not change behavior.

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2024-09-05 19:45:45 +02:00
Miloslav Trmač 3c99b1999d Use slices.Delete* instead of manual append
Conservatively use Index* + Delete to delete the
first element where it's not obvious that the code would really
want to delete all instances.

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2024-09-05 19:44:49 +02:00
Miloslav Trmač 7c8a73dd5d Use slices.Clone where appropriate
Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2024-09-05 19:44:47 +02:00
Miloslav Trmač a1da93b909 Be clearer about the layer store locking rules
... as modified by https://github.com/containers/storage/pull/2036 .

Also document a LOCKING BUG I don't now care to fix.

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2024-08-30 16:38:22 +02:00
Giuseppe Scrivano d7b8a61678 chunked: store compressed digest if validated
if the compressed digest was validated, as it happens when
'pull_options = {convert_images = "true"}' is set, then store it as
well so that reusing the blob by its compressed digest works.

Previously, when an image converted to zstd:chunked was pulled a
second time, it would not be recognized by its compressed digest,
resulting in the need to re-pull the image again.

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
2024-07-10 09:41:41 +02:00
Giuseppe Scrivano 5b744cf0f3 store: lock both graphroot and the imagestore root
when an image store is used, lock it as well as the graphroot.

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
2024-02-29 16:35:58 +01:00
Giuseppe Scrivano 09f953bc89 layers: add infra to lock multiple files
this is a preparation for the next commit, which will use this feature.

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
2024-02-29 16:34:29 +01:00
Miloslav Trmač 7dfe2c07fc Save our layer before calling SetBigData and other large I/O
SetBigData itself calls saveFor; so doing that before raises
fewer questions about stale data / stepping over each other.

The change in timing is externally-observable, but should hopefully
not matter much in practice, because this code is typically called
from layerStore.create as a part of an atomic create+populate operation
proptected by incompleteFlag.

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2024-02-26 21:04:14 +01:00
Giuseppe Scrivano 7ef73d7c5f store: new API ApplyStagedLayer
Add a race-condition-free alternative to using CreateLayer and
ApplyDiffFromStagingDirectory, ensuring the store is locked for the
entire duration while the layer is being created and populated.

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
2024-02-15 21:57:00 +01:00
Giuseppe Scrivano 51ff8cc47a driver: simplify ApplyDiffFromStagingDirectory
enforce that the stagingDirectory must have the same value as the
diffOutput.Target variable.  It allows to simplify the internal API.

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
2024-02-15 21:56:59 +01:00
Miloslav Trmač fff5352c79 Add LayerOptions.OriginalSize
This allows us to correctly set (CompresedDigest, CompressedSize)
when copying data from another layer; in that case we don't have the
compressed data, so computing the size from compressedCounter
sets an incorrect value.

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2024-02-13 21:56:05 +01:00
Miloslav Trmač badfa37c08 Optimize digest computation for uncompressed layers
When the caller provides neither OriginalDigest nor
UncompressedDigest, only digest the layer once.

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2024-02-13 21:51:10 +01:00
Giuseppe Scrivano cd67cb5a5f overlay: inhibit filegetter with composefs
Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
2023-12-11 15:06:41 +01:00
Giuseppe Scrivano db1dc31354 layers: add option to initialize layer Flags
Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
2023-12-04 16:58:13 +01:00
Giuseppe Scrivano cf52867921 store: new struct to pass ApplyDiffWithDiffer opts
Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
2023-12-04 16:58:13 +01:00
Giuseppe Scrivano 5987db5017 layers: add new TOCDigest attribute
introduce the TOCDigest field for a layer. TOCDigest is designed to
store the digest of the Table of Contents (TOC) of the blob.

It is useful when the UncompressedDigest cannot be validated during a
partial image pull, but the TOC itself is validated.

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
2023-12-04 16:58:13 +01:00
Miloslav Trmač fb74a8065e Don't call UpdateLayerIDMap when creating a layer with no parent
AFAICS this call is intended to "remap" the parent layer's contents to the
desired IDMappings; but when there is no parent layer, there is
nothing to remap.

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2023-10-25 16:45:49 +02:00
Miloslav Trmač 28c87be030 Shorten the scope of some variables
Should not change behavior.

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2023-10-25 16:45:37 +02:00
Giuseppe Scrivano 8ef163a990 chunked: generate tar-split as part of zstd:chunked
change the file format to store the tar-split as part of the
zstd:chunked image.  This will allow clients to rebuild the entire
tarball without having to download it fully.

also store the uncompressed digest for the tarball, so that it can be
stored into the storage database.

Needs: https://github.com/containers/image/pull/1976

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
2023-06-17 00:31:39 +02:00
Nalin Dahyabhai 7206d0f90c compareCheckDirectory: learn about ID maps
Handle old-fashioned ID mappings when looking at layers.  Nowadays,
we'll use an idmapped mount if we can, but we shouldn't blow up if we
had to chown a layer because we couldn't use an idmapped mount.

Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2023-06-13 14:14:56 -04:00
Miloslav Trmač 3a56602a8c Ensure compressor.Close() is called on error paths
Reportedly this is showing up as leaked goroutines in CRI-O:
https://issues.redhat.com/browse/OCPBUGS-10290 .

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2023-06-13 02:17:30 +02:00
Miloslav Trmač 3b4daf3c6a Fix a race in use of tarlog.tarLogger
tarLogger calls the provided callback in a separate
goroutine, and that can happen after tarLogger.Write
returns; tarLogger.Close is requried to ensure the callbacks
have all been correctly called, and the created uidLog and gidLog
values can be consumed.

So, move most of the IO pipeline that is formed around the
layer stream into a nested function that terminates earlier, notably
so that the "defer idLogger.Close()" is called at the appropriate time.

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2023-06-13 02:16:37 +02:00
Miloslav Trmač 032111ad37 Move some variable declarations upfront
We will want to move the next part of the code
into a closure; move variables that will be
accessed outside of that section.

Should not change behavior.

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2023-06-13 02:06:21 +02:00
Miloslav Trmač 3d68d2b4e2 Don't ignore pgzip.NewWriterLevel failures
AFAICS that can't fail with current pgzip; and
pgzip.NewWriter also calls NewWriteLevel, but it just
swallows the error.

Any failure would therefore be very unexpected;
report it instead of suppressing it.0

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2023-06-13 01:35:42 +02:00
Kir Kolyshkin fa414d963d Format sources with gofumpt
gofumpt is a superset of gofmt, enabling some more code formatting
rules.

This commit is brought to you by

	gofumpt -w .

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2023-05-26 16:17:31 -07:00
Miloslav Trmač 06b3862893 Don't silently ignore errors decoding mountpoints.json
Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2023-05-19 18:51:36 +02:00
Giuseppe Scrivano b792a0635a store: ensure lockfile is updated before writes
The lockfile's write record is now updated prior to the actual write
operation.  This ensures that, in the event of an unexpected
termination, other processes are correctly notified of an initiated
write operation.

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
2023-05-18 23:44:23 +02:00
Miloslav Trmač aa3520be0b Don't use bytes.NewBuffer to read data
The documentation says
> The new Buffer takes ownership of buf, and the
> caller should not use buf after this call.

so use the more directly applicable, and simpler, bytes.Reader
instead, to avoid this potentially risky use.

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2023-04-14 22:34:53 +02:00
Nalin Dahyabhai 751ae6693a Extend driver.ListLayers()
Implement ListLayers() for the aufs, btrfs, and devicemapper drivers,
along with a unit test for them.
Stop filtering out directories with names that aren't 64-hex chars in
vfs and overlay ListLayers() implementations, which is more a convention
than a hard rule.
Have layerStore.Wipe() try to remove remaining listed layers after it
removes the layers that the layerStore knew of.
Close() a dangling ReadCloser in NaiveCreateFromTemplate.
Switch from using plain defer to using t.Cleanup() to handle deleting
layers that tests create, have the addManyLayers() test function do so
as well.
Remove vfs.CopyDir, which near as I can tell isn't referenced anywhere.

Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2023-04-12 16:05:09 -04:00
Nalin Dahyabhai 447e9d8842 "pull up" images when creating them, too
We previously started "pulling up" images when we changed their names,
and started denying the presence of images in read-only stores which
shared their ID with an image in the read-write store, so that it would
be possible to "remove" names from an image in read-only storage.  We
forgot about the Flags field, so start pulling that up, too.

Do all of the above when we're asked to create an image, since denying
the presence of images with the same ID in read-only stores would
prevent us from finding the image by any of the names that it "had" just
a moment before we created the new record.

Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2023-04-06 18:21:11 -04:00
Nalin Dahyabhai 99e67c6aab Complete "pulling up" of images in updateNames()
When updateNames() copies an image's record from a read-only store into
the read-write store, copy the accompanying data as well.

Add fields for setting data items at creation-time to LayerOptions,
ImageOptions, and ContainerOptions to make this easier for us and our
consumers.

Replace the store-specific Create() (and the one CreateWithFlags() and
Put()) with private create() and put() methods, since they're not
intended for consumption outside of this package, and add Flags to the
options structures we pass into those methods.  In create() methods,
make copies of those passed-in options structures before modifying any
of their contents.

Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2023-03-31 10:36:30 -04:00