Merge pull request #2426 from kolyshkin/mem-swap-unlim

Fix some cases of swap setting
diff --git a/libcontainer/cgroups/fs/memory.go b/libcontainer/cgroups/fs/memory.go
index 39809ef..9508769 100644
--- a/libcontainer/cgroups/fs/memory.go
+++ b/libcontainer/cgroups/fs/memory.go
@@ -74,9 +74,9 @@
 }
 
 func setMemoryAndSwap(path string, cgroup *configs.Cgroup) error {
-	// If the memory update is set to -1 we should also
-	// set swap to -1, it means unlimited memory.
-	if cgroup.Resources.Memory == -1 {
+	// If the memory update is set to -1 and the swap is not explicitly
+	// set, we should also set swap to -1, it means unlimited memory.
+	if cgroup.Resources.Memory == -1 && cgroup.Resources.MemorySwap == 0 {
 		// Only set swap if it's enabled in kernel
 		if cgroups.PathExists(filepath.Join(path, cgroupMemorySwapLimit)) {
 			cgroup.Resources.MemorySwap = -1
diff --git a/libcontainer/cgroups/systemd/v2.go b/libcontainer/cgroups/systemd/v2.go
index 2fcf312..e78de66 100644
--- a/libcontainer/cgroups/systemd/v2.go
+++ b/libcontainer/cgroups/systemd/v2.go
@@ -57,12 +57,12 @@
 		properties = append(properties,
 			newProp("MemoryLow", uint64(c.Resources.MemoryReservation)))
 	}
-	// swap is set
-	if c.Resources.MemorySwap != 0 {
-		swap, err := cgroups.ConvertMemorySwapToCgroupV2Value(c.Resources.MemorySwap, c.Resources.Memory)
-		if err != nil {
-			return nil, err
-		}
+
+	swap, err := cgroups.ConvertMemorySwapToCgroupV2Value(c.Resources.MemorySwap, c.Resources.Memory)
+	if err != nil {
+		return nil, err
+	}
+	if swap != 0 {
 		properties = append(properties,
 			newProp("MemorySwapMax", uint64(swap)))
 	}
diff --git a/libcontainer/cgroups/utils.go b/libcontainer/cgroups/utils.go
index 3b6ef4a..0132169 100644
--- a/libcontainer/cgroups/utils.go
+++ b/libcontainer/cgroups/utils.go
@@ -612,6 +612,12 @@
 // for use by cgroup v2 drivers. A conversion is needed since Resources.MemorySwap
 // is defined as memory+swap combined, while in cgroup v2 swap is a separate value.
 func ConvertMemorySwapToCgroupV2Value(memorySwap, memory int64) (int64, error) {
+	// for compatibility with cgroup1 controller, set swap to unlimited in
+	// case the memory is set to unlimited, and swap is not explicitly set,
+	// treating the request as "set both memory and swap to unlimited".
+	if memory == -1 && memorySwap == 0 {
+		return -1, nil
+	}
 	if memorySwap == -1 || memorySwap == 0 {
 		// -1 is "max", 0 is "unset", so treat as is
 		return memorySwap, nil
diff --git a/tests/integration/update.bats b/tests/integration/update.bats
index 76d931f..72ee610 100644
--- a/tests/integration/update.bats
+++ b/tests/integration/update.bats
@@ -80,8 +80,7 @@
         SD_MEM_SWAP="MemorySwapMax"
         SYSTEM_MEM="max"
         SYSTEM_MEM_SWAP="max"
-        # checking swap is currently disabled for v2
-        #CGROUP_MEMORY=$CGROUP_PATH
+        CGROUP_MEMORY=$CGROUP_PATH
         ;;
     esac
     SD_UNLIMITED="infinity"
@@ -135,10 +134,19 @@
         check_systemd_value "$SD_MEM_SWAP" $SD_UNLIMITED
 
         # update memory swap
-        runc update test_update --memory-swap 96468992
-        [ "$status" -eq 0 ]
-        check_cgroup_value "$MEM_SWAP" 96468992
-        check_systemd_value "$SD_MEM_SWAP" 96468992
+        if [ "$CGROUP_UNIFIED" = "yes" ]; then
+            # for cgroupv2, memory and swap can only be set together
+            runc update test_update --memory 52428800 --memory-swap 96468992
+            [ "$status" -eq 0 ]
+            # for cgroupv2, swap is a separate limit (it does not include mem)
+            check_cgroup_value "$MEM_SWAP" $((96468992-52428800))
+            check_systemd_value "$SD_MEM_SWAP" $((96468992-52428800))
+        else
+            runc update test_update --memory-swap 96468992
+            [ "$status" -eq 0 ]
+            check_cgroup_value "$MEM_SWAP" 96468992
+            check_systemd_value "$SD_MEM_SWAP" 96468992
+        fi
     fi
 
     # try to remove memory limit