frontendFD implements vfs.FileDescriptionImpl for /dev/nvidia# and dev/nvidiactl. +stateify savable
| 91 | // |
| 92 | // +stateify savable |
| 93 | type frontendFD struct { |
| 94 | vfsfd vfs.FileDescription |
| 95 | vfs.FileDescriptionDefaultImpl |
| 96 | vfs.DentryMetadataFileDescriptionImpl |
| 97 | vfs.NoLockFD |
| 98 | memmap.MappableNoTrackMappings |
| 99 | |
| 100 | dev *frontendDevice |
| 101 | containerName string |
| 102 | hostFD int32 |
| 103 | memmapFile frontendFDMemmapFile |
| 104 | |
| 105 | // The driver's implementation of poll() for these files, |
| 106 | // kernel-open/nvidia/nv.c:nvidia_poll(), unsets |
| 107 | // nv_linux_file_private_t::dataless_event_pending if it's set. This makes |
| 108 | // notifications from dataless_event_pending edge-triggered; a host poll() |
| 109 | // or epoll_wait() that returns the notification consumes it, preventing |
| 110 | // future calls to poll() or epoll_wait() from observing the same |
| 111 | // notification again. |
| 112 | // |
| 113 | // This is problematic in gVisor: fdnotifier, which epoll_wait()s on an |
| 114 | // epoll instance that includes our hostFD, will forward notifications to |
| 115 | // registered waiters, but this typically only wakes up blocked task |
| 116 | // goroutines which will later call vfs.FileDescription.Readiness() to get |
| 117 | // the FD's most up-to-date state. If our implementation of Readiness() |
| 118 | // just polls the underlying host FD, it will no longer observe the |
| 119 | // consumed notification. |
| 120 | // |
| 121 | // To work around this, intercept all events from fdnotifier and cache them |
| 122 | // for the first following call to Readiness(), essentially replicating the |
| 123 | // driver's behavior. |
| 124 | internalQueue waiter.Queue |
| 125 | internalEntry waiter.Entry |
| 126 | cachedEvents atomicbitops.Uint64 |
| 127 | appQueue waiter.Queue |
| 128 | |
| 129 | // clients are handles of clients owned by this frontendFD. clients is |
| 130 | // protected by dev.nvp.clientsMu. |
| 131 | clients map[*rootClient]struct{} |
| 132 | } |
| 133 | |
| 134 | // Release implements vfs.FileDescriptionImpl.Release. |
| 135 | func (fd *frontendFD) Release(ctx context.Context) { |
nothing calls this directly
no outgoing calls
no test coverage detected