Repository: google/gvisor
File: runsc/specutils/specutils.go (Go)

Code before:
		}
		// Should we skip this capability?
		if _, ok := skipSet[c]; ok {
			continue
		}
		caps = append(caps, c)
	}
	return auth.CapabilitySetOfMany(caps), nil
}

// IsGoferMount returns true if the given mount can be mounted as an external
// gofer.
func IsGoferMount(m specs.Mount) bool {
	MaybeConvertToBindMount(&m)
	return m.Type == "bind" && m.Source != ""
}

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

// MaybeConvertToBindMount converts mount type to "bind" in case any of the
// mount options are either "bind" or "rbind" as required by the OCI spec.
//
// "For bind mounts (when options include either bind or rbind), the type is a
// dummy, often "none" (not listed in /proc/filesystems)."
func MaybeConvertToBindMount(m *specs.Mount) {
	if m.Type == "bind" {
		return
	}
	for _, opt := range m.Options {
		if opt == "bind" || opt == "rbind" {
			m.Type = "bind"
			return
		}
	}
}

// WaitForReady waits for a process to become ready. The process is ready when
// the 'ready' function returns true. It continues to wait if 'ready' returns
// false. It returns error on timeout, if the process stops or if 'ready' fails.
func WaitForReady(pid int, timeout time.Duration, ready func() (bool, error)) error {
	b := backoff.NewExponentialBackOff()
	b.InitialInterval = 1 * time.Millisecond
	b.MaxInterval = 1 * time.Second
	b.MaxElapsedTime = timeout

	op := func() error {
		if ok, err := ready(); err != nil {
			return backoff.Permanent(err)

Review comment (refactor):
I don't think specutils should take a dependency on fsimpl/erofs for this `== "erofs"` check. `specutils` has very limited dependencies on the sentry. erofs pulls in a lot of stuff.

Similar to the duplication of the string "bind" above on line 503 and in https://github.com/google/gvisor/blob/2773a02ea358c4537de8c4836a567f74f9719d94/runsc/boot/vfs.go#L70, we should just have `m.Type == "erofs"` and live with the duplication. It's not a big deal. In the future maybe we can move all these filesystem constants to a smaller high level package and refactor.

Code after:
		// Should we skip this capability?
		if _, ok := skipSet[c]; ok {
			continue
		}
		caps = append(caps, c)
	}
	return auth.CapabilitySetOfMany(caps), nil
}

// IsGoferMount returns true if the given mount can be mounted as an external
// gofer.
func IsGoferMount(m specs.Mount) bool {
	MaybeConvertToBindMount(&m)
	return m.Type == "bind" && m.Source != ""
}

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

// HasMountConfig returns true if the given mount has an associated GoferMountConf.
func HasMountConfig(m specs.Mount) bool {
	return IsGoferMount(m) || IsErofsMount(m)
}

// MaybeConvertToBindMount converts mount type to "bind" in case any of the
// mount options are either "bind" or "rbind" as required by the OCI spec.
//
// "For bind mounts (when options include either bind or rbind), the type is a
// dummy, often "none" (not listed in /proc/filesystems)."
func MaybeConvertToBindMount(m *specs.Mount) {
	if m.Type == "bind" {
		return
	}
	for _, opt := range m.Options {
		if opt == "bind" || opt == "rbind" {
			m.Type = "bind"
			return
		}
	}
}

// WaitForReady waits for a process to become ready. The process is ready when
// the 'ready' function returns true. It continues to wait if 'ready' returns
// false. It returns error on timeout, if the process stops or if 'ready' fails.
func WaitForReady(pid int, timeout time.Duration, ready func() (bool, error)) error {
	b := backoff.NewExponentialBackOff()
	b.InitialInterval = 1 * time.Millisecond
	b.MaxInterval = 1 * time.Second
	b.MaxElapsedTime = timeout