[prev in list] [next in list] [prev in thread] [next in thread] 

List:       lxc-devel
Subject:    [lxc-devel] [lxd/master] Add `shift` property on disk devices
From:       stgraber on Github <lxc-bot () linuxcontainers ! org>
Date:       2019-07-24 20:38:07
Message-ID: 5d38c1af.1c69fb81.4fad9.82a7SMTPIN_ADDED_MISSING () mx ! google ! com
[Download RAW message or body]

[Attachment #2 (text/x-mailbox)]

The following pull request was submitted through Github.
It can be accessed and reviewed at: https://github.com/lxc/lxd/pull/6010

This e-mail was sent by the LXC bot, direct replies will not reach the author
unless they happen to be subscribed to this list.

=== Description (from pull-request) ===
Closes #2860

There's going to be one step on top of that which should be for LXD to automatically \
use this feature for custom storage volumes so that they can be shared between \
idmap.isolated=true containers.


[Attachment #3 (text/plain)]

From a2016b362a2058d50f0d58fbdd067d0ec4e7950d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stéphane Graber?= <stgraber@ubuntu.com>
Date: Wed, 17 Jul 2019 23:35:06 -0400
Subject: [PATCH 1/6] api: Add container_disk_shift extension
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber@ubuntu.com>
---
 doc/api-extensions.md | 3 +++
 shared/version/api.go | 1 +
 2 files changed, 4 insertions(+)

diff --git a/doc/api-extensions.md b/doc/api-extensions.md
index 3bf3d1adad..3202ad3e1b 100644
--- a/doc/api-extensions.md
+++ b/doc/api-extensions.md
@@ -803,3 +803,6 @@ Adds support for specifying User, Group and Cwd during `POST \
/1.0/containers/NAM  Adds the `security.syscalls.intercept.\*` configuration keys to \
control  what system calls will be interecepted by LXD and processed with
 elevated permissions.
+
+## container\_disk\_shift
+Adds the `shift` property on `disk` devices which controls the use of the shiftfs \
                overlay.
diff --git a/shared/version/api.go b/shared/version/api.go
index 99fef0b913..fdf8a5921f 100644
--- a/shared/version/api.go
+++ b/shared/version/api.go
@@ -160,6 +160,7 @@ var APIExtensions = []string{
 	"resources_v2",
 	"container_exec_user_group_cwd",
 	"container_syscall_intercept",
+	"container_disk_shift",
 }

 // APIExtensionsCount returns the number of available API extensions.

From 1df04cfd26b3d975788bba99c59af6da2222da3c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stéphane Graber?= <stgraber@ubuntu.com>
Date: Wed, 17 Jul 2019 23:35:44 -0400
Subject: [PATCH 2/6] doc: Add shift option to disk device
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber@ubuntu.com>
---
 doc/containers.md | 1 +
 1 file changed, 1 insertion(+)

diff --git a/doc/containers.md b/doc/containers.md
index 4c33c2c254..c3741f416b 100644
--- a/doc/containers.md
+++ b/doc/containers.md
@@ -493,6 +493,7 @@ size            | string    | -                 | no        | \
Disk size in bytes  recursive       | boolean   | false             | no        | \
Whether or not to recursively mount the source path  pool            | string    | -  \
| no        | The storage pool the disk device belongs to. This is only applicable \
for storage volumes managed by LXD.  propagation     | string    | -                 \
| no        | Controls how a bind-mount is shared between the container and the host. \
(Can be one of `private`, the default, or `shared`, `slave`, `unbindable`,  \
`rshared`, `rslave`, `runbindable`,  `rprivate`. Please see the Linux Kernel [shared \
subtree](https://www.kernel.org/doc/Documentation/filesystems/sharedsubtree.txt) \
documentation for a full explanation) +shift           | boolean   | false            \
| no        | Setup a shifting overlay to translate the source uid/gid to match the \
container

 If multiple disks, backed by the same block device, have I/O limits set,
 the average of the limits will be used.

From 3f04a1e092074fdd5a62d68fa55b2612d910f438 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stéphane Graber?= <stgraber@ubuntu.com>
Date: Wed, 17 Jul 2019 23:40:42 -0400
Subject: [PATCH 3/6] lxd/container: Don't validate liblxc version during
 config parsing
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber@ubuntu.com>
---
 lxd/container.go     | 5 -----
 lxd/container_lxc.go | 4 ++++
 2 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/lxd/container.go b/lxd/container.go
index a690fff70c..d6e1cb8a5e 100644
--- a/lxd/container.go
+++ b/lxd/container.go
@@ -22,7 +22,6 @@ import (
 	"github.com/lxc/lxd/lxd/state"
 	"github.com/lxc/lxd/lxd/sys"
 	"github.com/lxc/lxd/lxd/task"
-	"github.com/lxc/lxd/lxd/util"
 	"github.com/lxc/lxd/shared"
 	"github.com/lxc/lxd/shared/api"
 	"github.com/lxc/lxd/shared/idmap"
@@ -515,10 +514,6 @@ func containerValidDevices(cluster *db.Cluster, devices \
config.Devices, profile  }

 			if m["propagation"] != "" {
-				if !util.RuntimeLiblxcVersionAtLeast(3, 0, 0) {
-					return fmt.Errorf("liblxc 3.0 is required for mount propagation configuration")
-				}
-
 				if !shared.StringInSlice(m["propagation"], []string{"private", "shared", \
"slave", "unbindable", "rprivate", "rshared", "rslave", "runbindable"}) {  return \
fmt.Errorf("Invalid propagation mode '%s'", m["propagation"])  }
diff --git a/lxd/container_lxc.go b/lxd/container_lxc.go
index 1b5ca2ccd0..31354ce189 100644
--- a/lxd/container_lxc.go
+++ b/lxd/container_lxc.go
@@ -1843,6 +1843,10 @@ func (c *containerLXC) initLXC(config bool) error {
 				}

 				if m["propagation"] != "" {
+					if !util.RuntimeLiblxcVersionAtLeast(3, 0, 0) {
+						return fmt.Errorf("liblxc 3.0 is required for mount propagation \
configuration") +					}
+
 					options = append(options, m["propagation"])
 				}


From ef59832e811f83d2771764e5dc8cc037ea8c889b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stéphane Graber?= <stgraber@ubuntu.com>
Date: Wed, 17 Jul 2019 23:59:28 -0400
Subject: [PATCH 4/6] lxd: Add shift disk option
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber@ubuntu.com>
---
 lxd/container.go | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/lxd/container.go b/lxd/container.go
index d6e1cb8a5e..4d4df4b91d 100644
--- a/lxd/container.go
+++ b/lxd/container.go
@@ -185,6 +185,8 @@ func containerValidDeviceConfigKey(t, k string) bool {
 			return true
 		case "propagation":
 			return true
+		case "shift":
+			return true
 		default:
 			return false
 		}
@@ -518,6 +520,12 @@ func containerValidDevices(cluster *db.Cluster, devices \
config.Devices, profile  return fmt.Errorf("Invalid propagation mode '%s'", \
m["propagation"])  }
 			}
+
+			if m["shift"] != "" {
+				if m["pool"] != "" {
+					return fmt.Errorf("The \"shift\" property cannot be used with custom storage \
volumes") +				}
+			}
 		} else if shared.StringInSlice(m["type"], []string{"unix-char", "unix-block"}) {
 			if m["source"] == "" && m["path"] == "" {
 				return fmt.Errorf("Unix device entry is missing the required \"source\" or \
\"path\" property")

From 12f16a412240f03222860bf31be7a38ca211a473 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stéphane Graber?= <stgraber@ubuntu.com>
Date: Thu, 18 Jul 2019 01:23:03 -0400
Subject: [PATCH 5/6] lxd/containers: Add shiftfs for disk devices
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber@ubuntu.com>
---
 lxd/container_lxc.go  | 44 ++++++++++++++++++++++++++++++++++---------
 lxd/main_forkmount.go | 24 ++++++++++++++++++++++-
 2 files changed, 58 insertions(+), 10 deletions(-)

diff --git a/lxd/container_lxc.go b/lxd/container_lxc.go
index 31354ce189..003b453e9c 100644
--- a/lxd/container_lxc.go
+++ b/lxd/container_lxc.go
@@ -1828,6 +1828,23 @@ func (c *containerLXC) initLXC(config bool) error {
 					}
 				}
 			} else {
+				if shared.IsTrue(m["shift"]) {
+					err = lxcSetConfigItem(cc, "lxc.hook.pre-start", fmt.Sprintf("/bin/mount -t \
shiftfs -o mark,passthrough=3 %s %s", sourceDevPath, sourceDevPath)) +					if err != \
nil { +						return err
+					}
+
+					err = lxcSetConfigItem(cc, "lxc.hook.pre-mount", fmt.Sprintf("/bin/mount -t \
shiftfs -o passthrough=3 %s %s", sourceDevPath, sourceDevPath)) +					if err != nil {
+						return err
+					}
+
+					err = lxcSetConfigItem(cc, "lxc.hook.start-host", fmt.Sprintf("/bin/umount -l \
%s", sourceDevPath)) +					if err != nil {
+						return err
+					}
+				}
+
 				rbind := ""
 				options := []string{}
 				if isReadOnly {
@@ -5130,7 +5147,7 @@ func (c *containerLXC) Update(args db.ContainerArgs, \
userRequested bool) error {  }
 			} else if key == "security.devlxd" {
 				if value == "" || shared.IsTrue(value) {
-					err = c.insertMount(shared.VarPath("devlxd"), "/dev/lxd", "none", unix.MS_BIND)
+					err = c.insertMount(shared.VarPath("devlxd"), "/dev/lxd", "none", unix.MS_BIND, \
false)  if err != nil {
 						return err
 					}
@@ -7274,7 +7291,7 @@ func (c *containerLXC) StorageStop() (bool, error) {
 }

 // Mount handling
-func (c *containerLXC) insertMountLXD(source, target, fstype string, flags int, \
mntnsPID int) error { +func (c *containerLXC) insertMountLXD(source, target, fstype \
string, flags int, mntnsPID int, shiftfs bool) error {  pid := mntnsPID
 	if pid <= 0 {
 		// Get the init PID
@@ -7311,11 +7328,20 @@ func (c *containerLXC) insertMountLXD(source, target, fstype \
string, flags int,  }
 	defer unix.Unmount(tmpMount, unix.MNT_DETACH)

+	// Setup host side shiftfs as needed
+	if shiftfs {
+		err = unix.Mount(tmpMount, tmpMount, "shiftfs", 0, "mark,passthrough=3")
+		if err != nil {
+			return fmt.Errorf("Failed to setup host side shiftfs mount: %s", err)
+		}
+		defer unix.Unmount(tmpMount, unix.MNT_DETACH)
+	}
+
 	// Move the mount inside the container
 	mntsrc := filepath.Join("/dev/.lxd-mounts", filepath.Base(tmpMount))
 	pidStr := fmt.Sprintf("%d", pid)

-	_, err = shared.RunCommand(c.state.OS.ExecPath, "forkmount", "lxd-mount", pidStr, \
mntsrc, target) +	_, err = shared.RunCommand(c.state.OS.ExecPath, "forkmount", \
"lxd-mount", pidStr, mntsrc, target, fmt.Sprintf("%v", shiftfs))  if err != nil {
 		return err
 	}
@@ -7342,12 +7368,12 @@ func (c *containerLXC) insertMountLXC(source, target, fstype \
string, flags int)  return nil
 }

-func (c *containerLXC) insertMount(source, target, fstype string, flags int) error {
-	if c.state.OS.LXCFeatures["mount_injection_file"] {
+func (c *containerLXC) insertMount(source, target, fstype string, flags int, shiftfs \
bool) error { +	if c.state.OS.LXCFeatures["mount_injection_file"] && !shiftfs {
 		return c.insertMountLXC(source, target, fstype, flags)
 	}

-	return c.insertMountLXD(source, target, fstype, flags, -1)
+	return c.insertMountLXD(source, target, fstype, flags, -1, shiftfs)
 }

 func (c *containerLXC) removeMount(mount string) error {
@@ -7549,7 +7575,7 @@ func (c *containerLXC) insertUnixDevice(prefix string, m \
config.Device, defaultM  tgtPath := paths[1]

 	// Bind-mount it into the container
-	err = c.insertMount(devPath, tgtPath, "none", unix.MS_BIND)
+	err = c.insertMount(devPath, tgtPath, "none", unix.MS_BIND, false)
 	if err != nil {
 		return fmt.Errorf("Failed to add mount for device: %s", err)
 	}
@@ -7642,7 +7668,7 @@ func (c *containerLXC) InsertSeccompUnixDevice(prefix string, m \
config.Device, p

 	// Bind-mount it into the container
 	defer os.Remove(devPath)
-	return c.insertMountLXD(devPath, tgtPath, "none", unix.MS_BIND, pid)
+	return c.insertMountLXD(devPath, tgtPath, "none", unix.MS_BIND, pid, false)
 }

 func (c *containerLXC) insertUnixDeviceNum(name string, m config.Device, major int, \
minor int, path string, defaultMode bool) error { @@ -9334,7 +9360,7 @@ func (c \
*containerLXC) insertDiskDevice(name string, m config.Device) error {

 	// Bind-mount it into the container
 	destPath := strings.TrimSuffix(m["path"], "/")
-	err = c.insertMount(devPath, destPath, "none", flags)
+	err = c.insertMount(devPath, destPath, "none", flags, shared.IsTrue(m["shift"]))
 	if err != nil {
 		return fmt.Errorf("Failed to add mount for device: %s", err)
 	}
diff --git a/lxd/main_forkmount.go b/lxd/main_forkmount.go
index 5b0209895b..c42bfa1f2d 100644
--- a/lxd/main_forkmount.go
+++ b/lxd/main_forkmount.go
@@ -128,7 +128,7 @@ void create(char *src, char *dest)
 }

 void do_lxd_forkmount(pid_t pid) {
-	char *src, *dest, *opts;
+	char *src, *dest, *opts, *shiftfs;

 	attach_userns(pid);

@@ -139,6 +139,7 @@ void do_lxd_forkmount(pid_t pid) {

 	src = advance_arg(true);
 	dest = advance_arg(true);
+	shiftfs = advance_arg(true);

 	create(src, dest);

@@ -152,14 +153,35 @@ void do_lxd_forkmount(pid_t pid) {
 		_exit(1);
 	}

+	if (strcmp(shiftfs, "true") == 0) {
+		// Setup shiftfs inside the container
+		if (mount(src, src, "shiftfs", 0, "passthrough=3") < 0) {
+			fprintf(stderr, "Failed shiftfs setup for %s: %s\n", src, strerror(errno));
+			_exit(1);
+		}
+	}
+
 	// Here, we always move recursively, because we sometimes allow
 	// recursive mounts. If the mount has no kids then it doesn't matter,
 	// but if it does, we want to move those too.
 	if (mount(src, dest, "none", MS_MOVE | MS_REC, NULL) < 0) {
+		// If using shiftfs, undo the shiftfs mount
+		if (strcmp(shiftfs, "true") == 0) {
+			umount2(src, MNT_DETACH);
+		}
+
 		fprintf(stderr, "Failed mounting %s onto %s: %s\n", src, dest, strerror(errno));
 		_exit(1);
 	}

+	if (strcmp(shiftfs, "true") == 0) {
+		// Clear source mount as target is now in place
+		if (umount2(src, MNT_DETACH) < 0) {
+			fprintf(stderr, "Failed shiftfs source unmount for %s: %s\n", src, \
strerror(errno)); +			_exit(1);
+		}
+	}
+
 	_exit(0);
 }


From 6ff7c7c1d0f94e8293116d70c35c6ce5286ee843 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stéphane Graber?= <stgraber@ubuntu.com>
Date: Wed, 24 Jul 2019 16:29:06 -0400
Subject: [PATCH 6/6] tests: Test the shift disk property
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgraber@ubuntu.com>
---
 test/main.sh                          |  1 +
 test/suites/container_devices_disk.sh | 32 +++++++++++++++++++++++++++
 2 files changed, 33 insertions(+)
 create mode 100644 test/suites/container_devices_disk.sh

diff --git a/test/main.sh b/test/main.sh
index 1e1e1b0578..6e0b6369f9 100755
--- a/test/main.sh
+++ b/test/main.sh
@@ -188,6 +188,7 @@ run_test test_projects_images "images inside projects"
 run_test test_projects_images_default "images from the global default project"
 run_test test_projects_storage "projects and storage pools"
 run_test test_projects_network "projects and networks"
+run_test test_container_devices_disk "container devices - disk"
 run_test test_container_devices_nic_p2p "container devices - nic - p2p"
 run_test test_container_devices_nic_bridged "container devices - nic - bridged"
 run_test test_container_devices_nic_bridged_filtering "container devices - nic - \
                bridged - filtering"
diff --git a/test/suites/container_devices_disk.sh \
b/test/suites/container_devices_disk.sh new file mode 100644
index 0000000000..e0368b25eb
--- /dev/null
+++ b/test/suites/container_devices_disk.sh
@@ -0,0 +1,32 @@
+test_container_devices_disk() {
+  ensure_import_testimage
+  ensure_has_localhost_remote "${LXD_ADDR}"
+
+  lxc launch testimage foo
+
+  test_container_devices_disk_shift
+
+  lxc delete -f foo
+}
+
+test_container_devices_disk_shift() {
+  if ! grep -q shiftfs /proc/filesystems; then
+    return
+  fi
+
+  mkdir -p "${TEST_DIR}/shift-source"
+  touch "${TEST_DIR}/shift-source/a"
+  chown 123:456 "${TEST_DIR}/shift-source/a"
+
+  lxc config device add foo shiftfs disk source="${TEST_DIR}/shift-source" path=/mnt
+  [ "$(lxc exec foo -- stat /mnt/a -c '%u:%g')" = "65534:65534" ] || false
+  lxc config device remove foo shiftfs
+
+  lxc config device add foo shiftfs disk source="${TEST_DIR}/shift-source" path=/mnt \
shift=true +  [ "$(lxc exec foo -- stat /mnt/a -c '%u:%g')" = "123:456" ] || false
+
+  lxc stop foo -f
+  lxc start foo
+  [ "$(lxc exec foo -- stat /mnt/a -c '%u:%g')" = "123:456" ] || false
+  lxc stop foo -f
+}


[Attachment #4 (text/plain)]

_______________________________________________
lxc-devel mailing list
lxc-devel@lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic