diff --git a/1021-udev-re-add-persistent-net-rules.patch b/1021-udev-re-add-persistent-net-rules.patch new file mode 100644 index 00000000..b329e1a5 --- /dev/null +++ b/1021-udev-re-add-persistent-net-rules.patch @@ -0,0 +1,501 @@ +Index: systemd-210/src/udev/rule_generator/75-persistent-net-generator.rules +=================================================================== +--- /dev/null ++++ systemd-210/src/udev/rule_generator/75-persistent-net-generator.rules +@@ -0,0 +1,105 @@ ++# do not edit this file, it will be overwritten on update ++ ++# these rules generate rules for persistent network device naming ++# ++# variables used to communicate: ++# MATCHADDR MAC address used for the match ++# MATCHID bus_id used for the match ++# MATCHDRV driver name used for the match ++# MATCHIFTYPE interface type match ++# COMMENT comment to add to the generated rule ++# INTERFACE_NAME requested name supplied by external tool ++# INTERFACE_NEW new interface name returned by rule writer ++ ++ACTION!="add", GOTO="persistent_net_generator_end" ++SUBSYSTEM!="net", GOTO="persistent_net_generator_end" ++ ++# ignore the interface if a name has already been set ++NAME=="?*", GOTO="persistent_net_generator_end" ++ ++IMPORT{cmdline}="net.ifnames" ++ENV{net.ifnames}!="0", GOTO="persistent_net_generator_end" ++ ++# device name whitelist ++KERNEL!="eth*|ath*|wlan*[0-9]|msh*|ra*|sta*|ctc*|lcs*|hsi*", GOTO="persistent_net_generator_end" ++ ++# ignore Xen virtual interfaces ++SUBSYSTEMS=="xen", GOTO="persistent_net_generator_end" ++ ++# read MAC address ++ENV{MATCHADDR}="$attr{address}" ++ ++# match interface type ++ENV{MATCHIFTYPE}="$attr{type}" ++ ++# ignore KVM virtual interfaces ++ENV{MATCHADDR}=="52:54:00:*", GOTO="persistent_net_generator_end" ++# ignore VMWare virtual interfaces ++ENV{MATCHADDR}=="00:0c:29:*|00:50:56:*", GOTO="persistent_net_generator_end" ++# ignore Hyper-V virtual interfaces ++ENV{MATCHADDR}=="00:15:5d:*", GOTO="persistent_net_generator_end" ++ ++# These vendors are known to violate the local MAC address assignment scheme ++# Interlan, DEC (UNIBUS or QBUS), Apollo, Cisco, Racal-Datacom ++ENV{MATCHADDR}=="02:07:01:*", GOTO="globally_administered_whitelist" ++# 3Com ++ENV{MATCHADDR}=="02:60:60:*", GOTO="globally_administered_whitelist" ++# 3Com IBM PC; Imagen; Valid; Cisco; Apple ++ENV{MATCHADDR}=="02:60:8c:*", GOTO="globally_administered_whitelist" ++# Intel ++ENV{MATCHADDR}=="02:a0:c9:*", GOTO="globally_administered_whitelist" ++# Olivetti ++ENV{MATCHADDR}=="02:aa:3c:*", GOTO="globally_administered_whitelist" ++# CMC Masscomp; Silicon Graphics; Prime EXL ++ENV{MATCHADDR}=="02:cf:1f:*", GOTO="globally_administered_whitelist" ++# Prominet Corporation Gigabit Ethernet Switch ++ENV{MATCHADDR}=="02:e0:3b:*", GOTO="globally_administered_whitelist" ++# BTI (Bus-Tech, Inc.) IBM Mainframes ++ENV{MATCHADDR}=="02:e6:d3:*", GOTO="globally_administered_whitelist" ++# Realtek ++ENV{MATCHADDR}=="52:54:00:*", GOTO="globally_administered_whitelist" ++# Novell 2000 ++ENV{MATCHADDR}=="52:54:4c:*", GOTO="globally_administered_whitelist" ++# Realtec ++ENV{MATCHADDR}=="52:54:ab:*", GOTO="globally_administered_whitelist" ++# Kingston Technologies ++ENV{MATCHADDR}=="e2:0c:0f:*", GOTO="globally_administered_whitelist" ++# Xensource ++ENV{MATCHADDR}=="00:16:3e:*", GOTO="globally_administered_whitelist" ++ ++# match interface dev_id ++ATTR{dev_id}=="?*", ENV{MATCHDEVID}="$attr{dev_id}" ++ ++# do not use "locally administered" MAC address ++ENV{MATCHADDR}=="?[2367abef]:*", ENV{MATCHADDR}="" ++ ++# do not use empty address ++ENV{MATCHADDR}=="00:00:00:00:00:00", ENV{MATCHADDR}="" ++ ++LABEL="globally_administered_whitelist" ++ ++# build comment line for generated rule: ++SUBSYSTEMS=="pci", ENV{COMMENT}="PCI device $attr{vendor}:$attr{device} ($driver)" ++SUBSYSTEMS=="usb", ATTRS{idVendor}=="?*", ENV{COMMENT}="USB device 0x$attr{idVendor}:0x$attr{idProduct} ($driver)" ++SUBSYSTEMS=="pcmcia", ENV{COMMENT}="PCMCIA device $attr{card_id}:$attr{manf_id} ($driver)" ++SUBSYSTEMS=="ieee1394", ENV{COMMENT}="Firewire device $attr{host_id})" ++ ++# ibmveth likes to use "locally administered" MAC addresses ++DRIVERS=="ibmveth", ENV{MATCHADDR}="$attr{address}", ENV{COMMENT}="ibmveth ($id)" ++ ++# S/390 uses id matches only, do not use MAC address match ++SUBSYSTEMS=="ccwgroup", ENV{COMMENT}="S/390 $driver device at $id", ENV{MATCHID}="$id", ENV{MATCHDRV}="$driver", ENV{MATCHADDR}="" ++ ++# see if we got enough data to create a rule ++ENV{MATCHADDR}=="", ENV{MATCHID}=="", ENV{INTERFACE_NAME}=="", GOTO="persistent_net_generator_end" ++ ++# default comment ++ENV{COMMENT}=="", ENV{COMMENT}="net device ($attr{driver})" ++ ++# write rule ++DRIVERS=="?*", IMPORT{program}="write_net_rules" ++ ++# rename interface if needed ++ENV{INTERFACE_NEW}=="?*", NAME="$env{INTERFACE_NEW}" ++ ++LABEL="persistent_net_generator_end" +Index: systemd-210/src/udev/rule_generator/rule_generator.functions +=================================================================== +--- /dev/null ++++ systemd-210/src/udev/rule_generator/rule_generator.functions +@@ -0,0 +1,113 @@ ++# functions used by the udev rule generator ++ ++# Copyright (C) 2006 Marco d'Itri ++ ++# This program is free software: you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation, either version 2 of the License, or ++# (at your option) any later version. ++ ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++ ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see . ++ ++PATH='/usr/bin:/bin:/usr/sbin:/sbin' ++ ++# Read a single line from file $1 in the $DEVPATH directory. ++# The function must not return an error even if the file does not exist. ++sysread() { ++ local file="$1" ++ [ -e "/sys$DEVPATH/$file" ] || return 0 ++ local value ++ read value < "/sys$DEVPATH/$file" || return 0 ++ echo "$value" ++} ++ ++sysreadlink() { ++ local file="$1" ++ [ -e "/sys$DEVPATH/$file" ] || return 0 ++ readlink -f /sys$DEVPATH/$file 2> /dev/null || true ++} ++ ++# Return true if a directory is writeable. ++writeable() { ++ if ln -s test-link $1/.is-writeable 2> /dev/null; then ++ rm -f $1/.is-writeable ++ return 0 ++ else ++ return 1 ++ fi ++} ++ ++# Create a lock file for the current rules file. ++lock_rules_file() { ++ RUNDIR="/run/udev" ++ [ -e "$RUNDIR" ] || return 0 ++ ++ RULES_LOCK="$RUNDIR/.lock-${RULES_FILE##*/}" ++ ++ retry=30 ++ while ! mkdir $RULES_LOCK 2> /dev/null; do ++ if [ $retry -eq 0 ]; then ++ echo "Cannot lock $RULES_FILE!" >&2 ++ exit 2 ++ fi ++ sleep 1 ++ retry=$(($retry - 1)) ++ done ++} ++ ++unlock_rules_file() { ++ [ "$RULES_LOCK" ] || return 0 ++ rmdir $RULES_LOCK || true ++} ++ ++# Choose the real rules file if it is writeable or a temporary file if not. ++# Both files should be checked later when looking for existing rules. ++choose_rules_file() { ++ RUNDIR="/run/udev" ++ local tmp_rules_file="$RUNDIR/tmp-rules--${RULES_FILE##*/}" ++ [ -e "$RULES_FILE" -o -e "$tmp_rules_file" ] || PRINT_HEADER=1 ++ ++ if writeable ${RULES_FILE%/*}; then ++ RO_RULES_FILE='/dev/null' ++ else ++ RO_RULES_FILE=$RULES_FILE ++ RULES_FILE=$tmp_rules_file ++ fi ++} ++ ++# Return the name of the first free device. ++raw_find_next_available() { ++ local links="$1" ++ ++ local basename=${links%%[ 0-9]*} ++ local max=-1 ++ for name in $links; do ++ local num=${name#$basename} ++ [ "$num" ] || num=0 ++ [ $num -gt $max ] && max=$num ++ done ++ ++ local max=$(($max + 1)) ++ # "name0" actually is just "name" ++ [ $max -eq 0 ] && return ++ echo "$max" ++} ++ ++# Find all rules matching a key (with action) and a pattern. ++find_all_rules() { ++ local key="$1" ++ local linkre="$2" ++ local match="$3" ++ ++ local search='.*[[:space:],]'"$key"'"('"$linkre"')".*' ++ echo $(sed -n -r -e 's/^#.*//' -e "${match}s/${search}/\1/p" \ ++ $RO_RULES_FILE \ ++ $([ -e $RULES_FILE ] && echo $RULES_FILE) \ ++ 2>/dev/null) ++} +Index: systemd-210/src/udev/rule_generator/write_net_rules +=================================================================== +--- /dev/null ++++ systemd-210/src/udev/rule_generator/write_net_rules +@@ -0,0 +1,141 @@ ++#!/bin/sh -e ++ ++# This script is run to create persistent network device naming rules ++# based on properties of the device. ++# If the interface needs to be renamed, INTERFACE_NEW= will be printed ++# on stdout to allow udev to IMPORT it. ++ ++# variables used to communicate: ++# MATCHADDR MAC address used for the match ++# MATCHID bus_id used for the match ++# MATCHDEVID dev_id used for the match ++# MATCHDRV driver name used for the match ++# MATCHIFTYPE interface type match ++# COMMENT comment to add to the generated rule ++# INTERFACE_NAME requested name supplied by external tool ++# INTERFACE_NEW new interface name returned by rule writer ++ ++# Copyright (C) 2006 Marco d'Itri ++# Copyright (C) 2007 Kay Sievers ++# ++# This program is free software: you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation, either version 2 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see . ++ ++# debug, if UDEV_LOG= ++if [ -n "$UDEV_LOG" ]; then ++ if [ "$UDEV_LOG" -ge 7 ]; then ++ set -x ++ fi ++fi ++ ++RULES_FILE='/etc/udev/rules.d/70-persistent-net.rules' ++ ++. /usr/lib/udev/rule_generator.functions ++ ++interface_name_taken() { ++ local value="$(find_all_rules 'NAME=' $INTERFACE)" ++ if [ "$value" ]; then ++ return 0 ++ else ++ return 1 ++ fi ++} ++ ++find_next_available() { ++ raw_find_next_available "$(find_all_rules 'NAME=' "$1")" ++} ++ ++write_rule() { ++ local match="$1" ++ local name="$2" ++ local comment="$3" ++ ++ { ++ if [ "$PRINT_HEADER" ]; then ++ PRINT_HEADER= ++ echo "# This file was automatically generated by the $0" ++ echo "# program, run by the persistent-net-generator.rules rules file." ++ echo "#" ++ echo "# You can modify it, as long as you keep each rule on a single" ++ echo "# line, and change only the value of the NAME= key." ++ fi ++ ++ echo "" ++ [ "$comment" ] && echo "# $comment" ++ echo "SUBSYSTEM==\"net\", ACTION==\"add\"$match, NAME=\"$name\"" ++ } >> $RULES_FILE ++} ++ ++if [ -z "$INTERFACE" ]; then ++ echo "missing \$INTERFACE" >&2 ++ exit 1 ++fi ++ ++# Prevent concurrent processes from modifying the file at the same time. ++lock_rules_file ++ ++# Check if the rules file is writeable. ++choose_rules_file ++ ++# the DRIVERS key is needed to not match bridges and VLAN sub-interfaces ++if [ "$MATCHADDR" ]; then ++ match="$match, DRIVERS==\"?*\", ATTR{address}==\"$MATCHADDR\"" ++fi ++ ++if [ "$MATCHDRV" ]; then ++ match="$match, DRIVERS==\"$MATCHDRV\"" ++fi ++ ++if [ "$MATCHDEVID" ]; then ++ match="$match, ATTR{dev_id}==\"$MATCHDEVID\"" ++fi ++ ++if [ "$MATCHID" ]; then ++ match="$match, KERNELS==\"$MATCHID\"" ++fi ++ ++if [ "$MATCHIFTYPE" ]; then ++ match="$match, ATTR{type}==\"$MATCHIFTYPE\"" ++fi ++ ++if [ -z "$match" ]; then ++ echo "missing valid match" >&2 ++ unlock_rules_file ++ exit 1 ++fi ++ ++basename=${INTERFACE%%[0-9]*} ++match="$match, KERNEL==\"$basename*\"" ++ ++if [ "$INTERFACE_NAME" ]; then ++ # external tools may request a custom name ++ COMMENT="$COMMENT (custom name provided by external tool)" ++ if [ "$INTERFACE_NAME" != "$INTERFACE" ]; then ++ INTERFACE=$INTERFACE_NAME; ++ echo "INTERFACE_NEW=$INTERFACE" ++ fi ++else ++ # if a rule using the current name already exists, find a new name ++ if interface_name_taken; then ++ INTERFACE="$basename$(find_next_available "$basename[0-9]*")" ++ # prevent INTERFACE from being "eth" instead of "eth0" ++ [ "$INTERFACE" = "${INTERFACE%%[ \[\]0-9]*}" ] && INTERFACE=${INTERFACE}0 ++ echo "INTERFACE_NEW=$INTERFACE" ++ fi ++fi ++ ++write_rule "$match" "$INTERFACE" "$COMMENT" ++ ++unlock_rules_file ++ ++exit 0 +Index: systemd-210/Makefile.am +=================================================================== +--- systemd-210.orig/Makefile.am ++++ systemd-210/Makefile.am +@@ -2552,7 +2552,14 @@ dist_udevrules_DATA += \ + rules/75-tty-description.rules \ + rules/78-sound-card.rules \ + rules/80-net-setup-link.rules \ +- rules/95-udev-late.rules ++ rules/95-udev-late.rules \ ++ src/udev/rule_generator/75-persistent-net-generator.rules \ ++ src/udev/rule_generator/76-net-sriov-names.rules ++ ++udevlibexec_PROGRAMS += \ ++ src/udev/rule_generator/rule_generator.functions \ ++ src/udev/rule_generator/write_net_rules \ ++ src/udev/rule_generator/net-set-sriov-names + + dist_udevhwdb_DATA = \ + hwdb/20-pci-vendor-model.hwdb \ +Index: systemd-210/src/udev/rule_generator/76-net-sriov-names.rules +=================================================================== +--- /dev/null ++++ systemd-210/src/udev/rule_generator/76-net-sriov-names.rules +@@ -0,0 +1,18 @@ ++# do not edit this file, it will be overwritten on update ++# ++# rename SRIOV virtual function interfaces ++ ++ACTION=="remove", GOTO="net-sriov-names_end" ++SUBSYSTEM!="net", GOTO="net-sriov-names_end" ++ ++IMPORT{cmdline}="net.ifnames" ++ENV{net.ifnames}!="0", GOTO="net-sriov-names_end" ++ ++SUBSYSTEM=="net", SUBSYSTEMS=="pci", ACTION=="add", NAME=="?*", ENV{INTERFACE_NEW}="$name" ++SUBSYSTEM=="net", SUBSYSTEMS=="pci", ACTION=="add", IMPORT{program}="net-set-sriov-names" ++ ++# rename interface if needed ++ENV{INTERFACE_NEW}=="?*", NAME="$env{INTERFACE_NEW}" ++ENV{INTERFACE_NEW}=="", DRIVERS=="cxgb4vf|igbvf|ixgbevf", NAME="vf$attr{ifindex}" ++ ++LABEL="net-sriov-names_end" +Index: systemd-210/src/udev/rule_generator/net-set-sriov-names +=================================================================== +--- /dev/null ++++ systemd-210/src/udev/rule_generator/net-set-sriov-names +@@ -0,0 +1,79 @@ ++#!/bin/bash -e ++# ++# This script is run to rename virtual interfaces ++# ++ ++if [ -n "$UDEV_LOG" ]; then ++ if [ "$UDEV_LOG" -ge 7 ]; then ++ set -x ++ fi ++fi ++ ++# according to dev_new_index(), ifindex is within [1, INT_MAX] ++int_max=$(/usr/bin/getconf INT_MAX) ++ifindex_before() { ++ a=$1 ++ b=$2 ++ ++ ((0 < (b - a) && (b - a) < int_max / 2 || ++ -1 * int_max < (b - a) && (b - a) < -1 * int_max / 2)) ++} ++ ++rename_interface() { ++ local src_net=$1 ++ local dest_net=$2 ++ local err=0 ++ ++ /sbin/ip link set dev $src_net down ++ /sbin/ip link set dev $src_net name $dest_net ++} ++ ++if [ -z "$INTERFACE" ]; then ++ echo "missing \$INTERFACE" >&2 ++ exit 1 ++fi ++ ++if [ -e "/sys/class/net/$INTERFACE/device/physfn" ]; then ++ pf=$(ls -1 "/sys/class/net/$INTERFACE/device/physfn/net") ++ if [ $(echo "$pf" | wc -l) -ne 1 ]; then ++ echo "too many pf's" >&2 ++ exit 1 ++ fi ++ read vfindex < "/sys/class/net/$INTERFACE/ifindex" ++ read pfindex < "/sys/class/net/$pf/ifindex" ++ if ifindex_before $pfindex $vfindex; then ++ bus_info=$(basename $(readlink "/sys/class/net/$INTERFACE/device")) ++ for virtfn in "/sys/class/net/$pf/device/"virtfn*; do ++ if [ "$(basename $(readlink "$virtfn"))" = "$bus_info" ]; then ++ vfnum=$(basename "$virtfn") ++ vfnum=${vfnum#virtfn} ++ echo "INTERFACE_NEW=$pf.vf$vfnum" ++ exit 0 ++ fi ++ done ++ fi ++fi ++ ++read pfindex < "/sys/class/net/$INTERFACE/ifindex" ++shopt -s nullglob ++for virtfn in "/sys/class/net/$INTERFACE/device/"virtfn*; do ++ vf=$(ls -1 "$virtfn/net") ++ if [ $(echo "$vf" | wc -l) -ne 1 ]; then ++ echo "too many vf's" >&2 ++ exit 1 ++ fi ++ read vfindex < "/sys/class/net/$vf/ifindex" ++ if ifindex_before $vfindex $pfindex; then ++ vfnum=$(basename "$virtfn") ++ vfnum=${vfnum#virtfn} ++ if [ "$INTERFACE_NEW" ]; then ++ new_name=$INTERFACE_NEW ++ else ++ new_name=$INTERFACE ++ fi ++ new_name="$new_name.vf$vfnum" ++ if [ "$vf" != "$new_name" ]; then ++ rename_interface "$vf" "$new_name" ++ fi ++ fi ++done diff --git a/1022-udev-remove-seqnum-API-and-all-assumptions-about-seq.patch b/1022-udev-remove-seqnum-API-and-all-assumptions-about-seq.patch new file mode 100644 index 00000000..db403e31 --- /dev/null +++ b/1022-udev-remove-seqnum-API-and-all-assumptions-about-seq.patch @@ -0,0 +1,1443 @@ +From 9ea28c55a2488e6cd4a44ac5786f12b71ad5bc9f Mon Sep 17 00:00:00 2001 +From: Kay Sievers +Date: Sat, 12 Apr 2014 22:35:50 -0700 +Subject: [PATCH] udev: remove seqnum API and all assumptions about seqnums + +The way the kernel namespaces have been implemented breaks assumptions +udev made regarding uevent sequence numbers. Creating devices in a +namespace "steals" uevents and its sequence numbers from the host. It +confuses the "udevadmin settle" logic, which might block until util a +timeout is reached, even when no uevent is pending. + +Remove any assumptions about sequence numbers and deprecate libudev's +API exposing these numbers; none of that can reliably be used anymore +when namespaces are involved. + +Signed-off-by: Robert Milasan +--- + Makefile.am | 6 +- + man/udevadm.xml | 22 -- + src/libudev/libudev-monitor.c | 17 +- + src/libudev/libudev-queue-private.c | 406 ------------------------------------ + src/libudev/libudev-queue.c | 302 ++------------------------- + src/libudev/libudev.h | 10 +- + src/shared/udev-util.h | 2 - + src/test/test-libudev.c | 24 --- + src/udev/udev-ctrl.c | 2 +- + src/udev/udevadm-settle.c | 131 ++---------- + src/udev/udevd.c | 59 +++--- + 11 files changed, 84 insertions(+), 897 deletions(-) + delete mode 100644 src/libudev/libudev-queue-private.c + +Index: systemd-210/Makefile.am +=================================================================== +--- systemd-210.orig/Makefile.am ++++ systemd-210/Makefile.am +@@ -2520,8 +2520,7 @@ noinst_LTLIBRARIES += \ + + libudev_internal_la_SOURCES =\ + $(libudev_la_SOURCES) \ +- src/libudev/libudev-device-private.c \ +- src/libudev/libudev-queue-private.c ++ src/libudev/libudev-device-private.c + + libudev_internal_la_CFLAGS = \ + $(AM_CFLAGS) \ +@@ -5063,6 +5062,9 @@ test_libsystemd_sym_LDADD = \ + + test_libudev_sym_SOURCES = \ + test-libudev-sym.c ++test_libudev_sym_CFLAGS = \ ++ $(AM_CFLAGS) \ ++ -Wno-deprecated-declarations + test_libudev_sym_LDADD = \ + libudev.la + +Index: systemd-210/man/udevadm.xml +=================================================================== +--- systemd-210.orig/man/udevadm.xml ++++ systemd-210/man/udevadm.xml +@@ -339,21 +339,6 @@ + + + +- +- +- +- Wait only for events after the given sequence +- number. +- +- +- +- +- +- +- Wait only for events before the given sequence number. +- +- +- + + + +@@ -361,13 +346,6 @@ + + + +- +- +- +- Do not print any output, like the remaining queue entries when reaching the timeout. +- +- +- + + + +Index: systemd-210/src/libudev/libudev-monitor.c +=================================================================== +--- systemd-210.orig/src/libudev/libudev-monitor.c ++++ systemd-210/src/libudev/libudev-monitor.c +@@ -147,21 +147,6 @@ static bool udev_has_devtmpfs(struct ude + return false; + } + +-/* we consider udev running when we have running udev service */ +-static bool udev_has_service(struct udev *udev) { +- struct udev_queue *queue; +- bool active; +- +- queue = udev_queue_new(udev); +- if (!queue) +- return false; +- +- active = udev_queue_get_udev_is_active(queue); +- udev_queue_unref(queue); +- +- return active; +-} +- + struct udev_monitor *udev_monitor_new_from_netlink_fd(struct udev *udev, const char *name, int fd) + { + struct udev_monitor *udev_monitor; +@@ -185,7 +170,7 @@ struct udev_monitor *udev_monitor_new_fr + * We do not set a netlink multicast group here, so the socket + * will not receive any messages. + */ +- if (!udev_has_service(udev) && !udev_has_devtmpfs(udev)) { ++ if (access("/run/udev/control", F_OK) < 0 && !udev_has_devtmpfs(udev)) { + udev_dbg(udev, "the udev service seems not to be active, disable the monitor\n"); + group = UDEV_MONITOR_NONE; + } else +Index: systemd-210/src/libudev/libudev-queue-private.c +=================================================================== +--- systemd-210.orig/src/libudev/libudev-queue-private.c ++++ /dev/null +@@ -1,406 +0,0 @@ +-/*** +- This file is part of systemd. +- +- Copyright 2008-2012 Kay Sievers +- Copyright 2009 Alan Jenkins +- +- systemd is free software; you can redistribute it and/or modify it +- under the terms of the GNU Lesser General Public License as published by +- the Free Software Foundation; either version 2.1 of the License, or +- (at your option) any later version. +- +- systemd is distributed in the hope that it will be useful, but +- WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- Lesser General Public License for more details. +- +- You should have received a copy of the GNU Lesser General Public License +- along with systemd; If not, see . +-***/ +- +-/* +- * DISCLAIMER - The file format mentioned here is private to udev/libudev, +- * and may be changed without notice. +- * +- * The udev event queue is exported as a binary log file. +- * Each log record consists of a sequence number followed by the device path. +- * +- * When a new event is queued, its details are appended to the log. +- * When the event finishes, a second record is appended to the log +- * with the same sequence number but a devpath len of 0. +- * +- * Example: +- * { 0x0000000000000001 } +- * { 0x0000000000000001, 0x0019, "/devices/virtual/mem/null" }, +- * { 0x0000000000000002, 0x001b, "/devices/virtual/mem/random" }, +- * { 0x0000000000000001, 0x0000 }, +- * { 0x0000000000000003, 0x0019, "/devices/virtual/mem/zero" }, +- * +- * Events 2 and 3 are still queued, but event 1 has finished. +- * +- * The queue does not grow indefinitely. It is periodically re-created +- * to remove finished events. Atomic rename() makes this transparent to readers. +- * +- * The queue file starts with a single sequence number which specifies the +- * minimum sequence number in the log that follows. Any events prior to this +- * sequence number have already finished. +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include "libudev.h" +-#include "libudev-private.h" +- +-static int rebuild_queue_file(struct udev_queue_export *udev_queue_export); +- +-struct udev_queue_export { +- struct udev *udev; +- int queued_count; /* number of unfinished events exported in queue file */ +- FILE *queue_file; +- unsigned long long int seqnum_max; /* earliest sequence number in queue file */ +- unsigned long long int seqnum_min; /* latest sequence number in queue file */ +- int waste_bytes; /* queue file bytes wasted on finished events */ +-}; +- +-struct udev_queue_export *udev_queue_export_new(struct udev *udev) +-{ +- struct udev_queue_export *udev_queue_export; +- unsigned long long int initial_seqnum; +- +- if (udev == NULL) +- return NULL; +- +- udev_queue_export = new0(struct udev_queue_export, 1); +- if (udev_queue_export == NULL) +- return NULL; +- udev_queue_export->udev = udev; +- +- initial_seqnum = udev_get_kernel_seqnum(udev); +- udev_queue_export->seqnum_min = initial_seqnum; +- udev_queue_export->seqnum_max = initial_seqnum; +- +- udev_queue_export_cleanup(udev_queue_export); +- if (rebuild_queue_file(udev_queue_export) != 0) { +- free(udev_queue_export); +- return NULL; +- } +- +- return udev_queue_export; +-} +- +-struct udev_queue_export *udev_queue_export_unref(struct udev_queue_export *udev_queue_export) +-{ +- if (udev_queue_export == NULL) +- return NULL; +- if (udev_queue_export->queue_file != NULL) +- fclose(udev_queue_export->queue_file); +- free(udev_queue_export); +- return NULL; +-} +- +-void udev_queue_export_cleanup(struct udev_queue_export *udev_queue_export) +-{ +- if (udev_queue_export == NULL) +- return; +- unlink("/run/udev/queue.tmp"); +- unlink("/run/udev/queue.bin"); +-} +- +-static int skip_to(FILE *file, long offset) +-{ +- long old_offset; +- +- /* fseek may drop buffered data, avoid it for small seeks */ +- old_offset = ftell(file); +- if (offset > old_offset && offset - old_offset <= BUFSIZ) { +- size_t skip_bytes = offset - old_offset; +- char *buf = alloca(skip_bytes); +- +- if (fread(buf, skip_bytes, 1, file) != skip_bytes) +- return -1; +- } +- +- return fseek(file, offset, SEEK_SET); +-} +- +-struct queue_devpaths { +- unsigned int devpaths_first; /* index of first queued event */ +- unsigned int devpaths_size; +- long devpaths[]; /* seqnum -> offset of devpath in queue file (or 0) */ +-}; +- +-/* +- * Returns a table mapping seqnum to devpath file offset for currently queued events. +- * devpaths[i] represents the event with seqnum = i + udev_queue_export->seqnum_min. +- */ +-static struct queue_devpaths *build_index(struct udev_queue_export *udev_queue_export) +-{ +- struct queue_devpaths *devpaths; +- unsigned long long int range; +- long devpath_offset; +- ssize_t devpath_len; +- unsigned long long int seqnum; +- unsigned long long int n; +- unsigned int i; +- +- /* seek to the first event in the file */ +- rewind(udev_queue_export->queue_file); +- udev_queue_read_seqnum(udev_queue_export->queue_file, &seqnum); +- +- /* allocate the table */ +- range = udev_queue_export->seqnum_min - udev_queue_export->seqnum_max; +- if (range - 1 > INT_MAX) { +- udev_err(udev_queue_export->udev, "queue file overflow\n"); +- return NULL; +- } +- devpaths = malloc0(sizeof(struct queue_devpaths) + (range + 1) * sizeof(long)); +- if (devpaths == NULL) +- return NULL; +- devpaths->devpaths_size = range + 1; +- +- /* read all records and populate the table */ +- for (;;) { +- if (udev_queue_read_seqnum(udev_queue_export->queue_file, &seqnum) < 0) +- break; +- n = seqnum - udev_queue_export->seqnum_max; +- if (n >= devpaths->devpaths_size) +- goto read_error; +- +- devpath_offset = ftell(udev_queue_export->queue_file); +- devpath_len = udev_queue_skip_devpath(udev_queue_export->queue_file); +- if (devpath_len < 0) +- goto read_error; +- +- if (devpath_len > 0) +- devpaths->devpaths[n] = devpath_offset; +- else +- devpaths->devpaths[n] = 0; +- } +- +- /* find first queued event */ +- for (i = 0; i < devpaths->devpaths_size; i++) { +- if (devpaths->devpaths[i] != 0) +- break; +- } +- devpaths->devpaths_first = i; +- +- return devpaths; +- +-read_error: +- udev_err(udev_queue_export->udev, "queue file corrupted\n"); +- free(devpaths); +- return NULL; +-} +- +-static int rebuild_queue_file(struct udev_queue_export *udev_queue_export) +-{ +- unsigned long long int seqnum; +- struct queue_devpaths *devpaths = NULL; +- FILE *new_queue_file = NULL; +- unsigned int i; +- +- /* read old queue file */ +- if (udev_queue_export->queue_file != NULL) { +- devpaths = build_index(udev_queue_export); +- if (devpaths != NULL) +- udev_queue_export->seqnum_max += devpaths->devpaths_first; +- } +- if (devpaths == NULL) { +- udev_queue_export->queued_count = 0; +- udev_queue_export->seqnum_max = udev_queue_export->seqnum_min; +- } +- +- /* create new queue file */ +- new_queue_file = fopen("/run/udev/queue.tmp", "w+e"); +- if (new_queue_file == NULL) +- goto error; +- seqnum = udev_queue_export->seqnum_max; +- fwrite(&seqnum, 1, sizeof(unsigned long long int), new_queue_file); +- +- /* copy unfinished events only to the new file */ +- if (devpaths != NULL) { +- for (i = devpaths->devpaths_first; i < devpaths->devpaths_size; i++) { +- char devpath[UTIL_PATH_SIZE]; +- int err; +- unsigned short devpath_len; +- +- if (devpaths->devpaths[i] != 0) +- { +- skip_to(udev_queue_export->queue_file, devpaths->devpaths[i]); +- err = udev_queue_read_devpath(udev_queue_export->queue_file, devpath, sizeof(devpath)); +- devpath_len = err; +- +- fwrite(&seqnum, sizeof(unsigned long long int), 1, new_queue_file); +- fwrite(&devpath_len, sizeof(unsigned short), 1, new_queue_file); +- fwrite(devpath, 1, devpath_len, new_queue_file); +- } +- seqnum++; +- } +- free(devpaths); +- devpaths = NULL; +- } +- fflush(new_queue_file); +- if (ferror(new_queue_file)) +- goto error; +- +- /* rename the new file on top of the old one */ +- if (rename("/run/udev/queue.tmp", "/run/udev/queue.bin") != 0) +- goto error; +- +- if (udev_queue_export->queue_file != NULL) +- fclose(udev_queue_export->queue_file); +- udev_queue_export->queue_file = new_queue_file; +- udev_queue_export->waste_bytes = 0; +- +- return 0; +- +-error: +- udev_err(udev_queue_export->udev, "failed to create queue file: %m\n"); +- udev_queue_export_cleanup(udev_queue_export); +- +- if (udev_queue_export->queue_file != NULL) { +- fclose(udev_queue_export->queue_file); +- udev_queue_export->queue_file = NULL; +- } +- if (new_queue_file != NULL) +- fclose(new_queue_file); +- +- if (devpaths != NULL) +- free(devpaths); +- udev_queue_export->queued_count = 0; +- udev_queue_export->waste_bytes = 0; +- udev_queue_export->seqnum_max = udev_queue_export->seqnum_min; +- +- return -1; +-} +- +-static int write_queue_record(struct udev_queue_export *udev_queue_export, +- unsigned long long int seqnum, const char *devpath, size_t devpath_len) +-{ +- unsigned short len; +- +- if (udev_queue_export->queue_file == NULL) +- return -1; +- +- if (fwrite(&seqnum, sizeof(unsigned long long int), 1, udev_queue_export->queue_file) != 1) +- goto write_error; +- +- len = (devpath_len < USHRT_MAX) ? devpath_len : USHRT_MAX; +- if (fwrite(&len, sizeof(unsigned short), 1, udev_queue_export->queue_file) != 1) +- goto write_error; +- if (len > 0) { +- if (fwrite(devpath, 1, len, udev_queue_export->queue_file) != len) +- goto write_error; +- } +- +- /* *must* flush output; caller may fork */ +- if (fflush(udev_queue_export->queue_file) != 0) +- goto write_error; +- +- return 0; +- +-write_error: +- /* if we failed half way through writing a record to a file, +- we should not try to write any further records to it. */ +- udev_err(udev_queue_export->udev, "error writing to queue file: %m\n"); +- fclose(udev_queue_export->queue_file); +- udev_queue_export->queue_file = NULL; +- +- return -1; +-} +- +-enum device_state { +- DEVICE_QUEUED, +- DEVICE_FINISHED, +-}; +- +-static inline size_t queue_record_size(size_t devpath_len) +-{ +- return sizeof(unsigned long long int) + sizeof(unsigned short int) + devpath_len; +-} +- +-static int update_queue(struct udev_queue_export *udev_queue_export, +- struct udev_device *udev_device, enum device_state state) +-{ +- unsigned long long int seqnum = udev_device_get_seqnum(udev_device); +- const char *devpath = NULL; +- size_t devpath_len = 0; +- int bytes; +- int err; +- +- /* FINISHED records have a zero length devpath */ +- if (state == DEVICE_QUEUED) { +- devpath = udev_device_get_devpath(udev_device); +- devpath_len = strlen(devpath); +- } +- +- /* recover from an earlier failed rebuild */ +- if (udev_queue_export->queue_file == NULL) { +- if (rebuild_queue_file(udev_queue_export) != 0) +- return -1; +- } +- +- /* if we're removing the last event from the queue, that's the best time to rebuild it */ +- if (state != DEVICE_QUEUED && udev_queue_export->queued_count == 1) { +- /* we don't need to read the old queue file */ +- fclose(udev_queue_export->queue_file); +- udev_queue_export->queue_file = NULL; +- rebuild_queue_file(udev_queue_export); +- return 0; +- } +- +- /* try to rebuild the queue files before they grow larger than one page. */ +- bytes = ftell(udev_queue_export->queue_file) + queue_record_size(devpath_len); +- if ((udev_queue_export->waste_bytes > bytes / 2) && bytes > 4096) +- rebuild_queue_file(udev_queue_export); +- +- /* don't record a finished event, if we already dropped the event in a failed rebuild */ +- if (seqnum < udev_queue_export->seqnum_max) +- return 0; +- +- /* now write to the queue */ +- if (state == DEVICE_QUEUED) { +- udev_queue_export->queued_count++; +- udev_queue_export->seqnum_min = seqnum; +- } else { +- udev_queue_export->waste_bytes += queue_record_size(devpath_len) + queue_record_size(0); +- udev_queue_export->queued_count--; +- } +- err = write_queue_record(udev_queue_export, seqnum, devpath, devpath_len); +- +- /* try to handle ENOSPC */ +- if (err != 0 && udev_queue_export->queued_count == 0) { +- udev_queue_export_cleanup(udev_queue_export); +- err = rebuild_queue_file(udev_queue_export); +- } +- +- return err; +-} +- +-static int update(struct udev_queue_export *udev_queue_export, +- struct udev_device *udev_device, enum device_state state) +-{ +- if (update_queue(udev_queue_export, udev_device, state) != 0) +- return -1; +- +- return 0; +-} +- +-int udev_queue_export_device_queued(struct udev_queue_export *udev_queue_export, struct udev_device *udev_device) +-{ +- return update(udev_queue_export, udev_device, DEVICE_QUEUED); +-} +- +-int udev_queue_export_device_finished(struct udev_queue_export *udev_queue_export, struct udev_device *udev_device) +-{ +- return update(udev_queue_export, udev_device, DEVICE_FINISHED); +-} +Index: systemd-210/src/libudev/libudev-queue.c +=================================================================== +--- systemd-210.orig/src/libudev/libudev-queue.c ++++ systemd-210/src/libudev/libudev-queue.c +@@ -24,8 +24,6 @@ + #include + #include + #include +-#include +-#include + #include + #include + +@@ -36,10 +34,7 @@ + * SECTION:libudev-queue + * @short_description: access to currently active events + * +- * The udev daemon processes events asynchronously. All events which do not have +- * interdependencies run in parallel. This exports the current state of the +- * event processing queue, and the current event sequence numbers from the kernel +- * and the udev daemon. ++ * This exports the current state of the udev processing queue. + */ + + /** +@@ -50,7 +45,6 @@ + struct udev_queue { + struct udev *udev; + int refcount; +- struct udev_list queue_list; + }; + + /** +@@ -72,9 +66,9 @@ _public_ struct udev_queue *udev_queue_n + udev_queue = new0(struct udev_queue, 1); + if (udev_queue == NULL) + return NULL; ++ + udev_queue->refcount = 1; + udev_queue->udev = udev; +- udev_list_init(udev, &udev_queue->queue_list, false); + return udev_queue; + } + +@@ -90,6 +84,7 @@ _public_ struct udev_queue *udev_queue_r + { + if (udev_queue == NULL) + return NULL; ++ + udev_queue->refcount++; + return udev_queue; + } +@@ -107,10 +102,11 @@ _public_ struct udev_queue *udev_queue_u + { + if (udev_queue == NULL) + return NULL; ++ + udev_queue->refcount--; + if (udev_queue->refcount > 0) + return NULL; +- udev_list_cleanup(&udev_queue->queue_list); ++ + free(udev_queue); + return NULL; + } +@@ -130,141 +126,30 @@ _public_ struct udev *udev_queue_get_ude + return udev_queue->udev; + } + +-unsigned long long int udev_get_kernel_seqnum(struct udev *udev) +-{ +- unsigned long long int seqnum; +- int fd; +- char buf[32]; +- ssize_t len; +- +- fd = open("/sys/kernel/uevent_seqnum", O_RDONLY|O_CLOEXEC); +- if (fd < 0) +- return 0; +- len = read(fd, buf, sizeof(buf)); +- close(fd); +- if (len <= 2) +- return 0; +- buf[len-1] = '\0'; +- seqnum = strtoull(buf, NULL, 10); +- return seqnum; +-} +- + /** + * udev_queue_get_kernel_seqnum: + * @udev_queue: udev queue context + * +- * Get the current kernel event sequence number. ++ * This function is deprecated. + * +- * Returns: the sequence number. ++ * Returns: 0. + **/ + _public_ unsigned long long int udev_queue_get_kernel_seqnum(struct udev_queue *udev_queue) + { +- unsigned long long int seqnum; +- +- if (udev_queue == NULL) +- return -EINVAL; +- +- seqnum = udev_get_kernel_seqnum(udev_queue->udev); +- return seqnum; +-} +- +-int udev_queue_read_seqnum(FILE *queue_file, unsigned long long int *seqnum) +-{ +- if (fread(seqnum, sizeof(unsigned long long int), 1, queue_file) != 1) +- return -1; +- + return 0; + } + +-ssize_t udev_queue_skip_devpath(FILE *queue_file) +-{ +- unsigned short int len; +- +- if (fread(&len, sizeof(unsigned short int), 1, queue_file) == 1) { +- char *devpath = alloca(len); +- +- /* use fread to skip, fseek might drop buffered data */ +- if (fread(devpath, 1, len, queue_file) == len) +- return len; +- } +- +- return -1; +-} +- +-ssize_t udev_queue_read_devpath(FILE *queue_file, char *devpath, size_t size) +-{ +- unsigned short int read_bytes = 0; +- unsigned short int len; +- +- if (fread(&len, sizeof(unsigned short int), 1, queue_file) != 1) +- return -1; +- +- read_bytes = (len < size - 1) ? len : size - 1; +- if (fread(devpath, 1, read_bytes, queue_file) != read_bytes) +- return -1; +- devpath[read_bytes] = '\0'; +- +- /* if devpath was too long, skip unread characters */ +- if (read_bytes != len) { +- unsigned short int skip_bytes = len - read_bytes; +- char *buf = alloca(skip_bytes); +- +- if (fread(buf, 1, skip_bytes, queue_file) != skip_bytes) +- return -1; +- } +- +- return read_bytes; +-} +- +-static FILE *open_queue_file(struct udev_queue *udev_queue, unsigned long long int *seqnum_start) +-{ +- FILE *queue_file; +- +- queue_file = fopen("/run/udev/queue.bin", "re"); +- if (queue_file == NULL) +- return NULL; +- +- if (udev_queue_read_seqnum(queue_file, seqnum_start) < 0) { +- udev_err(udev_queue->udev, "corrupt queue file\n"); +- fclose(queue_file); +- return NULL; +- } +- +- return queue_file; +-} +- + /** + * udev_queue_get_udev_seqnum: + * @udev_queue: udev queue context + * +- * Get the last known udev event sequence number. ++ * This function is deprecated. + * +- * Returns: the sequence number. ++ * Returns: 0. + **/ + _public_ unsigned long long int udev_queue_get_udev_seqnum(struct udev_queue *udev_queue) + { +- unsigned long long int seqnum_udev; +- FILE *queue_file; +- +- queue_file = open_queue_file(udev_queue, &seqnum_udev); +- if (queue_file == NULL) +- return 0; +- +- for (;;) { +- unsigned long long int seqnum; +- ssize_t devpath_len; +- +- if (udev_queue_read_seqnum(queue_file, &seqnum) < 0) +- break; +- devpath_len = udev_queue_skip_devpath(queue_file); +- if (devpath_len < 0) +- break; +- if (devpath_len > 0) +- seqnum_udev = seqnum; +- } +- +- fclose(queue_file); +- return seqnum_udev; ++ return 0; + } + + /** +@@ -277,15 +162,7 @@ _public_ unsigned long long int udev_que + **/ + _public_ int udev_queue_get_udev_is_active(struct udev_queue *udev_queue) + { +- unsigned long long int seqnum_start; +- FILE *queue_file; +- +- queue_file = open_queue_file(udev_queue, &seqnum_start); +- if (queue_file == NULL) +- return 0; +- +- fclose(queue_file); +- return 1; ++ return access("/run/udev/control", F_OK) >= 0; + } + + /** +@@ -298,48 +175,7 @@ _public_ int udev_queue_get_udev_is_acti + **/ + _public_ int udev_queue_get_queue_is_empty(struct udev_queue *udev_queue) + { +- unsigned long long int seqnum_kernel; +- unsigned long long int seqnum_udev = 0; +- int queued = 0; +- int is_empty = 0; +- FILE *queue_file; +- +- if (udev_queue == NULL) +- return -EINVAL; +- queue_file = open_queue_file(udev_queue, &seqnum_udev); +- if (queue_file == NULL) +- return 1; +- +- for (;;) { +- unsigned long long int seqnum; +- ssize_t devpath_len; +- +- if (udev_queue_read_seqnum(queue_file, &seqnum) < 0) +- break; +- devpath_len = udev_queue_skip_devpath(queue_file); +- if (devpath_len < 0) +- break; +- +- if (devpath_len > 0) { +- queued++; +- seqnum_udev = seqnum; +- } else { +- queued--; +- } +- } +- +- if (queued > 0) +- goto out; +- +- seqnum_kernel = udev_queue_get_kernel_seqnum(udev_queue); +- if (seqnum_udev < seqnum_kernel) +- goto out; +- +- is_empty = 1; +- +-out: +- fclose(queue_file); +- return is_empty; ++ return access("/run/udev/queue", F_OK) >= 0; + } + + /** +@@ -348,63 +184,15 @@ out: + * @start: first event sequence number + * @end: last event sequence number + * +- * Check if udev is currently processing any events in a given sequence number range. ++ * This function is deprecated, it just returns the result of ++ * udev_queue_get_queue_is_empty(). + * +- * Returns: a flag indicating if any of the sequence numbers in the given range is currently active. ++ * Returns: a flag indicating if udev is currently handling events. + **/ + _public_ int udev_queue_get_seqnum_sequence_is_finished(struct udev_queue *udev_queue, + unsigned long long int start, unsigned long long int end) + { +- unsigned long long int seqnum; +- ssize_t devpath_len; +- int unfinished; +- FILE *queue_file; +- +- if (udev_queue == NULL) +- return -EINVAL; +- queue_file = open_queue_file(udev_queue, &seqnum); +- if (queue_file == NULL) +- return 1; +- if (start < seqnum) +- start = seqnum; +- if (start > end) { +- fclose(queue_file); +- return 1; +- } +- if (end - start > INT_MAX - 1) { +- fclose(queue_file); +- return -EOVERFLOW; +- } +- +- /* +- * we might start with 0, and handle the initial seqnum +- * only when we find an entry in the queue file +- **/ +- unfinished = end - start; +- +- do { +- if (udev_queue_read_seqnum(queue_file, &seqnum) < 0) +- break; +- devpath_len = udev_queue_skip_devpath(queue_file); +- if (devpath_len < 0) +- break; +- +- /* +- * we might start with an empty or re-build queue file, where +- * the initial seqnum is not recorded as finished +- */ +- if (start == seqnum && devpath_len > 0) +- unfinished++; +- +- if (devpath_len == 0) { +- if (seqnum >= start && seqnum <= end) +- unfinished--; +- } +- } while (unfinished > 0); +- +- fclose(queue_file); +- +- return (unfinished == 0); ++ return udev_queue_get_queue_is_empty(udev_queue); + } + + /** +@@ -412,69 +200,25 @@ _public_ int udev_queue_get_seqnum_seque + * @udev_queue: udev queue context + * @seqnum: sequence number + * +- * Check if udev is currently processing a given sequence number. ++ * This function is deprecated, it just returns the result of ++ * udev_queue_get_queue_is_empty(). + * +- * Returns: a flag indicating if the given sequence number is currently active. ++ * Returns: a flag indicating if udev is currently handling events. + **/ + _public_ int udev_queue_get_seqnum_is_finished(struct udev_queue *udev_queue, unsigned long long int seqnum) + { +- if (!udev_queue_get_seqnum_sequence_is_finished(udev_queue, seqnum, seqnum)) +- return 0; +- +- return 1; ++ return udev_queue_get_queue_is_empty(udev_queue); + } + + /** + * udev_queue_get_queued_list_entry: + * @udev_queue: udev queue context + * +- * Get the first entry of the list of queued events. ++ * This function is deprecated. + * +- * Returns: a udev_list_entry. ++ * Returns: NULL. + **/ + _public_ struct udev_list_entry *udev_queue_get_queued_list_entry(struct udev_queue *udev_queue) + { +- unsigned long long int seqnum; +- FILE *queue_file; +- +- if (udev_queue == NULL) +- return NULL; +- udev_list_cleanup(&udev_queue->queue_list); +- +- queue_file = open_queue_file(udev_queue, &seqnum); +- if (queue_file == NULL) +- return NULL; +- +- for (;;) { +- char syspath[UTIL_PATH_SIZE]; +- char *s; +- size_t l; +- ssize_t len; +- char seqnum_str[32]; +- struct udev_list_entry *list_entry; +- +- if (udev_queue_read_seqnum(queue_file, &seqnum) < 0) +- break; +- snprintf(seqnum_str, sizeof(seqnum_str), "%llu", seqnum); +- +- s = syspath; +- l = strpcpy(&s, sizeof(syspath), "/sys"); +- len = udev_queue_read_devpath(queue_file, s, l); +- if (len < 0) +- break; +- +- if (len > 0) { +- udev_list_entry_add(&udev_queue->queue_list, syspath, seqnum_str); +- } else { +- udev_list_entry_foreach(list_entry, udev_list_get_entry(&udev_queue->queue_list)) { +- if (streq(seqnum_str, udev_list_entry_get_value(list_entry))) { +- udev_list_entry_delete(list_entry); +- break; +- } +- } +- } +- } +- fclose(queue_file); +- +- return udev_list_get_entry(&udev_queue->queue_list); ++ return NULL; + } +Index: systemd-210/src/libudev/libudev.h +=================================================================== +--- systemd-210.orig/src/libudev/libudev.h ++++ systemd-210/src/libudev/libudev.h +@@ -170,14 +170,14 @@ struct udev_queue *udev_queue_ref(struct + struct udev_queue *udev_queue_unref(struct udev_queue *udev_queue); + struct udev *udev_queue_get_udev(struct udev_queue *udev_queue); + struct udev_queue *udev_queue_new(struct udev *udev); +-unsigned long long int udev_queue_get_kernel_seqnum(struct udev_queue *udev_queue); +-unsigned long long int udev_queue_get_udev_seqnum(struct udev_queue *udev_queue); ++unsigned long long int udev_queue_get_kernel_seqnum(struct udev_queue *udev_queue) __attribute__ ((deprecated)); ++unsigned long long int udev_queue_get_udev_seqnum(struct udev_queue *udev_queue) __attribute__ ((deprecated)); + int udev_queue_get_udev_is_active(struct udev_queue *udev_queue); + int udev_queue_get_queue_is_empty(struct udev_queue *udev_queue); +-int udev_queue_get_seqnum_is_finished(struct udev_queue *udev_queue, unsigned long long int seqnum); ++int udev_queue_get_seqnum_is_finished(struct udev_queue *udev_queue, unsigned long long int seqnum) __attribute__ ((deprecated)); + int udev_queue_get_seqnum_sequence_is_finished(struct udev_queue *udev_queue, +- unsigned long long int start, unsigned long long int end); +-struct udev_list_entry *udev_queue_get_queued_list_entry(struct udev_queue *udev_queue); ++ unsigned long long int start, unsigned long long int end) __attribute__ ((deprecated)); ++struct udev_list_entry *udev_queue_get_queued_list_entry(struct udev_queue *udev_queue) __attribute__ ((deprecated)); + + /* + * udev_hwdb +Index: systemd-210/src/shared/udev-util.h +=================================================================== +--- systemd-210.orig/src/shared/udev-util.h ++++ systemd-210/src/shared/udev-util.h +@@ -31,7 +31,6 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_ + DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_rules*, udev_rules_unref); + DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_ctrl*, udev_ctrl_unref); + DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_monitor*, udev_monitor_unref); +-DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_queue*, udev_queue_unref); + + #define _cleanup_udev_unref_ _cleanup_(udev_unrefp) + #define _cleanup_udev_device_unref_ _cleanup_(udev_device_unrefp) +@@ -40,5 +39,4 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_ + #define _cleanup_udev_rules_unref_ _cleanup_(udev_rules_unrefp) + #define _cleanup_udev_ctrl_unref_ _cleanup_(udev_ctrl_unrefp) + #define _cleanup_udev_monitor_unref_ _cleanup_(udev_monitor_unrefp) +-#define _cleanup_udev_queue_unref_ _cleanup_(udev_queue_unrefp) + #define _cleanup_udev_list_cleanup_ _cleanup_(udev_list_cleanup) +Index: systemd-210/src/test/test-libudev.c +=================================================================== +--- systemd-210.orig/src/test/test-libudev.c ++++ systemd-210/src/test/test-libudev.c +@@ -303,38 +303,14 @@ out: + + static int test_queue(struct udev *udev) { + struct udev_queue *udev_queue; +- unsigned long long int seqnum; +- struct udev_list_entry *list_entry; + + udev_queue = udev_queue_new(udev); + if (udev_queue == NULL) + return -1; +- seqnum = udev_queue_get_kernel_seqnum(udev_queue); +- printf("seqnum kernel: %llu\n", seqnum); +- seqnum = udev_queue_get_udev_seqnum(udev_queue); +- printf("seqnum udev : %llu\n", seqnum); + + if (udev_queue_get_queue_is_empty(udev_queue)) + printf("queue is empty\n"); +- printf("get queue list\n"); +- udev_list_entry_foreach(list_entry, udev_queue_get_queued_list_entry(udev_queue)) +- printf("queued: '%s' [%s]\n", udev_list_entry_get_name(list_entry), udev_list_entry_get_value(list_entry)); +- printf("\n"); +- printf("get queue list again\n"); +- udev_list_entry_foreach(list_entry, udev_queue_get_queued_list_entry(udev_queue)) +- printf("queued: '%s' [%s]\n", udev_list_entry_get_name(list_entry), udev_list_entry_get_value(list_entry)); +- printf("\n"); + +- list_entry = udev_queue_get_queued_list_entry(udev_queue); +- if (list_entry != NULL) { +- printf("event [%llu] is queued\n", seqnum); +- seqnum = strtoull(udev_list_entry_get_value(list_entry), NULL, 10); +- if (udev_queue_get_seqnum_is_finished(udev_queue, seqnum)) +- printf("event [%llu] is not finished\n", seqnum); +- else +- printf("event [%llu] is finished\n", seqnum); +- } +- printf("\n"); + udev_queue_unref(udev_queue); + return 0; + } +Index: systemd-210/src/udev/udev-ctrl.c +=================================================================== +--- systemd-210.orig/src/udev/udev-ctrl.c ++++ systemd-210/src/udev/udev-ctrl.c +@@ -275,7 +275,7 @@ static int ctrl_send(struct udev_ctrl *u + + pfd[0].fd = uctrl->sock; + pfd[0].events = POLLIN; +- r = poll(pfd, 1, timeout * 1000); ++ r = poll(pfd, 1, timeout * MSEC_PER_SEC); + if (r < 0) { + if (errno == EINTR) + continue; +Index: systemd-210/src/udev/udevadm-settle.c +=================================================================== +--- systemd-210.orig/src/udev/udevadm-settle.c ++++ systemd-210/src/udev/udevadm-settle.c +@@ -41,42 +41,28 @@ + static void help(void) { + printf("Usage: udevadm settle OPTIONS\n" + " -t,--timeout= maximum time to wait for events\n" +- " -s,--seq-start= first seqnum to wait for\n" +- " -e,--seq-end= last seqnum to wait for\n" + " -E,--exit-if-exists= stop waiting if file exists\n" +- " -q,--quiet do not print list after timeout\n" + " -h,--help\n\n"); + } + + static int adm_settle(struct udev *udev, int argc, char *argv[]) + { + static const struct option options[] = { +- { "seq-start", required_argument, NULL, 's' }, +- { "seq-end", required_argument, NULL, 'e' }, ++ { "seq-start", required_argument, NULL, '\0' }, /* removed */ ++ { "seq-end", required_argument, NULL, '\0' }, /* removed */ + { "timeout", required_argument, NULL, 't' }, + { "exit-if-exists", required_argument, NULL, 'E' }, +- { "quiet", no_argument, NULL, 'q' }, ++ { "quiet", no_argument, NULL, 'q' }, /* removed */ + { "help", no_argument, NULL, 'h' }, + {} + }; +- usec_t start_usec = now(CLOCK_MONOTONIC); +- usec_t start = 0; +- usec_t end = 0; +- int quiet = 0; + const char *exists = NULL; + unsigned int timeout = 120; + struct pollfd pfd[1] = { {.fd = -1}, }; +- _cleanup_udev_queue_unref_ struct udev_queue *udev_queue = NULL; + int rc = EXIT_FAILURE, c; + +- while ((c = getopt_long(argc, argv, "s:e:t:E:qh", options, NULL)) >= 0) ++ while ((c = getopt_long(argc, argv, "s:e:t:E:qh", options, NULL)) >= 0) { + switch (c) { +- case 's': +- start = strtoull(optarg, NULL, 0); +- break; +- case 'e': +- end = strtoull(optarg, NULL, 0); +- break; + case 't': { + int r; + +@@ -91,9 +77,6 @@ static int adm_settle(struct udev *udev, + case 'E': + exists = optarg; + break; +- case 'q': +- quiet = 1; +- break; + case 'h': + help(); + exit(EXIT_SUCCESS); +@@ -102,44 +85,13 @@ static int adm_settle(struct udev *udev, + default: + assert_not_reached("Unknown argument"); + } ++ } + + if (optind < argc) { + fprintf(stderr, "Extraneous argument: '%s'\n", argv[optind]); + exit(EXIT_FAILURE); + } + +- udev_queue = udev_queue_new(udev); +- if (udev_queue == NULL) +- exit(2); +- +- if (start > 0) { +- unsigned long long kernel_seq; +- +- kernel_seq = udev_queue_get_kernel_seqnum(udev_queue); +- +- /* unless specified, the last event is the current kernel seqnum */ +- if (end == 0) +- end = udev_queue_get_kernel_seqnum(udev_queue); +- +- if (start > end) { +- log_error("seq-start larger than seq-end, ignoring"); +- start = 0; +- end = 0; +- } +- +- if (start > kernel_seq || end > kernel_seq) { +- log_error("seq-start or seq-end larger than current kernel value, ignoring"); +- start = 0; +- end = 0; +- } +- log_debug("start=%llu end=%llu current=%llu", (unsigned long long)start, (unsigned long long)end, kernel_seq); +- } else { +- if (end > 0) { +- log_error("seq-end needs seq-start parameter, ignoring"); +- end = 0; +- } +- } +- + /* guarantee that the udev daemon isn't pre-processing */ + if (getuid() == 0) { + struct udev_ctrl *uctrl; +@@ -160,73 +112,34 @@ static int adm_settle(struct udev *udev, + pfd[0].fd = inotify_init1(IN_CLOEXEC); + if (pfd[0].fd < 0) { + log_error("inotify_init failed: %m"); +- } else { +- if (inotify_add_watch(pfd[0].fd, "/run/udev" , IN_MOVED_TO) < 0) { +- log_error("watching /run/udev failed"); +- close(pfd[0].fd); +- pfd[0].fd = -1; +- } ++ goto out; + } + +- for (;;) { +- struct stat statbuf; ++ if (inotify_add_watch(pfd[0].fd, "/run/udev/queue" , IN_DELETE) < 0) { ++ log_debug("watching /run/udev failed"); ++ goto out; ++ } + +- if (exists != NULL && stat(exists, &statbuf) == 0) { ++ for (;;) { ++ if (exists && access(exists, F_OK) >= 0) { + rc = EXIT_SUCCESS; + break; + } + +- if (start > 0) { +- /* if asked for, wait for a specific sequence of events */ +- if (udev_queue_get_seqnum_sequence_is_finished(udev_queue, start, end) == 1) { +- rc = EXIT_SUCCESS; +- break; +- } +- } else { +- /* exit if queue is empty */ +- if (udev_queue_get_queue_is_empty(udev_queue)) { +- rc = EXIT_SUCCESS; +- break; +- } +- } +- +- if (pfd[0].fd >= 0) { +- int delay; +- +- if (exists != NULL || start > 0) +- delay = 100; +- else +- delay = 1000; +- /* wake up after delay, or immediately after the queue is rebuilt */ +- if (poll(pfd, 1, delay) > 0 && pfd[0].revents & POLLIN) { +- char buf[sizeof(struct inotify_event) + PATH_MAX]; +- +- read(pfd[0].fd, buf, sizeof(buf)); +- } +- } else { +- sleep(1); ++ /* exit if queue is empty */ ++ if (access("/run/udev/queue", F_OK) < 0) { ++ rc = EXIT_SUCCESS; ++ break; + } + +- if (timeout > 0) { +- usec_t age_usec; ++ /* wake up when "queue" file is deleted */ ++ if (poll(pfd, 1, 100) > 0 && pfd[0].revents & POLLIN) { ++ char buf[sizeof(struct inotify_event) + PATH_MAX]; + +- age_usec = now(CLOCK_MONOTONIC) - start_usec; +- if (age_usec / (1000 * 1000) >= timeout) { +- struct udev_list_entry *list_entry; +- +- if (!quiet && udev_queue_get_queued_list_entry(udev_queue) != NULL) { +- log_debug("timeout waiting for udev queue"); +- printf("\nudevadm settle - timeout of %i seconds reached, the event queue contains:\n", timeout); +- udev_list_entry_foreach(list_entry, udev_queue_get_queued_list_entry(udev_queue)) +- printf(" %s (%s)\n", +- udev_list_entry_get_name(list_entry), +- udev_list_entry_get_value(list_entry)); +- } +- +- break; +- } ++ read(pfd[0].fd, buf, sizeof(buf)); + } + } ++ + out: + if (pfd[0].fd >= 0) + close(pfd[0].fd); +@@ -236,5 +149,5 @@ out: + const struct udevadm_cmd udevadm_settle = { + .name = "settle", + .cmd = adm_settle, +- .help = "wait for the event queue to finish", ++ .help = "wait for pending udev events", + }; +Index: systemd-210/src/udev/udevd.c +=================================================================== +--- systemd-210.orig/src/udev/udevd.c ++++ systemd-210/src/udev/udevd.c +@@ -61,7 +61,6 @@ void udev_main_log(struct udev *udev, in + } + + static struct udev_rules *rules; +-static struct udev_queue_export *udev_queue_export; + static struct udev_ctrl *udev_ctrl; + static struct udev_monitor *monitor; + static int worker_watch[2] = { -1, -1 }; +@@ -140,14 +139,9 @@ static inline struct worker *node_to_wor + return container_of(node, struct worker, node); + } + +-static void event_queue_delete(struct event *event, bool export) ++static void event_queue_delete(struct event *event) + { + udev_list_node_remove(&event->node); +- +- if (export) { +- udev_queue_export_device_finished(udev_queue_export, event->dev); +- log_debug("seq %llu done with %i", udev_device_get_seqnum(event->dev), event->exitcode); +- } + udev_device_unref(event->dev); + free(event); + } +@@ -226,7 +220,6 @@ static void worker_new(struct event *eve + free(worker); + worker_list_cleanup(udev); + event_queue_cleanup(udev, EVENT_UNDEF); +- udev_queue_export_unref(udev_queue_export); + udev_monitor_unref(monitor); + udev_ctrl_unref(udev_ctrl); + close(fd_signal); +@@ -477,7 +470,6 @@ static int event_queue_insert(struct ude + event->nodelay = true; + #endif + +- udev_queue_export_device_queued(udev_queue_export, dev); + log_debug("seq %llu queued, '%s' '%s'", udev_device_get_seqnum(dev), + udev_device_get_action(dev), udev_device_get_subsystem(dev)); + +@@ -608,7 +600,7 @@ static void event_queue_cleanup(struct u + if (match_type != EVENT_UNDEF && match_type != event->state) + continue; + +- event_queue_delete(event, false); ++ event_queue_delete(event); + } + } + +@@ -633,7 +625,7 @@ static void worker_returned(int fd_worke + /* worker returned */ + if (worker->event) { + worker->event->exitcode = msg.exitcode; +- event_queue_delete(worker->event, true); ++ event_queue_delete(worker->event); + worker->event = NULL; + } + if (worker->state != WORKER_KILLED) +@@ -825,7 +817,8 @@ static void handle_signal(struct udev *u + log_error("worker [%u] failed while handling '%s'", + pid, worker->event->devpath); + worker->event->exitcode = -32; +- event_queue_delete(worker->event, true); ++ event_queue_delete(worker->event); ++ + /* drop reference taken for state 'running' */ + worker_unref(worker); + } +@@ -1104,14 +1097,7 @@ int main(int argc, char *argv[]) + goto exit; + } + +- udev_monitor_set_receive_buffer_size(monitor, 128*1024*1024); +- +- /* create queue file before signalling 'ready', to make sure we block 'settle' */ +- udev_queue_export = udev_queue_export_new(udev); +- if (udev_queue_export == NULL) { +- log_error("error creating queue file"); +- goto exit; +- } ++ udev_monitor_set_receive_buffer_size(monitor, 128 * 1024 * 1024); + + if (daemonize) { + pid_t pid; +@@ -1269,12 +1255,12 @@ int main(int argc, char *argv[]) + worker_kill(udev); + + /* exit after all has cleaned up */ +- if (udev_list_node_is_empty(&event_list) && udev_list_node_is_empty(&worker_list)) ++ if (udev_list_node_is_empty(&event_list) && children == 0) + break; + + /* timeout at exit for workers to finish */ +- timeout = 30 * 1000; +- } else if (udev_list_node_is_empty(&event_list) && !children) { ++ timeout = 30 * MSEC_PER_SEC; ++ } else if (udev_list_node_is_empty(&event_list) && children == 0) { + /* we are idle */ + timeout = -1; + +@@ -1283,8 +1269,20 @@ int main(int argc, char *argv[]) + cg_kill(SYSTEMD_CGROUP_CONTROLLER, udev_cgroup, SIGKILL, false, true, NULL); + } else { + /* kill idle or hanging workers */ +- timeout = 3 * 1000; ++ timeout = 3 * MSEC_PER_SEC; + } ++ ++ /* tell settle that we are busy or idle */ ++ if (!udev_list_node_is_empty(&event_list)) { ++ int fd; ++ ++ fd = open("/run/udev/queue", O_WRONLY|O_CREAT|O_CLOEXEC|O_TRUNC|O_NOFOLLOW, 0444); ++ if (fd >= 0) ++ close(fd); ++ } else { ++ unlink("/run/udev/queue"); ++ } ++ + fdcount = epoll_wait(fd_ep, ev, ELEMENTSOF(ev), timeout); + if (fdcount < 0) + continue; +@@ -1311,18 +1309,18 @@ int main(int argc, char *argv[]) + if (worker->state != WORKER_RUNNING) + continue; + +- if ((now(CLOCK_MONOTONIC) - worker->event_start_usec) > 30 * 1000 * 1000) { ++ if ((now(CLOCK_MONOTONIC) - worker->event_start_usec) > 30 * USEC_PER_SEC) { + log_error("worker [%u] %s timeout; kill it", worker->pid, + worker->event ? worker->event->devpath : ""); + kill(worker->pid, SIGKILL); + worker->state = WORKER_KILLED; ++ + /* drop reference taken for state 'running' */ + worker_unref(worker); + if (worker->event) { +- log_error("seq %llu '%s' killed", +- udev_device_get_seqnum(worker->event->dev), worker->event->devpath); ++ log_error("seq %llu '%s' killed", udev_device_get_seqnum(worker->event->dev), worker->event->devpath); + worker->event->exitcode = -64; +- event_queue_delete(worker->event, true); ++ event_queue_delete(worker->event); + worker->event = NULL; + } + } +@@ -1345,7 +1343,7 @@ int main(int argc, char *argv[]) + } + + /* check for changed config, every 3 seconds at most */ +- if ((now(CLOCK_MONOTONIC) - last_usec) > 3 * 1000 * 1000) { ++ if ((now(CLOCK_MONOTONIC) - last_usec) > 3 * USEC_PER_SEC) { + if (udev_rules_check_timestamp(rules)) + reload = true; + if (udev_builtin_validate(udev)) +@@ -1420,8 +1418,8 @@ int main(int argc, char *argv[]) + + rc = EXIT_SUCCESS; + exit: +- udev_queue_export_cleanup(udev_queue_export); + udev_ctrl_cleanup(udev_ctrl); ++ unlink("/run/udev/queue"); + exit_daemonize: + if (fd_ep >= 0) + close(fd_ep); +@@ -1436,7 +1434,6 @@ exit_daemonize: + if (worker_watch[WRITE_END] >= 0) + close(worker_watch[WRITE_END]); + udev_monitor_unref(monitor); +- udev_queue_export_unref(udev_queue_export); + udev_ctrl_connection_unref(ctrl_conn); + udev_ctrl_unref(udev_ctrl); + label_finish(); diff --git a/systemd-mini.changes b/systemd-mini.changes index 70662ea3..9477cc57 100644 --- a/systemd-mini.changes +++ b/systemd-mini.changes @@ -1,3 +1,12 @@ +------------------------------------------------------------------- +Fri May 30 07:35:07 UTC 2014 - rmilasan@suse.com + +- Re-add persistent rules to have a backup option if predictable + rules are disabled at boot time with 'net.ifnames=0' option. + add: 1021-udev-re-add-persistent-net-rules.patch +- udev: remove seqnum API and all assumptions about seqnums + add: 1022-udev-remove-seqnum-API-and-all-assumptions-about-seq.patch + ------------------------------------------------------------------- Tue May 27 07:23:47 UTC 2014 - werner@suse.de diff --git a/systemd-mini.spec b/systemd-mini.spec index 6c0acde3..88c5a306 100644 --- a/systemd-mini.spec +++ b/systemd-mini.spec @@ -558,6 +558,10 @@ Patch1018: 1018-udev-do-not-skip-the-execution-of-RUN-when-renaming-.patch Patch1019: 1019-udev-avoid-use-of-uninitialized-err.patch # PATCHFIX-UPSTREAM added at 2014/05/26 Patch1020: 1020-udev-keyboard-also-hook-into-change-events.patch +# PATCH-FIX-SUSE 1021-udev-re-add-persistent-net-rules.patch +Patch1021: 1021-udev-re-add-persistent-net-rules.patch +# PATCHFIX-UPSTREAM 1022-udev-remove-seqnum-API-and-all-assumptions-about-seq.patch +Patch1022: 1022-udev-remove-seqnum-API-and-all-assumptions-about-seq.patch %description Systemd is a system and service manager, compatible with SysV and LSB @@ -989,6 +993,8 @@ cp %{SOURCE7} m4/ %patch1018 -p0 %patch1019 -p0 %patch1020 -p0 +%patch1021 -p1 +%patch1022 -p1 # ensure generate files are removed rm -f units/emergency.service @@ -1731,6 +1737,9 @@ exit 0 %{_prefix}/lib/udev/v4l_id %{_prefix}/lib/udev/write_dev_root_rule %{_prefix}/lib/udev/udev-generate-peristent-rule +%{_prefix}/lib/udev/net-set-sriov-names +%{_prefix}/lib/udev/rule_generator.functions +%{_prefix}/lib/udev/write_net_rules %dir %{_prefix}/lib/udev/rules.d/ %exclude %{_prefix}/lib/udev/rules.d/70-uaccess.rules %exclude %{_prefix}/lib/udev/rules.d/71-seat.rules diff --git a/systemd.changes b/systemd.changes index 70662ea3..9477cc57 100644 --- a/systemd.changes +++ b/systemd.changes @@ -1,3 +1,12 @@ +------------------------------------------------------------------- +Fri May 30 07:35:07 UTC 2014 - rmilasan@suse.com + +- Re-add persistent rules to have a backup option if predictable + rules are disabled at boot time with 'net.ifnames=0' option. + add: 1021-udev-re-add-persistent-net-rules.patch +- udev: remove seqnum API and all assumptions about seqnums + add: 1022-udev-remove-seqnum-API-and-all-assumptions-about-seq.patch + ------------------------------------------------------------------- Tue May 27 07:23:47 UTC 2014 - werner@suse.de diff --git a/systemd.spec b/systemd.spec index f7024fae..17b10ce1 100644 --- a/systemd.spec +++ b/systemd.spec @@ -553,6 +553,10 @@ Patch1018: 1018-udev-do-not-skip-the-execution-of-RUN-when-renaming-.patch Patch1019: 1019-udev-avoid-use-of-uninitialized-err.patch # PATCHFIX-UPSTREAM added at 2014/05/26 Patch1020: 1020-udev-keyboard-also-hook-into-change-events.patch +# PATCH-FIX-SUSE 1021-udev-re-add-persistent-net-rules.patch +Patch1021: 1021-udev-re-add-persistent-net-rules.patch +# PATCHFIX-UPSTREAM 1022-udev-remove-seqnum-API-and-all-assumptions-about-seq.patch +Patch1022: 1022-udev-remove-seqnum-API-and-all-assumptions-about-seq.patch %description Systemd is a system and service manager, compatible with SysV and LSB @@ -984,6 +988,8 @@ cp %{SOURCE7} m4/ %patch1018 -p0 %patch1019 -p0 %patch1020 -p0 +%patch1021 -p1 +%patch1022 -p1 # ensure generate files are removed rm -f units/emergency.service @@ -1726,6 +1732,9 @@ exit 0 %{_prefix}/lib/udev/v4l_id %{_prefix}/lib/udev/write_dev_root_rule %{_prefix}/lib/udev/udev-generate-peristent-rule +%{_prefix}/lib/udev/net-set-sriov-names +%{_prefix}/lib/udev/rule_generator.functions +%{_prefix}/lib/udev/write_net_rules %dir %{_prefix}/lib/udev/rules.d/ %exclude %{_prefix}/lib/udev/rules.d/70-uaccess.rules %exclude %{_prefix}/lib/udev/rules.d/71-seat.rules