udev-cache: stop race between sysconf and cache generation

The validity of the udev cache is determined by the sysconf
file (/etc/udev/cache.data). Currently, there is a substantial delay
between sysconf generation in /etc/init.d/udev and cache generation in
/etc/init.d/udev-cache. If a hotplug event arrives in the middle of
this, then the sysconf will be out of date with respect to the cache.

The solution is two-pronged. First, we minimize the race window by
regenerating the sysconf immediately before the cache, in
/etc/init.d/udev-cache. This allows us to kill the race entirely by
stopping the udev event queue while the sysconf and cache are being
generated.

Signed-off-by: Richard Tollerton <rich.tollerton@ni.com>
udev-cache: replace readfiles() with cmp

Currently, udev-cache system configurations are compared as shell string
variables, read into memory with the readfiles() function. This is more
complex, and significantly (27-41%) slower, than comparing them using
`cmp`. (Performance was verified on both Cortex-A9 and Intel Nehalem
systems.)

So just use cmp. This requires a few other small changes:

exclude /proc/atags from CMP_FILE_LIST if it doesn't exist to avoid
errors in `cat` and `cmp`.

`cmp -q` doesn't exist in busybox, so instead, redirect output to
/dev/null.

Signed-off-by: Richard Tollerton <rich.tollerton@ni.com>
udev-cache: don't generate sysconf twice

The udev initscript signals udev-cache to run by generating a new
sysconf; but udev-cache now overwrites that with its own copy. To
eliminate the needless sysconf generating in udev, we instead trigger
udev-cache to run by touching a new file $DEVCACHE_REGEN.

Signed-off-by: Richard Tollerton <rich.tollerton@ni.com>
udev-cache: refactor sysconf generation

The current system configuration needs to be generated both inside
udev (to compare against the cached system configuration) and
udev-cache (to regenerate the cached system configuration). Use a single
function definition for this task, duplicated across both initscripts.
This also allows administrators to modify it for machine-specific
requirements.

Signed-off-by: Richard Tollerton <rich.tollerton@ni.com>
udev-cache: Clean up message when cache is invalidated

Replace a bunch of echo's with a single cat<<EOF. Take this opportunity
to more clearly communicate what is going on with the cache and what
files are being looked at.

Signed-off-by: Richard Tollerton <rich.tollerton@ni.com>
udev-cache: always warn on console if invalidated

Failure to use the udev cache is a significant enough impact to
the boot time (possibly seconds) that it should always be
reported on the console, regardless of the VERBOSE setting.

Signed-off-by: Richard Tollerton <rich.tollerton@ni.com>
udev-cache: invalidate on rules.d changes

Presently, the cache is not regenerated if udev rules are modified,
which may cause the cache to preserve an old configuration. To fix,
include the size, mtime, and filename of all udev rules in the system
configuration.

This change requires `stat`. If busybox supplies stat,
CONFIG_FEATURE_STAT_FORMAT must be enabled.

Signed-off-by: Richard Tollerton <rich.tollerton@ni.com>
udev-cache: Update cache asynchronously

Don't hold up the boot while the cache is being updated.

Signed-off-by: Richard Tollerton <rich.tollerton@ni.com>
Signed-off-by: Ben Shelton <ben.shelton@ni.com>
Acked-by: Gratian Crisan <gratian.crisan@ni.com>
udev-cache: refactor conditionals and error handling

Most of /etc/init.d/udev-cache is in a conditional block which can be
replaced by a `[ ... ] || exit 0` to reduce nesting.

This also provides an opportunity to add some additional messages
when VERBOSE is set.

Capture and report errors encountered in the cache generation process,
using set -e and trap EXIT. These errors were previously being ignored.

Signed-off-by: Richard Tollerton <rich.tollerton@ni.com>