diff options
author | Pavel Tikhomirov <ptikhomirov@virtuozzo.com> | 2020-07-28 11:49:45 +0300 |
---|---|---|
committer | Andrei Vagin <avagin@gmail.com> | 2022-04-29 03:53:52 +0300 |
commit | ef53df471d44666330c7a7b58aad9e0673b7ca65 (patch) | |
tree | a794b9b865190fc5bcb2a95033ae4bff06d87778 /test | |
parent | 486e1fd854429630a2d3a0c1f17a1724e3aaa5ee (diff) |
zdtm: add mount_complex_sharing test
Mounts-v2 engine should fix multiple problems of old engine relative to
sharing options, lets add a test for such problems.
Add all four types of shared groups: 1) private, 2) shared, 3) slave
and 4) slave+shared for mounts. Propagate them into sharing and after
propagation change sharing with four ways: 1) don't change, 2) make
private, 3) make slave and 4) make private + make shared.
This brings 16 cases of different sharing options for mount propagation,
lets check that they all are restored fine.
Lets create mounts from description to make it easier to improve this
test in future.
Cherry-picked from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/8bcd0034d
FIXME: need to check options restored right as we don't have
--check-mounts to do this job for us.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Diffstat (limited to 'test')
-rw-r--r-- | test/zdtm/static/Makefile | 1 | ||||
-rw-r--r-- | test/zdtm/static/mount_complex_sharing.c | 228 | ||||
-rw-r--r-- | test/zdtm/static/mount_complex_sharing.desc | 4 |
3 files changed, 233 insertions, 0 deletions
diff --git a/test/zdtm/static/Makefile b/test/zdtm/static/Makefile index 9183e7131..717306dbb 100644 --- a/test/zdtm/static/Makefile +++ b/test/zdtm/static/Makefile @@ -404,6 +404,7 @@ TST_DIR = \ mntns_pivot_root \ mntns_pivot_root_ro \ mnt_ext_sharing \ + mount_complex_sharing \ mnt_tracefs \ mntns_deleted \ unlink_regular00 \ diff --git a/test/zdtm/static/mount_complex_sharing.c b/test/zdtm/static/mount_complex_sharing.c new file mode 100644 index 000000000..efc1b14aa --- /dev/null +++ b/test/zdtm/static/mount_complex_sharing.c @@ -0,0 +1,228 @@ +#include <unistd.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/mount.h> +#include <linux/limits.h> + +#include "zdtmtst.h" + +const char *test_doc = "Check complex sharing options for mounts"; +const char *test_author = "Pavel Tikhomirov <ptikhomirov@virtuozzo.com>"; + +char *dirname = "mount_complex_sharing"; +TEST_OPTION(dirname, string, "directory name", 1); + +/* + * Description for creating a single file: + * path - path to create file in (relative to mount) + * dir - true if file is a directory + * content - if file is not a directory, this string is written into the file + */ +struct file { + char *path; + bool dir; + char *content; +}; + +/* + * Description for creating a single mount: + * mountpoint - path to create mount on (relative to dirname) + * bind - id of bind source if any or -1 + * bind_root - root offset from bind source + * fstype - needed for non-binds, always tmpfs + * source - source for mounting + * shflags - array of sharing options applied after mounting (ending with -1) + * mounted - identifies implicitly propagated mounts + * files - array of files we need to create on mount (ending with zeroed file) + */ +struct mountinfo { + char *mountpoint; + int bind; + char *bind_root; + char *fstype; + char *source; + int shflags[3]; + bool mounted; + struct file files[10]; +}; + +/* clang-format off */ +struct mountinfo mounts[] = { + {"", -1, "", "tmpfs", "tmpfs-dirname", {MS_PRIVATE, -1}, false, + { + {"shared-bind-1", true}, + {"shared-bind-2", true}, + {"shared-bind-3", true}, + {"shared-bind-4", true}, + {"private-mnt", true}, + {"shared-mnt", true}, + {"slave-mnt", true}, + {"slave-shared-mnt", true}, + {"testfile", false, "TESTFILE"}, + {NULL} + } + }, + + {"shared-bind-1", -1, "", "tmpfs", "tmpfs-shared-bind", {MS_SHARED, -1}, false, + { + {"prop-private", true}, + {"prop-shared", true}, + {"prop-slave", true}, + {"prop-slave-shared", true}, + {NULL} + } + }, + {"shared-bind-2", 1, "", NULL, NULL, {-1}, false}, + {"shared-bind-3", 1, "", NULL, NULL, {-1}, false}, + {"shared-bind-4", 1, "", NULL, NULL, {-1}, false}, + + {"private-mnt", -1, "", "tmpfs", "tmpfs-mnt", {MS_PRIVATE, -1}, false, + { + {"subdir", true}, + {NULL} + } + }, + {"shared-mnt", 5, "", NULL, NULL, {MS_SHARED, -1}, false}, + {"slave-mnt", 6, "", NULL, NULL, {MS_SLAVE, -1}, false}, + {"slave-shared-mnt", 7, "", NULL, NULL, {MS_SHARED, -1}, false}, + + {"shared-bind-1/prop-private", 5, "subdir", NULL, NULL, {-1}, false}, + {"shared-bind-1/prop-shared", 6, "subdir", NULL, NULL, {-1}, false}, + {"shared-bind-1/prop-slave", 7, "subdir", NULL, NULL, {-1}, false}, + {"shared-bind-1/prop-slave-shared", 8, "subdir", NULL, NULL, {-1}, false}, + + {"shared-bind-2/prop-private", -1, NULL, NULL, NULL, {MS_PRIVATE, -1}, true}, + {"shared-bind-2/prop-shared", -1, NULL, NULL, NULL, {MS_PRIVATE, -1}, true}, + {"shared-bind-2/prop-slave", -1, NULL, NULL, NULL, {MS_PRIVATE, -1}, true}, + {"shared-bind-2/prop-slave-shared", -1, NULL, NULL, NULL, {MS_PRIVATE, -1}, true}, + + {"shared-bind-3/prop-private", -1, NULL, NULL, NULL, {MS_SLAVE, -1}, true}, + {"shared-bind-3/prop-shared", -1, NULL, NULL, NULL, {MS_SLAVE, -1}, true}, + {"shared-bind-3/prop-slave", -1, NULL, NULL, NULL, {MS_SLAVE, -1}, true}, + {"shared-bind-3/prop-slave-shared", -1, NULL, NULL, NULL, {MS_SLAVE, -1}, true}, + + {"shared-bind-4/prop-private", -1, NULL, NULL, NULL, {MS_PRIVATE, MS_SHARED, -1}, true}, + {"shared-bind-4/prop-shared", -1, NULL, NULL, NULL, {MS_PRIVATE, MS_SHARED, -1}, true}, + {"shared-bind-4/prop-slave", -1, NULL, NULL, NULL, {MS_PRIVATE, MS_SHARED, -1}, true}, + {"shared-bind-4/prop-slave-shared", -1, NULL, NULL, NULL, {MS_PRIVATE, MS_SHARED, -1}, true}, +}; +/* clang-format on */ + +static int fill_content(struct mountinfo *mi) +{ + struct file *file = &mi->files[0]; + char path[PATH_MAX]; + + while (file->path != NULL) { + snprintf(path, sizeof(path), "%s/%s/%s", dirname, mi->mountpoint, file->path); + + if (file->dir) { + test_msg("Mkdir %s\n", path); + if (mkdir(path, 0700)) { + pr_perror("Failed to create dir %s", path); + return -1; + } + } else { + int fd, len = strlen(file->content); + + test_msg("Create file %s with content %s\n", path, file->content); + fd = open(path, O_WRONLY | O_CREAT, 0777); + if (fd < 0) { + pr_perror("Failed to create file %s", path); + return -1; + } + + if (write(fd, file->content, len) != len) { + pr_perror("Failed to write %s to file %s", file->content, path); + close(fd); + return -1; + } + close(fd); + } + + file++; + } + + return 0; +} + +static int mount_one(struct mountinfo *mi) +{ + char source[PATH_MAX], target[PATH_MAX]; + int *shflags = mi->shflags, mflags = 0; + char *fstype = NULL; + + test_msg("Mounting %s %d %s %s %d\n", mi->mountpoint, mi->bind, mi->fstype, mi->source, mi->mounted); + + snprintf(target, sizeof(target), "%s/%s", dirname, mi->mountpoint); + + if (mi->mounted) + goto sharing; + + if (mi->bind != -1) { + snprintf(source, sizeof(source), "%s/%s/%s", dirname, mounts[mi->bind].mountpoint, mi->bind_root); + fstype = NULL; + mflags = MS_BIND; + } else { + snprintf(source, sizeof(source), "%s", mi->source); + fstype = mi->fstype; + } + + if (mount(source, target, fstype, mflags, NULL)) { + pr_perror("Failed to mount %s %s %s", source, target, fstype); + return -1; + } + + if (fill_content(mi)) + return -1; + +sharing: + while (shflags[0] != -1) { + test_msg("Making mount %s 0x%x\n", target, shflags[0]); + if (mount(NULL, target, NULL, shflags[0], NULL)) { + pr_perror("Failed to make mount %s 0x%x", target, shflags[0]); + return -1; + } + shflags++; + } + + return 0; +} + +static int mount_loop(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(mounts); i++) { + if (mount_one(&mounts[i])) + return 1; + } + + return 0; +} + +int main(int argc, char **argv) +{ + int ret = 1; + + test_init(argc, argv); + + if (mkdir(dirname, 0700) && errno != EEXIST) { + pr_perror("Failed to create %s", dirname); + goto err; + } + + if (mount_loop()) + goto err; + + test_daemon(); + test_waitsig(); + + pass(); + ret = 0; +err: + if (ret) + fail(); + return ret; +} diff --git a/test/zdtm/static/mount_complex_sharing.desc b/test/zdtm/static/mount_complex_sharing.desc new file mode 100644 index 000000000..8910f4684 --- /dev/null +++ b/test/zdtm/static/mount_complex_sharing.desc @@ -0,0 +1,4 @@ +{ 'flavor': 'ns uns', + 'flags': 'suid', + 'feature': 'move_mount_set_group', + 'ropts': '--no-mntns-compat-mode'} |