From d4605dafaa9c326a5cf24c28d0c1efe6c9997f49 Mon Sep 17 00:00:00 2001
From: holyfei <yangfeiyu20092010@163.com>
Date: Sat, 21 Aug 2021 17:08:46 +0800
Subject: [PATCH] kata-containers: support with iSulad

reason: support with iSulad

Signed-off-by: holyfei <yangfeiyu20092010@163.com>
---
 src/agent/rustjail/src/cgroups/fs/mod.rs      |  2 +-
 src/runtime/containerd-shim-v2/container.go   |  9 +++
 src/runtime/containerd-shim-v2/service.go     | 55 +++++++++++++++++++
 src/runtime/containerd-shim-v2/start.go       | 10 ++++
 .../containerd/runtime/v2/shim/shim.go        |  8 ++-
 5 files changed, 81 insertions(+), 3 deletions(-)

diff --git a/src/agent/rustjail/src/cgroups/fs/mod.rs b/src/agent/rustjail/src/cgroups/fs/mod.rs
index 7f41cb4..6c3bb32 100644
--- a/src/agent/rustjail/src/cgroups/fs/mod.rs
+++ b/src/agent/rustjail/src/cgroups/fs/mod.rs
@@ -369,7 +369,7 @@ fn set_memory_resources(cg: &cgroups::Cgroup, memory: &LinuxMemory, update: bool
     if let Some(swappiness) = memory.swappiness {
         if (0..=100).contains(&swappiness) {
             mem_controller.set_swappiness(swappiness as u64)?;
-        } else {
+        } else if swappiness != -1 {
             return Err(anyhow!(
                 "invalid value:{}. valid memory swappiness range is 0-100",
                 swappiness
diff --git a/src/runtime/containerd-shim-v2/container.go b/src/runtime/containerd-shim-v2/container.go
index faea0e2..d563888 100644
--- a/src/runtime/containerd-shim-v2/container.go
+++ b/src/runtime/containerd-shim-v2/container.go
@@ -7,10 +7,13 @@ package containerdshim
 
 import (
 	"io"
+	"os"
+	"path"
 	"time"
 
 	"github.com/containerd/containerd/api/types/task"
 	"github.com/containerd/containerd/errdefs"
+	cdshim "github.com/containerd/containerd/runtime/v2/shim"
 	taskAPI "github.com/containerd/containerd/runtime/v2/task"
 	"github.com/opencontainers/runtime-spec/specs-go"
 
@@ -37,6 +40,8 @@ type container struct {
 	status      task.Status
 	terminal    bool
 	mounted     bool
+	exitFifo    string
+	exitFd      *os.File
 }
 
 func newContainer(s *service, r *taskAPI.CreateTaskRequest, containerType vc.ContainerType, spec *specs.Spec, mounted bool) (*container, error) {
@@ -49,6 +54,9 @@ func newContainer(s *service, r *taskAPI.CreateTaskRequest, containerType vc.Con
 		spec = &specs.Spec{}
 	}
 
+	dir := os.Getenv(cdshim.ExitFifoDir)
+	exitFifo := path.Join(dir, r.ID, exitFifoName)
+
 	c := &container{
 		s:           s,
 		spec:        spec,
@@ -65,6 +73,7 @@ func newContainer(s *service, r *taskAPI.CreateTaskRequest, containerType vc.Con
 		exitCh:      make(chan uint32, 1),
 		stdinCloser: make(chan struct{}),
 		mounted:     mounted,
+		exitFifo:    exitFifo,
 	}
 	return c, nil
 }
diff --git a/src/runtime/containerd-shim-v2/service.go b/src/runtime/containerd-shim-v2/service.go
index 1003f8e..e13283c 100644
--- a/src/runtime/containerd-shim-v2/service.go
+++ b/src/runtime/containerd-shim-v2/service.go
@@ -6,13 +6,16 @@
 package containerdshim
 
 import (
+	"bytes"
 	"context"
+	"encoding/binary"
 	"io/ioutil"
 	"os"
 	sysexec "os/exec"
 	"sync"
 	"syscall"
 	"time"
+	"unsafe"
 
 	eventstypes "github.com/containerd/containerd/api/events"
 	"github.com/containerd/containerd/api/types/task"
@@ -51,6 +54,8 @@ const (
 	// A time span used to wait for publish a containerd event,
 	// once it costs a longer time than timeOut, it will be canceld.
 	timeOut = 5 * time.Second
+
+	exitFifoName = "exit_fifo"
 )
 
 var (
@@ -1019,6 +1024,10 @@ func (s *service) Wait(ctx context.Context, r *taskAPI.WaitRequest) (_ *taskAPI.
 func (s *service) processExits() {
 	for e := range s.ec {
 		s.checkProcesses(e)
+
+		if os.Getenv(cdshim.ExitFifoDir) != "" {
+			s.closeExitFifo(e)
+		}
 	}
 }
 
@@ -1070,3 +1079,49 @@ func (s *service) getContainerStatus(containerID string) (task.Status, error) {
 
 	return status, nil
 }
+
+func isBigEndian() (ret bool) {
+	i := int(0x1)
+	bs := (*[int(unsafe.Sizeof(i))]byte)(unsafe.Pointer(&i))
+	return bs[0] == 0
+}
+
+func (s *service) closeExitFifo(e exit) {
+	if e.execid != "" {
+		// not a container, no need to close exit fifo
+		return
+	}
+
+	var ret uint32
+	var nativeEndian binary.ByteOrder
+
+	s.mu.Lock()
+	c, err := s.getContainer(e.id)
+	s.mu.Unlock()
+
+	if err != nil {
+		logrus.WithError(err).Errorf("Process container:%v exit fifo failed", e.id)
+		return
+	}
+
+	ret = <-c.exitCh
+	// refill the exitCh with the container process's exit code in case
+	// there were other waits on this process.
+	c.exitCh <- ret
+
+	if isBigEndian() {
+		nativeEndian = binary.BigEndian
+	} else {
+		nativeEndian = binary.LittleEndian
+	}
+
+	bytesBuffer := bytes.NewBuffer([]byte{})
+	binary.Write(bytesBuffer, nativeEndian, &ret)
+
+	_, err = c.exitFd.Write(bytesBuffer.Bytes())
+	if err != nil {
+		logrus.WithError(err).Error("write exit fifo failed")
+	}
+
+	c.exitFd.Close()
+}
diff --git a/src/runtime/containerd-shim-v2/start.go b/src/runtime/containerd-shim-v2/start.go
index 72420e4..e89dc48 100644
--- a/src/runtime/containerd-shim-v2/start.go
+++ b/src/runtime/containerd-shim-v2/start.go
@@ -8,8 +8,11 @@ package containerdshim
 import (
 	"context"
 	"fmt"
+	"golang.org/x/sys/unix"
+	"os"
 
 	"github.com/containerd/containerd/api/types/task"
+	cdshim "github.com/containerd/containerd/runtime/v2/shim"
 	"github.com/kata-containers/kata-containers/src/runtime/pkg/katautils"
 )
 
@@ -59,6 +62,13 @@ func startContainer(ctx context.Context, s *service, c *container) error {
 
 	c.status = task.StatusRunning
 
+	if os.Getenv(cdshim.ExitFifoDir) != "" {
+		c.exitFd, err = os.OpenFile(c.exitFifo, unix.O_WRONLY|unix.O_NONBLOCK|unix.O_CLOEXEC, 0)
+		if err != nil {
+			return err
+		}
+	}
+
 	stdin, stdout, stderr, err := s.sandbox.IOStream(c.id, c.id)
 	if err != nil {
 		return err
diff --git a/src/runtime/vendor/github.com/containerd/containerd/runtime/v2/shim/shim.go b/src/runtime/vendor/github.com/containerd/containerd/runtime/v2/shim/shim.go
index d60d496..946c386 100644
--- a/src/runtime/vendor/github.com/containerd/containerd/runtime/v2/shim/shim.go
+++ b/src/runtime/vendor/github.com/containerd/containerd/runtime/v2/shim/shim.go
@@ -84,6 +84,8 @@ var (
 	action               string
 )
 
+var ExitFifoDir = "EXIT_FIFO_DIR"
+
 func parseFlags() {
 	flag.BoolVar(&debugFlag, "debug", false, "enable debug output in logs")
 	flag.StringVar(&namespaceFlag, "namespace", "", "namespace that owns the shim")
@@ -198,8 +200,10 @@ func run(id string, initFunc Init, config Config) error {
 		}
 		return nil
 	default:
-		if err := setLogger(ctx, idFlag); err != nil {
-			return err
+		if os.Getenv("EXIT_FIFO_DIR") == "" {
+			if err := setLogger(ctx, idFlag); err != nil {
+				return err
+			}
 		}
 		client := NewShimClient(ctx, service, signals)
 		return client.Serve()
-- 
2.23.0

