wok-tiny view busybox/stuff/0001-mdev-create-devices-from-sys-dev.patch @ rev 176

busybox: fix modules order
author Pascal Bellard <pascal.bellard@slitaz.org>
date Wed Jul 14 19:16:39 2021 +0000 (2021-07-14)
parents
children
line source
1 From 20a3262cd756aadf8771969a4764cd3c571f0a3e Mon Sep 17 00:00:00 2001
2 From: Denys Vlasenko <vda.linux@googlemail.com>
3 Date: Wed, 7 Sep 2016 14:09:01 +0200
4 Subject: [PATCH] mdev: create devices from /sys/dev
6 Currently some new devices that have a bus but no class will
7 be missed by mdev coldplug device creation after boot. This
8 happens because mdev recursively searches /sys/class which will
9 by definition only find class devices.
11 Some important devices such as iio and gpiochip does not have
12 a class. But users will need them.
14 This switches from using /sys/class as the place to look for
15 devices to create to using /sys/dev where all char and block
16 devices are listed.
18 The subsystem lookup code that provide the G.subsystem
19 environment variable is changed from using the directory
20 name of the class device to instead dereference the
21 "subsystem" symlink for the device, and look at the last
22 element of the path of the symlink for the subsystem, which
23 will work with class devices and bus devices alike. (The new
24 bus-only devices only symlink to the /sys/bus/* hierarchy.)
26 We delete the legacy kernel v2.6.2x /sys/block device path
27 code as part of this change. It's too old to be kept alive.
29 Tested on kernel v4.6-rc2 with a bunch of devices, including
30 some IIO and gpiochip devices.
32 With a print inserted before make_device() the log looks
33 like so:
35 Create device from "/sys/dev/char/1:1", subsystem "mem"
36 Create device from "/sys/dev/char/1:2", subsystem "mem"
37 Create device from "/sys/dev/char/1:3", subsystem "mem"
38 Create device from "/sys/dev/char/1:5", subsystem "mem"
39 (...)
40 Create device from "/sys/dev/block/179:56", subsystem "block"
41 Create device from "/sys/dev/block/179:64", subsystem "block"
43 function old new delta
44 mdev_main 1388 1346 -42
45 dirAction 134 14 -120
46 ------------------------------------------------------------------------------
47 (add/remove: 0/0 grow/shrink: 0/2 up/down: 0/-162) Total: -162 bytes
49 Cc: Isaac Dunham <ibid.ag@gmail.com>
50 Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
51 Cc: Jonathan Cameron <jic23@cam.ac.uk>
52 Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
53 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
54 ---
55 util-linux/mdev.c | 88 ++++++++++++++++++++++++++-----------------------------
56 1 file changed, 41 insertions(+), 47 deletions(-)
58 diff --git a/util-linux/mdev.c b/util-linux/mdev.c
59 index 37514eb..a59115d 100644
60 --- a/util-linux/mdev.c
61 +++ b/util-linux/mdev.c
62 @@ -543,8 +543,7 @@ static char *build_alias(char *alias, const char *device_name)
64 /* mknod in /dev based on a path like "/sys/block/hda/hda1"
65 * NB1: path parameter needs to have SCRATCH_SIZE scratch bytes
66 - * after NUL, but we promise to not mangle (IOW: to restore NUL if needed)
67 - * path string.
68 + * after NUL, but we promise to not mangle it (IOW: to restore NUL if needed).
69 * NB2: "mdev -s" may call us many times, do not leak memory/fds!
70 *
71 * device_name = $DEVNAME (may be NULL)
72 @@ -810,41 +809,39 @@ static void make_device(char *device_name, char *path, int operation)
73 } /* for (;;) */
74 }
76 -/* File callback for /sys/ traversal */
77 +/* File callback for /sys/ traversal.
78 + * We act only on "/sys/.../dev" (pseudo)file
79 + */
80 static int FAST_FUNC fileAction(const char *fileName,
81 struct stat *statbuf UNUSED_PARAM,
82 void *userData,
83 int depth UNUSED_PARAM)
84 {
85 size_t len = strlen(fileName) - 4; /* can't underflow */
86 - char *scratch = userData;
87 -
88 - /* len check is for paranoid reasons */
89 - if (strcmp(fileName + len, "/dev") != 0 || len >= PATH_MAX)
90 - return FALSE;
91 -
92 - strcpy(scratch, fileName);
93 - scratch[len] = '\0';
94 - make_device(/*DEVNAME:*/ NULL, scratch, OP_add);
95 -
96 - return TRUE;
97 -}
98 -
99 -/* Directory callback for /sys/ traversal */
100 -static int FAST_FUNC dirAction(const char *fileName UNUSED_PARAM,
101 - struct stat *statbuf UNUSED_PARAM,
102 - void *userData UNUSED_PARAM,
103 - int depth)
104 -{
105 - /* Extract device subsystem -- the name of the directory
106 - * under /sys/class/ */
107 - if (1 == depth) {
108 + char *path = userData; /* char array[PATH_MAX + SCRATCH_SIZE] */
109 + char subsys[PATH_MAX];
110 + int res;
111 +
112 + /* Is it a ".../dev" file? (len check is for paranoid reasons) */
113 + if (strcmp(fileName + len, "/dev") != 0 || len >= PATH_MAX - 32)
114 + return FALSE; /* not .../dev */
115 +
116 + strcpy(path, fileName);
117 + path[len] = '\0';
118 +
119 + /* Read ".../subsystem" symlink in the same directory where ".../dev" is */
120 + strcpy(subsys, path);
121 + strcpy(subsys + len, "/subsystem");
122 + res = readlink(subsys, subsys, sizeof(subsys)-1);
123 + if (res > 0) {
124 + subsys[res] = '\0';
125 free(G.subsystem);
126 if (G.subsys_env) {
127 bb_unsetenv_and_free(G.subsys_env);
128 G.subsys_env = NULL;
129 }
130 - G.subsystem = strrchr(fileName, '/');
131 + /* Set G.subsystem and $SUBSYSTEM from symlink's last component */
132 + G.subsystem = strrchr(subsys, '/');
133 if (G.subsystem) {
134 G.subsystem = xstrdup(G.subsystem + 1);
135 G.subsys_env = xasprintf("%s=%s", "SUBSYSTEM", G.subsystem);
136 @@ -852,6 +849,17 @@ static int FAST_FUNC dirAction(const char *fileName UNUSED_PARAM,
137 }
138 }
140 + make_device(/*DEVNAME:*/ NULL, path, OP_add);
141 +
142 + return TRUE;
143 +}
144 +
145 +/* Directory callback for /sys/ traversal */
146 +static int FAST_FUNC dirAction(const char *fileName UNUSED_PARAM,
147 + struct stat *statbuf UNUSED_PARAM,
148 + void *userData UNUSED_PARAM,
149 + int depth)
150 +{
151 return (depth >= MAX_SYSFS_DEPTH ? SKIP : TRUE);
152 }
154 @@ -872,8 +880,9 @@ static void load_firmware(const char *firmware, const char *sysfs_path)
155 int firmware_fd, loading_fd;
157 /* check for /lib/firmware/$FIRMWARE */
158 - xchdir("/lib/firmware");
159 - firmware_fd = open(firmware, O_RDONLY); /* can fail */
160 + firmware_fd = -1;
161 + if (chdir("/lib/firmware") == 0)
162 + firmware_fd = open(firmware, O_RDONLY); /* can fail */
164 /* check for /sys/$DEVPATH/loading ... give 30 seconds to appear */
165 xchdir(sysfs_path);
166 @@ -1065,25 +1074,10 @@ int mdev_main(int argc UNUSED_PARAM, char **argv)
168 putenv((char*)"ACTION=add");
170 - /* ACTION_FOLLOWLINKS is needed since in newer kernels
171 - * /sys/block/loop* (for example) are symlinks to dirs,
172 - * not real directories.
173 - * (kernel's CONFIG_SYSFS_DEPRECATED makes them real dirs,
174 - * but we can't enforce that on users)
175 - */
176 - if (access("/sys/class/block", F_OK) != 0) {
177 - /* Scan obsolete /sys/block only if /sys/class/block
178 - * doesn't exist. Otherwise we'll have dupes.
179 - * Also, do not complain if it doesn't exist.
180 - * Some people configure kernel to have no blockdevs.
181 - */
182 - recursive_action("/sys/block",
183 - ACTION_RECURSE | ACTION_FOLLOWLINKS | ACTION_QUIET,
184 - fileAction, dirAction, temp, 0);
185 - }
186 - recursive_action("/sys/class",
187 - ACTION_RECURSE | ACTION_FOLLOWLINKS,
188 - fileAction, dirAction, temp, 0);
189 + /* Create all devices from /sys/dev hierarchy */
190 + recursive_action("/sys/dev",
191 + ACTION_RECURSE | ACTION_FOLLOWLINKS,
192 + fileAction, dirAction, temp, 0);
193 } else {
194 char *fw;
195 char *seq;
196 --
197 2.9.2