Resolve remaining inotify TODOs.

Also refactor HandleDeletion().

Updates #1479.

PiperOrigin-RevId: 317989000
This commit is contained in:
Dean Deng
2020-06-23 20:05:28 -07:00
committed by gVisor bot
parent 2189e0a660
commit 399c52888d
4 changed files with 26 additions and 34 deletions
+3 -5
View File
@@ -227,19 +227,17 @@ func (d *Dentry) destroy() {
// InotifyWithParent implements vfs.DentryImpl.InotifyWithParent.
//
// TODO(gvisor.dev/issue/1479): Implement inotify.
// Although Linux technically supports inotify on pseudo filesystems (inotify
// is implemented at the vfs layer), it is not particularly useful. It is left
// unimplemented until someone actually needs it.
func (d *Dentry) InotifyWithParent(events, cookie uint32, et vfs.EventType) {}
// Watches implements vfs.DentryImpl.Watches.
//
// TODO(gvisor.dev/issue/1479): Implement inotify.
func (d *Dentry) Watches() *vfs.Watches {
return nil
}
// OnZeroWatches implements vfs.Dentry.OnZeroWatches.
//
// TODO(gvisor.dev/issue/1479): Implement inotify.
func (d *Dentry) OnZeroWatches() {}
// InsertChild inserts child into the vfs dentry cache with the given name under
+3 -5
View File
@@ -300,17 +300,15 @@ func (d *anonDentry) DecRef() {
// InotifyWithParent implements DentryImpl.InotifyWithParent.
//
// TODO(gvisor.dev/issue/1479): Implement inotify.
// Although Linux technically supports inotify on pseudo filesystems (inotify
// is implemented at the vfs layer), it is not particularly useful. It is left
// unimplemented until someone actually needs it.
func (d *anonDentry) InotifyWithParent(events, cookie uint32, et EventType) {}
// Watches implements DentryImpl.Watches.
//
// TODO(gvisor.dev/issue/1479): Implement inotify.
func (d *anonDentry) Watches() *Watches {
return nil
}
// OnZeroWatches implements Dentry.OnZeroWatches.
//
// TODO(gvisor.dev/issue/1479): Implement inotify.
func (d *anonDentry) OnZeroWatches() {}
-2
View File
@@ -524,8 +524,6 @@ type FilesystemImpl interface {
//
// Preconditions: vd.Mount().Filesystem().Impl() == this FilesystemImpl.
PrependPath(ctx context.Context, vfsroot, vd VirtualDentry, b *fspath.Builder) error
// TODO(gvisor.dev/issue/1479): inotify_add_watch()
}
// PrependPathAtVFSRootError is returned by implementations of
+20 -22
View File
@@ -120,6 +120,7 @@ func NewInotifyFD(ctx context.Context, vfsObj *VirtualFilesystem, flags uint32)
// watches and frees all resources for an inotify instance.
func (i *Inotify) Release() {
var ds []*Dentry
// We need to hold i.mu to avoid a race with concurrent calls to
// Inotify.handleDeletion from Watches. There's no risk of Watches
// accessing this Inotify after the destructor ends, because we remove all
@@ -307,19 +308,6 @@ func (i *Inotify) nextWatchIDLocked() int32 {
return i.nextWatchMinusOne
}
// handleDeletion handles the deletion of the target of watch w. It removes w
// from i.watches and a watch removal event is generated.
func (i *Inotify) handleDeletion(w *Watch) {
i.mu.Lock()
_, found := i.watches[w.wd]
delete(i.watches, w.wd)
i.mu.Unlock()
if found {
i.queueEvent(newEvent(w.wd, "", linux.IN_IGNORED, 0))
}
}
// AddWatch constructs a new inotify watch and adds it to the target. It
// returns the watch descriptor returned by inotify_add_watch(2).
//
@@ -484,8 +472,9 @@ func (w *Watches) Notify(name string, events, cookie uint32, et EventType, unlin
w.mu.RUnlock()
}
// HandleDeletion is called when the watch target is destroyed to emit
// the appropriate events.
// HandleDeletion is called when the watch target is destroyed. Clear the
// watch set, detach watches from the inotify instances they belong to, and
// generate the appropriate events.
func (w *Watches) HandleDeletion() {
w.Notify("", linux.IN_DELETE_SELF, 0, InodeEvent, true /* unlinked */)
@@ -505,9 +494,23 @@ func (w *Watches) HandleDeletion() {
w.ws = nil
w.mu.Unlock()
// Remove each watch from its owner's watch set, and generate a corresponding
// watch removal event.
for _, watch := range ws {
// TODO(gvisor.dev/issue/1479): consider refactoring this.
watch.handleDeletion()
i := watch.owner
i.mu.Lock()
_, found := i.watches[watch.wd]
delete(i.watches, watch.wd)
// Release mutex before notifying waiters because we don't control what
// they can do.
i.mu.Unlock()
// If watch was not found, it was removed from the inotify instance before
// we could get to it, in which case we should not generate an event.
if found {
i.queueEvent(newEvent(watch.wd, "", linux.IN_IGNORED, 0))
}
}
}
@@ -559,11 +562,6 @@ func (w *Watch) Notify(name string, events uint32, cookie uint32) {
w.owner.queueEvent(newEvent(w.wd, name, matchedEvents, cookie))
}
// handleDeletion handles the deletion of w's target.
func (w *Watch) handleDeletion() {
w.owner.handleDeletion(w)
}
// Event represents a struct inotify_event from linux.
//
// +stateify savable