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