Documentation ¶
Overview ¶
Package lock is the API for POSIX-style advisory regional file locks and BSD-style full file locks.
Callers needing to enforce these types of locks, like sys_fcntl, can call LockRegion and UnlockRegion on a thread-safe set of Locks. Locks are specific to a unique file (unique device/inode pair) and for this reason should not be shared between files.
A Lock has a set of holders identified by UniqueID. Normally this is the pid of the thread attempting to acquire the lock.
Since these are advisory locks, they do not need to be integrated into Reads/Writes and for this reason there is no way to *check* if a lock is held. One can only attempt to take a lock or unlock an existing lock.
A Lock in a set of Locks is typed: it is either a read lock with any number of readers and no writer, or a write lock with no readers.
As expected from POSIX, any attempt to acquire a write lock on a file region when there already exits a write lock held by a different uid will fail. Any attempt to acquire a write lock on a file region when there is more than one reader will fail. Any attempt to acquire a read lock on a file region when there is already a writer will fail.
In special cases, a read lock may be upgraded to a write lock and a write lock can be downgraded to a read lock. This can only happen if:
read lock upgrade to write lock: There can be only one reader and the reader must be the same as the requested write lock holder.
write lock downgrade to read lock: The writer must be the same as the requested read lock holder.
UnlockRegion always succeeds. If LockRegion fails the caller should normally interpret this as "try again later".
Index ¶
- Constants
- type Lock
- type LockType
- type Locks
- func (l *Locks) EventRegister(e *waiter.Entry) error
- func (l *Locks) EventUnregister(e *waiter.Entry)
- func (l *Locks) LockRegion(ctx context.Context, uid UniqueID, ownerPID int32, t LockType, r LockRange, ...) error
- func (l *Locks) LockRegionVFS1(ctx context.Context, uid UniqueID, t LockType, r LockRange, block bool) error
- func (l *Locks) Readiness(waiter.EventMask) waiter.EventMask
- func (l *Locks) TestRegion(ctx context.Context, uid UniqueID, t LockType, r LockRange) linux.Flock
- func (l *Locks) UnlockRegion(uid UniqueID, r LockRange)
- type OwnerInfo
- type UniqueID
Constants ¶
const LockEOF = math.MaxUint64
LockEOF is the maximal possible end of a regional file lock.
A BSD-style full file lock can be represented as a regional file lock from offset 0 to LockEOF.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Lock ¶
type Lock struct { // Readers are the set of read lock holders identified by UniqueID. // If len(Readers) > 0 then Writer must be nil. Readers map[UniqueID]OwnerInfo // Writer holds the writer unique ID. It's nil if there are no writers. Writer UniqueID // WriterInfo describes the writer. It is only meaningful if Writer != nil. WriterInfo OwnerInfo }
Lock is a regional file lock. It consists of either a single writer or a set of readers.
A Lock may be upgraded from a read lock to a write lock only if there is a single reader and that reader has the same uid as the write lock.
A Lock may be downgraded from a write lock to a read lock only if the write lock's uid is the same as the read lock.
Accesses to Lock are synchronized through the Locks object to which it belongs.
+stateify savable
type LockType ¶
type LockType int
LockType is a type of regional file lock.
const ( // ReadLock describes a POSIX regional file lock to be taken // read only. There may be multiple of these locks on a single // file region as long as there is no writer lock on the same // region. ReadLock LockType = iota // WriteLock describes a POSIX regional file lock to be taken // write only. There may be only a single holder of this lock // and no read locks. WriteLock )
type Locks ¶
type Locks struct {
// contains filtered or unexported fields
}
Locks is a thread-safe wrapper around a LockSet.
+stateify savable
func (*Locks) EventRegister ¶
EventRegister implements waiter.Waitable.EventRegister.
func (*Locks) EventUnregister ¶
EventUnregister implements waiter.Waitable.EventUnregister.
func (*Locks) LockRegion ¶
func (l *Locks) LockRegion(ctx context.Context, uid UniqueID, ownerPID int32, t LockType, r LockRange, block bool) error
LockRegion attempts to acquire a typed lock for the uid on a region of a file. Returns nil if successful in locking the region, otherwise an appropriate error is returned.
func (*Locks) LockRegionVFS1 ¶
func (l *Locks) LockRegionVFS1(ctx context.Context, uid UniqueID, t LockType, r LockRange, block bool) error
LockRegionVFS1 is a wrapper around LockRegion for VFS1, which does not implement F_GETLK (and does not care about storing PIDs as a result).
TODO(gvisor.dev/issue/1624): Delete.
func (*Locks) TestRegion ¶
TestRegion checks whether the lock holder identified by uid can hold a lock of type t on range r. It returns a Flock struct representing this information as the F_GETLK fcntl does.
Note that the PID returned in the flock structure is relative to the root PID namespace. It needs to be converted to the caller's PID namespace before returning to userspace.
TODO(gvisor.dev/issue/5264): we don't support OFD locks through fcntl, which would return a struct with pid = -1.
func (*Locks) UnlockRegion ¶
UnlockRegion attempts to release a lock for the uid on a region of a file. This operation is always successful, even if there did not exist a lock on the requested region held by uid in the first place.
type OwnerInfo ¶
type OwnerInfo struct { // PID is the process ID of the lock owner. PID int32 }
OwnerInfo describes the owner of a lock.
TODO(gvisor.dev/issue/5264): We may need to add other fields in the future (e.g., Linux's file_lock.fl_flags to support open file-descriptor locks).
+stateify savable