1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Copyright (C) 2019 Cyril Hrubis <chrubis@suse.cz>
4 */
5
6 /*
7 * Very simple uevent netlink socket test.
8 *
9 * We fork a child that listens for a kernel events while parents attaches and
10 * detaches a loop device which should produce two change events.
11 */
12
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <sys/wait.h>
16 #include "tst_test.h"
17
18 #include "uevent.h"
19
generate_device_events(const char * dev_path)20 static void generate_device_events(const char *dev_path)
21 {
22 tst_fill_file("loop.img", 0, 1024, 1024);
23
24 tst_res(TINFO, "Attaching device %s", dev_path);
25 tst_attach_device(dev_path, "loop.img");
26 tst_res(TINFO, "Detaching device %s", dev_path);
27 tst_detach_device(dev_path);
28 }
29
verify_uevent(void)30 static void verify_uevent(void)
31 {
32 int pid, fd, dev_num;
33 char dev_path[1024];
34 char ev_msg[1024];
35 char ev_dev_path[1024];
36 char ev_dev_minor[128];
37 char ev_dev_name[128];
38
39 struct uevent_desc desc = {
40 .msg = ev_msg,
41 .value_cnt = 7,
42 .values = (const char*[]) {
43 "ACTION=change",
44 ev_dev_path,
45 "SUBSYSTEM=block",
46 "MAJOR=7",
47 ev_dev_minor,
48 ev_dev_name,
49 "DEVTYPE=disk",
50 }
51 };
52
53 dev_num = tst_find_free_loopdev(dev_path, sizeof(dev_path));
54
55 if (dev_num < 0)
56 tst_brk(TBROK, "Failed to find free loop device");
57
58 snprintf(ev_msg, sizeof(ev_msg),
59 "change@/devices/virtual/block/loop%i", dev_num);
60
61 snprintf(ev_dev_path, sizeof(ev_dev_path),
62 "DEVPATH=/devices/virtual/block/loop%i", dev_num);
63
64 snprintf(ev_dev_minor, sizeof(ev_dev_minor), "MINOR=%i", dev_num);
65 snprintf(ev_dev_name, sizeof(ev_dev_name), "DEVNAME=loop%i", dev_num);
66
67 const struct uevent_desc *const uevents[] = {
68 &desc,
69 &desc,
70 NULL
71 };
72
73 pid = SAFE_FORK();
74 if (!pid) {
75 fd = open_uevent_netlink();
76 TST_CHECKPOINT_WAKE(0);
77 wait_for_uevents(fd, uevents);
78 exit(0);
79 }
80
81 TST_CHECKPOINT_WAIT(0);
82
83 generate_device_events(dev_path);
84
85 wait_for_pid(pid);
86 }
87
88 static struct tst_test test = {
89 .test_all = verify_uevent,
90 .forks_child = 1,
91 .needs_checkpoints = 1,
92 .needs_drivers = (const char *const []) {
93 "loop",
94 NULL
95 },
96 .needs_root = 1
97 };
98