-
Notifications
You must be signed in to change notification settings - Fork 247
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
overlay: lock staging directories #1916
Changes from all commits
ca8158b
1e43992
26e97fb
e6d2359
eb53d59
76f8994
c06cd1c
f1352df
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -133,11 +133,25 @@ func (l *LockFile) Lock() { | |
} | ||
} | ||
|
||
// LockRead locks the lockfile as a reader. | ||
// RLock locks the lockfile as a reader. | ||
func (l *LockFile) RLock() { | ||
l.lock(readLock) | ||
} | ||
|
||
// TryLock attempts to lock the lockfile as a writer. Panic if the lock is a read-only one. | ||
func (l *LockFile) TryLock() error { | ||
if l.ro { | ||
panic("can't take write lock on read-only lock file") | ||
} else { | ||
return l.tryLock(writeLock) | ||
} | ||
} | ||
|
||
// TryRLock attempts to lock the lockfile as a reader. | ||
func (l *LockFile) TryRLock() error { | ||
return l.tryLock(readLock) | ||
} | ||
|
||
// Unlock unlocks the lockfile. | ||
func (l *LockFile) Unlock() { | ||
l.stateMutex.Lock() | ||
|
@@ -401,9 +415,47 @@ func (l *LockFile) lock(lType lockType) { | |
// Optimization: only use the (expensive) syscall when | ||
// the counter is 0. In this case, we're either the first | ||
// reader lock or a writer lock. | ||
lockHandle(l.fd, lType) | ||
lockHandle(l.fd, lType, false) | ||
} | ||
l.lockType = lType | ||
l.locked = true | ||
l.counter++ | ||
} | ||
|
||
// lock locks the lockfile via syscall based on the specified type and | ||
// command. | ||
func (l *LockFile) tryLock(lType lockType) error { | ||
var success bool | ||
if lType == readLock { | ||
success = l.rwMutex.TryRLock() | ||
} else { | ||
success = l.rwMutex.TryLock() | ||
} | ||
if !success { | ||
return fmt.Errorf("resource temporarily unavailable") | ||
} | ||
giuseppe marked this conversation as resolved.
Show resolved
Hide resolved
|
||
l.stateMutex.Lock() | ||
defer l.stateMutex.Unlock() | ||
if l.counter == 0 { | ||
// If we're the first reference on the lock, we need to open the file again. | ||
fd, err := openLock(l.file, l.ro) | ||
if err != nil { | ||
l.rwMutex.Unlock() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
return err | ||
} | ||
l.fd = fd | ||
|
||
// Optimization: only use the (expensive) syscall when | ||
// the counter is 0. In this case, we're either the first | ||
// reader lock or a writer lock. | ||
if err = lockHandle(l.fd, lType, true); err != nil { | ||
closeHandle(fd) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is, still, And looking at There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've splitted the functions so that we don't call There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I asked for But then https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-lockfileex says that WDYT about Ultimately I can live with the two functions split, as the PR is now. Maybe add a comment warning about the automatic unlock? |
||
l.rwMutex.Unlock() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
return err | ||
} | ||
} | ||
l.lockType = lType | ||
l.locked = true | ||
l.counter++ | ||
return nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With this,
ApplyDiffFromStagingDirectory
unlocks the lock on some error return paths, but not all. A caller can’t deal with that.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
… but there are also various error paths on callers. So maybe the staging area should only be unlocked when this succeeds?
Or maybe this does not matter?
Note to self: FIXME investigate.