diff --git a/components/ws-daemon/pkg/iws/iws.go b/components/ws-daemon/pkg/iws/iws.go index 3a5c0ff7e97465..af30f28a286cef 100644 --- a/components/ws-daemon/pkg/iws/iws.go +++ b/components/ws-daemon/pkg/iws/iws.go @@ -709,15 +709,15 @@ func (wbs *InWorkspaceServiceServer) MountSysfs(ctx context.Context, req *api.Mo func (wbs *InWorkspaceServiceServer) MountNfs(ctx context.Context, req *api.MountNfsRequest) (resp *api.MountNfsResponse, err error) { var ( - reqPID = req.Pid - nfsPID uint64 + reqPID = req.Pid + supervisorPID uint64 ) defer func() { if err == nil { return } - log.WithError(err).WithFields(wbs.Session.OWI()).WithField("procPID", nfsPID).WithField("reqPID", reqPID).WithFields(wbs.Session.OWI()).Error("cannot mount nfs") + log.WithError(err).WithFields(wbs.Session.OWI()).WithField("procPID", supervisorPID).WithField("reqPID", reqPID).WithFields(wbs.Session.OWI()).Error("cannot mount nfs") if _, ok := status.FromError(err); !ok { err = status.Error(codes.Internal, "cannot mount nfs") } @@ -737,9 +737,9 @@ func (wbs *InWorkspaceServiceServer) MountNfs(ctx context.Context, req *api.Moun return nil, xerrors.Errorf("cannot find container PID for containerID %v: %w", wscontainerID, err) } - nfsPID, err = wbs.Uidmapper.findHostPID(containerPID, uint64(req.Pid)) + supervisorPID, err = wbs.Uidmapper.findSupervisorPID(containerPID) if err != nil { - return nil, xerrors.Errorf("cannot map in-container PID %d (container PID: %d): %w", req.Pid, containerPID, err) + return nil, xerrors.Errorf("cannot map supervisor PID %d (container PID: %d): %w", req.Pid, containerPID, err) } nodeStaging, err := os.MkdirTemp("", "nfs-staging") @@ -774,7 +774,7 @@ func (wbs *InWorkspaceServiceServer) MountNfs(ctx context.Context, req *api.Moun } } - err = moveMount(wbs.Session.InstanceID, int(nfsPID), nodeStaging, req.Target) + err = moveMount(wbs.Session.InstanceID, int(supervisorPID), nodeStaging, req.Target) if err != nil { return nil, err } diff --git a/components/ws-daemon/pkg/iws/uidmap.go b/components/ws-daemon/pkg/iws/uidmap.go index 04bf7616b1629a..f3b403ccb23f64 100644 --- a/components/ws-daemon/pkg/iws/uidmap.go +++ b/components/ws-daemon/pkg/iws/uidmap.go @@ -174,7 +174,6 @@ func (m *Uidmapper) findHostPID(containerPID, inContainerPID uint64) (uint64, er seen[p] = struct{}{} p = filepath.Join(m.Config.ProcLocation, p) - pid, nspid, err := readStatusFile(filepath.Join(p, "status")) if err != nil { log.WithField("file", filepath.Join(p, "status")).WithError(err).Error("findHostPID: cannot read PID file") @@ -201,6 +200,54 @@ func (m *Uidmapper) findHostPID(containerPID, inContainerPID uint64) (uint64, er } } +func (m *Uidmapper) findSupervisorPID(containerPID uint64) (uint64, error) { + paths := []string{fmt.Sprint(containerPID)} + seen := make(map[string]struct{}) + + for { + if len(paths) == 0 { + return 0, xerrors.Errorf("cannot find supervisor PID for container %v", containerPID) + } + + p := paths[0] + paths = paths[1:] + + if _, ok := seen[p]; ok { + continue + } + seen[p] = struct{}{} + + procPath := filepath.Join(m.Config.ProcLocation, p) + cmdline, err := os.ReadFile(filepath.Join(procPath, "cmdline")) + if err != nil { + log.WithField("file", filepath.Join(procPath, "cmdline")).WithError(err).Error("cannot read cmdline") + continue + } + + if strings.HasPrefix(string(cmdline), "supervisor") { + pid, err := strconv.ParseUint(p, 10, 64) + if err != nil { + return 0, err + } + + return pid, nil + } + + taskfn := filepath.Join(procPath, "task") + tasks, err := os.ReadDir(taskfn) + if err != nil { + continue + } + for _, task := range tasks { + cldrn, err := os.ReadFile(filepath.Join(taskfn, task.Name(), "children")) + if err != nil { + continue + } + paths = append(paths, strings.Fields(string(cldrn))...) + } + } +} + func readStatusFile(fn string) (pid uint64, nspid []uint64, err error) { f, err := os.Open(fn) if err != nil {