diff options
author | Jamie Liu <jamieliu@google.com> | 2020-01-24 12:53:29 -0800 |
---|---|---|
committer | gVisor bot <gvisor-bot@google.com> | 2020-01-24 12:54:39 -0800 |
commit | d135b5abf6eafa92d2745dc98d48ef39d2f90e75 (patch) | |
tree | 6508a91a64e0b07739c31ed366c59e988cfc79d7 /pkg/sentry/vfs/device.go | |
parent | fb80979e3fe2614414d2d23c27e41bdb9e7c8541 (diff) |
Add anonymous device number allocation to VFS2.
Note that in VFS2, filesystem device numbers are per-vfs.FilesystemImpl rather
than global, avoiding the need for a "registry" type to handle save/restore.
(This is more consistent with Linux anyway: compare e.g.
mm/shmem.c:shmem_mount() => fs/super.c:mount_nodev() => (indirectly)
set_anon_super().)
PiperOrigin-RevId: 291425193
Diffstat (limited to 'pkg/sentry/vfs/device.go')
-rw-r--r-- | pkg/sentry/vfs/device.go | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/pkg/sentry/vfs/device.go b/pkg/sentry/vfs/device.go index cb672e36f..9f9d6e783 100644 --- a/pkg/sentry/vfs/device.go +++ b/pkg/sentry/vfs/device.go @@ -98,3 +98,32 @@ func (vfs *VirtualFilesystem) OpenDeviceSpecialFile(ctx context.Context, mnt *Mo } return rd.dev.Open(ctx, mnt, d, *opts) } + +// GetAnonBlockDevMinor allocates and returns an unused minor device number for +// an "anonymous" block device with major number 0. +func (vfs *VirtualFilesystem) GetAnonBlockDevMinor() (uint32, error) { + vfs.anonBlockDevMinorMu.Lock() + defer vfs.anonBlockDevMinorMu.Unlock() + minor := vfs.anonBlockDevMinorNext + const maxDevMinor = (1 << 20) - 1 + for minor < maxDevMinor { + if _, ok := vfs.anonBlockDevMinor[minor]; !ok { + vfs.anonBlockDevMinor[minor] = struct{}{} + vfs.anonBlockDevMinorNext = minor + 1 + return minor, nil + } + minor++ + } + return 0, syserror.EMFILE +} + +// PutAnonBlockDevMinor deallocates a minor device number returned by a +// previous call to GetAnonBlockDevMinor. +func (vfs *VirtualFilesystem) PutAnonBlockDevMinor(minor uint32) { + vfs.anonBlockDevMinorMu.Lock() + defer vfs.anonBlockDevMinorMu.Unlock() + delete(vfs.anonBlockDevMinor, minor) + if minor < vfs.anonBlockDevMinorNext { + vfs.anonBlockDevMinorNext = minor + } +} |