mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Fix runsc association of gofers and FDs on VFS2.
Updates #1487 PiperOrigin-RevId: 311443628
This commit is contained in:
+14
-8
@@ -770,14 +770,8 @@ func (c *containerMounter) getMountNameAndOptions(conf *Config, m specs.Mount) (
|
||||
useOverlay bool
|
||||
)
|
||||
|
||||
for _, opt := range m.Options {
|
||||
// When options include either "bind" or "rbind", this behaves as
|
||||
// bind mount even if the mount type is equal to a filesystem supported
|
||||
// on runsc.
|
||||
if opt == "bind" || opt == "rbind" {
|
||||
m.Type = bind
|
||||
break
|
||||
}
|
||||
if isBindMount(m) {
|
||||
m.Type = bind
|
||||
}
|
||||
|
||||
switch m.Type {
|
||||
@@ -807,6 +801,18 @@ func (c *containerMounter) getMountNameAndOptions(conf *Config, m specs.Mount) (
|
||||
return fsName, opts, useOverlay, nil
|
||||
}
|
||||
|
||||
func isBindMount(m specs.Mount) bool {
|
||||
for _, opt := range m.Options {
|
||||
// When options include either "bind" or "rbind", this behaves as
|
||||
// bind mount even if the mount type is equal to a filesystem supported
|
||||
// on runsc.
|
||||
if opt == "bind" || opt == "rbind" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (c *containerMounter) getMountAccessType(mount specs.Mount) FileAccessType {
|
||||
if hint := c.hints.findMount(mount); hint != nil {
|
||||
return hint.fileAccessType()
|
||||
|
||||
+81
-9
@@ -203,28 +203,61 @@ func (c *containerMounter) createMountNamespaceVFS2(ctx context.Context, conf *C
|
||||
}
|
||||
|
||||
func (c *containerMounter) mountSubmountsVFS2(ctx context.Context, conf *Config, mns *vfs.MountNamespace, creds *auth.Credentials) error {
|
||||
c.prepareMountsVFS2()
|
||||
mounts, err := c.prepareMountsVFS2()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, submount := range c.mounts {
|
||||
for i := range mounts {
|
||||
submount := &mounts[i]
|
||||
log.Debugf("Mounting %q to %q, type: %s, options: %s", submount.Source, submount.Destination, submount.Type, submount.Options)
|
||||
if err := c.mountSubmountVFS2(ctx, conf, mns, creds, &submount); err != nil {
|
||||
if err := c.mountSubmountVFS2(ctx, conf, mns, creds, submount); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(gvisor.dev/issue/1487): implement mountTmp from fs.go.
|
||||
|
||||
return c.checkDispenser()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *containerMounter) prepareMountsVFS2() {
|
||||
type mountAndFD struct {
|
||||
specs.Mount
|
||||
fd int
|
||||
}
|
||||
|
||||
func (c *containerMounter) prepareMountsVFS2() ([]mountAndFD, error) {
|
||||
// Associate bind mounts with their FDs before sorting since there is an
|
||||
// undocumented assumption that FDs are dispensed in the order in which
|
||||
// they are required by mounts.
|
||||
var mounts []mountAndFD
|
||||
for _, m := range c.mounts {
|
||||
fd := -1
|
||||
// Only bind mounts use host FDs; see
|
||||
// containerMounter.getMountNameAndOptionsVFS2.
|
||||
if m.Type == bind || isBindMount(m) {
|
||||
fd = c.fds.remove()
|
||||
}
|
||||
mounts = append(mounts, mountAndFD{
|
||||
Mount: m,
|
||||
fd: fd,
|
||||
})
|
||||
}
|
||||
if err := c.checkDispenser(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Sort the mounts so that we don't place children before parents.
|
||||
sort.Slice(c.mounts, func(i, j int) bool { return len(c.mounts[i].Destination) < len(c.mounts[j].Destination) })
|
||||
sort.Slice(mounts, func(i, j int) bool {
|
||||
return len(mounts[i].Destination) < len(mounts[j].Destination)
|
||||
})
|
||||
|
||||
return mounts, nil
|
||||
}
|
||||
|
||||
// TODO(gvisor.dev/issue/1487): Implement submount options similar to the VFS1
|
||||
// version.
|
||||
func (c *containerMounter) mountSubmountVFS2(ctx context.Context, conf *Config, mns *vfs.MountNamespace, creds *auth.Credentials, submount *specs.Mount) error {
|
||||
// version.
|
||||
func (c *containerMounter) mountSubmountVFS2(ctx context.Context, conf *Config, mns *vfs.MountNamespace, creds *auth.Credentials, submount *mountAndFD) error {
|
||||
root := mns.Root()
|
||||
defer root.DecRef()
|
||||
target := &vfs.PathOperation{
|
||||
@@ -233,7 +266,7 @@ func (c *containerMounter) mountSubmountVFS2(ctx context.Context, conf *Config,
|
||||
Path: fspath.Parse(submount.Destination),
|
||||
}
|
||||
|
||||
fsName, options, useOverlay, err := c.getMountNameAndOptions(conf, *submount)
|
||||
fsName, options, useOverlay, err := c.getMountNameAndOptionsVFS2(conf, submount)
|
||||
if err != nil {
|
||||
return fmt.Errorf("mountOptions failed: %w", err)
|
||||
}
|
||||
@@ -263,6 +296,45 @@ func (c *containerMounter) mountSubmountVFS2(ctx context.Context, conf *Config,
|
||||
return nil
|
||||
}
|
||||
|
||||
// getMountNameAndOptionsVFS2 retrieves the fsName, opts, and useOverlay values
|
||||
// used for mounts.
|
||||
func (c *containerMounter) getMountNameAndOptionsVFS2(conf *Config, m *mountAndFD) (string, []string, bool, error) {
|
||||
var (
|
||||
fsName string
|
||||
opts []string
|
||||
useOverlay bool
|
||||
)
|
||||
|
||||
if isBindMount(m.Mount) {
|
||||
m.Type = bind
|
||||
}
|
||||
|
||||
switch m.Type {
|
||||
case devpts.Name, devtmpfs.Name, proc.Name, sys.Name:
|
||||
fsName = m.Type
|
||||
case nonefs:
|
||||
fsName = sys.Name
|
||||
case tmpfs.Name:
|
||||
fsName = m.Type
|
||||
|
||||
var err error
|
||||
opts, err = parseAndFilterOptions(m.Options, tmpfsAllowedOptions...)
|
||||
if err != nil {
|
||||
return "", nil, false, err
|
||||
}
|
||||
|
||||
case bind:
|
||||
fsName = gofer.Name
|
||||
opts = p9MountOptions(m.fd, c.getMountAccessType(m.Mount), true /* vfs2 */)
|
||||
// If configured, add overlay to all writable mounts.
|
||||
useOverlay = conf.Overlay && !mountFlags(m.Options).ReadOnly
|
||||
|
||||
default:
|
||||
log.Warningf("ignoring unknown filesystem type %q", m.Type)
|
||||
}
|
||||
return fsName, opts, useOverlay, nil
|
||||
}
|
||||
|
||||
func (c *containerMounter) makeSyntheticMount(ctx context.Context, currentPath string, root vfs.VirtualDentry, creds *auth.Credentials) error {
|
||||
target := &vfs.PathOperation{
|
||||
Root: root,
|
||||
|
||||
Reference in New Issue
Block a user