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
This commit is contained in:
Jamie Liu
2020-01-24 12:54:39 -08:00
committed by gVisor bot
parent fb80979e3f
commit d135b5abf6
2 changed files with 43 additions and 4 deletions
+29
View File
@@ -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
}
}
+14 -4
View File
@@ -80,6 +80,14 @@ type VirtualFilesystem struct {
devicesMu sync.RWMutex
devices map[devTuple]*registeredDevice
// anonBlockDevMinor contains all allocated anonymous block device minor
// numbers. anonBlockDevMinorNext is a lower bound for the smallest
// unallocated anonymous block device number. anonBlockDevMinorNext and
// anonBlockDevMinor are protected by anonBlockDevMinorMu.
anonBlockDevMinorMu sync.Mutex
anonBlockDevMinorNext uint32
anonBlockDevMinor map[uint32]struct{}
// fsTypes contains all registered FilesystemTypes. fsTypes is protected by
// fsTypesMu.
fsTypesMu sync.RWMutex
@@ -94,10 +102,12 @@ type VirtualFilesystem struct {
// New returns a new VirtualFilesystem with no mounts or FilesystemTypes.
func New() *VirtualFilesystem {
vfs := &VirtualFilesystem{
mountpoints: make(map[*Dentry]map[*Mount]struct{}),
devices: make(map[devTuple]*registeredDevice),
fsTypes: make(map[string]*registeredFilesystemType),
filesystems: make(map[*Filesystem]struct{}),
mountpoints: make(map[*Dentry]map[*Mount]struct{}),
devices: make(map[devTuple]*registeredDevice),
anonBlockDevMinorNext: 1,
anonBlockDevMinor: make(map[uint32]struct{}),
fsTypes: make(map[string]*registeredFilesystemType),
filesystems: make(map[*Filesystem]struct{}),
}
vfs.mounts.Init()
return vfs