289 lines
7.2 KiB
Diff
289 lines
7.2 KiB
Diff
From c44c68028f22751ef12fac02567008a16e992fea Mon Sep 17 00:00:00 2001
|
|
From: "fu.lin" <fulin10@huawei.com>
|
|
Date: Thu, 17 Feb 2022 14:30:03 +0800
|
|
Subject: [PATCH 67/72] zdtm: add chardev testcase
|
|
|
|
- char dev `ioctl({IOCTL_CMD_NEEDREPAIR, IOCTL_CMD_REPAIR})`
|
|
checkpoint/restore test
|
|
- anonymous inode checkpoint/restore test
|
|
---
|
|
test/zdtm/customization/Makefile | 3 +-
|
|
test/zdtm/customization/chardev00.c | 65 +++++++++++
|
|
test/zdtm/customization/chardev00.desc | 1 +
|
|
test/zdtm/mod/Makefile | 5 +-
|
|
test/zdtm/mod/anon_inode.c | 148 +++++++++++++++++++++++++
|
|
5 files changed, 220 insertions(+), 2 deletions(-)
|
|
create mode 100644 test/zdtm/customization/chardev00.c
|
|
create mode 100644 test/zdtm/customization/chardev00.desc
|
|
create mode 100644 test/zdtm/mod/anon_inode.c
|
|
|
|
diff --git a/test/zdtm/customization/Makefile b/test/zdtm/customization/Makefile
|
|
index 93922c7..7d08db3 100644
|
|
--- a/test/zdtm/customization/Makefile
|
|
+++ b/test/zdtm/customization/Makefile
|
|
@@ -11,7 +11,8 @@ TST_NOFILE = \
|
|
maps05 \
|
|
maps007 \
|
|
maps008 \
|
|
- notifier00
|
|
+ notifier00 \
|
|
+ chardev00
|
|
|
|
TST_FILE = \
|
|
maps00 \
|
|
diff --git a/test/zdtm/customization/chardev00.c b/test/zdtm/customization/chardev00.c
|
|
new file mode 100644
|
|
index 0000000..c708699
|
|
--- /dev/null
|
|
+++ b/test/zdtm/customization/chardev00.c
|
|
@@ -0,0 +1,65 @@
|
|
+#include <stdio.h>
|
|
+#include <sys/types.h>
|
|
+#include <sys/stat.h>
|
|
+#include <fcntl.h>
|
|
+#include <sys/ioctl.h>
|
|
+#include "zdtmtst.h"
|
|
+
|
|
+#define CHARDEV_PATH "/dev/anon_test"
|
|
+
|
|
+const char *test_doc="Tests char dev and anonmous inode map checkpoint/restore";
|
|
+
|
|
+static int check_maps(unsigned long addr)
|
|
+{
|
|
+ FILE *fp = fopen("/proc/self/maps", "r");
|
|
+ char *line = NULL;
|
|
+ size_t n = 0;
|
|
+ unsigned long start = 0;
|
|
+
|
|
+ if (fp == NULL) {
|
|
+ pr_perror("open self maps failed");
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ while (getline(&line, &n, fp) != -1) {
|
|
+ test_msg("%s", line);
|
|
+ sscanf(line, "%lx-", &start);
|
|
+ if (start == addr)
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ return -1;
|
|
+}
|
|
+
|
|
+int main(int argc, char *argv[])
|
|
+{
|
|
+ int fd, retval = 0;
|
|
+ unsigned long addr;
|
|
+
|
|
+ test_init(argc, argv);
|
|
+
|
|
+ fd = open(CHARDEV_PATH, O_RDWR);
|
|
+ if (fd < 0) {
|
|
+ pr_perror("open '%s' failed", CHARDEV_PATH);
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ retval = ioctl(fd, 0, &addr);
|
|
+ if (retval < 0) {
|
|
+ pr_perror("create anonymous map failed");
|
|
+ retval = -1;
|
|
+ goto out;
|
|
+ }
|
|
+ test_msg("create anonymous vma start 0x%lx\n", addr);
|
|
+
|
|
+ test_daemon();
|
|
+ test_waitsig();
|
|
+
|
|
+ retval = check_maps(addr);
|
|
+ if (retval == 0)
|
|
+ pass();
|
|
+ else
|
|
+ fail("anonymous inode map don't restore");
|
|
+out:
|
|
+ return retval;
|
|
+}
|
|
diff --git a/test/zdtm/customization/chardev00.desc b/test/zdtm/customization/chardev00.desc
|
|
new file mode 100644
|
|
index 0000000..9c51ba8
|
|
--- /dev/null
|
|
+++ b/test/zdtm/customization/chardev00.desc
|
|
@@ -0,0 +1 @@
|
|
+{'arch': 'aarch64', 'opts': '--dump-char-dev', 'flavor': 'h', 'flags': 'suid excl', 'sysfs': '/sys/kernel/modrestore/anon_state_restore /sys/kernel/repairing_device', 'mod': 'anon_inode.ko'}
|
|
diff --git a/test/zdtm/mod/Makefile b/test/zdtm/mod/Makefile
|
|
index 10c9c9a..0bc89f7 100644
|
|
--- a/test/zdtm/mod/Makefile
|
|
+++ b/test/zdtm/mod/Makefile
|
|
@@ -2,7 +2,7 @@
|
|
# `ARCH` var is used in both criu and kernel, but they have the different value
|
|
# for the same architecture(e.g. arm64). Therefore, this Makefile can't be
|
|
# included in the criu Makefile.
|
|
-obj-m += notifier.o
|
|
+obj-m += notifier.o anon_inode.o
|
|
|
|
# specific the kernel devel path
|
|
# example (use `/home/me/kernel` as `KDIR`):
|
|
@@ -26,3 +26,6 @@ clean:
|
|
|
|
notifier.ko:
|
|
$(MAKE) -C $(KDIR) M=$(MOD) notifier.ko
|
|
+
|
|
+anon_inode.ko:
|
|
+ $(MAKE) -C $(KDIR) M=$(MOD) anon_inode.ko
|
|
diff --git a/test/zdtm/mod/anon_inode.c b/test/zdtm/mod/anon_inode.c
|
|
new file mode 100644
|
|
index 0000000..d9c7d2a
|
|
--- /dev/null
|
|
+++ b/test/zdtm/mod/anon_inode.c
|
|
@@ -0,0 +1,148 @@
|
|
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
|
+
|
|
+#include <linux/init.h>
|
|
+#include <linux/module.h>
|
|
+#include <linux/miscdevice.h>
|
|
+#include <linux/fs.h>
|
|
+#include <linux/mm.h>
|
|
+#include <linux/mman.h>
|
|
+#include <linux/anon_inodes.h>
|
|
+#include <linux/file.h>
|
|
+#include <linux/modrestore.h>
|
|
+
|
|
+static int anon_mmap(struct file *file, struct vm_area_struct *vma)
|
|
+{
|
|
+ pr_info("call %s\n", __func__);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static const struct file_operations none_fops = {
|
|
+ .owner = THIS_MODULE,
|
|
+ .mmap = anon_mmap,
|
|
+};
|
|
+
|
|
+static unsigned long create_mmap(void)
|
|
+{
|
|
+ struct file *filp;
|
|
+ unsigned long start;
|
|
+
|
|
+ pr_info("call %s\n", __func__);
|
|
+ filp = anon_inode_getfile("test", &none_fops, NULL, O_RDWR);
|
|
+ if (IS_ERR(filp)) {
|
|
+ pr_warn("anon_inode_getfile('test') failed: %d\n", (int)PTR_ERR(filp));
|
|
+ return PTR_ERR(filp);
|
|
+ }
|
|
+
|
|
+ start = vm_mmap(filp, 0, 1<<20, PROT_READ | PROT_WRITE, MAP_SHARED, 0);
|
|
+ if (IS_ERR_VALUE(start)) {
|
|
+ pr_warn("vm_mmap failed with: %d\n", (int)PTR_ERR((void *)start));
|
|
+ }
|
|
+
|
|
+ fput(filp);
|
|
+
|
|
+ return start;
|
|
+}
|
|
+
|
|
+static int anon_inode_notifier(struct notifier_block *nb,
|
|
+ unsigned long action, void *data)
|
|
+{
|
|
+ struct vma_anon_entry *vma_entry = data;
|
|
+ struct file *filp;
|
|
+ unsigned long start;
|
|
+
|
|
+ filp = anon_inode_getfile("test", &none_fops, NULL, O_RDWR);
|
|
+ if (IS_ERR(filp)) {
|
|
+ pr_warn("anon_inode_getfile('test') failed: %d\n", (int)PTR_ERR(filp));
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ start = vm_mmap(filp, vma_entry->start, vma_entry -> end-vma_entry->start,
|
|
+ PROT_READ | PROT_WRITE, MAP_SHARED, 0);
|
|
+ if (start != vma_entry->start)
|
|
+ pr_warn("vm_mmap() failed: %#lx\n", start);
|
|
+
|
|
+ fput(filp);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static long anon_ioctl(struct file *file, unsigned int cmd, unsigned long argp)
|
|
+{
|
|
+ unsigned long start;
|
|
+
|
|
+ switch (cmd) {
|
|
+ case 0:
|
|
+ start = create_mmap();
|
|
+ if (IS_ERR_VALUE(start))
|
|
+ return -EINVAL;
|
|
+ if (put_user(start, (unsigned long __user *)argp))
|
|
+ return -EFAULT;
|
|
+ break;
|
|
+ case IOCTL_CMD_NEEDREPAIR:
|
|
+ pr_info("call IOCTL_CMD_NEEDREPAIR");
|
|
+ /* do nothing, just a request slot */
|
|
+ return 17173;
|
|
+ case IOCTL_CMD_REPAIR:
|
|
+ pr_info("call IOCTL_CMD_REPAIR");
|
|
+ /* do nothing, just a request slot */
|
|
+ break;
|
|
+ default:
|
|
+ pr_warn("wrong cmd\n");
|
|
+ return -EINVAL;
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static const struct file_operations anon_fops = {
|
|
+ .owner = THIS_MODULE,
|
|
+ .unlocked_ioctl = anon_ioctl,
|
|
+ .compat_ioctl = anon_ioctl,
|
|
+};
|
|
+
|
|
+static struct miscdevice anon_dev = {
|
|
+ .minor = MISC_DYNAMIC_MINOR,
|
|
+ .name = "anon_test",
|
|
+ .fops = &anon_fops,
|
|
+};
|
|
+
|
|
+static struct notifier_block anon_inode_nb = {
|
|
+ .notifier_call = anon_inode_notifier,
|
|
+};
|
|
+
|
|
+static int __init anon_init(void)
|
|
+{
|
|
+ int retval;
|
|
+
|
|
+ retval = mures_add_devname(anon_dev.name);
|
|
+ if (retval != 0)
|
|
+ goto out;
|
|
+
|
|
+ retval = register_anon_notifier(&anon_inode_nb);
|
|
+ if (retval != 0)
|
|
+ goto del_devname;
|
|
+
|
|
+ retval = misc_register(&anon_dev);
|
|
+ if (retval != 0)
|
|
+ goto del_notifier;
|
|
+
|
|
+ return 0;
|
|
+
|
|
+del_notifier:
|
|
+ unregister_anon_notifier(&anon_inode_nb);
|
|
+del_devname:
|
|
+ mures_del_devname(anon_dev.name);
|
|
+out:
|
|
+ return retval;
|
|
+}
|
|
+
|
|
+static void __exit anon_exit(void)
|
|
+{
|
|
+ mures_del_devname(anon_dev.name);
|
|
+ unregister_anon_notifier(&anon_inode_nb);
|
|
+ misc_deregister(&anon_dev);
|
|
+ return;
|
|
+}
|
|
+
|
|
+module_init(anon_init);
|
|
+module_exit(anon_exit);
|
|
+MODULE_LICENSE("GPL");
|
|
--
|
|
2.34.1
|
|
|