mirror of
https://github.com/systemd/systemd-stable.git
synced 2024-12-23 17:34:00 +03:00
remove broken %e enumeration
This commit is contained in:
parent
f1e9ccb94d
commit
c8ff4b3db4
32
FAQ
32
FAQ
@ -14,7 +14,7 @@ A: udev works entirely in userspace, using hotplug events the kernel sends
|
||||
All device naming policy permission control and event handling is done in
|
||||
userspace. devfs is operated from within the kernel.
|
||||
|
||||
Q: Why was devfs marked OBSOLETE/removed if udev can't do everthing devfs did?
|
||||
Q: Why was devfs removed if udev can't do everthing devfs did?
|
||||
A: To quote Al Viro (Linux VFS kernel maintainer):
|
||||
- it was determined that the same thing could be done in userspace
|
||||
- devfs had been shoved into the tree in hope that its quality will
|
||||
@ -46,31 +46,25 @@ A: The devfs approach caused a lot of spurious modprobe attempts as
|
||||
spurious.
|
||||
|
||||
Q: I really like the devfs naming scheme, will udev do that?
|
||||
A: Yes, udev can create /dev nodes using the devfs naming policy. A
|
||||
configuration file needs to be created to map the kernel default names
|
||||
to the devfs names. See the udev.rules.devfs file in the udev
|
||||
release.
|
||||
Note that the devfs scheme is not recommended or officially supported
|
||||
because it is a really stupid idea to simply enumerate devices in a world
|
||||
where devices can come and go at any time. These numbers give you nothing
|
||||
but problems, and are not useful to identify a device. Have a look at the
|
||||
persistent disk rules for an example how to do it correctly in userspace
|
||||
without any stupid device enumeration.
|
||||
A: Yes, udev can create /dev nodes using the devfs naming policy. But you
|
||||
will need a custom configuration and scripts that enumerate your devices
|
||||
sequentially while events run in parallel, without a predictable order.
|
||||
The devfs scheme is not recommended or supported because it is a stupid
|
||||
idea to simply enumerate devices in a world where devices can come and go
|
||||
at any time. These numbers give you nothing but problems, and are not
|
||||
useful to identify a device. Have a look at the persistent rules for
|
||||
examples how to create persistent device names in userspace without any
|
||||
device enumeration depending on the device probing order.
|
||||
|
||||
Q: What kinds of devices does udev create nodes for?
|
||||
A: All devices that are shown in sysfs will work with udev. If more
|
||||
support is added for devices to the kernel, udev will automatically
|
||||
start working for them. All block devices are currently supported, and
|
||||
almost all major char devices are supported. Kernel developers are
|
||||
working on adding support for all char devices at this time. See the
|
||||
linux-kernel mailing list for patches and status of these patches.
|
||||
A: All devices that are shown in the kernel's sysfs tree will work with udev.
|
||||
|
||||
Q: Will udev remove the limit on the number of anonymous devices?
|
||||
A: udev is entirely in userspace. If the kernel supports a greater number
|
||||
of anonymous devices, udev will support it.
|
||||
|
||||
Q: Will udev support symlinks?
|
||||
A: Yes, It now does. Multiple symlinks per device node are supported.
|
||||
Q: Does udev support symlinks?
|
||||
A: Yes, multiple symlinks per device node are supported.
|
||||
|
||||
Q: How will udev handle the /dev filesystem?
|
||||
A: /dev is recomended to be a tmpfs filesystem that is recreated on every reboot.
|
||||
|
3
TODO
3
TODO
@ -7,9 +7,6 @@ These things need to be done, or would be nice to have:
|
||||
These things are deprecated and scheduled for removal in a future
|
||||
udev version:
|
||||
|
||||
o remove broken %e enumeration
|
||||
(simple enumerations can't work reliably and should go)
|
||||
|
||||
o remove udevstart
|
||||
(we rely on the kernel "uevent" triggers of kernel 2.6.15 and no longer
|
||||
want to guess event properties from sysfs like udevstart is doing it)
|
||||
|
@ -101,7 +101,7 @@ And now for udev:
|
||||
want to deviate away from this standard (for example when naming
|
||||
some devices in a persistent manner), it is easily possible to do
|
||||
so.
|
||||
3) udev is small (49Kb binary) and is entirely in userspace, which
|
||||
3) udev is small and is entirely in userspace, which
|
||||
is swapable, and doesn't have to be running at all times.
|
||||
|
||||
Nice, 7 out of 7 for udev. Makes you think the problems and constraints
|
||||
@ -146,7 +146,7 @@ So, how well does udev solve its goals:
|
||||
As the above scenarios show, both desktop users and big iron users
|
||||
both need to not worry about which device is assigned to what
|
||||
major/minor device.
|
||||
|
||||
|
||||
udev doesn't care what major/minor number is assigned to a device.
|
||||
It merely takes the numbers that the kernel says it assigned to the
|
||||
device and creates a device node based on it, which the user can
|
||||
@ -174,7 +174,7 @@ So, how well does udev solve its goals:
|
||||
For more information on how to create udev rules to name devices,
|
||||
please see the udev man page, and look at the example udev rules
|
||||
that ship with the tarball.
|
||||
|
||||
|
||||
|
||||
So, convinced already why you should use udev instead of devfs? No.
|
||||
Ok, fine, I'm not forcing you to abandon your bloated, stifling policy,
|
||||
|
@ -1008,74 +1008,6 @@ EOF
|
||||
exp_target => "node",
|
||||
rules => <<EOF
|
||||
BUS=="scsi", PROGRAM=="/bin/echo -n node link1 link2 link3 link4", RESULT=="node *", NAME="%c{1}", SYMLINK+="%c{2+}"
|
||||
EOF
|
||||
},
|
||||
{
|
||||
desc => "enumeration char test (single test)",
|
||||
subsys => "block",
|
||||
devpath => "/block/sda",
|
||||
exp_name => "cdrom",
|
||||
rules => <<EOF
|
||||
KERNEL=="sda", NAME="cdrom%e"
|
||||
EOF
|
||||
},
|
||||
{
|
||||
desc => "enumeration char test sequence 1/5 (keep)",
|
||||
subsys => "block",
|
||||
devpath => "/block/sda",
|
||||
exp_name => "cdrom",
|
||||
option => "keep",
|
||||
rules => <<EOF
|
||||
KERNEL=="sda", NAME="cdrom%e"
|
||||
EOF
|
||||
},
|
||||
{
|
||||
desc => "enumeration char test sequence 2/5 (keep)",
|
||||
subsys => "block",
|
||||
devpath => "/block/sda/sda1",
|
||||
exp_name => "enum",
|
||||
option => "keep",
|
||||
rules => <<EOF
|
||||
KERNEL=="sda1", NAME="enum%e"
|
||||
EOF
|
||||
},
|
||||
{
|
||||
desc => "enumeration char test sequence 3/5 (keep)",
|
||||
subsys => "block",
|
||||
devpath => "/block/sda/sda2",
|
||||
exp_name => "cdrom1",
|
||||
option => "keep",
|
||||
rules => <<EOF
|
||||
KERNEL=="sda2", NAME="cdrom%e"
|
||||
EOF
|
||||
},
|
||||
{
|
||||
desc => "enumeration char test sequence 4/5 (keep)",
|
||||
subsys => "block",
|
||||
devpath => "/block/sda/sda3",
|
||||
exp_name => "enum1",
|
||||
option => "keep",
|
||||
rules => <<EOF
|
||||
KERNEL=="sda3", NAME="enum%e"
|
||||
EOF
|
||||
},
|
||||
{
|
||||
desc => "enumeration char test sequence 5/5 (clean)",
|
||||
subsys => "block",
|
||||
devpath => "/block/sda/sda4",
|
||||
exp_name => "cdrom2",
|
||||
option => "clean",
|
||||
rules => <<EOF
|
||||
KERNEL=="sda4", NAME="cdrom%e"
|
||||
EOF
|
||||
},
|
||||
{
|
||||
desc => "enumeration char test after cleanup (single test)",
|
||||
subsys => "block",
|
||||
devpath => "/block/sda",
|
||||
exp_name => "cdrom",
|
||||
rules => <<EOF
|
||||
KERNEL=="sda", NAME="cdrom%e"
|
||||
EOF
|
||||
},
|
||||
{
|
||||
|
92
udev_rules.c
92
udev_rules.c
@ -263,88 +263,6 @@ static int import_parent_into_env(struct udevice *udev, const char *filter)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int match_name_and_get_number(const char *base, const char *devname)
|
||||
{
|
||||
size_t baselen;
|
||||
char *endptr;
|
||||
int num;
|
||||
|
||||
baselen = strlen(base);
|
||||
if (strncmp(base, devname, baselen) != 0)
|
||||
return -1;
|
||||
if (devname[baselen] == '\0')
|
||||
return 0;
|
||||
if (!isdigit(devname[baselen]))
|
||||
return -1;
|
||||
num = strtoul(&devname[baselen], &endptr, 10);
|
||||
if (endptr[0] != '\0')
|
||||
return -1;
|
||||
return num;
|
||||
}
|
||||
|
||||
/* finds the lowest positive device number such that <name>N isn't present in the udevdb
|
||||
* if <name> doesn't exist, 0 is returned, N otherwise */
|
||||
static int find_free_number(const char *base, const char *devpath)
|
||||
{
|
||||
char db_devpath[PATH_SIZE];
|
||||
char filename[PATH_SIZE];
|
||||
struct udevice *udev_db;
|
||||
int num = 0;
|
||||
static int warn = 1;
|
||||
|
||||
if (warn) {
|
||||
err("%%e is deprecated, will be removed and is unlikely to work correctly. Don't use it.");
|
||||
warn = 0;
|
||||
}
|
||||
|
||||
/* check if the device already owns a matching name */
|
||||
udev_db = udev_device_init();
|
||||
if (udev_db == NULL)
|
||||
return -1;
|
||||
if (udev_db_get_device(udev_db, devpath) == 0) {
|
||||
struct name_entry *name_loop;
|
||||
int devnum;
|
||||
|
||||
devnum = match_name_and_get_number(base, udev_db->name);
|
||||
if (devnum >= 0) {
|
||||
num = devnum;
|
||||
dbg("device '%s', already has the node '%s' with num %u, use it", devpath, base, num);
|
||||
goto out;
|
||||
}
|
||||
list_for_each_entry(name_loop, &udev_db->symlink_list, node) {
|
||||
devnum = match_name_and_get_number(base, name_loop->name);
|
||||
if (devnum >= 0) {
|
||||
num = devnum;
|
||||
dbg("device '%s', already has a symlink '%s' with num %u, use it", devpath, base, num);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* just search the database again and again until a free name is found */
|
||||
strlcpy(filename, base, sizeof(filename));
|
||||
while (1) {
|
||||
dbg("look for existing node '%s'", filename);
|
||||
if (udev_db_lookup_name(filename, db_devpath, sizeof(db_devpath)) != 0) {
|
||||
dbg("free num=%d", num);
|
||||
break;
|
||||
}
|
||||
|
||||
num++;
|
||||
if (num > 100000) {
|
||||
err("find_free_number aborted at num=%d", num);
|
||||
num = -1;
|
||||
break;
|
||||
}
|
||||
snprintf(filename, sizeof(filename), "%s%d", base, num);
|
||||
filename[sizeof(filename)-1] = '\0';
|
||||
}
|
||||
|
||||
out:
|
||||
udev_device_cleanup(udev_db);
|
||||
return num;
|
||||
}
|
||||
|
||||
#define WAIT_LOOP_PER_SECOND 50
|
||||
static int wait_for_sysfs(struct udevice *udev, const char *file, int timeout)
|
||||
{
|
||||
@ -386,7 +304,6 @@ void udev_rules_apply_format(struct udevice *udev, char *string, size_t maxsize)
|
||||
int len;
|
||||
int i;
|
||||
int count;
|
||||
unsigned int next_free_number;
|
||||
enum subst_type {
|
||||
SUBST_UNKNOWN,
|
||||
SUBST_DEVPATH,
|
||||
@ -397,7 +314,6 @@ void udev_rules_apply_format(struct udevice *udev, char *string, size_t maxsize)
|
||||
SUBST_MINOR,
|
||||
SUBST_RESULT,
|
||||
SUBST_SYSFS,
|
||||
SUBST_ENUM,
|
||||
SUBST_PARENT,
|
||||
SUBST_TEMP_NODE,
|
||||
SUBST_ROOT,
|
||||
@ -416,7 +332,6 @@ void udev_rules_apply_format(struct udevice *udev, char *string, size_t maxsize)
|
||||
{ .name = "minor", .fmt = 'm', .type = SUBST_MINOR },
|
||||
{ .name = "result", .fmt = 'c', .type = SUBST_RESULT },
|
||||
{ .name = "sysfs", .fmt = 's', .type = SUBST_SYSFS },
|
||||
{ .name = "enum", .fmt = 'e', .type = SUBST_ENUM },
|
||||
{ .name = "parent", .fmt = 'P', .type = SUBST_PARENT },
|
||||
{ .name = "tempnode", .fmt = 'N', .type = SUBST_TEMP_NODE },
|
||||
{ .name = "root", .fmt = 'r', .type = SUBST_ROOT },
|
||||
@ -572,13 +487,6 @@ found:
|
||||
dbg("substitute sysfs value '%s'", temp2);
|
||||
}
|
||||
break;
|
||||
case SUBST_ENUM:
|
||||
next_free_number = find_free_number(string, udev->dev->devpath);
|
||||
if (next_free_number > 0) {
|
||||
sprintf(temp2, "%d", next_free_number);
|
||||
strlcat(string, temp2, maxsize);
|
||||
}
|
||||
break;
|
||||
case SUBST_PARENT:
|
||||
{
|
||||
struct sysfs_device *dev_parent;
|
||||
|
Loading…
Reference in New Issue
Block a user