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