Skip to content

sandboxsetup: export gofer mount setup functions for reuse#12923

Open
shayonj wants to merge 1 commit intogoogle:masterfrom
shayonj:s/export-gofer-mount-setup
Open

sandboxsetup: export gofer mount setup functions for reuse#12923
shayonj wants to merge 1 commit intogoogle:masterfrom
shayonj:s/export-gofer-mount-setup

Conversation

@shayonj
Copy link
Copy Markdown
Contributor

@shayonj shayonj commented Apr 11, 2026

Building a custom gVisor gofer that serves LisaFS-backed volumes requires
duplicating unexported mount setup code from runsc/cmd/gofer.go.
These are Gofer struct methods (setupRootFS, setupMounts, setupDev,
resolveMounts, writeMounts) that must be manually re-synced on every gVisor
version bump.

This is a continuation of the work in #12902 which exported standalone utility
functions. The remaining methods only access struct fields for mount
configurations, device FDs, and mount FDs that can be passed as explicit
parameters.

To avoid importing the heavy runsc/boot package from sandboxsetup, this change
moves GoferMountConf and related types from runsc/boot to runsc/specutils
(replacing the erofs.Name import with a hardcoded "erofs" string, consistent
with specutils.IsErofsMount). The boot package re-exports these via type
aliases for backward compatibility. sandboxsetup now uses the concrete
specutils.GoferMountConf type directly instead of an interface.

Also introduces a MountOpener callback to avoid importing runsc/container.

And fixes a nil pointer dereference in setupMounts where srcFile.Close()
was called unconditionally, but srcFile is nil when unix.Access succeeds.

@shayonj
Copy link
Copy Markdown
Contributor Author

shayonj commented Apr 11, 2026

cc @EtiennePerot / @ayushr2 🙏🏾

Comment on lines +44 to +50
// MountConf abstracts gofer mount configuration. This avoids a dependency
// on the heavy runsc/boot package. boot.GoferMountConf satisfies this
// interface.
type MountConf interface {
ShouldUseLisafs() bool
ShouldUseOverlayfs() bool
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm I wonder if boot.GoferMountConf should be refactored out to a lighter package. Maybe specutils is a good place to hold such configuration.

The issue with interfaces is that when you convert a simple struct like boot.GoferMountConf to MountConf interface, Go runtime will heap allocate it. I think we're OK passing boot.GoferMountConf around by value and copying it, it is quite tiny (2 bytes + string).

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you'd need to move the entirety of runsc/boot/gofer_conf.go. It has a dependency on fsimpl/erofs, because it wants to use erofs.Name. It is OK to do that in boot package but when this is refactored, you should not carry forward that dependency. This is similar to what specutils already does (just hard-codes the string "erofs":

// IsErofsMount returns true if the given mount can be mounted as EROFS.
func IsErofsMount(m specs.Mount) bool {
return m.Type == "erofs"
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Absolutely, makes sense. I did noticed the erofs.Name import but didn't search beyond that to see if there were any more. The interface was a sort of a deliberate choice to avoid the boot import without touching existing import sites, but you're right that moving the concrete type to a lighter package is cleaner as it avoids the interface indirection entirely and sandboxsetup already depends on specutils.

Updated

Building a custom gVisor gofer that serves LisaFS-backed volumes requires
duplicating unexported mount setup code from runsc/cmd/gofer.go.
These are Gofer struct methods (setupRootFS, setupMounts, setupDev,
resolveMounts, writeMounts) that must be manually re-synced on every gVisor
version bump.

This is a continuation of the work in google#12902 which exported standalone utility
functions. The remaining methods only access struct fields for mount
configurations, device FDs, and mount FDs that can be passed as explicit
parameters.

To avoid importing the heavy runsc/boot package from sandboxsetup, this change
moves GoferMountConf and related types from runsc/boot to runsc/specutils
(replacing the erofs.Name import with a hardcoded "erofs" string, consistent
with specutils.IsErofsMount). The boot package re-exports these via type
aliases for backward compatibility. sandboxsetup now uses the concrete
specutils.GoferMountConf type directly instead of an interface.

Also introduces a MountOpener callback to avoid importing runsc/container.

Also fixes a nil pointer dereference in setupMounts where srcFile.Close()
was called unconditionally, but srcFile is nil when unix.Access succeeds.
@shayonj shayonj force-pushed the s/export-gofer-mount-setup branch from 5f3ca41 to efe3efd Compare April 13, 2026 22:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants