mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Fix data race on inotify.Watch.mask.
PiperOrigin-RevId: 203180463 Change-Id: Ief50988c1c028f81ec07a26e704d893e86985bf0
This commit is contained in:
@@ -16,6 +16,7 @@ package fs
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
"gvisor.googlesource.com/gvisor/pkg/abi/linux"
|
||||
"gvisor.googlesource.com/gvisor/pkg/ilist"
|
||||
@@ -279,13 +280,13 @@ func (i *Inotify) AddWatch(target *Dirent, mask uint32) int32 {
|
||||
// same inode. Obtain an extra reference if necessary.
|
||||
existing.Pin(target)
|
||||
|
||||
newmask := mask
|
||||
if mergeMask := mask&linux.IN_MASK_ADD != 0; mergeMask {
|
||||
// "Add (OR) events to watch mask for this pathname if it already
|
||||
// exists (instead of replacing mask)." -- inotify(7)
|
||||
existing.mask |= mask
|
||||
} else {
|
||||
existing.mask = mask
|
||||
newmask |= atomic.LoadUint32(&existing.mask)
|
||||
}
|
||||
atomic.StoreUint32(&existing.mask, newmask)
|
||||
return existing.wd
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ package fs
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
"gvisor.googlesource.com/gvisor/pkg/abi/linux"
|
||||
)
|
||||
@@ -33,9 +34,6 @@ type Watch struct {
|
||||
// Descriptor for this watch. This is unique across an inotify instance.
|
||||
wd int32
|
||||
|
||||
// Events being monitored via this watch.
|
||||
mask uint32
|
||||
|
||||
// The inode being watched. Note that we don't directly hold a reference on
|
||||
// this inode. Instead we hold a reference on the dirent(s) containing the
|
||||
// inode, which we record in pins.
|
||||
@@ -48,6 +46,10 @@ type Watch struct {
|
||||
// mu protects the fields below.
|
||||
mu sync.Mutex `state:"nosave"`
|
||||
|
||||
// Events being monitored via this watch. Must be accessed atomically,
|
||||
// writes are protected by mu.
|
||||
mask uint32
|
||||
|
||||
// pins is the set of dirents this watch is currently pinning in memory by
|
||||
// holding a reference to them. See Pin()/Unpin().
|
||||
pins map[*Dirent]bool
|
||||
@@ -62,7 +64,7 @@ func (w *Watch) ID() uint64 {
|
||||
// should continue to be be notified of events after the target has been
|
||||
// unlinked.
|
||||
func (w *Watch) NotifyParentAfterUnlink() bool {
|
||||
return w.mask&linux.IN_EXCL_UNLINK == 0
|
||||
return atomic.LoadUint32(&w.mask)&linux.IN_EXCL_UNLINK == 0
|
||||
}
|
||||
|
||||
// isRenameEvent returns true if eventMask describes a rename event.
|
||||
@@ -73,7 +75,7 @@ func isRenameEvent(eventMask uint32) bool {
|
||||
// Notify queues a new event on this watch.
|
||||
func (w *Watch) Notify(name string, events uint32, cookie uint32) {
|
||||
unmaskableBits := ^uint32(0) &^ linux.IN_ALL_EVENTS
|
||||
effectiveMask := unmaskableBits | w.mask
|
||||
effectiveMask := unmaskableBits | atomic.LoadUint32(&w.mask)
|
||||
matchedEvents := effectiveMask & events
|
||||
|
||||
if matchedEvents == 0 {
|
||||
|
||||
Reference in New Issue
Block a user