Commit Graph

32 Commits

Author SHA1 Message Date
Kir Kolyshkin a4d8f720a2 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č b2d3379ed4 Deprecate *LockFile.Modified and *LockFile.Touch
They are a shared state across all users of the *LockFile in the process,
and therefore incorrect to use for any single consumer for change tracking.

Direct users to user the new GetLastWrite, ModifiedSince, and RecordWrite,
instead, and convert all c/storage users.

In addition to just being correct, the new API is also more efficient:
- We now initialize stores with GetLastWrite before loading state;
  so, we don't trigger an immediate reload on the _second_ use of a store,
  due to the problematic semantics of .Modified().
- Unlike Modified() and Touch(), the new APi can be safely used without
  locking *LockFile.stateMutex, for a tiny speedup.

The conversion is, for now, trivial, just immediately updating the lastWrite
value after the ModifiedSince call.  That will get better.

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2022-11-29 18:12:43 +01:00
Miloslav Trmač d34bcddaa3 Add new LockFile state tracking API
lockfile.LastWrite allows callers to explicitly
track state across *LockFile.{GetLastWrite,ModifiedSince,
RecordWrite}.

*LockFile.{Modified,Touch} are now implemented
in terms of these APIs.

NOTE: This changes behavior, Touch() now updates
the built-in state only on success.  Either way there
can be suprious modification reports.

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2022-11-29 18:12:43 +01:00
Miloslav Trmač 9bcb737123 Modify pkg/lockfile to return a struct instead of an interface
Add lockfile.GetLockFile and lockfile.GetROLockFile (with upper-case
F, as opposed to existing methods with lower-case f) which return a
*LockFile struct, instead of the Locker interface.

This follows the general Go design heuristic: "return structs, accept
interfaces"; more importantly, it allows us to add more methods to the lock
object without breaking the Go API by extending a pre-existing interface.

Should not change behavior.

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2022-11-29 18:12:43 +01:00
Miloslav Trmač 41d128a4b2 Document the locking rules for fields of *LockFile
This actually relaxes some of the rules, contrary to previous
documentation, but some of those relaxed rules were already
assumed.

Should not change behavior.

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2022-11-29 18:12:43 +01:00
Miloslav Trmač d4462aad95 API BREAK: Drop Lockfile.Locked
It is fundamentally incorrect, and no users are remaining.

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2022-10-21 21:10:33 +02:00
Miloslav Trmač 5791b9d6af Add Lockfile.AssertLocked and AssertLockedForWriting
This will replace Lockfile.Locked for the sanity-checking
purposes.

It is, just like Locked never was, NOT a way for a caller
to check the current state. Hence the panic() instead of an
error return.

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2022-10-21 21:10:33 +02:00
Nalin Dahyabhai de366fc7f1 Fix lockfiles never detecting changes
If we ever check the last-writer of a lock file and get back a zero
value, don't only check if subsequent last-writer values match its first
zero bytes, which is always true, as a test to see if the last-writer
value has remained unchanged.

Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2022-10-18 14:32:27 -04:00
Daniel J Walsh aba77e1c98
Merge pull request #1364 from mtrmac/warnings
Another bunch of warning cleanups
2022-10-17 08:38:44 -04:00
Alexander Larsson ddb5de3f4a Correctly handle lockfiles without writes
A newly created lock-file is of size zero, which happens for example
if you reset the storage state. In this state, lockfile.Modified()
always returns true, because it thinks any short read means something
changed.

I ran into this with the image store, which was empty (using images
from a different store), and it keept re-reading the image store all
the time even if nothing changed (i.e. both lock file reads returned
zero bytes).

The proper way to handle this seems to be to compare partial reads
also.

Signed-off-by: Alexander Larsson <alexl@redhat.com>
2022-10-17 11:27:04 +02:00
Miloslav Trmač 5e410ef763 Misc individual warning fixes
Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2022-10-14 17:17:53 +02:00
Miloslav Trmač 082a8161ed Remove lockfile.Locker.RecursiveLock
It is not valid as currently implemented, and there is no known user.

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2022-10-07 19:45:14 +02:00
Miloslav Trmač 924ace221c Remove an undocumented assumption that O_RDONLY == 0
There's at least one Go platform where that is not true.

Making that assumption without any warning is just a trap for future readers.

Instead, just do the obviously correct thing, per the API documentation.

On macOS, this compiles to _literally exactly the same binary code_.

So, let the compiler be clever so that we don't have to.

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2022-09-14 20:22:04 +02:00
Kir Kolyshkin 7d52f1732b pkg/lockfile: wrap error in openLock
unix.Open returns a bare error (like EPERM). This is worked around in
on user, (*lockfile).lock, where we panic, but not in the other user,
createLockerForPath, and as a result such a bare error might be returned
from GetLockfile or GetROLockfile.

Wrap it into os.PathError and remove the workaround from lockfile.lock.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2022-09-12 12:56:37 -07:00
Kir Kolyshkin 463d50fabc pkg/lockfile: fix openLock file permissions
Since commit 162a0bf730, openLock creates a file in case ro
argument is set, but the file is created with 0 permission bits.

Fix this, and unify the file creation logic while at it.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2022-09-08 15:20:27 -07:00
Kir Kolyshkin 2076605830 pkg/lockfile: fix openLock doc
Since commit 162a0bf730, openLock creates a file even if ro is
set, but the documentation says otherwise.

Since commit 16de6d32b4, openLock also creates file's parent
directories if needed, but the documentation doesn't say that.

Fix both issues.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2022-09-08 15:18:59 -07: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
Miloslav Trmač 0fe5415cf8 Make sure the values returned by newLastWriterID() are unique
... by including the time, PID, and a per-process counter.

Pad the rest with rando values for continuity.

This feels a bit like overkill, OTOH adding the PID might be
useful for debugging, so there's that.

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2022-06-15 17:49:54 +02:00
Miloslav Trmač d51f02b648 Use a []byte for the "last writer ID" instead of a string
... simplifying the code.

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2022-06-15 17:44:56 +02:00
Miloslav Trmač 64f86d69a5 Consolidate lockfile.lw generation into a helper
... to have only one place that generates the value,
and make it easier to change how it is constructed.

For now, this is just a simple function call forwarding,
but we'll change that shortly.

Signed-off-by: Miloslav Trmač <mitr@redhat.com>
2022-06-15 17:44:56 +02:00
Daniel J Walsh 162a0bf730
Create readonly locks if the lockfile does not exists
Users are setting up readonly shares and sometimes they forget, or do
not even know that they need to create the lockfile.

Even in the quay.io/podman/stable images Dockerfile, I have to manually
create these files.

Fixes: https://github.com/containers/storage/issues/1029

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2021-09-29 09:29:00 -04:00
Daniel J Walsh 33b3369a7f
Merge pull request #957 from saschagrunert/panic-fix
Fix runtime panic for opening lockfile if parent dir got removed
2021-07-09 06:39:19 -04:00
Sascha Grunert 16de6d32b4
Fix runtime panic for opening lockfile if parent dir got removed
If the lockfile directory gets removed but the container runtime is
still running with an open storage instance, then we can trigger a
runtime panic by:

1. Starting CRI-O
2. Removing the lockfile dir, e.g.:
   `sudo rm -rf /var/lib/containers/storage/overlay-images`
3. Running `crictl images`

```
panic: error opening "/var/lib/containers/storage/overlay-images/images.lock": no such file or directory

goroutine 93 [running]:
github.com/containers/storage/pkg/lockfile.(*lockfile).lock(0xc0006b83c0, 0x2000000)
        /go/src/github.com/cri-o/cri-o/vendor/github.com/containers/storage/pkg/lockfile/lockfile_unix.go:107 +0x388
github.com/containers/storage/pkg/lockfile.(*lockfile).RLock(0xc0006b83c0)
        /go/src/github.com/cri-o/cri-o/vendor/github.com/containers/storage/pkg/lockfile/lockfile_unix.go:146 +0x37
github.com/containers/storage.(*imageStore).RLock(0xc00006e420)
        /go/src/github.com/cri-o/cri-o/vendor/github.com/containers/storage/images.go:778 +0x33
github.com/containers/storage.(*store).Images(0xc0003f3b80, 0x0, 0x0, 0x0, 0x0, 0x0)
        /go/src/github.com/cri-o/cri-o/vendor/github.com/containers/storage/store.go:3089 +0x1dc
```

We now ensure the parent lockfile directory, but only if it does not
exist to not degrade the performance of c/stroage.

Unit tests around that case have been added as well.

Signed-off-by: Sascha Grunert <sgrunert@redhat.com>
2021-07-07 14:05:09 +02:00
Giuseppe Scrivano 10afc9279e
lockfile: merge Seek+Read/Write into Pread/Pwrite
drop a call to Seek and use the Pread and Pwrite syscalls instead that
already accept an offset.

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
2021-06-09 11:06:20 +02:00
Nalin Dahyabhai 58be038c06 pkg/lockfile: fix a race and an incorrect unit test
Fix a race where the state lock in a Unixy lockfile structure wasn't
being used to protect access to all of the structure's state fields.

Fix usage of sync/atomic in the corresponding unit tests to not mix
atomic adds and reads with non-atomic reads, something which the race
detector complained about.

Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2021-02-22 18:24:04 -05:00
Daniel J Walsh 44195fdb33
Make lock files world readable
This will make them easier to consule for additional stores

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2020-06-25 09:10:35 -04:00
Daniel J Walsh 533121f287
Lock files should be CLOEXEC
We are getting reports of SELinux failures on leaked file descriptors.

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2020-06-25 06:06:59 -04:00
Giuseppe Scrivano c2d2788f52
lockfile: drop call to unix.Fsync
do not flush the modified metadata to disk each time the store is
modified.

It is not needed for other processes stat'ing the lock file to see the
updated mtime.

introduced with commit 9b0633295b

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
2020-03-02 12:07:11 +01: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
Matthew Heon fdd3af2db0 Do not discard errors when panicing on lockfile open
We're seeing some panics with Podman on Ubuntu 19 in this code,
and debugging without knowing what's going wrong is very
difficult.

Signed-off-by: Matthew Heon <matthew.heon@pm.me>
2019-10-11 15:40:33 -04:00
Nalin Dahyabhai 2dfeb3edf7 Move lockfiles to their own package
Move the lockfile implementation into a subpackage so that we can use it
in the devicemapper driver.

Signed-off-by: Nalin Dahyabhai <nalin@redhat.com>
2019-07-02 11:14:04 -04:00